Coverage for tests/test_simple.py: 15%
90 statements
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-17 10:27 +0000
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-17 10:27 +0000
1# This file is part of felis.
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 os
23import unittest
24from collections.abc import Iterable, MutableMapping, Sequence
25from typing import Any
27import yaml
29from felis import DEFAULT_FRAME, types
30from felis.simple import ForeignKeyConstraint, SimpleVisitor, UniqueConstraint
32TESTDIR = os.path.abspath(os.path.dirname(__file__))
33TEST_YAML = os.path.join(TESTDIR, "data", "test.yml")
36def _names(items: Iterable) -> Sequence[str]:
37 """Return names of items."""
38 return [item.name for item in items]
41class VisitorTestCase(unittest.TestCase):
42 """Tests for both SimpleVisitor classes."""
44 schema_obj: MutableMapping[str, Any] = {}
46 def setUp(self) -> None:
47 """Load data from test file."""
48 with open(TEST_YAML) as test_yaml:
49 self.schema_obj = yaml.load(test_yaml, Loader=yaml.SafeLoader)
50 self.schema_obj.update(DEFAULT_FRAME)
52 def test_schema(self) -> None:
53 """Check schema generated by SimpleVisitor class."""
54 visitor = SimpleVisitor()
55 schema = visitor.visit_schema(self.schema_obj)
57 self.assertIsNotNone(schema)
58 self.assertEqual(schema.name, "sdqa")
60 self.assertIsNotNone(schema.version)
61 assert schema.version is not None, "cannot be None"
62 self.assertEqual(schema.version.current, "1.2.3")
63 assert schema.version.compatible is not None, "cannot be None"
64 self.assertEqual(set(schema.version.compatible), {"1.2.0", "1.2.1", "1.2.2"})
65 assert schema.version.read_compatible is not None, "cannot be None"
66 self.assertEqual(set(schema.version.read_compatible), {"1.1.0", "1.1.1"})
68 self.assertIsNotNone(schema.tables)
69 table_names = [
70 "sdqa_ImageStatus",
71 "sdqa_Metric",
72 "sdqa_Rating_ForAmpVisit",
73 "sdqa_Rating_CcdVisit",
74 "sdqa_Threshold",
75 ]
77 # Check schema.tables attribute.
78 self.assertCountEqual(set(_names(schema.tables)), set(table_names))
80 tables = {table.name: table for table in schema.tables}
82 # Details of sdqa_ImageStatus table.
83 table = tables["sdqa_ImageStatus"]
84 self.assertEqual(_names(table.columns), ["sdqa_imageStatusId", "statusName", "definition"])
85 self.assertEqual(
86 [column.datatype for column in table.columns], [types.Short, types.String, types.String]
87 )
88 self.assertEqual([column.length for column in table.columns], [None, 30, 255])
89 self.assertEqual(
90 [column.annotations for column in table.columns],
91 [
92 {"mysql:datatype": "SMALLINT", "tap:principal": 1},
93 {"mysql:datatype": "VARCHAR(30)"},
94 {"mysql:datatype": "VARCHAR(255)"},
95 ],
96 )
97 self.assertEqual(_names(table.primary_key), ["sdqa_imageStatusId"])
98 self.assertFalse(table.indexes)
99 self.assertEqual(table.annotations, {"mysql:engine": "MyISAM", "tap:table_index": 1})
101 # Details of sdqa_Metric table.
102 table = tables["sdqa_Metric"]
103 self.assertEqual(
104 _names(table.columns), ["sdqa_metricId", "metricName", "physicalUnits", "dataType", "definition"]
105 )
106 self.assertEqual(
107 [column.datatype for column in table.columns],
108 [types.Short, types.String, types.String, types.Char, types.String],
109 )
110 self.assertEqual([column.length for column in table.columns], [None, 30, 30, 1, 255])
111 self.assertEqual(_names(table.primary_key), ["sdqa_metricId"])
112 self.assertFalse(table.indexes)
113 self.assertEqual(table.annotations, {"mysql:engine": "MyISAM", "tap:table_index": 2})
115 # It defines a unique constraint.
116 self.assertEqual(len(table.constraints), 1)
117 constraint = table.constraints[0]
118 self.assertIsInstance(constraint, UniqueConstraint)
119 assert isinstance(constraint, UniqueConstraint) # for mypy
120 self.assertEqual(constraint.name, "UQ_sdqaMetric_metricName")
121 self.assertEqual(_names(constraint.columns), ["metricName"])
122 self.assertEqual(constraint.annotations, {})
124 # Details of sdqa_Rating_ForAmpVisit table.
125 table = tables["sdqa_Rating_ForAmpVisit"]
126 self.assertEqual(
127 _names(table.columns),
128 [
129 "sdqa_ratingId",
130 "sdqa_metricId",
131 "sdqa_thresholdId",
132 "ampVisitId",
133 "metricValue",
134 "metricSigma",
135 ],
136 )
137 self.assertEqual(_names(table.primary_key), ["sdqa_ratingId"])
138 self.assertEqual(
139 [column.datatype for column in table.columns],
140 [types.Long, types.Short, types.Short, types.Long, types.Double, types.Double],
141 )
142 self.assertEqual(table.annotations, {"mysql:engine": "MyISAM", "tap:table_index": 3})
144 # constraints
145 self.assertEqual(len(table.constraints), 2)
146 constraint = table.constraints[0]
147 self.assertIsInstance(constraint, UniqueConstraint)
148 assert isinstance(constraint, UniqueConstraint) # for mypy
149 self.assertEqual(constraint.name, "UQ_sdqaRatingForAmpVisit_metricId_ampVisitId")
150 self.assertEqual(_names(constraint.columns), ["sdqa_metricId", "ampVisitId"])
151 self.assertEqual(constraint.annotations, {})
152 constraint = table.constraints[1]
153 self.assertIsInstance(constraint, ForeignKeyConstraint)
154 assert isinstance(constraint, ForeignKeyConstraint) # for mypy
155 self.assertEqual(constraint.name, "FK_sdqa_Rating_ForAmpVisit_sdqa_Metric")
156 self.assertEqual(_names(constraint.columns), ["sdqa_metricId"])
157 self.assertEqual(_names(constraint.referenced_columns), ["sdqa_metricId"])
158 self.assertIs(constraint.referenced_columns[0].table, tables["sdqa_Metric"])
159 self.assertEqual(constraint.annotations, {})
161 # It has a bunch of indices.
162 self.assertEqual(len(table.indexes), 3)
163 index = table.indexes[0]
164 self.assertEqual(index.name, "IDX_sdqaRatingForAmpVisit_metricId")
165 self.assertEqual(_names(index.columns), ["sdqa_metricId"])
166 self.assertEqual(index.annotations, {})
167 index = table.indexes[1]
168 self.assertEqual(index.name, "IDX_sdqaRatingForAmpVisit_thresholdId")
169 self.assertEqual(_names(index.columns), ["sdqa_thresholdId"])
170 self.assertEqual(index.annotations, {})
171 index = table.indexes[2]
172 self.assertEqual(index.name, "IDX_sdqaRatingForAmpVisit_ampVisitId")
173 self.assertEqual(_names(index.columns), ["ampVisitId"])
174 self.assertEqual(index.annotations, {})
177if __name__ == "__main__": 177 ↛ 178line 177 didn't jump to line 178, because the condition on line 177 was never true
178 unittest.main()