Blank identifier discarding results; verify intentional ignoring of return values
_ = os.Setenv("PATH", savePath)
1// SPDX-License-Identifier: MIT23package processor45import (6 "os"7 "path/filepath"8 "testing"9 "time"1011 "github.com/go-git/go-git/v5"12 "github.com/go-git/go-git/v5/plumbing/object"13)1415// makeFixtureRepo initialises a real on-disk repo in a temp dir and lets the16// caller commit a sequence of (path -> content) snapshots. Returns the repo17// path so tests can pass it to runHistory.18//19// We use PlainInit (not an in-memory storer) because scc's classifier needs20// to detect languages from file names — same as a normal scc run — and the21// engine itself only talks to go-git, so no shell-out happens.22func makeFixtureRepo(t *testing.T, commits []map[string]string) string {23 t.Helper()24 ProcessConstants()25 dir := t.TempDir()2627 repo, err := git.PlainInit(dir, false)28 if err != nil {29 t.Fatalf("init repo: %v", err)30 }31 wt, err := repo.Worktree()32 if err != nil {33 t.Fatalf("worktree: %v", err)34 }3536 when := time.Date(2025, 1, 1, 12, 0, 0, 0, time.UTC)37 for i, snap := range commits {38 for path, content := range snap {39 full := filepath.Join(dir, path)40 if err := os.MkdirAll(filepath.Dir(full), 0o755); err != nil {41 t.Fatalf("mkdir %s: %v", full, err)42 }43 if err := os.WriteFile(full, []byte(content), 0o644); err != nil {44 t.Fatalf("write %s: %v", full, err)45 }46 if _, err := wt.Add(path); err != nil {47 t.Fatalf("add %s: %v", path, err)48 }49 }50 _, err := wt.Commit("commit "+itoa(i), &git.CommitOptions{51 Author: &object.Signature{52 Name: "Author " + itoa(i%2),53 Email: "author" + itoa(i%2) + "@example.com",54 When: when.Add(time.Duration(i) * time.Hour),55 },56 })57 if err != nil {58 t.Fatalf("commit %d: %v", i, err)59 }60 }61 return dir62}6364// captureObserver records observe calls so tests can assert on them.65type captureObserver struct {66 commits []CommitInfo67 changes [][]FileChange68 window HistoryWindow69 snapshot HeadSnapshot70}7172func (c *captureObserver) Observe(info CommitInfo, changes []FileChange) {73 c.commits = append(c.commits, info)74 c.changes = append(c.changes, changes)75}7677func (c *captureObserver) Finalise(w HistoryWindow, s HeadSnapshot) {78 c.window = w79 c.snapshot = s80}8182func TestRunHistoryWalksOldestFirstAndCollectsChanges(t *testing.T) {83 // Set depth/flags to defaults this test cares about.84 saveDepth := HistoryDepth85 HistoryDepth = 10086 t.Cleanup(func() { HistoryDepth = saveDepth })8788 dir := makeFixtureRepo(t, []map[string]string{89 {"a.go": "package a\n\nfunc A() {}\n"},90 {"a.go": "package a\n\nfunc A() {}\nfunc B() {}\n"},91 {"a.go": "package a\n\nfunc A() {}\nfunc B() {}\nfunc C() {}\n"},92 })9394 cap := &captureObserver{}95 window, err := runHistory(dir, cap)96 if err != nil {97 t.Fatalf("runHistory: %v", err)98 }99100 if want := 3; window.Commits != want {101 t.Fatalf("window.Commits = %d, want %d", window.Commits, want)102 }103 if len(cap.commits) != 3 {104 t.Fatalf("observed %d commits, want 3", len(cap.commits))105 }106 // Oldest-first ordering: each commit's When should be >= previous.107 for i := 1; i < len(cap.commits); i++ {108 if cap.commits[i].When.Before(cap.commits[i-1].When) {109 t.Fatalf("commits not oldest-first: commit %d %s before %s",110 i, cap.commits[i].When, cap.commits[i-1].When)111 }112 }113 // Snapshot should contain a.go in HEAD.114 if _, ok := cap.snapshot.Files["a.go"]; !ok {115 t.Fatalf("HEAD snapshot missing a.go; got %v", cap.snapshot.Files)116 }117}118119func TestRunHistoryDepthCap(t *testing.T) {120 saveDepth := HistoryDepth121 HistoryDepth = 2122 t.Cleanup(func() { HistoryDepth = saveDepth })123124 dir := makeFixtureRepo(t, []map[string]string{125 {"a.go": "package a\nfunc A() {}\n"},126 {"a.go": "package a\nfunc A() {}\nfunc B() {}\n"},127 {"a.go": "package a\nfunc A() {}\nfunc B() {}\nfunc C() {}\n"},128 {"a.go": "package a\nfunc A() {}\nfunc B() {}\nfunc C() {}\nfunc D() {}\n"},129 })130131 cap := &captureObserver{}132 if _, err := runHistory(dir, cap); err != nil {133 t.Fatalf("runHistory: %v", err)134 }135 if len(cap.commits) != 2 {136 t.Fatalf("with --depth=2 observed %d commits, want 2", len(cap.commits))137 }138}139140func TestRunHistorySkipsBinaryAndUnknown(t *testing.T) {141 saveDepth := HistoryDepth142 HistoryDepth = 10143 t.Cleanup(func() { HistoryDepth = saveDepth })144145 dir := makeFixtureRepo(t, []map[string]string{146 {147 "main.go": "package main\nfunc main() {}\n",148 "weird-extension.xx": "no language for this\n",149 "data.bin": "\x00\x01\x02\x03\x00binary",150 },151 })152153 cap := &captureObserver{}154 if _, err := runHistory(dir, cap); err != nil {155 t.Fatalf("runHistory: %v", err)156 }157 if len(cap.changes) != 1 {158 t.Fatalf("expected one Observe call, got %d", len(cap.changes))159 }160 // Only main.go should survive.161 paths := []string{}162 for _, fc := range cap.changes[0] {163 paths = append(paths, fc.Path)164 }165 if len(paths) != 1 || paths[0] != "main.go" {166 t.Fatalf("expected only main.go, got %v", paths)167 }168}169170// TestRunHistoryWithoutGitInPath confirms the engine has no shell-out to the171// git binary by running the walk with PATH stripped to /nonexistent.172func TestRunHistoryWithoutGitInPath(t *testing.T) {173 savePath := os.Getenv("PATH")174 saveDepth := HistoryDepth175 HistoryDepth = 10176 t.Cleanup(func() {177 _ = os.Setenv("PATH", savePath)178 HistoryDepth = saveDepth179 })180181 dir := makeFixtureRepo(t, []map[string]string{182 {"a.go": "package a\nfunc A() {}\n"},183 {"a.go": "package a\nfunc A() { if true {} }\n"},184 })185186 // Strip PATH so any accidental exec.Command would fail.187 if err := os.Setenv("PATH", "/nonexistent"); err != nil {188 t.Fatalf("setenv: %v", err)189 }190191 cap := &captureObserver{}192 if _, err := runHistory(dir, cap); err != nil {193 t.Fatalf("runHistory: %v", err)194 }195 if len(cap.commits) != 2 {196 t.Fatalf("expected 2 commits, got %d", len(cap.commits))197 }198}199200func TestLineCountHelper(t *testing.T) {201 cases := []struct {202 in string203 want int204 }{205 {"", 0},206 {"a", 1},207 {"a\n", 1},208 {"a\nb", 2},209 {"a\nb\n", 2},210 {"\n", 1},211 }212 for _, c := range cases {213 if got := lineCount(c.in); got != c.want {214 t.Errorf("lineCount(%q) = %d, want %d", c.in, got, c.want)215 }216 }217}
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.