Skip to content

Commit

Permalink
IGNITE-16569 [ducktests] Add ability to customize the test context (a…
Browse files Browse the repository at this point in the history
  • Loading branch information
skorotkov authored Mar 16, 2022
1 parent 8b3f6eb commit 8fa8d92
Show file tree
Hide file tree
Showing 17 changed files with 150 additions and 29 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,5 @@ modules/ducktests/tests/docker/build/**
modules/ducktests/tests/.tox
modules/ducktests/tests/certs/*
modules/ducktests/tests/ignitetest.egg-info/**
modules/ducktests/tests/build/**
modules/ducktests/tests/dist/**
2 changes: 1 addition & 1 deletion modules/ducktests/tests/docker/run_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -160,5 +160,5 @@ if [[ -n "$MAX_PARALLEL" ]]; then
DUCKTAPE_OPTIONS="$DUCKTAPE_OPTIONS --max-parallel $MAX_PARALLEL"
fi

"$SCRIPT_DIR"/ducker-ignite test "$TC_PATHS" "$DUCKTAPE_OPTIONS" \
"$SCRIPT_DIR"/ducker-ignite test $TC_PATHS "$DUCKTAPE_OPTIONS" \
|| die "ducker-ignite test failed"
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class IgniteConfiguration(NamedTuple):
rebalance_batches_prefetch_count: int = None
rebalance_throttle: int = None
local_event_listeners: str = None
include_event_types: str = None
include_event_types: list = []
event_storage_spi: str = None
log4j_config: str = IgnitePathAware.IGNITE_LOG_CONFIG_NAME

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License

from enum import Enum, auto


class EventType(Enum):
"""
Helper for includeEventTypes property in XML configuration
"""

EVT_CACHE_STARTED = auto()
EVT_CACHE_STOPPED = auto()
EVT_CHECKPOINT_SAVED = auto()
EVT_CLUSTER_SNAPSHOT_FAILED = auto()
EVT_CLUSTER_SNAPSHOT_FINISHED = auto()
EVT_CLUSTER_SNAPSHOT_STARTED = auto()
EVT_CLUSTER_SNAPSHOT_RESTORE_FAILED = auto()
EVT_CLUSTER_SNAPSHOT_RESTORE_FINISHED = auto()
EVT_CLUSTER_SNAPSHOT_RESTORE_STARTED = auto()
EVT_CONSISTENCY_VIOLATION = auto()
EVT_NODE_JOINED = auto()
EVT_NODE_LEFT = auto()
EVT_NODE_FAILED = auto()
EVT_NODE_VALIDATION_FAILED = auto()
EVT_SQL_QUERY_EXECUTION = auto()

def __str__(self):
return '#{{T(org.apache.ignite.events.EventType).{}}}'.format(self._name_)

def __repr__(self):
return self.__str__()
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
from ignitetest.services.utils.ssl.ssl_params import SslParams


class ThinClientConfiguration(NamedTuple):
max_active_compute_tasks_per_connection: int = 0
max_active_tx_per_connection: int = 100


class ClientConnectorConfiguration(NamedTuple):
"""
Ignite ClientConnectorConfiguration.
Expand All @@ -32,7 +37,4 @@ class ClientConnectorConfiguration(NamedTuple):
use_ignite_ssl_context_factory: bool = True
ssl_client_auth: bool = False
ssl_params: SslParams = None
ssl_enabled: bool = False
use_ignite_ssl_context_factory: bool = True
ssl_client_auth: bool = False
ssl_params: SslParams = None
thin_client_configuration: ThinClientConfiguration = None
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,14 @@
<property name="useIgniteSslContextFactory" value="{{ config.client_connector_configuration.use_ignite_ssl_context_factory }}"/>
<property name="sslClientAuth" value="{{ config.client_connector_configuration.ssl_client_auth }}"/>
{% endif %}
{% if config.client_connector_configuration.thin_client_configuration %}
<property name="thinClientConfiguration">
<bean class="org.apache.ignite.configuration.ThinClientConfiguration">
<property name="maxActiveComputeTasksPerConnection" value="{{ config.client_connector_configuration.thin_client_configuration.max_active_compute_tasks_per_connection }}" />
<property name="maxActiveTxPerConnection" value="{{ config.client_connector_configuration.thin_client_configuration.max_active_tx_per_connection }}" />
</bean>
</property>
{% endif %}
</bean>
</property>
{% endif %}
Expand All @@ -120,8 +128,8 @@
<property name="localEventListeners" ref="{{ config.local_event_listeners }}"/>
{% endif %}

{% if config.include_event_types %}
<property name="includeEventTypes" ref="{{ config.include_event_types }}"/>
{% if config.include_event_types | length > 0 %}
<property name="includeEventTypes" ref="eventTypes"/>
{% endif %}

{% if config.event_storage_spi %}
Expand All @@ -132,4 +140,8 @@
</bean>

{{ misc_utils.ext_beans(config) }}

{% if config.include_event_types | length > 0 %}
{{ misc_utils.event_types(config) }}
{% endif %}
</beans>
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,13 @@
{% endfor %}
{% endif %}
{% endmacro %}

{% macro event_types(config) %}
{% if config.include_event_types | length > 0 %}
<util:list id="eventTypes" value-type="java.lang.Integer">
{% for event_type in config.include_event_types %}
<value>{{ event_type }}</value>
{% endfor %}
</util:list>
{% endif %}
{% endmacro %}
9 changes: 9 additions & 0 deletions modules/ducktests/tests/ignitetest/services/zk/zookeeper.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,16 @@ def config_file(self):
return os.path.join(self.persistent_root, "zookeeper.properties")

def start(self, **kwargs):
self.start_async(**kwargs)
self.await_started()

def start_async(self, **kwargs):
"""
Starts in async way.
"""
super().start(**kwargs)

def await_started(self):
self.logger.info("Waiting for Zookeeper quorum...")

for node in self.nodes:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def test_latency(self, ignite_version, stop_type, discovery_type, prep_type):
"""
Tests Cellular switch tx latency.
"""
cluster_size = len(self.test_context.cluster)
cluster_size = self.available_cluster_size

cells_amount = math.floor((cluster_size - self.ZOOKEPER_CLUSTER_SIZE) / (self.NODES_PER_CELL + 1))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from ignitetest.services.ignite_execution_exception import IgniteExecutionException
from ignitetest.services.utils.control_utility import ControlUtility
from ignitetest.services.utils.ignite_configuration import IgniteConfiguration
from ignitetest.services.utils.ignite_configuration.event_type import EventType
from ignitetest.utils import cluster, ignite_versions
from ignitetest.utils.ignite_test import IgniteTest
from ignitetest.utils.version import DEV_BRANCH, IgniteVersion
Expand All @@ -43,12 +44,6 @@ class ConsistencyTest(IgniteTest):
"""
CACHE_NAME = "TEST"

PROPERTIES = """
<property name="includeEventTypes">
<util:constant static-field="org.apache.ignite.events.EventType.EVT_CONSISTENCY_VIOLATION"/>
</property>
"""

@cluster(num_nodes=2)
@ignite_versions(str(DEV_BRANCH))
def test_logging(self, ignite_version):
Expand All @@ -62,7 +57,7 @@ def test_logging(self, ignite_version):
IgniteConfiguration(
version=IgniteVersion(ignite_version),
cluster_state="INACTIVE",
properties=self.PROPERTIES,
include_event_types=[EventType.EVT_CONSISTENCY_VIOLATION],
log4j_config=cfg_filename # default AI config (will be generated below)
),
java_class_name="org.apache.ignite.internal.ducktest.tests.control_utility.InconsistentNodeApplication",
Expand All @@ -73,7 +68,7 @@ def test_logging(self, ignite_version):
"tx": False
},
startup_timeout_sec=180,
num_nodes=len(self.test_context.cluster))
num_nodes=self.available_cluster_size)

for node in ignites.nodes: # copying default AI config with log path replacement
ignites.init_persistent(node)
Expand Down
2 changes: 1 addition & 1 deletion modules/ducktests/tests/ignitetest/tests/discovery_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ def test_2_nodes_fail_sequential_zk(self, ignite_version, load_type):
def _perform_node_fail_scenario(self, test_config):
failure_detection_timeout = self._global_int(self.GLOBAL_DETECTION_TIMEOUT, self.DEFAULT_DETECTION_TIMEOUT)

cluster_size = len(self.test_context.cluster)
cluster_size = self.available_cluster_size

# One node is required to detect the failure.
assert cluster_size >= 1 + test_config.nodes_to_kill + (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
from ignitetest.services.utils.control_utility import ControlUtility
from ignitetest.services.utils.ignite_configuration import IgniteConfiguration, DataStorageConfiguration
from ignitetest.services.utils.ignite_configuration.data_storage import DataRegionConfiguration
from ignitetest.utils import cluster
from ignitetest.services.utils.ssl.ssl_params import is_ssl_enabled
from ignitetest.utils import cluster, ignite_versions, ignore_if
from ignitetest.utils.ignite_test import IgniteTest
from ignitetest.utils.version import IgniteVersion, LATEST, DEV_BRANCH, OLDEST

Expand All @@ -33,8 +34,10 @@ class PersistenceUpgradeTest(IgniteTest):
"""

@cluster(num_nodes=1)
@ignite_versions(str(OLDEST))
@ignore_if(lambda _, globals: is_ssl_enabled(globals))
@parametrize(versions=[str(OLDEST), str(LATEST), str(DEV_BRANCH)])
def upgrade_test(self, versions):
def upgrade_test(self, versions, ignite_version):
"""
Basic upgrade test.
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def test(self, ignite_version, load_type):

config = IgniteConfiguration(version=IgniteVersion(ignite_version), caches=caches, cluster_state="INACTIVE")

num_nodes = len(self.test_context.cluster) - 2
num_nodes = self.available_cluster_size - 2

self.test_context.logger.info("Nodes amount calculated as %d." % num_nodes)

Expand Down
2 changes: 1 addition & 1 deletion modules/ducktests/tests/ignitetest/tests/rebalance/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def start_ignite(test_context, ignite_version: str, rebalance_params: RebalanceP
:param rebalance_params: Rebalance parameters.
:return: IgniteService.
"""
node_count = len(test_context.cluster) - rebalance_params.preloaders
node_count = test_context.available_cluster_size - rebalance_params.preloaders

if rebalance_params.persistent:
data_storage = DataStorageConfiguration(
Expand Down
5 changes: 2 additions & 3 deletions modules/ducktests/tests/ignitetest/tests/snapshot_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
Module contains snapshot test.
"""

from ducktape.mark.resource import cluster

from ignitetest.services.ignite import IgniteService
from ignitetest.services.ignite_app import IgniteApplicationService
from ignitetest.services.utils.control_utility import ControlUtility
Expand All @@ -28,6 +26,7 @@
from ignitetest.utils import ignite_versions
from ignitetest.utils.ignite_test import IgniteTest
from ignitetest.utils.version import IgniteVersion, LATEST, DEV_BRANCH
from ignitetest.utils import cluster


class SnapshotTest(IgniteTest):
Expand All @@ -52,7 +51,7 @@ def snapshot_test(self, ignite_version):
metric_exporter='org.apache.ignite.spi.metric.jmx.JmxMetricExporterSpi'
)

nodes = IgniteService(self.test_context, ignite_config, num_nodes=len(self.test_context.cluster) - 1)
nodes = IgniteService(self.test_context, ignite_config, num_nodes=self.available_cluster_size - 1)
nodes.start()

control_utility = ControlUtility(nodes)
Expand Down
15 changes: 12 additions & 3 deletions modules/ducktests/tests/ignitetest/utils/_mark.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from ducktape.mark._mark import Ignore, Mark, _inject

from ignitetest.utils.version import IgniteVersion
from ignitetest.utils.ignite_test import IgniteTestContext


class IgnoreIf(Ignore):
Expand Down Expand Up @@ -161,7 +162,7 @@ def apply(self, seed_context, context_list):
if not ctx.cluster_use_metadata:
ctx.cluster_use_metadata = self.metadata

return context_list
return list(map(lambda _ctx: IgniteTestContext.resolve(_ctx), context_list))

@staticmethod
def _extract_cluster_size(seed_context):
Expand Down Expand Up @@ -227,7 +228,15 @@ def cluster(**kwargs):
- ``cluster_spec`` provide hint about how many nodes of each type the test will consume
"""
def cluster_use_metadata_adder(func):
Mark.mark(func, ParametrizableClusterMetadata(**kwargs))
return func
def extended_test(self, *args, **kwargs):
self.test_context.before()
test_result = func(self, *args, **kwargs)
return self.test_context.after(test_result)

extended_test.__dict__.update(**func.__dict__)
extended_test.__name__ = func.__name__

Mark.mark(extended_test, ParametrizableClusterMetadata(**kwargs))
return extended_test

return cluster_use_metadata_adder
38 changes: 37 additions & 1 deletion modules/ducktests/tests/ignitetest/utils/ignite_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,60 @@
"""
This module contains basic ignite test.
"""
import importlib
from time import monotonic

from ducktape.cluster.remoteaccount import RemoteCommandError
from ducktape.tests.test import Test
from ducktape.tests.test import Test, TestContext

from ignitetest.services.utils.ducktests_service import DucktestsService

# globals:
JFR_ENABLED = "jfr_enabled"
IGNITE_TEST_CONTEXT_CLASS_KEY_NAME = "IgniteTestContext"


class IgniteTestContext(TestContext):
def __init__(self, test_context):
super().__init__()
self.__dict__.update(**test_context.__dict__)

@property
def available_cluster_size(self):
return len(self.cluster)

def before(self):
pass

def after(self, test_result):
return test_result

@staticmethod
def resolve(test_context):
if IGNITE_TEST_CONTEXT_CLASS_KEY_NAME in test_context.globals:
fqdn = test_context.globals[IGNITE_TEST_CONTEXT_CLASS_KEY_NAME]
(module, clazz) = fqdn.rsplit('.', 1)
module = importlib.import_module(module)
return getattr(module, clazz)(test_context)
else:
return IgniteTestContext(test_context)


class IgniteTest(Test):
"""
Basic ignite test.
"""
def __init__(self, test_context):
assert isinstance(test_context, IgniteTestContext),\
"any IgniteTest MUST BE decorated with the @ignitetest.utils.cluster decorator"

super().__init__(test_context=test_context)

@property
def available_cluster_size(self):
# noinspection PyUnresolvedReferences
return self.test_context.available_cluster_size

@staticmethod
def monotonic():
"""
Expand Down

0 comments on commit 8fa8d92

Please sign in to comment.