Coverage for tests/test_generic_workflow.py: 15%

173 statements  

« prev     ^ index     » next       coverage.py v7.3.0, created at 2023-08-23 10:45 +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 

24 

25import lsst.ctrl.bps.generic_workflow as gw 

26import networkx 

27import networkx.algorithms.isomorphism as iso 

28 

29 

30class TestGenericWorkflowJob(unittest.TestCase): 

31 """Test of generic workflow jobs.""" 

32 

33 def testEquality(self): 

34 job1 = gw.GenericWorkflowJob("job1") 

35 job2 = gw.GenericWorkflowJob("job1") 

36 self.assertEqual(job1, job2) 

37 

38 

39class TestGenericWorkflow(unittest.TestCase): 

40 """Test generic workflow.""" 

41 

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 

49 

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

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

52 self.job2.executable = self.exec1 

53 

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) 

59 

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) 

67 

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())) 

74 

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 

80 

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())) 

87 

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())) 

99 

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())) 

107 

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) 

113 

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") 

119 

120 def testSaveInvalidFormat(self): 

121 gwf = gw.GenericWorkflow("mytest") 

122 stream = io.BytesIO() 

123 with self.assertRaises(RuntimeError): 

124 gwf.save(stream, "badformat") 

125 

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 ) 

138 

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) 

148 

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) 

161 

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) 

170 

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") 

178 

179 gwf.del_job("job2") 

180 

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

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

183 

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") 

192 

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") 

212 

213 gwf.add_workflow_source(gwf2) 

214 

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 ) 

232 

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") 

241 

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

243 

244 

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

246 unittest.main()