// Copyright 2021 The Kubernetes Authors. // SPDX-License-Identifier: Apache-2.0 //go:build !windows // +build !windows package filesys import ( "os" "path/filepath" "reflect" "testing" ) // Confirm behavior of filepath.Match func TestFilePathMatch(t *testing.T) { cases := []struct { pattern string path string expected bool }{ { pattern: "*e*", path: "hey", expected: true, }, { pattern: "*e*", path: "hay", expected: false, }, { pattern: "*e*", path: filepath.Join("h", "e", "y"), expected: false, }, { pattern: "*/e/*", path: filepath.Join("h", "e", "y"), expected: true, }, { pattern: "h/e/*", path: filepath.Join("h", "e", "y"), expected: true, }, { pattern: "*/e/y", path: filepath.Join("h", "e", "y"), expected: true, }, { pattern: "*/*/*", path: filepath.Join("h", "e", "y"), expected: true, }, { pattern: "*/*/*", path: filepath.Join("h", "e", "y", "there"), expected: false, }, { pattern: "*/*/*/t*e", path: filepath.Join("h", "e", "y", "there"), expected: true, }, } for _, item := range cases { match, err := filepath.Match(item.pattern, item.path) if err != nil { t.Fatalf("unexpected err: %v", err) } if match != item.expected { t.Fatalf("'%s' '%s' %v\n", item.pattern, item.path, match) } } } // Confirm behavior of filepath.Split func TestFilePathSplit(t *testing.T) { cases := []struct { full string dir string file string }{ { full: "", dir: "", file: "", }, { full: SelfDir, dir: "", file: SelfDir, }, { full: "rabbit.jpg", dir: "", file: "rabbit.jpg", }, { full: "/", dir: "/", file: "", }, { full: "/beans", dir: "/", file: "beans", }, { full: "/home/foo/bar", dir: "/home/foo/", file: "bar", }, { full: "/usr/local/", dir: "/usr/local/", file: "", }, { full: "/usr//local//go", dir: "/usr//local//", file: "go", }, } for _, p := range cases { dir, file := filepath.Split(p.full) if dir != p.dir || file != p.file { t.Fatalf( "in '%s',\ngot dir='%s' (expected '%s'),\n got file='%s' (expected %s).", p.full, dir, p.dir, file, p.file) } } } func TestPathSplitAndJoin(t *testing.T) { cases := map[string]struct { original string expected []string }{ "Empty": { original: "", expected: []string{}, }, "One": { original: "hello", expected: []string{"hello"}, }, "Two": { original: "hello/there", expected: []string{"hello", "there"}, }, "Three": { original: "hello/my/friend", expected: []string{"hello", "my", "friend"}, }, } for n, c := range cases { f := func(t *testing.T, original string, expected []string) { t.Helper() actual := PathSplit(original) if len(actual) != len(expected) { t.Fatalf( "expected len %d, got len %d", len(expected), len(actual)) } for i := range expected { if expected[i] != actual[i] { t.Fatalf( "at i=%d, expected '%s', got '%s'", i, expected[i], actual[i]) } } joined := PathJoin(actual) if joined != original { t.Fatalf( "when rejoining, expected '%s', got '%s'", original, joined) } } t.Run("relative"+n, func(t *testing.T) { f(t, c.original, c.expected) }) t.Run("absolute"+n, func(t *testing.T) { f(t, string(os.PathSeparator)+c.original, append([]string{""}, c.expected...)) }) } } func TestInsertPathPart(t *testing.T) { cases := map[string]struct { original string pos int part string expected string }{ "rootOne": { original: "/", pos: 0, part: "___", expected: "/___", }, "rootTwo": { original: "/", pos: 444, part: "___", expected: "/___", }, "rootedFirst": { original: "/apple", pos: 0, part: "___", expected: "/___/apple", }, "rootedSecond": { original: "/apple", pos: 444, part: "___", expected: "/apple/___", }, "rootedThird": { original: "/apple/banana", pos: 444, part: "___", expected: "/apple/banana/___", }, "emptyLow": { original: "", pos: -3, part: "___", expected: "___", }, "emptyHigh": { original: "", pos: 444, part: "___", expected: "___", }, "peachPie": { original: "a/nice/warm/pie", pos: 3, part: "PEACH", expected: "a/nice/warm/PEACH/pie", }, "rootedPeachPie": { original: "/a/nice/warm/pie", pos: 3, part: "PEACH", expected: "/a/nice/warm/PEACH/pie", }, "longStart": { original: "a/b/c/d/e/f", pos: 0, part: "___", expected: "___/a/b/c/d/e/f", }, "rootedLongStart": { original: "/a/b/c/d/e/f", pos: 0, part: "___", expected: "/___/a/b/c/d/e/f", }, "longMiddle": { original: "a/b/c/d/e/f", pos: 3, part: "___", expected: "a/b/c/___/d/e/f", }, "rootedLongMiddle": { original: "/a/b/c/d/e/f", pos: 3, part: "___", expected: "/a/b/c/___/d/e/f", }, "longEnd": { original: "a/b/c/d/e/f", pos: 444, part: "___", expected: "a/b/c/d/e/f/___", }, "rootedLongEnd": { original: "/a/b/c/d/e/f", pos: 444, part: "___", expected: "/a/b/c/d/e/f/___", }, } for n, c := range cases { t.Run(n, func(t *testing.T) { actual := InsertPathPart(c.original, c.pos, c.part) if actual != c.expected { t.Fatalf("expected '%s', got '%s'", c.expected, actual) } }) } } func TestStripTrailingSeps(t *testing.T) { cases := []struct { full string rem string }{ { full: "foo", rem: "foo", }, { full: "", rem: "", }, { full: "foo/", rem: "foo", }, { full: "foo///bar///", rem: "foo///bar", }, { full: "/////", rem: "", }, { full: "/", rem: "", }, } for _, p := range cases { dir := StripTrailingSeps(p.full) if dir != p.rem { t.Fatalf( "in '%s', got dir='%s' (expected '%s')", p.full, dir, p.rem) } } } func TestStripLeadingSeps(t *testing.T) { cases := []struct { full string rem string }{ { full: "foo", rem: "foo", }, { full: "", rem: "", }, { full: "/foo", rem: "foo", }, { full: "///foo///bar///", rem: "foo///bar///", }, { full: "/////", rem: "", }, { full: "/", rem: "", }, } for _, p := range cases { dir := StripLeadingSeps(p.full) if dir != p.rem { t.Fatalf( "in '%s', got dir='%s' (expected '%s')", p.full, dir, p.rem) } } } func TestIsHiddenFilePath(t *testing.T) { tests := map[string]struct { paths []string expectHidden bool }{ "hiddenGlobs": { expectHidden: true, paths: []string{ ".*", "/.*", "dir/.*", "dir1/dir2/dir3/.*", "../../.*", "../../dir/.*", }, }, "visibleGlobes": { expectHidden: false, paths: []string{ "*", "/*", "dir/*", "dir1/dir2/dir3/*", "../../*", "../../dir/*", }, }, "hiddenFiles": { expectHidden: true, paths: []string{ ".root_file.xtn", "/.file_1.xtn", "dir/.file_2.xtn", "dir1/dir2/dir3/.file_3.xtn", "../../.file_4.xtn", "../../dir/.file_5.xtn", }, }, "visibleFiles": { expectHidden: false, paths: []string{ "root_file.xtn", "/file_1.xtn", "dir/file_2.xtn", "dir1/dir2/dir3/file_3.xtn", "../../file_4.xtn", "../../dir/file_5.xtn", }, }, } for n, c := range tests { t.Run(n, func(t *testing.T) { for _, path := range c.paths { actual := IsHiddenFilePath(path) if actual != c.expectHidden { t.Fatalf("For file path %q, expected hidden: %v, got hidden: %v", path, c.expectHidden, actual) } } }) } } func TestRemoveHiddenFiles(t *testing.T) { paths := []string{ "file1.xtn", ".file2.xtn", "dir/fa1", "dir/fa2", "dir/.fa3", "../../.fa4", "../../fa5", "../../dir/fa6", "../../dir/.fa7", } result := RemoveHiddenFiles(paths) expected := []string{ "file1.xtn", "dir/fa1", "dir/fa2", "../../fa5", "../../dir/fa6", } if !reflect.DeepEqual(result, expected) { t.Fatalf("Hidden dirs not correctly removed, expected %v but got %v\n", expected, result) } }