Coverage for tests/test_generic_workflow.py: 15%
173 statements
« prev ^ index » next coverage.py v7.3.0, created at 2023-08-22 09:44 +0000
« prev ^ index » next coverage.py v7.3.0, created at 2023-08-22 09:44 +0000
1# This file is part of ctrl_bps.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
21import io
22import unittest
23from collections import Counter
25import lsst.ctrl.bps.generic_workflow as gw
26import networkx
27import networkx.algorithms.isomorphism as iso
30class TestGenericWorkflowJob(unittest.TestCase):
31 """Test of generic workflow jobs."""
33 def testEquality(self):
34 job1 = gw.GenericWorkflowJob("job1")
35 job2 = gw.GenericWorkflowJob("job1")
36 self.assertEqual(job1, job2)
39class TestGenericWorkflow(unittest.TestCase):
40 """Test generic workflow."""
42 def setUp(self):
43 self.exec1 = gw.GenericWorkflowExec(
44 name="test1.py", src_uri="${CTRL_BPS_DIR}/bin/test1.py", transfer_executable=False
45 )
46 self.job1 = gw.GenericWorkflowJob("job1", label="label1")
47 self.job1.quanta_counts = Counter({"pt1": 1, "pt2": 2})
48 self.job1.executable = self.exec1
50 self.job2 = gw.GenericWorkflowJob("job2", label="label2")
51 self.job2.quanta_counts = Counter({"pt1": 1, "pt2": 2})
52 self.job2.executable = self.exec1
54 def testAddJobDuplicate(self):
55 gwf = gw.GenericWorkflow("mytest")
56 gwf.add_job(self.job1)
57 with self.assertRaises(RuntimeError):
58 gwf.add_job(self.job1)
60 def testAddJobValid(self):
61 gwf = gw.GenericWorkflow("mytest")
62 gwf.add_job(self.job1)
63 self.assertEqual(1, gwf.number_of_nodes())
64 self.assertListEqual(["job1"], list(gwf))
65 getjob = gwf.get_job("job1")
66 self.assertEqual(self.job1, getjob)
68 def testAddJobRelationshipsSingle(self):
69 gwf = gw.GenericWorkflow("mytest")
70 gwf.add_job(self.job1)
71 gwf.add_job(self.job2)
72 gwf.add_job_relationships("job1", "job2")
73 self.assertListEqual([("job1", "job2")], list(gwf.edges()))
75 def testAddJobRelationshipsMultiChild(self):
76 job3 = gw.GenericWorkflowJob("job3")
77 job3.label = "label2"
78 job3.quanta_counts = Counter({"pt1": 1, "pt2": 2})
79 job3.executable = self.exec1
81 gwf = gw.GenericWorkflow("mytest")
82 gwf.add_job(self.job1)
83 gwf.add_job(self.job2)
84 gwf.add_job(job3)
85 gwf.add_job_relationships("job1", ["job2", "job3"])
86 self.assertListEqual([("job1", "job2"), ("job1", "job3")], list(gwf.edges()))
88 def testAddJobRelationshipsMultiParents(self):
89 job3 = gw.GenericWorkflowJob("job3")
90 job3.label = "label2"
91 job3.quanta_counts = Counter({"pt1": 1, "pt2": 2})
92 job3.executable = self.exec1
93 gwf = gw.GenericWorkflow("mytest")
94 gwf.add_job(self.job1)
95 gwf.add_job(self.job2)
96 gwf.add_job(job3)
97 gwf.add_job_relationships(["job1", "job2"], "job3")
98 self.assertListEqual([("job1", "job3"), ("job2", "job3")], list(gwf.edges()))
100 def testAddJobRelationshipsNone(self):
101 gwf = gw.GenericWorkflow("mytest")
102 gwf.add_job(self.job1)
103 gwf.add_job_relationships(None, "job1")
104 self.assertListEqual([], list(gwf.edges()))
105 gwf.add_job_relationships("job1", None)
106 self.assertListEqual([], list(gwf.edges()))
108 def testGetJobExists(self):
109 gwf = gw.GenericWorkflow("mytest")
110 gwf.add_job(self.job1)
111 get_job = gwf.get_job("job1")
112 self.assertIs(self.job1, get_job)
114 def testGetJobError(self):
115 gwf = gw.GenericWorkflow("mytest")
116 gwf.add_job(self.job1)
117 with self.assertRaises(KeyError):
118 _ = gwf.get_job("job_not_there")
120 def testSaveInvalidFormat(self):
121 gwf = gw.GenericWorkflow("mytest")
122 stream = io.BytesIO()
123 with self.assertRaises(RuntimeError):
124 gwf.save(stream, "badformat")
126 def testSavePickle(self):
127 gwf = gw.GenericWorkflow("mytest")
128 gwf.add_job(self.job1)
129 gwf.add_job(self.job2)
130 gwf.add_job_relationships("job1", "job2")
131 stream = io.BytesIO()
132 gwf.save(stream, "pickle")
133 stream.seek(0)
134 gwf2 = gw.GenericWorkflow.load(stream, "pickle")
135 self.assertTrue(
136 networkx.is_isomorphic(gwf, gwf2, node_match=iso.categorical_node_match("data", None))
137 )
139 def testLabels(self):
140 job3 = gw.GenericWorkflowJob("job3")
141 job3.label = "label2"
142 gwf = gw.GenericWorkflow("mytest")
143 gwf.add_job(self.job1)
144 gwf.add_job(self.job2)
145 gwf.add_job(job3)
146 gwf.add_job_relationships(["job1", "job2"], "job3")
147 self.assertListEqual(["label1", "label2"], gwf.labels)
149 def testRegenerateLabels(self):
150 job3 = gw.GenericWorkflowJob("job3", label="label2")
151 gwf = gw.GenericWorkflow("mytest")
152 gwf.add_job(self.job1)
153 gwf.add_job(self.job2)
154 gwf.add_job(job3)
155 gwf.add_job_relationships(["job1", "job2"], "job3")
156 self.job1.label = "label1b"
157 self.job2.label = "label1b"
158 job3.label = "label2b"
159 gwf.regenerate_labels()
160 self.assertListEqual(["label1b", "label2b"], gwf.labels)
162 def testJobCounts(self):
163 job3 = gw.GenericWorkflowJob("job3", label="label2")
164 gwf = gw.GenericWorkflow("mytest")
165 gwf.add_job(self.job1)
166 gwf.add_job(self.job2)
167 gwf.add_job(job3)
168 gwf.add_job_relationships(["job1", "job2"], "job3")
169 self.assertEqual(Counter({"label1": 1, "label2": 2}), gwf.job_counts)
171 def testDelJob(self):
172 job3 = gw.GenericWorkflowJob("job3", label="label2")
173 gwf = gw.GenericWorkflow("mytest")
174 gwf.add_job(self.job1)
175 gwf.add_job(self.job2)
176 gwf.add_job(job3)
177 gwf.add_job_relationships(["job1", "job2"], "job3")
179 gwf.del_job("job2")
181 self.assertListEqual([("job1", "job3")], list(gwf.edges()))
182 self.assertEqual(Counter({"label1": 1, "label2": 1}), gwf.job_counts)
184 def testAddWorkflowSource(self):
185 job3 = gw.GenericWorkflowJob("job3")
186 job3.label = "label2"
187 gwf = gw.GenericWorkflow("mytest")
188 gwf.add_job(self.job1)
189 gwf.add_job(self.job2)
190 gwf.add_job(job3)
191 gwf.add_job_relationships(["job1", "job2"], "job3")
193 srcjob1 = gw.GenericWorkflowJob("srcjob1")
194 srcjob1.label = "srclabel1"
195 srcjob1.executable = self.exec1
196 srcjob2 = gw.GenericWorkflowJob("srcjob2")
197 srcjob2.label = "srclabel1"
198 srcjob2.executable = self.exec1
199 srcjob3 = gw.GenericWorkflowJob("srcjob3")
200 srcjob3.label = "srclabel2"
201 srcjob3.executable = self.exec1
202 srcjob4 = gw.GenericWorkflowJob("srcjob4")
203 srcjob4.label = "srclabel2"
204 srcjob4.executable = self.exec1
205 gwf2 = gw.GenericWorkflow("mytest2")
206 gwf2.add_job(srcjob1)
207 gwf2.add_job(srcjob2)
208 gwf2.add_job(srcjob3)
209 gwf2.add_job(srcjob4)
210 gwf2.add_job_relationships("srcjob1", "srcjob3")
211 gwf2.add_job_relationships("srcjob2", "srcjob4")
213 gwf.add_workflow_source(gwf2)
215 self.assertEqual(Counter({"srclabel1": 2, "srclabel2": 2, "label1": 1, "label2": 2}), gwf.job_counts)
216 self.assertListEqual(["srclabel1", "srclabel2", "label1", "label2"], gwf.labels)
217 self.assertListEqual(
218 sorted(
219 [
220 ("srcjob1", "srcjob3"),
221 ("srcjob2", "srcjob4"),
222 ("srcjob3", "job1"),
223 ("srcjob3", "job2"),
224 ("srcjob4", "job1"),
225 ("srcjob4", "job2"),
226 ("job1", "job3"),
227 ("job2", "job3"),
228 ]
229 ),
230 sorted(gwf.edges()),
231 )
233 def testGetJobsByLabel(self):
234 job3 = gw.GenericWorkflowJob("job3")
235 job3.label = "label3"
236 gwf = gw.GenericWorkflow("mytest")
237 gwf.add_job(self.job1)
238 gwf.add_job(self.job2)
239 gwf.add_job(job3)
240 gwf.add_job_relationships(["job1", "job2"], "job3")
242 self.assertListEqual([job3], gwf.get_jobs_by_label("label3"))
245if __name__ == "__main__": 245 ↛ 246line 245 didn't jump to line 246, because the condition on line 245 was never true
246 unittest.main()