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  }