From 32fa3cbb537cbad8f412cc82ff63125744f323d4 Mon Sep 17 00:00:00 2001 From: hive-quality Date: Mon, 7 Sep 2026 09:34:49 -0400 Subject: [PATCH] [quality] test: cover commitsBehindStableV4 dispatch branches (pkg/hub/commit_behind.go) commitsBehindStableV4 was 50% covered: only the cache-hit read path had tests. Cover the remaining dispatch branches: - same-commit short-circuit (prefix-matching base answers 0-behind with no compare dispatched) - empty-SHA guards (empty base, and missing stable-branch head SHA) - in-flight dedupe (a pending compare is not re-dispatched and answers unknown without blocking) - cache-miss async dispatch (stubbed fetch, canonical short-SHA key, result eventually cached and served) Function coverage: 50.0% -> 100.0%. No production code changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: hive-quality --- src/pkg/hub/commit_behind_test.go | 85 +++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/src/pkg/hub/commit_behind_test.go b/src/pkg/hub/commit_behind_test.go index b2fb897ad..8079a492d 100644 --- a/src/pkg/hub/commit_behind_test.go +++ b/src/pkg/hub/commit_behind_test.go @@ -7,6 +7,7 @@ import ( "net/http" "net/http/httptest" "testing" + "time" ) func resetCommitBehindState(t *testing.T) { @@ -55,6 +56,90 @@ func TestResolveCommitBehindCachesKnownAndUnknown(t *testing.T) { } } +func TestCommitsBehindStableV4SameCommitShortCircuits(t *testing.T) { + resetCommitBehindState(t) + // A base that prefix-matches the stable head must report 0-behind + // immediately, with no compare dispatched. + got, known := commitsBehindStableV4("head999extended", nil) + if !known || got != 0 { + t.Fatalf("same-commit result = %d,%v; want 0,true", got, known) + } + commitBehindMu.Lock() + defer commitBehindMu.Unlock() + if len(commitBehindInFlight) != 0 { + t.Fatal("same-commit path must not dispatch a compare") + } +} + +func TestCommitsBehindStableV4EmptySHAsStayUnknown(t *testing.T) { + resetCommitBehindState(t) + if _, known := commitsBehindStableV4("", nil); known { + t.Fatal("empty base SHA must stay unknown") + } + + // No cached SHA for the stable branch → empty head → unknown. + latestSHAMu.Lock() + delete(latestSHAByBranch, stableReleaseBranch) + latestSHAMu.Unlock() + if _, known := commitsBehindStableV4("base111", nil); known { + t.Fatal("missing stable-branch head SHA must stay unknown") + } + commitBehindMu.Lock() + defer commitBehindMu.Unlock() + if len(commitBehindInFlight) != 0 { + t.Fatal("empty-SHA guard must not dispatch a compare") + } +} + +func TestCommitsBehindStableV4InFlightDedupes(t *testing.T) { + resetCommitBehindState(t) + key := commitBehindKey{base: "base111", head: "head999"} + commitBehindMu.Lock() + commitBehindInFlight[key] = true + fetchCommitBehindCount = func(base, head string, logger *slog.Logger) (int, bool, error) { + t.Error("in-flight compare must not be re-dispatched") + return 0, false, nil + } + commitBehindMu.Unlock() + + if _, known := commitsBehindStableV4("base111", nil); known { + t.Fatal("in-flight compare must report unknown, not block") + } +} + +func TestCommitsBehindStableV4DispatchesAndCaches(t *testing.T) { + resetCommitBehindState(t) + commitBehindMu.Lock() + fetchCommitBehindCount = func(base, head string, logger *slog.Logger) (int, bool, error) { + if base != "base111" || head != "head999" { + t.Errorf("compare dispatched with %s...%s; want base111...head999", base, head) + } + return 5, true, nil + } + commitBehindMu.Unlock() + + // Cache miss: first call answers unknown and dispatches the compare + // asynchronously; note the base is truncated to the canonical short form. + if _, known := commitsBehindStableV4("base111full", nil); known { + t.Fatal("cache miss must answer unknown while the compare runs") + } + + deadline := time.Now().Add(5 * time.Second) + for { + got, known := commitsBehindStableV4("base111full", nil) + if known { + if got != 5 { + t.Fatalf("cached count = %d; want 5", got) + } + return + } + if time.Now().After(deadline) { + t.Fatal("compare result never cached") + } + time.Sleep(10 * time.Millisecond) + } +} + func TestResolveCommitBehindErrorNotCached(t *testing.T) { resetCommitBehindState(t) key := commitBehindKey{base: "base111", head: "head999"}