github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/volume/mounts/lcow_parser_test.go (about) 1 package mounts // import "github.com/docker/docker/volume/mounts" 2 3 import ( 4 "fmt" 5 "strings" 6 "testing" 7 8 "github.com/docker/docker/api/types/mount" 9 "gotest.tools/v3/assert" 10 ) 11 12 func TestLCOWParseMountRaw(t *testing.T) { 13 valid := []string{ 14 `/foo`, 15 `/foo/`, 16 `/foo bar`, 17 `c:\:/foo`, 18 `c:\windows\:/foo`, 19 `c:\windows:/s p a c e`, 20 `c:\windows:/s p a c e:RW`, 21 `c:\program files:/s p a c e i n h o s t d i r`, 22 `0123456789name:/foo`, 23 `MiXeDcAsEnAmE:/foo`, 24 `name:/foo`, 25 `name:/foo:rW`, 26 `name:/foo:RW`, 27 `name:/foo:RO`, 28 `c:/:/forward/slashes/are/good/too`, 29 `c:/:/including with/spaces:ro`, 30 `/Program Files (x86)`, // With capitals and brackets 31 } 32 33 invalid := map[string]string{ 34 ``: "invalid volume specification: ", 35 `.`: "invalid volume specification: ", 36 `c:`: "invalid volume specification: ", 37 `c:\`: "invalid volume specification: ", 38 `../`: "invalid volume specification: ", 39 `c:\:../`: "invalid volume specification: ", 40 `c:\:/foo:xyzzy`: "invalid volume specification: ", 41 `/`: "destination can't be '/'", 42 `/..`: "destination can't be '/'", 43 `c:\notexist:/foo`: `source path does not exist: c:\notexist`, 44 `c:\windows\system32\ntdll.dll:/foo`: `source path must be a directory`, 45 `name<:/foo`: `invalid volume specification`, 46 `name>:/foo`: `invalid volume specification`, 47 `name::/foo`: `invalid volume specification`, 48 `name":/foo`: `invalid volume specification`, 49 `name\:/foo`: `invalid volume specification`, 50 `name*:/foo`: `invalid volume specification`, 51 `name|:/foo`: `invalid volume specification`, 52 `name?:/foo`: `invalid volume specification`, 53 `name/:/foo`: `invalid volume specification`, 54 `/foo:rw`: `invalid volume specification`, 55 `/foo:ro`: `invalid volume specification`, 56 `con:/foo`: `cannot be a reserved word for Windows filenames`, 57 `PRN:/foo`: `cannot be a reserved word for Windows filenames`, 58 `aUx:/foo`: `cannot be a reserved word for Windows filenames`, 59 `nul:/foo`: `cannot be a reserved word for Windows filenames`, 60 `com1:/foo`: `cannot be a reserved word for Windows filenames`, 61 `com2:/foo`: `cannot be a reserved word for Windows filenames`, 62 `com3:/foo`: `cannot be a reserved word for Windows filenames`, 63 `com4:/foo`: `cannot be a reserved word for Windows filenames`, 64 `com5:/foo`: `cannot be a reserved word for Windows filenames`, 65 `com6:/foo`: `cannot be a reserved word for Windows filenames`, 66 `com7:/foo`: `cannot be a reserved word for Windows filenames`, 67 `com8:/foo`: `cannot be a reserved word for Windows filenames`, 68 `com9:/foo`: `cannot be a reserved word for Windows filenames`, 69 `lpt1:/foo`: `cannot be a reserved word for Windows filenames`, 70 `lpt2:/foo`: `cannot be a reserved word for Windows filenames`, 71 `lpt3:/foo`: `cannot be a reserved word for Windows filenames`, 72 `lpt4:/foo`: `cannot be a reserved word for Windows filenames`, 73 `lpt5:/foo`: `cannot be a reserved word for Windows filenames`, 74 `lpt6:/foo`: `cannot be a reserved word for Windows filenames`, 75 `lpt7:/foo`: `cannot be a reserved word for Windows filenames`, 76 `lpt8:/foo`: `cannot be a reserved word for Windows filenames`, 77 `lpt9:/foo`: `cannot be a reserved word for Windows filenames`, 78 `\\.\pipe\foo:/foo`: `Linux containers on Windows do not support named pipe mounts`, 79 } 80 81 parser := NewLCOWParser() 82 if p, ok := parser.(*lcowParser); ok { 83 p.fi = mockFiProvider{} 84 } 85 86 for _, path := range valid { 87 if _, err := parser.ParseMountRaw(path, "local"); err != nil { 88 t.Errorf("ParseMountRaw(`%q`) should succeed: error %q", path, err) 89 } 90 } 91 92 for path, expectedError := range invalid { 93 if mp, err := parser.ParseMountRaw(path, "local"); err == nil { 94 t.Errorf("ParseMountRaw(`%q`) should have failed validation. Err '%v' - MP: %v", path, err, mp) 95 } else { 96 if !strings.Contains(err.Error(), expectedError) { 97 t.Errorf("ParseMountRaw(`%q`) error should contain %q, got %v", path, expectedError, err.Error()) 98 } 99 } 100 } 101 } 102 103 func TestLCOWParseMountRawSplit(t *testing.T) { 104 cases := []struct { 105 bind string 106 driver string 107 expType mount.Type 108 expDest string 109 expSource string 110 expName string 111 expDriver string 112 expRW bool 113 fail bool 114 }{ 115 {`c:\:/foo`, "local", mount.TypeBind, `/foo`, `c:\`, ``, "", true, false}, 116 {`c:\:/foo:ro`, "local", mount.TypeBind, `/foo`, `c:\`, ``, "", false, false}, 117 {`c:\:/foo:rw`, "local", mount.TypeBind, `/foo`, `c:\`, ``, "", true, false}, 118 {`c:\:/foo:foo`, "local", mount.TypeBind, `/foo`, `c:\`, ``, "", false, true}, 119 {`name:/foo:rw`, "local", mount.TypeVolume, `/foo`, ``, `name`, "local", true, false}, 120 {`name:/foo`, "local", mount.TypeVolume, `/foo`, ``, `name`, "local", true, false}, 121 {`name:/foo:ro`, "local", mount.TypeVolume, `/foo`, ``, `name`, "local", false, false}, 122 {`name:/`, "", mount.TypeVolume, ``, ``, ``, "", true, true}, 123 {`driver/name:/`, "", mount.TypeVolume, ``, ``, ``, "", true, true}, 124 {`\\.\pipe\foo:\\.\pipe\bar`, "local", mount.TypeNamedPipe, `\\.\pipe\bar`, `\\.\pipe\foo`, "", "", true, true}, 125 {`\\.\pipe\foo:/data`, "local", mount.TypeNamedPipe, ``, ``, "", "", true, true}, 126 {`c:\foo\bar:\\.\pipe\foo`, "local", mount.TypeNamedPipe, ``, ``, "", "", true, true}, 127 } 128 129 parser := NewLCOWParser() 130 if p, ok := parser.(*lcowParser); ok { 131 p.fi = mockFiProvider{} 132 } 133 134 for i, c := range cases { 135 c := c 136 t.Run(fmt.Sprintf("%d_%s", i, c.bind), func(t *testing.T) { 137 m, err := parser.ParseMountRaw(c.bind, c.driver) 138 if c.fail { 139 assert.ErrorContains(t, err, "", "expected an error") 140 return 141 } 142 143 assert.NilError(t, err) 144 assert.Equal(t, m.Destination, c.expDest) 145 assert.Equal(t, m.Source, c.expSource) 146 assert.Equal(t, m.Name, c.expName) 147 assert.Equal(t, m.Driver, c.expDriver) 148 assert.Equal(t, m.RW, c.expRW) 149 assert.Equal(t, m.Type, c.expType) 150 }) 151 } 152 }