Coverage for tests/test_generic_workflow.py: 15%

173 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-04-11 02:16 -0700

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 

24 

25import lsst.ctrl.bps.generic_workflow as gw 

26import networkx 

27import networkx.algorithms.isomorphism as iso 

28 

29 

30class TestGenericWorkflowJob(unittest.TestCase): 

31 def testEquality(self): 

32 job1 = gw.GenericWorkflowJob("job1") 

33 job2 = gw.GenericWorkflowJob("job1") 

34 self.assertEqual(job1, job2) 

35 

36 

37class TestGenericWorkflow(unittest.TestCase): 

38 def setUp(self): 

39 self.exec1 = gw.GenericWorkflowExec( 

40 name="test1.py", src_uri="${CTRL_BPS_DIR}/bin/test1.py", transfer_executable=False 

41 ) 

42 self.job1 = gw.GenericWorkflowJob("job1", label="label1") 

43 self.job1.quanta_counts = Counter({"pt1": 1, "pt2": 2}) 

44 self.job1.executable = self.exec1 

45 

46 self.job2 = gw.GenericWorkflowJob("job2", label="label2") 

47 self.job2.quanta_counts = Counter({"pt1": 1, "pt2": 2}) 

48 self.job2.executable = self.exec1 

49 

50 def testAddJobDuplicate(self): 

51 gwf = gw.GenericWorkflow("mytest") 

52 gwf.add_job(self.job1) 

53 with self.assertRaises(RuntimeError): 

54 gwf.add_job(self.job1) 

55 

56 def testAddJobValid(self): 

57 gwf = gw.GenericWorkflow("mytest") 

58 gwf.add_job(self.job1) 

59 self.assertEqual(1, gwf.number_of_nodes()) 

60 self.assertListEqual(["job1"], list(gwf)) 

61 getjob = gwf.get_job("job1") 

62 self.assertEqual(self.job1, getjob) 

63 

64 def testAddJobRelationshipsSingle(self): 

65 gwf = gw.GenericWorkflow("mytest") 

66 gwf.add_job(self.job1) 

67 gwf.add_job(self.job2) 

68 gwf.add_job_relationships("job1", "job2") 

69 self.assertListEqual([("job1", "job2")], list(gwf.edges())) 

70 

71 def testAddJobRelationshipsMultiChild(self): 

72 job3 = gw.GenericWorkflowJob("job3") 

73 job3.label = "label2" 

74 job3.quanta_counts = Counter({"pt1": 1, "pt2": 2}) 

75 job3.executable = self.exec1 

76 

77 gwf = gw.GenericWorkflow("mytest") 

78 gwf.add_job(self.job1) 

79 gwf.add_job(self.job2) 

80 gwf.add_job(job3) 

81 gwf.add_job_relationships("job1", ["job2", "job3"]) 

82 self.assertListEqual([("job1", "job2"), ("job1", "job3")], list(gwf.edges())) 

83 

84 def testAddJobRelationshipsMultiParents(self): 

85 job3 = gw.GenericWorkflowJob("job3") 

86 job3.label = "label2" 

87 job3.quanta_counts = Counter({"pt1": 1, "pt2": 2}) 

88 job3.executable = self.exec1 

89 gwf = gw.GenericWorkflow("mytest") 

90 gwf.add_job(self.job1) 

91 gwf.add_job(self.job2) 

92 gwf.add_job(job3) 

93 gwf.add_job_relationships(["job1", "job2"], "job3") 

94 self.assertListEqual([("job1", "job3"), ("job2", "job3")], list(gwf.edges())) 

95 

96 def testAddJobRelationshipsNone(self): 

97 gwf = gw.GenericWorkflow("mytest") 

98 gwf.add_job(self.job1) 

99 gwf.add_job_relationships(None, "job1") 

100 self.assertListEqual([], list(gwf.edges())) 

101 gwf.add_job_relationships("job1", None) 

102 self.assertListEqual([], list(gwf.edges())) 

103 

104 def testGetJobExists(self): 

105 gwf = gw.GenericWorkflow("mytest") 

106 gwf.add_job(self.job1) 

107 get_job = gwf.get_job("job1") 

108 self.assertIs(self.job1, get_job) 

109 

110 def testGetJobError(self): 

111 gwf = gw.GenericWorkflow("mytest") 

112 gwf.add_job(self.job1) 

113 with self.assertRaises(KeyError): 

114 _ = gwf.get_job("job_not_there") 

115 

116 def testSaveInvalidFormat(self): 

117 gwf = gw.GenericWorkflow("mytest") 

118 stream = io.BytesIO() 

119 with self.assertRaises(RuntimeError): 

120 gwf.save(stream, "badformat") 

121 

122 def testSavePickle(self): 

123 gwf = gw.GenericWorkflow("mytest") 

124 gwf.add_job(self.job1) 

125 gwf.add_job(self.job2) 

126 gwf.add_job_relationships("job1", "job2") 

127 stream = io.BytesIO() 

128 gwf.save(stream, "pickle") 

129 stream.seek(0) 

130 gwf2 = gw.GenericWorkflow.load(stream, "pickle") 

131 self.assertTrue( 

132 networkx.is_isomorphic(gwf, gwf2, node_match=iso.categorical_node_match("data", None)) 

133 ) 

134 

135 def testLabels(self): 

136 job3 = gw.GenericWorkflowJob("job3") 

137 job3.label = "label2" 

138 gwf = gw.GenericWorkflow("mytest") 

139 gwf.add_job(self.job1) 

140 gwf.add_job(self.job2) 

141 gwf.add_job(job3) 

142 gwf.add_job_relationships(["job1", "job2"], "job3") 

143 self.assertListEqual(["label1", "label2"], gwf.labels) 

144 

145 def testRegenerateLabels(self): 

146 job3 = gw.GenericWorkflowJob("job3", label="label2") 

147 gwf = gw.GenericWorkflow("mytest") 

148 gwf.add_job(self.job1) 

149 gwf.add_job(self.job2) 

150 gwf.add_job(job3) 

151 gwf.add_job_relationships(["job1", "job2"], "job3") 

152 self.job1.label = "label1b" 

153 self.job2.label = "label1b" 

154 job3.label = "label2b" 

155 gwf.regenerate_labels() 

156 self.assertListEqual(["label1b", "label2b"], gwf.labels) 

157 

158 def testJobCounts(self): 

159 job3 = gw.GenericWorkflowJob("job3", label="label2") 

160 gwf = gw.GenericWorkflow("mytest") 

161 gwf.add_job(self.job1) 

162 gwf.add_job(self.job2) 

163 gwf.add_job(job3) 

164 gwf.add_job_relationships(["job1", "job2"], "job3") 

165 self.assertEqual(Counter({"label1": 1, "label2": 2}), gwf.job_counts) 

166 

167 def testDelJob(self): 

168 job3 = gw.GenericWorkflowJob("job3", label="label2") 

169 gwf = gw.GenericWorkflow("mytest") 

170 gwf.add_job(self.job1) 

171 gwf.add_job(self.job2) 

172 gwf.add_job(job3) 

173 gwf.add_job_relationships(["job1", "job2"], "job3") 

174 

175 gwf.del_job("job2") 

176 

177 self.assertListEqual([("job1", "job3")], list(gwf.edges())) 

178 self.assertEqual(Counter({"label1": 1, "label2": 1}), gwf.job_counts) 

179 

180 def testAddWorkflowSource(self): 

181 job3 = gw.GenericWorkflowJob("job3") 

182 job3.label = "label2" 

183 gwf = gw.GenericWorkflow("mytest") 

184 gwf.add_job(self.job1) 

185 gwf.add_job(self.job2) 

186 gwf.add_job(job3) 

187 gwf.add_job_relationships(["job1", "job2"], "job3") 

188 

189 srcjob1 = gw.GenericWorkflowJob("srcjob1") 

190 srcjob1.label = "srclabel1" 

191 srcjob1.executable = self.exec1 

192 srcjob2 = gw.GenericWorkflowJob("srcjob2") 

193 srcjob2.label = "srclabel1" 

194 srcjob2.executable = self.exec1 

195 srcjob3 = gw.GenericWorkflowJob("srcjob3") 

196 srcjob3.label = "srclabel2" 

197 srcjob3.executable = self.exec1 

198 srcjob4 = gw.GenericWorkflowJob("srcjob4") 

199 srcjob4.label = "srclabel2" 

200 srcjob4.executable = self.exec1 

201 gwf2 = gw.GenericWorkflow("mytest2") 

202 gwf2.add_job(srcjob1) 

203 gwf2.add_job(srcjob2) 

204 gwf2.add_job(srcjob3) 

205 gwf2.add_job(srcjob4) 

206 gwf2.add_job_relationships("srcjob1", "srcjob3") 

207 gwf2.add_job_relationships("srcjob2", "srcjob4") 

208 

209 gwf.add_workflow_source(gwf2) 

210 

211 self.assertEqual(Counter({"srclabel1": 2, "srclabel2": 2, "label1": 1, "label2": 2}), gwf.job_counts) 

212 self.assertListEqual(["srclabel1", "srclabel2", "label1", "label2"], gwf.labels) 

213 self.assertListEqual( 

214 sorted( 

215 [ 

216 ("srcjob1", "srcjob3"), 

217 ("srcjob2", "srcjob4"), 

218 ("srcjob3", "job1"), 

219 ("srcjob3", "job2"), 

220 ("srcjob4", "job1"), 

221 ("srcjob4", "job2"), 

222 ("job1", "job3"), 

223 ("job2", "job3"), 

224 ] 

225 ), 

226 sorted(list(gwf.edges())), 

227 ) 

228 

229 def testGetJobsByLabel(self): 

230 job3 = gw.GenericWorkflowJob("job3") 

231 job3.label = "label3" 

232 gwf = gw.GenericWorkflow("mytest") 

233 gwf.add_job(self.job1) 

234 gwf.add_job(self.job2) 

235 gwf.add_job(job3) 

236 gwf.add_job_relationships(["job1", "job2"], "job3") 

237 

238 self.assertListEqual([job3], gwf.get_jobs_by_label("label3")) 

239 

240 

241if __name__ == "__main__": 241 ↛ 242line 241 didn't jump to line 242, because the condition on line 241 was never true

242 unittest.main()