|
@@ -1,939 +0,0 @@
|
|
-// +build linux,amd64
|
|
|
|
-
|
|
|
|
-package devmapper
|
|
|
|
-
|
|
|
|
-import (
|
|
|
|
- "fmt"
|
|
|
|
- "github.com/dotcloud/docker/daemon/graphdriver"
|
|
|
|
- "github.com/dotcloud/docker/daemon/graphdriver/graphtest"
|
|
|
|
- "io/ioutil"
|
|
|
|
- "path"
|
|
|
|
- "runtime"
|
|
|
|
- "strings"
|
|
|
|
- "syscall"
|
|
|
|
- "testing"
|
|
|
|
-)
|
|
|
|
-
|
|
|
|
-func init() {
|
|
|
|
- // Reduce the size the the base fs and loopback for the tests
|
|
|
|
- DefaultDataLoopbackSize = 300 * 1024 * 1024
|
|
|
|
- DefaultMetaDataLoopbackSize = 200 * 1024 * 1024
|
|
|
|
- DefaultBaseFsSize = 300 * 1024 * 1024
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// We use assignment here to get the right type
|
|
|
|
-var (
|
|
|
|
- oldMounted = Mounted
|
|
|
|
- oldExecRun = execRun
|
|
|
|
-)
|
|
|
|
-
|
|
|
|
-// denyAllDevmapper mocks all calls to libdevmapper in the unit tests, and denies them by default
|
|
|
|
-func denyAllDevmapper() {
|
|
|
|
- oldExecRun = execRun
|
|
|
|
-
|
|
|
|
- // 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")
|
|
|
|
- }
|
|
|
|
- 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")
|
|
|
|
- }
|
|
|
|
- LogWithErrnoInit = func() {
|
|
|
|
- panic("LogWithErrnoInit: this method should not be called here")
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func restoreAllDevmapper() {
|
|
|
|
- DmGetLibraryVersion = dmGetLibraryVersionFct
|
|
|
|
- DmGetNextTarget = dmGetNextTargetFct
|
|
|
|
- DmLogInitVerbose = dmLogInitVerboseFct
|
|
|
|
- DmSetDevDir = dmSetDevDirFct
|
|
|
|
- DmTaskAddTarget = dmTaskAddTargetFct
|
|
|
|
- DmTaskCreate = dmTaskCreateFct
|
|
|
|
- DmTaskDestroy = dmTaskDestroyFct
|
|
|
|
- DmTaskGetInfo = dmTaskGetInfoFct
|
|
|
|
- DmTaskRun = dmTaskRunFct
|
|
|
|
- DmTaskSetAddNode = dmTaskSetAddNodeFct
|
|
|
|
- DmTaskSetCookie = dmTaskSetCookieFct
|
|
|
|
- DmTaskSetMessage = dmTaskSetMessageFct
|
|
|
|
- DmTaskSetName = dmTaskSetNameFct
|
|
|
|
- DmTaskSetRo = dmTaskSetRoFct
|
|
|
|
- DmTaskSetSector = dmTaskSetSectorFct
|
|
|
|
- DmUdevWait = dmUdevWaitFct
|
|
|
|
- LogWithErrnoInit = logWithErrnoInitFct
|
|
|
|
- execRun = oldExecRun
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func denyAllSyscall() {
|
|
|
|
- oldMounted = Mounted
|
|
|
|
- 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 restoreAllSyscall() {
|
|
|
|
- sysMount = syscall.Mount
|
|
|
|
- sysUnmount = syscall.Unmount
|
|
|
|
- sysCloseOnExec = syscall.CloseOnExec
|
|
|
|
- sysSyscall = syscall.Syscall
|
|
|
|
- Mounted = oldMounted
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func mkTestDirectory(t *testing.T) string {
|
|
|
|
- dir, err := ioutil.TempDir("", "docker-test-devmapper-")
|
|
|
|
- if err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
- return dir
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func newDriver(t *testing.T) *Driver {
|
|
|
|
- home := mkTestDirectory(t)
|
|
|
|
- d, err := Init(home)
|
|
|
|
- if err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
- return d.(*Driver)
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func cleanup(d *Driver) {
|
|
|
|
- d.Cleanup()
|
|
|
|
- osRemoveAll(d.home)
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-type Set map[string]bool
|
|
|
|
-
|
|
|
|
-func (r Set) Assert(t *testing.T, names ...string) {
|
|
|
|
- for _, key := range names {
|
|
|
|
- required := true
|
|
|
|
- if strings.HasPrefix(key, "?") {
|
|
|
|
- key = key[1:]
|
|
|
|
- required = false
|
|
|
|
- }
|
|
|
|
- if _, exists := r[key]; !exists && required {
|
|
|
|
- t.Fatalf("Key not set: %s", key)
|
|
|
|
- }
|
|
|
|
- delete(r, key)
|
|
|
|
- }
|
|
|
|
- if len(r) != 0 {
|
|
|
|
- t.Fatalf("Unexpected keys: %v", r)
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func TestInit(t *testing.T) {
|
|
|
|
- var (
|
|
|
|
- calls = make(Set)
|
|
|
|
- taskMessages = make(Set)
|
|
|
|
- taskTypes = make(Set)
|
|
|
|
- home = mkTestDirectory(t)
|
|
|
|
- )
|
|
|
|
- defer osRemoveAll(home)
|
|
|
|
-
|
|
|
|
- denyAllDevmapper()
|
|
|
|
- defer restoreAllDevmapper()
|
|
|
|
-
|
|
|
|
- func() {
|
|
|
|
- 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
|
|
|
|
- }
|
|
|
|
- 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)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- 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 function to make sure the garbage collection will
|
|
|
|
- // occur.
|
|
|
|
-
|
|
|
|
- // Call GC to cleanup runtime.Finalizers
|
|
|
|
- runtime.GC()
|
|
|
|
-
|
|
|
|
- calls.Assert(t,
|
|
|
|
- "DmSetDevDir",
|
|
|
|
- "DmLogWithErrnoInit",
|
|
|
|
- "DmTaskSetName",
|
|
|
|
- "DmTaskRun",
|
|
|
|
- "DmTaskGetInfo",
|
|
|
|
- "DmTaskDestroy",
|
|
|
|
- "execRun",
|
|
|
|
- "DmTaskCreate",
|
|
|
|
- "DmTaskSetTarget",
|
|
|
|
- "DmTaskSetCookie",
|
|
|
|
- "DmUdevWait",
|
|
|
|
- "DmTaskSetSector",
|
|
|
|
- "DmTaskSetMessage",
|
|
|
|
- "DmTaskSetAddNode",
|
|
|
|
- )
|
|
|
|
- taskTypes.Assert(t, "0", "6", "17")
|
|
|
|
- taskMessages.Assert(t, "create_thin 0", "set_transaction_id 0 1")
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func fakeInit() func(home string) (graphdriver.Driver, error) {
|
|
|
|
- oldInit := Init
|
|
|
|
- Init = func(home string) (graphdriver.Driver, error) {
|
|
|
|
- return &Driver{
|
|
|
|
- home: home,
|
|
|
|
- }, nil
|
|
|
|
- }
|
|
|
|
- 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
|
|
|
|
- }
|
|
|
|
- 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
|
|
|
|
- }
|
|
|
|
- DmTaskDestroy = func(task *CDmTask) {
|
|
|
|
- calls["DmTaskDestroy"] = true
|
|
|
|
- }
|
|
|
|
- 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) {
|
|
|
|
- denyAllDevmapper()
|
|
|
|
- defer restoreAllDevmapper()
|
|
|
|
-
|
|
|
|
- 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) {
|
|
|
|
- denyAllDevmapper()
|
|
|
|
- denyAllSyscall()
|
|
|
|
- defer restoreAllSyscall()
|
|
|
|
- defer restoreAllDevmapper()
|
|
|
|
-
|
|
|
|
- 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, flag int) error {
|
|
|
|
- //calls["sysUnmount"] = true
|
|
|
|
-
|
|
|
|
- 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
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- sysSyscall = func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
|
|
|
|
- calls["sysSyscall"] = true
|
|
|
|
- if trap != sysSysIoctl {
|
|
|
|
- t.Fatalf("Unexpected syscall. Expecting SYS_IOCTL, received: %d", trap)
|
|
|
|
- }
|
|
|
|
- switch a2 {
|
|
|
|
- case LoopSetFd:
|
|
|
|
- calls["ioctl.loopsetfd"] = true
|
|
|
|
- case LoopCtlGetFree:
|
|
|
|
- calls["ioctl.loopctlgetfree"] = true
|
|
|
|
- case LoopGetStatus64:
|
|
|
|
- calls["ioctl.loopgetstatus"] = true
|
|
|
|
- case LoopSetStatus64:
|
|
|
|
- calls["ioctl.loopsetstatus"] = true
|
|
|
|
- case LoopClrFd:
|
|
|
|
- calls["ioctl.loopclrfd"] = true
|
|
|
|
- case LoopSetCapacity:
|
|
|
|
- calls["ioctl.loopsetcapacity"] = true
|
|
|
|
- case BlkGetSize64:
|
|
|
|
- calls["ioctl.blkgetsize"] = true
|
|
|
|
- default:
|
|
|
|
- t.Fatalf("Unexpected IOCTL. Received %d", a2)
|
|
|
|
- }
|
|
|
|
- return 0, 0, 0
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- func() {
|
|
|
|
- d := newDriver(t)
|
|
|
|
-
|
|
|
|
- calls.Assert(t,
|
|
|
|
- "DmSetDevDir",
|
|
|
|
- "DmLogWithErrnoInit",
|
|
|
|
- "DmTaskSetName",
|
|
|
|
- "DmTaskRun",
|
|
|
|
- "DmTaskGetInfo",
|
|
|
|
- "execRun",
|
|
|
|
- "DmTaskCreate",
|
|
|
|
- "DmTaskSetTarget",
|
|
|
|
- "DmTaskSetCookie",
|
|
|
|
- "DmUdevWait",
|
|
|
|
- "DmTaskSetSector",
|
|
|
|
- "DmTaskSetMessage",
|
|
|
|
- "DmTaskSetAddNode",
|
|
|
|
- "sysSyscall",
|
|
|
|
- "ioctl.blkgetsize",
|
|
|
|
- "ioctl.loopsetfd",
|
|
|
|
- "ioctl.loopsetstatus",
|
|
|
|
- "?ioctl.loopctlgetfree",
|
|
|
|
- )
|
|
|
|
-
|
|
|
|
- if err := d.Create("1", ""); err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
- calls.Assert(t,
|
|
|
|
- "DmTaskCreate",
|
|
|
|
- "DmTaskGetInfo",
|
|
|
|
- "DmTaskRun",
|
|
|
|
- "DmTaskSetSector",
|
|
|
|
- "DmTaskSetName",
|
|
|
|
- "DmTaskSetMessage",
|
|
|
|
- )
|
|
|
|
-
|
|
|
|
- }()
|
|
|
|
-
|
|
|
|
- runtime.GC()
|
|
|
|
-
|
|
|
|
- calls.Assert(t,
|
|
|
|
- "DmTaskDestroy",
|
|
|
|
- )
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func TestDriverRemove(t *testing.T) {
|
|
|
|
- denyAllDevmapper()
|
|
|
|
- denyAllSyscall()
|
|
|
|
- defer restoreAllSyscall()
|
|
|
|
- defer restoreAllDevmapper()
|
|
|
|
-
|
|
|
|
- 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) {
|
|
|
|
- // 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
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- sysSyscall = func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
|
|
|
|
- calls["sysSyscall"] = true
|
|
|
|
- if trap != sysSysIoctl {
|
|
|
|
- t.Fatalf("Unexpected syscall. Expecting SYS_IOCTL, received: %d", trap)
|
|
|
|
- }
|
|
|
|
- switch a2 {
|
|
|
|
- case LoopSetFd:
|
|
|
|
- calls["ioctl.loopsetfd"] = true
|
|
|
|
- case LoopCtlGetFree:
|
|
|
|
- calls["ioctl.loopctlgetfree"] = true
|
|
|
|
- case LoopGetStatus64:
|
|
|
|
- calls["ioctl.loopgetstatus"] = true
|
|
|
|
- case LoopSetStatus64:
|
|
|
|
- calls["ioctl.loopsetstatus"] = true
|
|
|
|
- case LoopClrFd:
|
|
|
|
- calls["ioctl.loopclrfd"] = true
|
|
|
|
- case LoopSetCapacity:
|
|
|
|
- calls["ioctl.loopsetcapacity"] = true
|
|
|
|
- case BlkGetSize64:
|
|
|
|
- calls["ioctl.blkgetsize"] = true
|
|
|
|
- default:
|
|
|
|
- t.Fatalf("Unexpected IOCTL. Received %d", a2)
|
|
|
|
- }
|
|
|
|
- return 0, 0, 0
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- func() {
|
|
|
|
- d := newDriver(t)
|
|
|
|
-
|
|
|
|
- calls.Assert(t,
|
|
|
|
- "DmSetDevDir",
|
|
|
|
- "DmLogWithErrnoInit",
|
|
|
|
- "DmTaskSetName",
|
|
|
|
- "DmTaskRun",
|
|
|
|
- "DmTaskGetInfo",
|
|
|
|
- "execRun",
|
|
|
|
- "DmTaskCreate",
|
|
|
|
- "DmTaskSetTarget",
|
|
|
|
- "DmTaskSetCookie",
|
|
|
|
- "DmUdevWait",
|
|
|
|
- "DmTaskSetSector",
|
|
|
|
- "DmTaskSetMessage",
|
|
|
|
- "DmTaskSetAddNode",
|
|
|
|
- "sysSyscall",
|
|
|
|
- "ioctl.blkgetsize",
|
|
|
|
- "ioctl.loopsetfd",
|
|
|
|
- "ioctl.loopsetstatus",
|
|
|
|
- "?ioctl.loopctlgetfree",
|
|
|
|
- )
|
|
|
|
-
|
|
|
|
- if err := d.Create("1", ""); err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- calls.Assert(t,
|
|
|
|
- "DmTaskCreate",
|
|
|
|
- "DmTaskGetInfo",
|
|
|
|
- "DmTaskRun",
|
|
|
|
- "DmTaskSetSector",
|
|
|
|
- "DmTaskSetName",
|
|
|
|
- "DmTaskSetMessage",
|
|
|
|
- )
|
|
|
|
-
|
|
|
|
- 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",
|
|
|
|
- "DmTaskSetCookie",
|
|
|
|
- "DmTaskSetTarget",
|
|
|
|
- "DmTaskSetAddNode",
|
|
|
|
- "DmUdevWait",
|
|
|
|
- )
|
|
|
|
- }()
|
|
|
|
- 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 osRemoveAll(d.home)
|
|
|
|
-
|
|
|
|
- mountPoints := make([]string, 2)
|
|
|
|
-
|
|
|
|
- if err := d.Create("1", ""); err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
- // Mount the id
|
|
|
|
- p, err := d.Get("1", "")
|
|
|
|
- if err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
- mountPoints[0] = p
|
|
|
|
-
|
|
|
|
- if err := d.Create("2", "1"); err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- p, err = d.Get("2", "")
|
|
|
|
- if err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
- mountPoints[1] = p
|
|
|
|
-
|
|
|
|
- // Ensure that all the mount points are currently mounted
|
|
|
|
- for _, p := range mountPoints {
|
|
|
|
- if mounted, err := Mounted(p); err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- } else if !mounted {
|
|
|
|
- t.Fatalf("Expected %s to be mounted", p)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Ensure that devices are active
|
|
|
|
- for _, p := range []string{"1", "2"} {
|
|
|
|
- if !d.HasActivatedDevice(p) {
|
|
|
|
- t.Fatalf("Expected %s to have an active device", p)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if err := d.Cleanup(); err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Ensure that all the mount points are no longer mounted
|
|
|
|
- for _, p := range mountPoints {
|
|
|
|
- if mounted, err := Mounted(p); err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- } else if mounted {
|
|
|
|
- t.Fatalf("Expected %s to not be mounted", p)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Ensure that devices are no longer activated
|
|
|
|
- for _, p := range []string{"1", "2"} {
|
|
|
|
- if d.HasActivatedDevice(p) {
|
|
|
|
- t.Fatalf("Expected %s not be an active device", p)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func TestNotMounted(t *testing.T) {
|
|
|
|
- t.Skip("FIXME: not a unit test")
|
|
|
|
- t.Skip("Not implemented")
|
|
|
|
- d := newDriver(t)
|
|
|
|
- defer cleanup(d)
|
|
|
|
-
|
|
|
|
- if err := d.Create("1", ""); err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- mounted, err := Mounted(path.Join(d.home, "mnt", "1"))
|
|
|
|
- if err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
- if mounted {
|
|
|
|
- t.Fatal("Id 1 should not be mounted")
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func TestMounted(t *testing.T) {
|
|
|
|
- t.Skip("FIXME: not a unit test")
|
|
|
|
- d := newDriver(t)
|
|
|
|
- defer cleanup(d)
|
|
|
|
-
|
|
|
|
- if err := d.Create("1", ""); err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
- if _, err := d.Get("1", ""); err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- mounted, err := Mounted(path.Join(d.home, "mnt", "1"))
|
|
|
|
- if err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
- if !mounted {
|
|
|
|
- t.Fatal("Id 1 should be mounted")
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func TestInitCleanedDriver(t *testing.T) {
|
|
|
|
- t.Skip("FIXME: not a unit test")
|
|
|
|
- d := newDriver(t)
|
|
|
|
-
|
|
|
|
- if err := d.Create("1", ""); err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
- if _, err := d.Get("1", ""); err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if err := d.Cleanup(); err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- driver, err := Init(d.home)
|
|
|
|
- if err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
- d = driver.(*Driver)
|
|
|
|
- defer cleanup(d)
|
|
|
|
-
|
|
|
|
- if _, err := d.Get("1", ""); err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func TestMountMountedDriver(t *testing.T) {
|
|
|
|
- t.Skip("FIXME: not a unit test")
|
|
|
|
- d := newDriver(t)
|
|
|
|
- defer cleanup(d)
|
|
|
|
-
|
|
|
|
- if err := d.Create("1", ""); err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Perform get on same id to ensure that it will
|
|
|
|
- // not be mounted twice
|
|
|
|
- if _, err := d.Get("1", ""); err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
- if _, err := d.Get("1", ""); err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func TestGetReturnsValidDevice(t *testing.T) {
|
|
|
|
- t.Skip("FIXME: not a unit test")
|
|
|
|
- d := newDriver(t)
|
|
|
|
- defer cleanup(d)
|
|
|
|
-
|
|
|
|
- if err := d.Create("1", ""); err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if !d.HasDevice("1") {
|
|
|
|
- t.Fatalf("Expected id 1 to be in device set")
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if _, err := d.Get("1", ""); err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if !d.HasActivatedDevice("1") {
|
|
|
|
- t.Fatalf("Expected id 1 to be activated")
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func TestDriverGetSize(t *testing.T) {
|
|
|
|
- t.Skip("FIXME: not a unit test")
|
|
|
|
- t.Skipf("Size is currently not implemented")
|
|
|
|
-
|
|
|
|
- d := newDriver(t)
|
|
|
|
- defer cleanup(d)
|
|
|
|
-
|
|
|
|
- if err := d.Create("1", ""); err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- mountPoint, err := d.Get("1", "")
|
|
|
|
- if err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- size := int64(1024)
|
|
|
|
-
|
|
|
|
- f, err := osCreate(path.Join(mountPoint, "test_file"))
|
|
|
|
- if err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
- if err := f.Truncate(size); err != nil {
|
|
|
|
- t.Fatal(err)
|
|
|
|
- }
|
|
|
|
- f.Close()
|
|
|
|
-
|
|
|
|
- // diffSize, err := d.DiffSize("1")
|
|
|
|
- // if err != nil {
|
|
|
|
- // t.Fatal(err)
|
|
|
|
- // }
|
|
|
|
- // if diffSize != size {
|
|
|
|
- // 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)
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// This avoids creating a new driver for each test if all tests are run
|
|
|
|
-// Make sure to put new tests between TestDevmapperSetup and TestDevmapperTeardown
|
|
|
|
-func TestDevmapperSetup(t *testing.T) {
|
|
|
|
- graphtest.GetDriver(t, "devicemapper")
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func TestDevmapperCreateEmpty(t *testing.T) {
|
|
|
|
- graphtest.DriverTestCreateEmpty(t, "devicemapper")
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func TestDevmapperCreateBase(t *testing.T) {
|
|
|
|
- graphtest.DriverTestCreateBase(t, "devicemapper")
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func TestDevmapperCreateSnap(t *testing.T) {
|
|
|
|
- graphtest.DriverTestCreateSnap(t, "devicemapper")
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func TestDevmapperTeardown(t *testing.T) {
|
|
|
|
- graphtest.PutDriver(t)
|
|
|
|
-}
|
|
|