github.com/portworx/docker@v1.12.1/volume/volume_test.go (about) 1 package volume 2 3 import ( 4 "runtime" 5 "strings" 6 "testing" 7 ) 8 9 func TestParseMountSpec(t *testing.T) { 10 var ( 11 valid []string 12 invalid map[string]string 13 ) 14 15 if runtime.GOOS == "windows" { 16 valid = []string{ 17 `d:\`, 18 `d:`, 19 `d:\path`, 20 `d:\path with space`, 21 // TODO Windows post TP5 - readonly support `d:\pathandmode:ro`, 22 `c:\:d:\`, 23 `c:\windows\:d:`, 24 `c:\windows:d:\s p a c e`, 25 `c:\windows:d:\s p a c e:RW`, 26 `c:\program files:d:\s p a c e i n h o s t d i r`, 27 `0123456789name:d:`, 28 `MiXeDcAsEnAmE:d:`, 29 `name:D:`, 30 `name:D::rW`, 31 `name:D::RW`, 32 // TODO Windows post TP5 - readonly support `name:D::RO`, 33 `c:/:d:/forward/slashes/are/good/too`, 34 // TODO Windows post TP5 - readonly support `c:/:d:/including with/spaces:ro`, 35 `c:\Windows`, // With capital 36 `c:\Program Files (x86)`, // With capitals and brackets 37 } 38 invalid = map[string]string{ 39 ``: "Invalid volume specification: ", 40 `.`: "Invalid volume specification: ", 41 `..\`: "Invalid volume specification: ", 42 `c:\:..\`: "Invalid volume specification: ", 43 `c:\:d:\:xyzzy`: "Invalid volume specification: ", 44 `c:`: "cannot be c:", 45 `c:\`: `cannot be c:\`, 46 `c:\notexist:d:`: `The system cannot find the file specified`, 47 `c:\windows\system32\ntdll.dll:d:`: `Source 'c:\windows\system32\ntdll.dll' is not a directory`, 48 `name<:d:`: `Invalid volume specification`, 49 `name>:d:`: `Invalid volume specification`, 50 `name::d:`: `Invalid volume specification`, 51 `name":d:`: `Invalid volume specification`, 52 `name\:d:`: `Invalid volume specification`, 53 `name*:d:`: `Invalid volume specification`, 54 `name|:d:`: `Invalid volume specification`, 55 `name?:d:`: `Invalid volume specification`, 56 `name/:d:`: `Invalid volume specification`, 57 `d:\pathandmode:rw`: `Invalid volume specification`, 58 `con:d:`: `cannot be a reserved word for Windows filenames`, 59 `PRN:d:`: `cannot be a reserved word for Windows filenames`, 60 `aUx:d:`: `cannot be a reserved word for Windows filenames`, 61 `nul:d:`: `cannot be a reserved word for Windows filenames`, 62 `com1:d:`: `cannot be a reserved word for Windows filenames`, 63 `com2:d:`: `cannot be a reserved word for Windows filenames`, 64 `com3:d:`: `cannot be a reserved word for Windows filenames`, 65 `com4:d:`: `cannot be a reserved word for Windows filenames`, 66 `com5:d:`: `cannot be a reserved word for Windows filenames`, 67 `com6:d:`: `cannot be a reserved word for Windows filenames`, 68 `com7:d:`: `cannot be a reserved word for Windows filenames`, 69 `com8:d:`: `cannot be a reserved word for Windows filenames`, 70 `com9:d:`: `cannot be a reserved word for Windows filenames`, 71 `lpt1:d:`: `cannot be a reserved word for Windows filenames`, 72 `lpt2:d:`: `cannot be a reserved word for Windows filenames`, 73 `lpt3:d:`: `cannot be a reserved word for Windows filenames`, 74 `lpt4:d:`: `cannot be a reserved word for Windows filenames`, 75 `lpt5:d:`: `cannot be a reserved word for Windows filenames`, 76 `lpt6:d:`: `cannot be a reserved word for Windows filenames`, 77 `lpt7:d:`: `cannot be a reserved word for Windows filenames`, 78 `lpt8:d:`: `cannot be a reserved word for Windows filenames`, 79 `lpt9:d:`: `cannot be a reserved word for Windows filenames`, 80 } 81 82 } else { 83 valid = []string{ 84 "/home", 85 "/home:/home", 86 "/home:/something/else", 87 "/with space", 88 "/home:/with space", 89 "relative:/absolute-path", 90 "hostPath:/containerPath:ro", 91 "/hostPath:/containerPath:rw", 92 "/rw:/ro", 93 } 94 invalid = map[string]string{ 95 "": "Invalid volume specification", 96 "./": "Invalid volume destination", 97 "../": "Invalid volume destination", 98 "/:../": "Invalid volume destination", 99 "/:path": "Invalid volume destination", 100 ":": "Invalid volume specification", 101 "/tmp:": "Invalid volume destination", 102 ":test": "Invalid volume specification", 103 ":/test": "Invalid volume specification", 104 "tmp:": "Invalid volume destination", 105 ":test:": "Invalid volume specification", 106 "::": "Invalid volume specification", 107 ":::": "Invalid volume specification", 108 "/tmp:::": "Invalid volume specification", 109 ":/tmp::": "Invalid volume specification", 110 "/path:rw": "Invalid volume specification", 111 "/path:ro": "Invalid volume specification", 112 "/rw:rw": "Invalid volume specification", 113 "path:ro": "Invalid volume specification", 114 "/path:/path:sw": `invalid mode: sw`, 115 "/path:/path:rwz": `invalid mode: rwz`, 116 } 117 } 118 119 for _, path := range valid { 120 if _, err := ParseMountSpec(path, "local"); err != nil { 121 t.Fatalf("ParseMountSpec(`%q`) should succeed: error %q", path, err) 122 } 123 } 124 125 for path, expectedError := range invalid { 126 if _, err := ParseMountSpec(path, "local"); err == nil { 127 t.Fatalf("ParseMountSpec(`%q`) should have failed validation. Err %v", path, err) 128 } else { 129 if !strings.Contains(err.Error(), expectedError) { 130 t.Fatalf("ParseMountSpec(`%q`) error should contain %q, got %v", path, expectedError, err.Error()) 131 } 132 } 133 } 134 } 135 136 // testParseMountSpec is a structure used by TestParseMountSpecSplit for 137 // specifying test cases for the ParseMountSpec() function. 138 type testParseMountSpec struct { 139 bind string 140 driver string 141 expDest string 142 expSource string 143 expName string 144 expDriver string 145 expRW bool 146 fail bool 147 } 148 149 func TestParseMountSpecSplit(t *testing.T) { 150 var cases []testParseMountSpec 151 if runtime.GOOS == "windows" { 152 cases = []testParseMountSpec{ 153 {`c:\:d:`, "local", `d:`, `c:\`, ``, "", true, false}, 154 {`c:\:d:\`, "local", `d:\`, `c:\`, ``, "", true, false}, 155 // TODO Windows post TP5 - Add readonly support {`c:\:d:\:ro`, "local", `d:\`, `c:\`, ``, "", false, false}, 156 {`c:\:d:\:rw`, "local", `d:\`, `c:\`, ``, "", true, false}, 157 {`c:\:d:\:foo`, "local", `d:\`, `c:\`, ``, "", false, true}, 158 {`name:d::rw`, "local", `d:`, ``, `name`, "local", true, false}, 159 {`name:d:`, "local", `d:`, ``, `name`, "local", true, false}, 160 // TODO Windows post TP5 - Add readonly support {`name:d::ro`, "local", `d:`, ``, `name`, "local", false, false}, 161 {`name:c:`, "", ``, ``, ``, "", true, true}, 162 {`driver/name:c:`, "", ``, ``, ``, "", true, true}, 163 } 164 } else { 165 cases = []testParseMountSpec{ 166 {"/tmp:/tmp1", "", "/tmp1", "/tmp", "", "", true, false}, 167 {"/tmp:/tmp2:ro", "", "/tmp2", "/tmp", "", "", false, false}, 168 {"/tmp:/tmp3:rw", "", "/tmp3", "/tmp", "", "", true, false}, 169 {"/tmp:/tmp4:foo", "", "", "", "", "", false, true}, 170 {"name:/named1", "", "/named1", "", "name", "", true, false}, 171 {"name:/named2", "external", "/named2", "", "name", "external", true, false}, 172 {"name:/named3:ro", "local", "/named3", "", "name", "local", false, false}, 173 {"local/name:/tmp:rw", "", "/tmp", "", "local/name", "", true, false}, 174 {"/tmp:tmp", "", "", "", "", "", true, true}, 175 } 176 } 177 178 for _, c := range cases { 179 m, err := ParseMountSpec(c.bind, c.driver) 180 if c.fail { 181 if err == nil { 182 t.Fatalf("Expected error, was nil, for spec %s\n", c.bind) 183 } 184 continue 185 } 186 187 if m == nil || err != nil { 188 t.Fatalf("ParseMountSpec failed for spec %s driver %s error %v\n", c.bind, c.driver, err.Error()) 189 continue 190 } 191 192 if m.Destination != c.expDest { 193 t.Fatalf("Expected destination %s, was %s, for spec %s\n", c.expDest, m.Destination, c.bind) 194 } 195 196 if m.Source != c.expSource { 197 t.Fatalf("Expected source %s, was %s, for spec %s\n", c.expSource, m.Source, c.bind) 198 } 199 200 if m.Name != c.expName { 201 t.Fatalf("Expected name %s, was %s for spec %s\n", c.expName, m.Name, c.bind) 202 } 203 204 if m.Driver != c.expDriver { 205 t.Fatalf("Expected driver %s, was %s, for spec %s\n", c.expDriver, m.Driver, c.bind) 206 } 207 208 if m.RW != c.expRW { 209 t.Fatalf("Expected RW %v, was %v for spec %s\n", c.expRW, m.RW, c.bind) 210 } 211 } 212 }