volume/mounts: cleanup tests
- don't use un-keyed structs - user assert.Check where possible - use consts for fixed values Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
10aff57b26
commit
d69b1fdb72
7 changed files with 451 additions and 173 deletions
|
@ -1,12 +1,12 @@
|
|||
package mounts // import "github.com/docker/docker/volume/mounts"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types/mount"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
|
||||
func TestLCOWParseMountRaw(t *testing.T) {
|
||||
|
@ -112,18 +112,98 @@ func TestLCOWParseMountRawSplit(t *testing.T) {
|
|||
expRW bool
|
||||
fail bool
|
||||
}{
|
||||
{`c:\:/foo`, "local", mount.TypeBind, `/foo`, `c:\`, ``, "", true, false},
|
||||
{`c:\:/foo:ro`, "local", mount.TypeBind, `/foo`, `c:\`, ``, "", false, false},
|
||||
{`c:\:/foo:rw`, "local", mount.TypeBind, `/foo`, `c:\`, ``, "", true, false},
|
||||
{`c:\:/foo:foo`, "local", mount.TypeBind, `/foo`, `c:\`, ``, "", false, true},
|
||||
{`name:/foo:rw`, "local", mount.TypeVolume, `/foo`, ``, `name`, "local", true, false},
|
||||
{`name:/foo`, "local", mount.TypeVolume, `/foo`, ``, `name`, "local", true, false},
|
||||
{`name:/foo:ro`, "local", mount.TypeVolume, `/foo`, ``, `name`, "local", false, false},
|
||||
{`name:/`, "", mount.TypeVolume, ``, ``, ``, "", true, true},
|
||||
{`driver/name:/`, "", mount.TypeVolume, ``, ``, ``, "", true, true},
|
||||
{`\\.\pipe\foo:\\.\pipe\bar`, "local", mount.TypeNamedPipe, `\\.\pipe\bar`, `\\.\pipe\foo`, "", "", true, true},
|
||||
{`\\.\pipe\foo:/data`, "local", mount.TypeNamedPipe, ``, ``, "", "", true, true},
|
||||
{`c:\foo\bar:\\.\pipe\foo`, "local", mount.TypeNamedPipe, ``, ``, "", "", true, true},
|
||||
{
|
||||
bind: `c:\:/foo`,
|
||||
driver: "local",
|
||||
expType: mount.TypeBind,
|
||||
expDest: `/foo`,
|
||||
expSource: `c:\`,
|
||||
expRW: true,
|
||||
},
|
||||
{
|
||||
bind: `c:\:/foo:ro`,
|
||||
driver: "local",
|
||||
expType: mount.TypeBind,
|
||||
expDest: `/foo`,
|
||||
expSource: `c:\`,
|
||||
},
|
||||
{
|
||||
bind: `c:\:/foo:rw`,
|
||||
driver: "local",
|
||||
expType: mount.TypeBind,
|
||||
expDest: `/foo`,
|
||||
expSource: `c:\`,
|
||||
expRW: true,
|
||||
},
|
||||
{
|
||||
bind: `c:\:/foo:foo`,
|
||||
driver: "local",
|
||||
expType: mount.TypeBind,
|
||||
expDest: `/foo`,
|
||||
expSource: `c:\`,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
bind: `name:/foo:rw`,
|
||||
driver: "local",
|
||||
expType: mount.TypeVolume,
|
||||
expDest: `/foo`,
|
||||
expName: `name`,
|
||||
expDriver: "local",
|
||||
expRW: true,
|
||||
},
|
||||
{
|
||||
bind: `name:/foo`,
|
||||
driver: "local",
|
||||
expType: mount.TypeVolume,
|
||||
expDest: `/foo`,
|
||||
expName: `name`,
|
||||
expDriver: "local",
|
||||
expRW: true,
|
||||
},
|
||||
{
|
||||
bind: `name:/foo:ro`,
|
||||
driver: "local",
|
||||
expType: mount.TypeVolume,
|
||||
expDest: `/foo`,
|
||||
expName: `name`,
|
||||
expDriver: "local",
|
||||
},
|
||||
{
|
||||
bind: `name:/`,
|
||||
expType: mount.TypeVolume,
|
||||
expRW: true,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
bind: `driver/name:/`,
|
||||
expType: mount.TypeVolume,
|
||||
expRW: true,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
bind: `\\.\pipe\foo:\\.\pipe\bar`,
|
||||
driver: "local",
|
||||
expType: mount.TypeNamedPipe,
|
||||
expDest: `\\.\pipe\bar`,
|
||||
expSource: `\\.\pipe\foo`,
|
||||
expRW: true,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
bind: `\\.\pipe\foo:/data`,
|
||||
driver: "local",
|
||||
expType: mount.TypeNamedPipe,
|
||||
expRW: true,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
bind: `c:\foo\bar:\\.\pipe\foo`,
|
||||
driver: "local",
|
||||
expType: mount.TypeNamedPipe,
|
||||
expRW: true,
|
||||
fail: true,
|
||||
},
|
||||
}
|
||||
|
||||
parser := NewLCOWParser()
|
||||
|
@ -131,22 +211,22 @@ func TestLCOWParseMountRawSplit(t *testing.T) {
|
|||
p.fi = mockFiProvider{}
|
||||
}
|
||||
|
||||
for i, c := range cases {
|
||||
c := c
|
||||
t.Run(fmt.Sprintf("%d_%s", i, c.bind), func(t *testing.T) {
|
||||
m, err := parser.ParseMountRaw(c.bind, c.driver)
|
||||
if c.fail {
|
||||
assert.ErrorContains(t, err, "", "expected an error")
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(tc.bind, func(t *testing.T) {
|
||||
m, err := parser.ParseMountRaw(tc.bind, tc.driver)
|
||||
if tc.fail {
|
||||
assert.Check(t, is.ErrorContains(err, ""), "expected an error")
|
||||
return
|
||||
}
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, m.Destination, c.expDest)
|
||||
assert.Equal(t, m.Source, c.expSource)
|
||||
assert.Equal(t, m.Name, c.expName)
|
||||
assert.Equal(t, m.Driver, c.expDriver)
|
||||
assert.Equal(t, m.RW, c.expRW)
|
||||
assert.Equal(t, m.Type, c.expType)
|
||||
assert.Check(t, err)
|
||||
assert.Check(t, is.Equal(m.Destination, tc.expDest))
|
||||
assert.Check(t, is.Equal(m.Source, tc.expSource))
|
||||
assert.Check(t, is.Equal(m.Name, tc.expName))
|
||||
assert.Check(t, is.Equal(m.Driver, tc.expDriver))
|
||||
assert.Check(t, is.Equal(m.RW, tc.expRW))
|
||||
assert.Check(t, is.Equal(m.Type, tc.expType))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/docker/docker/api/types/mount"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
|
||||
func TestLinuxParseMountRaw(t *testing.T) {
|
||||
|
@ -109,15 +110,68 @@ func TestLinuxParseMountRawSplit(t *testing.T) {
|
|||
expRW bool
|
||||
fail bool
|
||||
}{
|
||||
{"/tmp:/tmp1", "", mount.TypeBind, "/tmp1", "/tmp", "", "", true, false},
|
||||
{"/tmp:/tmp2:ro", "", mount.TypeBind, "/tmp2", "/tmp", "", "", false, false},
|
||||
{"/tmp:/tmp3:rw", "", mount.TypeBind, "/tmp3", "/tmp", "", "", true, false},
|
||||
{"/tmp:/tmp4:foo", "", mount.TypeBind, "", "", "", "", false, true},
|
||||
{"name:/named1", "", mount.TypeVolume, "/named1", "", "name", "", true, false},
|
||||
{"name:/named2", "external", mount.TypeVolume, "/named2", "", "name", "external", true, false},
|
||||
{"name:/named3:ro", "local", mount.TypeVolume, "/named3", "", "name", "local", false, false},
|
||||
{"local/name:/tmp:rw", "", mount.TypeVolume, "/tmp", "", "local/name", "", true, false},
|
||||
{"/tmp:tmp", "", mount.TypeBind, "", "", "", "", true, true},
|
||||
{
|
||||
bind: "/tmp:/tmp1",
|
||||
expType: mount.TypeBind,
|
||||
expDest: "/tmp1",
|
||||
expSource: "/tmp",
|
||||
expRW: true,
|
||||
},
|
||||
{
|
||||
bind: "/tmp:/tmp2:ro",
|
||||
expType: mount.TypeBind,
|
||||
expDest: "/tmp2",
|
||||
expSource: "/tmp",
|
||||
},
|
||||
{
|
||||
bind: "/tmp:/tmp3:rw",
|
||||
expType: mount.TypeBind,
|
||||
expDest: "/tmp3",
|
||||
expSource: "/tmp",
|
||||
expRW: true,
|
||||
},
|
||||
{
|
||||
bind: "/tmp:/tmp4:foo",
|
||||
expType: mount.TypeBind,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
bind: "name:/named1",
|
||||
expType: mount.TypeVolume,
|
||||
expDest: "/named1",
|
||||
expName: "name",
|
||||
expRW: true,
|
||||
},
|
||||
{
|
||||
bind: "name:/named2",
|
||||
driver: "external",
|
||||
expType: mount.TypeVolume,
|
||||
expDest: "/named2",
|
||||
expName: "name",
|
||||
expDriver: "external",
|
||||
expRW: true,
|
||||
},
|
||||
{
|
||||
bind: "name:/named3:ro",
|
||||
driver: "local",
|
||||
expType: mount.TypeVolume,
|
||||
expDest: "/named3",
|
||||
expName: "name",
|
||||
expDriver: "local",
|
||||
},
|
||||
{
|
||||
bind: "local/name:/tmp:rw",
|
||||
expType: mount.TypeVolume,
|
||||
expDest: "/tmp",
|
||||
expName: "local/name",
|
||||
expRW: true,
|
||||
},
|
||||
{
|
||||
bind: "/tmp:tmp",
|
||||
expType: mount.TypeBind,
|
||||
expRW: true,
|
||||
fail: true,
|
||||
},
|
||||
}
|
||||
|
||||
parser := NewLinuxParser()
|
||||
|
@ -125,22 +179,22 @@ func TestLinuxParseMountRawSplit(t *testing.T) {
|
|||
p.fi = mockFiProvider{}
|
||||
}
|
||||
|
||||
for i, c := range cases {
|
||||
c := c
|
||||
t.Run(fmt.Sprintf("%d_%s", i, c.bind), func(t *testing.T) {
|
||||
m, err := parser.ParseMountRaw(c.bind, c.driver)
|
||||
if c.fail {
|
||||
assert.ErrorContains(t, err, "", "expected an error")
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(tc.bind, func(t *testing.T) {
|
||||
m, err := parser.ParseMountRaw(tc.bind, tc.driver)
|
||||
if tc.fail {
|
||||
assert.Check(t, is.ErrorContains(err, ""), "expected an error")
|
||||
return
|
||||
}
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, m.Destination, c.expDest)
|
||||
assert.Equal(t, m.Source, c.expSource)
|
||||
assert.Equal(t, m.Name, c.expName)
|
||||
assert.Equal(t, m.Driver, c.expDriver)
|
||||
assert.Equal(t, m.RW, c.expRW)
|
||||
assert.Equal(t, m.Type, c.expType)
|
||||
assert.Check(t, err)
|
||||
assert.Check(t, is.Equal(m.Destination, tc.expDest))
|
||||
assert.Check(t, is.Equal(m.Source, tc.expSource))
|
||||
assert.Check(t, is.Equal(m.Name, tc.expName))
|
||||
assert.Check(t, is.Equal(m.Driver, tc.expDriver))
|
||||
assert.Check(t, is.Equal(m.RW, tc.expRW))
|
||||
assert.Check(t, is.Equal(m.Type, tc.expType))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -200,21 +254,21 @@ func TestConvertTmpfsOptions(t *testing.T) {
|
|||
},
|
||||
}
|
||||
p := NewLinuxParser()
|
||||
for _, c := range cases {
|
||||
data, err := p.ConvertTmpfsOptions(&c.opt, c.readOnly)
|
||||
for _, tc := range cases {
|
||||
data, err := p.ConvertTmpfsOptions(&tc.opt, tc.readOnly)
|
||||
if err != nil {
|
||||
t.Fatalf("could not convert %+v (readOnly: %v) to string: %v",
|
||||
c.opt, c.readOnly, err)
|
||||
tc.opt, tc.readOnly, err)
|
||||
}
|
||||
t.Logf("data=%q", data)
|
||||
for _, s := range c.expectedSubstrings {
|
||||
for _, s := range tc.expectedSubstrings {
|
||||
if !strings.Contains(data, s) {
|
||||
t.Fatalf("expected substring: %s, got %v (case=%+v)", s, data, c)
|
||||
t.Fatalf("expected substring: %s, got %v (case=%+v)", s, data, tc)
|
||||
}
|
||||
}
|
||||
for _, s := range c.unexpectedSubstrings {
|
||||
for _, s := range tc.unexpectedSubstrings {
|
||||
if strings.Contains(data, s) {
|
||||
t.Fatalf("unexpected substring: %s, got %v (case=%+v)", s, data, c)
|
||||
t.Fatalf("unexpected substring: %s, got %v (case=%+v)", s, data, tc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types/mount"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
|
||||
type mockFiProvider struct{}
|
||||
|
@ -50,41 +52,44 @@ func TestParseMountSpec(t *testing.T) {
|
|||
input mount.Mount
|
||||
expected MountPoint
|
||||
}{
|
||||
{mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath, ReadOnly: true}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, Propagation: parser.DefaultPropagationMode()}},
|
||||
{mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, RW: true, Propagation: parser.DefaultPropagationMode()}},
|
||||
{mount.Mount{Type: mount.TypeBind, Source: testDir + string(os.PathSeparator), Target: testDestinationPath, ReadOnly: true}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, Propagation: parser.DefaultPropagationMode()}},
|
||||
{mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath + string(os.PathSeparator), ReadOnly: true}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, Propagation: parser.DefaultPropagationMode()}},
|
||||
{mount.Mount{Type: mount.TypeVolume, Target: testDestinationPath}, MountPoint{Type: mount.TypeVolume, Destination: testDestinationPath, RW: true, CopyData: parser.DefaultCopyMode()}},
|
||||
{mount.Mount{Type: mount.TypeVolume, Target: testDestinationPath + string(os.PathSeparator)}, MountPoint{Type: mount.TypeVolume, Destination: testDestinationPath, RW: true, CopyData: parser.DefaultCopyMode()}},
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath, ReadOnly: true},
|
||||
expected: MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, Propagation: parser.DefaultPropagationMode()},
|
||||
},
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath},
|
||||
expected: MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, RW: true, Propagation: parser.DefaultPropagationMode()},
|
||||
},
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeBind, Source: testDir + string(os.PathSeparator), Target: testDestinationPath, ReadOnly: true},
|
||||
expected: MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, Propagation: parser.DefaultPropagationMode()},
|
||||
},
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath + string(os.PathSeparator), ReadOnly: true},
|
||||
expected: MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, Propagation: parser.DefaultPropagationMode()},
|
||||
},
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeVolume, Target: testDestinationPath},
|
||||
expected: MountPoint{Type: mount.TypeVolume, Destination: testDestinationPath, RW: true, CopyData: parser.DefaultCopyMode()},
|
||||
},
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeVolume, Target: testDestinationPath + string(os.PathSeparator)},
|
||||
expected: MountPoint{Type: mount.TypeVolume, Destination: testDestinationPath, RW: true, CopyData: parser.DefaultCopyMode()},
|
||||
},
|
||||
}
|
||||
|
||||
for i, c := range cases {
|
||||
t.Logf("case %d", i)
|
||||
mp, err := parser.ParseMountSpec(c.input)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if c.expected.Type != mp.Type {
|
||||
t.Errorf("Expected mount types to match. Expected: '%s', Actual: '%s'", c.expected.Type, mp.Type)
|
||||
}
|
||||
if c.expected.Destination != mp.Destination {
|
||||
t.Errorf("Expected mount destination to match. Expected: '%s', Actual: '%s'", c.expected.Destination, mp.Destination)
|
||||
}
|
||||
if c.expected.Source != mp.Source {
|
||||
t.Errorf("Expected mount source to match. Expected: '%s', Actual: '%s'", c.expected.Source, mp.Source)
|
||||
}
|
||||
if c.expected.RW != mp.RW {
|
||||
t.Errorf("Expected mount writable to match. Expected: '%v', Actual: '%v'", c.expected.RW, mp.RW)
|
||||
}
|
||||
if c.expected.Propagation != mp.Propagation {
|
||||
t.Errorf("Expected mount propagation to match. Expected: '%v', Actual: '%s'", c.expected.Propagation, mp.Propagation)
|
||||
}
|
||||
if c.expected.Driver != mp.Driver {
|
||||
t.Errorf("Expected mount driver to match. Expected: '%v', Actual: '%s'", c.expected.Driver, mp.Driver)
|
||||
}
|
||||
if c.expected.CopyData != mp.CopyData {
|
||||
t.Errorf("Expected mount copy data to match. Expected: '%v', Actual: '%v'", c.expected.CopyData, mp.CopyData)
|
||||
}
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run("", func(t *testing.T) {
|
||||
mp, err := parser.ParseMountSpec(tc.input)
|
||||
assert.Check(t, err)
|
||||
assert.Check(t, is.Equal(mp.Type, tc.expected.Type))
|
||||
assert.Check(t, is.Equal(mp.Destination, tc.expected.Destination))
|
||||
assert.Check(t, is.Equal(mp.Source, tc.expected.Source))
|
||||
assert.Check(t, is.Equal(mp.RW, tc.expected.RW))
|
||||
assert.Check(t, is.Equal(mp.Propagation, tc.expected.Propagation))
|
||||
assert.Check(t, is.Equal(mp.Driver, tc.expected.Driver))
|
||||
assert.Check(t, is.Equal(mp.CopyData, tc.expected.CopyData))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,71 +2,123 @@ package mounts // import "github.com/docker/docker/volume/mounts"
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types/mount"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
|
||||
func TestValidateMount(t *testing.T) {
|
||||
testDir, err := os.MkdirTemp("", "test-validate-mount")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(testDir)
|
||||
|
||||
cases := []struct {
|
||||
input mount.Mount
|
||||
expected error
|
||||
}{
|
||||
{mount.Mount{Type: mount.TypeVolume}, errMissingField("Target")},
|
||||
{mount.Mount{Type: mount.TypeVolume, Target: testDestinationPath, Source: "hello"}, nil},
|
||||
{mount.Mount{Type: mount.TypeVolume, Target: testDestinationPath}, nil},
|
||||
{mount.Mount{Type: mount.TypeBind}, errMissingField("Target")},
|
||||
{mount.Mount{Type: mount.TypeBind, Target: testDestinationPath}, errMissingField("Source")},
|
||||
{mount.Mount{Type: mount.TypeBind, Target: testDestinationPath, Source: testSourcePath, VolumeOptions: &mount.VolumeOptions{}}, errExtraField("VolumeOptions")},
|
||||
|
||||
{mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath}, nil},
|
||||
{mount.Mount{Type: "invalid", Target: testDestinationPath}, errors.New("mount type unknown")},
|
||||
{mount.Mount{Type: mount.TypeBind, Source: testSourcePath, Target: testDestinationPath}, errBindSourceDoesNotExist(testSourcePath)},
|
||||
}
|
||||
|
||||
lcowCases := []struct {
|
||||
input mount.Mount
|
||||
expected error
|
||||
}{
|
||||
{mount.Mount{Type: mount.TypeVolume}, errMissingField("Target")},
|
||||
{mount.Mount{Type: mount.TypeVolume, Target: "/foo", Source: "hello"}, nil},
|
||||
{mount.Mount{Type: mount.TypeVolume, Target: "/foo"}, nil},
|
||||
{mount.Mount{Type: mount.TypeBind}, errMissingField("Target")},
|
||||
{mount.Mount{Type: mount.TypeBind, Target: "/foo"}, errMissingField("Source")},
|
||||
{mount.Mount{Type: mount.TypeBind, Target: "/foo", Source: "c:\\foo", VolumeOptions: &mount.VolumeOptions{}}, errExtraField("VolumeOptions")},
|
||||
{mount.Mount{Type: mount.TypeBind, Source: "c:\\foo", Target: "/foo"}, errBindSourceDoesNotExist("c:\\foo")},
|
||||
{mount.Mount{Type: mount.TypeBind, Source: testDir, Target: "/foo"}, nil},
|
||||
{mount.Mount{Type: "invalid", Target: "/foo"}, errors.New("mount type unknown")},
|
||||
}
|
||||
testDir := t.TempDir()
|
||||
parser := NewParser()
|
||||
for i, x := range cases {
|
||||
err := parser.ValidateMountConfig(&x.input)
|
||||
if err == nil && x.expected == nil {
|
||||
continue
|
||||
}
|
||||
if (err == nil && x.expected != nil) || (x.expected == nil && err != nil) || !strings.Contains(err.Error(), x.expected.Error()) {
|
||||
t.Errorf("expected %q, got %q, case: %d", x.expected, err, i)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
input mount.Mount
|
||||
expected error
|
||||
}{
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeVolume},
|
||||
expected: errMissingField("Target"),
|
||||
},
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeVolume, Target: testDestinationPath, Source: "hello"},
|
||||
},
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeVolume, Target: testDestinationPath},
|
||||
},
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeBind},
|
||||
expected: errMissingField("Target"),
|
||||
},
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeBind, Target: testDestinationPath},
|
||||
expected: errMissingField("Source"),
|
||||
},
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeBind, Target: testDestinationPath, Source: testSourcePath, VolumeOptions: &mount.VolumeOptions{}},
|
||||
expected: errExtraField("VolumeOptions"),
|
||||
},
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath},
|
||||
},
|
||||
{
|
||||
input: mount.Mount{Type: "invalid", Target: testDestinationPath},
|
||||
expected: errors.New("mount type unknown"),
|
||||
},
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeBind, Source: testSourcePath, Target: testDestinationPath},
|
||||
expected: errBindSourceDoesNotExist(testSourcePath),
|
||||
},
|
||||
}
|
||||
if runtime.GOOS == "windows" {
|
||||
parser = NewLCOWParser()
|
||||
for i, x := range lcowCases {
|
||||
err := parser.ValidateMountConfig(&x.input)
|
||||
if err == nil && x.expected == nil {
|
||||
continue
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run("", func(t *testing.T) {
|
||||
err := parser.ValidateMountConfig(&tc.input)
|
||||
if tc.expected != nil {
|
||||
assert.Check(t, is.ErrorContains(err, tc.expected.Error()))
|
||||
} else {
|
||||
assert.Check(t, err)
|
||||
}
|
||||
if (err == nil && x.expected != nil) || (x.expected == nil && err != nil) || !strings.Contains(err.Error(), x.expected.Error()) {
|
||||
t.Errorf("expected %q, got %q, case: %d", x.expected, err, i)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateLCOWMount(t *testing.T) {
|
||||
if runtime.GOOS != "windows" {
|
||||
t.Skip("only tested on Windows")
|
||||
}
|
||||
testDir := t.TempDir()
|
||||
parser := NewLCOWParser()
|
||||
|
||||
tests := []struct {
|
||||
input mount.Mount
|
||||
expected error
|
||||
}{
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeVolume},
|
||||
expected: errMissingField("Target"),
|
||||
},
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeVolume, Target: "/foo", Source: "hello"},
|
||||
},
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeVolume, Target: "/foo"},
|
||||
},
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeBind},
|
||||
expected: errMissingField("Target"),
|
||||
},
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeBind, Target: "/foo"},
|
||||
expected: errMissingField("Source"),
|
||||
},
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeBind, Target: "/foo", Source: "c:\\foo", VolumeOptions: &mount.VolumeOptions{}},
|
||||
expected: errExtraField("VolumeOptions"),
|
||||
},
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeBind, Source: "c:\\foo", Target: "/foo"},
|
||||
expected: errBindSourceDoesNotExist("c:\\foo"),
|
||||
},
|
||||
{
|
||||
input: mount.Mount{Type: mount.TypeBind, Source: testDir, Target: "/foo"},
|
||||
},
|
||||
{
|
||||
input: mount.Mount{Type: "invalid", Target: "/foo"},
|
||||
expected: errors.New("mount type unknown"),
|
||||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run("", func(t *testing.T) {
|
||||
err := parser.ValidateMountConfig(&tc.input)
|
||||
if tc.expected != nil {
|
||||
assert.Check(t, is.ErrorContains(err, tc.expected.Error()))
|
||||
} else {
|
||||
assert.Check(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
package mounts // import "github.com/docker/docker/volume/mounts"
|
||||
|
||||
var (
|
||||
const (
|
||||
testDestinationPath = "/foo"
|
||||
testSourcePath = "/foo"
|
||||
)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package mounts // import "github.com/docker/docker/volume/mounts"
|
||||
|
||||
var (
|
||||
const (
|
||||
testDestinationPath = `c:\foo`
|
||||
testSourcePath = `c:\foo`
|
||||
)
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/docker/docker/api/types/mount"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
|
||||
func TestWindowsParseMountRaw(t *testing.T) {
|
||||
|
@ -118,19 +119,105 @@ func TestWindowsParseMountRawSplit(t *testing.T) {
|
|||
expRW bool
|
||||
fail bool
|
||||
}{
|
||||
{`c:\:d:`, "local", mount.TypeBind, `d:`, `c:\`, ``, "", true, false},
|
||||
{`c:\:d:\`, "local", mount.TypeBind, `d:\`, `c:\`, ``, "", true, false},
|
||||
{`c:\:d:\:ro`, "local", mount.TypeBind, `d:\`, `c:\`, ``, "", false, false},
|
||||
{`c:\:d:\:rw`, "local", mount.TypeBind, `d:\`, `c:\`, ``, "", true, false},
|
||||
{`c:\:d:\:foo`, "local", mount.TypeBind, `d:\`, `c:\`, ``, "", false, true},
|
||||
{`name:d::rw`, "local", mount.TypeVolume, `d:`, ``, `name`, "local", true, false},
|
||||
{`name:d:`, "local", mount.TypeVolume, `d:`, ``, `name`, "local", true, false},
|
||||
{`name:d::ro`, "local", mount.TypeVolume, `d:`, ``, `name`, "local", false, false},
|
||||
{`name:c:`, "", mount.TypeVolume, ``, ``, ``, "", true, true},
|
||||
{`driver/name:c:`, "", mount.TypeVolume, ``, ``, ``, "", true, true},
|
||||
{`\\.\pipe\foo:\\.\pipe\bar`, "local", mount.TypeNamedPipe, `\\.\pipe\bar`, `\\.\pipe\foo`, "", "", true, false},
|
||||
{`\\.\pipe\foo:c:\foo\bar`, "local", mount.TypeNamedPipe, ``, ``, "", "", true, true},
|
||||
{`c:\foo\bar:\\.\pipe\foo`, "local", mount.TypeNamedPipe, ``, ``, "", "", true, true},
|
||||
{
|
||||
bind: `c:\:d:`,
|
||||
driver: "local",
|
||||
expType: mount.TypeBind,
|
||||
expDest: `d:`,
|
||||
expSource: `c:\`,
|
||||
expRW: true,
|
||||
},
|
||||
{
|
||||
bind: `c:\:d:\`,
|
||||
driver: "local",
|
||||
expType: mount.TypeBind,
|
||||
expDest: `d:\`,
|
||||
expSource: `c:\`,
|
||||
expRW: true,
|
||||
},
|
||||
{
|
||||
bind: `c:\:d:\:ro`,
|
||||
driver: "local",
|
||||
expType: mount.TypeBind,
|
||||
expDest: `d:\`,
|
||||
expSource: `c:\`,
|
||||
},
|
||||
{
|
||||
bind: `c:\:d:\:rw`,
|
||||
driver: "local",
|
||||
expType: mount.TypeBind,
|
||||
expDest: `d:\`,
|
||||
expSource: `c:\`,
|
||||
expRW: true,
|
||||
},
|
||||
{
|
||||
bind: `c:\:d:\:foo`,
|
||||
driver: "local",
|
||||
expType: mount.TypeBind,
|
||||
expDest: `d:\`,
|
||||
expSource: `c:\`,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
bind: `name:d::rw`,
|
||||
driver: "local",
|
||||
expType: mount.TypeVolume,
|
||||
expDest: `d:`,
|
||||
expName: `name`,
|
||||
expDriver: "local",
|
||||
expRW: true,
|
||||
},
|
||||
{
|
||||
bind: `name:d:`,
|
||||
driver: "local",
|
||||
expType: mount.TypeVolume,
|
||||
expDest: `d:`,
|
||||
expName: `name`,
|
||||
expDriver: "local",
|
||||
expRW: true,
|
||||
},
|
||||
{
|
||||
bind: `name:d::ro`,
|
||||
driver: "local",
|
||||
expType: mount.TypeVolume,
|
||||
expDest: `d:`,
|
||||
expName: `name`,
|
||||
expDriver: "local",
|
||||
},
|
||||
{
|
||||
bind: `name:c:`,
|
||||
expType: mount.TypeVolume,
|
||||
expRW: true,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
bind: `driver/name:c:`,
|
||||
expType: mount.TypeVolume,
|
||||
expRW: true,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
bind: `\\.\pipe\foo:\\.\pipe\bar`,
|
||||
driver: "local",
|
||||
expType: mount.TypeNamedPipe,
|
||||
expDest: `\\.\pipe\bar`,
|
||||
expSource: `\\.\pipe\foo`,
|
||||
expRW: true,
|
||||
},
|
||||
{
|
||||
bind: `\\.\pipe\foo:c:\foo\bar`,
|
||||
driver: "local",
|
||||
expType: mount.TypeNamedPipe,
|
||||
expRW: true,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
bind: `c:\foo\bar:\\.\pipe\foo`,
|
||||
driver: "local",
|
||||
expType: mount.TypeNamedPipe,
|
||||
expRW: true,
|
||||
fail: true,
|
||||
},
|
||||
}
|
||||
|
||||
parser := NewWindowsParser()
|
||||
|
@ -138,22 +225,22 @@ func TestWindowsParseMountRawSplit(t *testing.T) {
|
|||
p.fi = mockFiProvider{}
|
||||
}
|
||||
|
||||
for i, c := range cases {
|
||||
c := c
|
||||
t.Run(fmt.Sprintf("%d_%s", i, c.bind), func(t *testing.T) {
|
||||
m, err := parser.ParseMountRaw(c.bind, c.driver)
|
||||
if c.fail {
|
||||
assert.ErrorContains(t, err, "", "expected an error")
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(tc.bind, func(t *testing.T) {
|
||||
m, err := parser.ParseMountRaw(tc.bind, tc.driver)
|
||||
if tc.fail {
|
||||
assert.Check(t, is.ErrorContains(err, ""), "expected an error")
|
||||
return
|
||||
}
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, m.Destination, c.expDest)
|
||||
assert.Equal(t, m.Source, c.expSource)
|
||||
assert.Equal(t, m.Name, c.expName)
|
||||
assert.Equal(t, m.Driver, c.expDriver)
|
||||
assert.Equal(t, m.RW, c.expRW)
|
||||
assert.Equal(t, m.Type, c.expType)
|
||||
assert.Check(t, err)
|
||||
assert.Check(t, is.Equal(m.Destination, tc.expDest))
|
||||
assert.Check(t, is.Equal(m.Source, tc.expSource))
|
||||
assert.Check(t, is.Equal(m.Name, tc.expName))
|
||||
assert.Check(t, is.Equal(m.Driver, tc.expDriver))
|
||||
assert.Check(t, is.Equal(m.RW, tc.expRW))
|
||||
assert.Check(t, is.Equal(m.Type, tc.expType))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue