myxce/.kiro/specs/xce-test-rc-file/tasks.md
Rongsong Shen 8fc86ef4e2
test(xce-test-rc-file): task 3.3 confirm existing automation unaffected
No product/spec-test code changed. Ran the real xce-test-ha soak and
xce-test-resources verification drivers with no rc file present anywhere
in the environment they run under -- both pass their own documented
success criteria unchanged (zero job loss across rolling failover; zero
resource-value mismatches across controller/scheduler/apiserver), proving
Requirement 1.3's "no rc file -> unchanged behavior" guarantee holds for
real, pre-existing automation that has no awareness this feature exists.

Marks all tasks in the xce-test-rc-file spec complete.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AgYRU3zDTqNGV5Jk8aiKLg
2026-08-26 17:34:17 +00:00

7.4 KiB

Implementation Plan

  • 1. Foundation: rc-file path resolution and line-loading capability

  • 1.1 Implement rc-file path resolution following XDG precedence, with unit tests

    • Resolve the rc-file location using the XDG config variable when it is set and non-empty
    • Fall back to the home-directory XDG default when that variable is unset or empty, and to "no resolvable path" when neither variable is usable
    • Wire the new module and its test file into both existing build targets that need it, so both compile and the new unit tests run under the existing unit test suite
    • Save each of $HOME/$XDG_CONFIG_HOME's prior state (unset vs. empty vs. a value) before any test case mutates it, and restore that exact prior state afterward, since controller_unit_test runs 80+ test files sequentially in one process and a leaked env var would silently affect unrelated tests
    • Observable: a unit test run demonstrates the correct location is chosen for each of the three environment combinations above, and a subsequent unrelated test's own $HOME/$XDG_CONFIG_HOME reads are unaffected
    • Requirements: 1.1
  • 1.2 Implement rc-file line-loading with a pluggable command runner, with unit tests

    • Read the rc file line by line using getline() (no fixed-size buffer), invoking a caller-supplied runner once per line with the trailing newline removed
    • Treat a missing rc file as a no-op success (no error), and a present-but-unreadable rc file as a non-fatal warning that still allows startup to proceed
    • Stop reading immediately the first time the runner signals a stop, and propagate that signal to the caller without processing any remaining lines
    • Observable: a unit test run demonstrates every line is processed when the runner keeps succeeding, remaining lines are skipped the first time the runner signals a stop, the runner is never invoked when the file is absent, and a line well beyond a typical small fixed-buffer size (e.g. >4KB) reaches the runner intact and unsplit
    • Requirements: 1.2, 1.3
  • 2. Core: xce_test startup integration

  • 2.1 Add a flag that skips rc-file loading for a single invocation

    • Register the flag with xce_test's existing command-line option parsing so it is documented in xce_test's own help output
    • When the flag is given, record that rc-file loading should be skipped for this run
    • Observable: xce_test's help output lists the new flag with a description, and invoking xce_test with the flag parses successfully and records the skip state (verified directly, independent of task 2.2's wiring)
    • Requirements: 2.1, 2.2
    • Boundary: test.c::options[]/parse_opt
  • 2.2 Wire rc-file loading into xce_test startup for both interactive and scripted sessions

    • After xce_test determines whether the session is interactive or scripted and before it reads the first line of its normal session, resolve and load the rc file unless the skip flag was given, using the session's existing command-execution path as the per-line runner
    • When rc-file loading signals a stop, exit using the session's existing pass/fail exit-code convention without entering the normal session loop
    • Observable: a valid rc file's settings/context are visible once the normal session begins, in both a piped run and an interactive run; the same is confirmed absent when the skip flag is given
    • Requirements: 1.4, 1.5, 2.3
    • Depends: 1.1, 1.2
    • Boundary: test.c::main
  • 3. Validation: end-to-end behavior against the built binary

  • 3.1 Verify rc-file discovery, loading, and skip-flag behavior end-to-end

    • Scenario: a valid rc file's settings/context take effect in both a piped run and an interactive run
    • Scenario: the skip flag leaves default settings untouched even with a valid rc file present
    • Observable: an integration test run demonstrates both scenarios pass against the real built binary
    • Requirements: 1.1, 1.2, 1.4, 1.5, 2.1, 2.3
    • Depends: 2.2
  • 3.2 Verify rc-file failure handling matches the session's existing abort/continue behavior end-to-end

    • Scenario: a failing rc-file command in scripted/piped mode aborts before any of the piped script's own commands run, and the process exits with a failure status
    • Scenario: the same failing rc-file command in an interactive session still reaches the normal prompt afterward
    • Observable: an integration test run demonstrates both scenarios pass against the real built binary
    • Requirements: 3.1, 3.2, 3.3, 3.4
    • Depends: 2.2
  • 3.3 Confirm existing xce_test automation is unaffected when no rc file is present

    • Run the existing HA soak and resource-verification scripts (the known live callers of xce_test today) in an environment with no rc file at the resolved location
    • Compare their pass/fail result against their pre-feature baseline behavior
    • Observable: the existing scripts' outcomes are unchanged, demonstrating this feature introduces no regression for callers that know nothing about it
    • Requirements: 1.3
    • Depends: 2.2

Implementation Notes

  • Task 1.1: controller_unit_test can silently die with exit code 1/2 before reaching later-registered test groups if /tmp fills up — a pre-existing, already-tracked leak (bug-924) where test fixtures under /tmp/xce_* aren't cleaned up across many prior sessions' runs can exhaust disk and make mkdtemp() in unrelated tests (e.g. test_repl_apply.c) exit(1) on ENOSPC. If a later task's controller_unit_test run dies early or shows an unexplained failure in an unrelated file, check df -h /tmp before assuming a regression in this task's own code.
  • Task 1.1: the 2 pre-existing test_config_repl.c failures (test_conf_trim_keeps_only_n_versions, test_conf_get_saved_tag_no_config) are the tracked bug-1561 overlayfs-artifact regression, unrelated to this spec — expect them to keep appearing in every subsequent task's controller_unit_test run; do not treat them as a new regression.
  • Task 1.2: fopen() succeeds on a directory path on this platform's glibc — the EISDIR failure only surfaces on the first getline() call (errno=EISDIR, ferror(f) set). A naive if (!f) open-failure check misses this; a post-loop ferror(f) check is required to catch it (see rcfile_load(), bug-1716).
  • Task 1.2: an ASAN heap-use-after-free was observed ONCE in an ad-hoc standalone controller_unit_test run (commit_resolve_pending/fsync_worker/tap_teardown in test_apply_pump.c) — did not reproduce on a second run or in the canonical xce-build.sh run. Unrelated to this spec's files; logged as bug-1717 (unreproduced flake) for tracking. If it recurs on a later task's run, capture the full ASAN report before assuming it's this spec's fault.
  • Task 3.1: test_rcfile_integration.sh's per-test scratch $HOME dirs are cleaned via explicit rm -rf in each test function's normal flow, but there's no script-level trap ... EXIT INT TERM (unlike clean_failover_preservation.sh's global trap) — an interrupted run could leak a small scratch dir. Verified low-impact (small footprint, no leak in normal runs) but worth adding a trap if this script is extended later.
  • Task 3.3: xce-build.sh <component> without --incremental wipes the whole build dir before rebuilding only that one component (documented bug-1565 behavior) — running it for a component other than controller after a controller build silently deletes xce_controller/xce_test. Use --incremental (or all) when you need multiple binaries from the same build dir alongside each other.