Skip to content

Commit 60fcfd9

Browse files
committed
test for quotas caching correction
1 parent c0934b9 commit 60fcfd9

9 files changed

Lines changed: 63 additions & 46 deletions

res_amelioration/bench_quotas_metasched.csv

Lines changed: 0 additions & 15 deletions
This file was deleted.
-78.9 KB
Binary file not shown.

res_explosion/bench_quotas_metasched.csv

Lines changed: 0 additions & 15 deletions
This file was deleted.
-68 KB
Binary file not shown.
-140 KB
Binary file not shown.
-145 KB
Binary file not shown.

res_without_print/bench_quotas_metasched.csv

Lines changed: 0 additions & 15 deletions
This file was deleted.
-61.8 KB
Binary file not shown.

tests/kao/test_quotas.py

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from oar.kao.scheduling import schedule_id_jobs_ct, set_slots_with_prev_scheduled_jobs
1010
from oar.kao.slot import Slot, SlotSet
1111
from oar.lib.globals import init_oar
12-
from oar.lib.job_handling import JobPseudo
12+
from oar.lib.job_handling import JobPseudo, set_jobs_cache_keys
1313
from oar.lib.resource import ResourceSet
1414

1515
config, engine = init_oar(no_db=True)
@@ -43,6 +43,37 @@ def compare_slots_val_ref(slots, v):
4343
return True
4444

4545

46+
def sched_placement(nb_jobs, rules, alt_users=False):
47+
48+
res = ProcSet((1, 32))
49+
ResourceSet.default_itvs = ProcSet((1, 32))
50+
51+
Quotas.enabled = rules is not None
52+
if rules is not None:
53+
Quotas.default_rules = rules
54+
ss = SlotSet(Slot(1, 0, 0, ProcSet((1, 32)), 0, 2**31))
55+
all_ss = {"default": ss}
56+
hy = {"node": [ProcSet((i, i)) for i in range(1, 32 + 1)]}
57+
jobs, jids = {}, list(range(1, nb_jobs + 1))
58+
for i in jids:
59+
user = ("u0" if i % 2 == 0 else "u1") if alt_users else "u%d" % (i % 4)
60+
jobs[i] = JobPseudo(
61+
id=i,
62+
types={},
63+
deps=[],
64+
key_cache={},
65+
queue="default",
66+
user=user,
67+
project="",
68+
mld_res_rqts=[(i, 60, [([("node", 2)], res)])],
69+
ts=False,
70+
ph=0,
71+
)
72+
set_jobs_cache_keys(None, jobs) # session arg is unused
73+
schedule_id_jobs_ct(all_ss, jobs, hy, jids, 10)
74+
return {i: jobs[i].start_time for i in jids}
75+
76+
4677
@pytest.fixture(scope="module", autouse=True)
4778
def oar_conf(request):
4879
config["QUOTAS"] = "yes"
@@ -376,3 +407,34 @@ def test_quotas_two_jobs_job_type_proc():
376407

377408
assert j1.start_time == 0
378409
assert j2.start_time == 50
410+
411+
412+
def test_quotas_nonblocking_placement_equals_no_quotas():
413+
"""
414+
Non-blocking quotas reject nothing, so placement must match no-quotas.
415+
(regression test relatively to no quota resource research)
416+
"""
417+
big_quota = 10**9
418+
nb = 48
419+
off = sched_placement(nb, None)
420+
nonblocking = {
421+
("*", "*", "*", "/"): [big_quota, -1, -1],
422+
("*", "/", "*", "*"): [big_quota, -1, -1],
423+
("*", "*", "*", "*"): [-1, -1, -1],
424+
}
425+
on = sched_placement(nb, nonblocking)
426+
assert on == off
427+
428+
429+
def test_quotas_cache_no_gap_under_blocking():
430+
# Blocking per-user quota + mixed users: the cache must not leave a gap in
431+
# the first time layer (catches caching the quota-validated slot instead of
432+
# the resource frontier). Cluster 32 res, 2 res/job -> 16 jobs fill layer 0.
433+
nb = 64 # 32 u0 + 32 u1
434+
rules = {("*", "*", "*", "u0"): [2, -1, -1], ("*", "*", "*", "*"): [-1, -1, -1]}
435+
st = sched_placement(nb, rules, alt_users=True)
436+
t0 = min(st.values())
437+
nb_first_layer = sum(1 for t in st.values() if t == t0)
438+
assert nb_first_layer == 16, (
439+
"gap in first layer: %d/16 jobs (poisoned cache?)" % nb_first_layer
440+
)

0 commit comments

Comments
 (0)