2016-06-07 03:45:21 -04:00
|
|
|
// +build linux freebsd solaris
|
2015-10-31 14:49:03 -04:00
|
|
|
|
2014-04-30 08:43:51 -04:00
|
|
|
package graphtest
|
|
|
|
|
|
|
|
import (
|
2016-04-14 21:14:42 -04:00
|
|
|
"bytes"
|
2014-04-30 08:43:51 -04:00
|
|
|
"io/ioutil"
|
2016-05-19 14:47:33 -04:00
|
|
|
"math/rand"
|
2014-04-30 08:43:51 -04:00
|
|
|
"os"
|
|
|
|
"path"
|
2016-05-19 14:47:33 -04:00
|
|
|
"reflect"
|
2014-04-30 08:43:51 -04:00
|
|
|
"syscall"
|
|
|
|
"testing"
|
2016-05-19 14:47:33 -04:00
|
|
|
"unsafe"
|
2014-06-12 01:15:53 -04:00
|
|
|
|
2014-07-24 18:19:50 -04:00
|
|
|
"github.com/docker/docker/daemon/graphdriver"
|
2016-04-14 21:14:42 -04:00
|
|
|
"github.com/docker/docker/pkg/stringid"
|
2016-05-19 14:47:33 -04:00
|
|
|
"github.com/docker/go-units"
|
2014-04-30 08:43:51 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
drv *Driver
|
|
|
|
)
|
|
|
|
|
2015-07-23 20:23:33 -04:00
|
|
|
// 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.
|
2014-04-30 08:43:51 -04:00
|
|
|
type Driver struct {
|
|
|
|
graphdriver.Driver
|
|
|
|
root string
|
|
|
|
refCount int
|
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
func newDriver(t testing.TB, name string, options []string) *Driver {
|
2016-04-07 00:06:42 -04:00
|
|
|
root, err := ioutil.TempDir("", "docker-graphtest-")
|
2014-04-30 08:43:51 -04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := os.MkdirAll(root, 0755); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-11-19 11:41:07 -05:00
|
|
|
d, err := graphdriver.GetDriver(name, nil, graphdriver.Options{DriverOptions: options, Root: root})
|
2014-04-30 08:43:51 -04:00
|
|
|
if err != nil {
|
2015-03-16 04:35:15 -04:00
|
|
|
t.Logf("graphdriver: %v\n", err)
|
2015-02-04 16:51:44 -05:00
|
|
|
if err == graphdriver.ErrNotSupported || err == graphdriver.ErrPrerequisites || err == graphdriver.ErrIncompatibleFS {
|
2014-11-19 16:24:16 -05:00
|
|
|
t.Skipf("Driver %s not supported", name)
|
2014-05-06 08:44:42 -04:00
|
|
|
}
|
2014-04-30 08:43:51 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
return &Driver{d, root, 1}
|
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
func cleanup(t testing.TB, d *Driver) {
|
2014-04-30 08:43:51 -04:00
|
|
|
if err := drv.Cleanup(); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
os.RemoveAll(d.root)
|
|
|
|
}
|
|
|
|
|
2016-05-07 21:36:10 -04:00
|
|
|
// GetDriver create a new driver with given name or return an existing driver with the name updating the reference count.
|
2016-04-14 21:14:42 -04:00
|
|
|
func GetDriver(t testing.TB, name string, options ...string) graphdriver.Driver {
|
2014-04-30 08:43:51 -04:00
|
|
|
if drv == nil {
|
2016-04-14 21:14:42 -04:00
|
|
|
drv = newDriver(t, name, options)
|
2014-04-30 08:43:51 -04:00
|
|
|
} else {
|
|
|
|
drv.refCount++
|
|
|
|
}
|
|
|
|
return drv
|
|
|
|
}
|
|
|
|
|
2015-07-23 20:23:33 -04:00
|
|
|
// PutDriver removes the driver if it is no longer used and updates the reference count.
|
2016-04-14 21:14:42 -04:00
|
|
|
func PutDriver(t testing.TB) {
|
2014-04-30 08:43:51 -04:00
|
|
|
if drv == nil {
|
2014-05-06 08:44:42 -04:00
|
|
|
t.Skip("No driver to put!")
|
2014-04-30 08:43:51 -04:00
|
|
|
}
|
|
|
|
drv.refCount--
|
|
|
|
if drv.refCount == 0 {
|
|
|
|
cleanup(t, drv)
|
|
|
|
drv = nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
// 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)
|
|
|
|
|
2016-11-09 15:59:58 -05:00
|
|
|
if err := driver.Create("empty", "", nil); err != nil {
|
2014-04-30 08:43:51 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
defer func() {
|
|
|
|
if err := driver.Remove("empty"); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}()
|
2014-04-30 08:43:51 -04:00
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
if !driver.Exists("empty") {
|
|
|
|
t.Fatal("Newly created image doesn't exist")
|
2014-04-30 08:43:51 -04:00
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
dir, err := driver.Get("empty", "")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
2014-04-30 08:43:51 -04:00
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
verifyFile(t, dir, 0755|os.ModeDir, 0, 0)
|
2014-04-30 08:43:51 -04:00
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
// Verify that the directory is empty
|
|
|
|
fis, err := readDir(dir)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
2014-04-30 08:43:51 -04:00
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
if len(fis) != 0 {
|
|
|
|
t.Fatal("New directory not empty")
|
2014-04-30 08:43:51 -04:00
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
driver.Put("empty")
|
2014-04-30 08:43:51 -04:00
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
// DriverTestCreateBase create a base driver and verify.
|
|
|
|
func DriverTestCreateBase(t testing.TB, drivername string, driverOptions ...string) {
|
|
|
|
driver := GetDriver(t, drivername, driverOptions...)
|
|
|
|
defer PutDriver(t)
|
2015-08-07 21:37:21 -04:00
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
createBase(t, driver, "Base")
|
|
|
|
defer func() {
|
|
|
|
if err := driver.Remove("Base"); err != nil {
|
|
|
|
t.Fatal(err)
|
2015-08-07 21:37:21 -04:00
|
|
|
}
|
2016-04-14 21:14:42 -04:00
|
|
|
}()
|
|
|
|
verifyBase(t, driver, "Base")
|
2015-08-07 21:37:21 -04:00
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
// DriverTestCreateSnap Create a driver and snap and verify.
|
|
|
|
func DriverTestCreateSnap(t testing.TB, drivername string, driverOptions ...string) {
|
|
|
|
driver := GetDriver(t, drivername, driverOptions...)
|
2014-04-30 08:43:51 -04:00
|
|
|
defer PutDriver(t)
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
createBase(t, driver, "Base")
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
if err := driver.Remove("Base"); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2016-11-09 15:59:58 -05:00
|
|
|
if err := driver.Create("Snap", "Base", nil); err != nil {
|
2014-04-30 08:43:51 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-05-29 05:51:06 -04:00
|
|
|
defer func() {
|
2016-04-14 21:14:42 -04:00
|
|
|
if err := driver.Remove("Snap"); err != nil {
|
2016-05-29 05:51:06 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
verifyBase(t, driver, "Snap")
|
|
|
|
}
|
2014-04-30 08:43:51 -04:00
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
// 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()
|
2016-11-09 15:59:58 -05:00
|
|
|
if err := driver.Create(base, "", nil); err != nil {
|
2014-04-30 08:43:51 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
content := []byte("test content")
|
|
|
|
if err := addFile(driver, base, "testfile.txt", content); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2014-04-30 08:43:51 -04:00
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
topLayer, err := addManyLayers(driver, base, layerCount)
|
2014-04-30 08:43:51 -04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
err = checkManyLayers(driver, topLayer, layerCount)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
2014-04-30 08:43:51 -04:00
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
if err := checkFile(driver, topLayer, "testfile.txt", content); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2014-04-30 08:43:51 -04:00
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
// 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()
|
2016-06-23 16:34:38 -04:00
|
|
|
deleteFile := "file-remove.txt"
|
|
|
|
deleteFileContent := []byte("This file should get removed in upper!")
|
2016-07-26 14:56:38 -04:00
|
|
|
deleteDir := "var/lib"
|
2014-04-30 08:43:51 -04:00
|
|
|
|
2016-11-09 15:59:58 -05:00
|
|
|
if err := driver.Create(base, "", nil); err != nil {
|
2014-04-30 08:43:51 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
if err := addManyFiles(driver, base, fileCount, 3); err != nil {
|
2014-04-30 08:43:51 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-06-23 16:34:38 -04:00
|
|
|
if err := addFile(driver, base, deleteFile, deleteFileContent); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-07-26 14:56:38 -04:00
|
|
|
if err := addDirectory(driver, base, deleteDir); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-11-09 15:59:58 -05:00
|
|
|
if err := driver.Create(upper, base, nil); err != nil {
|
2014-04-30 08:43:51 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-04-14 21:14:42 -04:00
|
|
|
|
|
|
|
if err := addManyFiles(driver, upper, fileCount, 6); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-06-23 16:34:38 -04:00
|
|
|
|
2016-07-26 14:56:38 -04:00
|
|
|
if err := removeAll(driver, upper, deleteFile, deleteDir); err != nil {
|
2016-06-23 16:34:38 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
diffSize, err := driver.DiffSize(upper, "")
|
|
|
|
if err != nil {
|
2014-04-30 08:43:51 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
diff := stringid.GenerateRandomID()
|
2016-11-09 15:59:58 -05:00
|
|
|
if err := driver.Create(diff, base, nil); err != nil {
|
2014-04-30 08:43:51 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
if err := checkManyFiles(driver, diff, fileCount, 3); err != nil {
|
2014-04-30 08:43:51 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-06-23 16:34:38 -04:00
|
|
|
if err := checkFile(driver, diff, deleteFile, deleteFileContent); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
arch, err := driver.Diff(upper, base)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2014-04-30 08:43:51 -04:00
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
buf := bytes.NewBuffer(nil)
|
|
|
|
if _, err := buf.ReadFrom(arch); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if err := arch.Close(); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2014-04-30 08:43:51 -04:00
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
applyDiffSize, err := driver.ApplyDiff(diff, base, bytes.NewReader(buf.Bytes()))
|
2014-04-30 08:43:51 -04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
if applyDiffSize != diffSize {
|
|
|
|
t.Fatalf("Apply diff size different, got %d, expected %d", applyDiffSize, diffSize)
|
|
|
|
}
|
2016-06-23 16:34:38 -04:00
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
if err := checkManyFiles(driver, diff, fileCount, 6); err != nil {
|
|
|
|
t.Fatal(err)
|
2014-04-30 08:43:51 -04:00
|
|
|
}
|
2016-06-23 16:34:38 -04:00
|
|
|
|
|
|
|
if err := checkFileRemoved(driver, diff, deleteFile); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-07-26 14:56:38 -04:00
|
|
|
|
|
|
|
if err := checkFileRemoved(driver, diff, deleteDir); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2014-04-30 08:43:51 -04:00
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
// DriverTestChanges tests computed changes on a layer matches changes made
|
|
|
|
func DriverTestChanges(t testing.TB, drivername string, driverOptions ...string) {
|
|
|
|
driver := GetDriver(t, drivername, driverOptions...)
|
2014-04-30 08:43:51 -04:00
|
|
|
defer PutDriver(t)
|
2016-04-14 21:14:42 -04:00
|
|
|
base := stringid.GenerateRandomID()
|
|
|
|
upper := stringid.GenerateRandomID()
|
2016-11-09 15:59:58 -05:00
|
|
|
if err := driver.Create(base, "", nil); err != nil {
|
2016-04-14 21:14:42 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2014-04-30 08:43:51 -04:00
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
if err := addManyFiles(driver, base, 20, 3); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2014-04-30 08:43:51 -04:00
|
|
|
|
2016-11-09 15:59:58 -05:00
|
|
|
if err := driver.Create(upper, base, nil); err != nil {
|
2016-04-14 21:14:42 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2014-04-30 08:43:51 -04:00
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
expectedChanges, err := changeManyFiles(driver, upper, 20, 6)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-05-29 05:51:06 -04:00
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
changes, err := driver.Changes(upper, base)
|
|
|
|
if err != nil {
|
2014-04-30 08:43:51 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-04-14 21:14:42 -04:00
|
|
|
if err = checkChanges(expectedChanges, changes); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2014-04-30 08:43:51 -04:00
|
|
|
}
|
2016-05-19 14:47:33 -04:00
|
|
|
|
|
|
|
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")
|
2016-11-09 15:59:58 -05:00
|
|
|
createOpts := &graphdriver.CreateOpts{}
|
|
|
|
createOpts.StorageOpt = make(map[string]string, 1)
|
|
|
|
createOpts.StorageOpt["size"] = "50M"
|
|
|
|
if err := driver.Create("zfsTest", "Base", createOpts); err != nil {
|
2016-05-19 14:47:33 -04:00
|
|
|
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)
|
|
|
|
if pathError, ok := err.(*os.PathError); ok && pathError.Err != syscall.EDQUOT {
|
|
|
|
t.Fatalf("expect write() to fail with %v, got %v", syscall.EDQUOT, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|