Coverage for tests/test_apdbSqlSchema.py: 20%

93 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-04-26 09:55 +0000

1# This file is part of dax_apdb. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (http://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 <http://www.gnu.org/licenses/>. 

21 

22"""Unit test for ApdbSqlSchema class. 

23""" 

24 

25import os 

26import unittest 

27from typing import Any 

28 

29import lsst.utils.tests 

30import sqlalchemy 

31from lsst.dax.apdb.apdbSchema import ApdbTables 

32from lsst.dax.apdb.sql.apdbSqlSchema import ApdbSqlSchema, ExtraTables 

33from lsst.dax.apdb.tests import update_schema_yaml 

34from sqlalchemy import create_engine 

35 

36TEST_SCHEMA = os.path.join(os.path.abspath(os.path.dirname(__file__)), "config/schema.yaml") 

37 

38 

39class ApdbSchemaTestCase(unittest.TestCase): 

40 """Test case for ApdbSqlSchema class. 

41 

42 Schema is defined in YAML files, some checks here depend on that 

43 configuration and will need to be updated when configuration changes. 

44 """ 

45 

46 # number of columns as defined in tests/config/schema.yaml 

47 table_column_count = { 

48 ApdbTables.DiaObject: 8, 

49 ApdbTables.DiaObjectLast: 5, 

50 ApdbTables.DiaSource: 10, 

51 ApdbTables.DiaForcedSource: 4, 

52 ApdbTables.SSObject: 3, 

53 ApdbTables.metadata: 2, 

54 } 

55 

56 def _assertTable(self, table: sqlalchemy.schema.Table, name: str, ncol: int) -> None: 

57 """Validate tables schema. 

58 

59 Parameters 

60 ---------- 

61 table : `sqlalchemy.Table` 

62 name : `str` 

63 Expected table name 

64 ncol : `int` 

65 Expected number of columns 

66 """ 

67 self.assertIsNotNone(table) 

68 self.assertEqual(table.name, name) 

69 self.assertEqual(len(table.columns), ncol) 

70 

71 def test_makeSchema_default(self) -> None: 

72 """Test for creating schema.""" 

73 engine = create_engine("sqlite://") 

74 

75 # create standard (baseline) schema 

76 schema = ApdbSqlSchema( 

77 engine=engine, dia_object_index="baseline", htm_index_column="pixelId", schema_file=TEST_SCHEMA 

78 ) 

79 schema.makeSchema() 

80 table = schema.get_table(ApdbTables.DiaObject) 

81 # DiaObject table adds pixelId column. 

82 self._assertTable(table, "DiaObject", self.table_column_count[ApdbTables.DiaObject] + 1) 

83 self.assertEqual(len(table.primary_key), 2) 

84 self.assertEqual( 

85 len(schema.get_apdb_columns(ApdbTables.DiaObject)), self.table_column_count[ApdbTables.DiaObject] 

86 ) 

87 with self.assertRaisesRegex(ValueError, ".*does not exist in the schema"): 

88 schema.get_table(ApdbTables.DiaObjectLast) 

89 # DiaSource table also adds pixelId column. 

90 self._assertTable( 

91 schema.get_table(ApdbTables.DiaSource), 

92 "DiaSource", 

93 self.table_column_count[ApdbTables.DiaSource] + 1, 

94 ) 

95 self.assertEqual( 

96 len(schema.get_apdb_columns(ApdbTables.DiaSource)), self.table_column_count[ApdbTables.DiaSource] 

97 ) 

98 self._assertTable( 

99 schema.get_table(ApdbTables.DiaForcedSource), 

100 "DiaForcedSource", 

101 self.table_column_count[ApdbTables.DiaForcedSource], 

102 ) 

103 self.assertEqual( 

104 len(schema.get_apdb_columns(ApdbTables.DiaForcedSource)), 

105 self.table_column_count[ApdbTables.DiaForcedSource], 

106 ) 

107 self._assertTable( 

108 schema.get_table(ApdbTables.metadata), 

109 "metadata", 

110 self.table_column_count[ApdbTables.metadata], 

111 ) 

112 self.assertEqual( 

113 len(schema.get_apdb_columns(ApdbTables.metadata)), 

114 self.table_column_count[ApdbTables.metadata], 

115 ) 

116 for table_enum in ExtraTables: 

117 with self.assertRaisesRegex(ValueError, ".*does not exist in the schema"): 

118 schema.get_table(table_enum) 

119 

120 def test_makeSchema_prefix(self) -> None: 

121 """Create schema using prefix.""" 

122 engine = create_engine("sqlite://") 

123 schema = ApdbSqlSchema( 

124 engine=engine, 

125 dia_object_index="baseline", 

126 htm_index_column="pixelId", 

127 schema_file=TEST_SCHEMA, 

128 prefix="Pfx", 

129 ) 

130 # Drop existing tables (but we don't check it here) 

131 schema.makeSchema(drop=True) 

132 self._assertTable( 

133 schema.get_table(ApdbTables.DiaObject), 

134 "PfxDiaObject", 

135 self.table_column_count[ApdbTables.DiaObject] + 1, 

136 ) 

137 with self.assertRaisesRegex(ValueError, ".*does not exist in the schema"): 

138 schema.get_table(ApdbTables.DiaObjectLast) 

139 self._assertTable( 

140 schema.get_table(ApdbTables.DiaSource), 

141 "PfxDiaSource", 

142 self.table_column_count[ApdbTables.DiaSource] + 1, 

143 ) 

144 self._assertTable( 

145 schema.get_table(ApdbTables.DiaForcedSource), 

146 "PfxDiaForcedSource", 

147 self.table_column_count[ApdbTables.DiaForcedSource], 

148 ) 

149 

150 def test_makeSchema_other_index(self) -> None: 

151 """Use different indexing for DiaObject, this changes number of PK 

152 columns. 

153 """ 

154 engine = create_engine("sqlite://") 

155 schema = ApdbSqlSchema( 

156 engine=engine, dia_object_index="pix_id_iov", htm_index_column="pixelId", schema_file=TEST_SCHEMA 

157 ) 

158 schema.makeSchema(drop=True) 

159 table = schema.get_table(ApdbTables.DiaObject) 

160 self._assertTable(table, "DiaObject", self.table_column_count[ApdbTables.DiaObject] + 1) 

161 self.assertEqual(len(table.primary_key), 3) 

162 with self.assertRaisesRegex(ValueError, ".*does not exist in the schema"): 

163 schema.get_table(ApdbTables.DiaObjectLast) 

164 self._assertTable( 

165 schema.get_table(ApdbTables.DiaSource), 

166 "DiaSource", 

167 self.table_column_count[ApdbTables.DiaSource] + 1, 

168 ) 

169 self._assertTable( 

170 schema.get_table(ApdbTables.DiaForcedSource), 

171 "DiaForcedSource", 

172 self.table_column_count[ApdbTables.DiaForcedSource], 

173 ) 

174 

175 def test_makeSchema_diaobjectlast(self) -> None: 

176 """Use DiaObjectLast table for DiaObject.""" 

177 engine = create_engine("sqlite://") 

178 schema = ApdbSqlSchema( 

179 engine=engine, 

180 dia_object_index="last_object_table", 

181 htm_index_column="pixelId", 

182 schema_file=TEST_SCHEMA, 

183 ) 

184 schema.makeSchema(drop=True) 

185 table = schema.get_table(ApdbTables.DiaObject) 

186 self._assertTable(table, "DiaObject", self.table_column_count[ApdbTables.DiaObject] + 1) 

187 self.assertEqual(len(table.primary_key), 2) 

188 table = schema.get_table(ApdbTables.DiaObjectLast) 

189 self._assertTable(table, "DiaObjectLast", self.table_column_count[ApdbTables.DiaObjectLast] + 1) 

190 self.assertEqual(len(table.primary_key), 2) 

191 self._assertTable( 

192 schema.get_table(ApdbTables.DiaSource), 

193 "DiaSource", 

194 self.table_column_count[ApdbTables.DiaSource] + 1, 

195 ) 

196 self._assertTable( 

197 schema.get_table(ApdbTables.DiaForcedSource), 

198 "DiaForcedSource", 

199 self.table_column_count[ApdbTables.DiaForcedSource], 

200 ) 

201 

202 def test_makeSchema_replica(self) -> None: 

203 """Add replica tables.""" 

204 engine = create_engine("sqlite://") 

205 schema = ApdbSqlSchema( 

206 engine=engine, 

207 dia_object_index="last_object_table", 

208 htm_index_column="pixelId", 

209 schema_file=TEST_SCHEMA, 

210 enable_replica=True, 

211 ) 

212 schema.makeSchema(drop=True) 

213 self._assertTable(schema.get_table(ExtraTables.ApdbReplicaChunks), "ApdbReplicaChunks", 3) 

214 self.assertEqual(len(schema.get_apdb_columns(ExtraTables.ApdbReplicaChunks)), 3) 

215 self._assertTable(schema.get_table(ExtraTables.DiaObjectChunks), "DiaObjectChunks", 3) 

216 self.assertEqual(len(schema.get_apdb_columns(ExtraTables.DiaObjectChunks)), 3) 

217 self._assertTable(schema.get_table(ExtraTables.DiaSourceChunks), "DiaSourceChunks", 2) 

218 self.assertEqual(len(schema.get_apdb_columns(ExtraTables.DiaSourceChunks)), 2) 

219 self._assertTable(schema.get_table(ExtraTables.DiaForcedSourceChunks), "DiaForcedSourceChunks", 3) 

220 self.assertEqual(len(schema.get_apdb_columns(ExtraTables.DiaForcedSourceChunks)), 3) 

221 

222 def test_makeSchema_nometa(self) -> None: 

223 """Make schema using old yaml file without metadata table.""" 

224 with update_schema_yaml(TEST_SCHEMA, drop_metadata=True) as schema_file: 

225 engine = create_engine("sqlite://") 

226 schema = ApdbSqlSchema( 

227 engine=engine, 

228 dia_object_index="baseline", 

229 htm_index_column="pixelId", 

230 schema_file=schema_file, 

231 ) 

232 schema.makeSchema(drop=True) 

233 with self.assertRaisesRegex(ValueError, "Table type ApdbTables.metadata does not exist"): 

234 schema.get_table(ApdbTables.metadata) 

235 

236 # Also check the case when database is missing metadata table but 

237 # YAML schema has it. 

238 schema = ApdbSqlSchema( 

239 engine=engine, 

240 dia_object_index="baseline", 

241 htm_index_column="pixelId", 

242 schema_file=TEST_SCHEMA, 

243 ) 

244 with self.assertRaisesRegex(ValueError, "Table type ApdbTables.metadata does not exist"): 

245 schema.get_table(ApdbTables.metadata) 

246 

247 

248class MyMemoryTestCase(lsst.utils.tests.MemoryTestCase): 

249 """Run file leak tests.""" 

250 

251 

252def setup_module(module: Any) -> None: 

253 """Configure pytest.""" 

254 lsst.utils.tests.init() 

255 

256 

257if __name__ == "__main__": 

258 lsst.utils.tests.init() 

259 unittest.main()