Coverage for tests/test_dataid_match.py: 13%

52 statements  

« prev     ^ index     » next       coverage.py v7.4.0, created at 2024-01-11 17:45 +0000

1# This file is part of ctrl_mpexec. 

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 software is dual licensed under the GNU General Public License and also 

10# under a 3-clause BSD license. Recipients may choose which of these licenses 

11# to use; please see the files gpl-3.0.txt and/or bsd_license.txt, 

12# respectively. If you choose the GPL option then the following text applies 

13# (but note that there is still no warranty even if you opt for BSD instead): 

14# 

15# This program is free software: you can redistribute it and/or modify 

16# it under the terms of the GNU General Public License as published by 

17# the Free Software Foundation, either version 3 of the License, or 

18# (at your option) any later version. 

19# 

20# This program is distributed in the hope that it will be useful, 

21# but WITHOUT ANY WARRANTY; without even the implied warranty of 

22# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

23# GNU General Public License for more details. 

24# 

25# You should have received a copy of the GNU General Public License 

26# along with this program. If not, see <https://www.gnu.org/licenses/>. 

27 

28import unittest 

29 

30from lsst.pipe.base.tests.mocks import DataIdMatch 

31 

32 

33class DataIdMatchTestCase(unittest.TestCase): 

34 """A test case for DataidMatch class.""" 

35 

36 dataIds = ( 

37 {"instrument": "INSTR", "detector": 1, "number": 4}, 

38 {"instrument": "INSTR", "detector": 2, "number": 3}, 

39 {"instrument": "LSST", "detector": 3, "number": 2}, 

40 {"instrument": "LSST", "detector": 4, "number": 1}, 

41 ) 

42 

43 def test_strings(self): 

44 """Tests for string comparisons method.""" 

45 tests = ( 

46 ("instrument = 'INSTR'", [True, True, False, False]), 

47 ("instrument = 'LSST'", [False, False, True, True]), 

48 ("instrument < 'LSST'", [True, True, False, False]), 

49 ("instrument IN ('LSST', 'INSTR')", [True, True, True, True]), 

50 ) 

51 

52 for expr, result in tests: 

53 dataIdMatch = DataIdMatch(expr) 

54 self.assertEqual([dataIdMatch.match(dataId) for dataId in self.dataIds], result) 

55 

56 def test_comparisons(self): 

57 """Test all supported comparison operators.""" 

58 tests = ( 

59 ("detector = 1", [True, False, False, False]), 

60 ("detector != 1", [False, True, True, True]), 

61 ("detector > 2", [False, False, True, True]), 

62 ("2 <= detector", [False, True, True, True]), 

63 ("2 > detector", [True, False, False, False]), 

64 ("2 >= detector", [True, True, False, False]), 

65 ) 

66 

67 for expr, result in tests: 

68 dataIdMatch = DataIdMatch(expr) 

69 self.assertEqual([dataIdMatch.match(dataId) for dataId in self.dataIds], result) 

70 

71 def test_arith(self): 

72 """Test all supported arithmetical operators.""" 

73 tests = ( 

74 ("detector + number = 5", [True, True, True, True]), 

75 ("detector - number = 1", [False, False, True, False]), 

76 ("detector * number = 6", [False, True, True, False]), 

77 ("detector / number = 1.5", [False, False, True, False]), 

78 ("detector % number = 1", [True, False, True, False]), 

79 ("+detector = 1", [True, False, False, False]), 

80 ("-detector = -4", [False, False, False, True]), 

81 ) 

82 

83 for expr, result in tests: 

84 dataIdMatch = DataIdMatch(expr) 

85 self.assertEqual([dataIdMatch.match(dataId) for dataId in self.dataIds], result) 

86 

87 def test_logical(self): 

88 """Test all supported logical operators.""" 

89 tests = ( 

90 ("detector = 1 OR instrument = 'LSST'", [True, False, True, True]), 

91 ("detector = 1 AND instrument = 'INSTR'", [True, False, False, False]), 

92 ("NOT detector = 1", [False, True, True, True]), 

93 ) 

94 

95 for expr, result in tests: 

96 dataIdMatch = DataIdMatch(expr) 

97 self.assertEqual([dataIdMatch.match(dataId) for dataId in self.dataIds], result) 

98 

99 def test_parens(self): 

100 """Test parentheses.""" 

101 tests = (("(detector = 1 OR number = 1) AND instrument = 'LSST'", [False, False, False, True]),) 

102 

103 for expr, result in tests: 

104 dataIdMatch = DataIdMatch(expr) 

105 self.assertEqual([dataIdMatch.match(dataId) for dataId in self.dataIds], result) 

106 

107 def test_in(self): 

108 """Test IN expression.""" 

109 tests = ( 

110 ("detector in (1, 3, 2)", [True, True, True, False]), 

111 ("detector not in (1, 3, 2)", [False, False, False, True]), 

112 ("detector in (1..4:2)", [True, False, True, False]), 

113 ("detector in (1..4:2, 4)", [True, False, True, True]), 

114 ) 

115 

116 for expr, result in tests: 

117 dataIdMatch = DataIdMatch(expr) 

118 self.assertEqual([dataIdMatch.match(dataId) for dataId in self.dataIds], result) 

119 

120 def test_errors(self): 

121 """Test for errors in expressions.""" 

122 dataId = {"instrument": "INSTR", "detector": 1} 

123 

124 # Unknown identifier 

125 expr = "INSTRUMENT = 'INSTR'" 

126 dataIdMatch = DataIdMatch(expr) 

127 with self.assertRaisesRegex(KeyError, "INSTRUMENT"): 

128 dataIdMatch.match(dataId) 

129 

130 # non-boolean expression 

131 expr = "instrument" 

132 dataIdMatch = DataIdMatch(expr) 

133 with self.assertRaisesRegex(TypeError, "Expression 'instrument' returned non-boolean object"): 

134 dataIdMatch.match(dataId) 

135 

136 # operations on unsupported combination of types 

137 expr = "instrument - detector = 0" 

138 dataIdMatch = DataIdMatch(expr) 

139 with self.assertRaisesRegex(TypeError, "unsupported operand type"): 

140 dataIdMatch.match(dataId) 

141 

142 # function calls are not implemented 

143 expr = "POINT(2, 1) != POINT(1, 2)" 

144 dataIdMatch = DataIdMatch(expr) 

145 with self.assertRaises(NotImplementedError): 

146 dataIdMatch.match(dataId) 

147 

148 

149if __name__ == "__main__": 

150 unittest.main()