Coverage for tests/test_apdbCassandra.py: 46%
80 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-03-28 10:11 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-03-28 10:11 +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/>.
22"""Unit test for `ApdbCassandra` class.
24Notes
25-----
26For now this test can only run against actual Cassandra cluster, to specify
27cluster location use ``DAX_APDB_TEST_CASSANDRA_CLUSTER`` environment variable,
28e.g.:
30 export DAX_APDB_TEST_CASSANDRA_CLUSTER=cassandra.example.com
31 pytest tests/test_apdbCassandra.py
33Individual tests create and destroy unique keyspaces in the cluster, there is
34no need to pre-create a keyspace with predefined name.
35"""
37import logging
38import os
39import unittest
40import uuid
41from typing import TYPE_CHECKING, Any
43try:
44 from cassandra.cluster import EXEC_PROFILE_DEFAULT, Cluster, ExecutionProfile
45 from cassandra.policies import RoundRobinPolicy
47 CASSANDRA_IMPORTED = True
48except ImportError:
49 CASSANDRA_IMPORTED = False
51import lsst.utils.tests
52from lsst.dax.apdb import ApdbCassandraConfig, ApdbTables
53from lsst.dax.apdb.apdbCassandra import CASSANDRA_IMPORTED
54from lsst.dax.apdb.tests import ApdbSchemaUpdateTest, ApdbTest
56TEST_SCHEMA = os.path.join(os.path.abspath(os.path.dirname(__file__)), "config/schema.yaml")
58logging.basicConfig(level=logging.INFO)
61class ApdbCassandraMixin:
62 """Mixin class which defines common methods for unit tests."""
64 @classmethod
65 def setUpClass(cls) -> None:
66 """Prepare config for server connection."""
67 if not CASSANDRA_IMPORTED:
68 raise unittest.SkipTest("FAiled to import Cassandra modules")
69 cluster_host = os.environ.get("DAX_APDB_TEST_CASSANDRA_CLUSTER")
70 if not cluster_host:
71 raise unittest.SkipTest("DAX_APDB_TEST_CASSANDRA_CLUSTER is not set")
72 if not CASSANDRA_IMPORTED:
73 raise unittest.SkipTest("cassandra_driver cannot be imported")
75 def _run_query(self, query: str) -> None:
76 # Used protocol version from default config.
77 config = ApdbCassandraConfig()
78 default_profile = ExecutionProfile(load_balancing_policy=RoundRobinPolicy())
79 profiles = {EXEC_PROFILE_DEFAULT: default_profile}
80 cluster = Cluster(
81 contact_points=[self.cluster_host],
82 execution_profiles=profiles,
83 protocol_version=config.protocol_version,
84 )
85 session = cluster.connect()
86 session.execute(query, timeout=120)
87 del session
88 cluster.shutdown()
90 def setUp(self) -> None:
91 """Prepare config for server connection."""
92 self.cluster_host = os.environ.get("DAX_APDB_TEST_CASSANDRA_CLUSTER")
94 # create dedicated keyspace for each test
95 key = uuid.uuid4()
96 self.keyspace = f"apdb_{key.hex}"
97 query = (
98 f"CREATE KEYSPACE {self.keyspace}"
99 " WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}"
100 )
101 self._run_query(query)
103 def tearDown(self) -> None:
104 query = f"DROP KEYSPACE {self.keyspace}"
105 self._run_query(query)
107 if TYPE_CHECKING: 107 ↛ 109line 107 didn't jump to line 109, because the condition on line 107 was never true
108 # For mypy.
109 def make_config(self, **kwargs: Any) -> ApdbCassandraConfig: ...
112class ApdbCassandraTestCase(ApdbCassandraMixin, ApdbTest, unittest.TestCase):
113 """A test case for ApdbCassandra class"""
115 allow_visit_query = False
116 time_partition_tables = False
117 time_partition_start: str | None = None
118 time_partition_end: str | None = None
120 def make_config(self, **kwargs: Any) -> ApdbCassandraConfig:
121 """Make config class instance used in all tests."""
122 kw = {
123 "contact_points": [self.cluster_host],
124 "keyspace": self.keyspace,
125 "schema_file": TEST_SCHEMA,
126 "time_partition_tables": self.time_partition_tables,
127 "use_insert_id": self.use_insert_id,
128 }
129 if self.time_partition_start:
130 kw["time_partition_start"] = self.time_partition_start
131 if self.time_partition_end:
132 kw["time_partition_end"] = self.time_partition_end
133 kw.update(kwargs)
134 return ApdbCassandraConfig(**kw)
136 def getDiaObjects_table(self) -> ApdbTables:
137 """Return type of table returned from getDiaObjects method."""
138 return ApdbTables.DiaObjectLast
141class ApdbCassandraPerMonthTestCase(ApdbCassandraTestCase):
142 """A test case for ApdbCassandra class with per-month tables."""
144 time_partition_tables = True
145 time_partition_start = "2019-12-01T00:00:00"
146 time_partition_end = "2022-01-01T00:00:00"
149class ApdbCassandraTestCaseInsertIds(ApdbCassandraTestCase):
150 """A test case with use_insert_id."""
152 use_insert_id = True
155class ApdbSchemaUpdateCassandraTestCase(ApdbCassandraMixin, ApdbSchemaUpdateTest, unittest.TestCase):
156 """A test case for schema updates using Cassandra backend."""
158 def make_config(self, **kwargs: Any) -> ApdbCassandraConfig:
159 """Make config class instance used in all tests."""
160 kw = {
161 "contact_points": [self.cluster_host],
162 "keyspace": self.keyspace,
163 "schema_file": TEST_SCHEMA,
164 "time_partition_tables": False,
165 }
166 kw.update(kwargs)
167 return ApdbCassandraConfig(**kw)
170class MyMemoryTestCase(lsst.utils.tests.MemoryTestCase):
171 """Run file leak tests."""
174def setup_module(module: Any) -> None:
175 """Configure pytest."""
176 lsst.utils.tests.init()
179if __name__ == "__main__": 179 ↛ 180line 179 didn't jump to line 180, because the condition on line 179 was never true
180 lsst.utils.tests.init()
181 unittest.main()