# Copyright 2022-present ScyllaDB # # SPDX-License-Identifier: AGPL-3.0-or-later # # Common pytest fixtures for all subdirectories which specifically # request these by adding "addopts = --confcutdir .." in their # pytest.ini or lack pytest.ini altogether. # # Please avoid adding bloat (you can also import # fixtures directly from test/pylib). # # from cassandra.auth import PlainTextAuthProvider # type: ignore from cassandra.cluster import Cluster, ConsistencyLevel # type: ignore from cassandra.cluster import ExecutionProfile, EXEC_PROFILE_DEFAULT # type: ignore from cassandra.policies import RoundRobinPolicy # type: ignore from test.pylib.util import unique_name # type: ignore import pytest import ssl # By default, tests run against a CQL server (Scylla or Cassandra) listening # on localhost:9042. Add the --host and --port options to allow overiding # these defaults. def pytest_addoption(parser): parser.addoption('--host', action='store', default='localhost', help='CQL server host to connect to') parser.addoption('--port', action='store', default='9042', help='CQL server port to connect to') parser.addoption('--ssl', action='store_true', help='Connect to CQL via an encrypted TLSv1.2 connection') # "cql" fixture: set up client object for communicating with the CQL API. # The host/port combination of the server are determined by the --host and # --port options, and defaults to localhost and 9042, respectively. # We use scope="session" so that all tests will reuse the same client object. @pytest.fixture(scope="session") def cql(request): profile = ExecutionProfile( load_balancing_policy=RoundRobinPolicy(), consistency_level=ConsistencyLevel.LOCAL_QUORUM, serial_consistency_level=ConsistencyLevel.LOCAL_SERIAL, # The default timeout (in seconds) for execute() commands is 10, which # should have been more than enough, but in some extreme cases with a # very slow debug build running on a very busy machine and a very slow # request (e.g., a DROP KEYSPACE needing to drop multiple tables) # 10 seconds may not be enough, so let's increase it. See issue #7838. request_timeout=120) if request.config.getoption('ssl'): # Scylla does not support any earlier TLS protocol. If you try, # you will get mysterious EOF errors (see issue #6971) :-( ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) else: ssl_context = None cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile}, contact_points=[request.config.getoption('host')], port=int(request.config.getoption('port')), # TODO: make the protocol version an option, to allow testing with # different versions. If we drop this setting completely, it will # mean pick the latest version supported by the client and the server. protocol_version=4, # Use the default superuser credentials, which work for both Scylla and Cassandra auth_provider=PlainTextAuthProvider(username='cassandra', password='cassandra'), ssl_context=ssl_context, ) yield cluster.connect() cluster.shutdown() # A function-scoped autouse=True fixture allows us to test after every test # that the CQL connection is still alive - and if not report the test which # crashed Scylla and stop running any more tests. @pytest.fixture(scope="function", autouse=True) def cql_test_connection(cql, request): yield try: # We want to run a do-nothing CQL command. "use system" is the # closest to do-nothing I could find... cql.execute("use system") except: # noqa: E722 pytest.exit(f"Scylla appears to have crashed in test {request.node.parent.name}::{request.node.name}") # Until Cassandra 4, NetworkTopologyStrategy did not support the option # replication_factor (https://issues.apache.org/jira/browse/CASSANDRA-14303). # We want to allow these tests to run on Cassandra 3.* (for the convenience # of developers who happen to have it installed), so we'll use the older # syntax that needs to specify a DC name explicitly. For this, will have # a "this_dc" fixture to figure out the name of the current DC, so it can be # used in NetworkTopologyStrategy. @pytest.fixture(scope="session") def this_dc(cql): yield cql.execute("SELECT data_center FROM system.local").one()[0] # "test_keyspace" fixture: Creates and returns a temporary keyspace to be # used in tests that need a keyspace. The keyspace is created with RF=1, # and automatically deleted at the end. We use scope="session" so that all # tests will reuse the same keyspace. @pytest.fixture(scope="session") def test_keyspace(cql, this_dc): name = unique_name() cql.execute("CREATE KEYSPACE " + name + " WITH REPLICATION = { 'class' : 'NetworkTopologyStrategy', '" + this_dc + "' : 1 }") yield name cql.execute("DROP KEYSPACE " + name)