|
@@ -1,9 +1,13 @@
|
|
|
package devmapper
|
|
|
|
|
|
import (
|
|
|
+ "fmt"
|
|
|
+ "github.com/dotcloud/docker/graphdriver"
|
|
|
"io/ioutil"
|
|
|
- "os"
|
|
|
"path"
|
|
|
+ "runtime"
|
|
|
+ "strings"
|
|
|
+ "syscall"
|
|
|
"testing"
|
|
|
)
|
|
|
|
|
@@ -12,7 +16,105 @@ func init() {
|
|
|
DefaultDataLoopbackSize = 300 * 1024 * 1024
|
|
|
DefaultMetaDataLoopbackSize = 200 * 1024 * 1024
|
|
|
DefaultBaseFsSize = 300 * 1024 * 1024
|
|
|
+}
|
|
|
+
|
|
|
+// denyAllDevmapper mocks all calls to libdevmapper in the unit tests, and denies them by default
|
|
|
+func denyAllDevmapper() {
|
|
|
+ // Hijack all calls to libdevmapper with default panics.
|
|
|
+ // Authorized calls are selectively hijacked in each tests.
|
|
|
+ DmTaskCreate = func(t int) *CDmTask {
|
|
|
+ panic("DmTaskCreate: this method should not be called here")
|
|
|
+ }
|
|
|
+ DmTaskRun = func(task *CDmTask) int {
|
|
|
+ panic("DmTaskRun: this method should not be called here")
|
|
|
+ }
|
|
|
+ DmTaskSetName = func(task *CDmTask, name string) int {
|
|
|
+ panic("DmTaskSetName: this method should not be called here")
|
|
|
+ }
|
|
|
+ DmTaskSetMessage = func(task *CDmTask, message string) int {
|
|
|
+ panic("DmTaskSetMessage: this method should not be called here")
|
|
|
+ }
|
|
|
+ DmTaskSetSector = func(task *CDmTask, sector uint64) int {
|
|
|
+ panic("DmTaskSetSector: this method should not be called here")
|
|
|
+ }
|
|
|
+ DmTaskSetCookie = func(task *CDmTask, cookie *uint, flags uint16) int {
|
|
|
+ panic("DmTaskSetCookie: this method should not be called here")
|
|
|
+ }
|
|
|
+ DmTaskSetAddNode = func(task *CDmTask, addNode AddNodeType) int {
|
|
|
+ panic("DmTaskSetAddNode: this method should not be called here")
|
|
|
+ }
|
|
|
+ DmTaskSetRo = func(task *CDmTask) int {
|
|
|
+ panic("DmTaskSetRo: this method should not be called here")
|
|
|
+ }
|
|
|
+ DmTaskAddTarget = func(task *CDmTask, start, size uint64, ttype, params string) int {
|
|
|
+ panic("DmTaskAddTarget: this method should not be called here")
|
|
|
+ }
|
|
|
+ DmTaskGetInfo = func(task *CDmTask, info *Info) int {
|
|
|
+ panic("DmTaskGetInfo: this method should not be called here")
|
|
|
+ }
|
|
|
+ DmGetNextTarget = func(task *CDmTask, next uintptr, start, length *uint64, target, params *string) uintptr {
|
|
|
+ panic("DmGetNextTarget: this method should not be called here")
|
|
|
+ }
|
|
|
+ DmAttachLoopDevice = func(filename string, fd *int) string {
|
|
|
+ panic("DmAttachLoopDevice: this method should not be called here")
|
|
|
+ }
|
|
|
+ DmGetBlockSize = func(fd uintptr) (int64, sysErrno) {
|
|
|
+ panic("DmGetBlockSize: this method should not be called here")
|
|
|
+ }
|
|
|
+ DmUdevWait = func(cookie uint) int {
|
|
|
+ panic("DmUdevWait: this method should not be called here")
|
|
|
+ }
|
|
|
+ DmSetDevDir = func(dir string) int {
|
|
|
+ panic("DmSetDevDir: this method should not be called here")
|
|
|
+ }
|
|
|
+ DmGetLibraryVersion = func(version *string) int {
|
|
|
+ panic("DmGetLibraryVersion: this method should not be called here")
|
|
|
+ }
|
|
|
+ DmLogInitVerbose = func(level int) {
|
|
|
+ panic("DmLogInitVerbose: this method should not be called here")
|
|
|
+ }
|
|
|
+ DmTaskDestroy = func(task *CDmTask) {
|
|
|
+ panic("DmTaskDestroy: this method should not be called here")
|
|
|
+ }
|
|
|
+ GetBlockSize = func(fd uintptr, size *uint64) sysErrno {
|
|
|
+ panic("GetBlockSize: this method should not be called here")
|
|
|
+ }
|
|
|
+ LogWithErrnoInit = func() {
|
|
|
+ panic("LogWithErrnoInit: this method should not be called here")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func denyAllSyscall() {
|
|
|
+ sysMount = func(source, target, fstype string, flags uintptr, data string) (err error) {
|
|
|
+ panic("sysMount: this method should not be called here")
|
|
|
+ }
|
|
|
+ sysUnmount = func(target string, flags int) (err error) {
|
|
|
+ panic("sysUnmount: this method should not be called here")
|
|
|
+ }
|
|
|
+ sysCloseOnExec = func(fd int) {
|
|
|
+ panic("sysCloseOnExec: this method should not be called here")
|
|
|
+ }
|
|
|
+ sysSyscall = func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
|
|
|
+ panic("sysSyscall: this method should not be called here")
|
|
|
+ }
|
|
|
+ // Not a syscall, but forbidding it here anyway
|
|
|
+ Mounted = func(mnt string) (bool, error) {
|
|
|
+ panic("devmapper.Mounted: this method should not be called here")
|
|
|
+ }
|
|
|
+ // osOpenFile = os.OpenFile
|
|
|
+ // osNewFile = os.NewFile
|
|
|
+ // osCreate = os.Create
|
|
|
+ // osStat = os.Stat
|
|
|
+ // osIsNotExist = os.IsNotExist
|
|
|
+ // osIsExist = os.IsExist
|
|
|
+ // osMkdirAll = os.MkdirAll
|
|
|
+ // osRemoveAll = os.RemoveAll
|
|
|
+ // osRename = os.Rename
|
|
|
+ // osReadlink = os.Readlink
|
|
|
|
|
|
+ // execRun = func(name string, args ...string) error {
|
|
|
+ // return exec.Command(name, args...).Run()
|
|
|
+ // }
|
|
|
}
|
|
|
|
|
|
func mkTestDirectory(t *testing.T) string {
|
|
@@ -34,72 +136,521 @@ func newDriver(t *testing.T) *Driver {
|
|
|
|
|
|
func cleanup(d *Driver) {
|
|
|
d.Cleanup()
|
|
|
- os.RemoveAll(d.home)
|
|
|
+ osRemoveAll(d.home)
|
|
|
}
|
|
|
|
|
|
-func TestInit(t *testing.T) {
|
|
|
- home := mkTestDirectory(t)
|
|
|
- defer os.RemoveAll(home)
|
|
|
- driver, err := Init(home)
|
|
|
- if err != nil {
|
|
|
- t.Fatal(err)
|
|
|
+type Set map[string]bool
|
|
|
+
|
|
|
+func (r Set) Assert(t *testing.T, names ...string) {
|
|
|
+ for _, key := range names {
|
|
|
+ if _, exists := r[key]; !exists {
|
|
|
+ t.Fatalf("Key not set: %s", key)
|
|
|
+ }
|
|
|
+ delete(r, key)
|
|
|
}
|
|
|
- defer func() {
|
|
|
- if err := driver.Cleanup(); err != nil {
|
|
|
+ if len(r) != 0 {
|
|
|
+ t.Fatalf("Unexpected keys: %v", r)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestInit(t *testing.T) {
|
|
|
+ var (
|
|
|
+ calls = make(Set)
|
|
|
+ devicesAttached = make(Set)
|
|
|
+ taskMessages = make(Set)
|
|
|
+ taskTypes = make(Set)
|
|
|
+ home = mkTestDirectory(t)
|
|
|
+ )
|
|
|
+ defer osRemoveAll(home)
|
|
|
+
|
|
|
+ func() {
|
|
|
+ denyAllDevmapper()
|
|
|
+ DmSetDevDir = func(dir string) int {
|
|
|
+ calls["DmSetDevDir"] = true
|
|
|
+ expectedDir := "/dev"
|
|
|
+ if dir != expectedDir {
|
|
|
+ t.Fatalf("Wrong libdevmapper call\nExpected: DmSetDevDir(%v)\nReceived: DmSetDevDir(%v)\n", expectedDir, dir)
|
|
|
+ }
|
|
|
+ return 0
|
|
|
+ }
|
|
|
+ LogWithErrnoInit = func() {
|
|
|
+ calls["DmLogWithErrnoInit"] = true
|
|
|
+ }
|
|
|
+ var task1 CDmTask
|
|
|
+ DmTaskCreate = func(taskType int) *CDmTask {
|
|
|
+ calls["DmTaskCreate"] = true
|
|
|
+ taskTypes[fmt.Sprintf("%d", taskType)] = true
|
|
|
+ return &task1
|
|
|
+ }
|
|
|
+ DmTaskSetName = func(task *CDmTask, name string) int {
|
|
|
+ calls["DmTaskSetName"] = true
|
|
|
+ expectedTask := &task1
|
|
|
+ if task != expectedTask {
|
|
|
+ t.Fatalf("Wrong libdevmapper call\nExpected: DmTaskSetName(%v)\nReceived: DmTaskSetName(%v)\n", expectedTask, task)
|
|
|
+ }
|
|
|
+ // FIXME: use Set.AssertRegexp()
|
|
|
+ if !strings.HasPrefix(name, "docker-") && !strings.HasPrefix(name, "/dev/mapper/docker-") ||
|
|
|
+ !strings.HasSuffix(name, "-pool") && !strings.HasSuffix(name, "-base") {
|
|
|
+ t.Fatalf("Wrong libdevmapper call\nExpected: DmTaskSetName(%v)\nReceived: DmTaskSetName(%v)\n", "docker-...-pool", name)
|
|
|
+ }
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ DmTaskRun = func(task *CDmTask) int {
|
|
|
+ calls["DmTaskRun"] = true
|
|
|
+ expectedTask := &task1
|
|
|
+ if task != expectedTask {
|
|
|
+ t.Fatalf("Wrong libdevmapper call\nExpected: DmTaskRun(%v)\nReceived: DmTaskRun(%v)\n", expectedTask, task)
|
|
|
+ }
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ DmTaskGetInfo = func(task *CDmTask, info *Info) int {
|
|
|
+ calls["DmTaskGetInfo"] = true
|
|
|
+ expectedTask := &task1
|
|
|
+ if task != expectedTask {
|
|
|
+ t.Fatalf("Wrong libdevmapper call\nExpected: DmTaskGetInfo(%v)\nReceived: DmTaskGetInfo(%v)\n", expectedTask, task)
|
|
|
+ }
|
|
|
+ // This will crash if info is not dereferenceable
|
|
|
+ info.Exists = 0
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ DmTaskSetSector = func(task *CDmTask, sector uint64) int {
|
|
|
+ calls["DmTaskSetSector"] = true
|
|
|
+ expectedTask := &task1
|
|
|
+ if task != expectedTask {
|
|
|
+ t.Fatalf("Wrong libdevmapper call\nExpected: DmTaskSetSector(%v)\nReceived: DmTaskSetSector(%v)\n", expectedTask, task)
|
|
|
+ }
|
|
|
+ if expectedSector := uint64(0); sector != expectedSector {
|
|
|
+ t.Fatalf("Wrong libdevmapper call to DmTaskSetSector\nExpected: %v\nReceived: %v\n", expectedSector, sector)
|
|
|
+ }
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ DmTaskSetMessage = func(task *CDmTask, message string) int {
|
|
|
+ calls["DmTaskSetMessage"] = true
|
|
|
+ expectedTask := &task1
|
|
|
+ if task != expectedTask {
|
|
|
+ t.Fatalf("Wrong libdevmapper call\nExpected: DmTaskSetSector(%v)\nReceived: DmTaskSetSector(%v)\n", expectedTask, task)
|
|
|
+ }
|
|
|
+ taskMessages[message] = true
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ var (
|
|
|
+ fakeDataLoop = "/dev/loop42"
|
|
|
+ fakeMetadataLoop = "/dev/loop43"
|
|
|
+ fakeDataLoopFd = 42
|
|
|
+ fakeMetadataLoopFd = 43
|
|
|
+ )
|
|
|
+ var attachCount int
|
|
|
+ DmAttachLoopDevice = func(filename string, fd *int) string {
|
|
|
+ calls["DmAttachLoopDevice"] = true
|
|
|
+ if _, exists := devicesAttached[filename]; exists {
|
|
|
+ t.Fatalf("Already attached %s", filename)
|
|
|
+ }
|
|
|
+ devicesAttached[filename] = true
|
|
|
+ // This will crash if fd is not dereferenceable
|
|
|
+ if attachCount == 0 {
|
|
|
+ attachCount++
|
|
|
+ *fd = fakeDataLoopFd
|
|
|
+ return fakeDataLoop
|
|
|
+ } else {
|
|
|
+ *fd = fakeMetadataLoopFd
|
|
|
+ return fakeMetadataLoop
|
|
|
+ }
|
|
|
+ }
|
|
|
+ DmTaskDestroy = func(task *CDmTask) {
|
|
|
+ calls["DmTaskDestroy"] = true
|
|
|
+ expectedTask := &task1
|
|
|
+ if task != expectedTask {
|
|
|
+ t.Fatalf("Wrong libdevmapper call\nExpected: DmTaskDestroy(%v)\nReceived: DmTaskDestroy(%v)\n", expectedTask, task)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ fakeBlockSize := int64(4242 * 512)
|
|
|
+ DmGetBlockSize = func(fd uintptr) (int64, sysErrno) {
|
|
|
+ calls["DmGetBlockSize"] = true
|
|
|
+ if expectedFd := uintptr(42); fd != expectedFd {
|
|
|
+ t.Fatalf("Wrong libdevmapper call\nExpected: DmGetBlockSize(%v)\nReceived: DmGetBlockSize(%v)\n", expectedFd, fd)
|
|
|
+ }
|
|
|
+ return fakeBlockSize, 0
|
|
|
+ }
|
|
|
+ DmTaskAddTarget = func(task *CDmTask, start, size uint64, ttype, params string) int {
|
|
|
+ calls["DmTaskSetTarget"] = true
|
|
|
+ expectedTask := &task1
|
|
|
+ if task != expectedTask {
|
|
|
+ t.Fatalf("Wrong libdevmapper call\nExpected: DmTaskDestroy(%v)\nReceived: DmTaskDestroy(%v)\n", expectedTask, task)
|
|
|
+ }
|
|
|
+ if start != 0 {
|
|
|
+ t.Fatalf("Wrong start: %d != %d", start, 0)
|
|
|
+ }
|
|
|
+ if ttype != "thin" && ttype != "thin-pool" {
|
|
|
+ t.Fatalf("Wrong ttype: %s", ttype)
|
|
|
+ }
|
|
|
+ // Quick smoke test
|
|
|
+ if params == "" {
|
|
|
+ t.Fatalf("Params should not be empty")
|
|
|
+ }
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ fakeCookie := uint(4321)
|
|
|
+ DmTaskSetCookie = func(task *CDmTask, cookie *uint, flags uint16) int {
|
|
|
+ calls["DmTaskSetCookie"] = true
|
|
|
+ expectedTask := &task1
|
|
|
+ if task != expectedTask {
|
|
|
+ t.Fatalf("Wrong libdevmapper call\nExpected: DmTaskDestroy(%v)\nReceived: DmTaskDestroy(%v)\n", expectedTask, task)
|
|
|
+ }
|
|
|
+ if flags != 0 {
|
|
|
+ t.Fatalf("Cookie flags should be 0 (not %x)", flags)
|
|
|
+ }
|
|
|
+ *cookie = fakeCookie
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ DmUdevWait = func(cookie uint) int {
|
|
|
+ calls["DmUdevWait"] = true
|
|
|
+ if cookie != fakeCookie {
|
|
|
+ t.Fatalf("Wrong cookie: %d != %d", cookie, fakeCookie)
|
|
|
+ }
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ DmTaskSetAddNode = func(task *CDmTask, addNode AddNodeType) int {
|
|
|
+ if addNode != AddNodeOnCreate {
|
|
|
+ t.Fatalf("Wrong AddNoteType: %v (expected %v)", addNode, AddNodeOnCreate)
|
|
|
+ }
|
|
|
+ calls["DmTaskSetAddNode"] = true
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ execRun = func(name string, args ...string) error {
|
|
|
+ calls["execRun"] = true
|
|
|
+ if name != "mkfs.ext4" {
|
|
|
+ t.Fatalf("Expected %s to be executed, not %s", "mkfs.ext4", name)
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ driver, err := Init(home)
|
|
|
+ if err != nil {
|
|
|
t.Fatal(err)
|
|
|
}
|
|
|
+ defer func() {
|
|
|
+ if err := driver.Cleanup(); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ }()
|
|
|
}()
|
|
|
+ // Put all tests in a funciton to make sure the garbage collection will
|
|
|
+ // occur.
|
|
|
+
|
|
|
+ // Call GC to cleanup runtime.Finalizers
|
|
|
+ runtime.GC()
|
|
|
+
|
|
|
+ calls.Assert(t,
|
|
|
+ "DmSetDevDir",
|
|
|
+ "DmLogWithErrnoInit",
|
|
|
+ "DmTaskSetName",
|
|
|
+ "DmTaskRun",
|
|
|
+ "DmTaskGetInfo",
|
|
|
+ "DmAttachLoopDevice",
|
|
|
+ "DmTaskDestroy",
|
|
|
+ "execRun",
|
|
|
+ "DmTaskCreate",
|
|
|
+ "DmGetBlockSize",
|
|
|
+ "DmTaskSetTarget",
|
|
|
+ "DmTaskSetCookie",
|
|
|
+ "DmUdevWait",
|
|
|
+ "DmTaskSetSector",
|
|
|
+ "DmTaskSetMessage",
|
|
|
+ "DmTaskSetAddNode",
|
|
|
+ )
|
|
|
+ devicesAttached.Assert(t, path.Join(home, "devicemapper", "data"), path.Join(home, "devicemapper", "metadata"))
|
|
|
+ taskTypes.Assert(t, "0", "6", "17")
|
|
|
+ taskMessages.Assert(t, "create_thin 0", "set_transaction_id 0 1")
|
|
|
+}
|
|
|
|
|
|
- id := "foo"
|
|
|
- if err := driver.Create(id, ""); err != nil {
|
|
|
- t.Fatal(err)
|
|
|
+func fakeInit() func(home string) (graphdriver.Driver, error) {
|
|
|
+ oldInit := Init
|
|
|
+ Init = func(home string) (graphdriver.Driver, error) {
|
|
|
+ return &Driver{
|
|
|
+ home: home,
|
|
|
+ }, nil
|
|
|
}
|
|
|
- dir, err := driver.Get(id)
|
|
|
- if err != nil {
|
|
|
- t.Fatal(err)
|
|
|
+ return oldInit
|
|
|
+}
|
|
|
+
|
|
|
+func restoreInit(init func(home string) (graphdriver.Driver, error)) {
|
|
|
+ Init = init
|
|
|
+}
|
|
|
+
|
|
|
+func mockAllDevmapper(calls Set) {
|
|
|
+ DmSetDevDir = func(dir string) int {
|
|
|
+ calls["DmSetDevDir"] = true
|
|
|
+ return 0
|
|
|
}
|
|
|
- if st, err := os.Stat(dir); err != nil {
|
|
|
- t.Fatal(err)
|
|
|
- } else if !st.IsDir() {
|
|
|
- t.Fatalf("Get(%V) did not return a directory", id)
|
|
|
+ LogWithErrnoInit = func() {
|
|
|
+ calls["DmLogWithErrnoInit"] = true
|
|
|
+ }
|
|
|
+ DmTaskCreate = func(taskType int) *CDmTask {
|
|
|
+ calls["DmTaskCreate"] = true
|
|
|
+ return &CDmTask{}
|
|
|
+ }
|
|
|
+ DmTaskSetName = func(task *CDmTask, name string) int {
|
|
|
+ calls["DmTaskSetName"] = true
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ DmTaskRun = func(task *CDmTask) int {
|
|
|
+ calls["DmTaskRun"] = true
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ DmTaskGetInfo = func(task *CDmTask, info *Info) int {
|
|
|
+ calls["DmTaskGetInfo"] = true
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ DmTaskSetSector = func(task *CDmTask, sector uint64) int {
|
|
|
+ calls["DmTaskSetSector"] = true
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ DmTaskSetMessage = func(task *CDmTask, message string) int {
|
|
|
+ calls["DmTaskSetMessage"] = true
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ DmAttachLoopDevice = func(filename string, fd *int) string {
|
|
|
+ calls["DmAttachLoopDevice"] = true
|
|
|
+ return "/dev/loop42"
|
|
|
+ }
|
|
|
+ DmTaskDestroy = func(task *CDmTask) {
|
|
|
+ calls["DmTaskDestroy"] = true
|
|
|
+ }
|
|
|
+ DmGetBlockSize = func(fd uintptr) (int64, sysErrno) {
|
|
|
+ calls["DmGetBlockSize"] = true
|
|
|
+ return int64(4242 * 512), 0
|
|
|
+ }
|
|
|
+ DmTaskAddTarget = func(task *CDmTask, start, size uint64, ttype, params string) int {
|
|
|
+ calls["DmTaskSetTarget"] = true
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ DmTaskSetCookie = func(task *CDmTask, cookie *uint, flags uint16) int {
|
|
|
+ calls["DmTaskSetCookie"] = true
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ DmUdevWait = func(cookie uint) int {
|
|
|
+ calls["DmUdevWait"] = true
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ DmTaskSetAddNode = func(task *CDmTask, addNode AddNodeType) int {
|
|
|
+ calls["DmTaskSetAddNode"] = true
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ execRun = func(name string, args ...string) error {
|
|
|
+ calls["execRun"] = true
|
|
|
+ return nil
|
|
|
}
|
|
|
}
|
|
|
|
|
|
func TestDriverName(t *testing.T) {
|
|
|
- d := newDriver(t)
|
|
|
- defer cleanup(d)
|
|
|
+ denyAllDevmapper()
|
|
|
+ defer denyAllDevmapper()
|
|
|
+
|
|
|
+ oldInit := fakeInit()
|
|
|
+ defer restoreInit(oldInit)
|
|
|
|
|
|
+ d := newDriver(t)
|
|
|
if d.String() != "devicemapper" {
|
|
|
t.Fatalf("Expected driver name to be devicemapper got %s", d.String())
|
|
|
}
|
|
|
}
|
|
|
|
|
|
func TestDriverCreate(t *testing.T) {
|
|
|
- d := newDriver(t)
|
|
|
- defer cleanup(d)
|
|
|
-
|
|
|
- if err := d.Create("1", ""); err != nil {
|
|
|
- t.Fatal(err)
|
|
|
+ denyAllDevmapper()
|
|
|
+ denyAllSyscall()
|
|
|
+ defer denyAllSyscall()
|
|
|
+ defer denyAllDevmapper()
|
|
|
+
|
|
|
+ calls := make(Set)
|
|
|
+ mockAllDevmapper(calls)
|
|
|
+
|
|
|
+ sysMount = func(source, target, fstype string, flags uintptr, data string) (err error) {
|
|
|
+ calls["sysMount"] = true
|
|
|
+ // FIXME: compare the exact source and target strings (inodes + devname)
|
|
|
+ if expectedSource := "/dev/mapper/docker-"; !strings.HasPrefix(source, expectedSource) {
|
|
|
+ t.Fatalf("Wrong syscall call\nExpected: Mount(%v)\nReceived: Mount(%v)\n", expectedSource, source)
|
|
|
+ }
|
|
|
+ if expectedTarget := "/tmp/docker-test-devmapper-"; !strings.HasPrefix(target, expectedTarget) {
|
|
|
+ t.Fatalf("Wrong syscall call\nExpected: Mount(%v)\nReceived: Mount(%v)\n", expectedTarget, target)
|
|
|
+ }
|
|
|
+ if expectedFstype := "ext4"; fstype != expectedFstype {
|
|
|
+ t.Fatalf("Wrong syscall call\nExpected: Mount(%v)\nReceived: Mount(%v)\n", expectedFstype, fstype)
|
|
|
+ }
|
|
|
+ if expectedFlags := uintptr(3236757504); flags != expectedFlags {
|
|
|
+ t.Fatalf("Wrong syscall call\nExpected: Mount(%v)\nReceived: Mount(%v)\n", expectedFlags, flags)
|
|
|
+ }
|
|
|
+ return nil
|
|
|
}
|
|
|
+
|
|
|
+ Mounted = func(mnt string) (bool, error) {
|
|
|
+ calls["Mounted"] = true
|
|
|
+ if !strings.HasPrefix(mnt, "/tmp/docker-test-devmapper-") || !strings.HasSuffix(mnt, "/mnt/1") {
|
|
|
+ t.Fatalf("Wrong mounted call\nExpected: Mounted(%v)\nReceived: Mounted(%v)\n", "/tmp/docker-test-devmapper-.../mnt/1", mnt)
|
|
|
+ }
|
|
|
+ return false, nil
|
|
|
+ }
|
|
|
+
|
|
|
+ func() {
|
|
|
+ d := newDriver(t)
|
|
|
+
|
|
|
+ calls.Assert(t,
|
|
|
+ "DmSetDevDir",
|
|
|
+ "DmLogWithErrnoInit",
|
|
|
+ "DmTaskSetName",
|
|
|
+ "DmTaskRun",
|
|
|
+ "DmTaskGetInfo",
|
|
|
+ "DmAttachLoopDevice",
|
|
|
+ "execRun",
|
|
|
+ "DmTaskCreate",
|
|
|
+ "DmGetBlockSize",
|
|
|
+ "DmTaskSetTarget",
|
|
|
+ "DmTaskSetCookie",
|
|
|
+ "DmUdevWait",
|
|
|
+ "DmTaskSetSector",
|
|
|
+ "DmTaskSetMessage",
|
|
|
+ "DmTaskSetAddNode",
|
|
|
+ )
|
|
|
+
|
|
|
+ if err := d.Create("1", ""); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ calls.Assert(t,
|
|
|
+ "DmTaskCreate",
|
|
|
+ "DmTaskGetInfo",
|
|
|
+ "sysMount",
|
|
|
+ "Mounted",
|
|
|
+ "DmTaskRun",
|
|
|
+ "DmTaskSetTarget",
|
|
|
+ "DmTaskSetSector",
|
|
|
+ "DmTaskSetCookie",
|
|
|
+ "DmUdevWait",
|
|
|
+ "DmTaskSetName",
|
|
|
+ "DmTaskSetMessage",
|
|
|
+ "DmTaskSetAddNode",
|
|
|
+ )
|
|
|
+
|
|
|
+ }()
|
|
|
+
|
|
|
+ runtime.GC()
|
|
|
+
|
|
|
+ calls.Assert(t,
|
|
|
+ "DmTaskDestroy",
|
|
|
+ )
|
|
|
}
|
|
|
|
|
|
func TestDriverRemove(t *testing.T) {
|
|
|
- d := newDriver(t)
|
|
|
- defer cleanup(d)
|
|
|
-
|
|
|
- if err := d.Create("1", ""); err != nil {
|
|
|
- t.Fatal(err)
|
|
|
+ denyAllDevmapper()
|
|
|
+ denyAllSyscall()
|
|
|
+ defer denyAllSyscall()
|
|
|
+ defer denyAllDevmapper()
|
|
|
+
|
|
|
+ calls := make(Set)
|
|
|
+ mockAllDevmapper(calls)
|
|
|
+
|
|
|
+ sysMount = func(source, target, fstype string, flags uintptr, data string) (err error) {
|
|
|
+ calls["sysMount"] = true
|
|
|
+ // FIXME: compare the exact source and target strings (inodes + devname)
|
|
|
+ if expectedSource := "/dev/mapper/docker-"; !strings.HasPrefix(source, expectedSource) {
|
|
|
+ t.Fatalf("Wrong syscall call\nExpected: Mount(%v)\nReceived: Mount(%v)\n", expectedSource, source)
|
|
|
+ }
|
|
|
+ if expectedTarget := "/tmp/docker-test-devmapper-"; !strings.HasPrefix(target, expectedTarget) {
|
|
|
+ t.Fatalf("Wrong syscall call\nExpected: Mount(%v)\nReceived: Mount(%v)\n", expectedTarget, target)
|
|
|
+ }
|
|
|
+ if expectedFstype := "ext4"; fstype != expectedFstype {
|
|
|
+ t.Fatalf("Wrong syscall call\nExpected: Mount(%v)\nReceived: Mount(%v)\n", expectedFstype, fstype)
|
|
|
+ }
|
|
|
+ if expectedFlags := uintptr(3236757504); flags != expectedFlags {
|
|
|
+ t.Fatalf("Wrong syscall call\nExpected: Mount(%v)\nReceived: Mount(%v)\n", expectedFlags, flags)
|
|
|
+ }
|
|
|
+ return nil
|
|
|
}
|
|
|
+ sysUnmount = func(target string, flags int) (err error) {
|
|
|
+ calls["sysUnmount"] = true
|
|
|
+ // FIXME: compare the exact source and target strings (inodes + devname)
|
|
|
+ if expectedTarget := "/tmp/docker-test-devmapper-"; !strings.HasPrefix(target, expectedTarget) {
|
|
|
+ t.Fatalf("Wrong syscall call\nExpected: Mount(%v)\nReceived: Mount(%v)\n", expectedTarget, target)
|
|
|
+ }
|
|
|
+ if expectedFlags := 0; flags != expectedFlags {
|
|
|
+ t.Fatalf("Wrong syscall call\nExpected: Mount(%v)\nReceived: Mount(%v)\n", expectedFlags, flags)
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ Mounted = func(mnt string) (bool, error) {
|
|
|
+ calls["Mounted"] = true
|
|
|
+ return false, nil
|
|
|
+ }
|
|
|
+
|
|
|
+ func() {
|
|
|
+ d := newDriver(t)
|
|
|
+
|
|
|
+ calls.Assert(t,
|
|
|
+ "DmSetDevDir",
|
|
|
+ "DmLogWithErrnoInit",
|
|
|
+ "DmTaskSetName",
|
|
|
+ "DmTaskRun",
|
|
|
+ "DmTaskGetInfo",
|
|
|
+ "DmAttachLoopDevice",
|
|
|
+ "execRun",
|
|
|
+ "DmTaskCreate",
|
|
|
+ "DmGetBlockSize",
|
|
|
+ "DmTaskSetTarget",
|
|
|
+ "DmTaskSetCookie",
|
|
|
+ "DmUdevWait",
|
|
|
+ "DmTaskSetSector",
|
|
|
+ "DmTaskSetMessage",
|
|
|
+ "DmTaskSetAddNode",
|
|
|
+ )
|
|
|
+
|
|
|
+ if err := d.Create("1", ""); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
|
|
|
- if err := d.Remove("1"); err != nil {
|
|
|
- t.Fatal(err)
|
|
|
- }
|
|
|
+ calls.Assert(t,
|
|
|
+ "DmTaskCreate",
|
|
|
+ "DmTaskGetInfo",
|
|
|
+ "sysMount",
|
|
|
+ "Mounted",
|
|
|
+ "DmTaskRun",
|
|
|
+ "DmTaskSetTarget",
|
|
|
+ "DmTaskSetSector",
|
|
|
+ "DmTaskSetCookie",
|
|
|
+ "DmUdevWait",
|
|
|
+ "DmTaskSetName",
|
|
|
+ "DmTaskSetMessage",
|
|
|
+ "DmTaskSetAddNode",
|
|
|
+ )
|
|
|
+
|
|
|
+ Mounted = func(mnt string) (bool, error) {
|
|
|
+ calls["Mounted"] = true
|
|
|
+ return true, nil
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := d.Remove("1"); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ calls.Assert(t,
|
|
|
+ "DmTaskRun",
|
|
|
+ "DmTaskSetSector",
|
|
|
+ "DmTaskSetName",
|
|
|
+ "DmTaskSetMessage",
|
|
|
+ "DmTaskCreate",
|
|
|
+ "DmTaskGetInfo",
|
|
|
+ "Mounted",
|
|
|
+ "sysUnmount",
|
|
|
+ )
|
|
|
+ }()
|
|
|
+ runtime.GC()
|
|
|
+
|
|
|
+ calls.Assert(t,
|
|
|
+ "DmTaskDestroy",
|
|
|
+ )
|
|
|
}
|
|
|
|
|
|
func TestCleanup(t *testing.T) {
|
|
|
+ t.Skip("FIXME: not a unit test")
|
|
|
t.Skip("Unimplemented")
|
|
|
d := newDriver(t)
|
|
|
- defer os.RemoveAll(d.home)
|
|
|
+ defer osRemoveAll(d.home)
|
|
|
|
|
|
mountPoints := make([]string, 2)
|
|
|
|
|
@@ -161,6 +712,7 @@ func TestCleanup(t *testing.T) {
|
|
|
}
|
|
|
|
|
|
func TestNotMounted(t *testing.T) {
|
|
|
+ t.Skip("FIXME: not a unit test")
|
|
|
t.Skip("Not implemented")
|
|
|
d := newDriver(t)
|
|
|
defer cleanup(d)
|
|
@@ -179,6 +731,7 @@ func TestNotMounted(t *testing.T) {
|
|
|
}
|
|
|
|
|
|
func TestMounted(t *testing.T) {
|
|
|
+ t.Skip("FIXME: not a unit test")
|
|
|
d := newDriver(t)
|
|
|
defer cleanup(d)
|
|
|
|
|
@@ -199,6 +752,7 @@ func TestMounted(t *testing.T) {
|
|
|
}
|
|
|
|
|
|
func TestInitCleanedDriver(t *testing.T) {
|
|
|
+ t.Skip("FIXME: not a unit test")
|
|
|
d := newDriver(t)
|
|
|
|
|
|
if err := d.Create("1", ""); err != nil {
|
|
@@ -225,6 +779,7 @@ func TestInitCleanedDriver(t *testing.T) {
|
|
|
}
|
|
|
|
|
|
func TestMountMountedDriver(t *testing.T) {
|
|
|
+ t.Skip("FIXME: not a unit test")
|
|
|
d := newDriver(t)
|
|
|
defer cleanup(d)
|
|
|
|
|
@@ -243,6 +798,7 @@ func TestMountMountedDriver(t *testing.T) {
|
|
|
}
|
|
|
|
|
|
func TestGetReturnsValidDevice(t *testing.T) {
|
|
|
+ t.Skip("FIXME: not a unit test")
|
|
|
d := newDriver(t)
|
|
|
defer cleanup(d)
|
|
|
|
|
@@ -268,6 +824,7 @@ func TestGetReturnsValidDevice(t *testing.T) {
|
|
|
}
|
|
|
|
|
|
func TestDriverGetSize(t *testing.T) {
|
|
|
+ t.Skip("FIXME: not a unit test")
|
|
|
t.Skipf("Size is currently not implemented")
|
|
|
|
|
|
d := newDriver(t)
|
|
@@ -284,7 +841,7 @@ func TestDriverGetSize(t *testing.T) {
|
|
|
|
|
|
size := int64(1024)
|
|
|
|
|
|
- f, err := os.Create(path.Join(mountPoint, "test_file"))
|
|
|
+ f, err := osCreate(path.Join(mountPoint, "test_file"))
|
|
|
if err != nil {
|
|
|
t.Fatal(err)
|
|
|
}
|
|
@@ -301,3 +858,15 @@ func TestDriverGetSize(t *testing.T) {
|
|
|
// t.Fatalf("Expected size %d got %d", size, diffSize)
|
|
|
// }
|
|
|
}
|
|
|
+
|
|
|
+func assertMap(t *testing.T, m map[string]bool, keys ...string) {
|
|
|
+ for _, key := range keys {
|
|
|
+ if _, exists := m[key]; !exists {
|
|
|
+ t.Fatalf("Key not set: %s", key)
|
|
|
+ }
|
|
|
+ delete(m, key)
|
|
|
+ }
|
|
|
+ if len(m) != 0 {
|
|
|
+ t.Fatalf("Unexpected keys: %v", m)
|
|
|
+ }
|
|
|
+}
|