diff options
Diffstat (limited to 'internal/ignore/oracle_test.go')
| -rw-r--r-- | internal/ignore/oracle_test.go | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/internal/ignore/oracle_test.go b/internal/ignore/oracle_test.go new file mode 100644 index 0000000..a5a589c --- /dev/null +++ b/internal/ignore/oracle_test.go @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package ignore + +import ( + "os" + "os/exec" + "path/filepath" + "sort" + "strings" + "testing" +) + +var oracleFiles = []string{ + "a.txt", "b.log", "a1.txt", "abc", ".hidden", "foo.part", "keep.part", + "dir/c.txt", "dir/d.log", "dir/.hidden2", "dir/sub/e.txt", + "build/out.bin", "src/build/x.go", "doc/readme.md", "doc/sub/readme.md", + "deep/a/b/c/file.tmp", "x/z.txt", "x/y/z.txt", "sub/f.txt", "space name.txt", + "x]y", "xay", "xby", "a/b", "1.txt", "]a.txt", + "a.b", "xyz", "aq", "bq", +} + +var oracleSets = [][]string{ + {"*.log"}, {"/a.txt"}, {"build/"}, {"doc/*.md"}, {"**/readme.md"}, + {"deep/**"}, {"x/**/z.txt"}, {"*.part", "!keep.part"}, {".*"}, + {"a?.txt", "[ab]*.txt"}, {"[!a]*.txt"}, {"dir/", "!dir/c.txt"}, + {"sub"}, {"space name.txt"}, {"*", "!*.txt"}, {"dir/**/*.txt"}, + {"x[]a]y"}, {"a[/]b"}, {"[[:digit:]]*.txt"}, {"[!]a]*"}, + {"a[[:punct:]]b"}, {"x[[:alpha:]]z"}, {"[a\\b]q"}, +} + +// TestAgainstGit compares every file and directory of a real tree against +// `git check-ignore --no-index` for each pattern set. +func TestAgainstGit(t *testing.T) { + if _, err := exec.LookPath("git"); err != nil { + t.Skip("git not installed") + } + root := t.TempDir() + t.Setenv("HOME", root) + t.Setenv("GIT_CONFIG_GLOBAL", os.DevNull) + t.Setenv("GIT_CONFIG_NOSYSTEM", "1") + for _, f := range oracleFiles { + p := filepath.Join(root, f) + if err := os.MkdirAll(filepath.Dir(p), 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(p, nil, 0o644); err != nil { + t.Fatal(err) + } + } + if out, err := exec.Command("git", "-C", root, "init", "-q").CombinedOutput(); err != nil { + t.Fatalf("git init: %v %s", err, out) + } + // every path in the tree, files and directories, relative and slash-separated + var paths []string + isDir := map[string]bool{} + filepath.WalkDir(root, func(p string, d os.DirEntry, err error) error { + rel, _ := filepath.Rel(root, p) + if rel == "." || rel == ".git" || strings.HasPrefix(rel, ".git"+string(filepath.Separator)) || rel == ".gitignore" { + if rel == ".git" { + return filepath.SkipDir + } + return nil + } + rel = filepath.ToSlash(rel) + paths = append(paths, rel) + isDir[rel] = d.IsDir() + return nil + }) + sort.Strings(paths) + for _, set := range oracleSets { + if err := os.WriteFile(filepath.Join(root, ".gitignore"), []byte(strings.Join(set, "\n")+"\n"), 0o644); err != nil { + t.Fatal(err) + } + cmd := exec.Command("git", "-C", root, "check-ignore", "--no-index", "--stdin") + cmd.Stdin = strings.NewReader(strings.Join(paths, "\n") + "\n") + out, _ := cmd.Output() // exit status 1 means "nothing ignored" + gitIgnored := map[string]bool{} + for _, l := range strings.Split(strings.TrimSpace(string(out)), "\n") { + if l != "" { + gitIgnored[strings.TrimSuffix(l, "/")] = true + } + } + m, err := New(set) + if err != nil { + t.Fatalf("New(%q): %v", set, err) + } + for _, p := range paths { + if got := m.Match(p, isDir[p]); got != gitIgnored[p] { + t.Errorf("patterns %q, path %q (dir=%v): krino says %v, git says %v", set, p, isDir[p], got, gitIgnored[p]) + } + } + } +} |
