github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/daemon/graphdriver/graphtest/graphtest_unix.go (about) 1 //go:build linux || freebsd 2 // +build linux freebsd 3 4 package graphtest // import "github.com/docker/docker/daemon/graphdriver/graphtest" 5 6 import ( 7 "bytes" 8 "crypto/rand" 9 "os" 10 "path" 11 "testing" 12 13 "github.com/docker/docker/daemon/graphdriver" 14 "github.com/docker/docker/pkg/stringid" 15 "github.com/docker/docker/quota" 16 units "github.com/docker/go-units" 17 "golang.org/x/sys/unix" 18 "gotest.tools/v3/assert" 19 is "gotest.tools/v3/assert/cmp" 20 ) 21 22 var ( 23 drv *Driver 24 ) 25 26 // Driver conforms to graphdriver.Driver interface and 27 // contains information such as root and reference count of the number of clients using it. 28 // This helps in testing drivers added into the framework. 29 type Driver struct { 30 graphdriver.Driver 31 root string 32 refCount int 33 } 34 35 func newDriver(t testing.TB, name string, options []string) *Driver { 36 root, err := os.MkdirTemp("", "docker-graphtest-") 37 assert.NilError(t, err) 38 39 assert.NilError(t, os.MkdirAll(root, 0755)) 40 d, err := graphdriver.GetDriver(name, nil, graphdriver.Options{DriverOptions: options, Root: root}) 41 if err != nil { 42 t.Logf("graphdriver: %v\n", err) 43 if graphdriver.IsDriverNotSupported(err) { 44 t.Skipf("Driver %s not supported", name) 45 } 46 t.Fatal(err) 47 } 48 return &Driver{d, root, 1} 49 } 50 51 func cleanup(t testing.TB, d *Driver) { 52 if err := drv.Cleanup(); err != nil { 53 t.Fatal(err) 54 } 55 os.RemoveAll(d.root) 56 } 57 58 // GetDriver create a new driver with given name or return an existing driver with the name updating the reference count. 59 func GetDriver(t testing.TB, name string, options ...string) graphdriver.Driver { 60 if drv == nil { 61 drv = newDriver(t, name, options) 62 } else { 63 drv.refCount++ 64 } 65 return drv 66 } 67 68 // PutDriver removes the driver if it is no longer used and updates the reference count. 69 func PutDriver(t testing.TB) { 70 if drv == nil { 71 t.Skip("No driver to put!") 72 } 73 drv.refCount-- 74 if drv.refCount == 0 { 75 cleanup(t, drv) 76 drv = nil 77 } 78 } 79 80 // DriverTestCreateEmpty creates a new image and verifies it is empty and the right metadata 81 func DriverTestCreateEmpty(t testing.TB, drivername string, driverOptions ...string) { 82 driver := GetDriver(t, drivername, driverOptions...) 83 defer PutDriver(t) 84 85 err := driver.Create("empty", "", nil) 86 assert.NilError(t, err) 87 88 defer func() { 89 assert.NilError(t, driver.Remove("empty")) 90 }() 91 92 if !driver.Exists("empty") { 93 t.Fatal("Newly created image doesn't exist") 94 } 95 96 dir, err := driver.Get("empty", "") 97 assert.NilError(t, err) 98 99 verifyFile(t, dir, 0755|os.ModeDir, 0, 0) 100 101 // Verify that the directory is empty 102 fis, err := readDir(dir) 103 assert.NilError(t, err) 104 assert.Check(t, is.Len(fis, 0)) 105 106 driver.Put("empty") 107 } 108 109 // DriverTestCreateBase create a base driver and verify. 110 func DriverTestCreateBase(t testing.TB, drivername string, driverOptions ...string) { 111 driver := GetDriver(t, drivername, driverOptions...) 112 defer PutDriver(t) 113 114 createBase(t, driver, "Base") 115 defer func() { 116 assert.NilError(t, driver.Remove("Base")) 117 }() 118 verifyBase(t, driver, "Base") 119 } 120 121 // DriverTestCreateSnap Create a driver and snap and verify. 122 func DriverTestCreateSnap(t testing.TB, drivername string, driverOptions ...string) { 123 driver := GetDriver(t, drivername, driverOptions...) 124 defer PutDriver(t) 125 126 createBase(t, driver, "Base") 127 defer func() { 128 assert.NilError(t, driver.Remove("Base")) 129 }() 130 131 err := driver.Create("Snap", "Base", nil) 132 assert.NilError(t, err) 133 defer func() { 134 assert.NilError(t, driver.Remove("Snap")) 135 }() 136 137 verifyBase(t, driver, "Snap") 138 } 139 140 // DriverTestDeepLayerRead reads a file from a lower layer under a given number of layers 141 func DriverTestDeepLayerRead(t testing.TB, layerCount int, drivername string, driverOptions ...string) { 142 driver := GetDriver(t, drivername, driverOptions...) 143 defer PutDriver(t) 144 145 base := stringid.GenerateRandomID() 146 if err := driver.Create(base, "", nil); err != nil { 147 t.Fatal(err) 148 } 149 150 content := []byte("test content") 151 if err := addFile(driver, base, "testfile.txt", content); err != nil { 152 t.Fatal(err) 153 } 154 155 topLayer, err := addManyLayers(driver, base, layerCount) 156 if err != nil { 157 t.Fatal(err) 158 } 159 160 err = checkManyLayers(driver, topLayer, layerCount) 161 if err != nil { 162 t.Fatal(err) 163 } 164 165 if err := checkFile(driver, topLayer, "testfile.txt", content); err != nil { 166 t.Fatal(err) 167 } 168 } 169 170 // DriverTestDiffApply tests diffing and applying produces the same layer 171 func DriverTestDiffApply(t testing.TB, fileCount int, drivername string, driverOptions ...string) { 172 driver := GetDriver(t, drivername, driverOptions...) 173 defer PutDriver(t) 174 base := stringid.GenerateRandomID() 175 upper := stringid.GenerateRandomID() 176 deleteFile := "file-remove.txt" 177 deleteFileContent := []byte("This file should get removed in upper!") 178 deleteDir := "var/lib" 179 180 if err := driver.Create(base, "", nil); err != nil { 181 t.Fatal(err) 182 } 183 184 if err := addManyFiles(driver, base, fileCount, 3); err != nil { 185 t.Fatal(err) 186 } 187 188 if err := addFile(driver, base, deleteFile, deleteFileContent); err != nil { 189 t.Fatal(err) 190 } 191 192 if err := addDirectory(driver, base, deleteDir); err != nil { 193 t.Fatal(err) 194 } 195 196 if err := driver.Create(upper, base, nil); err != nil { 197 t.Fatal(err) 198 } 199 200 if err := addManyFiles(driver, upper, fileCount, 6); err != nil { 201 t.Fatal(err) 202 } 203 204 if err := removeAll(driver, upper, deleteFile, deleteDir); err != nil { 205 t.Fatal(err) 206 } 207 208 diffSize, err := driver.DiffSize(upper, "") 209 if err != nil { 210 t.Fatal(err) 211 } 212 213 diff := stringid.GenerateRandomID() 214 if err := driver.Create(diff, base, nil); err != nil { 215 t.Fatal(err) 216 } 217 218 if err := checkManyFiles(driver, diff, fileCount, 3); err != nil { 219 t.Fatal(err) 220 } 221 222 if err := checkFile(driver, diff, deleteFile, deleteFileContent); err != nil { 223 t.Fatal(err) 224 } 225 226 arch, err := driver.Diff(upper, base) 227 if err != nil { 228 t.Fatal(err) 229 } 230 231 buf := bytes.NewBuffer(nil) 232 if _, err := buf.ReadFrom(arch); err != nil { 233 t.Fatal(err) 234 } 235 if err := arch.Close(); err != nil { 236 t.Fatal(err) 237 } 238 239 applyDiffSize, err := driver.ApplyDiff(diff, base, bytes.NewReader(buf.Bytes())) 240 if err != nil { 241 t.Fatal(err) 242 } 243 244 if applyDiffSize != diffSize { 245 t.Fatalf("Apply diff size different, got %d, expected %d", applyDiffSize, diffSize) 246 } 247 248 if err := checkManyFiles(driver, diff, fileCount, 6); err != nil { 249 t.Fatal(err) 250 } 251 252 if err := checkFileRemoved(driver, diff, deleteFile); err != nil { 253 t.Fatal(err) 254 } 255 256 if err := checkFileRemoved(driver, diff, deleteDir); err != nil { 257 t.Fatal(err) 258 } 259 } 260 261 // DriverTestChanges tests computed changes on a layer matches changes made 262 func DriverTestChanges(t testing.TB, drivername string, driverOptions ...string) { 263 driver := GetDriver(t, drivername, driverOptions...) 264 defer PutDriver(t) 265 base := stringid.GenerateRandomID() 266 upper := stringid.GenerateRandomID() 267 if err := driver.Create(base, "", nil); err != nil { 268 t.Fatal(err) 269 } 270 271 if err := addManyFiles(driver, base, 20, 3); err != nil { 272 t.Fatal(err) 273 } 274 275 if err := driver.Create(upper, base, nil); err != nil { 276 t.Fatal(err) 277 } 278 279 expectedChanges, err := changeManyFiles(driver, upper, 20, 6) 280 if err != nil { 281 t.Fatal(err) 282 } 283 284 changes, err := driver.Changes(upper, base) 285 if err != nil { 286 t.Fatal(err) 287 } 288 289 if err = checkChanges(expectedChanges, changes); err != nil { 290 t.Fatal(err) 291 } 292 } 293 294 func writeRandomFile(path string, size uint64) error { 295 data := make([]byte, size) 296 _, err := rand.Read(data) 297 if err != nil { 298 return err 299 } 300 return os.WriteFile(path, data, 0700) 301 } 302 303 // DriverTestSetQuota Create a driver and test setting quota. 304 func DriverTestSetQuota(t *testing.T, drivername string, required bool) { 305 driver := GetDriver(t, drivername) 306 defer PutDriver(t) 307 308 createBase(t, driver, "Base") 309 createOpts := &graphdriver.CreateOpts{} 310 createOpts.StorageOpt = make(map[string]string, 1) 311 createOpts.StorageOpt["size"] = "50M" 312 layerName := drivername + "Test" 313 if err := driver.CreateReadWrite(layerName, "Base", createOpts); err == quota.ErrQuotaNotSupported && !required { 314 t.Skipf("Quota not supported on underlying filesystem: %v", err) 315 } else if err != nil { 316 t.Fatal(err) 317 } 318 319 mountPath, err := driver.Get(layerName, "") 320 if err != nil { 321 t.Fatal(err) 322 } 323 324 quota := uint64(50 * units.MiB) 325 326 // Try to write a file smaller than quota, and ensure it works 327 err = writeRandomFile(path.Join(mountPath, "smallfile"), quota/2) 328 if err != nil { 329 t.Fatal(err) 330 } 331 defer os.Remove(path.Join(mountPath, "smallfile")) 332 333 // Try to write a file bigger than quota. We've already filled up half the quota, so hitting the limit should be easy 334 err = writeRandomFile(path.Join(mountPath, "bigfile"), quota) 335 if err == nil { 336 t.Fatalf("expected write to fail(), instead had success") 337 } 338 if pathError, ok := err.(*os.PathError); ok && pathError.Err != unix.EDQUOT && pathError.Err != unix.ENOSPC { 339 os.Remove(path.Join(mountPath, "bigfile")) 340 t.Fatalf("expect write() to fail with %v or %v, got %v", unix.EDQUOT, unix.ENOSPC, pathError.Err) 341 } 342 }