# Copyright 2021-present ScyllaDB # # SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0 # This file configures pytest for all tests in this directory, and also # defines common test fixtures for all of them to use. A "fixture" is some # setup which an individual test requires to run; The fixture has setup code # and teardown code, and if multiple tests require the same fixture, it can # be set up only once - while still allowing the user to run individual tests # and automatically setting up the fixtures they need. import pytest import requests from test.cqlpy.conftest import host, cql, this_dc # add required fixtures from test.cqlpy.util import unique_name, new_test_keyspace, keyspace_has_tablets, is_scylla from test.pylib.runner import testpy_test_fixture_scope from test.pylib.suite.python import add_host_option, add_cql_connection_options # By default, tests run against a Scylla server listening # on localhost:9042 for CQL and localhost:10000 for the REST API. # Add the --host, --port, --ssl, or --api-port options to allow overriding these defaults. def pytest_addoption(parser): add_host_option(parser) add_cql_connection_options(parser) parser.addoption('--api-port', action='store', default='10000', help='server REST API port to connect to') class RestApiSession: def __init__(self, host, port): self.host = host self.port = port self.session = requests.Session() def send(self, method, path, params={}, json_body=None): url=f"http://{self.host}:{self.port}/{path}" if params: sep = '?' for key, value in params.items(): if isinstance(value, list): for v in value: url += f"{sep}{key}={v}" sep = '&' else: url += f"{sep}{key}={value}" sep = '&' req = self.session.prepare_request(requests.Request(method, url, json=json_body)) return self.session.send(req) # "api" fixture: set up client object for communicating with Scylla API. # The host/port combination of the server are determined by the --host and # --port options, and defaults to localhost and 10000, respectively. @pytest.fixture(scope=testpy_test_fixture_scope) def rest_api(request, host): port = request.config.getoption('api_port') return RestApiSession(host, port) # The "scylla_only" fixture can be used by tests for Scylla-only features, # which do not exist on Apache Cassandra. A test using this fixture will be # skipped if running with "run-cassandra". @pytest.fixture(scope=testpy_test_fixture_scope) def scylla_only(cql): # We recognize Scylla by checking if there is any system table whose name # contains the word "scylla": if not is_scylla(cql): pytest.skip('Scylla-only test skipped') @pytest.fixture(scope=testpy_test_fixture_scope) def has_tablets(cql): with new_test_keyspace(cql, " WITH REPLICATION = {'class' : 'NetworkTopologyStrategy', 'replication_factor': 1}") as keyspace: return keyspace_has_tablets(cql, keyspace) @pytest.fixture(scope="function") def skip_with_tablets(has_tablets): if has_tablets: pytest.skip("Test may crash with tablets experimental feature on") @pytest.fixture(scope="function") def skip_without_tablets(scylla_only, has_tablets): if not has_tablets: pytest.skip("Test needs tablets experimental feature on") @pytest.fixture(scope=testpy_test_fixture_scope) def test_keyspace_vnodes(cql, this_dc, has_tablets): name = unique_name() if has_tablets: cql.execute("CREATE KEYSPACE " + name + " WITH REPLICATION = { 'class' : 'NetworkTopologyStrategy', '" + this_dc + "' : 1 } AND TABLETS = {'enabled': false}") else: # If tablets are not available or not enabled, we just create a regular keyspace cql.execute("CREATE KEYSPACE " + name + " WITH REPLICATION = { 'class' : 'NetworkTopologyStrategy', '" + this_dc + "' : 1 }") yield name cql.execute("DROP KEYSPACE " + name) @pytest.fixture(scope=testpy_test_fixture_scope) 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)