github.com/vrothberg/storage@v1.12.13/drivers/graphtest/graphtest_unix.go (about)

     1  // +build linux freebsd solaris
     2  
     3  package graphtest
     4  
     5  import (
     6  	"bytes"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"math/rand"
    10  	"os"
    11  	"path"
    12  	"path/filepath"
    13  	"reflect"
    14  	"testing"
    15  	"unsafe"
    16  
    17  	"github.com/containers/storage/drivers"
    18  	"github.com/containers/storage/pkg/archive"
    19  	"github.com/containers/storage/pkg/stringid"
    20  	"github.com/docker/go-units"
    21  	"github.com/pkg/errors"
    22  	"github.com/stretchr/testify/assert"
    23  	"github.com/stretchr/testify/require"
    24  	"golang.org/x/sys/unix"
    25  )
    26  
    27  var (
    28  	drv *Driver
    29  )
    30  
    31  // Driver conforms to graphdriver.Driver interface and
    32  // contains information such as root and reference count of the number of clients using it.
    33  // This helps in testing drivers added into the framework.
    34  type Driver struct {
    35  	graphdriver.Driver
    36  	root     string
    37  	runroot  string
    38  	refCount int
    39  }
    40  
    41  func newDriver(t testing.TB, name string, options []string) *Driver {
    42  	root, err := ioutil.TempDir("", "storage-graphtest-")
    43  	require.NoError(t, err)
    44  	runroot, err := ioutil.TempDir("", "storage-graphtest-")
    45  	require.NoError(t, err)
    46  
    47  	require.NoError(t, os.MkdirAll(root, 0755))
    48  	d, err := graphdriver.GetDriver(name, graphdriver.Options{DriverOptions: options, Root: root, RunRoot: runroot})
    49  	if err != nil {
    50  		t.Logf("graphdriver: %v\n", err)
    51  		cause := errors.Cause(err)
    52  		if cause == graphdriver.ErrNotSupported || cause == graphdriver.ErrPrerequisites || cause == graphdriver.ErrIncompatibleFS {
    53  			t.Skipf("Driver %s not supported", name)
    54  		}
    55  		t.Fatal(err)
    56  	}
    57  	return &Driver{d, root, runroot, 1}
    58  }
    59  
    60  func cleanup(t testing.TB, d *Driver) {
    61  	if err := drv.Cleanup(); err != nil {
    62  		t.Fatal(err)
    63  	}
    64  	os.RemoveAll(d.runroot)
    65  	os.RemoveAll(d.root)
    66  }
    67  
    68  // GetDriver create a new driver with given name or return an existing driver with the name updating the reference count.
    69  func GetDriver(t testing.TB, name string, options ...string) graphdriver.Driver {
    70  	if drv == nil {
    71  		drv = newDriver(t, name, options)
    72  	} else {
    73  		drv.refCount++
    74  	}
    75  	return drv
    76  }
    77  
    78  // PutDriver removes the driver if it is no longer used and updates the reference count.
    79  func PutDriver(t testing.TB) {
    80  	if drv == nil {
    81  		t.Skip("No driver to put!")
    82  	}
    83  	drv.refCount--
    84  	if drv.refCount == 0 {
    85  		cleanup(t, drv)
    86  		drv = nil
    87  	}
    88  }
    89  
    90  // DriverTestCreateEmpty creates a new image and verifies it is empty and the right metadata
    91  func DriverTestCreateEmpty(t testing.TB, drivername string, driverOptions ...string) {
    92  	driver := GetDriver(t, drivername, driverOptions...)
    93  	defer PutDriver(t)
    94  
    95  	err := driver.Create("empty", "", nil)
    96  	require.NoError(t, err)
    97  
    98  	defer func() {
    99  		require.NoError(t, driver.Remove("empty"))
   100  	}()
   101  
   102  	if !driver.Exists("empty") {
   103  		t.Fatal("Newly created image doesn't exist")
   104  	}
   105  
   106  	dir, err := driver.Get("empty", graphdriver.MountOpts{})
   107  	require.NoError(t, err)
   108  
   109  	verifyFile(t, dir, 0755|os.ModeDir, 0, 0)
   110  
   111  	// Verify that the directory is empty
   112  	fis, err := readDir(dir)
   113  	require.NoError(t, err)
   114  	assert.Len(t, fis, 0)
   115  
   116  	driver.Put("empty")
   117  }
   118  
   119  // DriverTestCreateBase create a base driver and verify.
   120  func DriverTestCreateBase(t testing.TB, drivername string, driverOptions ...string) {
   121  	driver := GetDriver(t, drivername, driverOptions...)
   122  	defer PutDriver(t)
   123  
   124  	createBase(t, driver, "Base")
   125  	defer func() {
   126  		require.NoError(t, driver.Remove("Base"))
   127  	}()
   128  	verifyBase(t, driver, "Base")
   129  }
   130  
   131  // DriverTestCreateSnap Create a driver and snap and verify.
   132  func DriverTestCreateSnap(t testing.TB, drivername string, driverOptions ...string) {
   133  	driver := GetDriver(t, drivername, driverOptions...)
   134  	defer PutDriver(t)
   135  
   136  	createBase(t, driver, "Base")
   137  	defer func() {
   138  		require.NoError(t, driver.Remove("Base"))
   139  	}()
   140  
   141  	err := driver.Create("Snap", "Base", nil)
   142  	require.NoError(t, err)
   143  	defer func() {
   144  		require.NoError(t, driver.Remove("Snap"))
   145  	}()
   146  
   147  	verifyBase(t, driver, "Snap")
   148  }
   149  
   150  // DriverTestCreateFromTemplate Create a driver and template of a snap and verifies its
   151  // contents.
   152  func DriverTestCreateFromTemplate(t testing.TB, drivername string, driverOptions ...string) {
   153  	driver := GetDriver(t, drivername, driverOptions...)
   154  	defer PutDriver(t)
   155  
   156  	createBase(t, driver, "Base")
   157  	defer func() {
   158  		require.NoError(t, driver.Remove("Base"))
   159  	}()
   160  
   161  	err := driver.Create("Snap", "Base", nil)
   162  	require.NoError(t, err)
   163  	defer func() {
   164  		require.NoError(t, driver.Remove("Snap"))
   165  	}()
   166  
   167  	content := []byte("test content")
   168  	if err := addFile(driver, "Snap", "testfile.txt", content); err != nil {
   169  		t.Fatal(err)
   170  	}
   171  
   172  	err = driver.CreateFromTemplate("FromTemplate", "Snap", nil, "Base", nil, nil, true)
   173  	require.NoError(t, err)
   174  	defer func() {
   175  		require.NoError(t, driver.Remove("FromTemplate"))
   176  	}()
   177  
   178  	err = driver.CreateFromTemplate("ROFromTemplate", "Snap", nil, "Base", nil, nil, false)
   179  	require.NoError(t, err)
   180  	defer func() {
   181  		require.NoError(t, driver.Remove("ROFromTemplate"))
   182  	}()
   183  
   184  	noChanges := []archive.Change{}
   185  
   186  	changes, err := driver.Changes("FromTemplate", nil, "Snap", nil, "")
   187  	if err != nil {
   188  		t.Fatal(err)
   189  	}
   190  	if err = checkChanges(noChanges, changes); err != nil {
   191  		t.Fatal(err)
   192  	}
   193  
   194  	changes, err = driver.Changes("ROFromTemplate", nil, "Snap", nil, "")
   195  	if err != nil {
   196  		t.Fatal(err)
   197  	}
   198  	if err = checkChanges(noChanges, changes); err != nil {
   199  		t.Fatal(err)
   200  	}
   201  
   202  	if err := checkFile(driver, "FromTemplate", "testfile.txt", content); err != nil {
   203  		t.Fatal(err)
   204  	}
   205  	if err := checkFile(driver, "ROFromTemplate", "testfile.txt", content); err != nil {
   206  		t.Fatal(err)
   207  	}
   208  	if err := checkFile(driver, "Snap", "testfile.txt", content); err != nil {
   209  		t.Fatal(err)
   210  	}
   211  
   212  	expectedChanges := []archive.Change{{
   213  		Path: "/testfile.txt",
   214  		Kind: archive.ChangeAdd,
   215  	}}
   216  
   217  	changes, err = driver.Changes("Snap", nil, "Base", nil, "")
   218  	if err != nil {
   219  		t.Fatal(err)
   220  	}
   221  	if err = checkChanges(expectedChanges, changes); err != nil {
   222  		t.Fatal(err)
   223  	}
   224  
   225  	changes, err = driver.Changes("FromTemplate", nil, "Base", nil, "")
   226  	if err != nil {
   227  		t.Fatal(err)
   228  	}
   229  	if err = checkChanges(expectedChanges, changes); err != nil {
   230  		t.Fatal(err)
   231  	}
   232  
   233  	changes, err = driver.Changes("ROFromTemplate", nil, "Base", nil, "")
   234  	if err != nil {
   235  		t.Fatal(err)
   236  	}
   237  	if err = checkChanges(expectedChanges, changes); err != nil {
   238  		t.Fatal(err)
   239  	}
   240  
   241  	verifyBase(t, driver, "Base")
   242  }
   243  
   244  // DriverTestDeepLayerRead reads a file from a lower layer under a given number of layers
   245  func DriverTestDeepLayerRead(t testing.TB, layerCount int, drivername string, driverOptions ...string) {
   246  	driver := GetDriver(t, drivername, driverOptions...)
   247  	defer PutDriver(t)
   248  
   249  	base := stringid.GenerateRandomID()
   250  	if err := driver.Create(base, "", nil); err != nil {
   251  		t.Fatal(err)
   252  	}
   253  
   254  	content := []byte("test content")
   255  	if err := addFile(driver, base, "testfile.txt", content); err != nil {
   256  		t.Fatal(err)
   257  	}
   258  
   259  	topLayer, err := addManyLayers(driver, base, layerCount)
   260  	if err != nil {
   261  		t.Fatal(err)
   262  	}
   263  
   264  	err = checkManyLayers(driver, topLayer, layerCount)
   265  	if err != nil {
   266  		t.Fatal(err)
   267  	}
   268  
   269  	if err := checkFile(driver, topLayer, "testfile.txt", content); err != nil {
   270  		t.Fatal(err)
   271  	}
   272  }
   273  
   274  // DriverTestDiffApply tests diffing and applying produces the same layer
   275  func DriverTestDiffApply(t testing.TB, fileCount int, drivername string, driverOptions ...string) {
   276  	driver := GetDriver(t, drivername, driverOptions...)
   277  	defer PutDriver(t)
   278  	base := stringid.GenerateRandomID()
   279  	upper := stringid.GenerateRandomID()
   280  	deleteFile := "file-remove.txt"
   281  	deleteFileContent := []byte("This file should get removed in upper!")
   282  	deleteDir := "var/lib"
   283  
   284  	if err := driver.Create(base, "", nil); err != nil {
   285  		t.Fatal(err)
   286  	}
   287  
   288  	if err := addManyFiles(driver, base, fileCount, 3); err != nil {
   289  		t.Fatal(err)
   290  	}
   291  
   292  	if err := addFile(driver, base, deleteFile, deleteFileContent); err != nil {
   293  		t.Fatal(err)
   294  	}
   295  
   296  	if err := addDirectory(driver, base, deleteDir); err != nil {
   297  		t.Fatal(err)
   298  	}
   299  
   300  	if err := driver.Create(upper, base, nil); err != nil {
   301  		t.Fatal(err)
   302  	}
   303  
   304  	if err := addManyFiles(driver, upper, fileCount, 6); err != nil {
   305  		t.Fatal(err)
   306  	}
   307  
   308  	if err := removeAll(driver, upper, deleteFile, deleteDir); err != nil {
   309  		t.Fatal(err)
   310  	}
   311  
   312  	diffSize, err := driver.DiffSize(upper, nil, "", nil, "")
   313  	if err != nil {
   314  		t.Fatal(err)
   315  	}
   316  
   317  	diff := stringid.GenerateRandomID()
   318  	if err := driver.Create(diff, base, nil); err != nil {
   319  		t.Fatal(err)
   320  	}
   321  
   322  	if err := checkManyFiles(driver, diff, fileCount, 3); err != nil {
   323  		t.Fatal(err)
   324  	}
   325  
   326  	if err := checkFile(driver, diff, deleteFile, deleteFileContent); err != nil {
   327  		t.Fatal(err)
   328  	}
   329  
   330  	arch, err := driver.Diff(upper, nil, base, nil, "")
   331  	if err != nil {
   332  		t.Fatal(err)
   333  	}
   334  
   335  	buf := bytes.NewBuffer(nil)
   336  	if _, err := buf.ReadFrom(arch); err != nil {
   337  		t.Fatal(err)
   338  	}
   339  	if err := arch.Close(); err != nil {
   340  		t.Fatal(err)
   341  	}
   342  
   343  	applyDiffSize, err := driver.ApplyDiff(diff, nil, base, "", bytes.NewReader(buf.Bytes()))
   344  	if err != nil {
   345  		t.Fatal(err)
   346  	}
   347  
   348  	if applyDiffSize != diffSize {
   349  		t.Fatalf("Apply diff size different, got %d, expected %d", applyDiffSize, diffSize)
   350  	}
   351  
   352  	if err := checkManyFiles(driver, diff, fileCount, 6); err != nil {
   353  		t.Fatal(err)
   354  	}
   355  
   356  	if err := checkFileRemoved(driver, diff, deleteFile); err != nil {
   357  		t.Fatal(err)
   358  	}
   359  
   360  	if err := checkFileRemoved(driver, diff, deleteDir); err != nil {
   361  		t.Fatal(err)
   362  	}
   363  }
   364  
   365  // DriverTestChanges tests computed changes on a layer matches changes made
   366  func DriverTestChanges(t testing.TB, drivername string, driverOptions ...string) {
   367  	driver := GetDriver(t, drivername, driverOptions...)
   368  	defer PutDriver(t)
   369  	base := stringid.GenerateRandomID()
   370  	upper := stringid.GenerateRandomID()
   371  	if err := driver.Create(base, "", nil); err != nil {
   372  		t.Fatal(err)
   373  	}
   374  
   375  	if err := addManyFiles(driver, base, 20, 3); err != nil {
   376  		t.Fatal(err)
   377  	}
   378  
   379  	if err := driver.Create(upper, base, nil); err != nil {
   380  		t.Fatal(err)
   381  	}
   382  
   383  	expectedChanges, err := changeManyFiles(driver, upper, 20, 6)
   384  	if err != nil {
   385  		t.Fatal(err)
   386  	}
   387  
   388  	changes, err := driver.Changes(upper, nil, base, nil, "")
   389  	if err != nil {
   390  		t.Fatal(err)
   391  	}
   392  
   393  	if err = checkChanges(expectedChanges, changes); err != nil {
   394  		t.Fatal(err)
   395  	}
   396  }
   397  
   398  func writeRandomFile(path string, size uint64) error {
   399  	buf := make([]int64, size/8)
   400  
   401  	r := rand.NewSource(0)
   402  	for i := range buf {
   403  		buf[i] = r.Int63()
   404  	}
   405  
   406  	// Cast to []byte
   407  	header := *(*reflect.SliceHeader)(unsafe.Pointer(&buf))
   408  	header.Len *= 8
   409  	header.Cap *= 8
   410  	data := *(*[]byte)(unsafe.Pointer(&header))
   411  
   412  	return ioutil.WriteFile(path, data, 0700)
   413  }
   414  
   415  // DriverTestSetQuota Create a driver and test setting quota.
   416  func DriverTestSetQuota(t *testing.T, drivername string) {
   417  	driver := GetDriver(t, drivername)
   418  	defer PutDriver(t)
   419  
   420  	createBase(t, driver, "Base")
   421  	createOpts := &graphdriver.CreateOpts{}
   422  	createOpts.StorageOpt = make(map[string]string, 1)
   423  	createOpts.StorageOpt["size"] = "50M"
   424  	if err := driver.Create("zfsTest", "Base", createOpts); err != nil {
   425  		t.Fatal(err)
   426  	}
   427  
   428  	mountPath, err := driver.Get("zfsTest", graphdriver.MountOpts{})
   429  	if err != nil {
   430  		t.Fatal(err)
   431  	}
   432  
   433  	quota := uint64(50 * units.MiB)
   434  	err = writeRandomFile(path.Join(mountPath, "file"), quota*2)
   435  	if pathError, ok := err.(*os.PathError); ok && pathError.Err != unix.EDQUOT {
   436  		t.Fatalf("expect write() to fail with %v, got %v", unix.EDQUOT, err)
   437  	}
   438  
   439  }
   440  
   441  // DriverTestEcho tests that we can diff a layer correctly, focusing on trouble spots that NaiveDiff doesn't have
   442  func DriverTestEcho(t testing.TB, drivername string, driverOptions ...string) {
   443  	driver := GetDriver(t, drivername, driverOptions...)
   444  	defer PutDriver(t)
   445  	var err error
   446  	var root string
   447  	components := 10
   448  
   449  	for depth := 0; depth < components; depth++ {
   450  		base := stringid.GenerateRandomID()
   451  		second := stringid.GenerateRandomID()
   452  		third := stringid.GenerateRandomID()
   453  
   454  		if err := driver.Create(base, "", nil); err != nil {
   455  			t.Fatal(err)
   456  		}
   457  
   458  		if root, err = driver.Get(base, graphdriver.MountOpts{}); err != nil {
   459  			t.Fatal(err)
   460  		}
   461  
   462  		paths := []string{}
   463  		path := "/"
   464  		expectedChanges := []archive.Change{}
   465  		for i := 0; i < components-1; i++ {
   466  			path = filepath.Join(path, fmt.Sprintf("subdir%d", i+1))
   467  			paths = append(paths, path)
   468  			if err = os.Mkdir(filepath.Join(root, path), 0700); err != nil {
   469  				t.Fatal(err)
   470  			}
   471  			expectedChanges = append(expectedChanges, archive.Change{Kind: archive.ChangeAdd, Path: path})
   472  		}
   473  		path = filepath.Join(path, "file")
   474  		paths = append(paths, path)
   475  		if err = ioutil.WriteFile(filepath.Join(root, path), randomContent(128, int64(depth)), 0600); err != nil {
   476  			t.Fatal(err)
   477  		}
   478  		expectedChanges = append(expectedChanges, archive.Change{Kind: archive.ChangeAdd, Path: path})
   479  
   480  		changes, err := driver.Changes(base, nil, "", nil, "")
   481  		if err != nil {
   482  			t.Fatal(err)
   483  		}
   484  
   485  		if err = checkChanges(expectedChanges, changes); err != nil {
   486  			t.Fatal(err)
   487  		}
   488  
   489  		if err := driver.Create(second, base, nil); err != nil {
   490  			t.Fatal(err)
   491  		}
   492  
   493  		if root, err = driver.Get(second, graphdriver.MountOpts{}); err != nil {
   494  			t.Fatal(err)
   495  		}
   496  
   497  		if err = os.RemoveAll(filepath.Join(root, paths[depth])); err != nil {
   498  			t.Fatal(err)
   499  		}
   500  		expectedChanges = []archive.Change{}
   501  		for i := 0; i < depth; i++ {
   502  			expectedChanges = append(expectedChanges, archive.Change{Kind: archive.ChangeModify, Path: paths[i]})
   503  		}
   504  		expectedChanges = append(expectedChanges, archive.Change{Kind: archive.ChangeDelete, Path: paths[depth]})
   505  
   506  		changes, err = driver.Changes(second, nil, base, nil, "")
   507  		if err != nil {
   508  			t.Fatal(err)
   509  		}
   510  
   511  		if err = checkChanges(expectedChanges, changes); err != nil {
   512  			t.Fatal(err)
   513  		}
   514  
   515  		if err = driver.Create(third, second, nil); err != nil {
   516  			t.Fatal(err)
   517  		}
   518  
   519  		if root, err = driver.Get(third, graphdriver.MountOpts{}); err != nil {
   520  			t.Fatal(err)
   521  		}
   522  
   523  		expectedChanges = []archive.Change{}
   524  		for i := 0; i < depth; i++ {
   525  			expectedChanges = append(expectedChanges, archive.Change{Kind: archive.ChangeModify, Path: paths[i]})
   526  		}
   527  		for i := depth; i < components-1; i++ {
   528  			if err = os.Mkdir(filepath.Join(root, paths[i]), 0700); err != nil {
   529  				t.Fatal(err)
   530  			}
   531  			expectedChanges = append(expectedChanges, archive.Change{Kind: archive.ChangeAdd, Path: paths[i]})
   532  		}
   533  		if err = ioutil.WriteFile(filepath.Join(root, paths[len(paths)-1]), randomContent(128, int64(depth)), 0600); err != nil {
   534  			t.Fatal(err)
   535  		}
   536  		expectedChanges = append(expectedChanges, archive.Change{Kind: archive.ChangeAdd, Path: paths[len(paths)-1]})
   537  
   538  		changes, err = driver.Changes(third, nil, second, nil, "")
   539  		if err != nil {
   540  			t.Fatal(err)
   541  		}
   542  
   543  		if err = checkChanges(expectedChanges, changes); err != nil {
   544  			t.Fatal(err)
   545  		}
   546  
   547  		err = driver.Put(third)
   548  		if err != nil {
   549  			t.Fatal(err)
   550  		}
   551  		err = driver.Put(second)
   552  		if err != nil {
   553  			t.Fatal(err)
   554  		}
   555  		err = driver.Put(base)
   556  		if err != nil {
   557  			t.Fatal(err)
   558  		}
   559  	}
   560  }