Repository navigation
test: e2e suite against the compiled binary - #3
Merged
Merged
Conversation
added 3 commits
April 24, 2026 14:29
New e2e/ package. TestMain builds the hearsay binary into a temp dir
once per test run; each test then starts a subprocess with an isolated
HOME + scratch ~/.claude/projects/ tree and drives it over real HTTP.
Covers the cross-process paths the in-package unit tests don't reach:
* MCP streamable-HTTP handshake end-to-end
* get_peer_info / list_sessions / read_session over the wire,
via real mcp.StreamableClientTransport
* Bearer-token auth rejection (missing / wrong scheme / wrong token)
* 'hearsay invite' URI generation matches the on-disk token
* claude-md install/uninstall round-trip via the compiled binary
* 'hearsay pair' shells out to a stubbed `claude` on PATH; we
capture the argv and assert the shape of the 'claude mcp add'
invocation
Runs as part of 'go test ./...' — no new CI steps needed; existing
coverage gate is unaffected (e2e package has no production statements
to drive the aggregate number).
The .gitignore line 'hearsay' (no leading slash) was matching every
path component named 'hearsay' — including the cmd/hearsay/ source
directory. As a result cmd/hearsay/main.go and cmd/hearsay/main_test.go
were never committed to the repo despite existing on my working copy
for weeks. CI didn't catch it because:
- go build ./... and go test ./... silently skip packages whose
directories contain no .go files (from git's perspective, cmd/
on main is empty).
- The internal/ unit tests ran fine without the binary.
Adding the long-missing files and anchoring the gitignore rule to the
repo root (/hearsay) so only the compiled artifact at the root is
ignored. Now CI will actually build+test the hearsay binary itself.
The test passed 'nil' as the signal channel, assuming config.Resolve
would error out before the signal wait. On the GitHub Actions runner
that assumption didn't hold — something in the environment let
config.Resolve succeed (likely a pre-populated XDG_CONFIG_HOME), the
HTTP server booted for real, and <-nil blocks forever.
Defensive fix:
* clear XDG_CONFIG_HOME so Dir() resolves strictly under the
scratch HOME
* pre-signal the channel so the server shuts down even if Resolve
regresses in the future
* bind to an ephemeral port so parallel tests don't collide on :3456
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
e2e/package with a TestMain that builds the hearsay binary once; each test spins up a subprocess with isolated HOME + scratch~/.claude/projects/tree and drives it over real HTTP.get_peer_info/list_sessions/read_sessionover the wire, via realmcp.StreamableClientTransporthearsay inviteURI matches the on-disk tokenclaude-md install/uninstallround-trip via the binaryhearsay pairshells out correctly — stubbedclaudeon PATH captures argv; we assert theclaude mcp addinvocation shapeWhy
Existing unit tests hit ~94% via in-process transports and mocked helpers. E2E proves the process boundary (CLI parsing, on-disk config generation, HTTP listener, signal handling, real MCP transport) actually assembles.
Test plan
go test ./e2e/passes locally on macOS (~1.7s for 5 tests)