github.com/hashicorp/packer@v1.14.3/packer_test/common/fs.go (about) 1 package common 2 3 import ( 4 "crypto/sha256" 5 "fmt" 6 "io" 7 "os" 8 "path/filepath" 9 "runtime" 10 "testing" 11 ) 12 13 // CopyFile essentially replicates the `cp` command, for a file only. 14 // 15 // # Permissions are copied over from the source to destination 16 // 17 // The function detects if destination is a directory or a file (existent or not). 18 // 19 // If this is the former, we append the source file's basename to the 20 // directory and create the file from that inferred path. 21 func CopyFile(t *testing.T, dest, src string) { 22 st, err := os.Stat(src) 23 if err != nil { 24 t.Fatalf("failed to stat origin file %q: %s", src, err) 25 } 26 27 // If the stat call fails, we assume dest is the destination file. 28 dstStat, err := os.Stat(dest) 29 if err == nil && dstStat.IsDir() { 30 dest = filepath.Join(dest, filepath.Base(src)) 31 } 32 33 destFD, err := os.OpenFile(dest, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, st.Mode().Perm()) 34 if err != nil { 35 t.Fatalf("failed to create cp destination file %q: %s", dest, err) 36 } 37 defer destFD.Close() 38 39 srcFD, err := os.Open(src) 40 if err != nil { 41 t.Fatalf("failed to open source file to copy: %s", err) 42 } 43 defer srcFD.Close() 44 45 _, err = io.Copy(destFD, srcFD) 46 if err != nil { 47 t.Fatalf("failed to copy from %q -> %q: %s", src, dest, err) 48 } 49 } 50 51 // WriteFile writes `content` to a file `dest` 52 // 53 // The default permissions of that file is 0644 54 func WriteFile(t *testing.T, dest string, content string) { 55 outFile, err := os.OpenFile(dest, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) 56 if err != nil { 57 t.Fatalf("failed to open/create %q: %s", dest, err) 58 } 59 defer outFile.Close() 60 61 _, err = fmt.Fprintf(outFile, "%s", content) 62 if err != nil { 63 t.Fatalf("failed to write to file %q: %s", dest, err) 64 } 65 } 66 67 // TempWorkdir creates a working directory for a Packer test with the list of files 68 // given as input. 69 // 70 // The files should either have a path relative to the test that invokes it, or should 71 // be absolute. 72 // Each file will be copied to the root of the workdir being created. 73 // 74 // If any file cannot be found, this function will fail 75 func TempWorkdir(t *testing.T, files ...string) (string, func()) { 76 var err error 77 tempDir, err := os.MkdirTemp("", "packer-test-workdir-") 78 if err != nil { 79 t.Fatalf("failed to create temporary working directory: %s", err) 80 } 81 82 defer func() { 83 if err != nil { 84 os.RemoveAll(tempDir) 85 t.Errorf("failed to create temporary workdir: %s", err) 86 } 87 }() 88 89 for _, file := range files { 90 CopyFile(t, tempDir, file) 91 } 92 93 return tempDir, func() { 94 err := os.RemoveAll(tempDir) 95 if err != nil { 96 t.Logf("failed to remove temporary workdir %q: %s. This will need manual action.", tempDir, err) 97 } 98 } 99 } 100 101 // SHA256Sum computes the SHA256 digest for an input file 102 // 103 // The digest is returned as a hexstring 104 func SHA256Sum(t *testing.T, file string) string { 105 fl, err := os.ReadFile(file) 106 if err != nil { 107 t.Fatalf("failed to compute sha256sum for %q: %s", file, err) 108 } 109 sha := sha256.New() 110 sha.Write(fl) 111 return fmt.Sprintf("%x", sha.Sum([]byte{})) 112 } 113 114 // currentDir returns the directory in which the current file is located. 115 // 116 // Since we're in tests it's reliable as they're supposed to run on the same 117 // machine the binary's compiled from, but goes to say it's not meant for use 118 // in distributed binaries. 119 func currentDir() (string, error) { 120 // pc uintptr, file string, line int, ok bool 121 _, testDir, _, ok := runtime.Caller(0) 122 if !ok { 123 return "", fmt.Errorf("couldn't get the location of the test suite file") 124 } 125 126 return filepath.Dir(testDir), nil 127 }