Files
scylladb/test/cluster/dtest/conftest.py
Andrei Chekun 4a7d8cd99d test.py: add explicit default values to pytest options
Add explicit default values to pytest command line options to prevent
issues when running tests with pytest's parallel execution where
options are not present on upper conftest, so they're just not set at all.
2026-02-24 09:48:38 +01:00

134 lines
5.1 KiB
Python

#
# Copyright (C) 2025-present ScyllaDB
#
# SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
#
from __future__ import annotations
import argparse
import logging
from typing import TYPE_CHECKING
import pytest
from test.cluster.dtest.dtest_config import DTestConfig
from test.cluster.dtest.dtest_setup import DTestSetup
from test.cluster.dtest.dtest_setup_overrides import DTestSetupOverrides
if TYPE_CHECKING:
from collections.abc import Generator
from pytest import Config, Parser, FixtureRequest
from test.pylib.manager_client import ManagerClient
logger = logging.getLogger(__name__)
def pytest_addoption(parser: Parser) -> None:
parser.addoption("--use-vnodes", action="store_true", default=True, help="Determines wither or not to setup clusters using vnodes for tests")
parser.addoption("--num-tokens", action="store", default=256, help="Number of tokens to set num_tokens yaml setting to when creating instances with vnodes enabled")
parser.addoption("--experimental-features", type=lambda s: s.split(","), action="store", help="Pass experimental features <feature>,<feature> to enable", default=None)
parser.addoption("--tablets", action=argparse.BooleanOptionalAction, default=False, help="Whether to enable tablets support (default: %(default)s)")
parser.addoption("--force-gossip-topology-changes", action="store_true", default=False, help="force gossip topology changes in a fresh cluster")
def pytest_configure(config: Config) -> None:
features = {"cdc", "raft", "consistent-cluster-management", "consistent-topology-changes"}
if experimental_features := config.getoption("--experimental-features"):
features.update(experimental_features)
if config.getoption("--force-gossip-topology-changes") and config.getoption("--tablets"):
raise Exception("--force-gossip-topology-changes and --tablets cannot be used together")
if config.getoption("--force-gossip-topology-changes"):
features.remove("consistent-topology-changes")
if config.getoption("--tablets"):
features.add("tablets")
config.scylla_features = features
@pytest.fixture(scope="function", autouse=True)
def fixture_dtest_setup_overrides(dtest_config: DTestConfig) -> DTestSetupOverrides:
"""
no-op default implementation of fixture_dtest_setup_overrides.
we run this when a test class hasn't implemented their own
fixture_dtest_setup_overrides
"""
return DTestSetupOverrides()
@pytest.fixture(scope="function", autouse=False)
def fixture_dtest_setup(request: FixtureRequest,
dtest_config: DTestConfig,
fixture_dtest_setup_overrides: DTestSetupOverrides,
manager: ManagerClient,
build_mode: str) -> Generator[DTestSetup]:
dtest_setup = DTestSetup(
dtest_config=dtest_config,
setup_overrides=fixture_dtest_setup_overrides,
manager=manager,
scylla_mode=build_mode,
)
if request.node.get_closest_marker("single_node") or not request.node.get_closest_marker("no_boot_speedups"):
dtest_setup.cluster_options.setdefault("skip_wait_for_gossip_to_settle", 0)
# Reduce waiting time for the nodes to hear from others before joining the ring.
# Since all test cases run on localhost and there are no large test clusters
# it's safe to reduce the value to save a lot of time while testing.
# (Default value for the option is 30s)
dtest_setup.cluster_options.setdefault("ring_delay_ms", 10000)
cluster_options = request.node.get_closest_marker("cluster_options")
if cluster_options:
for name, value in cluster_options.kwargs.items():
dtest_setup.cluster_options.setdefault(name, value)
dtest_setup.init_default_config()
# at this point we're done with our setup operations in this fixture
# yield to allow the actual test to run
yield dtest_setup
# phew! we're back after executing the test, now we need to do
# all of our teardown and cleanup operations
dtest_setup.jvm_args = []
for con in dtest_setup.connections:
con.cluster.shutdown()
dtest_setup.connections = []
try:
dtest_setup.cluster.stop(gently=True)
except Exception as e: # noqa: BLE001
logger.error("Error stopping cluster: %s", str(e))
manager.ignore_log_patterns.extend(dtest_setup.ignore_log_patterns)
manager.ignore_cores_log_patterns.extend(dtest_setup.ignore_cores_log_patterns)
try:
if not dtest_setup.allow_log_errors:
exclude_errors = []
if marker := request.node.get_closest_marker("exclude_errors"):
exclude_errors = list(marker.args)
dtest_setup.check_errors_all_nodes(exclude_errors=exclude_errors)
finally:
pass
@pytest.fixture(scope="session", autouse=True)
def install_debugging_signal_handler() -> None:
import faulthandler
faulthandler.enable()
@pytest.fixture(scope="session")
def dtest_config(request: FixtureRequest) -> Generator[DTestConfig]:
dtest_config = DTestConfig()
dtest_config.setup(request)
yield dtest_config