1
2
3
4
19
20 package subpath
21
22 import (
23 "fmt"
24 "io/ioutil"
25 "os"
26 "os/exec"
27 "path/filepath"
28 "testing"
29
30 "github.com/stretchr/testify/assert"
31 )
32
33 func makeLink(link, target string) error {
34 if output, err := exec.Command("cmd", "/c", "mklink", "/D", link, target).CombinedOutput(); err != nil {
35 return fmt.Errorf("mklink failed: %v, link(%q) target(%q) output: %q", err, link, target, string(output))
36 }
37 return nil
38 }
39
40 func TestDoSafeMakeDir(t *testing.T) {
41 base, err := ioutil.TempDir("", "TestDoSafeMakeDir")
42 if err != nil {
43 t.Fatalf(err.Error())
44 }
45
46 defer os.RemoveAll(base)
47
48 testingVolumePath := filepath.Join(base, "testingVolumePath")
49 os.MkdirAll(testingVolumePath, 0755)
50 defer os.RemoveAll(testingVolumePath)
51
52 tests := []struct {
53 volumePath string
54 subPath string
55 expectError bool
56 symlinkTarget string
57 }{
58 {
59 volumePath: testingVolumePath,
60 subPath: ``,
61 expectError: true,
62 symlinkTarget: "",
63 },
64 {
65 volumePath: testingVolumePath,
66 subPath: filepath.Join(testingVolumePath, `x`),
67 expectError: false,
68 symlinkTarget: "",
69 },
70 {
71 volumePath: testingVolumePath,
72 subPath: filepath.Join(testingVolumePath, `a\b\c\d`),
73 expectError: false,
74 symlinkTarget: "",
75 },
76 {
77 volumePath: testingVolumePath,
78 subPath: filepath.Join(testingVolumePath, `symlink`),
79 expectError: false,
80 symlinkTarget: base,
81 },
82 {
83 volumePath: testingVolumePath,
84 subPath: filepath.Join(testingVolumePath, `symlink\c\d`),
85 expectError: true,
86 symlinkTarget: "",
87 },
88 {
89 volumePath: testingVolumePath,
90 subPath: filepath.Join(testingVolumePath, `symlink\y926`),
91 expectError: true,
92 symlinkTarget: "",
93 },
94 {
95 volumePath: testingVolumePath,
96 subPath: filepath.Join(testingVolumePath, `a\b\symlink`),
97 expectError: false,
98 symlinkTarget: base,
99 },
100 {
101 volumePath: testingVolumePath,
102 subPath: filepath.Join(testingVolumePath, `a\x\symlink`),
103 expectError: false,
104 symlinkTarget: filepath.Join(testingVolumePath, `a`),
105 },
106 }
107
108 for _, test := range tests {
109 if len(test.volumePath) > 0 && len(test.subPath) > 0 && len(test.symlinkTarget) > 0 {
110
111 if parent := filepath.Dir(test.subPath); parent != "." {
112 os.MkdirAll(parent, 0755)
113 }
114
115
116 linkPath := test.subPath
117 if _, err := os.Stat(linkPath); err != nil && os.IsNotExist(err) {
118 if err := makeLink(linkPath, test.symlinkTarget); err != nil {
119 t.Fatalf("unexpected error: %v", fmt.Errorf("mklink link(%q) target(%q) error: %q", linkPath, test.symlinkTarget, err))
120 }
121 }
122 }
123
124 err := doSafeMakeDir(test.subPath, test.volumePath, os.FileMode(0755))
125 if test.expectError {
126 assert.NotNil(t, err, "Expect error during doSafeMakeDir(%s, %s)", test.subPath, test.volumePath)
127 continue
128 }
129 assert.Nil(t, err, "Expect no error during doSafeMakeDir(%s, %s)", test.subPath, test.volumePath)
130 if _, err := os.Stat(test.subPath); os.IsNotExist(err) {
131 t.Errorf("subPath should exists after doSafeMakeDir(%s, %s)", test.subPath, test.volumePath)
132 }
133 }
134 }
135
136 func TestLockAndCheckSubPath(t *testing.T) {
137 base, err := ioutil.TempDir("", "TestLockAndCheckSubPath")
138 if err != nil {
139 t.Fatalf(err.Error())
140 }
141
142 defer os.RemoveAll(base)
143
144 testingVolumePath := filepath.Join(base, "testingVolumePath")
145
146 tests := []struct {
147 volumePath string
148 subPath string
149 expectedHandleCount int
150 expectError bool
151 symlinkTarget string
152 }{
153 {
154 volumePath: `c:\`,
155 subPath: ``,
156 expectedHandleCount: 0,
157 expectError: false,
158 symlinkTarget: "",
159 },
160 {
161 volumePath: ``,
162 subPath: `a`,
163 expectedHandleCount: 0,
164 expectError: false,
165 symlinkTarget: "",
166 },
167 {
168 volumePath: testingVolumePath,
169 subPath: filepath.Join(testingVolumePath, `a`),
170 expectedHandleCount: 1,
171 expectError: false,
172 symlinkTarget: "",
173 },
174 {
175 volumePath: testingVolumePath,
176 subPath: filepath.Join(testingVolumePath, `a\b\c\d`),
177 expectedHandleCount: 4,
178 expectError: false,
179 symlinkTarget: "",
180 },
181 {
182 volumePath: testingVolumePath,
183 subPath: filepath.Join(testingVolumePath, `symlink`),
184 expectedHandleCount: 0,
185 expectError: true,
186 symlinkTarget: base,
187 },
188 {
189 volumePath: testingVolumePath,
190 subPath: filepath.Join(testingVolumePath, `a\b\c\symlink`),
191 expectedHandleCount: 0,
192 expectError: true,
193 symlinkTarget: base,
194 },
195 {
196 volumePath: testingVolumePath,
197 subPath: filepath.Join(testingVolumePath, `a\b\c\d\symlink`),
198 expectedHandleCount: 2,
199 expectError: false,
200 symlinkTarget: filepath.Join(testingVolumePath, `a\b`),
201 },
202 }
203
204 for _, test := range tests {
205 if len(test.volumePath) > 0 && len(test.subPath) > 0 {
206 os.MkdirAll(test.volumePath, 0755)
207 if len(test.symlinkTarget) == 0 {
208
209 os.MkdirAll(test.subPath, 0755)
210 } else {
211
212 if parent := filepath.Dir(test.subPath); parent != "." {
213 os.MkdirAll(parent, 0755)
214 }
215
216
217 linkPath := test.subPath
218 if _, err := os.Stat(linkPath); err != nil && os.IsNotExist(err) {
219 if err := makeLink(linkPath, test.symlinkTarget); err != nil {
220 t.Fatalf("unexpected error: %v", fmt.Errorf("mklink link(%q) target(%q) error: %q", linkPath, test.symlinkTarget, err))
221 }
222 }
223 }
224 }
225
226 fileHandles, err := lockAndCheckSubPath(test.volumePath, test.subPath)
227 unlockPath(fileHandles)
228 assert.Equal(t, test.expectedHandleCount, len(fileHandles))
229 if test.expectError {
230 assert.NotNil(t, err, "Expect error during LockAndCheckSubPath(%s, %s)", test.volumePath, test.subPath)
231 continue
232 }
233 assert.Nil(t, err, "Expect no error during LockAndCheckSubPath(%s, %s)", test.volumePath, test.subPath)
234 }
235
236
237 assert.Nil(t, os.RemoveAll(testingVolumePath), "Expect no error during remove dir %s", testingVolumePath)
238 }
239
240 func TestLockAndCheckSubPathWithoutSymlink(t *testing.T) {
241 base, err := ioutil.TempDir("", "TestLockAndCheckSubPathWithoutSymlink")
242 if err != nil {
243 t.Fatalf(err.Error())
244 }
245
246 defer os.RemoveAll(base)
247
248 testingVolumePath := filepath.Join(base, "testingVolumePath")
249
250 tests := []struct {
251 volumePath string
252 subPath string
253 expectedHandleCount int
254 expectError bool
255 symlinkTarget string
256 }{
257 {
258 volumePath: `c:\`,
259 subPath: ``,
260 expectedHandleCount: 0,
261 expectError: false,
262 symlinkTarget: "",
263 },
264 {
265 volumePath: ``,
266 subPath: `a`,
267 expectedHandleCount: 0,
268 expectError: false,
269 symlinkTarget: "",
270 },
271 {
272 volumePath: testingVolumePath,
273 subPath: filepath.Join(testingVolumePath, `a`),
274 expectedHandleCount: 1,
275 expectError: false,
276 symlinkTarget: "",
277 },
278 {
279 volumePath: testingVolumePath,
280 subPath: filepath.Join(testingVolumePath, `a\b\c\d`),
281 expectedHandleCount: 4,
282 expectError: false,
283 symlinkTarget: "",
284 },
285 {
286 volumePath: testingVolumePath,
287 subPath: filepath.Join(testingVolumePath, `symlink`),
288 expectedHandleCount: 1,
289 expectError: true,
290 symlinkTarget: base,
291 },
292 {
293 volumePath: testingVolumePath,
294 subPath: filepath.Join(testingVolumePath, `a\b\c\symlink`),
295 expectedHandleCount: 4,
296 expectError: true,
297 symlinkTarget: base,
298 },
299 {
300 volumePath: testingVolumePath,
301 subPath: filepath.Join(testingVolumePath, `a\b\c\d\symlink`),
302 expectedHandleCount: 5,
303 expectError: true,
304 symlinkTarget: filepath.Join(testingVolumePath, `a\b`),
305 },
306 }
307
308 for _, test := range tests {
309 if len(test.volumePath) > 0 && len(test.subPath) > 0 {
310 os.MkdirAll(test.volumePath, 0755)
311 if len(test.symlinkTarget) == 0 {
312
313 os.MkdirAll(test.subPath, 0755)
314 } else {
315
316 if parent := filepath.Dir(test.subPath); parent != "." {
317 os.MkdirAll(parent, 0755)
318 }
319
320
321 linkPath := test.subPath
322 if _, err := os.Stat(linkPath); err != nil && os.IsNotExist(err) {
323 if err := makeLink(linkPath, test.symlinkTarget); err != nil {
324 t.Fatalf("unexpected error: %v", fmt.Errorf("mklink link(%q) target(%q) error: %q", linkPath, test.symlinkTarget, err))
325 }
326 }
327 }
328 }
329
330 fileHandles, err := lockAndCheckSubPathWithoutSymlink(test.volumePath, test.subPath)
331 unlockPath(fileHandles)
332 assert.Equal(t, test.expectedHandleCount, len(fileHandles))
333 if test.expectError {
334 assert.NotNil(t, err, "Expect error during LockAndCheckSubPath(%s, %s)", test.volumePath, test.subPath)
335 continue
336 }
337 assert.Nil(t, err, "Expect no error during LockAndCheckSubPath(%s, %s)", test.volumePath, test.subPath)
338 }
339
340
341 assert.Nil(t, os.RemoveAll(testingVolumePath), "Expect no error during remove dir %s", testingVolumePath)
342 }
343
344 func TestFindExistingPrefix(t *testing.T) {
345 base, err := ioutil.TempDir("", "TestFindExistingPrefix")
346 if err != nil {
347 t.Fatalf(err.Error())
348 }
349
350 defer os.RemoveAll(base)
351
352 testingVolumePath := filepath.Join(base, "testingVolumePath")
353
354 tests := []struct {
355 base string
356 pathname string
357 expectError bool
358 expectedExistingPath string
359 expectedToCreateDirs []string
360 createSubPathBeforeTest bool
361 }{
362 {
363 base: `c:\tmp\a`,
364 pathname: `c:\tmp\b`,
365 expectError: true,
366 expectedExistingPath: "",
367 expectedToCreateDirs: []string{},
368 createSubPathBeforeTest: false,
369 },
370 {
371 base: ``,
372 pathname: `c:\tmp\b`,
373 expectError: true,
374 expectedExistingPath: "",
375 expectedToCreateDirs: []string{},
376 createSubPathBeforeTest: false,
377 },
378 {
379 base: `c:\tmp\a`,
380 pathname: `d:\tmp\b`,
381 expectError: true,
382 expectedExistingPath: "",
383 expectedToCreateDirs: []string{},
384 createSubPathBeforeTest: false,
385 },
386 {
387 base: testingVolumePath,
388 pathname: testingVolumePath,
389 expectError: false,
390 expectedExistingPath: testingVolumePath,
391 expectedToCreateDirs: []string{},
392 createSubPathBeforeTest: false,
393 },
394 {
395 base: testingVolumePath,
396 pathname: filepath.Join(testingVolumePath, `a\b`),
397 expectError: false,
398 expectedExistingPath: filepath.Join(testingVolumePath, `a\b`),
399 expectedToCreateDirs: []string{},
400 createSubPathBeforeTest: true,
401 },
402 {
403 base: testingVolumePath,
404 pathname: filepath.Join(testingVolumePath, `a\b\c\`),
405 expectError: false,
406 expectedExistingPath: filepath.Join(testingVolumePath, `a\b`),
407 expectedToCreateDirs: []string{`c`},
408 createSubPathBeforeTest: false,
409 },
410 {
411 base: testingVolumePath,
412 pathname: filepath.Join(testingVolumePath, `a\b\c\d`),
413 expectError: false,
414 expectedExistingPath: filepath.Join(testingVolumePath, `a\b`),
415 expectedToCreateDirs: []string{`c`, `d`},
416 createSubPathBeforeTest: false,
417 },
418 }
419
420 for _, test := range tests {
421 if test.createSubPathBeforeTest {
422 os.MkdirAll(test.pathname, 0755)
423 }
424
425 existingPath, toCreate, err := findExistingPrefix(test.base, test.pathname)
426 if test.expectError {
427 assert.NotNil(t, err, "Expect error during findExistingPrefix(%s, %s)", test.base, test.pathname)
428 continue
429 }
430 assert.Nil(t, err, "Expect no error during findExistingPrefix(%s, %s)", test.base, test.pathname)
431
432 assert.Equal(t, test.expectedExistingPath, existingPath, "Expect result not equal with findExistingPrefix(%s, %s) return: %q, expected: %q",
433 test.base, test.pathname, existingPath, test.expectedExistingPath)
434
435 assert.Equal(t, test.expectedToCreateDirs, toCreate, "Expect result not equal with findExistingPrefix(%s, %s) return: %q, expected: %q",
436 test.base, test.pathname, toCreate, test.expectedToCreateDirs)
437
438 }
439
440 assert.Nil(t, os.RemoveAll(testingVolumePath), "Expect no error during remove dir %s", testingVolumePath)
441 }
442
443 func TestIsDriveLetterorEmptyPath(t *testing.T) {
444 tests := []struct {
445 path string
446 expectedResult bool
447 }{
448 {
449 path: ``,
450 expectedResult: true,
451 },
452 {
453 path: `\tmp`,
454 expectedResult: false,
455 },
456 {
457 path: `c:\tmp`,
458 expectedResult: false,
459 },
460 {
461 path: `c:\\`,
462 expectedResult: true,
463 },
464 {
465 path: `c:\`,
466 expectedResult: true,
467 },
468 {
469 path: `c:`,
470 expectedResult: true,
471 },
472 }
473
474 for _, test := range tests {
475 result := isDriveLetterorEmptyPath(test.path)
476 assert.Equal(t, test.expectedResult, result, "Expect result not equal with isDriveLetterorEmptyPath(%s) return: %t, expected: %t",
477 test.path, result, test.expectedResult)
478 }
479 }
480
View as plain text