forked from TrueCloudLab/frostfs-testcases
[#205] Add EC policy to sanity testsuite
Signed-off-by: Evgenii Stratonikov <stratonikov@runbox.com>
This commit is contained in:
parent
2d042e2387
commit
9d664290f7
2 changed files with 36 additions and 10 deletions
|
@ -23,6 +23,7 @@ from frostfs_testlib.resources.common import (
|
||||||
)
|
)
|
||||||
from frostfs_testlib.s3 import AwsCliClient, Boto3ClientWrapper, S3ClientWrapper, VersioningStatus
|
from frostfs_testlib.s3 import AwsCliClient, Boto3ClientWrapper, S3ClientWrapper, VersioningStatus
|
||||||
from frostfs_testlib.shell import LocalShell, Shell
|
from frostfs_testlib.shell import LocalShell, Shell
|
||||||
|
from frostfs_testlib.steps.cli.container import DEFAULT_PLACEMENT_RULE, DEFAULT_EC_PLACEMENT_RULE
|
||||||
from frostfs_testlib.steps.cli.object import get_netmap_netinfo
|
from frostfs_testlib.steps.cli.object import get_netmap_netinfo
|
||||||
from frostfs_testlib.steps.s3 import s3_helper
|
from frostfs_testlib.steps.s3 import s3_helper
|
||||||
from frostfs_testlib.storage import get_service_registry
|
from frostfs_testlib.storage import get_service_registry
|
||||||
|
@ -30,6 +31,7 @@ from frostfs_testlib.storage.cluster import Cluster, ClusterNode
|
||||||
from frostfs_testlib.storage.controllers.cluster_state_controller import ClusterStateController
|
from frostfs_testlib.storage.controllers.cluster_state_controller import ClusterStateController
|
||||||
from frostfs_testlib.storage.dataclasses.frostfs_services import StorageNode
|
from frostfs_testlib.storage.dataclasses.frostfs_services import StorageNode
|
||||||
from frostfs_testlib.storage.dataclasses.object_size import ObjectSize
|
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
|
from frostfs_testlib.storage.dataclasses.wallet import WalletInfo
|
||||||
from frostfs_testlib.testing.cluster_test_base import ClusterTestBase
|
from frostfs_testlib.testing.cluster_test_base import ClusterTestBase
|
||||||
from frostfs_testlib.testing.parallel import parallel
|
from frostfs_testlib.testing.parallel import parallel
|
||||||
|
@ -208,6 +210,29 @@ def object_size(
|
||||||
|
|
||||||
return complex_object_size
|
return complex_object_size
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session")
|
||||||
|
def rep_placement_policy() -> PlacementPolicy:
|
||||||
|
return PlacementPolicy("rep", DEFAULT_PLACEMENT_RULE)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session")
|
||||||
|
def ec_placement_policy() -> PlacementPolicy:
|
||||||
|
return PlacementPolicy("ec", DEFAULT_EC_PLACEMENT_RULE)
|
||||||
|
|
||||||
|
|
||||||
|
# By default we want all tests to be executed with both storage policies.
|
||||||
|
# This can be overriden in choosen tests if needed.
|
||||||
|
@pytest.fixture(
|
||||||
|
scope="session",
|
||||||
|
params=[pytest.param("rep", marks=pytest.mark.rep), pytest.param("ec", marks=pytest.mark.ec)],
|
||||||
|
)
|
||||||
|
def placement_policy(
|
||||||
|
rep_placement_policy: PlacementPolicy, ec_placement_policy: PlacementPolicy, request: pytest.FixtureRequest
|
||||||
|
) -> PlacementPolicy:
|
||||||
|
if request.param == "rep":
|
||||||
|
return rep_placement_policy
|
||||||
|
|
||||||
|
return ec_placement_policy
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def cluster(temp_directory: str, hosting: Hosting, client_shell: Shell) -> Cluster:
|
def cluster(temp_directory: str, hosting: Hosting, client_shell: Shell) -> Cluster:
|
||||||
|
|
|
@ -27,6 +27,7 @@ from frostfs_testlib.steps.storage_object import delete_objects
|
||||||
from frostfs_testlib.steps.storage_policy import get_complex_object_copies, get_simple_object_copies
|
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
|
||||||
from frostfs_testlib.storage.dataclasses.object_size import ObjectSize
|
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
|
from frostfs_testlib.storage.dataclasses.storage_object_info import StorageObjectInfo
|
||||||
from frostfs_testlib.storage.dataclasses.wallet import WalletInfo
|
from frostfs_testlib.storage.dataclasses.wallet import WalletInfo
|
||||||
from frostfs_testlib.testing.cluster_test_base import ClusterTestBase
|
from frostfs_testlib.testing.cluster_test_base import ClusterTestBase
|
||||||
|
@ -93,11 +94,11 @@ def generate_ranges(
|
||||||
scope="module"
|
scope="module"
|
||||||
)
|
)
|
||||||
def storage_objects(
|
def storage_objects(
|
||||||
default_wallet: WalletInfo, client_shell: Shell, cluster: Cluster, object_size: ObjectSize
|
default_wallet: WalletInfo, client_shell: Shell, cluster: Cluster, object_size: ObjectSize, placement_policy: PlacementPolicy
|
||||||
) -> list[StorageObjectInfo]:
|
) -> list[StorageObjectInfo]:
|
||||||
wallet = default_wallet
|
wallet = default_wallet
|
||||||
# Separate containers for complex/simple objects to avoid side-effects
|
# Separate containers for complex/simple objects to avoid side-effects
|
||||||
cid = create_container(wallet, shell=client_shell, endpoint=cluster.default_rpc_endpoint)
|
cid = create_container(wallet, shell=client_shell, rule=placement_policy.value, endpoint=cluster.default_rpc_endpoint)
|
||||||
|
|
||||||
file_path = generate_file(object_size.value)
|
file_path = generate_file(object_size.value)
|
||||||
file_hash = get_file_hash(file_path)
|
file_hash = get_file_hash(file_path)
|
||||||
|
@ -134,7 +135,7 @@ def storage_objects(
|
||||||
@pytest.mark.sanity
|
@pytest.mark.sanity
|
||||||
@pytest.mark.grpc_api
|
@pytest.mark.grpc_api
|
||||||
class TestObjectApi(ClusterTestBase):
|
class TestObjectApi(ClusterTestBase):
|
||||||
@allure.title("Storage policy by native API (obj_size={object_size})")
|
@allure.title("Storage policy by native API (obj_size={object_size}, policy={placement_policy})")
|
||||||
def test_object_storage_policies(
|
def test_object_storage_policies(
|
||||||
self,
|
self,
|
||||||
storage_objects: list[StorageObjectInfo],
|
storage_objects: list[StorageObjectInfo],
|
||||||
|
@ -164,7 +165,7 @@ class TestObjectApi(ClusterTestBase):
|
||||||
)
|
)
|
||||||
assert copies == 2, "Expected 2 copies"
|
assert copies == 2, "Expected 2 copies"
|
||||||
|
|
||||||
@allure.title("Get object by native API (obj_size={object_size})")
|
@allure.title("Get object by native API (obj_size={object_size}, policy={placement_policy})")
|
||||||
def test_get_object_api(self, storage_objects: list[StorageObjectInfo]):
|
def test_get_object_api(self, storage_objects: list[StorageObjectInfo]):
|
||||||
"""
|
"""
|
||||||
Validate get object native API
|
Validate get object native API
|
||||||
|
@ -182,7 +183,7 @@ class TestObjectApi(ClusterTestBase):
|
||||||
file_hash = get_file_hash(file_path)
|
file_hash = get_file_hash(file_path)
|
||||||
assert storage_object.file_hash == file_hash
|
assert storage_object.file_hash == file_hash
|
||||||
|
|
||||||
@allure.title("Head object by native API (obj_size={object_size})")
|
@allure.title("Head object by native API (obj_size={object_size}, policy={placement_policy})")
|
||||||
def test_head_object_api(self, storage_objects: list[StorageObjectInfo]):
|
def test_head_object_api(self, storage_objects: list[StorageObjectInfo]):
|
||||||
"""
|
"""
|
||||||
Validate head object native API
|
Validate head object native API
|
||||||
|
@ -208,7 +209,7 @@ class TestObjectApi(ClusterTestBase):
|
||||||
)
|
)
|
||||||
self.check_header_is_presented(head_info, storage_object_2.attributes)
|
self.check_header_is_presented(head_info, storage_object_2.attributes)
|
||||||
|
|
||||||
@allure.title("Search objects by native API (obj_size={object_size})")
|
@allure.title("Search objects by native API (obj_size={object_size}, policy={placement_policy})")
|
||||||
def test_search_object_api(self, storage_objects: list[StorageObjectInfo]):
|
def test_search_object_api(self, storage_objects: list[StorageObjectInfo]):
|
||||||
"""
|
"""
|
||||||
Validate object search by native API
|
Validate object search by native API
|
||||||
|
@ -302,7 +303,7 @@ class TestObjectApi(ClusterTestBase):
|
||||||
object_type == "TOMBSTONE"
|
object_type == "TOMBSTONE"
|
||||||
), f"Object wasn't deleted properly. Found object {tombstone_oid} with type {object_type}"
|
), f"Object wasn't deleted properly. Found object {tombstone_oid} with type {object_type}"
|
||||||
|
|
||||||
@allure.title("Get range hash by native API (obj_size={object_size})")
|
@allure.title("Get range hash by native API (obj_size={object_size}, policy={placement_policy})")
|
||||||
@pytest.mark.grpc_api
|
@pytest.mark.grpc_api
|
||||||
def test_object_get_range_hash(self, storage_objects: list[StorageObjectInfo], max_object_size):
|
def test_object_get_range_hash(self, storage_objects: list[StorageObjectInfo], max_object_size):
|
||||||
"""
|
"""
|
||||||
|
@ -333,7 +334,7 @@ class TestObjectApi(ClusterTestBase):
|
||||||
get_file_hash(file_path, range_len, range_start) == range_hash
|
get_file_hash(file_path, range_len, range_start) == range_hash
|
||||||
), f"Expected range hash to match {range_cut} slice of file payload"
|
), f"Expected range hash to match {range_cut} slice of file payload"
|
||||||
|
|
||||||
@allure.title("Get range by native API (obj_size={object_size})")
|
@allure.title("Get range by native API (obj_size={object_size}, policy={placement_policy})")
|
||||||
@pytest.mark.grpc_api
|
@pytest.mark.grpc_api
|
||||||
def test_object_get_range(self, storage_objects: list[StorageObjectInfo], max_object_size):
|
def test_object_get_range(self, storage_objects: list[StorageObjectInfo], max_object_size):
|
||||||
"""
|
"""
|
||||||
|
@ -365,7 +366,7 @@ class TestObjectApi(ClusterTestBase):
|
||||||
== range_content
|
== range_content
|
||||||
), f"Expected range content to match {range_cut} slice of file payload"
|
), f"Expected range content to match {range_cut} slice of file payload"
|
||||||
|
|
||||||
@allure.title("[NEGATIVE] Get invalid range by native API (obj_size={object_size})")
|
@allure.title("[NEGATIVE] Get invalid range by native API (obj_size={object_size}, policy={placement_policy})")
|
||||||
@pytest.mark.grpc_api
|
@pytest.mark.grpc_api
|
||||||
def test_object_get_range_negatives(
|
def test_object_get_range_negatives(
|
||||||
self,
|
self,
|
||||||
|
@ -413,7 +414,7 @@ class TestObjectApi(ClusterTestBase):
|
||||||
range_cut=range_cut,
|
range_cut=range_cut,
|
||||||
)
|
)
|
||||||
|
|
||||||
@allure.title("[NEGATIVE] Get invalid range hash by native API (obj_size={object_size})")
|
@allure.title("[NEGATIVE] Get invalid range hash by native API (obj_size={object_size}, policy={placement_policy})")
|
||||||
def test_object_get_range_hash_negatives(
|
def test_object_get_range_hash_negatives(
|
||||||
self,
|
self,
|
||||||
storage_objects: list[StorageObjectInfo],
|
storage_objects: list[StorageObjectInfo],
|
||||||
|
|
Loading…
Reference in a new issue