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