Skip to content

Contract test suite (2/5): MDSplus tier - #96

Open
olivhoenen wants to merge 8 commits into
split85/1-contract-corefrom
split85/2-contract-mdsplus
Open

olivhoenen wants to merge 8 commits into
split85/1-contract-corefrom
split85/2-contract-mdsplus

Conversation

@olivhoenen

Copy link
Copy Markdown
Collaborator

Part of the split of #85 (Tests and Benchmarks for regression) into smaller, single-purpose PRs that are easier to review.

Adds the MDSplus contract-test tier: a tracer-bullet round trip, MDSplus joined to the parametrized fixtures, a real-DD-path datatype × rank matrix, a version-drift check and the MDSplus-specific surface (interpolation, timerange, segments, timebase cache). It also adds a Docker reference image (docker/mdsplus) and the non-blocking mdsplus-contract CI workflow. Tests and CI only.

Fork history: issues yohannmarguier#12 – yohannmarguier#18, fork PR yohannmarguier#22.

Stack position: 2/9; depends on #95.

Authorship: these commits are @yohannmarguier's, cherry-picked unchanged from his fork with git cherry-pick -x, so each one keeps its original author, date and message plus a (cherry picked from commit …) link back to the fork. Only conflicts with current develop and with the new commit order were resolved.

⚠️ Please merge with "Create a merge commit" or "Rebase and merge", not "Squash and merge": squashing would attribute Yohann's commits to the person who merges.

🤖 Generated with Claude Code

Stands up a real, runnable MDSplus in an aarch64 Docker image
(docker/mdsplus/), bakes a DD-4.1.1 model tree, and proves one equilibrium
scalar survives a write->read round trip through the public C ABI against
it -- lighting up the whole characterization stack (build gate, runtime
skip, CTest label) before any behavioral breadth is attempted per issue #12.

- tests/contract/test_mdsplus.cpp: MdsplusTracerBullet.ScalarSurvivesWriteThenRead,
  reusing equilibrium_seed.h's real DD path/value. Compiles out entirely
  unless AL_CONTRACT_HAVE_MDSPLUS is defined; GTEST_SKIP()s at runtime when
  MDSPLUS_MODELS_PATH is unset (TEST_STRATEGY.md D4: absent/skipped, never
  failed).
- tests/contract/CMakeLists.txt: defines AL_CONTRACT_HAVE_MDSPLUS when
  AL_BACKEND_MDSPLUS=ON, and adds a new `mdsplus` CTest label. Also documents
  (without fixing, out of scope) a pre-existing gtest_discover_tests defect
  found while wiring this up: multi-element LABELS lists silently collapse to
  their first token, so `ctest -L unit`/`-L integration` currently select
  nothing -- the new mdsplus pass sidesteps it with a single-element list.
- docker/mdsplus/: Ubuntu 24.04 (not the issue's suggested 22.04 -- MDSplus
  publishes no arm64 .debs for 22.04/20.04, empirically confirmed) with
  MDSplus, a JDK for the model-tree compiler, and the DD-4.1.1 bake via
  pip-installed imas_data_dictionary. Verified end-to-end: image builds,
  model bakes, contract suite builds with AL_BACKEND_MDSPLUS=ON, and
  `ctest -L mdsplus` passes.
- tests/contract/TRACEABILITY.md: new Part 4 section (MDSplus backend,
  compile-guarded tier) with the four-status scaffolding and the tracer
  bullet's first row.

(cherry picked from commit 353e4ca)
Adds MDSplus as a parameter/case to DataEntryModes, CapabilityMatrix,
Occurrences, and AosMatrix, reusing their existing test bodies, and
triages every resulting outcome into Part 4 of TRACEABILITY.md.

Empirically resolved against a real DD-4.1.1 model tree (docker/mdsplus/):
occurrence naming is "<ids>/<N>" (a third convention, same slash form as
ASCII); get_occurrences is real (gated on homogeneous_time being set);
list_filled_paths always throws (BACKEND_ERR); slice read/write genuinely
round-trip (supportsTimeDataInterpolation() is unconditionally true) while
timerange is refused (LOWLEVEL_ERR, supportsTimeRangeOperation() is
unconditionally false); and DataEntryModes' CREATE_PULSE guard matches
HDF5/Memory, not ASCII's defect.

AosMatrix and EquilibriumSeedMatrix hit the same divergence: MDSplus
resolves every path against its real DD-baked model tree, so their
synthetic/DD-agnostic field shapes ("elements"/"val", the seed's flat
profiles_1d/psi write, the generic constraints AOS) throw Node Not Found
at flush time. This is a legitimate storage-model difference, not a
defect, so AosMatrix's MDSplus case is skipped (via a new AosExpect::
Divergence, mirroring the existing KnownDefect skip) and MDSplus is left
out of EquilibriumSeedMatrix's backend list (like Flexbuffers already is,
for its own reason) rather than landing a permanently red test -- both are
documented in-place and in TRACEABILITY.md.

No genuine defect surfaced this round, so no new xfail pairs.

(cherry picked from commit ce74eba)
…ip logic

- EquilibriumSeedMatrix now takes an actual MDSplus instantiation (skipped
  in-place via GTEST_SKIP) instead of omitting it from kSeedBackends[],
  matching AosMatrix's divergence treatment and issue #12 Q5's explicit
  listing of this fixture as one MDSplus can join.
- Extract the repeated "skip if MDSPLUS_MODELS_PATH unset" block into a
  single AL_CONTRACT_SKIP_IF_MDSPLUS_UNCONFIGURED() macro in al_contract.h
  (a macro, not a function, since GTEST_SKIP()'s implicit return must
  unwind the calling SetUp()/TEST body directly); reuse it in
  test_mdsplus.cpp, test_pulse_lifecycle.cpp, test_capability_gated.cpp,
  and the new Occurrences test.
- Add `divergence` to TRACEABILITY.md's status vocabulary list (it was
  used as a live status without ever being defined there).
- Fix a stray escaped-slash in CMakeLists.txt's mdsplus TEST_FILTER that
  didn't match its own explanatory comment.

(cherry picked from commit 2c206a8)
RoundTripMatrix sweeps {CHAR,INTEGER,DOUBLE,COMPLEX} x rank against synthetic
opaque paths MDSplus structurally can't join. test_mdsplus_real_paths.cpp
curates one real DD-4.1.1 path per (type, rank) cell instead, sourced by
walking build-mdsplus/_deps/data-dictionary-src/IDSDef.xml directly (the
imas-dd MCP tool wasn't available in this session), spanning multiple IDSs.

32 cells: 18 covered (13 plain leaf, 5 via 1-3 level AOS descent reusing
AosMatrix's proven idiom), 1 divergence (CHAR r0 against a real STR_0D node:
MDSplus's text node is inherently string-shaped, so it cleanly refuses a
dim=0 read-back instead of HDF5's crash on the same synthetic shape), 13
terminal-gap (DD 4.1.1 has no field of that type/rank anywhere, e.g. no
STR_2D+, no CPX_0D). Verified against a real MDSplus tree in docker/mdsplus/:
ctest -L mdsplus is green (45/45).

(cherry picked from commit 09a4d61)
al_lowlevel.cpp's al_begin_dataentry_action compares the compiled backend
version against the version stored in an opened pulse and throws on
mismatch -- the one place MDSplus behavior is DD-version-sensitive today,
and the exact seam the north-star Phase-4 de-coupling rewrites. Forces
both the matching and mismatched cases through the C ABI: the mismatch is
produced by overwriting the pulse's VERSION:BACK_MAJOR tree node directly
via the raw MDSplus C++ API, which needed test-only find_package(MDSplus)
wiring on contract_tests (gated behind AL_BACKEND_MDSPLUS).

Unlike HDF5's identical drift-check gap (Part 2 row B, left as a terminal
gap because that suite has no HDF5 C API wiring), this closes cleanly for
MDSplus because its tier is already a separate, compile-guarded, Docker-
characterized target -- recorded as a finding in TRACEABILITY.md Part 4.

Verified against a real MDSplus backend (DD 4.1.1, docker/mdsplus/): both
new cases pass, and the full mdsplus-labeled suite (47 cases) stays green.

(cherry picked from commit 43d6849)
…review)

run_cell() used AL_ASSERT_OK (fatal) for each al_begin_arraystruct_action
in the aos_chain descent, so a failure on a non-first level would skip
the unwind of already-opened contexts, the outer action, and the pulse
close. Switch to AL_EXPECT_OK, matching AosMatrix.NestedWriteIterateRead's
established convention so descent failures still fall through to cleanup.

(cherry picked from commit f903fbf)
Characterizes struct-aware slice interpolation, timerange resampling,
segment-backed dynamic writes, and the timebase cache through the public
C ABI against a real DD-4.1.1 model tree (equilibrium/time_slice). Timerange
resampling has no unique MDSplus surface (supportsTimeRangeOperation() is
unconditionally false, already parity-pinned); struct-aware interpolation,
segment-backed appends, and the timebase cache are all covered.

Characterization surfaced one genuine crash defect: MDSplusBackend::writeData
dereferences size[0] unconditionally in its SLICE_OP branch, but the C ABI
passes size=nullptr for any dim=0 write, segfaulting on a scalar write inside
a slice action. Pinned as DISABLED_/tripwire per the suite's D2 discipline.
Closes TRACEABILITY.md Part 4's last deferred row.

(cherry picked from commit d4c5e89)
… leg (issue #18)

Closes the one capability with no MDSplus verdict at all (al_delete_data,
not joined to DeleteMatrix) as an explicit terminal-gap row, threads
"see Part 4" notes through the shared always-on rows in Part 1/2, and adds
a progress-summary line atop Part 4. Adds mdsplus-contract.yml, mirroring
the D7 sanitizer leg: continue-on-error, aarch64 runner, and a two-layer
cache (toolchain image + baked DD-4.1.1 model tree).

(cherry picked from commit 21bc634)

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants