aboutsummaryrefslogtreecommitdiff
path: root/internal/ignore/oracle_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/ignore/oracle_test.go')
-rw-r--r--internal/ignore/oracle_test.go94
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])
+ }
+ }
+ }
+}