mirror of
https://github.com/langgenius/dify.git
synced 2026-08-24 12:32:54 -04:00
79 lines
3.0 KiB
Go
79 lines
3.0 KiB
Go
package snapshot
|
|
|
|
import "testing"
|
|
|
|
// Caller patterns are gitignore syntax and reach any depth, which plain
|
|
// top-level name matching could not express.
|
|
func TestExcluderCallerPatterns(t *testing.T) {
|
|
for name, tc := range map[string]struct {
|
|
patterns []string
|
|
rel string
|
|
isDir bool
|
|
want bool
|
|
}{
|
|
"exact top-level name": {[]string{".cache"}, ".cache", true, true},
|
|
"bare name at depth": {[]string{"node_modules"}, "src/app/node_modules", true, true},
|
|
"bare name matches file": {[]string{"tags"}, "src/tags", false, true},
|
|
"anchored hits root only": {[]string{"/build"}, "build", true, true},
|
|
"anchored misses depth": {[]string{"/build"}, "src/build", true, false},
|
|
"suffix glob": {[]string{"*.log"}, "var/app.log", false, true},
|
|
"suffix glob non-match": {[]string{"*.log"}, "var/app.txt", false, false},
|
|
"doublestar spans segments": {[]string{".cache/**"}, ".cache/a/b/c.bin", false, true},
|
|
"doublestar mid-pattern": {[]string{"src/**/dist"}, "src/a/b/dist", true, true},
|
|
"dir-only skips file": {[]string{"target/"}, "target", false, false},
|
|
"dir-only matches dir": {[]string{"target/"}, "target", true, true},
|
|
"question mark": {[]string{"tmp?"}, "tmp1", false, true},
|
|
"unmatched pattern is inert": {[]string{"nothing-here"}, "bin/tool.sh", false, false},
|
|
"no patterns": {nil, "bin/tool.sh", false, false},
|
|
} {
|
|
t.Run(name, func(t *testing.T) {
|
|
got := NewExcluder(tc.patterns).Excluded(tc.rel, tc.isDir)
|
|
if got != tc.want {
|
|
t.Errorf("Excluded(%q, isDir=%v) with %v = %v, want %v",
|
|
tc.rel, tc.isDir, tc.patterns, got, tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// Within the caller's own list, a later "!" pattern re-includes what an
|
|
// earlier one excluded — standard last-match-wins.
|
|
func TestExcluderCallerNegationWins(t *testing.T) {
|
|
e := NewExcluder([]string{".cache/**", "!.cache/keep-me"})
|
|
if !e.Excluded(".cache/junk", false) {
|
|
t.Error(".cache/junk should be excluded by .cache/**")
|
|
}
|
|
if e.Excluded(".cache/keep-me", false) {
|
|
t.Error(".cache/keep-me should be re-included by the later ! pattern")
|
|
}
|
|
}
|
|
|
|
// The two layers are ordered: defaults are decided before caller patterns are
|
|
// consulted, so no caller pattern can subtract from them.
|
|
func TestExcluderDefaultsBeatCallerPatterns(t *testing.T) {
|
|
for _, pattern := range []string{
|
|
"!" + RuntimeStateDir,
|
|
"!/" + RuntimeStateDir,
|
|
"!" + RuntimeStateDir + "/**",
|
|
"!**",
|
|
} {
|
|
t.Run(pattern, func(t *testing.T) {
|
|
e := NewExcluder([]string{pattern})
|
|
for _, dir := range defaultExcludes {
|
|
if !e.Excluded(dir, true) {
|
|
t.Errorf("%q pulled %s back in", pattern, dir)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// Blank entries are dropped rather than compiled into a pattern that would
|
|
// match everything or nothing surprisingly.
|
|
func TestExcluderIgnoresBlankPatterns(t *testing.T) {
|
|
e := NewExcluder([]string{"", " ", "\t"})
|
|
if e.Excluded("bin/tool.sh", false) {
|
|
t.Error("blank patterns must not exclude anything")
|
|
}
|
|
}
|