github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/daemon/graphdriver/graphtest/graphtest_unix.go (about)

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