test: realistic-client protocol coverage (40 new integration tests) #20

merged colechristensen cole.christensen@gmail.com wants to merge test/realistic-client-protocol-coverage into main
No CI

Closes #30 at the test-writing level (the underlying feature gaps remain tracked in #30).

Summary

40 new integration tests across 6 suites that drive real `git` CLI invocations and real HTTP clients through `UploadPackV2` and `ReceivePack`. Motivation: after the two back-to-back UploadPackV2 regressions (PR #18, PR #19), we needed actual client-facing coverage for every advertised capability and every negotiation path — the bugs all hid in paths no test drove a real client through.

Zero production code changes. Each skipped test links its tracking note (capability gap or known bug).

What’s new

Shared harness — `test/support/git_daemon.ex`:

  • `start_upload_pack/1` — git:// TCP daemon → UploadPackV2
  • `start_receive_pack/2` — git:// TCP daemon → ReceivePack (hooks forwardable)
  • `start_http_smart/2` — HTTP/1.1 mini-server routing GET /info/refs + POST /git-(upload|receive)-pack. No Plug/Cowboy dep; ~100 lines of raw :gen_tcp.
  • Helpers: `git_at`, `git!`, `init_client_dir`, `seed_client_clone`
  • Per-connection `repo_fun` for stale-haves scenarios.

Six new test files in `test/ex_git_objectstore/integration/`:

File What it covers
`git_daemon_smoke_test.exs` Harness smoke checks
`upload_pack_v2_negotiation_test.exs` Stale haves, partial overlap, deep divergence, negotiate-only, concurrent push/fetch
`upload_pack_v2_capabilities_test.exs` symrefs, peel, unborn, shallow, deepen, blob:none, tree:0, wait-for-done, advertisement canary
`upload_pack_v2_dataplane_test.exs` >64KB sideband, >1MB pack (slow), 250 refs, ref-prefix filter, client disconnect mid-pack, TCP-chunk invariance
`receive_pack_git_client_test.exs` new branch, FF, non-FF ± –force, delete ref, –atomic, update-hook rejection, thin-pack REF_DELTA, concurrent push
`smart_http_test.exs` clone / fetch / push over HTTP, two-daemon stale-haves, direct POST (no git client) — hits the done+haves+no-match path the git CLI avoids

Results

`mix test –include integration`:

``` 753 tests, 0 failures, 12 skipped (35 excluded) ```

Broken-down: ~40 new tests in this PR, 12 of them are currently skipped with a `@tag skip: “…”` message explaining what’s missing. They become active once the referenced capability or bug is addressed.

Bugs found while writing

  • Issue #29 — `UploadPackV2.feed/2`’s `has_complete_command?` treats `delim` (`0001`) as a command terminator. TCP-chunked requests that split between delim and flush cause the state machine to process an incomplete command and transition to `:done`, ignoring the rest. Caught by `test “fetch request response is invariant under TCP chunking”` in the dataplane suite (skipped pending fix).
  • The direct-POST HTTP test deterministically reproduces the bug PR #19 fixes (`expected ‘acknowledgments’, received ‘packfile’`). Skipped pending PR #19 merge.

Follow-ups

All skipped-test feature gaps are indexed in the master tracking issue #30.

Test plan

  • `mix test –include integration` — 753 pass, 12 skipped
  • `mix format –check-formatted`
  • `mix credo –strict` on touched files — zero issues
  • CI green
Created Apr 19, 2026 at 00:04 UTC | Merged Apr 19, 2026 at 02:06 UTC by colechristensen cole.christensen@gmail.com