Coverage for tests/test_dataid_match.py: 15%
54 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-12 02:34 -0800
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-12 02:34 -0800
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 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/>.
22import unittest
24from lsst.ctrl.mpexec.dataid_match import DataIdMatch
27class DataIdMatchTestCase(unittest.TestCase):
28 """A test case for DataidMatch class"""
30 dataIds = (
31 {"instrument": "INSTR", "detector": 1, "number": 4},
32 {"instrument": "INSTR", "detector": 2, "number": 3},
33 {"instrument": "LSST", "detector": 3, "number": 2},
34 {"instrument": "LSST", "detector": 4, "number": 1},
35 )
37 def test_strings(self):
38 """Tests for string comparisons method"""
40 tests = (
41 ("instrument = 'INSTR'", [True, True, False, False]),
42 ("instrument = 'LSST'", [False, False, True, True]),
43 ("instrument < 'LSST'", [True, True, False, False]),
44 ("instrument IN ('LSST', 'INSTR')", [True, True, True, True]),
45 )
47 for expr, result in tests:
48 dataIdMatch = DataIdMatch(expr)
49 self.assertEqual([dataIdMatch.match(dataId) for dataId in self.dataIds], result)
51 def test_comparisons(self):
52 """Test all supported comparison operators"""
54 tests = (
55 ("detector = 1", [True, False, False, False]),
56 ("detector != 1", [False, True, True, True]),
57 ("detector > 2", [False, False, True, True]),
58 ("2 <= detector", [False, True, True, True]),
59 ("2 > detector", [True, False, False, False]),
60 ("2 >= detector", [True, True, False, False]),
61 )
63 for expr, result in tests:
64 dataIdMatch = DataIdMatch(expr)
65 self.assertEqual([dataIdMatch.match(dataId) for dataId in self.dataIds], result)
67 def test_arith(self):
68 """Test all supported arithmetical operators"""
70 tests = (
71 ("detector + number = 5", [True, True, True, True]),
72 ("detector - number = 1", [False, False, True, False]),
73 ("detector * number = 6", [False, True, True, False]),
74 ("detector / number = 1.5", [False, False, True, False]),
75 ("detector % number = 1", [True, False, True, False]),
76 ("+detector = 1", [True, False, False, False]),
77 ("-detector = -4", [False, False, False, True]),
78 )
80 for expr, result in tests:
81 dataIdMatch = DataIdMatch(expr)
82 self.assertEqual([dataIdMatch.match(dataId) for dataId in self.dataIds], result)
84 def test_logical(self):
85 """Test all supported logical operators"""
87 tests = (
88 ("detector = 1 OR instrument = 'LSST'", [True, False, True, True]),
89 ("detector = 1 AND instrument = 'INSTR'", [True, False, False, False]),
90 ("NOT detector = 1", [False, True, True, True]),
91 )
93 for expr, result in tests:
94 dataIdMatch = DataIdMatch(expr)
95 self.assertEqual([dataIdMatch.match(dataId) for dataId in self.dataIds], result)
97 def test_parens(self):
98 """Test parentheses"""
100 tests = (("(detector = 1 OR number = 1) AND instrument = 'LSST'", [False, False, False, True]),)
102 for expr, result in tests:
103 dataIdMatch = DataIdMatch(expr)
104 self.assertEqual([dataIdMatch.match(dataId) for dataId in self.dataIds], result)
106 def test_in(self):
107 """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 )
116 for expr, result in tests:
117 dataIdMatch = DataIdMatch(expr)
118 self.assertEqual([dataIdMatch.match(dataId) for dataId in self.dataIds], result)
120 def test_errors(self):
121 """Test for errors in expressions"""
123 dataId = {"instrument": "INSTR", "detector": 1}
125 # Unknown identifier
126 expr = "INSTRUMENT = 'INSTR'"
127 dataIdMatch = DataIdMatch(expr)
128 with self.assertRaisesRegex(KeyError, "INSTRUMENT"):
129 dataIdMatch.match(dataId)
131 # non-boolean expression
132 expr = "instrument"
133 dataIdMatch = DataIdMatch(expr)
134 with self.assertRaisesRegex(TypeError, "Expression 'instrument' returned non-boolean object"):
135 dataIdMatch.match(dataId)
137 # operations on unsupported combination of types
138 expr = "instrument - detector = 0"
139 dataIdMatch = DataIdMatch(expr)
140 with self.assertRaisesRegex(TypeError, "unsupported operand type"):
141 dataIdMatch.match(dataId)
143 # function calls are not implemented
144 expr = "POINT(2, 1) != POINT(1, 2)"
145 dataIdMatch = DataIdMatch(expr)
146 with self.assertRaises(NotImplementedError):
147 dataIdMatch.match(dataId)
150if __name__ == "__main__": 150 ↛ 151line 150 didn't jump to line 151, because the condition on line 150 was never true
151 unittest.main()