github.com/toplink-cn/moby@v0.0.0-20240305205811-460b4aebdf81/layer/mount_test.go (about) 1 package layer // import "github.com/docker/docker/layer" 2 3 import ( 4 "io" 5 "os" 6 "path/filepath" 7 "runtime" 8 "sort" 9 "testing" 10 11 "github.com/containerd/continuity/driver" 12 "github.com/docker/docker/pkg/archive" 13 ) 14 15 func TestMountInit(t *testing.T) { 16 // TODO Windows: Figure out why this is failing 17 if runtime.GOOS == "windows" { 18 t.Skip("Failing on Windows") 19 } 20 ls, _, cleanup := newTestStore(t) 21 defer cleanup() 22 23 basefile := newTestFile("testfile.txt", []byte("base data!"), 0o644) 24 initfile := newTestFile("testfile.txt", []byte("init data!"), 0o777) 25 26 li := initWithFiles(basefile) 27 layer, err := createLayer(ls, "", li) 28 if err != nil { 29 t.Fatal(err) 30 } 31 32 mountInit := func(root string) error { 33 return initfile.ApplyFile(root) 34 } 35 36 rwLayerOpts := &CreateRWLayerOpts{ 37 InitFunc: mountInit, 38 } 39 m, err := ls.CreateRWLayer("fun-mount", layer.ChainID(), rwLayerOpts) 40 if err != nil { 41 t.Fatal(err) 42 } 43 44 pathFS, err := m.Mount("") 45 if err != nil { 46 t.Fatal(err) 47 } 48 49 fi, err := os.Stat(filepath.Join(pathFS, "testfile.txt")) 50 if err != nil { 51 t.Fatal(err) 52 } 53 54 f, err := os.Open(filepath.Join(pathFS, "testfile.txt")) 55 if err != nil { 56 t.Fatal(err) 57 } 58 defer f.Close() 59 60 b, err := io.ReadAll(f) 61 if err != nil { 62 t.Fatal(err) 63 } 64 65 if expected := "init data!"; string(b) != expected { 66 t.Fatalf("Unexpected test file contents %q, expected %q", string(b), expected) 67 } 68 69 if fi.Mode().Perm() != 0o777 { 70 t.Fatalf("Unexpected filemode %o, expecting %o", fi.Mode().Perm(), 0o777) 71 } 72 } 73 74 func TestMountSize(t *testing.T) { 75 // TODO Windows: Figure out why this is failing 76 if runtime.GOOS == "windows" { 77 t.Skip("Failing on Windows") 78 } 79 ls, _, cleanup := newTestStore(t) 80 defer cleanup() 81 82 content1 := []byte("Base contents") 83 content2 := []byte("Mutable contents") 84 contentInit := []byte("why am I excluded from the size ☹") 85 86 li := initWithFiles(newTestFile("file1", content1, 0o644)) 87 layer, err := createLayer(ls, "", li) 88 if err != nil { 89 t.Fatal(err) 90 } 91 92 mountInit := func(root string) error { 93 return newTestFile("file-init", contentInit, 0o777).ApplyFile(root) 94 } 95 rwLayerOpts := &CreateRWLayerOpts{ 96 InitFunc: mountInit, 97 } 98 99 m, err := ls.CreateRWLayer("mount-size", layer.ChainID(), rwLayerOpts) 100 if err != nil { 101 t.Fatal(err) 102 } 103 104 pathFS, err := m.Mount("") 105 if err != nil { 106 t.Fatal(err) 107 } 108 109 if err := os.WriteFile(filepath.Join(pathFS, "file2"), content2, 0o755); err != nil { 110 t.Fatal(err) 111 } 112 113 mountSize, err := m.Size() 114 if err != nil { 115 t.Fatal(err) 116 } 117 118 if expected := len(content2); int(mountSize) != expected { 119 t.Fatalf("Unexpected mount size %d, expected %d", int(mountSize), expected) 120 } 121 } 122 123 func TestMountChanges(t *testing.T) { 124 // TODO Windows: Figure out why this is failing 125 if runtime.GOOS == "windows" { 126 t.Skip("Failing on Windows") 127 } 128 ls, _, cleanup := newTestStore(t) 129 defer cleanup() 130 131 basefiles := []FileApplier{ 132 newTestFile("testfile1.txt", []byte("base data!"), 0o644), 133 newTestFile("testfile2.txt", []byte("base data!"), 0o644), 134 newTestFile("testfile3.txt", []byte("base data!"), 0o644), 135 } 136 initfile := newTestFile("testfile1.txt", []byte("init data!"), 0o777) 137 138 li := initWithFiles(basefiles...) 139 layer, err := createLayer(ls, "", li) 140 if err != nil { 141 t.Fatal(err) 142 } 143 144 mountInit := func(root string) error { 145 return initfile.ApplyFile(root) 146 } 147 rwLayerOpts := &CreateRWLayerOpts{ 148 InitFunc: mountInit, 149 } 150 151 m, err := ls.CreateRWLayer("mount-changes", layer.ChainID(), rwLayerOpts) 152 if err != nil { 153 t.Fatal(err) 154 } 155 156 pathFS, err := m.Mount("") 157 if err != nil { 158 t.Fatal(err) 159 } 160 161 if err := driver.LocalDriver.Lchmod(filepath.Join(pathFS, "testfile1.txt"), 0o755); err != nil { 162 t.Fatal(err) 163 } 164 165 if err := os.WriteFile(filepath.Join(pathFS, "testfile1.txt"), []byte("mount data!"), 0o755); err != nil { 166 t.Fatal(err) 167 } 168 169 if err := os.Remove(filepath.Join(pathFS, "testfile2.txt")); err != nil { 170 t.Fatal(err) 171 } 172 173 if err := driver.LocalDriver.Lchmod(filepath.Join(pathFS, "testfile3.txt"), 0o755); err != nil { 174 t.Fatal(err) 175 } 176 177 if err := os.WriteFile(filepath.Join(pathFS, "testfile4.txt"), []byte("mount data!"), 0o644); err != nil { 178 t.Fatal(err) 179 } 180 181 changes, err := m.Changes() 182 if err != nil { 183 t.Fatal(err) 184 } 185 186 if expected := 4; len(changes) != expected { 187 t.Fatalf("Wrong number of changes %d, expected %d", len(changes), expected) 188 } 189 190 sortChanges(changes) 191 192 assertChange(t, changes[0], archive.Change{ 193 Path: "/testfile1.txt", 194 Kind: archive.ChangeModify, 195 }) 196 assertChange(t, changes[1], archive.Change{ 197 Path: "/testfile2.txt", 198 Kind: archive.ChangeDelete, 199 }) 200 assertChange(t, changes[2], archive.Change{ 201 Path: "/testfile3.txt", 202 Kind: archive.ChangeModify, 203 }) 204 assertChange(t, changes[3], archive.Change{ 205 Path: "/testfile4.txt", 206 Kind: archive.ChangeAdd, 207 }) 208 } 209 210 func TestMountApply(t *testing.T) { 211 // TODO Windows: Figure out why this is failing 212 if runtime.GOOS == "windows" { 213 t.Skip("Failing on Windows") 214 } 215 ls, _, cleanup := newTestStore(t) 216 defer cleanup() 217 218 basefile := newTestFile("testfile.txt", []byte("base data!"), 0o644) 219 newfile := newTestFile("newfile.txt", []byte("new data!"), 0o755) 220 221 li := initWithFiles(basefile) 222 layer, err := createLayer(ls, "", li) 223 if err != nil { 224 t.Fatal(err) 225 } 226 227 di := initWithFiles(newfile) 228 diffLayer, err := createLayer(ls, "", di) 229 if err != nil { 230 t.Fatal(err) 231 } 232 233 m, err := ls.CreateRWLayer("fun-mount", layer.ChainID(), nil) 234 if err != nil { 235 t.Fatal(err) 236 } 237 238 r, err := diffLayer.TarStream() 239 if err != nil { 240 t.Fatal(err) 241 } 242 243 if _, err := m.ApplyDiff(r); err != nil { 244 t.Fatal(err) 245 } 246 247 pathFS, err := m.Mount("") 248 if err != nil { 249 t.Fatal(err) 250 } 251 252 f, err := os.Open(filepath.Join(pathFS, "newfile.txt")) 253 if err != nil { 254 t.Fatal(err) 255 } 256 defer f.Close() 257 258 b, err := io.ReadAll(f) 259 if err != nil { 260 t.Fatal(err) 261 } 262 263 if expected := "new data!"; string(b) != expected { 264 t.Fatalf("Unexpected test file contents %q, expected %q", string(b), expected) 265 } 266 } 267 268 func assertChange(t *testing.T, actual, expected archive.Change) { 269 if actual.Path != expected.Path { 270 t.Fatalf("Unexpected change path %s, expected %s", actual.Path, expected.Path) 271 } 272 if actual.Kind != expected.Kind { 273 t.Fatalf("Unexpected change type %s, expected %s", actual.Kind, expected.Kind) 274 } 275 } 276 277 func sortChanges(changes []archive.Change) { 278 cs := &changeSorter{ 279 changes: changes, 280 } 281 sort.Sort(cs) 282 } 283 284 type changeSorter struct { 285 changes []archive.Change 286 } 287 288 func (cs *changeSorter) Len() int { 289 return len(cs.changes) 290 } 291 292 func (cs *changeSorter) Swap(i, j int) { 293 cs.changes[i], cs.changes[j] = cs.changes[j], cs.changes[i] 294 } 295 296 func (cs *changeSorter) Less(i, j int) bool { 297 return cs.changes[i].Path < cs.changes[j].Path 298 }