github.com/rawahars/moby@v24.0.4+incompatible/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  }