Skip to content

Commit 6ce4b8e

Browse files
committed
testsuite: add Python job kvs lookup tests
Problem: There is no coverage for the new flux.job.kvslookup Python module. Add coverage via new tests in t/python/t0014-job-kvslookup.py.
1 parent da25fb3 commit 6ce4b8e

File tree

2 files changed

+191
-0
lines changed

2 files changed

+191
-0
lines changed

t/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ TESTSCRIPTS = \
260260
python/t0010-job.py \
261261
python/t0012-futures.py \
262262
python/t0013-job-list.py \
263+
python/t0014-job-kvslookup.py \
263264
python/t0020-hostlist.py \
264265
python/t0021-idset.py \
265266
python/t0022-resource-set.py \

t/python/t0014-job-kvslookup.py

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
#!/usr/bin/env python3
2+
3+
###############################################################
4+
# Copyright 2023 Lawrence Livermore National Security, LLC
5+
# (c.f. AUTHORS, NOTICE.LLNS, COPYING)
6+
#
7+
# This file is part of the Flux resource manager framework.
8+
# For details, see https://github.com/flux-framework.
9+
#
10+
# SPDX-License-Identifier: LGPL-3.0
11+
###############################################################
12+
13+
import json
14+
import unittest
15+
16+
import flux
17+
import subflux # noqa: F401 - for PYTHONPATH
18+
from flux.job import JobspecV1
19+
20+
21+
def __flux_size():
22+
return 1
23+
24+
25+
class TestJob(unittest.TestCase):
26+
@classmethod
27+
def submitJob(self, command):
28+
compute_jobreq = JobspecV1.from_command(
29+
command=command, num_tasks=1, num_nodes=1, cores_per_task=1
30+
)
31+
return flux.job.submit(self.fh, compute_jobreq, waitable=True)
32+
33+
@classmethod
34+
def setUpClass(self):
35+
self.fh = flux.Flux()
36+
self.jobid1 = self.submitJob(["hostname"])
37+
flux.job.event_wait(self.fh, self.jobid1, name="start")
38+
self.jobid2 = self.submitJob(["hostname"])
39+
flux.job.event_wait(self.fh, self.jobid2, name="start")
40+
41+
def check_jobspec_str(self, data, jobid):
42+
self.assertEqual(data["id"], jobid)
43+
self.assertIn("jobspec", data)
44+
self.assertEqual(type(data["jobspec"]), str)
45+
jobspec = json.loads(data["jobspec"])
46+
self.assertEqual(jobspec["tasks"][0]["command"][0], "hostname")
47+
self.assertNotIn("R", data)
48+
49+
def check_jobspec_decoded(self, data, jobid):
50+
self.assertEqual(data["id"], jobid)
51+
self.assertIn("jobspec", data)
52+
self.assertEqual(data["jobspec"]["tasks"][0]["command"][0], "hostname")
53+
self.assertNotIn("R", data)
54+
55+
def check_R_J_str(self, data, jobid):
56+
self.assertEqual(data["id"], jobid)
57+
self.assertNotIn("jobspec", data, jobid)
58+
self.assertIn("R", data)
59+
self.assertIn("J", data)
60+
self.assertEqual(type(data["R"]), str)
61+
self.assertEqual(type(data["J"]), str)
62+
R = json.loads(data["R"])
63+
self.assertEqual(R["execution"]["R_lite"][0]["rank"], "0")
64+
65+
def check_R_J_decoded(self, data, jobid):
66+
self.assertEqual(data["id"], jobid)
67+
self.assertNotIn("jobspec", data)
68+
self.assertIn("R", data)
69+
self.assertIn("J", data)
70+
self.assertEqual(type(data["J"]), str)
71+
self.assertEqual(data["R"]["execution"]["R_lite"][0]["rank"], "0")
72+
73+
def test_00_job_info_lookup(self):
74+
rpc = flux.job.job_info_lookup(self.fh, self.jobid1)
75+
data = rpc.get()
76+
self.check_jobspec_str(data, self.jobid1)
77+
data = rpc.get_decode()
78+
self.assertEqual(data["id"], self.jobid1)
79+
80+
def test_01_job_info_lookup_keys(self):
81+
rpc = flux.job.job_info_lookup(self.fh, self.jobid1, keys=["R", "J"])
82+
data = rpc.get()
83+
self.check_R_J_str(data, self.jobid1)
84+
data = rpc.get_decode()
85+
self.check_R_J_decoded(data, self.jobid1)
86+
87+
def test_02_job_info_lookup_badid(self):
88+
rpc = flux.job.job_info_lookup(self.fh, 123456789)
89+
notfound = False
90+
try:
91+
rpc.get()
92+
except FileNotFoundError:
93+
notfound = True
94+
self.assertEqual(notfound, True)
95+
96+
def test_03_job_info_lookup_badkey(self):
97+
rpc = flux.job.job_info_lookup(self.fh, self.jobid1, keys=["foo"])
98+
notfound = False
99+
try:
100+
rpc.get()
101+
except FileNotFoundError:
102+
notfound = True
103+
self.assertEqual(notfound, True)
104+
105+
def test_04_job_kvs_lookup(self):
106+
data = flux.job.job_kvs_lookup(self.fh, self.jobid1)
107+
self.check_jobspec_decoded(data, self.jobid1)
108+
109+
def test_05_job_kvs_lookup_nodecode(self):
110+
data = flux.job.job_kvs_lookup(self.fh, self.jobid1, decode=False)
111+
self.check_jobspec_str(data, self.jobid1)
112+
113+
def test_06_job_kvs_lookup_keys(self):
114+
data = flux.job.job_kvs_lookup(self.fh, self.jobid1, keys=["R", "J"])
115+
self.check_R_J_decoded(data, self.jobid1)
116+
117+
def test_07_job_kvs_lookup_keys_nodecode(self):
118+
data = flux.job.job_kvs_lookup(
119+
self.fh, self.jobid1, keys=["R", "J"], decode=False
120+
)
121+
self.check_R_J_str(data, self.jobid1)
122+
123+
def test_08_job_kvs_lookup_badid(self):
124+
data = flux.job.job_kvs_lookup(self.fh, 123456789)
125+
self.assertEqual(data, None)
126+
127+
def test_09_job_kvs_lookup_badkey(self):
128+
data = flux.job.job_kvs_lookup(self.fh, self.jobid1, keys=["foo"])
129+
self.assertEqual(data, None)
130+
131+
def test_10_job_kvs_lookup_list(self):
132+
ids = [self.jobid1]
133+
data = flux.job.JobKVSLookup(self.fh, ids).data()
134+
self.assertEqual(len(data), 1)
135+
self.check_jobspec_decoded(data[0], self.jobid1)
136+
137+
def test_11_job_kvs_lookup_list_multiple(self):
138+
ids = [self.jobid1, self.jobid2]
139+
data = flux.job.JobKVSLookup(self.fh, ids).data()
140+
self.assertEqual(len(data), 2)
141+
self.check_jobspec_decoded(data[0], self.jobid1)
142+
self.check_jobspec_decoded(data[1], self.jobid2)
143+
144+
def test_12_job_kvs_lookup_list_multiple_nodecode(self):
145+
ids = [self.jobid1, self.jobid2]
146+
data = flux.job.JobKVSLookup(self.fh, ids, decode=False).data()
147+
self.assertEqual(len(data), 2)
148+
self.check_jobspec_str(data[0], self.jobid1)
149+
self.check_jobspec_str(data[1], self.jobid2)
150+
151+
def test_13_job_kvs_lookup_list_multiple_keys(self):
152+
ids = [self.jobid1, self.jobid2]
153+
data = flux.job.JobKVSLookup(self.fh, ids, keys=["R", "J"]).data()
154+
self.assertEqual(len(data), 2)
155+
self.check_R_J_decoded(data[0], self.jobid1)
156+
self.check_R_J_decoded(data[1], self.jobid2)
157+
158+
def test_14_job_kvs_lookup_list_multiple_keys_nodecode(self):
159+
ids = [self.jobid1, self.jobid2]
160+
data = flux.job.JobKVSLookup(self.fh, ids, keys=["R", "J"], decode=False).data()
161+
self.assertEqual(len(data), 2)
162+
self.check_R_J_str(data[0], self.jobid1)
163+
self.check_R_J_str(data[1], self.jobid2)
164+
165+
def test_15_job_kvs_lookup_list_none(self):
166+
data = flux.job.JobKVSLookup(self.fh).data()
167+
self.assertEqual(len(data), 0)
168+
169+
def test_16_job_kvs_lookup_list_badid(self):
170+
ids = [123456789]
171+
datalookup = flux.job.JobKVSLookup(self.fh, ids)
172+
data = datalookup.data()
173+
self.assertEqual(len(data), 0)
174+
self.assertEqual(len(datalookup.errors), 1)
175+
176+
def test_17_job_kvs_lookup_list_badkey(self):
177+
ids = [self.jobid1]
178+
datalookup = flux.job.JobKVSLookup(self.fh, ids, keys=["foo"])
179+
data = datalookup.data()
180+
self.assertEqual(len(data), 0)
181+
self.assertEqual(len(datalookup.errors), 1)
182+
183+
184+
if __name__ == "__main__":
185+
from subflux import rerun_under_flux
186+
187+
if rerun_under_flux(size=__flux_size(), personality="job"):
188+
from pycotap import TAPTestRunner
189+
190+
unittest.main(testRunner=TAPTestRunner())

0 commit comments

Comments
 (0)