diff --git a/volume/mounts/lcow_parser_test.go b/volume/mounts/lcow_parser_test.go index c62309b143..57c45eccaf 100644 --- a/volume/mounts/lcow_parser_test.go +++ b/volume/mounts/lcow_parser_test.go @@ -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)) }) } } diff --git a/volume/mounts/linux_parser_test.go b/volume/mounts/linux_parser_test.go index bc0039d081..2f64d6cc78 100644 --- a/volume/mounts/linux_parser_test.go +++ b/volume/mounts/linux_parser_test.go @@ -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) } } } diff --git a/volume/mounts/parser_test.go b/volume/mounts/parser_test.go index 67c8d4c065..6f9d18a418 100644 --- a/volume/mounts/parser_test.go +++ b/volume/mounts/parser_test.go @@ -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)) + }) } } diff --git a/volume/mounts/validate_test.go b/volume/mounts/validate_test.go index 9a7f9ae1c5..ea0004b7e4 100644 --- a/volume/mounts/validate_test.go +++ b/volume/mounts/validate_test.go @@ -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) + } + }) } } diff --git a/volume/mounts/validate_unix_test.go b/volume/mounts/validate_unix_test.go index 88e828c7c9..f0089eb0c6 100644 --- a/volume/mounts/validate_unix_test.go +++ b/volume/mounts/validate_unix_test.go @@ -2,7 +2,7 @@ package mounts // import "github.com/docker/docker/volume/mounts" -var ( +const ( testDestinationPath = "/foo" testSourcePath = "/foo" ) diff --git a/volume/mounts/validate_windows_test.go b/volume/mounts/validate_windows_test.go index 74b40a6c30..996bcbeaec 100644 --- a/volume/mounts/validate_windows_test.go +++ b/volume/mounts/validate_windows_test.go @@ -1,6 +1,6 @@ package mounts // import "github.com/docker/docker/volume/mounts" -var ( +const ( testDestinationPath = `c:\foo` testSourcePath = `c:\foo` ) diff --git a/volume/mounts/windows_parser_test.go b/volume/mounts/windows_parser_test.go index cd63be11b2..e6b5d35b20 100644 --- a/volume/mounts/windows_parser_test.go +++ b/volume/mounts/windows_parser_test.go @@ -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)) }) } }