-
Notifications
You must be signed in to change notification settings - Fork 2
Add a test suite to detect backwards-incompatibility of new changes #28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
8d70fe2
chore: treat ROOT files as binary in git
olantwin f995589
test: add version-agnostic reference-file writer
olantwin 261122e
test: freeze reference files for v0.1.0-v0.4.0 and main
olantwin f98aacf
test: read frozen reference files with the current model
olantwin 2b3fd67
test: gate schema changes behind a committed snapshot
olantwin 838b3d7
build: pin BUILD_TESTING=ON in the configure task
olantwin a0f1c56
build: freeze compatibility artefacts when cutting a release
olantwin efdb902
docs: document the backward-compatibility policy
olantwin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,3 @@ | ||
| * text=auto | ||
| *.sh text eol=lf | ||
| *.root binary |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| #!/usr/bin/env bash | ||
| # SPDX-License-Identifier: LGPL-3.0-or-later | ||
| # Copyright (C) CERN for the benefit of the SHiP Collaboration | ||
| # | ||
| # One-time backfill of the frozen compatibility reference files for releases | ||
| # that predate the compatibility suite (see tests/data/README.md). For each | ||
| # tag: build the tag's dictionary library, compile the CURRENT | ||
| # tests/write_reference.cpp against the TAG's headers (the old headers define | ||
| # the on-disk shape; reference_values.hpp adapts via __has_include and member | ||
| # detection), and write tests/data/reference_<tag>.root. | ||
| # | ||
| # Run from the repo root inside the pixi environment: | ||
| # pixi run bash scripts/backfill_reference_files.sh | ||
| # | ||
| # Kept for provenance; releases from v0.5.0 on write their reference file at | ||
| # release time via scripts/release.sh instead. | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| REPO="$(git rev-parse --show-toplevel)" | ||
| mkdir -p "${REPO}/tests/data" | ||
|
|
||
| for tag in v0.1.0 v0.2.0 v0.3.0 v0.4.0; do | ||
| out="${REPO}/tests/data/reference_${tag}.root" | ||
| if [[ -e "${out}" ]]; then | ||
| echo "skip ${tag}: ${out} already exists (frozen files are never rewritten)" | ||
| continue | ||
| fi | ||
| wt="$(mktemp -d)/data-model-${tag}" | ||
| tmp="${out}.tmp" | ||
| # Never leave a partial file at the frozen path (the skip-check above | ||
| # would treat it as frozen) or a registered worktree behind on failure. | ||
| trap 'rm -f "${tmp}"; git worktree remove --force "${wt}" 2>/dev/null || true' EXIT | ||
| git worktree add "${wt}" "${tag}" | ||
| cmake -S "${wt}" -B "${wt}/build" -G Ninja \ | ||
| -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=OFF | ||
| cmake --build "${wt}/build" -j | ||
| # Tag headers first on the include path; reference_values.hpp resolves | ||
| # next to write_reference.cpp, i.e. to the current repo's copy. | ||
| "${CXX:-g++}" -std=c++23 -I "${wt}/include" $(root-config --cflags) \ | ||
| "${REPO}/tests/write_reference.cpp" -o "${wt}/build/write_reference" \ | ||
| $(root-config --libs) -lROOTNTuple \ | ||
| -L "${wt}/build" -Wl,--no-as-needed -lSHiPDataModel -Wl,--as-needed \ | ||
| -Wl,-rpath,"${wt}/build" | ||
| "${wt}/build/write_reference" "${tmp}" | ||
| mv "${tmp}" "${out}" | ||
| git worktree remove --force "${wt}" | ||
| trap - EXIT | ||
| done |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| # Backward-compatibility reference data | ||
|
|
||
| This directory holds the on-disk compatibility contract of the SHiP data | ||
| model. Two independent safety nets are exercised by ctest (part of | ||
| `pixi run test` and CI): | ||
|
|
||
| 1. **Compat read tests** (`compat_read_<version>`): every reference file | ||
| must be readable with the *current* library, materialized into the | ||
| current structs, with all values matching the canonical recipe. Members | ||
| that did not exist in the writing version must read back | ||
| default-initialized (ROOT RNTuple automatic schema evolution). | ||
| 2. **Schema snapshot** (`schema_snapshot`): `schema_snapshot.txt` is a text | ||
| dump of the persistent schema (TClass layout of every dictionary class + | ||
| the RNTuple field tree). CI fails on *any* schema change — even a | ||
| backward-compatible one — until the snapshot is deliberately regenerated | ||
| in the same PR, so every schema change is a conscious, reviewable | ||
| decision. | ||
|
|
||
| ## Files | ||
|
|
||
| - `reference_v<X.Y.Z>.root` — frozen forever, **never modified or | ||
| regenerated**. Written at release time by `scripts/release.sh` from | ||
| exactly the tagged code with the ROOT version pinned in `pixi.lock` at | ||
| that moment, so it captures both the schema and the writing ROOT. | ||
| Exception: the files for v0.1.0–v0.4.0 predate this suite and were | ||
| backfilled with `scripts/backfill_reference_files.sh` — they were written | ||
| by each tag's *headers* (defining the on-disk schema) but by ROOT 6.40.02, | ||
| not the historical ROOT versions. | ||
| - `reference_head.root` — tracks `main`; asserts "current code reads the | ||
| current schema". Regenerated in the same PR as any event-model change. | ||
| - `schema_snapshot.txt` — committed schema dump, see above. | ||
|
|
||
| Each file is an RNTuple named `events` with 2 entries and top-level fields | ||
| `event_header` (v0.4.0+), `mcParticles`, `simHits`, `simParticles`, | ||
| `recParticles`, `simResult`. | ||
|
|
||
| ## When a compat test fails in your PR | ||
|
|
||
| - `schema_snapshot` fails, `compat_read_*` pass: you changed the persistent | ||
| schema in a backward-compatible way (e.g. added a member). If intentional, | ||
| run and commit in the same PR: | ||
|
|
||
| ```sh | ||
| pixi run update-schema-snapshot | ||
| pixi run update-reference-head | ||
| ``` | ||
|
|
||
| This is at least a **minor** version bump. | ||
| - `compat_read_v*` fails: your change breaks reading of existing files | ||
| (e.g. renaming a member silently drops its on-disk values — RNTuple | ||
| matches members by name). Either make the change compatible (e.g. an | ||
| [I/O customization rule](https://root.cern/doc/master/md_tree_2ntuple_2doc_2SchemaEvolution.html) | ||
| mapping the old name), or accept it as a **breaking change**: mark the | ||
| commit `!`/`BREAKING CHANGE` (major version bump) and adjust the | ||
| expectations in `tests/test_read_reference.cpp` (masking table) — never by | ||
| editing the frozen files. | ||
| - `compat_read_head` fails but frozen versions pass: the current schema and | ||
| `reference_head.root` are out of sync — run `pixi run | ||
| update-reference-head` (plus the snapshot) in this PR. | ||
|
|
||
| ## Value recipe | ||
|
|
||
| Expected values are defined in `tests/reference_values.hpp` and are part of | ||
| the contract (a future non-C++ reader can check against the same formulas). | ||
| For members that existed at v0.1.0 they equal the `SHiP::test::make*` | ||
| generators in `tests/test_utils.hpp`; members added later have their own | ||
| formulas there (e.g. `SimHit::geometryNodeId = 900 + 7*i + offset`, | ||
| `RecParticle::hits` filled from `makeSimHits(offset + 2)`). Per entry | ||
| `e` (0-based): field offsets are `e` for the top-level collections and | ||
| `e + 5` inside `simResult`; each collection has 3 elements. A reference file | ||
| written by version V contains values for exactly the members existing in V; | ||
| newer members read back default-initialized and are masked accordingly in | ||
| `test_read_reference.cpp`. |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.