Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# This file is part of verify. 

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/>. 

21 

22import shutil 

23import tempfile 

24import unittest.mock 

25 

26import astropy.units as u 

27 

28import lsst.utils.tests 

29from lsst.pex.config import Config 

30import lsst.daf.butler.tests as butlerTests 

31from lsst.pipe.base import Task, Struct, testUtils 

32 

33from lsst.verify import Measurement 

34from lsst.verify.tasks import ApdbMetricTask, MetricComputationError 

35from lsst.verify.tasks.testUtils import ApdbMetricTestCase 

36 

37 

38class DummyTask(ApdbMetricTask): 

39 _DefaultName = "NotARealTask" 

40 

41 def makeMeasurement(self, _dbHandle, outputDataId): 

42 if outputDataId: 

43 nChars = len(outputDataId["instrument"]) 

44 return Measurement(self.config.metricName, 

45 nChars * u.dimensionless_unscaled) 

46 else: 

47 return Measurement(self.config.metricName, 

48 0 * u.dimensionless_unscaled) 

49 

50 

51class Gen3ApdbTestSuite(ApdbMetricTestCase): 

52 @classmethod 

53 def makeTask(cls): 

54 class MockDbLoader(Task): 

55 ConfigClass = Config 

56 

57 def run(self, _): 

58 return Struct(apdb=unittest.mock.Mock()) 

59 

60 config = DummyTask.ConfigClass() 

61 config.dbLoader.retarget(MockDbLoader) 

62 config.connections.package = "verify" 

63 config.connections.metric = "DummyApdb" 

64 config.validate() 

65 return DummyTask(config=config) 

66 

67 @classmethod 

68 def setUpClass(cls): 

69 super().setUpClass() 

70 

71 cls.CAMERA_ID = "NotACam" 

72 cls.VISIT_ID = 42 

73 cls.CHIP_ID = 5 

74 

75 # makeTestRepo called in setUpClass because it's *very* slow 

76 cls.root = tempfile.mkdtemp() 

77 cls.repo = butlerTests.makeTestRepo(cls.root, { 

78 "instrument": [cls.CAMERA_ID], 

79 "visit": [cls.VISIT_ID], 

80 "detector": [cls.CHIP_ID], 

81 }) 

82 

83 # self.task not visible at class level 

84 task = cls.makeTask() 

85 connections = task.config.ConnectionsClass(config=task.config) 

86 

87 butlerTests.addDatasetType( 

88 cls.repo, 

89 connections.measurement.name, 

90 connections.measurement.dimensions, 

91 connections.measurement.storageClass) 

92 butlerTests.addDatasetType( 

93 cls.repo, 

94 connections.dbInfo.name, 

95 connections.dbInfo.dimensions, 

96 connections.dbInfo.storageClass) 

97 

98 @classmethod 

99 def tearDownClass(cls): 

100 shutil.rmtree(cls.root, ignore_errors=True) 

101 super().tearDownClass() 

102 

103 def setUp(self): 

104 super().setUp() 

105 

106 self.connections = self.task.config.ConnectionsClass( 

107 config=self.task.config) 

108 

109 def _prepareQuantum(self, task): 

110 inputId = { 

111 "instrument": self.CAMERA_ID, 

112 "visit": self.VISIT_ID, 

113 "detector": self.CHIP_ID, 

114 } 

115 

116 butler = butlerTests.makeTestCollection(self.repo) 

117 # task.config not persistable if it refers to a local class 

118 # We don't actually use the persisted config, so just make a new one 

119 info = task.ConfigClass() 

120 butler.put(info, "apdb_marker", inputId) 

121 

122 quantum = testUtils.makeQuantum( 

123 task, butler, inputId, 

124 {"dbInfo": [inputId], "measurement": inputId}) 

125 

126 return (butler, quantum, info) 

127 

128 def testRunQuantum(self): 

129 butler, quantum, input = self._prepareQuantum(self.task) 

130 

131 run = testUtils.runTestQuantum(self.task, butler, quantum) 

132 

133 # Did output data ID get passed to DummyTask.run? 

134 expectedId = lsst.daf.butler.DataCoordinate.standardize( 

135 {"instrument": self.CAMERA_ID}, 

136 universe=butler.registry.dimensions) 

137 run.assert_called_once_with( 

138 dbInfo=[input], 

139 outputDataId=expectedId) 

140 

141 def testRunQuantumNone(self): 

142 class NoneTask(DummyTask): 

143 def run(self, *args, **kwargs): 

144 return Struct(measurement=None) 

145 

146 config = NoneTask.ConfigClass() 

147 config.connections.package = "verify" 

148 config.connections.metric = "DummyApdb" 

149 task = NoneTask(config=config) 

150 butler, quantum, input = self._prepareQuantum(task) 

151 

152 with unittest.mock.patch.object( 

153 lsst.pipe.base.ButlerQuantumContext, "put") as put: 

154 testUtils.runTestQuantum(task, butler, quantum, mockRun=False) 

155 # Should not attempt to write nonexistent data 

156 put.assert_not_called() 

157 

158 def testRunQuantumException(self): 

159 class ExceptionalTask(DummyTask): 

160 def run(self, *args, **kwargs): 

161 raise MetricComputationError() 

162 

163 config = ExceptionalTask.ConfigClass() 

164 config.connections.package = "verify" 

165 config.connections.metric = "DummyApdb" 

166 task = ExceptionalTask(config=config) 

167 butler, quantum, input = self._prepareQuantum(task) 

168 

169 with unittest.mock.patch.object( 

170 lsst.pipe.base.ButlerQuantumContext, "put") as put: 

171 testUtils.runTestQuantum(task, butler, quantum, mockRun=False) 

172 # Should not propagate MetricComputationError 

173 # Should not attempt to write data that was never returned 

174 put.assert_not_called() 

175 

176 

177# Hack around unittest's hacky test setup system 

178del ApdbMetricTestCase 

179 

180 

181class MemoryTester(lsst.utils.tests.MemoryTestCase): 

182 pass 

183 

184 

185def setup_module(module): 

186 lsst.utils.tests.init() 

187 

188 

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

190 lsst.utils.tests.init() 

191 unittest.main()