daemon/graphdriver/graphtest/graphtest_unix.go
934328d8
 // +build linux freebsd solaris
87649673
 
27744062
 package graphtest
 
 import (
8b0441d4
 	"bytes"
27744062
 	"io/ioutil"
04b4e3e6
 	"math/rand"
27744062
 	"os"
 	"path"
04b4e3e6
 	"reflect"
27744062
 	"testing"
04b4e3e6
 	"unsafe"
f08cd445
 
b3ee9ac7
 	"github.com/docker/docker/daemon/graphdriver"
8b0441d4
 	"github.com/docker/docker/pkg/stringid"
04b4e3e6
 	"github.com/docker/go-units"
acdbc285
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
069fdc8a
 	"golang.org/x/sys/unix"
27744062
 )
 
 var (
 	drv *Driver
 )
 
12460f41
 // Driver conforms to graphdriver.Driver interface and
 // contains information such as root and reference count of the number of clients using it.
 // This helps in testing drivers added into the framework.
27744062
 type Driver struct {
 	graphdriver.Driver
 	root     string
 	refCount int
 }
 
8b0441d4
 func newDriver(t testing.TB, name string, options []string) *Driver {
824c72f4
 	root, err := ioutil.TempDir("", "docker-graphtest-")
acdbc285
 	require.NoError(t, err)
27744062
 
acdbc285
 	require.NoError(t, os.MkdirAll(root, 0755))
677fa036
 	d, err := graphdriver.GetDriver(name, nil, graphdriver.Options{DriverOptions: options, Root: root})
27744062
 	if err != nil {
210ab030
 		t.Logf("graphdriver: %v\n", err)
c809fc55
 		if err == graphdriver.ErrNotSupported || err == graphdriver.ErrPrerequisites || err == graphdriver.ErrIncompatibleFS {
67054776
 			t.Skipf("Driver %s not supported", name)
55cd7dd7
 		}
27744062
 		t.Fatal(err)
 	}
 	return &Driver{d, root, 1}
 }
 
8b0441d4
 func cleanup(t testing.TB, d *Driver) {
27744062
 	if err := drv.Cleanup(); err != nil {
 		t.Fatal(err)
 	}
 	os.RemoveAll(d.root)
 }
 
c1be45fa
 // GetDriver create a new driver with given name or return an existing driver with the name updating the reference count.
8b0441d4
 func GetDriver(t testing.TB, name string, options ...string) graphdriver.Driver {
27744062
 	if drv == nil {
8b0441d4
 		drv = newDriver(t, name, options)
27744062
 	} else {
 		drv.refCount++
 	}
 	return drv
 }
 
12460f41
 // PutDriver removes the driver if it is no longer used and updates the reference count.
8b0441d4
 func PutDriver(t testing.TB) {
27744062
 	if drv == nil {
55cd7dd7
 		t.Skip("No driver to put!")
27744062
 	}
 	drv.refCount--
 	if drv.refCount == 0 {
 		cleanup(t, drv)
 		drv = nil
 	}
 }
 
8b0441d4
 // DriverTestCreateEmpty creates a new image and verifies it is empty and the right metadata
 func DriverTestCreateEmpty(t testing.TB, drivername string, driverOptions ...string) {
 	driver := GetDriver(t, drivername, driverOptions...)
 	defer PutDriver(t)
 
acdbc285
 	err := driver.Create("empty", "", nil)
 	require.NoError(t, err)
27744062
 
8b0441d4
 	defer func() {
acdbc285
 		require.NoError(t, driver.Remove("empty"))
8b0441d4
 	}()
27744062
 
8b0441d4
 	if !driver.Exists("empty") {
 		t.Fatal("Newly created image doesn't exist")
27744062
 	}
 
8b0441d4
 	dir, err := driver.Get("empty", "")
acdbc285
 	require.NoError(t, err)
27744062
 
8b0441d4
 	verifyFile(t, dir, 0755|os.ModeDir, 0, 0)
27744062
 
8b0441d4
 	// Verify that the directory is empty
 	fis, err := readDir(dir)
acdbc285
 	require.NoError(t, err)
 	assert.Len(t, fis, 0)
27744062
 
8b0441d4
 	driver.Put("empty")
27744062
 }
 
8b0441d4
 // DriverTestCreateBase create a base driver and verify.
 func DriverTestCreateBase(t testing.TB, drivername string, driverOptions ...string) {
 	driver := GetDriver(t, drivername, driverOptions...)
 	defer PutDriver(t)
158c5362
 
8b0441d4
 	createBase(t, driver, "Base")
 	defer func() {
acdbc285
 		require.NoError(t, driver.Remove("Base"))
8b0441d4
 	}()
 	verifyBase(t, driver, "Base")
158c5362
 }
 
8b0441d4
 // DriverTestCreateSnap Create a driver and snap and verify.
 func DriverTestCreateSnap(t testing.TB, drivername string, driverOptions ...string) {
 	driver := GetDriver(t, drivername, driverOptions...)
27744062
 	defer PutDriver(t)
 
8b0441d4
 	createBase(t, driver, "Base")
 	defer func() {
acdbc285
 		require.NoError(t, driver.Remove("Base"))
8b0441d4
 	}()
 
acdbc285
 	err := driver.Create("Snap", "Base", nil)
 	require.NoError(t, err)
b1806212
 	defer func() {
acdbc285
 		require.NoError(t, driver.Remove("Snap"))
b1806212
 	}()
 
8b0441d4
 	verifyBase(t, driver, "Snap")
 }
27744062
 
8b0441d4
 // DriverTestDeepLayerRead reads a file from a lower layer under a given number of layers
 func DriverTestDeepLayerRead(t testing.TB, layerCount int, drivername string, driverOptions ...string) {
 	driver := GetDriver(t, drivername, driverOptions...)
 	defer PutDriver(t)
 
 	base := stringid.GenerateRandomID()
b937aa8e
 	if err := driver.Create(base, "", nil); err != nil {
27744062
 		t.Fatal(err)
 	}
 
8b0441d4
 	content := []byte("test content")
 	if err := addFile(driver, base, "testfile.txt", content); err != nil {
 		t.Fatal(err)
 	}
27744062
 
8b0441d4
 	topLayer, err := addManyLayers(driver, base, layerCount)
27744062
 	if err != nil {
 		t.Fatal(err)
 	}
 
8b0441d4
 	err = checkManyLayers(driver, topLayer, layerCount)
 	if err != nil {
 		t.Fatal(err)
27744062
 	}
 
8b0441d4
 	if err := checkFile(driver, topLayer, "testfile.txt", content); err != nil {
 		t.Fatal(err)
 	}
27744062
 }
 
8b0441d4
 // DriverTestDiffApply tests diffing and applying produces the same layer
 func DriverTestDiffApply(t testing.TB, fileCount int, drivername string, driverOptions ...string) {
 	driver := GetDriver(t, drivername, driverOptions...)
 	defer PutDriver(t)
 	base := stringid.GenerateRandomID()
 	upper := stringid.GenerateRandomID()
bd13c53f
 	deleteFile := "file-remove.txt"
 	deleteFileContent := []byte("This file should get removed in upper!")
5c05b844
 	deleteDir := "var/lib"
27744062
 
b937aa8e
 	if err := driver.Create(base, "", nil); err != nil {
27744062
 		t.Fatal(err)
 	}
 
8b0441d4
 	if err := addManyFiles(driver, base, fileCount, 3); err != nil {
27744062
 		t.Fatal(err)
 	}
 
bd13c53f
 	if err := addFile(driver, base, deleteFile, deleteFileContent); err != nil {
 		t.Fatal(err)
 	}
 
5c05b844
 	if err := addDirectory(driver, base, deleteDir); err != nil {
 		t.Fatal(err)
 	}
 
b937aa8e
 	if err := driver.Create(upper, base, nil); err != nil {
27744062
 		t.Fatal(err)
 	}
8b0441d4
 
 	if err := addManyFiles(driver, upper, fileCount, 6); err != nil {
 		t.Fatal(err)
 	}
bd13c53f
 
5c05b844
 	if err := removeAll(driver, upper, deleteFile, deleteDir); err != nil {
bd13c53f
 		t.Fatal(err)
 	}
 
8b0441d4
 	diffSize, err := driver.DiffSize(upper, "")
 	if err != nil {
27744062
 		t.Fatal(err)
 	}
 
8b0441d4
 	diff := stringid.GenerateRandomID()
b937aa8e
 	if err := driver.Create(diff, base, nil); err != nil {
27744062
 		t.Fatal(err)
 	}
 
8b0441d4
 	if err := checkManyFiles(driver, diff, fileCount, 3); err != nil {
27744062
 		t.Fatal(err)
 	}
 
bd13c53f
 	if err := checkFile(driver, diff, deleteFile, deleteFileContent); err != nil {
 		t.Fatal(err)
 	}
 
8b0441d4
 	arch, err := driver.Diff(upper, base)
 	if err != nil {
 		t.Fatal(err)
 	}
27744062
 
8b0441d4
 	buf := bytes.NewBuffer(nil)
 	if _, err := buf.ReadFrom(arch); err != nil {
 		t.Fatal(err)
 	}
 	if err := arch.Close(); err != nil {
 		t.Fatal(err)
 	}
27744062
 
8b0441d4
 	applyDiffSize, err := driver.ApplyDiff(diff, base, bytes.NewReader(buf.Bytes()))
27744062
 	if err != nil {
 		t.Fatal(err)
 	}
 
8b0441d4
 	if applyDiffSize != diffSize {
 		t.Fatalf("Apply diff size different, got %d, expected %d", applyDiffSize, diffSize)
 	}
bd13c53f
 
8b0441d4
 	if err := checkManyFiles(driver, diff, fileCount, 6); err != nil {
 		t.Fatal(err)
27744062
 	}
bd13c53f
 
 	if err := checkFileRemoved(driver, diff, deleteFile); err != nil {
 		t.Fatal(err)
 	}
5c05b844
 
 	if err := checkFileRemoved(driver, diff, deleteDir); err != nil {
 		t.Fatal(err)
 	}
27744062
 }
 
8b0441d4
 // DriverTestChanges tests computed changes on a layer matches changes made
 func DriverTestChanges(t testing.TB, drivername string, driverOptions ...string) {
 	driver := GetDriver(t, drivername, driverOptions...)
27744062
 	defer PutDriver(t)
8b0441d4
 	base := stringid.GenerateRandomID()
 	upper := stringid.GenerateRandomID()
b937aa8e
 	if err := driver.Create(base, "", nil); err != nil {
8b0441d4
 		t.Fatal(err)
 	}
27744062
 
8b0441d4
 	if err := addManyFiles(driver, base, 20, 3); err != nil {
 		t.Fatal(err)
 	}
27744062
 
b937aa8e
 	if err := driver.Create(upper, base, nil); err != nil {
8b0441d4
 		t.Fatal(err)
 	}
27744062
 
8b0441d4
 	expectedChanges, err := changeManyFiles(driver, upper, 20, 6)
 	if err != nil {
 		t.Fatal(err)
 	}
b1806212
 
8b0441d4
 	changes, err := driver.Changes(upper, base)
 	if err != nil {
27744062
 		t.Fatal(err)
 	}
 
8b0441d4
 	if err = checkChanges(expectedChanges, changes); err != nil {
 		t.Fatal(err)
 	}
27744062
 }
04b4e3e6
 
 func writeRandomFile(path string, size uint64) error {
 	buf := make([]int64, size/8)
 
 	r := rand.NewSource(0)
 	for i := range buf {
 		buf[i] = r.Int63()
 	}
 
 	// Cast to []byte
 	header := *(*reflect.SliceHeader)(unsafe.Pointer(&buf))
 	header.Len *= 8
 	header.Cap *= 8
 	data := *(*[]byte)(unsafe.Pointer(&header))
 
 	return ioutil.WriteFile(path, data, 0700)
 }
 
 // DriverTestSetQuota Create a driver and test setting quota.
 func DriverTestSetQuota(t *testing.T, drivername string) {
 	driver := GetDriver(t, drivername)
 	defer PutDriver(t)
 
 	createBase(t, driver, "Base")
b937aa8e
 	createOpts := &graphdriver.CreateOpts{}
 	createOpts.StorageOpt = make(map[string]string, 1)
 	createOpts.StorageOpt["size"] = "50M"
 	if err := driver.Create("zfsTest", "Base", createOpts); err != nil {
04b4e3e6
 		t.Fatal(err)
 	}
 
 	mountPath, err := driver.Get("zfsTest", "")
 	if err != nil {
 		t.Fatal(err)
 	}
 
 	quota := uint64(50 * units.MiB)
 	err = writeRandomFile(path.Join(mountPath, "file"), quota*2)
069fdc8a
 	if pathError, ok := err.(*os.PathError); ok && pathError.Err != unix.EDQUOT {
 		t.Fatalf("expect write() to fail with %v, got %v", unix.EDQUOT, err)
04b4e3e6
 	}
 
 }