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 |
}
} |