2022-12-19 17:45:26 +00:00
import logging
import os
import allure
import pytest
2023-05-15 09:59:33 +00:00
from frostfs_testlib . resources . wellknown_acl import PUBLIC_ACL
from frostfs_testlib . steps . cli . container import (
2022-12-19 17:45:26 +00:00
create_container ,
delete_container ,
list_containers ,
wait_for_container_deletion ,
)
2023-05-15 09:59:33 +00:00
from frostfs_testlib . steps . cli . object import delete_object
from frostfs_testlib . steps . http . http_gate import (
2022-12-19 17:45:26 +00:00
attr_into_str_header_curl ,
get_object_by_attr_and_verify_hashes ,
try_to_get_object_and_expect_error ,
try_to_get_object_via_passed_request_and_expect_error ,
upload_via_http_gate_curl ,
)
2023-08-02 11:54:03 +00:00
from frostfs_testlib . storage . dataclasses . object_size import ObjectSize
2023-05-15 09:59:33 +00:00
from frostfs_testlib . storage . dataclasses . storage_object_info import StorageObjectInfo
from frostfs_testlib . testing . cluster_test_base import ClusterTestBase
from frostfs_testlib . utils . file_utils import generate_file
from pytest import FixtureRequest
2022-12-19 17:45:26 +00:00
OBJECT_ALREADY_REMOVED_ERROR = " object already removed "
logger = logging . getLogger ( " NeoLogger " )
@pytest.mark.sanity
@pytest.mark.http_gate
class Test_http_headers ( ClusterTestBase ) :
PLACEMENT_RULE = " REP 2 IN X CBF 1 SELECT 4 FROM * AS X "
obj1_keys = [ " Writer " , " Chapter1 " , " Chapter2 " ]
obj2_keys = [ " Writer " , " Ch@pter1 " , " chapter2 " ]
values = [ " Leo Tolstoy " , " peace " , " w@r " ]
OBJECT_ATTRIBUTES = [
{ obj1_keys [ 0 ] : values [ 0 ] , obj1_keys [ 1 ] : values [ 1 ] , obj1_keys [ 2 ] : values [ 2 ] } ,
{ obj2_keys [ 0 ] : values [ 0 ] , obj2_keys [ 1 ] : values [ 1 ] , obj2_keys [ 2 ] : values [ 2 ] } ,
]
@pytest.fixture ( scope = " class " , autouse = True )
@allure.title ( " [Class/Autouse]: Prepare wallet and deposit " )
def prepare_wallet ( self , default_wallet ) :
Test_http_headers . wallet = default_wallet
@pytest.fixture (
params = [
pytest . lazy_fixture ( " simple_object_size " ) ,
2023-06-23 14:50:18 +00:00
# TODO: Temp disable for v0.37
# pytest.lazy_fixture("complex_object_size"),
2022-12-19 17:45:26 +00:00
] ,
2023-06-23 14:50:18 +00:00
# TODO: Temp disable for v0.37
2023-08-02 11:54:03 +00:00
# ids=["simple object size", "complex object size"],
ids = [ " simple object size " ] ,
2022-12-19 17:45:26 +00:00
scope = " class " ,
)
def storage_objects_with_attributes ( self , request : FixtureRequest ) - > list [ StorageObjectInfo ] :
2023-08-02 11:54:03 +00:00
object_size : ObjectSize = request . param
2022-12-19 17:45:26 +00:00
storage_objects = [ ]
wallet = self . wallet
cid = create_container (
wallet = self . wallet ,
shell = self . shell ,
endpoint = self . cluster . default_rpc_endpoint ,
rule = self . PLACEMENT_RULE ,
basic_acl = PUBLIC_ACL ,
)
2023-08-02 11:54:03 +00:00
file_path = generate_file ( object_size . value )
2022-12-19 17:45:26 +00:00
for attributes in self . OBJECT_ATTRIBUTES :
storage_object_id = upload_via_http_gate_curl (
cid = cid ,
filepath = file_path ,
endpoint = self . cluster . default_http_gate_endpoint ,
headers = attr_into_str_header_curl ( attributes ) ,
)
storage_object = StorageObjectInfo ( cid , storage_object_id )
storage_object . size = os . path . getsize ( file_path )
storage_object . wallet_file_path = wallet
storage_object . file_path = file_path
storage_object . attributes = attributes
storage_objects . append ( storage_object )
yield storage_objects
2023-08-07 14:08:54 +00:00
@pytest.mark.skip ( " Skipped due to deprecated PUT via http " )
2022-12-19 17:45:26 +00:00
@allure.title ( " Get object1 by attribute " )
def test_object1_can_be_get_by_attr (
self , storage_objects_with_attributes : list [ StorageObjectInfo ]
) :
"""
Test to get object #1 by attribute and comapre hashes
Steps :
1. Download object #1 with attributes [Chapter2=w@r] and compare hashes
"""
storage_object_1 = storage_objects_with_attributes [ 0 ]
with allure . step (
f ' Download object#1 via wget with attributes Chapter2: { storage_object_1 . attributes [ " Chapter2 " ] } and compare hashes '
) :
get_object_by_attr_and_verify_hashes (
oid = storage_object_1 . oid ,
file_name = storage_object_1 . file_path ,
cid = storage_object_1 . cid ,
attrs = { " Chapter2 " : storage_object_1 . attributes [ " Chapter2 " ] } ,
endpoint = self . cluster . default_http_gate_endpoint ,
2023-07-24 06:55:14 +00:00
http_hostname = self . cluster . default_http_hostname ,
2022-12-19 17:45:26 +00:00
)
2023-08-07 09:43:16 +00:00
@allure.title ( " Get object2 with different attributes, then delete object2 and get object1 " )
2022-12-19 17:45:26 +00:00
def test_object2_can_be_get_by_attr (
self , storage_objects_with_attributes : list [ StorageObjectInfo ]
) :
"""
Test to get object2 with different attributes , then delete object2 and get object1 using 1 st attribute . Note : obj1 and obj2 have the same attribute #1,
and when obj2 is deleted you can get obj1 by 1 st attribute
Steps :
1. Download object #2 with attributes [chapter2=w@r] and compare hashes
2. Download object #2 with attributes [Ch@pter1=peace] and compare hashes
3. Delete object #2
4. Download object #1 with attributes [Writer=Leo Tolstoy] and compare hashes
"""
storage_object_1 = storage_objects_with_attributes [ 0 ]
storage_object_2 = storage_objects_with_attributes [ 1 ]
with allure . step (
f ' Download object#2 via wget with attributes [chapter2= { storage_object_2 . attributes [ " chapter2 " ] } ] / [Ch@pter1= { storage_object_2 . attributes [ " Ch@pter1 " ] } ] and compare hashes '
) :
selected_attributes_object2 = [
{ " chapter2 " : storage_object_2 . attributes [ " chapter2 " ] } ,
{ " Ch@pter1 " : storage_object_2 . attributes [ " Ch@pter1 " ] } ,
]
for attributes in selected_attributes_object2 :
get_object_by_attr_and_verify_hashes (
oid = storage_object_2 . oid ,
file_name = storage_object_2 . file_path ,
cid = storage_object_2 . cid ,
attrs = attributes ,
endpoint = self . cluster . default_http_gate_endpoint ,
2023-07-24 06:55:14 +00:00
http_hostname = self . cluster . default_http_hostname ,
2022-12-19 17:45:26 +00:00
)
with allure . step ( " Delete object#2 and verify is the container deleted " ) :
delete_object (
wallet = self . wallet ,
cid = storage_object_2 . cid ,
oid = storage_object_2 . oid ,
shell = self . shell ,
endpoint = self . cluster . default_rpc_endpoint ,
)
try_to_get_object_and_expect_error (
cid = storage_object_2 . cid ,
oid = storage_object_2 . oid ,
error_pattern = OBJECT_ALREADY_REMOVED_ERROR ,
endpoint = self . cluster . default_http_gate_endpoint ,
2023-07-24 06:55:14 +00:00
http_hostname = self . cluster . default_http_hostname ,
2022-12-19 17:45:26 +00:00
)
storage_objects_with_attributes . remove ( storage_object_2 )
with allure . step (
f ' Download object#1 with attributes [Writer= { storage_object_1 . attributes [ " Writer " ] } ] and compare hashes '
) :
key_value_pair = { " Writer " : storage_object_1 . attributes [ " Writer " ] }
get_object_by_attr_and_verify_hashes (
oid = storage_object_1 . oid ,
file_name = storage_object_1 . file_path ,
cid = storage_object_1 . cid ,
attrs = key_value_pair ,
endpoint = self . cluster . default_http_gate_endpoint ,
2023-07-24 06:55:14 +00:00
http_hostname = self . cluster . default_http_hostname ,
2022-12-19 17:45:26 +00:00
)
2023-08-07 09:43:16 +00:00
@allure.title ( " [NEGATIVE] Put object and get right after container is deleted " )
2023-07-17 06:26:58 +00:00
@pytest.mark.skip ( " Skipped due to deprecated PUT via http " )
2022-12-19 17:45:26 +00:00
def test_negative_put_and_get_object3 (
self , storage_objects_with_attributes : list [ StorageObjectInfo ]
) :
"""
Test to attempt to put object and try to download it right after the container has been deleted
Steps :
1. [ Negative ] Allocate and attempt to put object #3 via http with attributes: [Writer=Leo Tolstoy, Writer=peace, peace=peace]
Expected : " Error duplication of attributes detected "
2. Delete container
3. [ Negative ] Try to download object with attributes [ peace = peace ]
Expected : " HTTP request sent, awaiting response... 404 Not Found "
"""
storage_object_1 = storage_objects_with_attributes [ 0 ]
with allure . step (
" [Negative] Allocate and attemt to put object#3 via http with attributes: [Writer=Leo Tolstoy, Writer=peace, peace=peace] "
) :
file_path_3 = generate_file ( storage_object_1 . size )
attrs_obj3 = { " Writer " : " Leo Tolstoy " , " peace " : " peace " }
headers = attr_into_str_header_curl ( attrs_obj3 )
headers . append ( " " . join ( attr_into_str_header_curl ( { " Writer " : " peace " } ) ) )
error_pattern = f " key duplication error: X-Attribute-Writer "
upload_via_http_gate_curl (
cid = storage_object_1 . cid ,
filepath = file_path_3 ,
endpoint = self . cluster . default_http_gate_endpoint ,
headers = headers ,
error_pattern = error_pattern ,
)
with allure . step ( " Delete container and verify container deletion " ) :
delete_container (
wallet = self . wallet ,
cid = storage_object_1 . cid ,
shell = self . shell ,
endpoint = self . cluster . default_rpc_endpoint ,
)
2022-12-23 11:42:41 +00:00
self . tick_epoch ( )
2022-12-19 17:45:26 +00:00
wait_for_container_deletion (
self . wallet ,
storage_object_1 . cid ,
shell = self . shell ,
endpoint = self . cluster . default_rpc_endpoint ,
)
assert storage_object_1 . cid not in list_containers (
self . wallet , shell = self . shell , endpoint = self . cluster . default_rpc_endpoint
)
with allure . step (
" [Negative] Try to download (wget) object via wget with attributes [peace=peace] "
) :
request = f " /get/ { storage_object_1 . cid } /peace/peace "
error_pattern = " 404 Not Found "
try_to_get_object_via_passed_request_and_expect_error (
cid = storage_object_1 . cid ,
oid = " " ,
error_pattern = error_pattern ,
attrs = attrs_obj3 ,
http_request_path = request ,
endpoint = self . cluster . default_http_gate_endpoint ,
2023-07-24 06:55:14 +00:00
http_hostname = self . cluster . default_http_hostname ,
2022-12-19 17:45:26 +00:00
)