forked from ChelseaKR/exitdrill
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_exercise.py
More file actions
121 lines (99 loc) · 3.63 KB
/
Copy pathtest_exercise.py
File metadata and controls
121 lines (99 loc) · 3.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import json
from collections.abc import Callable
from pathlib import Path
from shutil import copy
from typing import cast
import pytest
from exitdrill.exercise import ExercisePlanError, load_exercise_plan
def _copy_plan(tmp_path: Path) -> Path:
source = Path(__file__).parents[1] / "examples" / "synthetic-exercise" / "plan.json"
destination = tmp_path / "plan.json"
copy(source, destination)
return destination
def _raw(path: Path) -> dict[str, object]:
value = json.loads(path.read_text(encoding="utf-8"))
assert isinstance(value, dict)
return value
def _write(path: Path, value: object) -> None:
path.write_text(json.dumps(value), encoding="utf-8")
def _section(value: dict[str, object], key: str) -> dict[str, object]:
item = value[key]
assert isinstance(item, dict)
return cast(dict[str, object], item)
def _items(value: dict[str, object], key: str) -> list[object]:
item = value[key]
assert isinstance(item, list)
return cast(list[object], item)
def _remove_last_probe(value: dict[str, object]) -> None:
_items(value, "workflow_probes").pop()
def _duplicate_probe(value: dict[str, object]) -> None:
probes = _items(value, "workflow_probes")
probes.append(probes[0])
def test_loads_synthetic_exercise_preflight() -> None:
path = Path(__file__).parents[1] / "examples" / "synthetic-exercise" / "plan.json"
plan = load_exercise_plan(path)
assert plan.exercise_id == "invented-crm-target-preflight-001"
assert plan.target_system == "Invented AlternateCase Sandbox"
@pytest.mark.parametrize(
("mutation", "message"),
[
(lambda raw: raw.update({"data_mode": "production"}), "synthetic_only"),
(
lambda raw: _section(raw, "source").update({"customer_obtainable": False}),
"must be true",
),
(
lambda raw: _section(raw, "source").update({"transform_command": "curl"}),
"unknown field",
),
(
lambda raw: _section(raw, "baseline").update({"captured_before_export": False}),
"must be true",
),
(
lambda raw: _section(_section(raw, "baseline"), "coverage").update(
{"permissions": "assumed"}
),
"coverage is unsupported",
),
(
lambda raw: _section(raw, "target_sandbox").update({"egress_blocked": False}),
"must be true",
),
(
lambda raw: _section(raw, "target_sandbox").update({"production_data_allowed": True}),
"must be false",
),
(_remove_last_probe, "exactly the five"),
(_duplicate_probe, "ids must be unique"),
(
lambda raw: _section(raw, "evidence_controls").update(
{"target_readback_required": False}
),
"must be true",
),
],
)
def test_rejects_unsafe_or_incomplete_exercise_plan(
tmp_path: Path,
mutation: Callable[[dict[str, object]], None],
message: str,
) -> None:
path = _copy_plan(tmp_path)
raw = _raw(path)
mutation(raw)
_write(path, raw)
with pytest.raises(ExercisePlanError, match=message):
load_exercise_plan(path)
def test_rejects_duplicate_exercise_json_key(tmp_path: Path) -> None:
path = _copy_plan(tmp_path)
content = path.read_text(encoding="utf-8")
path.write_text(
content.replace(
'"data_mode": "synthetic_only",',
'"data_mode": "synthetic_only", "data_mode": "synthetic_only",',
),
encoding="utf-8",
)
with pytest.raises(ExercisePlanError, match="duplicate object key"):
load_exercise_plan(path)