diff --git a/pytest_tests/testsuites/acl/conftest.py b/pytest_tests/testsuites/acl/conftest.py index 84e17016..bbacd543 100644 --- a/pytest_tests/testsuites/acl/conftest.py +++ b/pytest_tests/testsuites/acl/conftest.py @@ -12,9 +12,7 @@ from frostfs_testlib.steps.cli.object import put_object_to_random_node from frostfs_testlib.storage.cluster import Cluster from frostfs_testlib.storage.dataclasses.acl import EACLRole from frostfs_testlib.storage.dataclasses.frostfs_services import InnerRing, StorageNode -from frostfs_testlib.storage.dataclasses.object_size import ObjectSize from frostfs_testlib.storage.dataclasses.wallet import WalletInfo -from frostfs_testlib.utils.file_utils import generate_file OBJECT_COUNT = 5 @@ -60,11 +58,6 @@ def wallets(default_wallet: WalletInfo, credentials_provider: CredentialsProvide return wallets_collection -@pytest.fixture() -def file_path(object_size: ObjectSize) -> str: - yield generate_file(object_size.value) - - @pytest.fixture(scope="function") def eacl_container_with_objects( wallets: Wallets, client_shell: Shell, cluster: Cluster, file_path: str diff --git a/pytest_tests/testsuites/conftest.py b/pytest_tests/testsuites/conftest.py index b3390b8d..7d05e962 100644 --- a/pytest_tests/testsuites/conftest.py +++ b/pytest_tests/testsuites/conftest.py @@ -37,6 +37,7 @@ from frostfs_testlib.testing.cluster_test_base import ClusterTestBase from frostfs_testlib.testing.parallel import parallel from frostfs_testlib.testing.test_control import wait_for_success from frostfs_testlib.utils import env_utils, version_utils +from frostfs_testlib.utils.file_utils import generate_file from pytest_tests.resources.common import HOSTING_CONFIG_FILE, TEST_CYCLES_COUNT @@ -190,6 +191,11 @@ def simple_object_size(max_object_size: int) -> ObjectSize: return ObjectSize("simple", size) +@pytest.fixture() +def file_path(object_size: ObjectSize) -> str: + yield generate_file(object_size.value) + + @pytest.fixture(scope="session") def complex_object_size(max_object_size: int) -> ObjectSize: size = max_object_size * int(COMPLEX_OBJECT_CHUNKS_COUNT) + int(COMPLEX_OBJECT_TAIL_SIZE) diff --git a/pytest_tests/testsuites/object/test_object_api.py b/pytest_tests/testsuites/object/test_object_api.py index 4fed2b92..1a82f401 100755 --- a/pytest_tests/testsuites/object/test_object_api.py +++ b/pytest_tests/testsuites/object/test_object_api.py @@ -14,19 +14,20 @@ from frostfs_testlib.resources.error_patterns import ( OUT_OF_RANGE, ) from frostfs_testlib.shell import Shell -from frostfs_testlib.steps.cli.container import create_container +from frostfs_testlib.steps.cli.container import create_container, search_nodes_with_container from frostfs_testlib.steps.cli.object import ( get_object_from_random_node, get_range, get_range_hash, head_object, + put_object, put_object_to_random_node, search_object, ) from frostfs_testlib.steps.complex_object_actions import get_complex_object_split_ranges from frostfs_testlib.steps.storage_object import delete_object, delete_objects from frostfs_testlib.steps.storage_policy import get_complex_object_copies, get_simple_object_copies -from frostfs_testlib.storage.cluster import Cluster +from frostfs_testlib.storage.cluster import Cluster, ClusterNode from frostfs_testlib.storage.dataclasses.object_size import ObjectSize from frostfs_testlib.storage.dataclasses.policy import PlacementPolicy from frostfs_testlib.storage.dataclasses.storage_object_info import StorageObjectInfo @@ -90,6 +91,29 @@ def generate_ranges( return file_ranges_to_test +@pytest.fixture(scope="module") +def common_container(default_wallet: WalletInfo, client_shell: Shell, cluster: Cluster) -> str: + rule = "REP 1 IN X CBF 1 SELECT 1 FROM * AS X" + with reporter.step(f"Create container with {rule} and put object"): + cid = create_container(default_wallet, client_shell, cluster.default_rpc_endpoint, rule) + + return cid + + +@pytest.fixture(scope="module") +def container_nodes( + default_wallet: WalletInfo, client_shell: Shell, cluster: Cluster, common_container: str +) -> list[ClusterNode]: + return search_nodes_with_container( + default_wallet, common_container, client_shell, cluster.default_rpc_endpoint, cluster + ) + + +@pytest.fixture(scope="module") +def non_container_nodes(cluster: Cluster, container_nodes: list[ClusterNode]) -> list[ClusterNode]: + return list(set(cluster.cluster_nodes) - set(container_nodes)) + + @pytest.fixture( # Scope session to upload/delete each files set only once scope="module" @@ -494,6 +518,80 @@ class TestObjectApi(ClusterTestBase): range_cut=range_cut, ) + @allure.title("Get range from container and non-container nodes (object_size={object_size})") + def test_get_range_from_different_node( + self, + default_wallet: str, + common_container: str, + container_nodes: list[ClusterNode], + non_container_nodes: list[ClusterNode], + file_path: str, + ): + + with reporter.step("Put object to container"): + container_node = random.choice(container_nodes) + oid = put_object( + default_wallet, file_path, common_container, self.shell, container_node.storage_node.get_rpc_endpoint() + ) + + with reporter.step("Get range from container node endpoint"): + get_range( + default_wallet, + common_container, + oid, + "0:10", + self.shell, + container_node.storage_node.get_rpc_endpoint(), + ) + + with reporter.step("Get range from non-container node endpoint"): + non_container_node = random.choice(non_container_nodes) + get_range( + default_wallet, + common_container, + oid, + "0:10", + self.shell, + non_container_node.storage_node.get_rpc_endpoint(), + ) + + @allure.title("Get range hash from container and non-container nodes (object_size={object_size})") + def test_get_range_hash_from_different_node( + self, + default_wallet: str, + common_container: str, + container_nodes: list[ClusterNode], + non_container_nodes: list[ClusterNode], + file_path: str, + ): + + with reporter.step("Put object to container"): + container_node = random.choice(container_nodes) + oid = put_object( + default_wallet, file_path, common_container, self.shell, container_node.storage_node.get_rpc_endpoint() + ) + + with reporter.step("Get range hash from container node endpoint"): + get_range_hash( + default_wallet, + common_container, + oid, + "0:10", + self.shell, + container_node.storage_node.get_rpc_endpoint(), + ) + + with reporter.step("Get range hash from non-container node endpoint"): + non_container_node = random.choice(non_container_nodes) + get_range_hash( + default_wallet, + common_container, + oid, + "0:10", + self.shell, + non_container_node.storage_node.get_rpc_endpoint(), + ) + def check_header_is_presented(self, head_info: dict, object_header: dict) -> None: for key_to_check, val_to_check in object_header.items(): assert key_to_check in head_info["header"]["attributes"], f"Key {key_to_check} is found in {head_object}"