From 35f60af47d73326b855b2b994a83c310ccb40915 Mon Sep 17 00:00:00 2001 From: "a.berezin" Date: Tue, 28 Jan 2025 13:05:59 +0300 Subject: [PATCH] [#363] Updates for sanity scope Signed-off-by: a.berezin --- pytest.ini | 1 + pytest_tests/testsuites/conftest.py | 48 ++++--------------- .../testsuites/container/test_container.py | 3 +- .../management/test_node_management.py | 1 - .../testsuites/object/test_object_api.py | 1 + .../replication/test_replication.py | 1 - .../services/http_gate/test_http_gate.py | 46 +----------------- .../testsuites/services/test_binaries.py | 1 + 8 files changed, 14 insertions(+), 88 deletions(-) diff --git a/pytest.ini b/pytest.ini index 11047c40..95b01716 100644 --- a/pytest.ini +++ b/pytest.ini @@ -10,6 +10,7 @@ markers = staging: test to be excluded from run in verifier/pr-validation/sanity jobs and run test in staging job sanity: test runs in sanity testrun smoke: test runs in smoke testrun + exclude_sanity: tests which should not be in sanity scope # controlling markers order: manual control of test order logs_after_session: Make the last test in session diff --git a/pytest_tests/testsuites/conftest.py b/pytest_tests/testsuites/conftest.py index a507147d..0eb75b91 100644 --- a/pytest_tests/testsuites/conftest.py +++ b/pytest_tests/testsuites/conftest.py @@ -1,11 +1,10 @@ import logging import random -from datetime import datetime, timedelta, timezone +from datetime import datetime from typing import Optional import allure import pytest -from dateutil import parser from frostfs_testlib import plugins, reporter from frostfs_testlib.cli import FrostfsCli from frostfs_testlib.clients import AwsCliClient, Boto3ClientWrapper, S3ClientWrapper, S3HttpClient @@ -22,7 +21,6 @@ from frostfs_testlib.steps.cli.object import get_netmap_netinfo from frostfs_testlib.steps.epoch import ensure_fresh_epoch from frostfs_testlib.storage.cluster import Cluster, ClusterNode from frostfs_testlib.storage.controllers.cluster_state_controller import ClusterStateController -from frostfs_testlib.storage.dataclasses.frostfs_services import StorageNode from frostfs_testlib.storage.dataclasses.object_size import ObjectSize from frostfs_testlib.storage.dataclasses.policy import PlacementPolicy from frostfs_testlib.storage.dataclasses.wallet import WalletInfo @@ -30,7 +28,7 @@ from frostfs_testlib.storage.grpc_operations.client_wrappers import CliClientWra from frostfs_testlib.storage.grpc_operations.interfaces import GrpcClientWrapper from frostfs_testlib.testing.cluster_test_base import ClusterTestBase from frostfs_testlib.testing.parallel import parallel -from frostfs_testlib.testing.test_control import cached_fixture, run_optionally, wait_for_success +from frostfs_testlib.testing.test_control import cached_fixture, run_optionally from frostfs_testlib.utils import env_utils, string_utils, version_utils from frostfs_testlib.utils.file_utils import TestFile, generate_file @@ -40,7 +38,6 @@ from ..resources.common import TEST_CYCLES_COUNT logger = logging.getLogger("NeoLogger") -SERVICE_ACTIVE_TIME = 20 WALLTETS_IN_POOL = 2 @@ -155,7 +152,11 @@ def complex_object_size(max_object_size: int) -> ObjectSize: # By default we want all tests to be executed with both object sizes # This can be overriden in choosen tests if needed @pytest.fixture( - scope="session", params=[pytest.param("simple", marks=pytest.mark.simple), pytest.param("complex", marks=pytest.mark.complex)] + scope="session", + params=[ + pytest.param("simple", marks=[pytest.mark.simple, pytest.mark.exclude_sanity]), + pytest.param("complex", marks=pytest.mark.complex), + ], ) def object_size(simple_object_size: ObjectSize, complex_object_size: ObjectSize, request: pytest.FixtureRequest) -> ObjectSize: if request.param == "simple": @@ -291,7 +292,7 @@ def credentials_provider(cluster: Cluster) -> CredentialsProvider: @pytest.fixture( scope="session", params=[ - pytest.param(AwsCliClient, marks=[pytest.mark.aws, pytest.mark.weekly]), + pytest.param(AwsCliClient, marks=[pytest.mark.aws, pytest.mark.weekly, pytest.mark.exclude_sanity]), pytest.param(Boto3ClientWrapper, marks=[pytest.mark.boto3, pytest.mark.nightly]), ], ) @@ -416,44 +417,11 @@ def session_start_time(configure_testlib): return start_time -@allure.title("[Autouse/Session] After deploy healthcheck") -@pytest.fixture(scope="session", autouse=True) -@run_optionally(optionals.OPTIONAL_AUTOUSE_FIXTURES_ENABLED) -def after_deploy_healthcheck(cluster: Cluster): - with reporter.step("Wait for cluster readiness after deploy"): - parallel(readiness_on_node, cluster.cluster_nodes) - - @pytest.fixture(scope="session") def rpc_endpoint(cluster: Cluster): return cluster.default_rpc_endpoint -@wait_for_success(60 * SERVICE_ACTIVE_TIME * 3, 60, title="Wait for {cluster_node} readiness") -def readiness_on_node(cluster_node: ClusterNode): - if "skip_readiness_check" in cluster_node.host.config.attributes and cluster_node.host.config.attributes["skip_readiness_check"]: - return - - # TODO: Move to healtcheck classes - svc_name = cluster_node.service(StorageNode).get_service_systemctl_name() - with reporter.step(f"Check service {svc_name} is active"): - result = cluster_node.host.get_shell().exec(f"systemctl is-active {svc_name}") - assert "active" == result.stdout.strip(), f"Service {svc_name} should be in active state" - - with reporter.step(f"Check service {svc_name} is active more than {SERVICE_ACTIVE_TIME} minutes"): - result = cluster_node.host.get_shell().exec(f"systemctl show {svc_name} --property ActiveEnterTimestamp | cut -d '=' -f 2") - start_time = parser.parse(result.stdout.strip()) - current_time = datetime.now(tz=timezone.utc) - active_time = current_time - start_time - - active_minutes = active_time.seconds // 60 - active_seconds = active_time.seconds - active_minutes * 60 - - assert active_time > timedelta( - minutes=SERVICE_ACTIVE_TIME - ), f"Service should be in active state more than {SERVICE_ACTIVE_TIME} minutes, current {active_minutes}m:{active_seconds}s" - - @reporter.step("Prepare default user with wallet") @pytest.fixture(scope="session") @cached_fixture(optionals.OPTIONAL_CACHE_FIXTURES) diff --git a/pytest_tests/testsuites/container/test_container.py b/pytest_tests/testsuites/container/test_container.py index 685d55b7..8137d8b3 100644 --- a/pytest_tests/testsuites/container/test_container.py +++ b/pytest_tests/testsuites/container/test_container.py @@ -59,7 +59,7 @@ class TestContainer(ClusterTestBase): self.tick_epoch() wait_for_container_deletion(wallet, cid, self.shell, rpc_endpoint) - @allure.title("Delete container without force (name={name})") + @allure.title("Delete container without force") @pytest.mark.smoke def test_container_deletion_no_force(self, container: str, default_wallet: WalletInfo, rpc_endpoint: str): with reporter.step("Delete container and check it was deleted"): @@ -68,6 +68,7 @@ class TestContainer(ClusterTestBase): wait_for_container_deletion(default_wallet, container, self.shell, rpc_endpoint) @allure.title("Parallel container creation and deletion") + @pytest.mark.exclude_sanity def test_container_creation_deletion_parallel(self, default_wallet: WalletInfo, rpc_endpoint: str): containers_count = 3 wallet = default_wallet diff --git a/pytest_tests/testsuites/management/test_node_management.py b/pytest_tests/testsuites/management/test_node_management.py index 5eae5406..e6f90ecb 100644 --- a/pytest_tests/testsuites/management/test_node_management.py +++ b/pytest_tests/testsuites/management/test_node_management.py @@ -424,7 +424,6 @@ class TestMaintenanceMode(ClusterTestBase): with pytest.raises(RuntimeError, match=node_under_maintenance_error): put_object(default_wallet, file_path, cid, self.shell, endpoint) - @pytest.mark.sanity @allure.title("MAINTENANCE and OFFLINE mode transitions") def test_mode_transitions( self, diff --git a/pytest_tests/testsuites/object/test_object_api.py b/pytest_tests/testsuites/object/test_object_api.py index cce5ba6f..b54adab3 100755 --- a/pytest_tests/testsuites/object/test_object_api.py +++ b/pytest_tests/testsuites/object/test_object_api.py @@ -314,6 +314,7 @@ class TestObjectApi(ClusterTestBase): assert sorted(expected_oids) == sorted(result) @allure.title("Search objects with removed items (obj_size={object_size})") + @pytest.mark.exclude_sanity def test_object_search_should_return_tombstone_items( self, default_wallet: WalletInfo, diff --git a/pytest_tests/testsuites/replication/test_replication.py b/pytest_tests/testsuites/replication/test_replication.py index 6547c842..726b06c2 100644 --- a/pytest_tests/testsuites/replication/test_replication.py +++ b/pytest_tests/testsuites/replication/test_replication.py @@ -22,7 +22,6 @@ OBJECT_ATTRIBUTES = {"common_key": "common_value"} WAIT_FOR_REPLICATION = 60 # Adding failover mark because it may make cluster unhealthy -@pytest.mark.sanity @pytest.mark.failover @pytest.mark.replication class TestReplication(ClusterTestBase): diff --git a/pytest_tests/testsuites/services/http_gate/test_http_gate.py b/pytest_tests/testsuites/services/http_gate/test_http_gate.py index 2afb8194..1605aae5 100644 --- a/pytest_tests/testsuites/services/http_gate/test_http_gate.py +++ b/pytest_tests/testsuites/services/http_gate/test_http_gate.py @@ -1,7 +1,6 @@ import allure import pytest from frostfs_testlib import reporter -from frostfs_testlib.steps.cli.object import put_object_to_random_node from frostfs_testlib.steps.epoch import get_epoch from frostfs_testlib.steps.http_gate import ( attr_into_header, @@ -19,55 +18,12 @@ from frostfs_testlib.storage.dataclasses.wallet import WalletInfo from frostfs_testlib.testing.cluster_test_base import ClusterTestBase from frostfs_testlib.utils.file_utils import TestFile, generate_file, get_file_hash -from ....helpers.container_request import REP_1_1_1_PUBLIC, REP_2_2_2_PUBLIC, requires_container +from ....helpers.container_request import REP_2_2_2_PUBLIC, requires_container from ....helpers.utility import wait_for_gc_pass_on_storage_nodes OBJECT_NOT_FOUND_ERROR = "not found" -@allure.link( - "https://git.frostfs.info/TrueCloudLab/frostfs-http-gw#frostfs-http-gateway", - name="frostfs-http-gateway", -) -@allure.link("https://git.frostfs.info/TrueCloudLab/frostfs-http-gw#uploading", name="uploading") -@allure.link("https://git.frostfs.info/TrueCloudLab/frostfs-http-gw#downloading", name="downloading") -@pytest.mark.nightly -@pytest.mark.sanity -@pytest.mark.http_gate -class TestHttpGate(ClusterTestBase): - @allure.title("Put over gRPC, Get over HTTP (object_size={object_size})") - @requires_container(REP_1_1_1_PUBLIC) - def test_put_grpc_get_http(self, default_wallet: WalletInfo, container: str, test_file: TestFile): - """ - Test that object can be put using gRPC interface and get using HTTP. - - Steps: - 1. Create object. - 2. Put object using gRPC (frostfs-cli). - 3. Download object using HTTP gate (https://git.frostfs.info/TrueCloudLab/frostfs-http-gw#downloading). - 4. Get object using gRPC (frostfs-cli). - 5. Compare hashes for got object. - 6. Compare hashes for got and original objects. - - Expected result: - Hashes must be the same. - """ - - with reporter.step("Put object using gRPC"): - object_id = put_object_to_random_node(default_wallet, test_file.path, container, self.shell, self.cluster) - - with reporter.step("Get object and check hash"): - verify_object_hash( - object_id, - test_file.path, - default_wallet, - container, - self.shell, - self.cluster.storage_nodes, - self.cluster.cluster_nodes[0], - ) - - @allure.link( "https://git.frostfs.info/TrueCloudLab/frostfs-http-gw#frostfs-http-gateway", name="frostfs-http-gateway", diff --git a/pytest_tests/testsuites/services/test_binaries.py b/pytest_tests/testsuites/services/test_binaries.py index db1ac947..1cf0c620 100644 --- a/pytest_tests/testsuites/services/test_binaries.py +++ b/pytest_tests/testsuites/services/test_binaries.py @@ -18,6 +18,7 @@ def _check_version_format(version): @allure.title("Check binaries versions") +@pytest.mark.nightly @pytest.mark.check_binaries def test_binaries_versions(hosting: Hosting): """