64 lines
3 KiB
Python
64 lines
3 KiB
Python
|
import allure
|
||
|
import pytest
|
||
|
from frostfs_testlib import reporter
|
||
|
from frostfs_testlib.resources.common import EXPIRATION_EPOCH_ATTRIBUTE
|
||
|
from frostfs_testlib.resources.error_patterns import OBJECT_NOT_FOUND
|
||
|
from frostfs_testlib.storage.controllers.cluster_state_controller import ClusterStateController
|
||
|
from frostfs_testlib.storage.controllers.state_managers.config_state_manager import ConfigStateManager
|
||
|
from frostfs_testlib.storage.dataclasses.frostfs_services import StorageNode
|
||
|
from frostfs_testlib.storage.grpc_operations.interfaces import GrpcClientWrapper
|
||
|
from frostfs_testlib.testing.cluster_test_base import ClusterTestBase
|
||
|
from frostfs_testlib.utils.file_utils import TestFile
|
||
|
|
||
|
from ....pytest_tests.helpers.container_spec import APE_PUBLIC_READ_WRITE, ContainerSpec
|
||
|
|
||
|
|
||
|
class TestObjectTombstone(ClusterTestBase):
|
||
|
@pytest.fixture()
|
||
|
@allure.title("Change tombstone lifetime")
|
||
|
def tombstone_lifetime(self, cluster_state_controller: ClusterStateController, request: pytest.FixtureRequest):
|
||
|
config_manager = cluster_state_controller.manager(ConfigStateManager)
|
||
|
config_manager.set_on_all_nodes(StorageNode, {"object:delete:tombstone_lifetime": request.param}, True)
|
||
|
|
||
|
yield f"Tombstone lifetime was changed to {request.param}"
|
||
|
|
||
|
config_manager.revert_all(True)
|
||
|
|
||
|
@pytest.mark.container(ContainerSpec(ape_rules=APE_PUBLIC_READ_WRITE))
|
||
|
@pytest.mark.parametrize("object_size, tombstone_lifetime", [("simple", 2)], indirect=True)
|
||
|
@allure.title("Tombstone object should be removed after expiration")
|
||
|
def test_tombstone_lifetime(
|
||
|
self,
|
||
|
new_epoch: int,
|
||
|
container: str,
|
||
|
grpc_client: GrpcClientWrapper,
|
||
|
test_file: TestFile,
|
||
|
rpc_endpoint: str,
|
||
|
tombstone_lifetime: str,
|
||
|
):
|
||
|
allure.dynamic.description(tombstone_lifetime)
|
||
|
|
||
|
with reporter.step("Put object"):
|
||
|
oid = grpc_client.object.put(test_file.path, container, rpc_endpoint)
|
||
|
|
||
|
with reporter.step("Remove object"):
|
||
|
tombstone_oid = grpc_client.object.delete(container, oid, rpc_endpoint)
|
||
|
|
||
|
with reporter.step("Get tombstone object lifetime"):
|
||
|
tombstone_info = grpc_client.object.head(container, tombstone_oid, rpc_endpoint)
|
||
|
tombstone_expiration_epoch = tombstone_info["header"]["attributes"][EXPIRATION_EPOCH_ATTRIBUTE]
|
||
|
|
||
|
with reporter.step("Tombstone lifetime should be <= 3"):
|
||
|
epochs_to_skip = int(tombstone_expiration_epoch) - new_epoch + 1
|
||
|
assert epochs_to_skip <= 3
|
||
|
|
||
|
with reporter.step("Wait for tombstone expiration"):
|
||
|
self.tick_epochs(epochs_to_skip)
|
||
|
|
||
|
with reporter.step("Tombstone should be removed after expiration"):
|
||
|
with pytest.raises(RuntimeError, match=OBJECT_NOT_FOUND):
|
||
|
grpc_client.object.head(container, tombstone_oid, rpc_endpoint)
|
||
|
|
||
|
with pytest.raises(RuntimeError, match=OBJECT_NOT_FOUND):
|
||
|
grpc_client.object.get(container, tombstone_oid, rpc_endpoint)
|