ref:176c8af20558ccb4dfc01c65c63d0d34db9eeb6b

test: close audit gaps — strengthen assertions, drive telemetry via real git

Four items from the branch audit, landed together: 1. Filter integration tests (blob:none, tree:0, object:type=commit, combine, sparse:oid) now assert directly on pack contents via `git cat-file --batch-check --batch-all-objects`. Earlier versions passed if the server merely advertised `filter` and returned code 0 — a full pack from a filter-ignoring server would have slipped through. New helpers `count_local_objects_by_type/1`, `local_object_shas/1`, and `assert_promisor_configured/1`. `--no-checkout` is used so post-clone lazy-fetches don't pollute the counts. 2. "Concurrent fetch and push" test was running on two separate daemon ports, so nothing actually raced. Replaced with two tests that hit shared state: a. two concurrent clones against the SAME upload-pack port — forces the accept loop to spawn two independent handlers and asserts both produce matching HEADs. b. clone + push against the same shared repo (upload-pack and receive-pack daemons pointing at one Memory backend) — asserts both operations complete, the ref landed, and `git fsck` on the clone is clean. 3. "hook_rejected" detail-preservation test was ignoring the push exit code (`{out, _code}`). Now asserts `refute code == 0` and also that the target ref was not moved on the server. 4. Atomic-receive-pack telemetry test was poking at a `%ReceivePack{}` struct directly to trigger the span. Rewritten to drive the real TCP daemon with a `git push --atomic` subprocess, so the telemetry path executes exactly as it does in production. All 798 tests pass.
SHA: 176c8af20558ccb4dfc01c65c63d0d34db9eeb6b
Author: Cole Christensen <cole.christensen@macmillan.com>
Date: 2026-04-19 01:43
Parents: 86dbb1b
4 files changed +229 -74
Type
test/ex_git_objectstore/protocol/telemetry_test.exs +39 −32
@@ -16,17 +16,22 @@
@moduledoc """
Operational coverage: every new code path added in the recent
protocol-v2 work must emit a telemetry event with useful payload.
Fetch / filter coverage drives the UploadPackV2 state machine
directly (no network). Atomic receive-pack coverage drives a
real `git push --atomic` subprocess against a TCP daemon so the
telemetry path executes exactly as it would in production.
"""
use ExUnit.Case, async: false
alias ExGitObjectstore.Object
alias ExGitObjectstore.Object.{Blob, Commit, Tree}
alias ExGitObjectstore.Protocol.{PktLine, ReceivePack, UploadPackV2}
alias ExGitObjectstore.Protocol.{PktLine, UploadPackV2}
alias ExGitObjectstore.Ref
alias ExGitObjectstore.Test.RepoHelper
alias ExGitObjectstore.Test.{GitDaemon, RepoHelper}
@zero_sha String.duplicate("0", 40)
@moduletag timeout: :timer.minutes(1)
setup do
test_pid = self()
@@ -139,33 +144,44 @@
end
describe "atomic receive-pack telemetry" do
@tag :integration
@tag :tmp_dir
test "emits :start and :stop with outcome=:committed on real `git push --atomic`",
test "emits :start and :stop with outcome=:committed on success" do
%{tmp_dir: tmp_dir} do
repo = RepoHelper.memory_repo("tel-atomic-ok")
ExGitObjectstore.init(repo)
commit_sha = make_commit(repo, "content\n")
{port, stop} = GitDaemon.start_receive_pack(repo)
try do
client = GitDaemon.init_client_dir(tmp_dir)
File.write!(Path.join(client, "a.txt"), "hi\n")
GitDaemon.git!(client, ["add", "a.txt"])
GitDaemon.git!(client, ["commit", "-m", "first"])
{_advert, state} = ReceivePack.init(repo)
state = %{
state
{_out, code} =
GitDaemon.git_at(client, [
"push",
"--atomic",
"git://127.0.0.1:#{port}/repo",
"main:refs/heads/a",
"main:refs/heads/b"
])
assert code == 0
| client_caps: MapSet.new(["report-status", "atomic"]),
commands: [
%{ref: "refs/heads/a", old_sha: @zero_sha, new_sha: commit_sha},
%{ref: "refs/heads/b", old_sha: @zero_sha, new_sha: commit_sha}
],
phase: :pack
}
# Drive through the pack-stage to trigger ref-update processing.
# With no pack bytes and all-creates, ReceivePack treats it as
# the "all-creates, pack optional" path and runs ref updates.
assert_receive {:telemetry,
[:ex_git_objectstore, :protocol, :receive_pack, :atomic, :stop],
%{duration: duration},
%{outcome: :committed, commands: 2, validation_failures: 0}}
{_report, _final} = ReceivePack.feed(state, empty_pack())
assert_receive {:telemetry, [:ex_git_objectstore, :protocol, :receive_pack, :atomic, :stop],
%{duration: duration},
assert duration > 0
%{outcome: :committed, commands: 2, validation_failures: 0}}
# And the refs actually landed.
{:ok, _} = Ref.get(repo, "refs/heads/a")
{:ok, _} = Ref.get(repo, "refs/heads/b")
after
assert duration > 0
stop.()
end
end
end
@@ -188,14 +204,5 @@
{:ok, sha} = Object.write(repo, commit)
sha
end
# Empty pack (header + checksum) — enough for ReceivePack's
# `check_pack_complete/1` to declare the pack phase done so the
# state machine runs ref updates.
defp empty_pack do
header = <<"PACK", 2::unsigned-big-32, 0::unsigned-big-32>>
checksum = :crypto.hash(:sha, header)
<<header::binary, checksum::binary>>
end
end