From d355eccfd862800473655be461ca0f4f74fea64e Mon Sep 17 00:00:00 2001 From: Andrey Berezin Date: Wed, 5 Apr 2023 19:02:42 +0300 Subject: [PATCH] Add deletion 1001 objects test Signed-off-by: Andrey Berezin --- pytest_tests/steps/s3_gate_base.py | 6 +- .../services/s3_gate/test_s3_object.py | 55 ++++++++++++++++++- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/pytest_tests/steps/s3_gate_base.py b/pytest_tests/steps/s3_gate_base.py index 9ab84b35..0c9deb28 100644 --- a/pytest_tests/steps/s3_gate_base.py +++ b/pytest_tests/steps/s3_gate_base.py @@ -14,13 +14,12 @@ from botocore.exceptions import ClientError from frostfs_testlib.shell import Shell from pytest import FixtureRequest -from pytest_tests.steps import s3_gate_bucket -from pytest_tests.steps import s3_gate_object from pytest_tests.helpers.aws_cli_client import AwsCliClient from pytest_tests.helpers.cli_helpers import _cmd_run, _configure_aws_cli, _run_with_passwd from pytest_tests.helpers.cluster import Cluster from pytest_tests.helpers.container import list_containers from pytest_tests.resources.common import FROSTFS_AUTHMATE_EXEC +from pytest_tests.steps import s3_gate_bucket, s3_gate_object from pytest_tests.steps.cluster_test_base import ClusterTestBase # Disable warnings on self-signed certificate which the @@ -34,6 +33,9 @@ CREDENTIALS_CREATE_TIMEOUT = "1m" # without any retries) MAX_REQUEST_ATTEMPTS = 1 RETRY_MODE = "standard" +S3_MALFORMED_XML_REQUEST = ( + "The XML you provided was not well-formed or did not validate against our published schema." +) class TestS3GateBase(ClusterTestBase): diff --git a/pytest_tests/testsuites/services/s3_gate/test_s3_object.py b/pytest_tests/testsuites/services/s3_gate/test_s3_object.py index 04c0c49d..e8463128 100644 --- a/pytest_tests/testsuites/services/s3_gate/test_s3_object.py +++ b/pytest_tests/testsuites/services/s3_gate/test_s3_object.py @@ -21,9 +21,10 @@ from pytest_tests.helpers.s3_helper import ( check_objects_in_bucket, set_bucket_versioning, ) +from pytest_tests.helpers.test_control import expect_not_raises from pytest_tests.resources.common import ASSETS_DIR, WALLET_PASS from pytest_tests.steps import s3_gate_bucket, s3_gate_object -from pytest_tests.steps.s3_gate_base import TestS3GateBase +from pytest_tests.steps.s3_gate_base import S3_MALFORMED_XML_REQUEST, TestS3GateBase def pytest_generate_tests(metafunc): @@ -39,6 +40,31 @@ class TestS3GateObject(TestS3GateBase): def object_key_from_file_path(full_path: str) -> str: return os.path.basename(full_path) + @allure.title("Set object size for current test") + @pytest.fixture + def object_size(self, request: pytest.FixtureRequest) -> int: + object_size = request.param + return object_size + + @allure.title("Put objects in a bucket") + @pytest.fixture + def objects_in_bucket( + self, bucket: str, object_size: int, request: pytest.FixtureRequest + ) -> list[str]: + objects: list[str] = [] + objects_count = int(request.param) + + with allure.step( + f"Put {objects_count} objects of size '{object_size}' bytes into bucket '{bucket}'" + ): + for _ in range(objects_count): + file_path = generate_file(object_size) + file_name = self.object_key_from_file_path(file_path) + objects.append(file_name) + s3_gate_object.put_object_s3(self.s3_client, bucket, file_path) + + return objects + @pytest.fixture def second_wallet_public_key(self): second_wallet = os.path.join(os.getcwd(), ASSETS_DIR, f"{str(uuid.uuid4())}.json") @@ -481,6 +507,33 @@ class TestS3GateObject(TestS3GateBase): con_file = concat_files([object_3_part_1, object_3_part_2, object_3_part_3]) assert get_file_hash(con_file) == get_file_hash(file_name_1), "Hashes must be the same" + def copy_extend_list(self, original_list: list[str], n: int) -> list[str]: + """Extend the list with own elements up to n elements""" + multiplier = n // len(original_list) + result_list = original_list.copy() + result_list = result_list * multiplier + for i in range(n - len(result_list)): + result_list.append(result_list[i]) + + return result_list + + @allure.title("Test S3: Bulk deletion should be limited to 1000 objects") + @pytest.mark.parametrize( + "objects_in_bucket, object_size", + [(3, 10)], + indirect=True, + ) + def test_s3_bulk_deletion_limit(self, bucket: str, objects_in_bucket: list[str]): + # Extend deletion list to 1001 elements with same keys for test speed + objects_to_delete = self.copy_extend_list(objects_in_bucket, 1001) + with allure.step("Delete 1001 objects and expect error"): + with pytest.raises(Exception, match=S3_MALFORMED_XML_REQUEST): + s3_gate_object.delete_objects_s3(self.s3_client, bucket, objects_to_delete) + + with allure.step("Delete 1000 objects without error"): + with expect_not_raises(): + s3_gate_object.delete_objects_s3(self.s3_client, bucket, objects_to_delete[:1000]) + @allure.title("Test S3: Copy object with metadata") @pytest.mark.smoke def test_s3_head_object(self, bucket, complex_object_size, simple_object_size):