github.com/markusbkk/elvish@v0.0.0-20231204143114-91dc52438621/pkg/testutil/testdir.go (about) 1 package testutil 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 8 "github.com/markusbkk/elvish/pkg/env" 9 ) 10 11 // TempDir creates a temporary directory for testing that will be removed 12 // after the test finishes. It is different from testing.TB.TempDir in that it 13 // resolves symlinks in the path of the directory. 14 // 15 // It panics if the test directory cannot be created or symlinks cannot be 16 // resolved. It is only suitable for use in tests. 17 func TempDir(c Cleanuper) string { 18 dir, err := os.MkdirTemp("", "elvishtest.") 19 if err != nil { 20 panic(err) 21 } 22 dir, err = filepath.EvalSymlinks(dir) 23 if err != nil { 24 panic(err) 25 } 26 c.Cleanup(func() { 27 err := os.RemoveAll(dir) 28 if err != nil { 29 fmt.Fprintf(os.Stderr, "failed to remove temp dir %s: %v\n", dir, err) 30 } 31 }) 32 return dir 33 } 34 35 // TempHome is equivalent to Setenv(c, env.HOME, TempDir(c)) 36 func TempHome(c Cleanuper) string { 37 return Setenv(c, env.HOME, TempDir(c)) 38 } 39 40 // Chdir changes into a directory, and restores the original working directory 41 // when a test finishes. It returns the directory for easier chaining. 42 func Chdir(c Cleanuper, dir string) string { 43 oldWd, err := os.Getwd() 44 if err != nil { 45 panic(err) 46 } 47 Must(os.Chdir(dir)) 48 c.Cleanup(func() { 49 Must(os.Chdir(oldWd)) 50 }) 51 return dir 52 } 53 54 // InTempDir is equivalent to Chdir(c, TempDir(c)). 55 func InTempDir(c Cleanuper) string { 56 return Chdir(c, TempDir(c)) 57 } 58 59 // InTempHome is equivalent to Setenv(c, env.HOME, InTempDir(c)) 60 func InTempHome(c Cleanuper) string { 61 return Setenv(c, env.HOME, InTempDir(c)) 62 } 63 64 // Dir describes the layout of a directory. The keys of the map represent 65 // filenames. Each value is either a string (for the content of a regular file 66 // with permission 0644), a File, or a Dir. 67 type Dir map[string]interface{} 68 69 // File describes a file to create. 70 type File struct { 71 Perm os.FileMode 72 Content string 73 } 74 75 // ApplyDir creates the given filesystem layout in the current directory. 76 func ApplyDir(dir Dir) { 77 applyDir(dir, "") 78 } 79 80 func applyDir(dir Dir, prefix string) { 81 for name, file := range dir { 82 path := filepath.Join(prefix, name) 83 switch file := file.(type) { 84 case string: 85 Must(os.WriteFile(path, []byte(file), 0644)) 86 case File: 87 Must(os.WriteFile(path, []byte(file.Content), file.Perm)) 88 case Dir: 89 Must(os.MkdirAll(path, 0755)) 90 applyDir(file, path) 91 default: 92 panic(fmt.Sprintf("file is neither string, Dir, or Symlink: %v", file)) 93 } 94 } 95 }