Skip to content

test: cover runScriptInSandbox's spawn-failure fallbacks - #1215

Merged
mrbobbytables merged 1 commit into
mainfrom
quality/test-script-sandbox-spawn-fallbacks
Oct 9, 2026
Merged

mrbobbytables merged 1 commit into
mainfrom
quality/test-script-sandbox-spawn-fallbacks

Conversation

@hivecommons-hive

Copy link
Copy Markdown
Contributor

Test Improvement

Closes #1214.

tests/helpers-script-sandbox.mjs was at 80.00% regions — the lowest of the
six tests/helpers-*.mjs sandbox modules. Its five uncovered regions were all
of the normalisation it applies to the spawnSync result before handing it to a
test: the process.env.PATH ?? '' tail it builds the child's PATH from (177),
status ?? 1 / stdout ?? '' / stderr ?? '' (200-202), and realGitPath's
(found.stdout ?? '').trim() || '/usr/bin/git' (229).

tests/helpers-spawn-fallbacks.test.mjs already pins exactly this contract for
the three other sandbox helpers — runScriptWithFixtures,
runScriptWithFetchMock and runWithGhStub. runScriptInSandbox was left out,
and it is the helper backing the five collect-*.test.mjs suites. Since
spawnSync reports a failed spawn as status: null with stdout/stderr
undefined rather than throwing, those fallbacks are the whole difference between
"the script under test failed" and "the harness could not start it" — and a
regression there would leak null into every collect-* assertion instead.

Adds tests/helpers-script-sandbox-fallbacks.test.mjs, 4 tests reusing the
established withoutPath pattern from the existing file:

  • spawn failure degrades cleanly — with PATH deleted the helper's bare
    node lookup fails with ENOENT; status is 1, stdout/stderr are '',
    and requests is empty because a child that never started issued no fetch.
  • outputs survive a failed spawn — outputs are collected from the sandbox
    directory, not from the child, so a fixture written before the spawn is still
    read back and a path nothing wrote is still null. That is what keeps a
    harness fault distinguishable from a script that produced nothing.
  • the null contract on a normal run — the child ran and exited 0, and a
    declared output it never wrote comes back null, not ''.
  • realGitPath falls back to /usr/bin/git — deleting PATH is not
    enough here: command -v git runs under /bin/sh, and a shell with no PATH
    in its environment falls back to a confstr default that still finds git
    (verified: PATH= /bin/sh -c 'command -v git' exits 127, while unsetting it
    does not). An empty PATH is honoured as an empty search path, so the
    || '/usr/bin/git' arm is taken. This matters because realGitPath is
    resolved before the git shim is prepended to PATH, so the shim delegates to
    the real binary instead of recursing; an empty result would expand the shim's
    exec "$ENDUSERS_REAL_GIT" "$@" to a bare exec "".

Both helpers restore PATH in a finally, and node --test runs the tests
within a file sequentially, so no sibling test observes the gap.

Measured

npm run test:unit:coverage, node v26.10.0, TZ=UTC, run locally at 593b9fe
(this branch's base):

tests/helpers-script-sandbox.mjs lines regions
before 100.00 80.00
after 100.00 96.67

All-files regions 95.20 → 95.26. Full unit suite: 2090 tests, 0 failures.
npm run test:unit:coverage:check exits 0; Prettier clean.

Residual, deliberately left

The one region still uncovered is the found.stdout ?? '' arm of 229. It is
unreachable from the helper's surface: with shell: true, spawnSync launches
/bin/sh by absolute path, so no PATH manipulation can make that spawn fail
and leave stdout nullish. #1214's completion criterion names the
|| '/usr/bin/git' arm specifically for this reason, so this PR closes it.

Scope / overlap

Adds one new file and touches nothing else — no production code, no
package.json, no existing test. Checked against every open hold-gated PR:
#1206 and #1213 are scripts/lib/svg-active-content.mjs +
tests/svg-active-content.test.mjs; #1203 is the e2e fixture overlay builds;
#1207 is the tests/tools/ harness floor (its new per-file floor is scoped to
tests/tools/, and this file is tests/helpers-script-sandbox.mjs, so the
threshold line is untouched); #1209 and #1211 are
tests/tools/e2e-coverage-report.mjs. No overlap with any of them.


Filed by quality agent (hold-gated mode). Human review required.

— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88

tests/helpers-script-sandbox.mjs was the one sandbox helper whose
spawnSync normalisation no test reached, at 80.00% regions. Its five
uncovered regions were all of it: the PATH tail it builds for the child,
the status/stdout/stderr fallbacks, and realGitPath's last resort.

tests/helpers-spawn-fallbacks.test.mjs already pins this contract for
helpers.mjs, helpers-fetch-mock.mjs and helpers-gh-sandbox.mjs. This
adds the matching file for runScriptInSandbox, which backs the five
collect-*.test.mjs suites.

Deleting PATH reaches 177 and 200-202. An empty PATH is needed for 229,
because /bin/sh with no PATH in its environment falls back to a confstr
default that still finds git.

96.67% regions after; the residual is the found.stdout ?? '' arm, which
is unreachable while the lookup runs under shell: true.

Signed-off-by: quality <quality@hive.kubestellar.io>
@hivecommons-hive hivecommons-hive Bot added the hold label Oct 8, 2026
@hivecommons-hive

Copy link
Copy Markdown
Contributor Author

Important

Held for human review by the hive's ACMM level gate.

This PR was opened by the "quality" agent while Hive policy required a human checkpoint for that agent. Non-outreach agents are held at ACMM L3–L5; the outreach agent is always held because it publishes project-facing communication.

Hive will keep the hold label until a human removes it. Operators can make a deliberate one-off release during an ACMM level change with release_level_holds=true, but level changes never release this hold automatically.

@hivecommons-hive hivecommons-hive Bot added quality Approved by a Hive merger/owner for auto-merge on green CI testing Approved by a Hive merger/owner for auto-merge on green CI labels Oct 8, 2026
@mrbobbytables
mrbobbytables added this pull request to the merge queue Oct 9, 2026
Merged via the queue into main with commit fd9cc93 Oct 9, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

hold quality Approved by a Hive merger/owner for auto-merge on green CI testing Approved by a Hive merger/owner for auto-merge on green CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[quality] runScriptInSandbox is the one sandbox helper whose spawn-failure fallbacks no test reaches

1 participant