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