package main import ( "context" "os" "path/filepath" "testing" ) func TestScannerCountsAndExcludes(t *testing.T) { root := t.TempDir() if err := os.WriteFile(filepath.Join(root, "main.go"), []byte("package main\n\n// note\nfunc main() {}\n"), 0644); err != nil { t.Fatal(err) } if err := os.Mkdir(filepath.Join(root, "node_modules"), 0755); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(root, "node_modules", "bad.js"), []byte("alert(1)\n"), 0644); err != nil { t.Fatal(err) } langs, files, err := (Scanner{}).Analyze(context.Background(), root, []ExclusionRule{{Pattern: "node_modules"}}, func(int, string) {}) if err != nil { t.Fatal(err) } if len(langs) != 1 || langs[0].Name != "Go" { t.Fatalf("unexpected languages: %#v", langs) } if langs[0].Code != 2 || langs[0].Comments != 1 || langs[0].Blanks != 1 { t.Fatalf("unexpected count: %#v", langs[0]) } for _, f := range files { if f.Name == "bad.js" { t.Fatal("excluded file was scanned") } } } func TestWildcardMatch(t *testing.T) { cases := []struct { p, s string want bool }{{"*.log", "storage/app.log", true}, {"vendor", "vendor/a.php", true}, {"dist", "src/main.js", false}} for _, c := range cases { if got := wildcardMatch(c.p, c.s); got != c.want { t.Errorf("%s %s = %v", c.p, c.s, got) } } } func TestNestedGitignoreDoesNotExcludeSiblingSource(t *testing.T) { root := t.TempDir() dependency := filepath.Join(root, "vendor", "package") if err := os.MkdirAll(dependency, 0755); err != nil { t.Fatal(err) } // 依赖包中的局部规则只应作用于 vendor/package,不能过滤项目根目录。 if err := os.WriteFile(filepath.Join(dependency, ".gitignore"), []byte("*\n"), 0644); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(dependency, "ignored.go"), []byte("package ignored\n"), 0644); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(root, "main.go"), []byte("package main\nfunc main() {}\n"), 0644); err != nil { t.Fatal(err) } langs, files, err := (Scanner{}).Analyze(context.Background(), root, nil, func(int, string) {}) if err != nil { t.Fatal(err) } if len(langs) != 1 || langs[0].Name != "Go" || langs[0].Files != 1 { t.Fatalf("嵌套 .gitignore 错误影响了同级源码: %#v", langs) } for _, file := range files { if file.Name == "ignored.go" { t.Fatal("嵌套 .gitignore 未排除自身目录中的文件") } } }