processor/file_test.go GO 374 lines View on github.com → Search inside
1// SPDX-License-Identifier: MIT23package processor45import (6	"math/rand/v2"7	"os"8	"path/filepath"9	"runtime"10	"testing"11)1213func TestGetExtension(t *testing.T) {14	got := getExtension("something.c")15	expected := "c"1617	if got != expected {18		t.Errorf("Expected %s got %s", expected, got)19	}20}2122func TestGetExtensionNoExtension(t *testing.T) {23	got := getExtension("something")24	expected := "something"2526	if got != expected {27		t.Errorf("Expected %s got %s", expected, got)28	}29}3031func TestGetExtensionMultipleDots(t *testing.T) {32	got := getExtension(".travis.yml")33	expected := "travis.yml"3435	if got != expected {36		t.Errorf("Expected %s got %s", expected, got)37	}38}3940func TestGetExtensionMultipleExtensions(t *testing.T) {41	got := getExtension("something.go.yml")42	expected := "go.yml"4344	if got != expected {45		t.Errorf("Expected %s got %s", expected, got)46	}47}4849func TestGetExtensionStartsWith(t *testing.T) {50	got := getExtension(".gitignore")51	expected := ".gitignore"5253	if got != expected {54		t.Errorf("Expected %s got %s", expected, got)55	}56}5758func TestGetExtensionTypeScriptDefinition(t *testing.T) {59	got := getExtension("test.d.ts")60	expected := "d.ts"6162	if got != expected {63		t.Errorf("Expected %s got %s", expected, got)64	}65}6667func TestGetExtensionSecondPass(t *testing.T) {68	got := getExtension("test.d.ts")69	got = getExtension(got)70	expected := "ts"7172	if got != expected {73		t.Errorf("Expected %s got %s", expected, got)74	}75}7677func TestNewFileJobCountAsPattern(t *testing.T) {78	defer func() {79		CountAsPattern = nil80		CountRules = nil81		compiledCountRules = nil82		delete(languageDatabase, "Ruby Spec")83		delete(languageDatabase, "Ruby App")84		delete(languageDatabase, "Rescued")85	}()8687	AllowListExtensions = []string{}88	// First matching rule wins, so the spec rule is ordered before a broad rule89	CountAsPattern = []string{90		"glob:*_spec.rb:Ruby Spec:Ruby",91		"glob:*.rb:Ruby App:Ruby",92		"glob:*.unknownext:Rescued:JavaScript",93	}94	CountRules = nil95	compiledCountRules = nil96	ProcessConstants()97	cleanVisitedPaths()9899	// A *_spec.rb path is relabelled to the new minted category100	fi, _ := os.Stat("../examples/countaspattern/foo_spec.rb")101	job := newFileJob("../examples/countaspattern/foo_spec.rb", "foo_spec.rb", fi)102	if job == nil || job.PossibleLanguages[0] != "Ruby Spec" {103		t.Fatalf("expected Ruby Spec, got %+v", job)104	}105106	// First-match-wins: app.rb matches *.rb only, so falls to the second rule107	cleanVisitedPaths()108	fi, _ = os.Stat("../examples/countaspattern/app.rb")109	job = newFileJob("../examples/countaspattern/app.rb", "app.rb", fi)110	if job == nil || job.PossibleLanguages[0] != "Ruby App" {111		t.Fatalf("expected Ruby App, got %+v", job)112	}113}114115func TestNewFileJobFullname(t *testing.T) {116	ProcessConstants()117	cleanVisitedPaths()118	AllowListExtensions = []string{}119120	fi, _ := os.Stat("../examples/issue114/makefile")121	job := newFileJob("../examples/issue114/", "makefile", fi)122123	if job.PossibleLanguages[0] != "Makefile" {124		t.Error("Expected makefile got", job.PossibleLanguages[0])125	}126}127128func TestNewFileJob(t *testing.T) {129	ProcessConstants()130	cleanVisitedPaths()131132	fi, _ := os.Stat("../examples/issue114/java")133	job := newFileJob("../examples/issue114/", "java", fi)134135	if job.PossibleLanguages[0] != "#!" {136		t.Error("Expected special value #! got", job.PossibleLanguages[0])137	}138}139140func TestNewFileJobGitIgnore(t *testing.T) {141	AllowListExtensions = []string{}142	ProcessConstants()143	cleanVisitedPaths()144	CountIgnore = true145146	fi, _ := os.Stat("../examples/issue114/.gitignore")147	job := newFileJob("../examples/issue114/", ".gitignore", fi)148149	if job.PossibleLanguages[0] != "gitignore" {150		t.Error("Expected gitignore got", job.PossibleLanguages[0])151	}152}153154func TestNewFileJobIgnore(t *testing.T) {155	AllowListExtensions = []string{}156	ProcessConstants()157	cleanVisitedPaths()158159	fi, _ := os.Stat("../examples/issue114/.ignore")160	job := newFileJob("../examples/issue114/", ".ignore", fi)161162	if job.PossibleLanguages[0] != "ignore" {163		t.Error("Expected ignore got", job.PossibleLanguages[0])164	}165}166167func TestNewFileJobLicense(t *testing.T) {168	ProcessConstants()169	cleanVisitedPaths()170171	fi, _ := os.Stat("../examples/issue114/license")172	job := newFileJob("../examples/issue114/", "license", fi)173174	if job.PossibleLanguages[0] != "License" {175		t.Error("Expected License got", job.PossibleLanguages[0])176	}177}178179func TestNewFileJobYAML(t *testing.T) {180	ProcessConstants()181	cleanVisitedPaths()182183	fi, _ := os.Stat("../examples/issue114/.travis.yml")184	job := newFileJob("../examples/issue114/", ".travis.yml", fi)185186	found := false187	for _, j := range job.PossibleLanguages {188		if j == "YAML" {189			found = true190		}191	}192193	if !found {194		t.Error("Expected YAML in but didn't find", job.PossibleLanguages)195	}196}197198func TestNewFileJobYAMLCloudformation(t *testing.T) {199	ProcessConstants()200	cleanVisitedPaths()201202	fi, _ := os.Stat("../examples/issue114/.travis.yml")203	job := newFileJob("../examples/issue114/", ".travis.yml", fi)204205	found := false206	for _, j := range job.PossibleLanguages {207		if j == "CloudFormation (YAML)" {208			found = true209		}210	}211212	if !found {213		t.Error("Expected CloudFormation in but didn't find", job.PossibleLanguages)214	}215}216217func TestNewFileJobSize(t *testing.T) {218	ProcessConstants()219	cleanVisitedPaths()220	NoLarge = true221	LargeByteCount = 1222223	fi, _ := os.Stat("file_test.go")224	job := newFileJob("file_test.go", "file_test.go", fi)225226	if job != nil {227		t.Error("Expected nil got", job)228	}229230	NoLarge = false231	LargeByteCount = 1000000232}233234func TestNewFileJobBrokenSymlink(t *testing.T) {235	if runtime.GOOS == "windows" {236		t.Skip("skipping symlink test on Windows due to privilege requirements")237	}238239	ProcessConstants()240	cleanVisitedPaths()241	IncludeSymLinks = true242	defer func() {243		IncludeSymLinks = false244	}()245246	// Create a temp directory to work in247	file := filepath.Join(t.TempDir(), "source.go")248	err := os.WriteFile(file, []byte("package main\n"), 0644)249	if err != nil {250		t.Fatal(err)251	}252	symPath := filepath.Join(t.TempDir(), "broken.go")253	err = os.Symlink(file, symPath)254	if err != nil {255		t.Fatal(err)256	}257	// Delete the file breaks the symlink258	err = os.Remove(file)259	if err != nil {260		t.Fatal(err)261	}262263	fi, _ := os.Lstat(symPath)264	job := newFileJob(symPath, "broken.go", fi)265266	if job != nil {267		t.Error("Expected nil for broken symlink got", job)268	}269}270271func BenchmarkGetExtensionDifferent(b *testing.B) {272	for i := 0; i < b.N; i++ {273274		b.StopTimer()275		name := randStringBytes(3) + "." + randStringBytes(2)276		b.StartTimer()277278		getExtension(name)279	}280}281282func BenchmarkGetExtensionSame(b *testing.B) {283	name := randStringBytes(7) + "." + randStringBytes(3)284285	for i := 0; i < b.N; i++ {286		getExtension(name)287	}288}289290const letterBytes = "abcdefghijklmnopqrstuvwxyz"291292func randStringBytes(n int) string {293	b := make([]byte, n)294	for i := range b {295		b[i] = letterBytes[rand.IntN(len(letterBytes))]296	}297	return string(b)298}299300func TestNewFileJobCircularSymlink(t *testing.T) {301	if runtime.GOOS == "windows" {302		t.Skip("skipping symlink test on Windows due to privilege requirements")303	}304	ProcessConstants()305	cleanVisitedPaths()306	IncludeSymLinks = true307	defer func() { IncludeSymLinks = false }()308309	// Create a temp directory to work in310	dir, _ := filepath.EvalSymlinks(t.TempDir())311	link1 := filepath.Join(dir, "link1.go")312	link2 := filepath.Join(dir, "link2.go")313	// Create a loop: link1 -> link2 and link2 -> link1314	if err := os.Symlink(link2, link1); err != nil {315		t.Fatal("Failed to create first link:", err)316	}317	if err := os.Symlink(link1, link2); err != nil {318		t.Fatal("Failed to create circular link:", err)319	}320321	fi, err := os.Lstat(link1)322	if err != nil {323		t.Fatal(err)324	}325	// It should return the 'too many links' error.326	job := newFileJob(link1, "link1.go", fi)327328	if job != nil {329		t.Error("Expected nil for circular symlink, but got a FileJob")330	}331}332333func TestNewFileJobDuplicateCounting(t *testing.T) {334	if runtime.GOOS == "windows" {335		t.Skip("skipping symlink test on Windows due to privilege requirements")336	}337	ProcessConstants()338	cleanVisitedPaths()339	IncludeSymLinks = true340	defer func() { IncludeSymLinks = false }()341342	// on some systems like macOS, t.TempDir is also a symlink343	dir, _ := filepath.EvalSymlinks(t.TempDir())344	// Create a test file345	testFile := filepath.Join(dir, "file.go")346347	if err := os.WriteFile(testFile, []byte("package main"), 0644); err != nil {348		t.Fatal(err)349	}350351	// Create a symlink to the same file352	linkFile := filepath.Join(dir, "link.go")353	if err := os.Symlink(testFile, linkFile); err != nil {354		t.Fatalf("Failed to create link file: %s", err)355	}356	// Process the test file357	fi1, _ := os.Lstat(testFile)358	job1 := newFileJob(testFile, "file.go", fi1)359360	// Process the symlink (same target)361	fi2, _ := os.Lstat(linkFile)362	job2 := newFileJob(linkFile, "link.go", fi2)363364	// First count should go through365	if job1 == nil {366		t.Fatal("Expected first file job to be created")367	}368369	// Second count should be skipped370	if job2 != nil {371		t.Error("Expected nil for duplicate file through symlink, but got a FileJob")372	}373}

Code quality findings 7

Blank identifier discarding results; verify intentional ignoring of return values
warning correctness blank-identifier-discard
fi, _ = os.Stat("../examples/countaspattern/app.rb")
Can cause issues on Windows consider filepath.Join instead
info correctness path-join-windows
file := filepath.Join(t.TempDir(), "source.go")
Can cause issues on Windows consider filepath.Join instead
info correctness path-join-windows
symPath := filepath.Join(t.TempDir(), "broken.go")
Can cause issues on Windows consider filepath.Join instead
info correctness path-join-windows
link1 := filepath.Join(dir, "link1.go")
Can cause issues on Windows consider filepath.Join instead
info correctness path-join-windows
link2 := filepath.Join(dir, "link2.go")
Can cause issues on Windows consider filepath.Join instead
info correctness path-join-windows
testFile := filepath.Join(dir, "file.go")
Can cause issues on Windows consider filepath.Join instead
info correctness path-join-windows
linkFile := filepath.Join(dir, "link.go")

Get this view in your editor

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