github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/daemon/graphdriver/copy/copy_test.go (about) 1 // +build linux 2 3 package copy // import "github.com/demonoid81/moby/daemon/graphdriver/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/demonoid81/moby/pkg/system" 16 "golang.org/x/sys/unix" 17 "gotest.tools/v3/assert" 18 is "gotest.tools/v3/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 on filesystems that have granular ctimes 71 assert.Check(t, is.DeepEqual(srcFileSys.Mode, dstFileSys.Mode)) 72 assert.Check(t, is.DeepEqual(srcFileSys.Uid, dstFileSys.Uid)) 73 assert.Check(t, is.DeepEqual(srcFileSys.Gid, dstFileSys.Gid)) 74 assert.Check(t, is.DeepEqual(srcFileSys.Mtim, dstFileSys.Mtim)) 75 76 return nil 77 })) 78 } 79 80 func randomMode(baseMode int) os.FileMode { 81 for i := 0; i < 7; i++ { 82 baseMode = baseMode | (1&rand.Intn(2))<<uint(i) 83 } 84 return os.FileMode(baseMode) 85 } 86 87 func populateSrcDir(t *testing.T, srcDir string, remainingDepth int) { 88 if remainingDepth == 0 { 89 return 90 } 91 aTime := time.Unix(rand.Int63(), 0) 92 mTime := time.Unix(rand.Int63(), 0) 93 94 for i := 0; i < 10; i++ { 95 dirName := filepath.Join(srcDir, fmt.Sprintf("srcdir-%d", i)) 96 // Owner all bits set 97 assert.NilError(t, os.Mkdir(dirName, randomMode(0700))) 98 populateSrcDir(t, dirName, remainingDepth-1) 99 assert.NilError(t, system.Chtimes(dirName, aTime, mTime)) 100 } 101 102 for i := 0; i < 10; i++ { 103 fileName := filepath.Join(srcDir, fmt.Sprintf("srcfile-%d", i)) 104 // Owner read bit set 105 assert.NilError(t, ioutil.WriteFile(fileName, []byte{}, randomMode(0400))) 106 assert.NilError(t, system.Chtimes(fileName, aTime, mTime)) 107 } 108 } 109 110 func doCopyTest(t *testing.T, copyWithFileRange, copyWithFileClone *bool) { 111 dir, err := ioutil.TempDir("", "docker-copy-check") 112 assert.NilError(t, err) 113 defer os.RemoveAll(dir) 114 srcFilename := filepath.Join(dir, "srcFilename") 115 dstFilename := filepath.Join(dir, "dstilename") 116 117 r := rand.New(rand.NewSource(0)) 118 buf := make([]byte, 1024) 119 _, err = r.Read(buf) 120 assert.NilError(t, err) 121 assert.NilError(t, ioutil.WriteFile(srcFilename, buf, 0777)) 122 fileinfo, err := os.Stat(srcFilename) 123 assert.NilError(t, err) 124 125 assert.NilError(t, copyRegular(srcFilename, dstFilename, fileinfo, copyWithFileRange, copyWithFileClone)) 126 readBuf, err := ioutil.ReadFile(dstFilename) 127 assert.NilError(t, err) 128 assert.Check(t, is.DeepEqual(buf, readBuf)) 129 } 130 131 func TestCopyHardlink(t *testing.T) { 132 var srcFile1FileInfo, srcFile2FileInfo, dstFile1FileInfo, dstFile2FileInfo unix.Stat_t 133 134 srcDir, err := ioutil.TempDir("", "srcDir") 135 assert.NilError(t, err) 136 defer os.RemoveAll(srcDir) 137 138 dstDir, err := ioutil.TempDir("", "dstDir") 139 assert.NilError(t, err) 140 defer os.RemoveAll(dstDir) 141 142 srcFile1 := filepath.Join(srcDir, "file1") 143 srcFile2 := filepath.Join(srcDir, "file2") 144 dstFile1 := filepath.Join(dstDir, "file1") 145 dstFile2 := filepath.Join(dstDir, "file2") 146 assert.NilError(t, ioutil.WriteFile(srcFile1, []byte{}, 0777)) 147 assert.NilError(t, os.Link(srcFile1, srcFile2)) 148 149 assert.Check(t, DirCopy(srcDir, dstDir, Content, false)) 150 151 assert.NilError(t, unix.Stat(srcFile1, &srcFile1FileInfo)) 152 assert.NilError(t, unix.Stat(srcFile2, &srcFile2FileInfo)) 153 assert.Equal(t, srcFile1FileInfo.Ino, srcFile2FileInfo.Ino) 154 155 assert.NilError(t, unix.Stat(dstFile1, &dstFile1FileInfo)) 156 assert.NilError(t, unix.Stat(dstFile2, &dstFile2FileInfo)) 157 assert.Check(t, is.Equal(dstFile1FileInfo.Ino, dstFile2FileInfo.Ino)) 158 }