feat(xce-harness-component): relocate xce_test into standalone harness component
Move xce_test's 15 production sources + headers from src/controller/testsuite/ into a new src/harness/ component with its own meson.build, and strip every now-dangling controller-side reference (11 controller_unit_test_src entries, 4 standalone test-binary blocks, 11 controller_test.c extern/RUN_TEST lines) so the controller build is never left broken. Fixes a broken relative-symlink bridge (xce_test_controller_link) added to keep two controller-embedded tests (test_test_cli.c, test_xcetest_process_entry.c) finding the relocated xce_test binary until task 2.1 moves them too. Discovered and documented in design.md: four controller-domain regression tests call functions directly from four of xce_test's own files, requiring controller_unit_test to permanently recompile them from src/harness/ — a real dependency neither the original discovery nor design audit caught. controller_unit_test: 1228 Tests 0 Failures 0 Ignored (verified via the Unity binary's own printed summary line, not just meson's aggregate count). Task 1.1 of xce-harness-component. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
This commit is contained in:
parent
b8ef82c1b2
commit
cf55d691de
36 changed files with 550 additions and 180 deletions
348
.kiro/specs/xce-harness-component/design.md
Normal file
348
.kiro/specs/xce-harness-component/design.md
Normal file
|
|
@ -0,0 +1,348 @@
|
|||
# Design Document: xce-harness-component
|
||||
|
||||
## Overview
|
||||
|
||||
**Purpose**: This feature relocates `xce_test` — an already-decoupled wire-protocol test client — out of `src/controller/testsuite/` into its own standalone `src/harness/` component, giving it an independent build target, its own unit-test binary, and its own documentation, with zero change to its runtime behavior.
|
||||
|
||||
**Users**: XCE engineers who build the project, run HA soak / multi-host / resource-verification workflows, or maintain `xce_test` itself.
|
||||
|
||||
**Impact**: Changes `src/controller/meson.build` (removes the `xce_test` executable, 13 test-file entries from `controller_unit_test_src`, and 4 standalone test-binary blocks), `controller_test.c` (removes 13 extern/RUN_TEST entries), `src/tools/xce-build.sh` (decouples the `controller` build case, adds a `harness` case), four downstream skills, and three steering/documentation files. No change to `xce_test`'s command surface, output, or the controller's own domain test coverage.
|
||||
|
||||
### Goals
|
||||
- `xce_test` becomes buildable, testable, and documented as an independent component (`src/harness/`).
|
||||
- Building `controller` no longer implicitly builds `xce_test`, and vice versa.
|
||||
- Every white-box/integration test that validates one of xce_test's own source files keeps running, now attributed to the harness's own test suite.
|
||||
- Every downstream workflow that assumed the old coupling keeps working.
|
||||
|
||||
### Non-Goals
|
||||
- No new `xce_test` command, flag, or output change.
|
||||
- No rename of the `xce_test` binary.
|
||||
- No change to `xcecli`, `xceadmin`, the Go frontend, or controller's own domain unit tests (HA, persistence, commit, replication, job).
|
||||
- No nix/AppImage packaging change (xce_test is not part of either today).
|
||||
|
||||
## Boundary Commitments
|
||||
|
||||
### This Spec Owns
|
||||
- The `src/harness/` component directory: its `meson.build`, `CLAUDE.md`, production sources, and test sources.
|
||||
- The `xce_test` executable and its five test binaries (`harness_unit_test`, `resval_typeresolve_unit_test`, `joblist_display_unit_test`, `join_worker_args_unit_test`, `listrow_json_unit_test`) and their meson `test()` registration.
|
||||
- The `controller)` and new `harness)` cases in `src/tools/xce-build.sh`, and root `CLAUDE.md`'s component list.
|
||||
- The relocation of the one genuinely shared header, `ctrlstatus_fmt.h`, to `src/include/xce/` (the existing cross-daemon shared-header prefix, e.g. `cluster.h`, `types.h`, `errnox.h` — not the main libxce API headers).
|
||||
- Updates to the four downstream skills (`xce-test-ha`, `xce-deploy-ha`, `xce-test-multihost`, `xce-test-resources`) so they no longer assume the old coupling.
|
||||
- Updates to `structure.md` and `build-deployment.md` describing the new component.
|
||||
|
||||
### Out of Boundary
|
||||
- Any xce_test behavioral change (owned by `xce-test-cli-ux`, `xce-test-e2e-primitives`, `xce-test-rc-file`, and the still-open roadmap item for further WAL/snapshot inspectors).
|
||||
- Controller's own domain test files (`test_ha_*.c`, `test_persist_*.c`, `test_commit_*.c`, etc.) — these stay in `src/controller/testsuite/` untouched.
|
||||
- Any change to `xcecli`/`xceadmin`/Go frontend build wiring.
|
||||
- Re-litigating which controller tests belong where beyond the 17 files whose production counterpart is physically moving.
|
||||
|
||||
### Allowed Dependencies
|
||||
- The harness component may depend on libxce (`src/lib/`) and its existing dependency set (`librtti`, `struct2json`, `libedit`, `tinylog`, `zlib`, `c_capnproto`, `openssl`, `thread`) — unchanged from today.
|
||||
- The harness component may depend on `src/include/xce/ctrlstatus_fmt.h` once promoted there — the one small, header-only, link-free utility shared with controller's own test suite. Placed under the existing `xce/` cross-daemon shared-header prefix (not bare `src/include/`) so it doesn't read as part of libxce's real runtime API surface. This is the **only** sanctioned harness→controller-adjacent dependency; no other controller header or source file may be referenced.
|
||||
- `harness_unit_test` may declare a build-order dependency on the `xce_test` executable target (two of its tests spawn that binary directly) — this is an intra-harness dependency, not a cross-component one.
|
||||
- **Sanctioned exception, discovered during task 1.1 (not part of the original design)**: `controller_unit_test` may compile `waldump.c`, `walcompare.c`, `snapverify.c`, and `snapdiff.c` a second time directly from `src/harness/`, because four controller-domain regression tests (`test_config_repl.c`, `test_ha_core_safety.c`, `test_upgrade_snapshot_apply.c`, `test_bug857_regression.c`) call their functions directly and are themselves out of this spec's boundary (controller's own domain tests, untouched). This is a **controller→harness** dependency — the reverse direction from the `ctrlstatus_fmt.h` exception above — and does not violate Requirement 1.4 (which constrains harness's dependencies on controller, not the reverse). It is permanent, not a migration artifact to be removed by a later task.
|
||||
|
||||
### Revalidation Triggers
|
||||
- Any future xce_test source file that grows a `#include` of a controller-private header (anything under `src/controller/` other than `src/include/xce/ctrlstatus_fmt.h`) breaks this spec's boundary and must be caught in review.
|
||||
- Any new downstream skill/script that assumes xce_test exists without an explicit harness-build step must be added to Requirement 5's coverage.
|
||||
- If `ctrlstatus_fmt.h` ever grows beyond a header-only `static inline` function (e.g. needs a `.c` file with real controller state), the shared-header decision must be revisited.
|
||||
|
||||
### Invariant Cross-Check
|
||||
This spec touches zero controller/scheduler runtime code paths (async I/O thread-role placement, fail-loud/never-self-exit process lifecycle, consensus/replication safety, commit-before-materialize ordering) and adds no persistence/save-restore mechanism — it moves build/test infrastructure and one header-only formatting helper only. `xce-audit-invariants`' controller/scheduler dimension lists and `persistence.md`'s save/restore field-completeness rule are therefore both **not applicable**; noted here so a later reviewer does not have to re-derive that determination.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Existing Architecture Analysis
|
||||
|
||||
Today, `xce_test`'s 15 source files live in `src/controller/testsuite/` and are compiled into **six** separate binaries by `src/controller/meson.build`: the `xce_test` executable itself; 10 of the 15 production files recompiled a second time into `controller_unit_test` alongside their white-box tests (plus 3 more test files with no separate production pairing — `test_xcetest_interrupt.c`, `test_test_cli.c`, `test_xcetest_process_entry.c` — 13 test files total in that group); and the remaining 4 production files (`resval_typeresolve.c`, `joblist_display.c`, `join_worker_args.c`, `listrow_json.c`) each recompiled into their own already-standalone test binary (`resval_typeresolve_unit_test`, `joblist_display_unit_test`, `join_worker_args_unit_test`, `listrow_json_unit_test`). `src/tools/xce-build.sh`'s `controller)` case compiles all of these together and is the sole mechanism that currently makes `xce_test` buildable. A confirmed dependency audit (see `research.md`) found one genuinely shared header (`ctrlstatus_fmt.h`, header-only) between controller's own tests and xce_test's sources. **Correction discovered during task 1.1 implementation**: the audit's "already fully decoupled at the source level" claim was incomplete — four controller-domain regression tests (`test_config_repl.c`, `test_ha_core_safety.c`, `test_upgrade_snapshot_apply.c`, `test_bug857_regression.c`) call functions directly from four of xce_test's own production files (`snapdiff_paths`/`waldump_path_visit`/`walcompare`/`snapverify_path`, i.e. `waldump.c`, `walcompare.c`, `snapverify.c`, `snapdiff.c`). This is a real, permanent controller→harness compile dependency, not a temporary migration artifact — `controller_unit_test_src` now recompiles those four files a second time via a relative path into `src/harness/`. See the updated Allowed Dependencies below. This spec otherwise formalizes the harness/controller split into the build graph and directory layout, preserving the existing 5-test-binary shape (`harness_unit_test` plus the four already-standalone binaries) rather than consolidating it.
|
||||
|
||||
### Architecture Pattern & Boundary Map
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph Before
|
||||
CtrlBuildOld[controller build case]
|
||||
XceTestOld[xce_test executable]
|
||||
CtrlUnitOld[controller_unit_test executable]
|
||||
SharedHeaderOld[ctrlstatus_fmt header]
|
||||
CtrlBuildOld --> XceTestOld
|
||||
CtrlBuildOld --> CtrlUnitOld
|
||||
CtrlUnitOld --> SharedHeaderOld
|
||||
XceTestOld --> SharedHeaderOld
|
||||
end
|
||||
subgraph After
|
||||
CtrlBuildNew[controller build case]
|
||||
HarnessBuildNew[harness build case]
|
||||
XceTestNew[xce_test executable]
|
||||
HarnessUnitNew[harness_unit_test executable]
|
||||
CtrlUnitNew[controller_unit_test executable]
|
||||
SharedHeaderNew[shared include ctrlstatus_fmt]
|
||||
CtrlBuildNew --> CtrlUnitNew
|
||||
HarnessBuildNew --> XceTestNew
|
||||
HarnessBuildNew --> HarnessUnitNew
|
||||
HarnessUnitNew --> XceTestNew
|
||||
HarnessUnitNew --> SharedHeaderNew
|
||||
CtrlUnitNew --> SharedHeaderNew
|
||||
end
|
||||
```
|
||||
|
||||
**Architecture Integration**:
|
||||
- **Selected pattern**: Directory/build-graph split following the project's existing C-daemon component pattern, with the flat-root variant controller already established as an exception.
|
||||
- **Domain/feature boundaries**: harness owns everything that is xce_test-specific (its 15 sources + 17 tests, across 5 test binaries — see below); controller keeps everything that is controller-domain (its own daemon sources + its own domain tests); the one shared header moves to the pre-existing neutral `xce/` shared-header prefix (`src/include/xce/`) rather than living inside either component.
|
||||
- **Existing patterns preserved**: component-per-directory with its own `meson.build`/`CLAUDE.md`; `/xce-build <component>` dispatch pattern in `xce-build.sh`; meson `test(..., suite: '<name>')` registration pattern; the project's existing practice of splitting a lean, dependency-light module into its own standalone Unity binary rather than folding it into one monolith (already used today for `resval_typeresolve_unit_test`, `joblist_display_unit_test`, `join_worker_args_unit_test`, `listrow_json_unit_test`) — **preserved as-is, not consolidated** (user decision, validate-design review).
|
||||
- **New components rationale**: `src/harness/` is needed because no existing component directory can host xce_test without re-creating the same coupling this spec removes. Five distinct test-binary targets move with it: the ~13-file group that lives inside `controller_unit_test` today becomes a new `harness_unit_test` binary (needs its own new Unity runner, since `controller_test.c` stays with controller's own remaining tests), and the four already-standalone binaries (`resval_typeresolve_unit_test`, `joblist_display_unit_test`, `join_worker_args_unit_test`, `listrow_json_unit_test`) relocate verbatim with only their `suite:` tag changing from `controller` to `harness`.
|
||||
- **Steering compliance**: matches `structure.md`'s "component-per-directory, own Meson build + CLAUDE.md" philosophy; matches `build-deployment.md`'s three-part `setup_build` / `meson compile` / `meson test` dispatch pattern per component.
|
||||
|
||||
### Technology Stack
|
||||
|
||||
| Layer | Choice / Version | Role in Feature | Notes |
|
||||
|-------|------------------|------------------|-------|
|
||||
| Build | Meson ≥ 1.5 (unchanged) | New `src/harness/meson.build`; `subdir('harness')` added to `src/meson.build` | Same build system, no version change |
|
||||
| Build orchestration | `src/tools/xce-build.sh` (bash) | New `harness)` case; `controller)` case trimmed | Mirrors the existing `scheduler)`/`worker)` case template exactly |
|
||||
| C toolchain | gnu17 (unchanged) | Harness sources compile with the same standard/flags as controller | No new dependency |
|
||||
| Test framework | Unity (unchanged) | New `harness_unit_test` Unity runner, modeled on `controller_test.c` | Reuses the existing `-DXCE_TESTING` pattern where applicable |
|
||||
|
||||
No new external dependencies are introduced; the harness reuses xce_test's existing dependency set unchanged (`libxce`, `librtti`, `struct2json`, `libedit`, `tinylog`, `zlib`, `c_capnproto`, `openssl`, `thread`).
|
||||
|
||||
## File Structure Plan
|
||||
|
||||
### Directory Structure
|
||||
```
|
||||
src/
|
||||
├── harness/ # NEW component (this spec)
|
||||
│ ├── meson.build # xce_test executable + FIVE test executables (see below)
|
||||
│ ├── CLAUDE.md # component guide
|
||||
│ ├── include/ # the 15 xce_test-local headers (waldump.h, rcfile.h, ...)
|
||||
│ ├── test.c # REPL/dispatch entry point (unchanged content, new location)
|
||||
│ ├── waldump.c ... listrow_json.c # remaining 14 production files (unchanged content)
|
||||
│ └── testsuite/ # the 17 white-box / integration test files, across 5 binaries:
|
||||
│ ├── harness_test.c # NEW Unity runner (modeled on controller_test.c) for the
|
||||
│ │ # 13-file group below -- this is the ONE binary that is new
|
||||
│ ├── test_waldump.c, test_walcompare.c, test_snapverify.c, test_snapdiff.c,
|
||||
│ │ test_configcompare.c, test_rcfile.c, test_flagspec.c, test_xcetest_interrupt.c,
|
||||
│ │ test_interruptcall.c, test_confirm.c, test_listfmt_json.c, test_test_cli.c,
|
||||
│ │ test_xcetest_process_entry.c # 13 files -> new "harness_unit_test" binary
|
||||
│ ├── test_resval_typeresolve.c # -> "resval_typeresolve_unit_test" (relocated as-is)
|
||||
│ ├── test_joblist_display.c # -> "joblist_display_unit_test" (relocated as-is)
|
||||
│ ├── test_join_worker_args.c # -> "join_worker_args_unit_test" (relocated as-is)
|
||||
│ └── test_listrow_json.c # -> "listrow_json_unit_test" (relocated as-is)
|
||||
├── controller/
|
||||
│ ├── meson.build # MODIFIED: remove xce_test_src/xce_test_deps/xce_test executable;
|
||||
│ │ # remove the moved entries from controller_unit_test_src;
|
||||
│ │ # remove the 4 standalone test-binary blocks that move
|
||||
│ │ # (resval_typeresolve_unit_test, joblist_display_unit_test,
|
||||
│ │ # join_worker_args_unit_test, listrow_json_unit_test)
|
||||
│ └── testsuite/
|
||||
│ └── controller_test.c # MODIFIED: remove the 13 extern + RUN_TEST entries for the
|
||||
│ # functions moving into the new harness_unit_test runner
|
||||
│ # (test_ctrlstatus stays -- it tests controller's own ctrlstatus.c)
|
||||
└── include/
|
||||
└── xce/
|
||||
└── ctrlstatus_fmt.h # MODIFIED location: promoted here from controller/testsuite/
|
||||
```
|
||||
|
||||
> `src/harness/` follows controller's own documented flat-root exception (files directly in the component root, not nested under `src/`) rather than the general worker/scheduler `src/`+`include/` nested pattern — see `research.md`'s Architecture Pattern Evaluation for why.
|
||||
|
||||
### Modified Files
|
||||
- `src/controller/meson.build` — remove the `xce_test_src`/`xce_test_deps`/`xce_test` executable block; remove the 13 harness-owned entries from `controller_unit_test_src`; remove the four standalone test-binary blocks that move (`resval_typeresolve_unit_test`, `joblist_display_unit_test`, `join_worker_args_unit_test`, `listrow_json_unit_test`, each currently its own `executable()`+`test()` pair).
|
||||
- `src/controller/testsuite/controller_test.c` — remove the 13 `extern`/`RUN_TEST` entries (lines 68-80 today: `test_waldump` through `test_test_cli`) for the functions moving into the new harness Unity runner; `test_ctrlstatus`'s extern/RUN_TEST stays (it tests controller's own `ctrlstatus.c`).
|
||||
- `src/meson.build` — add `subdir('harness')`.
|
||||
- `src/tools/xce-build.sh:292-299` — drop `controller/xce_test` from the `controller)` case's compile target list; add a new `harness)` case following the identical `setup_build` / `meson compile` / conditional `meson test --suite harness` template already used by `scheduler)`/`worker)`.
|
||||
- `CLAUDE.md` (root) — add `harness` to the `/xce-build` component list; add `src/harness/` to Subdirectory Guidelines pointing at its new `CLAUDE.md`.
|
||||
- `.kiro/steering/build-deployment.md` — remove the "controller always builds xce_test" claim (current line 24); add `harness` to the `/xce-build` command table and the Meson Structure tree.
|
||||
- `.kiro/steering/structure.md` — add `harness` to the component table and to the flat-root Exceptions list alongside controller.
|
||||
- `.claude/skills/xce-test-ha/run-ha-soak.sh`, `.claude/skills/xce-test-ha/SKILL.md` — ensure the harness is built before the soak runs.
|
||||
- `.claude/skills/xce-deploy-ha/SKILL.md` — document the harness under the existing soft-skip pattern (same treatment as worker/scheduler/xceadmin).
|
||||
- `.claude/skills/xce-test-multihost/run-multihost-verify.sh`, `.claude/skills/xce-test-multihost/SKILL.md` — ensure the harness is built before verification runs.
|
||||
- `.claude/skills/xce-test-resources/run-resource-verify.sh`, `.claude/skills/xce-test-resources/SKILL.md` — ensure the harness is built before verification runs.
|
||||
|
||||
## System Flows
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Engineer
|
||||
participant XceBuild as xce build script
|
||||
participant Meson
|
||||
participant XceTestBin as xce_test binary
|
||||
participant HarnessTests as harness_unit_test
|
||||
|
||||
Engineer->>XceBuild: request harness build
|
||||
XceBuild->>Meson: compile harness targets
|
||||
Meson->>XceTestBin: build xce_test executable
|
||||
Meson->>HarnessTests: build harness_unit_test
|
||||
Note over Meson,HarnessTests: harness_unit_test depends on<br/>XceTestBin already being built
|
||||
XceBuild->>Meson: run test suite harness
|
||||
HarnessTests->>XceTestBin: spawn over pty for CLI and process entry tests
|
||||
HarnessTests-->>XceBuild: pass fail report under suite harness
|
||||
```
|
||||
|
||||
**Key decision**: `harness_unit_test`'s two subprocess-spawning tests (`test_test_cli.c`, `test_xcetest_process_entry.c`) require `xce_test` to already be built — `src/harness/meson.build` declares this as an explicit target dependency so meson's own build graph enforces the order, rather than relying on incidental compile-order luck.
|
||||
|
||||
## Requirements Traceability
|
||||
|
||||
| Requirement | Summary | Components | Flows |
|
||||
|-------------|---------|------------|-------|
|
||||
| 1.1, 1.2 | Standalone directory matching worker/scheduler-style structure | src/harness/ layout | — |
|
||||
| 1.3 | Binary name unchanged | xce_test executable target | — |
|
||||
| 1.4 | No controller-private dependency | ctrlstatus_fmt.h relocation to src/include/xce/ | — |
|
||||
| 2.1, 2.2 | Independent, decoupled build | xce-build.sh harness)/controller) cases | Build & test sequence |
|
||||
| 2.3 | Harness is a selectable component | xce-build.sh, root CLAUDE.md | — |
|
||||
| 2.4 | All-components build includes harness | src/meson.build subdir('harness') | — |
|
||||
| 3.1, 3.2, 3.4 | Unit tests move and report under harness's own suite, as 5 separate binaries | harness unit-test suite (5 binaries), meson test(suite: harness) | Build & test sequence |
|
||||
| 3.3 | Controller's own suite unaffected | controller_unit_test + controller_test.c (trimmed, not gutted) | — |
|
||||
| 4.1, 4.2, 4.3 | Behavioral parity | xce_test executable (content unchanged) | — |
|
||||
| 5.1, 5.2, 5.3 | Downstream workflows keep working | xce-test-ha, xce-deploy-ha, xce-test-multihost, xce-test-resources | — |
|
||||
| 5.4 | Clear, actionable failure when harness missing | same four skills | — |
|
||||
| 6.1, 6.2, 6.3 | Documentation consistency | src/harness/CLAUDE.md, build-deployment.md, structure.md | — |
|
||||
|
||||
## Components and Interfaces
|
||||
|
||||
| Component | Domain/Layer | Intent | Req Coverage | Key Dependencies (P0/P1) | Contracts |
|
||||
|-----------|--------------|--------|---------------|--------------------------|-----------|
|
||||
| harness component (xce_test) | C CLI / build | Standalone wire-protocol test client, structurally unchanged | 1.1-1.4, 4.1-4.3 | libxce (P0), src/include/xce/ctrlstatus_fmt.h (P1) | Batch |
|
||||
| harness unit-test suite (5 binaries) | C test binaries | Runs the 17 moved white-box/integration tests, preserved as 5 separate binaries (not consolidated) under the `harness` suite | 3.1-3.4 | xce_test executable (P0, build-order, `harness_unit_test` only) | Batch |
|
||||
| xce-build.sh dispatch | Build orchestration | Independent `harness` build entry, decoupled `controller` entry | 2.1-2.4 | Meson (P0) | Batch |
|
||||
| Downstream verification skills | Workflow automation | Build/verify harness exists before use, with a clear failure path | 5.1-5.4 | harness component (P0) | Batch |
|
||||
| Component/steering docs | Documentation | Describe harness accurately | 6.1-6.3 | — | — |
|
||||
|
||||
### Build & Test Domain
|
||||
|
||||
#### Harness Component (xce_test)
|
||||
|
||||
| Field | Detail |
|
||||
|-------|--------|
|
||||
| Intent | Wire-protocol REPL test client, relocated with no behavioral change |
|
||||
| Requirements | 1.1, 1.2, 1.3, 1.4, 4.1, 4.2, 4.3 |
|
||||
|
||||
**Responsibilities & Constraints**
|
||||
- Owns all 15 xce_test production source files and their headers.
|
||||
- Must not include any controller-private header or source file (Allowed Dependencies lists the one sanctioned exception).
|
||||
- Must produce byte-identical CLI/REPL output to today's binary.
|
||||
|
||||
**Dependencies**
|
||||
- Inbound: `harness_unit_test` (P0) — two of its tests spawn this binary directly.
|
||||
- Outbound: libxce (P0), `src/include/xce/ctrlstatus_fmt.h` (P1, via `test.c`/`joblist_display.c`).
|
||||
- External: libedit, OpenSSL, zlib, Cap'n Proto runtime — unchanged from today.
|
||||
|
||||
**Contracts**: Batch [x]
|
||||
|
||||
##### Batch / Job Contract
|
||||
- Trigger: `/xce-build harness` (new) or `/xce-build all`.
|
||||
- Input / validation: none beyond today's existing CLI argument parsing (unchanged).
|
||||
- Output / destination: `<build_dir>/harness/xce_test` binary.
|
||||
- Idempotency & recovery: a rebuild simply recompiles; no state to recover.
|
||||
|
||||
**Implementation Notes**
|
||||
- Integration: `src/harness/meson.build` defines this executable exactly as `src/controller/meson.build` does today, just relocated.
|
||||
- Validation: rerun the existing `xce-test-cli-ux`/`xce-test-e2e-primitives`/`xce-test-rc-file` test coverage against the relocated binary and diff output against a pre-move capture.
|
||||
- Risks: none beyond the header relocation already resolved in `research.md`.
|
||||
|
||||
#### Harness Unit-Test Suite (5 binaries)
|
||||
|
||||
| Field | Detail |
|
||||
|-------|--------|
|
||||
| Intent | Unity-based unit/integration test coverage for harness's own sources, preserved as 5 separate binaries matching today's structure (validate-design review: consolidation rejected in favor of file-for-file fidelity) |
|
||||
| Requirements | 3.1, 3.2, 3.3, 3.4 |
|
||||
|
||||
**Responsibilities & Constraints**
|
||||
- **`harness_unit_test`** (new binary, new name) — the 13 files that live inside `controller_unit_test` today (`test_waldump.c` through `test_test_cli.c`, listed in the File Structure Plan) plus their production pairs, with a **new** Unity runner `harness_test.c` (modeled on `controller_test.c`, carrying only these 13 `extern`/`RUN_TEST` entries).
|
||||
- **`resval_typeresolve_unit_test`**, **`joblist_display_unit_test`**, **`join_worker_args_unit_test`**, **`listrow_json_unit_test`** — relocate verbatim from `src/controller/meson.build` (each already a self-contained 2-3 file `executable()`/`test()` pair with no shared runner); only their `include_directories`/`dependencies` source path and `suite:` tag change (`controller` → `harness`).
|
||||
- All five register under the meson suite name `harness`, distinct from `controller`.
|
||||
- `harness_unit_test` specifically must not silently pass if the `xce_test` executable its two pty-spawning tests (`test_test_cli.c`, `test_xcetest_process_entry.c`) rely on is stale or missing — that build-order dependency must be a hard prerequisite, not an informal expectation. The other four binaries have no such dependency (they never spawn `xce_test`).
|
||||
|
||||
**Dependencies**
|
||||
- Inbound: none (leaf targets).
|
||||
- Outbound: `xce_test` executable (P0, build-order — `harness_unit_test` only, declared via meson's target-dependency mechanism), `src/include/xce/ctrlstatus_fmt.h` (P1 — `joblist_display_unit_test` only, since `joblist_display.c` is its production file).
|
||||
|
||||
**Contracts**: Batch [x]
|
||||
|
||||
##### Batch / Job Contract
|
||||
- Trigger: `/xce-build harness`'s test step, or `meson test -C <build_dir> --suite harness`.
|
||||
- Input / validation: none.
|
||||
- Output / destination: Unity `PASS`/`FAIL` report per test, aggregate suite result per binary.
|
||||
- Idempotency & recovery: rerunning is safe; no persisted state.
|
||||
|
||||
**Implementation Notes**
|
||||
- Integration: the four standalone binaries keep the exact registration pattern they already have today (`test('<name> test', <binary>, suite: 'harness', timeout: 60, env: [...])`); `harness_unit_test` mirrors `controller_unit_test`'s own pattern (`suite: 'harness'`, `timeout: 300`).
|
||||
- Validation: verify via meson's own dependency graph (not just documentation) that `harness_unit_test` cannot start before `xce_test` finishes building; per `testing.md`'s standing rule, cross-check each standalone binary's own stdout `:FAIL:` count, not just meson's aggregate `Ok:N Fail:0`, before treating a run as green.
|
||||
- Risks: a future edit could accidentally drop the build-order dependency — `research.md`'s follow-up recommends one regression check that the two spawning tests fail loudly (not silently pass) if `xce_test` is absent. A second risk specific to this corrected design: missing one of the four standalone `executable()`/`test()` blocks during the move — mitigated by naming all four explicitly here and in the File Structure Plan rather than referring to "the test files" generically.
|
||||
|
||||
#### xce-build.sh Dispatch
|
||||
|
||||
| Field | Detail |
|
||||
|-------|--------|
|
||||
| Intent | Independent `harness` build entry point; `controller` no longer produces xce_test as a side effect |
|
||||
| Requirements | 2.1, 2.2, 2.3, 2.4 |
|
||||
|
||||
**Responsibilities & Constraints**
|
||||
- `controller)` case (`xce-build.sh:292-299`) drops `controller/xce_test` from its compile target list.
|
||||
- New `harness)` case follows the identical three-part template already used by `scheduler)`/`worker)`: `setup_build`, an explicit `meson compile` target list (`harness/xce_test harness/harness_unit_test`), then a conditional `meson test --suite harness`.
|
||||
- `all)` requires no code change — it already compiles with no explicit target list, so it picks up the new `subdir('harness')` automatically.
|
||||
|
||||
**Dependencies**
|
||||
- Inbound: engineers, the four downstream verification skills.
|
||||
- Outbound: Meson (P0).
|
||||
|
||||
**Contracts**: Batch [x]
|
||||
|
||||
##### Batch / Job Contract
|
||||
- Trigger: `/xce-build harness [profile]`, `/xce-build controller [profile]`, `/xce-build all [profile]`.
|
||||
- Input / validation: existing profile validation (`asan`/`debug`/`release`) — unchanged.
|
||||
- Output / destination: component-scoped binaries under the chosen build dir.
|
||||
- Idempotency & recovery: same full-wipe-vs-`--incremental` semantics that already exist for every other component pair (`build-deployment.md` bug-1565 note) — unchanged behavior, now also applicable to the harness/controller pair.
|
||||
|
||||
**Implementation Notes**
|
||||
- Integration: no new orchestration concept — this is the same case-block template every other component already uses.
|
||||
- Validation: run `/xce-build harness` alone (no prior controller build) and confirm `xce_test` is produced; run `/xce-build controller` alone and confirm `xce_test` is absent; run `/xce-build all` and confirm both exist.
|
||||
- Risks: none beyond the pre-existing, already-documented full-wipe behavior.
|
||||
|
||||
#### Downstream Verification Skills
|
||||
|
||||
| Field | Detail |
|
||||
|-------|--------|
|
||||
| Intent | Keep `/xce-test-ha`, `/xce-deploy-ha`, `/xce-test-multihost`, `/xce-test-resources` working once the old coupling is removed |
|
||||
| Requirements | 5.1, 5.2, 5.3, 5.4 |
|
||||
|
||||
**Responsibilities & Constraints**
|
||||
- Each workflow must ensure the harness is built before it is needed — either by invoking the harness build itself or by checking for the binary and failing with a clear, actionable message (matching the existing soft-skip pattern `xce-deploy-ha` already uses for worker/scheduler/xceadmin).
|
||||
- Must not fail with an unrelated error (e.g. a raw "no such file" from a spawned process) when the real cause is "harness was never built."
|
||||
|
||||
**Dependencies**
|
||||
- Outbound: harness component (P0).
|
||||
|
||||
**Contracts**: Batch [x]
|
||||
|
||||
##### Batch / Job Contract
|
||||
- Trigger: `/xce-test-ha`, `/xce-deploy-ha`, `/xce-test-multihost`, `/xce-test-resources`.
|
||||
- Input / validation: presence check for `<build_dir>/harness/xce_test` (or equivalent) before use.
|
||||
- Output / destination: existing workflow outputs, unchanged; only the failure path for a missing binary changes (from an unrelated/confusing error to `xce-deploy-ha`'s existing clear soft-skip style).
|
||||
- Idempotency & recovery: re-running after building the harness proceeds normally.
|
||||
|
||||
**Implementation Notes**
|
||||
- Integration: `xce-deploy-ha` already has a soft-skip precedent (worker/scheduler/xceadmin) to extend to harness rather than inventing a new pattern.
|
||||
- Validation: run each of the four workflows from a clean build directory (harness never built) and confirm a clear, actionable message rather than a confusing downstream failure.
|
||||
- Risks: missing one of the four in the actual edit pass — mitigated by the grep-verified inventory in `research.md` (three shell scripts + four `SKILL.md` files, all named explicitly above).
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Error Strategy
|
||||
This feature has no runtime user-facing error surface (it is build/workflow infrastructure); "errors" here are build-time and workflow-time failure modes.
|
||||
|
||||
### Error Categories and Responses
|
||||
- **Missing harness binary at workflow time** (Requirement 5.4): the consuming skill must report a clear, actionable message (e.g. "harness not built — run `/xce-build harness` first"), matching `xce-deploy-ha`'s existing soft-skip wording style, rather than surfacing a raw spawn/connect failure.
|
||||
- **Stale harness binary vs. a fresh `xce_test` change**: prevented structurally by `harness_unit_test`'s explicit build-order dependency on the `xce_test` target (Architecture, System Flows).
|
||||
- **Build-dir clobbering** (pre-existing project behavior, `build-deployment.md` bug-1565): unchanged — a harness build after a controller build in the same dir without `--incremental` wipes the controller's binaries, exactly as any other two-component pair behaves today; no new mitigation required, only awareness.
|
||||
|
||||
### Monitoring
|
||||
No new monitoring surface — this is dev/CI-time tooling, not a running service.
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
- **Unit Tests** (Requirement 3): all 17 relocated test files pass under the harness's five `suite: 'harness'` binaries (`harness_unit_test` plus the four relocated standalone binaries) with identical pass/fail semantics to their pre-move behavior; `controller_unit_test`'s remaining test count (and `controller_test.c`'s remaining extern/RUN_TEST list) is unchanged aside from the 13 entries removed for the new `harness_unit_test`, and the four standalone `executable()`/`test()` blocks are confirmed gone from `src/controller/meson.build` (no accidental loss).
|
||||
- **Integration Tests** (Requirement 2): `/xce-build harness` alone (no prior controller build) produces `xce_test`; `/xce-build controller` alone does not produce `xce_test`; `/xce-build all` produces both; deliberately removing the built `xce_test` binary before running `harness_unit_test` causes `test_test_cli.c`/`test_xcetest_process_entry.c` to fail loudly (proves the build-order dependency is real, not incidental).
|
||||
- **Workflow Tests** (Requirement 5): run `/xce-test-ha`, `/xce-deploy-ha`, `/xce-test-multihost`, `/xce-test-resources` starting from a clean build directory (harness never built) and confirm each either builds it or fails with a clear, actionable message — never a silent skip or an unrelated error.
|
||||
- **Behavioral Parity Tests** (Requirement 4): capture `xce_test`'s command/flag/output behavior before the move (via the existing `xce-test-cli-ux`/`xce-test-e2e-primitives`/`xce-test-rc-file` coverage), rerun the same coverage against the relocated binary, and diff for any deviation.
|
||||
|
||||
## Supporting References
|
||||
- `.kiro/specs/xce-harness-component/research.md` — full discovery log, header-dependency audit, and design-decision rationale.
|
||||
- `.kiro/specs/xce-harness-component/brief.md` — original discovery brief and locked-in scope decisions.
|
||||
104
.kiro/specs/xce-harness-component/tasks.md
Normal file
104
.kiro/specs/xce-harness-component/tasks.md
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
# Implementation Plan: xce-harness-component
|
||||
|
||||
- [ ] 1. Foundation: relocate xce_test itself and establish the component
|
||||
- [x] 1.1 Relocate xce_test's production sources, wire its standalone build, and strip every controller-side reference to the moved files
|
||||
- Move all 15 xce_test source files (`test.c`, `waldump.c`, `walcompare.c`, `snapverify.c`, `snapdiff.c`, `configcompare.c`, `resval_typeresolve.c`, `joblist_display.c`, `join_worker_args.c`, `rcfile.c`, `flagspec.c`, `interruptcall.c`, `confirm.c`, `listfmt_json.c`, `listrow_json.c`) and their headers out of `src/controller/testsuite/` into `src/harness/`, content unchanged
|
||||
- Create `src/harness/meson.build` defining only the `xce_test` executable so far (same sources/dependencies as today, paths updated); add `subdir('harness')` to `src/meson.build`
|
||||
- In the same task, from `src/controller/meson.build` remove: the `xce_test_src`/`xce_test_deps`/`xce_test` executable block; every `controller_unit_test_src` entry that references one of the 15 moved files, which is 10 production+test pairs (`waldump`, `walcompare`, `snapverify`, `snapdiff`, `configcompare`, `rcfile`, `flagspec`, `interruptcall`, `confirm`, `listfmt_json`, each with its `test_*.c`) plus `test_xcetest_interrupt.c` (extra `interruptcall.c` coverage) — 11 test files total; and the four entire standalone `executable()`/`test()` blocks (`resval_typeresolve_unit_test`, `joblist_display_unit_test`, `join_worker_args_unit_test`, `listrow_json_unit_test`), since each references one of the 15 moved production files directly
|
||||
- Also remove those same 11 test files' `extern`/`RUN_TEST` entries from `controller_test.c`. Leave `test_test_cli.c`'s and `test_xcetest_process_entry.c`'s entries in place — neither links any of the 15 moved files (they spawn the built `xce_test` binary as a subprocess instead), so they stay valid in `controller_unit_test` until task 2.1 relocates them
|
||||
- The 11 removed test files' `.c` sources are left on disk at their current `src/controller/testsuite/` path for now (referenced by no build target) — task 2.1 physically relocates them together with `test_test_cli.c`/`test_xcetest_process_entry.c`
|
||||
- Observable: a harness-scoped build produces an `xce_test` binary; a controller-scoped build run immediately after this single task (no later tasks applied) still succeeds, `controller_unit_test`'s reported test count has dropped by exactly the 11 removed entries, and none of the four standalone binaries are defined anymore
|
||||
- _Requirements: 1.1, 1.2, 1.3, 2.1, 2.2, 2.4_
|
||||
- [ ] 1.2 Promote the shared ctrlstatus_fmt.h header and repoint its current consumers
|
||||
- Move `ctrlstatus_fmt.h` to `src/include/xce/`; update the include path in harness's `test.c` and `joblist_display.c` (already relocated in 1.1) and in controller's `test_ctrlstatus.c`
|
||||
- `joblist_display.c`'s own test file, `test_joblist_display.c`, still lives in `src/controller/testsuite/` at this point and is intentionally left untouched here — its include-path fix happens in task 2.2, when that file relocates
|
||||
- Observable: a repo-wide search finds no remaining relative `#include "ctrlstatus_fmt.h"`; all three current consumers include it from `xce/ctrlstatus_fmt.h`
|
||||
- _Requirements: 1.4_
|
||||
- [ ] 1.3 Write the harness component guide
|
||||
- New `src/harness/CLAUDE.md` describing the component's purpose, build command, and structure, matching the style of existing component guides (e.g. `src/controller/CLAUDE.md`)
|
||||
- Observable: `src/harness/CLAUDE.md` exists and documents the build command and file layout
|
||||
- _Requirements: 6.1_
|
||||
|
||||
- [ ] 2. Core: migrate the five harness test binaries
|
||||
- [ ] 2.1 Consolidate the controller-embedded harness tests into a new binary and finish clearing them from the controller's own test binary
|
||||
- Physically relocate the 13 test files for this group into `src/harness/testsuite/`: the 11 whose `controller_unit_test_src`/`controller_test.c` references were already removed in task 1.1 (`test_waldump.c` through `test_xcetest_interrupt.c`, left on disk at their old path until now), plus `test_test_cli.c` and `test_xcetest_process_entry.c` (still validly part of `controller_unit_test` until this task)
|
||||
- Write a new Unity runner `harness_test.c` (modeled on `controller_test.c`) carrying all 13 `extern`/`RUN_TEST` entries; register the new `harness_unit_test` executable and its `meson test()` under suite `harness` in `src/harness/meson.build`; declare its build-order dependency on the `xce_test` executable target (two of its tests spawn that binary over a pty)
|
||||
- In the same task, remove `test_test_cli.c`'s and `test_xcetest_process_entry.c`'s entries from `controller_unit_test_src` and their `extern`/`RUN_TEST` lines from `controller_test.c` — the only two of the 13 not already removed in task 1.1 (`test_ctrlstatus`'s entry stays — it tests controller's own `ctrlstatus.c`)
|
||||
- Observable: `meson test --suite harness` runs `harness_unit_test` with the same pass count these 13 files reported before the move; `meson test --suite controller` run immediately after this same task still runs `controller_unit_test` successfully, with its test count reduced by exactly these final 2 entries (11 were already reflected in task 1.1's count drop)
|
||||
- _Requirements: 3.1, 3.2, 3.3, 3.4_
|
||||
- [ ] 2.2 Relocate the four already-standalone harness test binaries
|
||||
- Physically relocate the `test_resval_typeresolve.c`, `test_joblist_display.c`, `test_join_worker_args.c`, and `test_listrow_json.c` files into `src/harness/testsuite/` (left on disk at their old path since task 1.1 removed their controller-side `executable()`/`test()` blocks); re-create each of the four `executable()`/`test()` blocks, unchanged in shape, in `src/harness/meson.build` under suite `harness`, referencing their production files already relocated to `src/harness/` in task 1.1
|
||||
- Update `test_joblist_display.c`'s `ctrlstatus_fmt.h` include path to `xce/ctrlstatus_fmt.h` as part of this same move
|
||||
- Observable: `meson test --suite harness` lists all four binaries alongside `harness_unit_test`, each reporting the same pass count as before the move
|
||||
- _Requirements: 1.4, 3.1, 3.2, 3.4_
|
||||
|
||||
- [ ] 3. Integration: decouple build orchestration, downstream workflows, and documentation
|
||||
- [ ] 3.1 Add the harness build entry and decouple it from the controller build
|
||||
- In `src/tools/xce-build.sh`, drop `controller/xce_test` from the `controller)` case's compile target list; add a new `harness)` case following the identical three-part `setup_build` / `meson compile` / conditional `meson test --suite harness` template already used by `scheduler)`/`worker)`
|
||||
- Observable: `/xce-build harness` on a fresh build dir (no prior controller build) produces the `xce_test` binary and runs the `harness` suite; `/xce-build controller` alone does not produce `xce_test`
|
||||
- _Requirements: 2.1, 2.2, 2.3, 2.4_
|
||||
- [ ] 3.2 (P) Update the HA soak workflow's harness prerequisite
|
||||
- Update `.claude/skills/xce-test-ha/run-ha-soak.sh` and `SKILL.md` so the soak ensures the harness is built (or fails with a clear message) instead of assuming a controller build produced it
|
||||
- Observable: running the workflow from a build dir where only controller was built either builds the harness itself or reports a clear, actionable message instead of a raw spawn/connect failure
|
||||
- _Requirements: 5.1, 5.4_
|
||||
- _Boundary: xce-test-ha skill_
|
||||
- _Depends: 3.1_
|
||||
- [ ] 3.3 (P) Extend the local HA deploy workflow's soft-skip handling to the harness
|
||||
- Update `.claude/skills/xce-deploy-ha/SKILL.md` to cover the harness binary under its existing worker/scheduler/xceadmin soft-skip pattern
|
||||
- Observable: deploying from a build dir without the harness built reports the same clear soft-skip style already used for a missing worker/scheduler/xceadmin binary
|
||||
- _Requirements: 5.2, 5.4_
|
||||
- _Boundary: xce-deploy-ha skill_
|
||||
- _Depends: 3.1_
|
||||
- [ ] 3.4 (P) Update the multi-host verification workflow's harness prerequisite
|
||||
- Update `.claude/skills/xce-test-multihost/run-multihost-verify.sh` and `SKILL.md`
|
||||
- Observable: running the workflow from a build dir where only controller was built either builds the harness itself or reports a clear, actionable message
|
||||
- _Requirements: 5.3, 5.4_
|
||||
- _Boundary: xce-test-multihost skill_
|
||||
- _Depends: 3.1_
|
||||
- [ ] 3.5 (P) Update the resource-value verification workflow's harness prerequisite
|
||||
- Update `.claude/skills/xce-test-resources/run-resource-verify.sh` and `SKILL.md`
|
||||
- Observable: running the workflow from a build dir where only controller was built either builds the harness itself or reports a clear, actionable message
|
||||
- _Requirements: 5.3, 5.4_
|
||||
- _Boundary: xce-test-resources skill_
|
||||
- _Depends: 3.1_
|
||||
- [ ] 3.6 (P) Update root guide and build/deployment steering for the harness component
|
||||
- Add `harness` to root `CLAUDE.md`'s `/xce-build` component list and Subdirectory Guidelines; remove `build-deployment.md`'s "controller always builds xce_test" claim and add harness to its `/xce-build` command table and Meson Structure tree
|
||||
- Observable: `CLAUDE.md` lists `harness` among buildable components; `build-deployment.md` no longer claims the controller build produces `xce_test`
|
||||
- _Requirements: 6.1, 6.2_
|
||||
- _Boundary: CLAUDE.md, build-deployment.md_
|
||||
- _Depends: 3.1_
|
||||
- [ ] 3.7 (P) Update structure steering to list the harness component
|
||||
- Add `harness` to `structure.md`'s component table and to its flat-root Exceptions list alongside controller
|
||||
- Observable: `structure.md`'s component tree and Exceptions section both mention harness
|
||||
- _Requirements: 6.3_
|
||||
- _Boundary: structure.md_
|
||||
- _Depends: 1.1_
|
||||
|
||||
- [ ] 4. Validation: prove behavioral parity and end-to-end correctness
|
||||
- [ ] 4.1 Verify xce_test's behavioral parity after relocation
|
||||
- Rerun the existing `xce-test-cli-ux` / `xce-test-e2e-primitives` / `xce-test-rc-file` test coverage against the harness-built `xce_test` binary and diff its command/flag/output behavior against a pre-move capture
|
||||
- Observable: no behavioral difference is found; every previously-passing scenario in that coverage still passes unchanged
|
||||
- _Requirements: 4.1, 4.2, 4.3_
|
||||
- _Depends: 3.1_
|
||||
- [ ] 4.2 Verify the harness_unit_test build-order dependency actually holds
|
||||
- Deliberately remove the built `xce_test` binary, run `harness_unit_test`, and confirm `test_test_cli.c`/`test_xcetest_process_entry.c` fail loudly rather than silently pass; rebuild normally and confirm the suite passes
|
||||
- Observable: the deliberate-removal run reports a clear failure from the two pty-spawning tests; the normal run reports the full suite green
|
||||
- _Requirements: 3.1, 3.2_
|
||||
- _Depends: 2.1, 3.1_
|
||||
- [ ] 4.3 Verify independent and combined build behavior
|
||||
- Run `/xce-build harness` alone on a clean build dir and confirm `xce_test` is produced; run `/xce-build controller` alone and confirm `xce_test` is absent; run `/xce-build all` and confirm both exist
|
||||
- Observable: each of the three build invocations produces exactly the binaries described above
|
||||
- _Requirements: 2.1, 2.2, 2.4_
|
||||
- _Depends: 3.1_
|
||||
- [ ] 4.4 Verify every downstream workflow from a clean build state
|
||||
- Run the HA soak, local HA deploy, multi-host verification, and resource-value verification workflows starting from a build directory where the harness has never been built
|
||||
- Observable: none of the four workflows fails with a raw/unrelated error; each either succeeds after building the harness itself or reports the expected clear, actionable message
|
||||
- _Requirements: 5.1, 5.2, 5.3, 5.4_
|
||||
- _Depends: 3.2, 3.3, 3.4, 3.5_
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- **Task 1.1**: discovered a real gap in the discovery/design audit — `test_config_repl.c`, `test_ha_core_safety.c`, `test_upgrade_snapshot_apply.c`, `test_bug857_regression.c` (controller's own domain tests, out of this spec's boundary) call functions directly from `waldump.c`/`walcompare.c`/`snapverify.c`/`snapdiff.c`. Fixed by having `controller_unit_test_src` recompile those four files a second time from `../harness/`. This is a permanent, sanctioned controller→harness dependency, not a migration artifact — recorded in design.md's Allowed Dependencies. Later tasks: do not assume harness has zero inbound dependency from controller; only assume harness has zero *outbound* dependency on controller (Requirement 1.4).
|
||||
- **Task 1.1**: `test_test_cli.c`/`test_xcetest_process_entry.c` locate `xce_test` as a build-dir sibling via `resolve_xce_test_path()`. Since they still live in `src/controller/testsuite/` until task 2.1, a temporary `xce_test_controller_link` custom_target symlink bridge was added to `src/controller/meson.build` (documented in-code as removable once task 2.1 relocates both files). Task 2.1 must remove this custom_target and the `test()`'s `depends:` on it as part of that relocation.
|
||||
- **Task 1.1 gotcha**: a meson `custom_target` command's `@INPUT0@`/`@OUTPUT0@` tokens expand to build-root-relative paths, but a symlink's target string is resolved relative to the *symlink's own directory* at dereference time, not the invocation cwd or the string's own reference frame — using `@INPUT0@` directly as an `ln -sf` target from a different subdirectory produces a broken link. Use an explicit `../`-relative (or absolute) path instead.
|
||||
- **Build dir note**: this repo's default build dir resolves to `src/xce.build/` (relative to `src/tools/xce-build.sh`'s own cwd), not a bare `xce.build/` at the repo root.
|
||||
|
|
@ -31,7 +31,7 @@ controller_src = [
|
|||
]
|
||||
|
||||
incdir = include_directories('.', '../include', '../lib',
|
||||
'include')
|
||||
'include', '../harness/include')
|
||||
|
||||
# cc = meson.get_compiler('c')
|
||||
# math_dep = cc.find_library('m', required : false)
|
||||
|
|
@ -55,35 +55,6 @@ controller = executable('xce_controller',
|
|||
link_args: wrap_link_args,
|
||||
install: true)
|
||||
|
||||
xce_test_src = [ 'testsuite/test.c', 'testsuite/waldump.c', 'testsuite/walcompare.c', 'testsuite/snapverify.c', 'testsuite/snapdiff.c', 'testsuite/configcompare.c', 'testsuite/resval_typeresolve.c', 'testsuite/joblist_display.c', 'testsuite/join_worker_args.c', 'testsuite/rcfile.c', 'testsuite/flagspec.c', 'testsuite/interruptcall.c', 'testsuite/confirm.c', 'testsuite/listfmt_json.c', 'testsuite/listrow_json.c']
|
||||
|
||||
# BSD-licensed readline replacement (scheduler-core spec, task 12.1 review
|
||||
# finding): GNU readline is GPL; xce_test's REPL only needs readline()/
|
||||
# add_history(), both provided by libedit's editline/readline.h emulation
|
||||
# header under a permissive license. Single dependency, no separate
|
||||
# ncurses/history split (libedit's own .pc pulls ncurses in privately).
|
||||
libedit_dep = dependency('libedit')
|
||||
ssl_dep = dependency('openssl') # also needed by configcompare.c (SHA256());
|
||||
# controller_unit_test_deps below re-assigns
|
||||
# the same dependency() result, harmless
|
||||
|
||||
xce_test_deps = [
|
||||
libxce_dep,
|
||||
librtti_dep,
|
||||
struct2json_dep,
|
||||
libedit_dep,
|
||||
tinylog_dep,
|
||||
zlib_dep, # waldump: crc32 WAL validation
|
||||
c_capnproto_dep, # waldump: decode JOB_SUBMIT jobid
|
||||
ssl_dep, # configcompare: SHA256() active-config hashing
|
||||
thread_dep, # interruptcall.c: xcetest_run_interruptible() detached worker (task 1.4)
|
||||
]
|
||||
xce_test = executable('xce_test',
|
||||
xce_test_src,
|
||||
include_directories: [incdir],
|
||||
dependencies: xce_test_deps,
|
||||
install: true)
|
||||
|
||||
# Controller Unity test suite (persist types and future controller unit tests)
|
||||
controller_unit_test_src = [
|
||||
'testsuite/controller_test.c',
|
||||
|
|
@ -157,27 +128,24 @@ controller_unit_test_src = [
|
|||
'testsuite/test_term_adoption_vectors.c',
|
||||
'testsuite/test_ha_core_safety.c',
|
||||
'testsuite/test_ha_partition.c',
|
||||
'testsuite/test_waldump.c',
|
||||
'testsuite/waldump.c',
|
||||
'testsuite/test_walcompare.c',
|
||||
'testsuite/walcompare.c',
|
||||
'testsuite/test_snapverify.c',
|
||||
'testsuite/snapverify.c',
|
||||
'testsuite/test_snapdiff.c',
|
||||
'testsuite/snapdiff.c',
|
||||
'testsuite/test_configcompare.c',
|
||||
'testsuite/configcompare.c',
|
||||
'testsuite/test_rcfile.c',
|
||||
'testsuite/rcfile.c',
|
||||
'testsuite/test_flagspec.c',
|
||||
'testsuite/flagspec.c',
|
||||
'testsuite/test_xcetest_interrupt.c',
|
||||
'testsuite/test_interruptcall.c',
|
||||
'testsuite/interruptcall.c',
|
||||
'testsuite/test_confirm.c',
|
||||
'testsuite/confirm.c',
|
||||
'testsuite/test_listfmt_json.c',
|
||||
'testsuite/listfmt_json.c',
|
||||
# xce-harness-component task 1.1: these 4 of the 15 files relocated to
|
||||
# src/harness/ are NOT purely xce_test-private -- test_config_repl.c/
|
||||
# test_bug857_regression.c call snapdiff_paths() (snapdiff.c),
|
||||
# test_ha_core_safety.c calls waldump_path_visit()/walcompare()
|
||||
# (waldump.c/walcompare.c), and test_upgrade_snapshot_apply.c calls
|
||||
# snapverify_path() (snapverify.c) -- a real cross-dependency the
|
||||
# spec's own research.md audit missed (it only checked what xce_test's
|
||||
# sources #include, not who #includes xce_test's headers back). Their
|
||||
# own white-box test pairs (test_waldump.c etc.) DID move to the
|
||||
# harness's future harness_unit_test (task 2.1) and are correctly gone
|
||||
# from this list below; these 4 production files themselves stay
|
||||
# compiled a second time here too, exactly mirroring today's existing
|
||||
# dual-compilation pattern (recompiled from their new ../harness/
|
||||
# location -- see incdir's added '../harness/include' entry above).
|
||||
'../harness/waldump.c',
|
||||
'../harness/walcompare.c',
|
||||
'../harness/snapverify.c',
|
||||
'../harness/snapdiff.c',
|
||||
'testsuite/test_xcetest_process_entry.c',
|
||||
'testsuite/test_test_cli.c',
|
||||
'testsuite/test_persist_snapshot_entities.c',
|
||||
|
|
@ -253,9 +221,31 @@ controller_unit_test = executable('controller_unit_test',
|
|||
c_args: ['-DXCE_TESTING'],
|
||||
install: false)
|
||||
|
||||
# TEMPORARY (xce-harness-component task 1.1): test_test_cli.c and
|
||||
# test_xcetest_process_entry.c stay registered in controller_unit_test_src
|
||||
# above until task 2.1 relocates them into src/harness/testsuite/. Both
|
||||
# spawn the built xce_test binary as a subprocess via resolve_xce_test_path()
|
||||
# (test_xcetest_process_entry.c), which finds it by looking in the SAME
|
||||
# build directory as the running test binary (dirname(/proc/self/exe) +
|
||||
# "/xce_test") -- an assumption that held when xce_test built into this
|
||||
# same controller/ build subdir, and breaks now that xce_test builds into
|
||||
# harness/ instead (task 1.1's whole point). This symlink keeps that
|
||||
# assumption satisfied without touching either test file, both of which
|
||||
# are out of this task's boundary -- remove this custom_target and the
|
||||
# test()'s `depends:` below once task 2.1 physically relocates both files,
|
||||
# at which point they become genuine build-dir siblings of xce_test again
|
||||
# (mirroring harness_unit_test's own explicit dependency on the xce_test
|
||||
# target, per the design's System Flows).
|
||||
xce_test_controller_link = custom_target('xce_test_controller_link',
|
||||
output: 'xce_test',
|
||||
input: xce_test,
|
||||
command: ['ln', '-sf', '../harness/xce_test', '@OUTPUT0@'],
|
||||
)
|
||||
|
||||
test('controller test', controller_unit_test,
|
||||
suite: 'controller',
|
||||
timeout: 300,
|
||||
depends: [xce_test_controller_link],
|
||||
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
||||
|
||||
# job-array-single-wal-record task 5.1: sched.c's push logic (sched_job_new_fun /
|
||||
|
|
@ -347,32 +337,6 @@ test('apiserver push test', apiserver_push_unit_test,
|
|||
timeout: 60,
|
||||
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
||||
|
||||
# resource-value-verification task 1.1: resval_typeresolve.c is a small,
|
||||
# dependency-light module (no networking/REPL/global state) extracted from
|
||||
# test.c's set_resval() specifically so its name -> Value_u_which resolution
|
||||
# logic can be unit-tested in isolation -- test.c itself (4298 lines, its own
|
||||
# main(), heavy libedit/network dependencies) cannot be white-box included
|
||||
# into a Unity test. Standalone binary (not folded into controller_unit_test_
|
||||
# src) since it has zero dependency on controller.c/cluster.c internals,
|
||||
# mirroring sched_push_unit_test's/apiserver_push_unit_test's own standalone-
|
||||
# binary rationale above.
|
||||
resval_typeresolve_unit_test_src = [
|
||||
'testsuite/test_resval_typeresolve.c',
|
||||
'testsuite/resval_typeresolve.c',
|
||||
]
|
||||
|
||||
resval_typeresolve_unit_test = executable('resval_typeresolve_unit_test',
|
||||
resval_typeresolve_unit_test_src,
|
||||
include_directories: [incdir],
|
||||
dependencies: controller_unit_test_deps,
|
||||
c_args: ['-DXCE_TESTING'],
|
||||
install: false)
|
||||
|
||||
test('resval typeresolve test', resval_typeresolve_unit_test,
|
||||
suite: 'controller',
|
||||
timeout: 60,
|
||||
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
||||
|
||||
# bug-1735: misc.c's update_host_runusage()/aggregate_job_runusage() are
|
||||
# small, dependency-light functions (calloc/realloc/strcmp only, no RTTI
|
||||
# locking, no networking) -- standalone binary linking the REAL misc.c
|
||||
|
|
@ -397,85 +361,4 @@ test('host runusage test', host_runusage_unit_test,
|
|||
timeout: 60,
|
||||
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
||||
|
||||
# xce-test-cli-ux task 2.5 remediation: joblist_display.c is a small,
|
||||
# dependency-light module (no networking/REPL/global state) extracted from
|
||||
# test.c's worker_status_str()/job_state_str()/format_job_time() specifically
|
||||
# so their bug-1711 display-formatting fixes can be unit-tested in isolation
|
||||
# -- test.c itself cannot be white-box included into a Unity test, same
|
||||
# rationale as resval_typeresolve_unit_test above. Standalone binary (not
|
||||
# folded into controller_unit_test_src) since it has zero dependency on
|
||||
# controller.c/cluster.c internals, mirroring resval_typeresolve_unit_test's/
|
||||
# host_runusage_unit_test's own standalone-binary rationale.
|
||||
joblist_display_unit_test_src = [
|
||||
'testsuite/test_joblist_display.c',
|
||||
'testsuite/joblist_display.c',
|
||||
]
|
||||
|
||||
joblist_display_unit_test = executable('joblist_display_unit_test',
|
||||
joblist_display_unit_test_src,
|
||||
include_directories: [incdir],
|
||||
dependencies: controller_unit_test_deps,
|
||||
c_args: ['-DXCE_TESTING'],
|
||||
install: false)
|
||||
|
||||
test('joblist display test', joblist_display_unit_test,
|
||||
suite: 'controller',
|
||||
timeout: 60,
|
||||
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
||||
|
||||
# xce-test-cli-ux task 2.6 remediation: join_worker_args.c is a small,
|
||||
# dependency-light module (no networking/REPL/global state) extracted from
|
||||
# test.c's cmd_join_worker() specifically so the bug-1557 maxmem-default fix
|
||||
# can be unit-tested in isolation -- test.c itself cannot be white-box
|
||||
# included into a Unity test, same rationale as joblist_display_unit_test/
|
||||
# resval_typeresolve_unit_test above. Standalone binary (not folded into
|
||||
# controller_unit_test_src) since it has zero dependency on
|
||||
# controller.c/cluster.c internals, mirroring those tests' own
|
||||
# standalone-binary rationale.
|
||||
join_worker_args_unit_test_src = [
|
||||
'testsuite/test_join_worker_args.c',
|
||||
'testsuite/join_worker_args.c',
|
||||
'testsuite/flagspec.c', # xce-test-cli-ux task 3.1: join_worker_parse_attrs
|
||||
# migrated onto flagspec_build_opts/flagspec_reject
|
||||
]
|
||||
|
||||
join_worker_args_unit_test = executable('join_worker_args_unit_test',
|
||||
join_worker_args_unit_test_src,
|
||||
include_directories: [incdir],
|
||||
dependencies: controller_unit_test_deps,
|
||||
c_args: ['-DXCE_TESTING'],
|
||||
install: false)
|
||||
|
||||
test('join worker args test', join_worker_args_unit_test,
|
||||
suite: 'controller',
|
||||
timeout: 60,
|
||||
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
||||
|
||||
# xce-test-cli-ux task 3.4: listrow_json.c is a small, dependency-light
|
||||
# module (no networking/REPL/global state) extracted from cmd_reslist/
|
||||
# cmd_workerlist/joblist_query specifically so their new --json output
|
||||
# mode's per-command field-mapping logic can be unit-tested in isolation
|
||||
# -- test.c itself cannot be white-box included into a Unity test, same
|
||||
# rationale as joblist_display_unit_test/resval_typeresolve_unit_test
|
||||
# above. Standalone binary (not folded into controller_unit_test_src)
|
||||
# mirroring those tests' own standalone-binary rationale. Links
|
||||
# listfmt_json.c directly (not struct2json_dep alone) since listrow_json.c
|
||||
# calls its add_string()/add_number()/new_row() helpers.
|
||||
listrow_json_unit_test_src = [
|
||||
'testsuite/test_listrow_json.c',
|
||||
'testsuite/listrow_json.c',
|
||||
'testsuite/listfmt_json.c',
|
||||
]
|
||||
|
||||
listrow_json_unit_test = executable('listrow_json_unit_test',
|
||||
listrow_json_unit_test_src,
|
||||
include_directories: [incdir],
|
||||
dependencies: controller_unit_test_deps,
|
||||
c_args: ['-DXCE_TESTING'],
|
||||
install: false)
|
||||
|
||||
test('listrow json test', listrow_json_unit_test,
|
||||
suite: 'controller',
|
||||
timeout: 60,
|
||||
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
||||
|
||||
|
|
|
|||
|
|
@ -65,17 +65,6 @@ extern void test_ctrlstatus(void);
|
|||
extern void test_ha_heartbeat_committed(void);
|
||||
extern void test_ha_vote_floor_heartbeat(void);
|
||||
extern void test_term_safety_adapter(void);
|
||||
extern void test_waldump(void);
|
||||
extern void test_walcompare(void);
|
||||
extern void test_snapverify(void);
|
||||
extern void test_snapdiff(void);
|
||||
extern void test_configcompare(void);
|
||||
extern void test_rcfile(void);
|
||||
extern void test_flagspec(void);
|
||||
extern void test_xcetest_interrupt(void);
|
||||
extern void test_interruptcall(void);
|
||||
extern void test_confirm(void);
|
||||
extern void test_listfmt_json(void);
|
||||
extern void test_xcetest_process_entry(void);
|
||||
extern void test_test_cli(void);
|
||||
extern void test_drive_async_config(void);
|
||||
|
|
@ -252,17 +241,6 @@ int main(int argc, char* argv[])
|
|||
TEST(test_ha_heartbeat_committed);
|
||||
TEST(test_ha_vote_floor_heartbeat);
|
||||
TEST(test_term_safety_adapter);
|
||||
TEST(test_waldump);
|
||||
TEST(test_walcompare);
|
||||
TEST(test_snapverify);
|
||||
TEST(test_snapdiff);
|
||||
TEST(test_configcompare);
|
||||
TEST(test_rcfile);
|
||||
TEST(test_flagspec);
|
||||
TEST(test_xcetest_interrupt);
|
||||
TEST(test_interruptcall);
|
||||
TEST(test_confirm);
|
||||
TEST(test_listfmt_json);
|
||||
TEST(test_xcetest_process_entry);
|
||||
TEST(test_test_cli);
|
||||
TEST(test_drive_async_config);
|
||||
|
|
|
|||
56
src/harness/meson.build
Normal file
56
src/harness/meson.build
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# TEMPORARY (xce-harness-component task 1.1): '../controller/testsuite' is
|
||||
# only here so the bare `#include "ctrlstatus_fmt.h"` in test.c/
|
||||
# joblist_display.c keeps resolving -- ctrlstatus_fmt.h itself still
|
||||
# physically lives at src/controller/testsuite/ctrlstatus_fmt.h pending
|
||||
# task 1.2, which promotes it to src/include/xce/ctrlstatus_fmt.h and
|
||||
# repoints these two #include lines at it. Remove this entry when task 1.2
|
||||
# lands (it will make it redundant, since src/include is already on this
|
||||
# path via '../include').
|
||||
incdir = include_directories('.', '../include', '../lib', 'include',
|
||||
'../controller/testsuite')
|
||||
|
||||
zlib_dep = dependency('zlib')
|
||||
|
||||
# BSD-licensed readline replacement (scheduler-core spec, task 12.1 review
|
||||
# finding): GNU readline is GPL; xce_test's REPL only needs readline()/
|
||||
# add_history(), both provided by libedit's editline/readline.h emulation
|
||||
# header under a permissive license. Single dependency, no separate
|
||||
# ncurses/history split (libedit's own .pc pulls ncurses in privately).
|
||||
libedit_dep = dependency('libedit')
|
||||
ssl_dep = dependency('openssl') # also needed by configcompare.c (SHA256())
|
||||
|
||||
xce_test_src = [
|
||||
'test.c',
|
||||
'waldump.c',
|
||||
'walcompare.c',
|
||||
'snapverify.c',
|
||||
'snapdiff.c',
|
||||
'configcompare.c',
|
||||
'resval_typeresolve.c',
|
||||
'joblist_display.c',
|
||||
'join_worker_args.c',
|
||||
'rcfile.c',
|
||||
'flagspec.c',
|
||||
'interruptcall.c',
|
||||
'confirm.c',
|
||||
'listfmt_json.c',
|
||||
'listrow_json.c',
|
||||
]
|
||||
|
||||
xce_test_deps = [
|
||||
libxce_dep,
|
||||
librtti_dep,
|
||||
struct2json_dep,
|
||||
libedit_dep,
|
||||
tinylog_dep,
|
||||
zlib_dep, # waldump: crc32 WAL validation
|
||||
c_capnproto_dep, # waldump: decode JOB_SUBMIT jobid
|
||||
ssl_dep, # configcompare: SHA256() active-config hashing
|
||||
thread_dep, # interruptcall.c: xcetest_run_interruptible() detached worker (task 1.4)
|
||||
]
|
||||
|
||||
xce_test = executable('xce_test',
|
||||
xce_test_src,
|
||||
include_directories: [incdir],
|
||||
dependencies: xce_test_deps,
|
||||
install: true)
|
||||
|
|
@ -64,6 +64,7 @@ if component != 'xcecli'
|
|||
]
|
||||
|
||||
subdir('lib')
|
||||
subdir('harness')
|
||||
subdir('controller')
|
||||
subdir('worker')
|
||||
subdir('autoscaler')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue