gitee.com/mirrors_u-root/u-root@v7.0.0+incompatible/cmds/core/cp/cp_test.go (about) 1 // Copyright 2016 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // created by Manoel Vilela <manoel_vilela@engineer.com> 6 7 package main 8 9 import ( 10 "bytes" 11 "fmt" 12 "io/ioutil" 13 "log" 14 "math/rand" 15 "os" 16 "path/filepath" 17 "strings" 18 "testing" 19 20 "github.com/u-root/u-root/pkg/cp" 21 "github.com/u-root/u-root/pkg/cp/cmp" 22 ) 23 24 const ( 25 maxSizeFile = 1000 26 maxDirDepth = 5 27 maxFiles = 5 28 ) 29 30 // resetFlags is used to reset the cp flags to default 31 func resetFlags() { 32 flags.recursive = false 33 flags.ask = false 34 flags.force = false 35 flags.verbose = false 36 flags.noFollowSymlinks = false 37 } 38 39 // randomFile create a random file with random content 40 func randomFile(fpath, prefix string) (*os.File, error) { 41 f, err := ioutil.TempFile(fpath, prefix) 42 if err != nil { 43 return nil, err 44 } 45 // generate random content for files 46 bytes := []byte{} 47 for i := 0; i < rand.Intn(maxSizeFile); i++ { 48 bytes = append(bytes, byte(i)) 49 } 50 f.Write(bytes) 51 52 return f, nil 53 } 54 55 // createFilesTree create a random files tree 56 func createFilesTree(root string, maxDepth, depth int) error { 57 // create more one dir if don't achieve the maxDepth 58 if depth < maxDepth { 59 newDir, err := ioutil.TempDir(root, fmt.Sprintf("cpdir_%d_", depth)) 60 if err != nil { 61 return err 62 } 63 64 if err = createFilesTree(newDir, maxDepth, depth+1); err != nil { 65 return err 66 } 67 } 68 // generate random files 69 for i := 0; i < maxFiles; i++ { 70 f, err := randomFile(root, fmt.Sprintf("cpfile_%d_", i)) 71 if err != nil { 72 return err 73 } 74 f.Close() 75 } 76 77 return nil 78 } 79 80 // TestCpsSimple make a simple test for copy file-to-file 81 // cmd-line equivalent: cp file file-copy 82 func TestCpSimple(t *testing.T) { 83 tempDir, err := ioutil.TempDir("", "TestCpSimple") 84 if err != nil { 85 t.Fatal(err) 86 } 87 defer os.RemoveAll(tempDir) 88 89 f, err := randomFile(tempDir, "src-") 90 if err != nil { 91 t.Fatalf("cannot create a random file: %v", err) 92 } 93 defer f.Close() 94 95 srcf := f.Name() 96 dstf := filepath.Join(tempDir, "destination") 97 98 if err := cpArgs([]string{srcf, dstf}); err != nil { 99 t.Fatalf("copy(%q -> %q) = %v, want nil", srcf, dstf, err) 100 } 101 if err := cmp.IsEqualTree(cp.Default, srcf, dstf); err != nil { 102 t.Fatalf("copy(%q -> %q): file trees not equal: %v", srcf, dstf, err) 103 } 104 } 105 106 // TestCpSrcDirectory tests copying source to destination without recursive 107 // cmd-line equivalent: cp ~/dir ~/dir2 108 func TestCpSrcDirectory(t *testing.T) { 109 flags.recursive = false 110 defer resetFlags() 111 112 tempDir, err := ioutil.TempDir("", "TestCpSrcDirectory") 113 if err != nil { 114 t.Fatal(err) 115 } 116 defer os.RemoveAll(tempDir) 117 118 tempDirTwo, err := ioutil.TempDir("", "TestCpSrcDirectoryTwo") 119 if err != nil { 120 t.Fatal(err) 121 } 122 defer os.RemoveAll(tempDirTwo) 123 124 // capture log output to verify 125 var logBytes bytes.Buffer 126 log.SetOutput(&logBytes) 127 128 if err := cpArgs([]string{tempDir, tempDirTwo}); err != nil { 129 t.Fatalf("copy(%q -> %q) = %v, want nil", tempDir, tempDirTwo, err) 130 } 131 132 outString := fmt.Sprintf("cp: -r not specified, omitting directory %s", tempDir) 133 capturedString := logBytes.String() 134 if !strings.Contains(capturedString, outString) { 135 t.Fatalf("copy(%q -> %q) = %v, want %v", tempDir, tempDirTwo, capturedString, outString) 136 } 137 } 138 139 // TestCpRecursive tests the recursive mode copy 140 // Copy dir hierarchies src-dir to dst-dir 141 // whose src-dir and dst-dir already exists 142 // cmd-line equivalent: $ cp -R src-dir/ dst-dir/ 143 func TestCpRecursive(t *testing.T) { 144 flags.recursive = true 145 defer resetFlags() 146 147 tempDir, err := ioutil.TempDir("", "TestCpRecursive") 148 if err != nil { 149 t.Fatal(err) 150 } 151 defer os.RemoveAll(tempDir) 152 153 srcDir := filepath.Join(tempDir, "src") 154 if err := os.Mkdir(srcDir, 0755); err != nil { 155 t.Fatal(err) 156 } 157 dstDir := filepath.Join(tempDir, "dst-exists") 158 if err := os.Mkdir(dstDir, 0755); err != nil { 159 t.Fatal(err) 160 } 161 162 if err = createFilesTree(srcDir, maxDirDepth, 0); err != nil { 163 t.Fatalf("cannot create files tree on directory %q: %v", srcDir, err) 164 } 165 166 t.Run("existing-dst-dir", func(t *testing.T) { 167 if err := cpArgs([]string{srcDir, dstDir}); err != nil { 168 t.Fatalf("cp(%q -> %q) = %v, want nil", srcDir, dstDir, err) 169 } 170 // Because dstDir already existed, a new dir was created inside it. 171 realDestination := filepath.Join(dstDir, filepath.Base(srcDir)) 172 if err := cmp.IsEqualTree(cp.Default, srcDir, realDestination); err != nil { 173 t.Fatalf("copy(%q -> %q): file trees not equal: %v", srcDir, realDestination, err) 174 } 175 }) 176 177 t.Run("non-existing-dst-dir", func(t *testing.T) { 178 notExistDstDir := filepath.Join(tempDir, "dst-does-not-exist") 179 if err := cpArgs([]string{srcDir, notExistDstDir}); err != nil { 180 t.Fatalf("cp(%q -> %q) = %v, want nil", srcDir, notExistDstDir, err) 181 } 182 183 if err := cmp.IsEqualTree(cp.Default, srcDir, notExistDstDir); err != nil { 184 t.Fatalf("copy(%q -> %q): file trees not equal: %v", srcDir, notExistDstDir, err) 185 } 186 }) 187 } 188 189 // Other test to verify the CopyRecursive 190 // whose dir$n and dst-dir already exists 191 // cmd-line equivalent: $ cp -R dir1/ dir2/ dir3/ dst-dir/ 192 // 193 // dst-dir will content dir{1, 3} 194 // $ dst-dir/ 195 // .. dir1/ 196 // .. dir2/ 197 // .. dir3/ 198 func TestCpRecursiveMultiple(t *testing.T) { 199 flags.recursive = true 200 defer resetFlags() 201 tempDir, err := ioutil.TempDir("", "TestCpRecursiveMultiple") 202 if err != nil { 203 t.Fatal(err) 204 } 205 defer os.RemoveAll(tempDir) 206 207 dstTest := filepath.Join(tempDir, "destination") 208 if err := os.Mkdir(dstTest, 0755); err != nil { 209 t.Fatalf("Failed on build directory %v: %v", dstTest, err) 210 } 211 212 // create multiple random directories sources 213 srcDirs := []string{} 214 for i := 0; i < maxDirDepth; i++ { 215 srcTest, err := ioutil.TempDir(tempDir, "src-") 216 if err != nil { 217 t.Fatalf("Failed on build directory %v: %v\n", srcTest, err) 218 } 219 if err = createFilesTree(srcTest, maxDirDepth, 0); err != nil { 220 t.Fatalf("cannot create files tree on directory %v: %v", srcTest, err) 221 } 222 223 srcDirs = append(srcDirs, srcTest) 224 225 } 226 227 args := srcDirs 228 args = append(args, dstTest) 229 if err := cpArgs(args); err != nil { 230 t.Fatalf("cp %q exit with error: %v", args, err) 231 } 232 for _, src := range srcDirs { 233 _, srcFile := filepath.Split(src) 234 235 dst := filepath.Join(dstTest, srcFile) 236 if err := cmp.IsEqualTree(cp.Default, src, dst); err != nil { 237 t.Fatalf("The copy %q -> %q failed: %v", src, dst, err) 238 } 239 } 240 } 241 242 // using -P don't follow symlinks, create other symlink 243 // cmd-line equivalent: $ cp -P symlink symlink-copy 244 func TestCpSymlink(t *testing.T) { 245 tempDir, err := ioutil.TempDir("", "TestCpSymlink") 246 if err != nil { 247 t.Fatal(err) 248 } 249 defer os.RemoveAll(tempDir) 250 251 f, err := randomFile(tempDir, "src-") 252 if err != nil { 253 t.Fatalf("cannot create a random file: %v", err) 254 } 255 defer f.Close() 256 257 srcFpath := f.Name() 258 srcFname := filepath.Base(srcFpath) 259 260 newName := filepath.Join(tempDir, srcFname+"_link") 261 if err := os.Symlink(srcFname, newName); err != nil { 262 t.Fatalf("cannot create a link %q with target %q: %v", newName, srcFname, err) 263 } 264 265 t.Run("no-follow-symlink", func(t *testing.T) { 266 defer resetFlags() 267 flags.noFollowSymlinks = true 268 269 dst := filepath.Join(tempDir, "dst-no-follow") 270 if err := cpArgs([]string{newName, dst}); err != nil { 271 t.Fatalf("cp(%q -> %q) = %v, want nil", newName, dst, err) 272 } 273 if err := cmp.IsEqualTree(cp.NoFollowSymlinks, newName, dst); err != nil { 274 t.Fatalf("The copy %q -> %q failed: %v", newName, dst, err) 275 } 276 }) 277 278 t.Run("follow-symlink", func(t *testing.T) { 279 defer resetFlags() 280 flags.noFollowSymlinks = false 281 282 dst := filepath.Join(tempDir, "dst-follow") 283 if err := cpArgs([]string{newName, dst}); err != nil { 284 t.Fatalf("cp(%q -> %q) = %v, want nil", newName, dst, err) 285 } 286 if err := cmp.IsEqualTree(cp.Default, newName, dst); err != nil { 287 t.Fatalf("The copy %q -> %q failed: %v", newName, dst, err) 288 } 289 }) 290 }