github.com/OpenFlowLabs/storage@v1.12.13/drivers/copy/copy_test.go (about) 1 // +build linux 2 3 package copy 4 5 import ( 6 "fmt" 7 "io/ioutil" 8 "math/rand" 9 "os" 10 "path/filepath" 11 "syscall" 12 "testing" 13 "time" 14 15 "github.com/containers/storage/pkg/system" 16 "golang.org/x/sys/unix" 17 "gotest.tools/assert" 18 is "gotest.tools/assert/cmp" 19 ) 20 21 func TestCopy(t *testing.T) { 22 copyWithFileRange := true 23 copyWithFileClone := true 24 doCopyTest(t, ©WithFileRange, ©WithFileClone) 25 } 26 27 func TestCopyWithoutRange(t *testing.T) { 28 copyWithFileRange := false 29 copyWithFileClone := false 30 doCopyTest(t, ©WithFileRange, ©WithFileClone) 31 } 32 33 func TestCopyDir(t *testing.T) { 34 srcDir, err := ioutil.TempDir("", "srcDir") 35 assert.NilError(t, err) 36 populateSrcDir(t, srcDir, 3) 37 38 dstDir, err := ioutil.TempDir("", "testdst") 39 assert.NilError(t, err) 40 defer os.RemoveAll(dstDir) 41 42 assert.Check(t, DirCopy(srcDir, dstDir, Content, false)) 43 assert.NilError(t, filepath.Walk(srcDir, func(srcPath string, f os.FileInfo, err error) error { 44 if err != nil { 45 return err 46 } 47 48 // Rebase path 49 relPath, err := filepath.Rel(srcDir, srcPath) 50 assert.NilError(t, err) 51 if relPath == "." { 52 return nil 53 } 54 55 dstPath := filepath.Join(dstDir, relPath) 56 assert.NilError(t, err) 57 58 // If we add non-regular dirs and files to the test 59 // then we need to add more checks here. 60 dstFileInfo, err := os.Lstat(dstPath) 61 assert.NilError(t, err) 62 63 srcFileSys := f.Sys().(*syscall.Stat_t) 64 dstFileSys := dstFileInfo.Sys().(*syscall.Stat_t) 65 66 t.Log(relPath) 67 if srcFileSys.Dev == dstFileSys.Dev { 68 assert.Check(t, srcFileSys.Ino != dstFileSys.Ino) 69 } 70 // Todo: check size, and ctim is not equal 71 /// on filesystems that have granular ctimes 72 assert.Check(t, is.DeepEqual(srcFileSys.Mode, dstFileSys.Mode)) 73 assert.Check(t, is.DeepEqual(srcFileSys.Uid, dstFileSys.Uid)) 74 assert.Check(t, is.DeepEqual(srcFileSys.Gid, dstFileSys.Gid)) 75 assert.Check(t, is.DeepEqual(srcFileSys.Mtim, dstFileSys.Mtim)) 76 77 return nil 78 })) 79 } 80 81 func randomMode(baseMode int) os.FileMode { 82 for i := 0; i < 7; i++ { 83 baseMode = baseMode | (1&rand.Intn(2))<<uint(i) 84 } 85 return os.FileMode(baseMode) 86 } 87 88 func populateSrcDir(t *testing.T, srcDir string, remainingDepth int) { 89 if remainingDepth == 0 { 90 return 91 } 92 aTime := time.Unix(rand.Int63(), 0) 93 mTime := time.Unix(rand.Int63(), 0) 94 95 for i := 0; i < 10; i++ { 96 dirName := filepath.Join(srcDir, fmt.Sprintf("srcdir-%d", i)) 97 // Owner all bits set 98 assert.NilError(t, os.Mkdir(dirName, randomMode(0700))) 99 populateSrcDir(t, dirName, remainingDepth-1) 100 assert.NilError(t, system.Chtimes(dirName, aTime, mTime)) 101 } 102 103 for i := 0; i < 10; i++ { 104 fileName := filepath.Join(srcDir, fmt.Sprintf("srcfile-%d", i)) 105 // Owner read bit set 106 assert.NilError(t, ioutil.WriteFile(fileName, []byte{}, randomMode(0400))) 107 assert.NilError(t, system.Chtimes(fileName, aTime, mTime)) 108 } 109 } 110 111 func doCopyTest(t *testing.T, copyWithFileRange, copyWithFileClone *bool) { 112 dir, err := ioutil.TempDir("", "storage-copy-check") 113 assert.NilError(t, err) 114 defer os.RemoveAll(dir) 115 srcFilename := filepath.Join(dir, "srcFilename") 116 dstFilename := filepath.Join(dir, "dstilename") 117 118 r := rand.New(rand.NewSource(0)) 119 buf := make([]byte, 1024) 120 _, err = r.Read(buf) 121 assert.NilError(t, err) 122 assert.NilError(t, ioutil.WriteFile(srcFilename, buf, 0777)) 123 fileinfo, err := os.Stat(srcFilename) 124 assert.NilError(t, err) 125 126 assert.NilError(t, copyRegular(srcFilename, dstFilename, fileinfo, copyWithFileRange, copyWithFileClone)) 127 readBuf, err := ioutil.ReadFile(dstFilename) 128 assert.NilError(t, err) 129 assert.Check(t, is.DeepEqual(buf, readBuf)) 130 } 131 132 func TestCopyHardlink(t *testing.T) { 133 var srcFile1FileInfo, srcFile2FileInfo, dstFile1FileInfo, dstFile2FileInfo unix.Stat_t 134 135 srcDir, err := ioutil.TempDir("", "srcDir") 136 assert.NilError(t, err) 137 defer os.RemoveAll(srcDir) 138 139 dstDir, err := ioutil.TempDir("", "dstDir") 140 assert.NilError(t, err) 141 defer os.RemoveAll(dstDir) 142 143 srcFile1 := filepath.Join(srcDir, "file1") 144 srcFile2 := filepath.Join(srcDir, "file2") 145 dstFile1 := filepath.Join(dstDir, "file1") 146 dstFile2 := filepath.Join(dstDir, "file2") 147 assert.NilError(t, ioutil.WriteFile(srcFile1, []byte{}, 0777)) 148 assert.NilError(t, os.Link(srcFile1, srcFile2)) 149 150 assert.Check(t, DirCopy(srcDir, dstDir, Content, false)) 151 152 assert.NilError(t, unix.Stat(srcFile1, &srcFile1FileInfo)) 153 assert.NilError(t, unix.Stat(srcFile2, &srcFile2FileInfo)) 154 assert.Equal(t, srcFile1FileInfo.Ino, srcFile2FileInfo.Ino) 155 156 assert.NilError(t, unix.Stat(dstFile1, &dstFile1FileInfo)) 157 assert.NilError(t, unix.Stat(dstFile2, &dstFile2FileInfo)) 158 assert.Check(t, is.Equal(dstFile1FileInfo.Ino, dstFile2FileInfo.Ino)) 159 }