Skip to content

Commit d86eb27

Browse files
committed
testing: reimpl snapshots CITs
- Update and reimplement snapshots tests.
1 parent e950d2a commit d86eb27

File tree

6 files changed

+353
-40
lines changed

6 files changed

+353
-40
lines changed

tests/python_test_cases/tests/common.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ def build_tools(self, version: str) -> BuildTools:
4949
assert version in ("cpp", "rust")
5050
return BazelTools(option_prefix=version)
5151

52+
@pytest.fixture(scope="class")
53+
def temp_dir(
54+
self, tmp_path_factory: pytest.TempPathFactory, version: str
55+
) -> Generator[Path, None, None]:
56+
yield from temp_dir_common(tmp_path_factory, self.__class__.__name__, version)
57+
5258
@pytest.fixture(scope="class")
5359
def logs_target(self, target_path: Path, logs: LogContainer) -> LogContainer:
5460
"""

tests/python_test_cases/tests/test_cit_multiple_kvs.py

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,14 @@
11
from pathlib import Path
2-
from typing import Any, Generator
2+
from typing import Any
33
import pytest
44

5-
from common import CommonScenario, ResultCode, temp_dir_common
5+
from common import CommonScenario, ResultCode
66
from testing_utils import ScenarioResult, LogContainer
77

88

99
pytestmark = pytest.mark.parametrize("version", ["rust"], scope="class")
1010

1111

12-
class MultipleKvsScenario(CommonScenario):
13-
"""
14-
Common base implementation for multiple KVS tests.
15-
"""
16-
17-
@pytest.fixture(scope="class")
18-
def temp_dir(
19-
self, tmp_path_factory: pytest.TempPathFactory, version: str
20-
) -> Generator[Path, None, None]:
21-
yield from temp_dir_common(tmp_path_factory, self.__class__.__name__, version)
22-
23-
2412
@pytest.mark.PartiallyVerifies(
2513
["comp_req__persistency__multi_instance", "comp_req__persistency__concurrency"]
2614
)
@@ -30,7 +18,7 @@ def temp_dir(
3018
)
3119
@pytest.mark.TestType("requirements-based")
3220
@pytest.mark.DerivationTechnique("requirements-based")
33-
class TestMultipleInstanceIds(MultipleKvsScenario):
21+
class TestMultipleInstanceIds(CommonScenario):
3422
@pytest.fixture(scope="class")
3523
def scenario_name(self) -> str:
3624
return "cit.multiple_kvs.multiple_instance_ids"
@@ -70,7 +58,7 @@ def test_ok(self, results: ScenarioResult, logs_info_level: LogContainer):
7058
)
7159
@pytest.mark.TestType("requirements-based")
7260
@pytest.mark.DerivationTechnique("requirements-based")
73-
class TestSameInstanceIdSameValue(MultipleKvsScenario):
61+
class TestSameInstanceIdSameValue(CommonScenario):
7462
@pytest.fixture(scope="class")
7563
def scenario_name(self) -> str:
7664
return "cit.multiple_kvs.same_instance_id_same_value"
@@ -105,7 +93,7 @@ def test_ok(self, results: ScenarioResult, logs_info_level: LogContainer):
10593
)
10694
@pytest.mark.TestType("requirements-based")
10795
@pytest.mark.DerivationTechnique("requirements-based")
108-
class TestSameInstanceIdDifferentValue(MultipleKvsScenario):
96+
class TestSameInstanceIdDifferentValue(CommonScenario):
10997
@pytest.fixture(scope="class")
11098
def scenario_name(self) -> str:
11199
return "cit.multiple_kvs.same_instance_id_diff_value"

tests/python_test_cases/tests/test_cit_persistency.py

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,20 @@
11
from pathlib import Path
2-
from typing import Any, Generator
2+
from typing import Any
33
import pytest
4-
from common import CommonScenario, ResultCode, temp_dir_common
4+
from common import CommonScenario, ResultCode
55
from testing_utils import ScenarioResult, LogContainer
66

77
pytestmark = pytest.mark.parametrize("version", ["rust"], scope="class")
88

99

10-
class PersistencyScenario(CommonScenario):
11-
"""
12-
Common base implementation for persistency tests.
13-
"""
14-
15-
def instance_id(self) -> int:
16-
return 2
17-
18-
@pytest.fixture(scope="class")
19-
def temp_dir(
20-
self, tmp_path_factory: pytest.TempPathFactory, version: str
21-
) -> Generator[Path, None, None]:
22-
yield from temp_dir_common(tmp_path_factory, self.__class__.__name__, version)
23-
24-
2510
@pytest.mark.PartiallyVerifies([])
2611
@pytest.mark.FullyVerifies(["comp_req__persistency__persist_data_store_com"])
2712
@pytest.mark.Description(
2813
"Verifies that disabling flush on exit but manually flushing ensures data is persisted correctly."
2914
)
3015
@pytest.mark.TestType("requirements-based")
3116
@pytest.mark.DerivationTechnique("requirements-based")
32-
class TestExplicitFlush(PersistencyScenario):
17+
class TestExplicitFlush(CommonScenario):
3318
NUM_VALUES = 5
3419

3520
@pytest.fixture(scope="class")
@@ -40,7 +25,7 @@ def scenario_name(self) -> str:
4025
def test_config(self, temp_dir: Path) -> dict[str, Any]:
4126
return {
4227
"kvs_parameters": {
43-
"instance_id": self.instance_id(),
28+
"instance_id": 2,
4429
"dir": str(temp_dir),
4530
"flush_on_exit": False,
4631
}
@@ -62,7 +47,7 @@ def test_data_stored(self, results: ScenarioResult, logs_info_level: LogContaine
6247
)
6348
@pytest.mark.TestType("requirements-based")
6449
@pytest.mark.DerivationTechnique("requirements-based")
65-
class TestFlushOnExitEnabled(PersistencyScenario):
50+
class TestFlushOnExitEnabled(CommonScenario):
6651
NUM_VALUES = 5
6752

6853
@pytest.fixture(scope="class")
@@ -73,7 +58,7 @@ def scenario_name(self) -> str:
7358
def test_config(self, temp_dir: Path) -> dict[str, Any]:
7459
return {
7560
"kvs_parameters": {
76-
"instance_id": self.instance_id(),
61+
"instance_id": 2,
7762
"dir": str(temp_dir),
7863
"flush_on_exit": True,
7964
}
@@ -95,7 +80,7 @@ def test_data_stored(self, results: ScenarioResult, logs_info_level: LogContaine
9580
)
9681
@pytest.mark.TestType("requirements-based")
9782
@pytest.mark.DerivationTechnique("requirements-based")
98-
class TestFlushOnExitDisabled(PersistencyScenario):
83+
class TestFlushOnExitDisabled(CommonScenario):
9984
NUM_VALUES = 5
10085

10186
@pytest.fixture(scope="class")
@@ -106,7 +91,7 @@ def scenario_name(self) -> str:
10691
def test_config(self, temp_dir: Path) -> dict[str, Any]:
10792
return {
10893
"kvs_parameters": {
109-
"instance_id": self.instance_id(),
94+
"instance_id": 2,
11095
"dir": str(temp_dir),
11196
"flush_on_exit": False,
11297
}
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
from pathlib import Path
2+
from typing import Any
3+
import pytest
4+
from common import CommonScenario, ResultCode
5+
from testing_utils import ScenarioResult, LogContainer
6+
7+
pytestmark = pytest.mark.parametrize("version", ["rust"], scope="class")
8+
9+
10+
class TestSnapshotCountFirstFlush(CommonScenario):
11+
@pytest.fixture(scope="class")
12+
def scenario_name(self) -> str:
13+
return "cit.snapshots.count"
14+
15+
@pytest.fixture(scope="class")
16+
def test_config(self, temp_dir: Path) -> dict[str, Any]:
17+
return {"kvs_parameters": {"instance_id": 1, "dir": str(temp_dir)}, "count": 1}
18+
19+
def test_ok(
20+
self,
21+
test_config: dict[str, Any],
22+
results: ScenarioResult,
23+
logs_info_level: LogContainer,
24+
):
25+
max_count = 3
26+
assert results.return_code == ResultCode.SUCCESS
27+
28+
count = test_config["count"]
29+
logs = logs_info_level.get_logs("snapshot_count")
30+
assert len(logs) == count + 1
31+
for i in range(count):
32+
expected = min(i, max_count)
33+
assert logs[i].snapshot_count == expected
34+
35+
assert logs[-1].snapshot_count == min(count, max_count)
36+
37+
38+
class TestSnapshotCountFull(TestSnapshotCountFirstFlush):
39+
@pytest.fixture(scope="class")
40+
def test_config(self, temp_dir: Path) -> dict[str, Any]:
41+
return {"kvs_parameters": {"instance_id": 1, "dir": str(temp_dir)}, "count": 4}
42+
43+
44+
class TestSnapshotMaxCount(CommonScenario):
45+
@pytest.fixture(scope="class")
46+
def scenario_name(self) -> str:
47+
return "cit.snapshots.max_count"
48+
49+
@pytest.fixture(scope="class")
50+
def test_config(self, temp_dir: Path) -> dict[str, Any]:
51+
return {"kvs_parameters": {"instance_id": 1, "dir": str(temp_dir)}}
52+
53+
def test_ok(self, results: ScenarioResult, logs_info_level: LogContainer):
54+
assert results.return_code == ResultCode.SUCCESS
55+
assert logs_info_level.find_log("max_count", value=3) is not None
56+
57+
58+
class TestSnapshotRestorePrevious(CommonScenario):
59+
@pytest.fixture(scope="class")
60+
def scenario_name(self) -> str:
61+
return "cit.snapshots.restore"
62+
63+
@pytest.fixture(scope="class")
64+
def test_config(self, temp_dir: Path) -> dict[str, Any]:
65+
return {
66+
"kvs_parameters": {"instance_id": 1, "dir": str(temp_dir)},
67+
"snapshot_id": 1,
68+
"count": 3,
69+
}
70+
71+
def test_ok(
72+
self,
73+
results: ScenarioResult,
74+
logs_info_level: LogContainer,
75+
):
76+
assert results.return_code == ResultCode.SUCCESS
77+
78+
result_log = logs_info_level.find_log("result")
79+
assert result_log is not None
80+
assert result_log.result == "Ok(())"
81+
82+
value_log = logs_info_level.find_log("value")
83+
assert value_log is not None
84+
assert value_log.value == 1
85+
86+
87+
class TestSnapshotRestoreCurrent(CommonScenario):
88+
@pytest.fixture(scope="class")
89+
def scenario_name(self) -> str:
90+
return "cit.snapshots.restore"
91+
92+
@pytest.fixture(scope="class")
93+
def test_config(self, temp_dir: Path) -> dict[str, Any]:
94+
return {
95+
"kvs_parameters": {"instance_id": 1, "dir": str(temp_dir)},
96+
"snapshot_id": 0,
97+
"count": 3,
98+
}
99+
100+
def capture_stderr(self) -> bool:
101+
return True
102+
103+
def test_error(
104+
self,
105+
results: ScenarioResult,
106+
logs_info_level: LogContainer,
107+
):
108+
assert results.return_code == ResultCode.SUCCESS
109+
110+
assert results.stderr is not None
111+
assert "error: tried to restore current KVS as snapshot" in results.stderr
112+
113+
result_log = logs_info_level.find_log("result")
114+
assert result_log is not None
115+
assert result_log.result == "Err(InvalidSnapshotId)"
116+
117+
118+
class TestSnapshotRestoreNonexistent(CommonScenario):
119+
@pytest.fixture(scope="class")
120+
def scenario_name(self) -> str:
121+
return "cit.snapshots.restore"
122+
123+
@pytest.fixture(scope="class")
124+
def test_config(self, temp_dir: Path) -> dict[str, Any]:
125+
return {
126+
"kvs_parameters": {"instance_id": 1, "dir": str(temp_dir)},
127+
"snapshot_id": 2,
128+
"count": 1,
129+
}
130+
131+
def capture_stderr(self) -> bool:
132+
return True
133+
134+
def test_error(
135+
self,
136+
results: ScenarioResult,
137+
logs_info_level: LogContainer,
138+
):
139+
assert results.return_code == ResultCode.SUCCESS
140+
141+
assert results.stderr is not None
142+
assert "error: tried to restore a non-existing snapshot" in results.stderr
143+
144+
result_log = logs_info_level.find_log("result")
145+
assert result_log is not None
146+
assert result_log.result == "Err(InvalidSnapshotId)"
147+
148+
149+
class TestSnapshotPathsExist(CommonScenario):
150+
@pytest.fixture(scope="class")
151+
def scenario_name(self) -> str:
152+
return "cit.snapshots.paths"
153+
154+
@pytest.fixture(scope="class")
155+
def test_config(self, temp_dir: Path) -> dict[str, Any]:
156+
return {
157+
"kvs_parameters": {"instance_id": 1, "dir": str(temp_dir)},
158+
"snapshot_id": 1,
159+
"count": 3,
160+
}
161+
162+
def test_ok(
163+
self,
164+
temp_dir: Path,
165+
results: ScenarioResult,
166+
logs_info_level: LogContainer,
167+
):
168+
assert results.return_code == ResultCode.SUCCESS
169+
170+
paths_log = logs_info_level.find_log("kvs_path")
171+
assert paths_log is not None
172+
assert paths_log.kvs_path == f'Ok("{temp_dir}/kvs_1_1.json")'
173+
assert paths_log.hash_path == f'Ok("{temp_dir}/kvs_1_1.hash")'
174+
175+
176+
class TestSnapshotPathsNonexistent(CommonScenario):
177+
@pytest.fixture(scope="class")
178+
def scenario_name(self) -> str:
179+
return "cit.snapshots.paths"
180+
181+
@pytest.fixture(scope="class")
182+
def test_config(self, temp_dir: Path) -> dict[str, Any]:
183+
return {
184+
"kvs_parameters": {"instance_id": 1, "dir": str(temp_dir)},
185+
"snapshot_id": 2,
186+
"count": 1,
187+
}
188+
189+
def test_error(
190+
self,
191+
results: ScenarioResult,
192+
logs_info_level: LogContainer,
193+
):
194+
assert results.return_code == ResultCode.SUCCESS
195+
196+
paths_log = logs_info_level.find_log("kvs_path")
197+
assert paths_log is not None
198+
assert paths_log.kvs_path == "Err(FileNotFound)"
199+
assert paths_log.hash_path == "Err(FileNotFound)"

tests/rust_test_scenarios/src/cit/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
use crate::cit::default_values::default_values_group;
22
use crate::cit::multiple_kvs::multiple_kvs_group;
33
use crate::cit::persistency::persistency_group;
4+
use crate::cit::snapshots::snapshots_group;
45
use crate::cit::supported_datatypes::supported_datatypes_group;
56
use test_scenarios_rust::scenario::{ScenarioGroup, ScenarioGroupImpl};
67

78
mod default_values;
89
mod multiple_kvs;
910
mod persistency;
11+
mod snapshots;
1012
mod supported_datatypes;
1113

1214
pub fn cit_scenario_group() -> Box<dyn ScenarioGroup> {
@@ -17,6 +19,7 @@ pub fn cit_scenario_group() -> Box<dyn ScenarioGroup> {
1719
default_values_group(),
1820
multiple_kvs_group(),
1921
persistency_group(),
22+
snapshots_group(),
2023
supported_datatypes_group(),
2124
],
2225
))

0 commit comments

Comments
 (0)