processor/history_cache_test.go GO 126 lines View on github.com → Search inside
1// SPDX-License-Identifier: MIT23package processor45import (6	"testing"78	"github.com/go-git/go-git/v5/plumbing"9)1011// TestBlobClassifyCacheMemoisesByHash verifies the cache returns the same12// result for repeated lookups of the same hash and only adds one entry.13// The classify method is the only call site for classifyHistoryBlob inside14// the cache, so len(cache.entries) is the underlying classifier call count.15func TestBlobClassifyCacheMemoisesByHash(t *testing.T) {16	ProcessConstants()17	cache := newBlobClassifyCache()18	blob := []byte("package a\nfunc A() {}\n")19	hash := plumbing.ComputeHash(plumbing.BlobObject, blob)2021	r1 := cache.classify(hash, "a.go", blob)22	r2 := cache.classify(hash, "a.go", blob)2324	if !r1.ok || !r2.ok {25		t.Fatalf("expected ok=true for both lookups, got %v / %v", r1.ok, r2.ok)26	}27	if r1.language != r2.language {28		t.Fatalf("language mismatch across hits: %q vs %q", r1.language, r2.language)29	}30	if got := len(cache.entries); got != 1 {31		t.Fatalf("expected 1 cache entry after two lookups of the same hash, got %d", got)32	}33}3435// TestBlobClassifyCacheKeysByHashNotPath confirms two different paths36// pointing at the same blob (a rename) classify once. The cache is37// hash-keyed by design — the rename inherits the original language.38func TestBlobClassifyCacheKeysByHashNotPath(t *testing.T) {39	ProcessConstants()40	cache := newBlobClassifyCache()41	content := []byte("package a\nfunc A() {}\n")42	hash := plumbing.ComputeHash(plumbing.BlobObject, content)4344	r1 := cache.classify(hash, "a.go", content)45	r2 := cache.classify(hash, "renamed.go", content)4647	if !r1.ok || !r2.ok {48		t.Fatalf("expected ok=true for both, got %v / %v", r1.ok, r2.ok)49	}50	if len(cache.entries) != 1 {51		t.Fatalf("expected 1 cache entry for same hash on different paths, got %d", len(cache.entries))52	}53	if r1.language != r2.language {54		t.Fatalf("expected same language for same hash; got %q vs %q", r1.language, r2.language)55	}56}5758// TestBlobClassifyCacheNegativeCaching confirms a blob the classifier59// rejects (unknown extension) is cached with ok=false. A repeat lookup of60// the same hash is a hit, so the classifier does not run a second time.61func TestBlobClassifyCacheNegativeCaching(t *testing.T) {62	ProcessConstants()63	cache := newBlobClassifyCache()64	blob := []byte("nothing identifiable here\n")65	hash := plumbing.ComputeHash(plumbing.BlobObject, blob)6667	r1 := cache.classify(hash, "weird.xx", blob)68	r2 := cache.classify(hash, "weird.xx", blob)6970	if r1.ok || r2.ok {71		t.Fatalf("expected ok=false for unknown-extension blob, got %v / %v", r1.ok, r2.ok)72	}73	if len(cache.entries) != 1 {74		t.Fatalf("expected negative result to be cached as 1 entry, got %d", len(cache.entries))75	}76}7778// TestBlobClassifyCacheSeparatesByHash sanity-checks that distinct hashes79// produce distinct cache entries.80func TestBlobClassifyCacheSeparatesByHash(t *testing.T) {81	ProcessConstants()82	cache := newBlobClassifyCache()83	a := []byte("package a\nfunc A() {}\n")84	b := []byte("package a\nfunc A() {}\nfunc B() {}\n")85	ha := plumbing.ComputeHash(plumbing.BlobObject, a)86	hb := plumbing.ComputeHash(plumbing.BlobObject, b)8788	cache.classify(ha, "a.go", a)89	cache.classify(hb, "a.go", b)90	cache.classify(ha, "a.go", a)9192	if len(cache.entries) != 2 {93		t.Fatalf("expected 2 cache entries for 2 distinct hashes, got %d", len(cache.entries))94	}95}9697// TestRunHistoryStillProducesHeadAndChanges is a smoke test that confirms98// threading the cache through runHistory / buildBaselineForObserver /99// commitChanges / buildHeadSnapshot doesn't change observable behavior: HEAD100// and per-commit changes still classify correctly.101func TestRunHistoryStillProducesHeadAndChanges(t *testing.T) {102	saveDepth := HistoryDepth103	HistoryDepth = 10104	t.Cleanup(func() { HistoryDepth = saveDepth })105106	dir := makeFixtureRepo(t, []map[string]string{107		{"a.go": "package a\nfunc A() {}\n"},108		{"b.go": "package b\nfunc B() {}\n"},109		{"c.go": "package c\nfunc C() {}\n"},110	})111112	cap := &captureObserver{}113	if _, err := runHistory(dir, cap); err != nil {114		t.Fatalf("runHistory: %v", err)115	}116	for _, name := range []string{"a.go", "b.go", "c.go"} {117		hf, ok := cap.snapshot.Files[name]118		if !ok {119			t.Fatalf("HEAD snapshot missing %s; got %v", name, cap.snapshot.Files)120		}121		if hf.Language != "Go" {122			t.Errorf("%s language = %q, want Go", name, hf.Language)123		}124	}125}

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.