Skip to content

Commit 3f3786d

Browse files
author
Evgeniy Zayats
committed
tests: add ec sanity test
Signed-off-by: Evgeniy Zayats <zayatsevgeniy@nspcc.io>
1 parent dae474d commit 3f3786d

File tree

5 files changed

+152
-7
lines changed

5 files changed

+152
-7
lines changed

neofs-testlib/neofs_testlib/cli/neofs_cli/object.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,3 +415,27 @@ def searchv2(
415415
"object searchv2",
416416
**{param: value for param, value in locals().items() if param not in ["self"]},
417417
)
418+
419+
def nodes(
420+
self,
421+
rpc_endpoint: str,
422+
cid: str,
423+
oid: Optional[str] = None,
424+
shell_timeout: Optional[str] = None,
425+
) -> CommandResult:
426+
"""
427+
Search object.
428+
429+
Args:
430+
rpc_endpoint: Remote node address (as 'multiaddr' or '<host>:<port>').
431+
cid: Container ID.
432+
oid: Object ID.
433+
shell_timeout: Shell timeout for the command.
434+
435+
Returns:
436+
Command's result.
437+
"""
438+
return self._execute(
439+
"object nodes",
440+
**{param: value for param, value in locals().items() if param not in ["self"]},
441+
)

neofs-testlib/neofs_testlib/env/env.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -171,13 +171,16 @@ def generate_neo_go_config(self, wallet: NodeWallet):
171171
return neo_go_config_path
172172

173173
@allure.step("Deploy inner ring nodes")
174-
def deploy_inner_ring_nodes(self, count=1, with_main_chain=False, chain_meta_data=False, sn_validator_url=None):
174+
def deploy_inner_ring_nodes(
175+
self, count=1, with_main_chain=False, chain_meta_data=False, sn_validator_url=None, allow_ec=False
176+
):
175177
for _ in range(count):
176178
new_inner_ring_node = InnerRing(
177179
self,
178180
len(self.inner_ring_nodes) + 1,
179181
chain_meta_data=chain_meta_data,
180182
sn_validator_url=sn_validator_url,
183+
allow_ec=allow_ec,
181184
)
182185
new_inner_ring_node.generate_network_config()
183186
self.inner_ring_nodes.append(new_inner_ring_node)
@@ -664,6 +667,7 @@ def deploy(
664667
request=None,
665668
chain_meta_data=False,
666669
sn_validator_url=None,
670+
allow_ec=False,
667671
fschain_endpoints: Optional[list[str]] = None,
668672
shards_count=2,
669673
gc_remover_batch_size=200,
@@ -680,6 +684,7 @@ def deploy(
680684
with_main_chain=with_main_chain,
681685
chain_meta_data=chain_meta_data,
682686
sn_validator_url=sn_validator_url,
687+
allow_ec=allow_ec,
683688
)
684689

685690
if storage_nodes_count:
@@ -1052,11 +1057,7 @@ def _wait_until_ready(self):
10521057

10531058
class InnerRing(ResurrectableProcess):
10541059
def __init__(
1055-
self,
1056-
neofs_env: NeoFSEnv,
1057-
ir_number: int,
1058-
chain_meta_data=False,
1059-
sn_validator_url=None,
1060+
self, neofs_env: NeoFSEnv, ir_number: int, chain_meta_data=False, sn_validator_url=None, allow_ec=False
10601061
):
10611062
self.neofs_env = neofs_env
10621063
self.ir_number = ir_number
@@ -1083,6 +1084,7 @@ def __init__(
10831084
self.ir_state_file = self.neofs_env._generate_temp_file(self.inner_ring_dir, prefix="ir_state_file")
10841085
self.chain_meta_data = chain_meta_data
10851086
self.sn_validator_url = sn_validator_url
1087+
self.allow_ec = allow_ec
10861088
self.stdout = "Not initialized"
10871089
self.stderr = "Not initialized"
10881090
self.process = None
@@ -1178,6 +1180,7 @@ def start(
11781180
prometheus_address=self.prometheus_address,
11791181
chain_meta_data=self.chain_meta_data,
11801182
sn_validator_url=self.sn_validator_url,
1183+
allow_ec=self.allow_ec,
11811184
)
11821185
logger.info(f"Launching Inner Ring Node:{self}")
11831186
self._launch_process()

neofs-testlib/neofs_testlib/env/templates/ir.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ prometheus:
125125

126126
experimental:
127127
chain_meta_data: {{ chain_meta_data }}
128+
allow_ec: {{ allow_ec }}
128129

129130
{% if sn_validator_url %}
130131
sn_validator:

pytest_tests/tests/conftest.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def get_or_create_neofs_env(
3838
with_rest_gw=True,
3939
chain_meta_data=False,
4040
sn_validator_url=None,
41+
allow_ec=False,
4142
shards_count=2,
4243
gc_remover_batch_size=200,
4344
gc_sleep_interval=STORAGE_GC_TIME,
@@ -56,6 +57,7 @@ def get_or_create_neofs_env(
5657
request=request,
5758
chain_meta_data=chain_meta_data,
5859
sn_validator_url=sn_validator_url,
60+
allow_ec=allow_ec,
5961
shards_count=shards_count,
6062
gc_remover_batch_size=gc_remover_batch_size,
6163
gc_sleep_interval=gc_sleep_interval,
@@ -70,7 +72,11 @@ def neofs_env(temp_directory, artifacts_directory, request):
7072
else:
7173
params = {}
7274
neofs_env = get_or_create_neofs_env(
73-
request, with_s3_gw=True, with_rest_gw=True, chain_meta_data=params.get("chain_meta_data", False)
75+
request,
76+
with_s3_gw=True,
77+
with_rest_gw=True,
78+
chain_meta_data=params.get("chain_meta_data", False),
79+
allow_ec=params.get("allow_ec", False),
7480
)
7581
yield neofs_env
7682
neofs_env.finalize(request)
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import re
2+
3+
import allure
4+
import neofs_env.neofs_epoch as neofs_epoch
5+
import pytest
6+
from helpers.container import (
7+
create_container,
8+
delete_container,
9+
list_containers,
10+
wait_for_container_deletion,
11+
)
12+
from helpers.file_helper import generate_file
13+
from helpers.neofs_verbs import (
14+
get_object,
15+
put_object_to_random_node,
16+
search_objectv2,
17+
)
18+
from neofs_testlib.env.env import NeoFSEnv, NodeWallet
19+
20+
21+
def parse_ec_nodes_count(output: str) -> int:
22+
"""
23+
Parse the EC descriptor output and count the number of nodes.
24+
25+
Args:
26+
output: The output from neofs-cli object nodes command
27+
28+
Returns:
29+
int: Number of nodes found in the output
30+
"""
31+
node_pattern = r"Node \d+:"
32+
nodes = re.findall(node_pattern, output)
33+
return len(nodes)
34+
35+
36+
@pytest.mark.sanity
37+
@pytest.mark.parametrize("neofs_env", [{"allow_ec": True}], ids=["allow_ec=True"], indirect=True)
38+
@pytest.mark.parametrize(
39+
"data_shards,parity_shards",
40+
[
41+
(3, 1),
42+
(2, 1),
43+
(1, 1),
44+
(1, 2),
45+
(2, 2),
46+
(1, 3),
47+
],
48+
ids=[
49+
"EC_3/1",
50+
"EC_2/1",
51+
"EC_1/1",
52+
"EC_1/2",
53+
"EC_2/2",
54+
"EC_1/3",
55+
],
56+
)
57+
@pytest.mark.simple
58+
def test_ec_container_sanity(default_wallet: NodeWallet, neofs_env: NeoFSEnv, data_shards: int, parity_shards: int):
59+
wallet = default_wallet
60+
61+
placement_rule = f"EC {data_shards}/{parity_shards} CBF 1"
62+
cid = create_container(
63+
wallet.path,
64+
rule=placement_rule,
65+
name="ec-container",
66+
shell=neofs_env.shell,
67+
endpoint=neofs_env.sn_rpc,
68+
)
69+
70+
containers = list_containers(wallet.path, shell=neofs_env.shell, endpoint=neofs_env.sn_rpc)
71+
assert cid in containers, f"Expected container {cid} in containers: {containers}"
72+
73+
source_file_path = generate_file(neofs_env.get_object_size("simple_object_size"))
74+
75+
oid = put_object_to_random_node(wallet.path, source_file_path, cid, shell=neofs_env.shell, neofs_env=neofs_env)
76+
77+
get_object(
78+
default_wallet.path,
79+
cid,
80+
oid,
81+
neofs_env.shell,
82+
neofs_env.sn_rpc,
83+
)
84+
85+
result = (
86+
neofs_env.neofs_cli(neofs_env.storage_nodes[0].cli_config)
87+
.object.nodes(rpc_endpoint=neofs_env.storage_nodes[0].endpoint, cid=cid, oid=oid)
88+
.stdout
89+
)
90+
assert f"EC {data_shards}/{parity_shards}" in result, f"Expected placement rule {placement_rule} in nodes output: {result}"
91+
92+
expected_nodes = data_shards + parity_shards
93+
actual_nodes = parse_ec_nodes_count(result)
94+
assert actual_nodes == expected_nodes, (
95+
f"Expected {expected_nodes} nodes (data: {data_shards}, parity: {parity_shards}), but found {actual_nodes} nodes in output: {result}"
96+
)
97+
98+
found_objects, _ = search_objectv2(
99+
rpc_endpoint=neofs_env.sn_rpc, wallet=default_wallet.path, cid=cid, shell=neofs_env.shell
100+
)
101+
102+
assert len(found_objects) == expected_nodes + 1, (
103+
f"Invalid number of found objects in EC container, expected {expected_nodes + 1}, found {len(found_objects)}"
104+
)
105+
106+
with allure.step("Delete container and check it was deleted"):
107+
delete_container(wallet.path, cid, shell=neofs_env.shell, endpoint=neofs_env.sn_rpc)
108+
current_epoch = neofs_epoch.get_epoch(neofs_env)
109+
neofs_epoch.tick_epoch(neofs_env)
110+
neofs_epoch.wait_for_epochs_align(neofs_env, current_epoch)
111+
wait_for_container_deletion(wallet.path, cid, shell=neofs_env.shell, endpoint=neofs_env.sn_rpc)

0 commit comments

Comments
 (0)