You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by iv...@apache.org on 2022/03/16 14:02:05 UTC

[ignite] branch master updated: IGNITE-16569 [ducktests] Add ability to customize the test context (#9890)

This is an automated email from the ASF dual-hosted git repository.

ivandasch pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 8fa8d92  IGNITE-16569 [ducktests] Add ability to customize the test context (#9890)
8fa8d92 is described below

commit 8fa8d92e6f6778fd61b828f4c2a19ad2b8f0d926
Author: Sergey Korotkov <se...@gmail.com>
AuthorDate: Wed Mar 16 21:00:14 2022 +0700

    IGNITE-16569 [ducktests] Add ability to customize the test context (#9890)
---
 .gitignore                                         |  2 +
 modules/ducktests/tests/docker/run_tests.sh        |  2 +-
 .../utils/ignite_configuration/__init__.py         |  2 +-
 .../utils/ignite_configuration/event_type.py       | 44 ++++++++++++++++++++++
 .../utils/ssl/client_connector_configuration.py    | 10 +++--
 .../services/utils/templates/ignite.xml.j2         | 16 +++++++-
 .../services/utils/templates/misc_macro.j2         | 10 +++++
 .../tests/ignitetest/services/zk/zookeeper.py      |  9 +++++
 .../ignitetest/tests/cellular_affinity_test.py     |  2 +-
 .../tests/control_utility/consistency_test.py      | 11 ++----
 .../tests/ignitetest/tests/discovery_test.py       |  2 +-
 .../ignitetest/tests/persistence_upgrade_test.py   |  7 +++-
 .../tests/ignitetest/tests/pme_free_switch_test.py |  2 +-
 .../tests/ignitetest/tests/rebalance/util.py       |  2 +-
 .../tests/ignitetest/tests/snapshot_test.py        |  5 +--
 modules/ducktests/tests/ignitetest/utils/_mark.py  | 15 ++++++--
 .../tests/ignitetest/utils/ignite_test.py          | 38 ++++++++++++++++++-
 17 files changed, 150 insertions(+), 29 deletions(-)

diff --git a/.gitignore b/.gitignore
index 6315a9b..36a547e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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/**
diff --git a/modules/ducktests/tests/docker/run_tests.sh b/modules/ducktests/tests/docker/run_tests.sh
index 6fb10b1..7db1dcf 100755
--- a/modules/ducktests/tests/docker/run_tests.sh
+++ b/modules/ducktests/tests/docker/run_tests.sh
@@ -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"
diff --git a/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/__init__.py b/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/__init__.py
index 82ceca0..d3caf00 100644
--- a/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/__init__.py
+++ b/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/__init__.py
@@ -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
 
diff --git a/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/event_type.py b/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/event_type.py
new file mode 100644
index 0000000..307a6ad
--- /dev/null
+++ b/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/event_type.py
@@ -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__()
diff --git a/modules/ducktests/tests/ignitetest/services/utils/ssl/client_connector_configuration.py b/modules/ducktests/tests/ignitetest/services/utils/ssl/client_connector_configuration.py
index 5757fdf..80512ff 100644
--- a/modules/ducktests/tests/ignitetest/services/utils/ssl/client_connector_configuration.py
+++ b/modules/ducktests/tests/ignitetest/services/utils/ssl/client_connector_configuration.py
@@ -22,6 +22,11 @@ from typing import NamedTuple
 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.
@@ -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
diff --git a/modules/ducktests/tests/ignitetest/services/utils/templates/ignite.xml.j2 b/modules/ducktests/tests/ignitetest/services/utils/templates/ignite.xml.j2
index fb7c204..fd04894 100644
--- a/modules/ducktests/tests/ignitetest/services/utils/templates/ignite.xml.j2
+++ b/modules/ducktests/tests/ignitetest/services/utils/templates/ignite.xml.j2
@@ -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 %}
@@ -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 %}
@@ -132,4 +140,8 @@
     </bean>
 
     {{ misc_utils.ext_beans(config) }}
+
+    {% if config.include_event_types | length > 0 %}
+        {{ misc_utils.event_types(config) }}
+    {% endif %}
 </beans>
diff --git a/modules/ducktests/tests/ignitetest/services/utils/templates/misc_macro.j2 b/modules/ducktests/tests/ignitetest/services/utils/templates/misc_macro.j2
index f34f211..809dc64 100644
--- a/modules/ducktests/tests/ignitetest/services/utils/templates/misc_macro.j2
+++ b/modules/ducktests/tests/ignitetest/services/utils/templates/misc_macro.j2
@@ -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 %}
diff --git a/modules/ducktests/tests/ignitetest/services/zk/zookeeper.py b/modules/ducktests/tests/ignitetest/services/zk/zookeeper.py
index 6758994..fc6e03c 100644
--- a/modules/ducktests/tests/ignitetest/services/zk/zookeeper.py
+++ b/modules/ducktests/tests/ignitetest/services/zk/zookeeper.py
@@ -79,7 +79,16 @@ class ZookeeperService(DucktestsService, PathAware):
         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:
diff --git a/modules/ducktests/tests/ignitetest/tests/cellular_affinity_test.py b/modules/ducktests/tests/ignitetest/tests/cellular_affinity_test.py
index eafc6f5..e6e2bed 100644
--- a/modules/ducktests/tests/ignitetest/tests/cellular_affinity_test.py
+++ b/modules/ducktests/tests/ignitetest/tests/cellular_affinity_test.py
@@ -150,7 +150,7 @@ class CellularAffinity(IgniteTest):
         """
         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))
 
diff --git a/modules/ducktests/tests/ignitetest/tests/control_utility/consistency_test.py b/modules/ducktests/tests/ignitetest/tests/control_utility/consistency_test.py
index 72e17e1..b18ce7e 100644
--- a/modules/ducktests/tests/ignitetest/tests/control_utility/consistency_test.py
+++ b/modules/ducktests/tests/ignitetest/tests/control_utility/consistency_test.py
@@ -32,6 +32,7 @@ from ignitetest.services.ignite_app import IgniteApplicationService
 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
@@ -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):
@@ -62,7 +57,7 @@ class ConsistencyTest(IgniteTest):
             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",
@@ -73,7 +68,7 @@ class ConsistencyTest(IgniteTest):
                 "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)
diff --git a/modules/ducktests/tests/ignitetest/tests/discovery_test.py b/modules/ducktests/tests/ignitetest/tests/discovery_test.py
index 52f8028..80872c1 100644
--- a/modules/ducktests/tests/ignitetest/tests/discovery_test.py
+++ b/modules/ducktests/tests/ignitetest/tests/discovery_test.py
@@ -175,7 +175,7 @@ class DiscoveryTest(IgniteTest):
     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 + (
diff --git a/modules/ducktests/tests/ignitetest/tests/persistence_upgrade_test.py b/modules/ducktests/tests/ignitetest/tests/persistence_upgrade_test.py
index ff6d1cd..91d35c1 100644
--- a/modules/ducktests/tests/ignitetest/tests/persistence_upgrade_test.py
+++ b/modules/ducktests/tests/ignitetest/tests/persistence_upgrade_test.py
@@ -22,7 +22,8 @@ from ignitetest.services.ignite_app import IgniteApplicationService
 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
 
@@ -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.
         """
diff --git a/modules/ducktests/tests/ignitetest/tests/pme_free_switch_test.py b/modules/ducktests/tests/ignitetest/tests/pme_free_switch_test.py
index 23c78c3..a2cd141 100644
--- a/modules/ducktests/tests/ignitetest/tests/pme_free_switch_test.py
+++ b/modules/ducktests/tests/ignitetest/tests/pme_free_switch_test.py
@@ -75,7 +75,7 @@ class PmeFreeSwitchTest(IgniteTest):
 
         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)
 
diff --git a/modules/ducktests/tests/ignitetest/tests/rebalance/util.py b/modules/ducktests/tests/ignitetest/tests/rebalance/util.py
index adf2635..03f7eee 100644
--- a/modules/ducktests/tests/ignitetest/tests/rebalance/util.py
+++ b/modules/ducktests/tests/ignitetest/tests/rebalance/util.py
@@ -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(
diff --git a/modules/ducktests/tests/ignitetest/tests/snapshot_test.py b/modules/ducktests/tests/ignitetest/tests/snapshot_test.py
index 8e1e9d9..711d2c7 100644
--- a/modules/ducktests/tests/ignitetest/tests/snapshot_test.py
+++ b/modules/ducktests/tests/ignitetest/tests/snapshot_test.py
@@ -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
@@ -28,6 +26,7 @@ from ignitetest.services.utils.ignite_configuration.discovery import from_ignite
 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):
@@ -52,7 +51,7 @@ class SnapshotTest(IgniteTest):
             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)
diff --git a/modules/ducktests/tests/ignitetest/utils/_mark.py b/modules/ducktests/tests/ignitetest/utils/_mark.py
index 28998be..9d0a06d 100644
--- a/modules/ducktests/tests/ignitetest/utils/_mark.py
+++ b/modules/ducktests/tests/ignitetest/utils/_mark.py
@@ -24,6 +24,7 @@ from ducktape.cluster.cluster_spec import ClusterSpec
 from ducktape.mark._mark import Ignore, Mark, _inject
 
 from ignitetest.utils.version import IgniteVersion
+from ignitetest.utils.ignite_test import IgniteTestContext
 
 
 class IgnoreIf(Ignore):
@@ -161,7 +162,7 @@ class ParametrizableClusterMetadata(Mark):
             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):
@@ -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
diff --git a/modules/ducktests/tests/ignitetest/utils/ignite_test.py b/modules/ducktests/tests/ignitetest/utils/ignite_test.py
index b2b38cb..5eb7dd6 100644
--- a/modules/ducktests/tests/ignitetest/utils/ignite_test.py
+++ b/modules/ducktests/tests/ignitetest/utils/ignite_test.py
@@ -16,15 +16,43 @@
 """
 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):
@@ -32,8 +60,16 @@ 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():
         """