• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2014 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package pathtools
16
17import (
18	"os"
19	"path/filepath"
20	"reflect"
21	"testing"
22)
23
24var pwd, _ = os.Getwd()
25
26type globTestCase struct {
27	pattern  string
28	matches  []string
29	excludes []string
30	deps     []string
31	err      error
32}
33
34var globTestCases = []globTestCase{
35	// Current directory tests
36	{
37		pattern: "*",
38		matches: []string{"a/", "b/", "c/", "d.ext", "e.ext"},
39		deps:    []string{"."},
40	},
41	{
42		pattern: "*.ext",
43		matches: []string{"d.ext", "e.ext"},
44		deps:    []string{"."},
45	},
46	{
47		pattern: "*/a",
48		matches: []string{"a/a/", "b/a"},
49		deps:    []string{".", "a", "b", "c"},
50	},
51	{
52		pattern: "*/*/a",
53		matches: []string{"a/a/a"},
54		deps:    []string{".", "a", "b", "c", "a/a", "a/b", "c/f", "c/g", "c/h"},
55	},
56	{
57		pattern: "*/a/a",
58		matches: []string{"a/a/a"},
59		deps:    []string{".", "a", "b", "c", "a/a"},
60	},
61	{
62		pattern: "c/*/?",
63		matches: []string{"c/h/h"},
64		deps:    []string{"c", "c/f", "c/g", "c/h"},
65	},
66	{
67		pattern: "c/*/[gh]*",
68		matches: []string{"c/g/g.ext", "c/h/h"},
69		deps:    []string{"c", "c/f", "c/g", "c/h"},
70	},
71	{
72		pattern: "c/*/[fgh]*",
73		matches: []string{"c/f/f.ext", "c/g/g.ext", "c/h/h"},
74		deps:    []string{"c", "c/f", "c/g", "c/h"},
75	},
76	{
77		pattern: "c/*/[f-h]*",
78		matches: []string{"c/f/f.ext", "c/g/g.ext", "c/h/h"},
79		deps:    []string{"c", "c/f", "c/g", "c/h"},
80	},
81	// ./ directory tests
82	{
83		pattern: "./*",
84		matches: []string{"a/", "b/", "c/", "d.ext", "e.ext"},
85		deps:    []string{"."},
86	},
87	{
88		pattern: "./*.ext",
89		matches: []string{"d.ext", "e.ext"},
90		deps:    []string{"."},
91	},
92	{
93		pattern: "./*/a",
94		matches: []string{"a/a/", "b/a"},
95		deps:    []string{".", "a", "b", "c"},
96	},
97	{
98		pattern: "./[ac]/a",
99		matches: []string{"a/a/"},
100		deps:    []string{".", "a", "c"},
101	},
102
103	// subdirectory tests
104	{
105		pattern: "c/*/*.ext",
106		matches: []string{"c/f/f.ext", "c/g/g.ext"},
107		deps:    []string{"c", "c/f", "c/g", "c/h"},
108	},
109	{
110		pattern: "a/*/a",
111		matches: []string{"a/a/a"},
112		deps:    []string{"a", "a/a", "a/b"},
113	},
114
115	// absolute tests
116	{
117		pattern: filepath.Join(pwd, "testdata/glob/c/*/*.ext"),
118		matches: []string{
119			filepath.Join(pwd, "testdata/glob/c/f/f.ext"),
120			filepath.Join(pwd, "testdata/glob/c/g/g.ext"),
121		},
122		deps: []string{
123			filepath.Join(pwd, "testdata/glob/c"),
124			filepath.Join(pwd, "testdata/glob/c/f"),
125			filepath.Join(pwd, "testdata/glob/c/g"),
126			filepath.Join(pwd, "testdata/glob/c/h"),
127		},
128	},
129
130	// no-wild tests
131	{
132		pattern: "a",
133		matches: []string{"a/"},
134		deps:    []string{"a"},
135	},
136	{
137		pattern: "a/a",
138		matches: []string{"a/a/"},
139		deps:    []string{"a/a"},
140	},
141
142	// clean tests
143	{
144		pattern: "./c/*/*.ext",
145		matches: []string{"c/f/f.ext", "c/g/g.ext"},
146		deps:    []string{"c", "c/f", "c/g", "c/h"},
147	},
148	{
149		pattern: "c/../c/*/*.ext",
150		matches: []string{"c/f/f.ext", "c/g/g.ext"},
151		deps:    []string{"c", "c/f", "c/g", "c/h"},
152	},
153
154	// recursive tests
155	{
156		pattern: "**/a",
157		matches: []string{"a/", "a/a/", "a/a/a", "b/a"},
158		deps:    []string{".", "a", "a/a", "a/b", "b", "c", "c/f", "c/g", "c/h"},
159	},
160	{
161		pattern: "a/**/a",
162		matches: []string{"a/a/", "a/a/a"},
163		deps:    []string{"a", "a/a", "a/b"},
164	},
165	{
166		pattern: "a/**/*",
167		matches: []string{"a/a/", "a/b/", "a/a/a", "a/b/b"},
168		deps:    []string{"a", "a/a", "a/b"},
169	},
170
171	// absolute recursive tests
172	{
173		pattern: filepath.Join(pwd, "testdata/glob/**/*.ext"),
174		matches: []string{
175			filepath.Join(pwd, "testdata/glob/d.ext"),
176			filepath.Join(pwd, "testdata/glob/e.ext"),
177			filepath.Join(pwd, "testdata/glob/c/f/f.ext"),
178			filepath.Join(pwd, "testdata/glob/c/g/g.ext"),
179		},
180		deps: []string{
181			filepath.Join(pwd, "testdata/glob"),
182			filepath.Join(pwd, "testdata/glob/a"),
183			filepath.Join(pwd, "testdata/glob/a/a"),
184			filepath.Join(pwd, "testdata/glob/a/b"),
185			filepath.Join(pwd, "testdata/glob/b"),
186			filepath.Join(pwd, "testdata/glob/c"),
187			filepath.Join(pwd, "testdata/glob/c/f"),
188			filepath.Join(pwd, "testdata/glob/c/g"),
189			filepath.Join(pwd, "testdata/glob/c/h"),
190		},
191	},
192
193	// recursive error tests
194	{
195		pattern: "**/**/*",
196		err:     GlobMultipleRecursiveErr,
197	},
198	{
199		pattern: "a/**/**/*",
200		err:     GlobMultipleRecursiveErr,
201	},
202	{
203		pattern: "**/a/**/*",
204		err:     GlobMultipleRecursiveErr,
205	},
206	{
207		pattern: "**/**/a/*",
208		err:     GlobMultipleRecursiveErr,
209	},
210	{
211		pattern: "a/**",
212		err:     GlobLastRecursiveErr,
213	},
214	{
215		pattern: "**/**",
216		err:     GlobLastRecursiveErr,
217	},
218
219	// exclude tests
220	{
221		pattern:  "*.ext",
222		excludes: []string{"d.ext"},
223		matches:  []string{"e.ext"},
224		deps:     []string{"."},
225	},
226	{
227		pattern:  "*/*",
228		excludes: []string{"a/b"},
229		matches:  []string{"a/a/", "b/a", "c/c", "c/f/", "c/g/", "c/h/"},
230		deps:     []string{".", "a", "b", "c"},
231	},
232	{
233		pattern:  "*/*",
234		excludes: []string{"a/b", "c/c"},
235		matches:  []string{"a/a/", "b/a", "c/f/", "c/g/", "c/h/"},
236		deps:     []string{".", "a", "b", "c"},
237	},
238	{
239		pattern:  "*/*",
240		excludes: []string{"c/*", "*/a"},
241		matches:  []string{"a/b/"},
242		deps:     []string{".", "a", "b", "c"},
243	},
244	{
245		pattern:  "*/*",
246		excludes: []string{"*/*"},
247		matches:  nil,
248		deps:     []string{".", "a", "b", "c"},
249	},
250
251	// absolute exclude tests
252	{
253		pattern:  filepath.Join(pwd, "testdata/glob/c/*/*.ext"),
254		excludes: []string{filepath.Join(pwd, "testdata/glob/c/*/f.ext")},
255		matches: []string{
256			filepath.Join(pwd, "testdata/glob/c/g/g.ext"),
257		},
258		deps: []string{
259			filepath.Join(pwd, "testdata/glob/c"),
260			filepath.Join(pwd, "testdata/glob/c/f"),
261			filepath.Join(pwd, "testdata/glob/c/g"),
262			filepath.Join(pwd, "testdata/glob/c/h"),
263		},
264	},
265	{
266		pattern:  filepath.Join(pwd, "testdata/glob/c/*/*.ext"),
267		excludes: []string{filepath.Join(pwd, "testdata/glob/c/f/*.ext")},
268		matches: []string{
269			filepath.Join(pwd, "testdata/glob/c/g/g.ext"),
270		},
271		deps: []string{
272			filepath.Join(pwd, "testdata/glob/c"),
273			filepath.Join(pwd, "testdata/glob/c/f"),
274			filepath.Join(pwd, "testdata/glob/c/g"),
275			filepath.Join(pwd, "testdata/glob/c/h"),
276		},
277	},
278
279	// recursive exclude tests
280	{
281		pattern:  "*.ext",
282		excludes: []string{"**/*.ext"},
283		matches:  nil,
284		deps:     []string{"."},
285	},
286	{
287		pattern:  "*/*",
288		excludes: []string{"**/b"},
289		matches:  []string{"a/a/", "b/a", "c/c", "c/f/", "c/g/", "c/h/"},
290		deps:     []string{".", "a", "b", "c"},
291	},
292	{
293		pattern:  "*/*",
294		excludes: []string{"a/**/*"},
295		matches:  []string{"b/a", "c/c", "c/f/", "c/g/", "c/h/"},
296		deps:     []string{".", "a", "b", "c"},
297	},
298	{
299		pattern:  "**/*",
300		excludes: []string{"**/*"},
301		matches:  nil,
302		deps:     []string{".", "a", "a/a", "a/b", "b", "c", "c/f", "c/g", "c/h"},
303	},
304	{
305		pattern:  "*/*/*",
306		excludes: []string{"a/**/a"},
307		matches:  []string{"a/b/b", "c/f/f.ext", "c/g/g.ext", "c/h/h"},
308		deps:     []string{".", "a", "b", "c", "a/a", "a/b", "c/f", "c/g", "c/h"},
309	},
310	{
311		pattern:  "*/*/*",
312		excludes: []string{"**/a"},
313		matches:  []string{"a/b/b", "c/f/f.ext", "c/g/g.ext", "c/h/h"},
314		deps:     []string{".", "a", "b", "c", "a/a", "a/b", "c/f", "c/g", "c/h"},
315	},
316	{
317		pattern:  "c/*/*.ext",
318		excludes: []string{"c/**/f.ext"},
319		matches:  []string{"c/g/g.ext"},
320		deps:     []string{"c", "c/f", "c/g", "c/h"},
321	},
322
323	// absoulte recursive exclude tests
324	{
325		pattern:  filepath.Join(pwd, "testdata/glob/c/*/*.ext"),
326		excludes: []string{filepath.Join(pwd, "testdata/glob/**/f.ext")},
327		matches: []string{
328			filepath.Join(pwd, "testdata/glob/c/g/g.ext"),
329		},
330		deps: []string{
331			filepath.Join(pwd, "testdata/glob/c"),
332			filepath.Join(pwd, "testdata/glob/c/f"),
333			filepath.Join(pwd, "testdata/glob/c/g"),
334			filepath.Join(pwd, "testdata/glob/c/h"),
335		},
336	},
337
338	// clean exclude tests
339	{
340		pattern:  "./c/*/*.ext",
341		excludes: []string{"./c/*/f.ext"},
342		matches:  []string{"c/g/g.ext"},
343		deps:     []string{"c", "c/f", "c/g", "c/h"},
344	},
345	{
346		pattern:  "c/*/*.ext",
347		excludes: []string{"./c/*/f.ext"},
348		matches:  []string{"c/g/g.ext"},
349		deps:     []string{"c", "c/f", "c/g", "c/h"},
350	},
351	{
352		pattern:  "./c/*/*.ext",
353		excludes: []string{"c/*/f.ext"},
354		matches:  []string{"c/g/g.ext"},
355		deps:     []string{"c", "c/f", "c/g", "c/h"},
356	},
357
358	// non-existant non-wild path tests
359	{
360		pattern: "d/*",
361		matches: nil,
362		deps:    []string{"."},
363	},
364	{
365		pattern: "d",
366		matches: nil,
367		deps:    []string{"."},
368	},
369	{
370		pattern: "a/d/*",
371		matches: nil,
372		deps:    []string{"a"},
373	},
374	{
375		pattern: "a/d",
376		matches: nil,
377		deps:    []string{"a"},
378	},
379	{
380		pattern: "a/a/d/*",
381		matches: nil,
382		deps:    []string{"a/a"},
383	},
384	{
385		pattern: "a/a/d",
386		matches: nil,
387		deps:    []string{"a/a"},
388	},
389	{
390		pattern: "a/d/a/*",
391		matches: nil,
392		deps:    []string{"a"},
393	},
394	{
395		pattern: "a/d/a",
396		matches: nil,
397		deps:    []string{"a"},
398	},
399	{
400		pattern: "a/d/a/*/a",
401		matches: nil,
402		deps:    []string{"a"},
403	},
404	{
405		pattern: "a/d/a/**/a",
406		matches: nil,
407		deps:    []string{"a"},
408	},
409
410	// recursive exclude error tests
411	{
412		pattern:  "**/*",
413		excludes: []string{"**/**/*"},
414		err:      GlobMultipleRecursiveErr,
415	},
416	{
417		pattern:  "**/*",
418		excludes: []string{"a/**/**/*"},
419		err:      GlobMultipleRecursiveErr,
420	},
421	{
422		pattern:  "**/*",
423		excludes: []string{"**/a/**/*"},
424		err:      GlobMultipleRecursiveErr,
425	},
426	{
427		pattern:  "**/*",
428		excludes: []string{"**/**/a/*"},
429		err:      GlobMultipleRecursiveErr,
430	},
431	{
432		pattern:  "**/*",
433		excludes: []string{"a/**"},
434		err:      GlobLastRecursiveErr,
435	},
436	{
437		pattern:  "**/*",
438		excludes: []string{"**/**"},
439		err:      GlobLastRecursiveErr,
440	},
441
442	// If names are excluded by default, but referenced explicitly, they should return results
443	{
444		pattern: ".test/*",
445		matches: []string{".test/a"},
446		deps:    []string{".test"},
447	},
448	{
449		pattern: ".t*/a",
450		matches: []string{".test/a"},
451		deps:    []string{".", ".test"},
452	},
453	{
454		pattern: ".*/.*",
455		matches: []string{".test/.ing"},
456		deps:    []string{".", ".test"},
457	},
458	{
459		pattern: ".t*",
460		matches: []string{".test/", ".testing"},
461		deps:    []string{"."},
462	},
463}
464
465func TestMockGlob(t *testing.T) {
466	files := []string{
467		"a/a/a",
468		"a/b/b",
469		"b/a",
470		"c/c",
471		"c/f/f.ext",
472		"c/g/g.ext",
473		"c/h/h",
474		"d.ext",
475		"e.ext",
476		".test/a",
477		".testing",
478		".test/.ing",
479	}
480
481	mockFiles := make(map[string][]byte)
482
483	for _, f := range files {
484		mockFiles[f] = nil
485		mockFiles[filepath.Join(pwd, "testdata/glob", f)] = nil
486	}
487
488	mock := MockFs(mockFiles)
489
490	for _, testCase := range globTestCases {
491		t.Run(testCase.pattern, func(t *testing.T) {
492			testGlob(t, mock, testCase, FollowSymlinks)
493		})
494	}
495}
496
497func TestGlob(t *testing.T) {
498	os.Chdir("testdata/glob")
499	defer os.Chdir("../..")
500	for _, testCase := range globTestCases {
501		t.Run(testCase.pattern, func(t *testing.T) {
502			testGlob(t, OsFs, testCase, FollowSymlinks)
503		})
504	}
505}
506
507var globEscapeTestCases = []globTestCase{
508	{
509		pattern: `**/*`,
510		matches: []string{`*`, `**/`, `?`, `a/`, `b`, `**/*`, `**/a`, `**/b/`, `**/b/b`, `a/a`},
511		deps:    []string{`.`, `**`, `**/b`, `a`},
512	},
513	{
514		pattern: `**/\*`,
515		matches: []string{`*`, `**/*`},
516		deps:    []string{`.`, `**`, `**/b`, `a`},
517	},
518	{
519		pattern: `\*\*/*`,
520		matches: []string{`**/*`, `**/a`, `**/b/`},
521		deps:    []string{`.`, `**`},
522	},
523	{
524		pattern: `\*\*/**/*`,
525		matches: []string{`**/*`, `**/a`, `**/b/`, `**/b/b`},
526		deps:    []string{`.`, `**`, `**/b`},
527	},
528}
529
530func TestMockGlobEscapes(t *testing.T) {
531	files := []string{
532		`*`,
533		`**/*`,
534		`**/a`,
535		`**/b/b`,
536		`?`,
537		`a/a`,
538		`b`,
539	}
540
541	mockFiles := make(map[string][]byte)
542
543	for _, f := range files {
544		mockFiles[f] = nil
545	}
546
547	mock := MockFs(mockFiles)
548
549	for _, testCase := range globEscapeTestCases {
550		t.Run(testCase.pattern, func(t *testing.T) {
551			testGlob(t, mock, testCase, FollowSymlinks)
552		})
553	}
554
555}
556
557func TestGlobEscapes(t *testing.T) {
558	os.Chdir("testdata/escapes")
559	defer os.Chdir("../..")
560	for _, testCase := range globEscapeTestCases {
561		t.Run(testCase.pattern, func(t *testing.T) {
562			testGlob(t, OsFs, testCase, FollowSymlinks)
563		})
564	}
565
566}
567
568var globSymlinkTestCases = []globTestCase{
569	{
570		pattern: `**/*`,
571		matches: []string{"a/", "b/", "c/", "d/", "e", "a/a/", "a/a/a", "b/a/", "b/a/a", "c/a", "d/a"},
572		deps:    []string{".", "a", "a/a", "b", "b/a", "c", "d"},
573	},
574	{
575		pattern: `b/**/*`,
576		matches: []string{"b/a/", "b/a/a"},
577		deps:    []string{"b", "b/a"},
578	},
579}
580
581func TestMockGlobSymlinks(t *testing.T) {
582	files := []string{
583		"a/a/a",
584		"b -> a",
585		"c -> a/a",
586		"d -> c",
587		"e -> a/a/a",
588	}
589
590	mockFiles := make(map[string][]byte)
591
592	for _, f := range files {
593		mockFiles[f] = nil
594	}
595
596	mock := MockFs(mockFiles)
597
598	for _, testCase := range globSymlinkTestCases {
599		t.Run(testCase.pattern, func(t *testing.T) {
600			testGlob(t, mock, testCase, FollowSymlinks)
601		})
602	}
603}
604
605func TestGlobSymlinks(t *testing.T) {
606	os.Chdir("testdata/symlinks")
607	defer os.Chdir("../..")
608
609	for _, testCase := range globSymlinkTestCases {
610		t.Run(testCase.pattern, func(t *testing.T) {
611			testGlob(t, OsFs, testCase, FollowSymlinks)
612		})
613	}
614}
615
616var globDontFollowSymlinkTestCases = []globTestCase{
617	{
618		pattern: `**/*`,
619		matches: []string{"a/", "b", "c", "d", "e", "a/a/", "a/a/a"},
620		deps:    []string{".", "a", "a/a"},
621	},
622	{
623		pattern: `b/**/*`,
624		matches: []string{"b/a/", "b/a/a"},
625		deps:    []string{"b", "b/a"},
626	},
627}
628
629func TestMockGlobDontFollowSymlinks(t *testing.T) {
630	files := []string{
631		"a/a/a",
632		"b -> a",
633		"c -> a/a",
634		"d -> c",
635		"e -> a/a/a",
636	}
637
638	mockFiles := make(map[string][]byte)
639
640	for _, f := range files {
641		mockFiles[f] = nil
642	}
643
644	mock := MockFs(mockFiles)
645
646	for _, testCase := range globDontFollowSymlinkTestCases {
647		t.Run(testCase.pattern, func(t *testing.T) {
648			testGlob(t, mock, testCase, DontFollowSymlinks)
649		})
650	}
651}
652
653func TestGlobDontFollowSymlinks(t *testing.T) {
654	os.Chdir("testdata/symlinks")
655	defer os.Chdir("../..")
656
657	for _, testCase := range globDontFollowSymlinkTestCases {
658		t.Run(testCase.pattern, func(t *testing.T) {
659			testGlob(t, OsFs, testCase, DontFollowSymlinks)
660		})
661	}
662}
663
664var globDontFollowDanglingSymlinkTestCases = []globTestCase{
665	{
666		pattern: `**/*`,
667		matches: []string{"a/", "b", "c", "d", "dangling", "e", "f", "a/a/", "a/a/a", "a/a/f"},
668		deps:    []string{".", "a", "a/a"},
669	},
670	{
671		pattern: `dangling`,
672		matches: []string{"dangling"},
673		deps:    []string{"dangling"},
674	},
675}
676
677func TestMockGlobDontFollowDanglingSymlinks(t *testing.T) {
678	files := []string{
679		"a/a/a",
680		"a/a/f -> ../../f",
681		"b -> a",
682		"c -> a/a",
683		"d -> c",
684		"e -> a/a/a",
685		"f",
686		"dangling -> missing",
687	}
688
689	mockFiles := make(map[string][]byte)
690
691	for _, f := range files {
692		mockFiles[f] = nil
693	}
694
695	mock := MockFs(mockFiles)
696
697	for _, testCase := range globDontFollowDanglingSymlinkTestCases {
698		t.Run(testCase.pattern, func(t *testing.T) {
699			testGlob(t, mock, testCase, DontFollowSymlinks)
700		})
701	}
702}
703
704func TestGlobDontFollowDanglingSymlinks(t *testing.T) {
705	os.Chdir("testdata/dangling")
706	defer os.Chdir("../..")
707
708	for _, testCase := range globDontFollowDanglingSymlinkTestCases {
709		t.Run(testCase.pattern, func(t *testing.T) {
710			testGlob(t, OsFs, testCase, DontFollowSymlinks)
711		})
712	}
713}
714
715func testGlob(t *testing.T, fs FileSystem, testCase globTestCase, follow ShouldFollowSymlinks) {
716	t.Helper()
717	matches, deps, err := fs.Glob(testCase.pattern, testCase.excludes, follow)
718	if err != testCase.err {
719		if err == nil {
720			t.Fatalf("missing error: %s", testCase.err)
721		} else {
722			t.Fatalf("error: %s", err)
723		}
724		return
725	}
726
727	if !reflect.DeepEqual(matches, testCase.matches) {
728		t.Errorf("incorrect matches list:")
729		t.Errorf(" pattern: %q", testCase.pattern)
730		if testCase.excludes != nil {
731			t.Errorf("excludes: %q", testCase.excludes)
732		}
733		t.Errorf("     got: %#v", matches)
734		t.Errorf("expected: %#v", testCase.matches)
735	}
736	if !reflect.DeepEqual(deps, testCase.deps) {
737		t.Errorf("incorrect deps list:")
738		t.Errorf(" pattern: %q", testCase.pattern)
739		if testCase.excludes != nil {
740			t.Errorf("excludes: %q", testCase.excludes)
741		}
742		t.Errorf("     got: %#v", deps)
743		t.Errorf("expected: %#v", testCase.deps)
744	}
745}
746
747func TestMatch(t *testing.T) {
748	testCases := []struct {
749		pattern, name string
750		match         bool
751	}{
752		{"a/*", "b/", false},
753		{"a/*", "b/a", false},
754		{"a/*", "b/b/", false},
755		{"a/*", "b/b/c", false},
756		{"a/**/*", "b/", false},
757		{"a/**/*", "b/a", false},
758		{"a/**/*", "b/b/", false},
759		{"a/**/*", "b/b/c", false},
760
761		{"a/*", "a/", false},
762		{"a/*", "a/a", true},
763		{"a/*", "a/b/", false},
764		{"a/*", "a/b/c", false},
765
766		{"a/*/", "a/", false},
767		{"a/*/", "a/a", false},
768		{"a/*/", "a/b/", true},
769		{"a/*/", "a/b/c", false},
770
771		{"a/**/*", "a/", false},
772		{"a/**/*", "a/a", true},
773		{"a/**/*", "a/b/", false},
774		{"a/**/*", "a/b/c", true},
775
776		{"a/**/*/", "a/", false},
777		{"a/**/*/", "a/a", false},
778		{"a/**/*/", "a/b/", true},
779		{"a/**/*/", "a/b/c", false},
780
781		{`a/\*\*/\*`, `a/**/*`, true},
782		{`a/\*\*/\*`, `a/a/*`, false},
783		{`a/\*\*/\*`, `a/**/a`, false},
784		{`a/\*\*/\*`, `a/a/a`, false},
785
786		{`a/**/\*`, `a/**/*`, true},
787		{`a/**/\*`, `a/a/*`, true},
788		{`a/**/\*`, `a/**/a`, false},
789		{`a/**/\*`, `a/a/a`, false},
790
791		{`a/\*\*/*`, `a/**/*`, true},
792		{`a/\*\*/*`, `a/a/*`, false},
793		{`a/\*\*/*`, `a/**/a`, true},
794		{`a/\*\*/*`, `a/a/a`, false},
795
796		{`*/**/a`, `a/a/a`, true},
797		{`*/**/a`, `*/a/a`, true},
798		{`*/**/a`, `a/**/a`, true},
799		{`*/**/a`, `*/**/a`, true},
800
801		{`\*/\*\*/a`, `a/a/a`, false},
802		{`\*/\*\*/a`, `*/a/a`, false},
803		{`\*/\*\*/a`, `a/**/a`, false},
804		{`\*/\*\*/a`, `*/**/a`, true},
805
806		{`a/?`, `a/?`, true},
807		{`a/?`, `a/a`, true},
808		{`a/\?`, `a/?`, true},
809		{`a/\?`, `a/a`, false},
810
811		{`a/?`, `a/?`, true},
812		{`a/?`, `a/a`, true},
813		{`a/\?`, `a/?`, true},
814		{`a/\?`, `a/a`, false},
815
816		{`a/[a-c]`, `a/b`, true},
817		{`a/[abc]`, `a/b`, true},
818
819		{`a/\[abc]`, `a/b`, false},
820		{`a/\[abc]`, `a/[abc]`, true},
821
822		{`a/\[abc\]`, `a/b`, false},
823		{`a/\[abc\]`, `a/[abc]`, true},
824
825		{`a/?`, `a/?`, true},
826		{`a/?`, `a/a`, true},
827		{`a/\?`, `a/?`, true},
828		{`a/\?`, `a/a`, false},
829	}
830
831	for _, test := range testCases {
832		t.Run(test.pattern+","+test.name, func(t *testing.T) {
833			match, err := Match(test.pattern, test.name)
834			if err != nil {
835				t.Fatal(err)
836			}
837			if match != test.match {
838				t.Errorf("want: %v, got %v", test.match, match)
839			}
840		})
841	}
842}
843