@@ -120,10 +120,12 @@ end
120120
121121# We'll re-use this further down in job submission tests.
122122ns_cheapest = Mocking. apply (mocking_patch) do
123+ empty! (MOCK_JULIAHUB_STATE)
123124 JuliaHub. nodespec ()
124125end
125126
126127@testset " JuliaHub.nodespec/s()" begin
128+ empty! (MOCK_JULIAHUB_STATE)
127129 @testset " Cheapest" begin
128130 @test ns_cheapest. hasGPU === false
129131 @test ns_cheapest. vcores == 2
@@ -184,6 +186,106 @@ end
184186 @test_throws JuliaHub. InvalidRequestError JuliaHub. nodespec (; ngpu= 10 , throw= true )
185187 @test @test_logs (:warn ,) JuliaHub. nodespec (; ngpu= 10 , throw= false ) === nothing
186188 end
189+
190+ # Check that we ignore bad price information, and match node based on the GPU, CPU, and memory (in that order)
191+ MOCK_JULIAHUB_STATE[:nodespecs ] = [
192+ # ! format: off
193+ # class, gpu, cpu, mem, price, desc, ?, memdisp, ?, ?, id
194+ [ " c1" , false , 1.0 , 16.0 , 3.00 , " 3.5 GHz Intel Xeon Platinum 8375C" , " " , " 4" , 90.50 , 87.90 , 2 ],
195+ [ " c2" , false , 2.0 , 8.0 , 2.00 , " 3.5 GHz Intel Xeon Platinum 8375C" , " " , " 4" , 95.10 , 92.10 , 3 ],
196+ [ " c8" , false , 8.0 , 4.0 , 1.00 , " 3.5 GHz Intel Xeon Platinum 8375C" , " " , " 4" , 98.50 , 93.90 , 4 ],
197+ # ! format: on
198+ ]
199+ Mocking. apply (mocking_patch) do
200+ let n = JuliaHub. nodespec ()
201+ @test n. nodeClass == " c1"
202+ @test n. _id == 2
203+ @test n. vcores == 1
204+ @test n. mem == 16
205+ @test ! n. hasGPU
206+ end
207+ let n = JuliaHub. nodespec (; ncpu= 2 )
208+ @test n. nodeClass == " c2"
209+ @test n. _id == 3
210+ @test n. vcores == 2
211+ @test n. mem == 8
212+ @test ! n. hasGPU
213+ end
214+ # Test sorting of JuliaHub.nodespecs()
215+ @test [n. nodeClass for n in JuliaHub. nodespecs ()] == [" c1" , " c2" , " c8" ]
216+ end
217+ # Cheap GPU node gets de-prioritised:
218+ push! (
219+ MOCK_JULIAHUB_STATE[:nodespecs ],
220+ # ! format: off
221+ # class, gpu, cpu, mem, price, desc, ?, memdisp, ?, ?, id
222+ [ " c1g1" , true , 1.0 , 16.0 , 0.00 , " 3.5 GHz Intel Xeon Platinum 8375C" , " " , " 4" , 90.50 , 87.90 , 5 ],
223+ # ! format: on
224+ )
225+ Mocking. apply (mocking_patch) do
226+ let n = JuliaHub. nodespec ()
227+ @test n. nodeClass == " c1"
228+ @test n. _id == 2
229+ @test n. vcores == 1
230+ @test n. mem == 16
231+ @test ! n. hasGPU
232+ end
233+ # Test sorting of JuliaHub.nodespecs()
234+ @test [n. nodeClass for n in JuliaHub. nodespecs ()] == [" c1" , " c2" , " c8" , " c1g1" ]
235+ end
236+ # Low memory gets prioritized:
237+ push! (
238+ MOCK_JULIAHUB_STATE[:nodespecs ],
239+ # ! format: off
240+ # class, gpu, cpu, mem, price, desc, ?, memdisp, ?, ?, id
241+ [ " c1m1" , false , 1.0 , 1.0 , 99.99 , " 3.5 GHz Intel Xeon Platinum 8375C" , " " , " 4" , 90.50 , 87.90 , 6 ],
242+ # ! format: on
243+ )
244+ Mocking. apply (mocking_patch) do
245+ let n = JuliaHub. nodespec ()
246+ @test n. nodeClass == " c1m1"
247+ @test n. _id == 6
248+ @test n. vcores == 1
249+ @test n. mem == 1
250+ @test ! n. hasGPU
251+ end
252+ # But we'll be forced to pick the GPU node here:
253+ let n = JuliaHub. nodespec (; ngpu= 1 )
254+ @test n. nodeClass == " c1g1"
255+ @test n. _id == 5
256+ @test n. vcores == 1
257+ @test n. mem == 16
258+ @test n. hasGPU
259+ end
260+ # Test sorting of JuliaHub.nodespecs()
261+ @test [n. nodeClass for n in JuliaHub. nodespecs ()] == [" c1m1" , " c1" , " c2" , " c8" , " c1g1" ]
262+ end
263+ # However, for identical nodespecs, we disambiguate based on price:
264+ MOCK_JULIAHUB_STATE[:nodespecs ] = [
265+ # ! format: off
266+ # class, gpu, cpu, mem, price, desc, ?, memdisp, ?, ?, id
267+ [ " a1" , false , 1.0 , 1.0 , 2.00 , " 3.5 GHz Intel Xeon Platinum 8375C" , " " , " 4" , 90.50 , 87.90 , 2 ],
268+ [ " a2" , false , 1.0 , 1.0 , 1.00 , " 3.5 GHz Intel Xeon Platinum 8375C" , " " , " 4" , 95.10 , 92.10 , 3 ],
269+ [ " a3" , false , 1.0 , 1.0 , 2.00 , " 3.5 GHz Intel Xeon Platinum 8375C" , " " , " 4" , 98.50 , 93.90 , 4 ],
270+ # ! format: on
271+ ]
272+ Mocking. apply (mocking_patch) do
273+ let n = JuliaHub. nodespec ()
274+ @test n. _id == 3
275+ @test n. nodeClass == " a2"
276+ @test n. vcores == 1
277+ @test n. mem == 1
278+ @test ! n. hasGPU
279+ end
280+ # Test sorting of JuliaHub.nodespecs()
281+ let ns = JuliaHub. nodespecs ()
282+ @test ns[1 ]. nodeClass == " a2"
283+ # With identical spec and price, order is not guaranteed
284+ @test ns[2 ]. nodeClass ∈ (" a1" , " a3" )
285+ @test ns[3 ]. nodeClass ∈ (" a1" , " a3" )
286+ end
287+ end
288+ empty! (MOCK_JULIAHUB_STATE)
187289end
188290
189291# This testset uses the show(::IO, ::JuliaHub.ComputeConfig) representation of ComputeConfig,
0 commit comments