github.com/markusbkk/elvish@v0.0.0-20231204143114-91dc52438621/pkg/mods/path/path_test.go (about) 1 package path 2 3 import ( 4 "os" 5 "path/filepath" 6 "regexp" 7 "testing" 8 9 "github.com/markusbkk/elvish/pkg/eval" 10 "github.com/markusbkk/elvish/pkg/eval/errs" 11 . "github.com/markusbkk/elvish/pkg/eval/evaltest" 12 "github.com/markusbkk/elvish/pkg/mods/file" 13 "github.com/markusbkk/elvish/pkg/testutil" 14 ) 15 16 var testDir = testutil.Dir{ 17 "d": testutil.Dir{ 18 "f": "", 19 }, 20 } 21 22 // A regular expression fragment to match the directory part of an absolute 23 // path. QuoteMeta is needed since on Windows filepath.Separator is '\\'. 24 var anyDir = "^.*" + regexp.QuoteMeta(string(filepath.Separator)) 25 26 func TestPath(t *testing.T) { 27 tmpdir := testutil.InTempDir(t) 28 testutil.ApplyDir(testDir) 29 30 absPath, err := filepath.Abs("a/b/c.png") 31 if err != nil { 32 panic("unable to convert a/b/c.png to an absolute path") 33 } 34 35 TestWithSetup(t, importModules, 36 // This block of tests is not meant to be comprehensive. Their primary purpose is to simply 37 // ensure the Elvish command is correctly mapped to the relevant Go function. We assume the 38 // Go function behaves correctly. 39 That("path:abs a/b/c.png").Puts(absPath), 40 That("path:base a/b/d.png").Puts("d.png"), 41 That("path:clean ././x").Puts("x"), 42 That("path:clean a/b/.././c").Puts(filepath.Join("a", "c")), 43 That("path:dir a/b/d.png").Puts(filepath.Join("a", "b")), 44 That("path:ext a/b/e.png").Puts(".png"), 45 That("path:ext a/b/s").Puts(""), 46 That("path:is-abs a/b/s").Puts(false), 47 That("path:is-abs "+absPath).Puts(true), 48 49 // Elvish "path:" module functions that are not trivial wrappers around a Go stdlib function 50 // should have comprehensive tests below this comment. 51 That("path:is-dir "+tmpdir).Puts(true), 52 That("path:is-dir d").Puts(true), 53 That("path:is-dir d/f").Puts(false), 54 That("path:is-dir bad").Puts(false), 55 56 That("path:is-regular "+tmpdir).Puts(false), 57 That("path:is-regular d").Puts(false), 58 That("path:is-regular d/f").Puts(true), 59 That("path:is-regular bad").Puts(false), 60 61 // Verify the commands for creating temporary filesystem objects work correctly. 62 That("var x = (path:temp-dir)", "rmdir $x", "put $x").Puts( 63 MatchingRegexp{Pattern: anyDir + `elvish-.*$`}), 64 That("var x = (path:temp-dir 'x-*.y')", "rmdir $x", "put $x").Puts( 65 MatchingRegexp{Pattern: anyDir + `x-.*\.y$`}), 66 That("var x = (path:temp-dir &dir=. 'x-*.y')", "rmdir $x", "put $x").Puts( 67 MatchingRegexp{Pattern: `^(\.[/\\])?x-.*\.y$`}), 68 That("var x = (path:temp-dir &dir=.)", "rmdir $x", "put $x").Puts( 69 MatchingRegexp{Pattern: `^(\.[/\\])?elvish-.*$`}), 70 That("path:temp-dir a b").Throws( 71 errs.ArityMismatch{What: "arguments", ValidLow: 0, ValidHigh: 1, Actual: 2}, 72 "path:temp-dir a b"), 73 74 That("var f = (path:temp-file)", "file:close $f", "put $f[fd]", "rm $f[name]"). 75 Puts(-1), 76 That("var f = (path:temp-file)", "put $f[name]", "file:close $f", "rm $f[name]"). 77 Puts(MatchingRegexp{Pattern: anyDir + `elvish-.*$`}), 78 That("var f = (path:temp-file 'x-*.y')", "put $f[name]", "file:close $f", "rm $f[name]"). 79 Puts(MatchingRegexp{Pattern: anyDir + `x-.*\.y$`}), 80 That("var f = (path:temp-file &dir=. 'x-*.y')", "put $f[name]", "file:close $f", "rm $f[name]"). 81 Puts(MatchingRegexp{Pattern: `^(\.[/\\])?x-.*\.y$`}), 82 That("var f = (path:temp-file &dir=.)", "put $f[name]", "file:close $f", "rm $f[name]"). 83 Puts(MatchingRegexp{Pattern: `^(\.[/\\])?elvish-.*$`}), 84 That("path:temp-file a b").Throws( 85 errs.ArityMismatch{What: "arguments", ValidLow: 0, ValidHigh: 1, Actual: 2}, 86 "path:temp-file a b"), 87 ) 88 } 89 90 var symlinks = []struct { 91 path string 92 target string 93 }{ 94 {"d/s-f", "f"}, 95 {"s-d", "d"}, 96 {"s-d-f", "d/f"}, 97 {"s-bad", "bad"}, 98 } 99 100 func TestPath_Symlink(t *testing.T) { 101 testutil.InTempDir(t) 102 testutil.ApplyDir(testDir) 103 // testutil.ApplyDir(testDirSymlinks) 104 for _, link := range symlinks { 105 err := os.Symlink(link.target, link.path) 106 if err != nil { 107 // Creating symlinks requires a special permission on Windows. If 108 // the user doesn't have that permission, just skip the whole test. 109 t.Skip(err) 110 } 111 } 112 113 TestWithSetup(t, importModules, 114 That("path:eval-symlinks d/f").Puts(filepath.Join("d", "f")), 115 That("path:eval-symlinks d/s-f").Puts(filepath.Join("d", "f")), 116 That("path:eval-symlinks s-d/f").Puts(filepath.Join("d", "f")), 117 That("path:eval-symlinks s-bad").Throws(ErrorWithType(&os.PathError{})), 118 119 That("path:is-dir s-d").Puts(false), 120 That("path:is-dir s-d &follow-symlink").Puts(true), 121 That("path:is-dir s-d-f").Puts(false), 122 That("path:is-dir s-d-f &follow-symlink").Puts(false), 123 That("path:is-dir s-bad").Puts(false), 124 That("path:is-dir s-bad &follow-symlink").Puts(false), 125 That("path:is-dir bad").Puts(false), 126 That("path:is-dir bad &follow-symlink").Puts(false), 127 128 That("path:is-regular s-d").Puts(false), 129 That("path:is-regular s-d &follow-symlink").Puts(false), 130 That("path:is-regular s-d-f").Puts(false), 131 That("path:is-regular s-d-f &follow-symlink").Puts(true), 132 That("path:is-regular s-bad").Puts(false), 133 That("path:is-regular s-bad &follow-symlink").Puts(false), 134 That("path:is-regular bad").Puts(false), 135 That("path:is-regular bad &follow-symlink").Puts(false), 136 ) 137 } 138 139 func importModules(ev *eval.Evaler) { 140 ev.ExtendGlobal(eval.BuildNs().AddNs("path", Ns).AddNs("file", file.Ns)) 141 }