Skip to content

Commit bdce5ae

Browse files
fix: enforce EXCLUDED_FROM_GATE at check time and harden file reads
1 parent 0f55400 commit bdce5ae

2 files changed

Lines changed: 42 additions & 10 deletions

File tree

scripts/check_benchmark_regression.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ def load_results(results_path: str | Path) -> dict[str, float]:
2626
path = Path(results_path)
2727
try:
2828
data = json.loads(path.read_text(encoding="utf-8"))
29+
except OSError as exc:
30+
raise BenchmarkDataError(f"cannot read {path}: {exc}") from exc
2931
except json.JSONDecodeError as exc:
3032
raise BenchmarkDataError(f"invalid JSON in {path}: {exc}") from exc
3133
try:
@@ -57,6 +59,7 @@ def load_baseline_means(baselines_path: str | Path) -> dict[str, float]:
5759
path = Path(baselines_path)
5860
try:
5961
data = json.loads(path.read_text(encoding="utf-8"))
62+
except OSError as exc:
6063
except json.JSONDecodeError as exc:
6164
raise BenchmarkDataError(f"invalid JSON in {path}: {exc}") from exc
6265
if not isinstance(data, dict):
@@ -97,6 +100,8 @@ def check_regression(
97100

98101
failures: list[str] = []
99102
for name, base in baseline_means.items():
103+
if name in EXCLUDED_FROM_GATE:
104+
continue
100105
cur = flat.get(name)
101106
if cur is None:
102107
print(f"WARN: no current result for baseline {name!r}; skipping")
@@ -111,6 +116,8 @@ def check_regression(
111116
failures.append(name)
112117

113118
for name in flat:
119+
if name in EXCLUDED_FROM_GATE:
120+
continue
114121
if name not in baseline_means:
115122
print(f"WARN: {name!r} has no baseline yet; not gated")
116123

tests/test_check_benchmark_regression.py

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
load_results,
1414
)
1515

16+
GATED_BENCH = "test_parse_session_medium"
17+
1618

1719
def _write_results(path, benchmarks: list[dict]) -> None:
1820
path.write_text(
@@ -55,11 +57,11 @@ def test_regression_over_threshold_fails(tmp_path, capsys: pytest.CaptureFixture
5557
baselines = tmp_path / "baselines.json"
5658
_write_results(
5759
results,
58-
[{"name": "test_parse_session_small", "stats": {"mean": 0.0002}}],
60+
[{"name": GATED_BENCH, "stats": {"mean": 0.0025}}],
5961
)
6062
_write_baselines(
6163
baselines,
62-
{"parse": {"test_parse_session_small": 0.0001}},
64+
{"parse": {GATED_BENCH: 0.002}},
6365
)
6466

6567
assert check_regression(results, baselines) == 1
@@ -72,11 +74,11 @@ def test_within_threshold_passes(tmp_path) -> None:
7274
baselines = tmp_path / "baselines.json"
7375
_write_results(
7476
results,
75-
[{"name": "test_parse_session_small", "stats": {"mean": 0.00011}}],
77+
[{"name": GATED_BENCH, "stats": {"mean": 0.0022}}],
7678
)
7779
_write_baselines(
7880
baselines,
79-
{"parse": {"test_parse_session_small": 0.0001}},
81+
{"parse": {GATED_BENCH: 0.002}},
8082
)
8183

8284
assert check_regression(results, baselines) == 0
@@ -96,35 +98,58 @@ def test_load_results_requires_benchmarks_array(tmp_path) -> None:
9698
load_results(path)
9799

98100

101+
def test_load_results_rejects_missing_file(tmp_path) -> None:
102+
with pytest.raises(BenchmarkDataError, match="cannot read"):
103+
load_results(tmp_path / "missing.json")
104+
105+
99106
def test_zero_baseline_skips_ratio_check(tmp_path, capsys: pytest.CaptureFixture[str]) -> None:
100107
results = tmp_path / "results.json"
101108
baselines = tmp_path / "baselines.json"
102109
_write_results(
103110
results,
104-
[{"name": "test_parse_session_small", "stats": {"mean": 0.0002}}],
111+
[{"name": GATED_BENCH, "stats": {"mean": 0.0025}}],
105112
)
106113
_write_baselines(
107114
baselines,
108-
{"parse": {"test_parse_session_small": 0.0}},
115+
{"parse": {GATED_BENCH: 0.0}},
109116
)
110117

111118
assert check_regression(results, baselines) == 0
112-
assert "baseline for 'test_parse_session_small' is zero" in capsys.readouterr().out
119+
assert f"baseline for '{GATED_BENCH}' is zero" in capsys.readouterr().out
113120

114121

115122
def test_exactly_at_threshold_passes(tmp_path) -> None:
116123
results = tmp_path / "results.json"
117124
baselines = tmp_path / "baselines.json"
118125
_write_results(
119126
results,
120-
[{"name": "test_parse_session_small", "stats": {"mean": 0.00012}}],
127+
[{"name": GATED_BENCH, "stats": {"mean": 0.0024}}],
128+
)
129+
_write_baselines(
130+
baselines,
131+
{"parse": {GATED_BENCH: 0.002}},
132+
)
133+
134+
assert check_regression(results, baselines) == 0
135+
136+
137+
def test_excluded_benchmark_in_baselines_is_not_gated(
138+
tmp_path, capsys: pytest.CaptureFixture[str]
139+
) -> None:
140+
results = tmp_path / "results.json"
141+
baselines = tmp_path / "baselines.json"
142+
_write_results(
143+
results,
144+
[{"name": "test_parse_session_small", "stats": {"mean": 0.001}}],
121145
)
122146
_write_baselines(
123147
baselines,
124148
{"parse": {"test_parse_session_small": 0.0001}},
125149
)
126150

127151
assert check_regression(results, baselines) == 0
152+
assert "REGRESSION" not in capsys.readouterr().out
128153

129154

130155
def test_missing_current_result_warns_without_failing(
@@ -135,7 +160,7 @@ def test_missing_current_result_warns_without_failing(
135160
_write_results(results, [])
136161
_write_baselines(
137162
baselines,
138-
{"parse": {"test_parse_session_small": 0.0001}},
163+
{"parse": {GATED_BENCH: 0.002}},
139164
)
140165

141166
assert check_regression(results, baselines) == 0
@@ -148,7 +173,7 @@ def test_main_reports_benchmark_data_error(tmp_path, capsys: pytest.CaptureFixtu
148173
bad = tmp_path / "bad.json"
149174
bad.write_text("{}", encoding="utf-8")
150175
baselines = tmp_path / "baselines.json"
151-
_write_baselines(baselines, {"parse": {"test_parse_session_small": 0.0001}})
176+
_write_baselines(baselines, {"parse": {GATED_BENCH: 0.002}})
152177

153178
assert main([str(bad), str(baselines)]) == 2
154179
assert "ERROR:" in capsys.readouterr().err

0 commit comments

Comments
 (0)