Skip to content

BashSwiftScriptTests: end-to-end verify Subprocess.run hits bash builtins#22

Merged
odrobnik merged 2 commits into
mainfrom
feat/subprocess-e2e-test
May 9, 2026
Merged

BashSwiftScriptTests: end-to-end verify Subprocess.run hits bash builtins#22
odrobnik merged 2 commits into
mainfrom
feat/subprocess-e2e-test

Conversation

@odrobnik
Copy link
Copy Markdown
Contributor

@odrobnik odrobnik commented May 9, 2026

Closes the verification loop on the polyglot subprocess unification:

A SwiftScript script under SwiftBash that does Subprocess.run(Executable.name(\"echo\"), ...) should not reach posix_spawn; it should hit EchoCommand (the pure-Swift bash builtin). Two tests confirm this end-to-end — they're the script-author-visible payoff for the layered work above.

Tests

subprocessRunRoutesThroughBashCommandRegistry — script:

#!/usr/bin/env swift-script
import Subprocess
let r = try await Subprocess.run(
    Executable.name(\"echo\"),
    arguments: [\"hello-from-bash-builtin\"],
    output: Output.string(limit: 4096))
if let out = r.standardOutput, r.terminationStatus.isSuccess {
    print(\"got=\\(out)\", terminator: \"\")
}

Bridge calls Shell.current.processLauncher.launch(...), BashProcessLauncher resolves \"echo\" to the registered EchoCommand, the captured standardOutput round-trips back to the script and prints got=hello-from-bash-builtin\\n. No posix_spawn, no host /bin/echo involvement.

subprocessRunWithCanonicalPathHitsBashBuiltin — same flow with Executable.path(\"/bin/echo\"). Verifies the canonical-bin-path resolution rule (PR #19's P2 fix): /bin/echo matches BinCatalog.knownPaths[\"echo\"], so the launcher dispatches to the registered builtin instead of throwing ProcessLaunchUnresolved.

Both pass locally.

Test plan

  • CI green on macOS / iOS / tvOS / watchOS / Linux / Windows / Android
  • Local: 2/2 e2e tests pass

🤖 Generated with Claude Code

…tins

Closes the verification loop on the polyglot subprocess unification:

- ShellKit#1 — `Shell.processLauncher` primitive
- SwiftBash#19 — `BashProcessLauncher` resolves against the bash
  command registry
- SwiftScript#5 — `import Subprocess` bridge routes through
  `Shell.current.processLauncher`

A SwiftScript script under SwiftBash that does
`Subprocess.run(Executable.name("echo"), ...)` should NOT reach
`posix_spawn`; it should hit `EchoCommand` (the pure-Swift bash
builtin). Two tests confirm this in practice — they're the
script-author-visible payoff for the layered work above.

* `subprocessRunRoutesThroughBashCommandRegistry` — script calls
  `Subprocess.run(Executable.name("echo"), arguments: ["hello-..."], ...)`,
  the bridge calls `Shell.current.processLauncher.launch(...)`,
  `BashProcessLauncher` resolves `"echo"` to the registered
  `EchoCommand`, the captured `standardOutput` round-trips back
  to the script and prints. No `posix_spawn`, no host `/bin/echo`
  involvement.

* `subprocessRunWithCanonicalPathHitsBashBuiltin` — same flow with
  `Executable.path("/bin/echo")`. Verifies the canonical-bin-path
  resolution rule (PR #19's P2 fix): `/bin/echo` matches
  `BinCatalog.knownPaths["echo"]`, so the launcher dispatches to
  the registered builtin.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b306a51687

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Tests/BashSwiftScriptTests/BashSwiftScriptTests.swift Outdated
P2 from the automated review on
#22:

The original tests asserted on `echo` output, which is identical
whether produced by `EchoCommand` (the bash builtin) or `/bin/echo`
(the host). A regression that routed `Subprocess.run` through real
exec instead of `BashProcessLauncher` would still pass on Unix-
likes — the test didn't actually verify the routing claim.

Fix: use a signal that differs between dispatch paths.

- `subprocessRunRoutesThroughBashCommandRegistry` registers a
  sentinel command name (`swiftbash-only-marker`) that exists only
  in the shell's command table — nothing matches on the host's
  PATH. A regression that fell through to real exec would fail
  with "executable not found." The test asserts on a `REGISTRY-OK:`
  prefix produced by the registered closure.

- `subprocessRunWithCanonicalPathHitsBashBuiltin` overrides the
  registry's `echo` with a closure that prepends `BUILTIN:`. The
  canonical-path resolution rule
  (`BinCatalog.knownPaths["echo"] == "/bin/echo"`) routes the call
  through `BashProcessLauncher` to the override; a regression that
  invoked real `/bin/echo` would miss the prefix.

Both pass locally.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@odrobnik odrobnik merged commit d1d6518 into main May 9, 2026
5 checks passed
@odrobnik odrobnik deleted the feat/subprocess-e2e-test branch May 9, 2026 12:59
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.

1 participant