|
3 | 3 |
|
4 | 4 | """Tests for the declarative benchmark matrix. |
5 | 5 |
|
6 | | -The parity tests read the current workflow YAML and assert that the ``develop`` and ``nightly`` |
7 | | -profiles reproduce today's hand-written matrices exactly. They are the proof that introducing the |
8 | | -registry is behavior-preserving; once the workflows consume ``vx-bench matrix`` and the inline |
9 | | -matrices are removed, these two tests should be replaced by the golden tests alone. |
10 | | -
|
11 | | -Regenerate the golden files after an intended change with ``UPDATE_GOLDEN=1 pytest``. |
| 6 | +The golden files (``tests/golden/<profile>.json``) pin each profile's resolved matrix, so any |
| 7 | +change to what-runs surfaces as a reviewable diff. Regenerate them after an intended change with |
| 8 | +``UPDATE_GOLDEN=1 pytest``. |
12 | 9 | """ |
13 | 10 |
|
14 | 11 | import json |
@@ -197,57 +194,43 @@ def test_matrix_matches_golden(profile_name: str) -> None: |
197 | 194 |
|
198 | 195 |
|
199 | 196 | # -------------------------------------------------------------------------------------------------- |
200 | | -# Parity with the current workflow YAML (behavior preservation) |
| 197 | +# Behavior preservation: develop and nightly reproduce the target sets the (now-deleted) inline |
| 198 | +# workflow matrices used. The golden files pin the full output; these spot the key invariants. |
201 | 199 | # -------------------------------------------------------------------------------------------------- |
202 | 200 |
|
203 | 201 |
|
204 | | -def _repo_root() -> pathlib.Path: |
205 | | - return pathlib.Path(__file__).resolve().parents[2] |
206 | | - |
207 | | - |
208 | | -def _extract_json_block(text: str, key: str) -> list[dict[str, object]]: |
209 | | - """Extract the JSON array that follows ``key`` in a ``... | <block>`` workflow scalar.""" |
210 | | - pipe = text.index("|", text.index(key)) |
211 | | - body: list[str] = [] |
212 | | - indent: int | None = None |
213 | | - for line in text[pipe + 1 :].splitlines(): |
214 | | - if line.strip() == "": |
215 | | - if indent is not None: |
216 | | - body.append(line) |
217 | | - continue |
218 | | - line_indent = len(line) - len(line.lstrip()) |
219 | | - if indent is None: |
220 | | - indent = line_indent |
221 | | - elif line_indent < indent: |
222 | | - break |
223 | | - body.append(line) |
224 | | - return json.loads("\n".join(body)) |
225 | | - |
226 | | - |
227 | | -def _target_pairs(targets: list[dict[str, object]]) -> frozenset[tuple[object, object]]: |
228 | | - return frozenset((t["engine"], t["format"]) for t in targets) |
| 202 | +def _pairs(entry: dict[str, object]) -> set[tuple[str, str]]: |
| 203 | + return {(t["engine"], t["format"]) for t in entry["targets"]} |
229 | 204 |
|
230 | 205 |
|
231 | | -def test_develop_profile_matches_current_full_matrix() -> None: |
232 | | - text = (_repo_root() / ".github/workflows/sql-benchmarks.yml").read_text(encoding="utf-8") |
233 | | - current = {b["id"]: b for b in _extract_json_block(text, "benchmark_matrix:")} |
234 | | - resolved = {entry["id"]: entry for entry in resolve_matrix(PROFILES["develop"])} |
235 | | - |
236 | | - assert set(resolved) == set(current) |
237 | | - for bid, bench in current.items(): |
238 | | - assert _target_pairs(resolved[bid]["targets"]) == _target_pairs(bench["develop_targets"]), bid |
239 | | - assert resolved[bid]["data_formats"] == bench["data_formats"], bid |
240 | | - |
241 | | - |
242 | | -def test_nightly_profile_matches_current_nightly_matrix() -> None: |
243 | | - text = (_repo_root() / ".github/workflows/nightly-bench.yml").read_text(encoding="utf-8") |
244 | | - current = _extract_json_block(text, "benchmark_matrix:") |
245 | | - resolved = {entry["id"]: entry for entry in resolve_matrix(PROFILES["nightly"])} |
246 | | - |
247 | | - # The SF=100 entries map to the current nightly tpch-nvme / tpch-s3 rows by storage. |
248 | | - for resolved_id, bench in (("tpch-nvme-100", current[0]), ("tpch-s3-100", current[1])): |
249 | | - assert _target_pairs(resolved[resolved_id]["targets"]) == _target_pairs(bench["develop_targets"]) |
250 | | - assert resolved[resolved_id]["data_formats"] == bench["data_formats"] |
| 206 | +def test_develop_tpch_nvme_keeps_full_target_coverage() -> None: |
| 207 | + develop = {entry["id"]: entry for entry in resolve_matrix(PROFILES["develop"])} |
| 208 | + # TPC-H on NVMe compares both engines across the columnar formats plus arrow, lance, duckdb. |
| 209 | + assert _pairs(develop["tpch-nvme"]) == { |
| 210 | + ("datafusion", "arrow"), |
| 211 | + ("datafusion", "parquet"), |
| 212 | + ("datafusion", "vortex"), |
| 213 | + ("datafusion", "vortex-compact"), |
| 214 | + ("datafusion", "lance"), |
| 215 | + ("duckdb", "parquet"), |
| 216 | + ("duckdb", "vortex"), |
| 217 | + ("duckdb", "vortex-compact"), |
| 218 | + ("duckdb", "duckdb"), |
| 219 | + } |
| 220 | + assert develop["tpch-nvme"]["data_formats"] == ["parquet", "vortex", "vortex-compact", "duckdb"] |
| 221 | + |
| 222 | + |
| 223 | +def test_nightly_runs_default_targets_at_sf100() -> None: |
| 224 | + nightly = {entry["id"]: entry for entry in resolve_matrix(PROFILES["nightly"])} |
| 225 | + assert set(nightly) == {"tpch-nvme-100", "tpch-s3-100"} |
| 226 | + for entry in nightly.values(): |
| 227 | + assert _pairs(entry) == { |
| 228 | + ("datafusion", "parquet"), |
| 229 | + ("datafusion", "vortex"), |
| 230 | + ("duckdb", "parquet"), |
| 231 | + ("duckdb", "vortex"), |
| 232 | + } |
| 233 | + assert entry["scale_factor"] == "100.0" |
251 | 234 |
|
252 | 235 |
|
253 | 236 | # -------------------------------------------------------------------------------------------------- |
|
0 commit comments