1
// http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test
3
// TODO: Some of these tests do very bad things with backslashes, and will
4
// most likely fail badly on windows. They should probably be skipped.
6
var tap = require("tap")
7
, globalBefore = Object.keys(global)
9
, files = [ "a", "b", "c", "d", "abc"
10
, "abd", "abe", "bb", "bcd"
11
, "ca", "cb", "dd", "de"
12
, "bdir/", "bdir/cfile"]
13
, next = files.concat([ "a-b", "aXb"
18
[ "http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test"
19
, ["a*", ["a", "abc", "abd", "abe"]]
20
, ["X*", ["X*"], {nonull: true}]
22
// allow null glob expansion
25
// isaacs: Slightly different than bash/sh/ksh
26
// \\* is not un-escaped to literal "*" in a failed match,
27
// but it does make it get treated as a literal star
28
, ["\\*", ["\\*"], {nonull: true}]
29
, ["\\**", ["\\**"], {nonull: true}]
30
, ["\\*\\*", ["\\*\\*"], {nonull: true}]
33
, ["c*", ["c", "ca", "cb"]]
36
, ["\\.\\./*/", ["\\.\\./*/"], {nonull: true}]
37
, ["s/\\..*//", ["s/\\..*//"], {nonull: true}]
39
, "legendary larry crashes bashes"
40
, ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"
41
, ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"], {nonull: true}]
42
, ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"
43
, ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"], {nonull: true}]
46
, ["[a-c]b*", ["abc", "abd", "abe", "bb", "cb"]]
47
, ["[a-y]*[^c]", ["abd", "abe", "bb", "bcd",
48
"bdir/", "ca", "cb", "dd", "de"]]
49
, ["a*[^c]", ["abd", "abe"]]
50
, function () { files.push("a-b", "aXb") }
51
, ["a[X-]b", ["a-b", "aXb"]]
52
, function () { files.push(".x", ".y") }
53
, ["[^a-c]*", ["d", "dd", "de"]]
54
, function () { files.push("a*b/", "a*b/ooo") }
55
, ["a\\*b/*", ["a*b/ooo"]]
56
, ["a\\*?/*", ["a*b/ooo"]]
57
, ["*\\\\!*", [], {null: true}, ["echo !7"]]
58
, ["*\\!*", ["echo !7"], null, ["echo !7"]]
59
, ["*.\\*", ["r.*"], null, ["r.*"]]
61
, ["a[\\b]c", ["abc"]]
63
, ["a\\*c", [], {null: true}, ["abc"]]
64
, ["", [""], { null: true }, [""]]
66
, "http://www.opensource.apple.com/source/bash/bash-23/" +
67
"bash/tests/glob-test"
68
, function () { files.push("man/", "man/man1/", "man/man1/bash.1") }
69
, ["*/man*/bash.*", ["man/man1/bash.1"]]
70
, ["man/man1/bash.1", ["man/man1/bash.1"]]
71
, ["a***c", ["abc"], null, ["abc"]]
72
, ["a*****?c", ["abc"], null, ["abc"]]
73
, ["?*****??", ["abc"], null, ["abc"]]
74
, ["*****??", ["abc"], null, ["abc"]]
75
, ["?*****?c", ["abc"], null, ["abc"]]
76
, ["?***?****c", ["abc"], null, ["abc"]]
77
, ["?***?****?", ["abc"], null, ["abc"]]
78
, ["?***?****", ["abc"], null, ["abc"]]
79
, ["*******c", ["abc"], null, ["abc"]]
80
, ["*******?", ["abc"], null, ["abc"]]
81
, ["a*cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]]
82
, ["a**?**cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]]
83
, ["a**?**cd**?**??k***", ["abcdecdhjk"], null, ["abcdecdhjk"]]
84
, ["a**?**cd**?**??***k", ["abcdecdhjk"], null, ["abcdecdhjk"]]
85
, ["a**?**cd**?**??***k**", ["abcdecdhjk"], null, ["abcdecdhjk"]]
86
, ["a****c**?**??*****", ["abcdecdhjk"], null, ["abcdecdhjk"]]
87
, ["[-abc]", ["-"], null, ["-"]]
88
, ["[abc-]", ["-"], null, ["-"]]
89
, ["\\", ["\\"], null, ["\\"]]
90
, ["[\\\\]", ["\\"], null, ["\\"]]
91
, ["[[]", ["["], null, ["["]]
92
, ["[", ["["], null, ["["]]
93
, ["[*", ["[abc"], null, ["[abc"]]
94
, "a right bracket shall lose its special meaning and\n" +
95
"represent itself in a bracket expression if it occurs\n" +
96
"first in the list. -- POSIX.2 2.8.3.2"
97
, ["[]]", ["]"], null, ["]"]]
98
, ["[]-]", ["]"], null, ["]"]]
99
, ["[a-\z]", ["p"], null, ["p"]]
100
, ["??**********?****?", [], { null: true }, ["abc"]]
101
, ["??**********?****c", [], { null: true }, ["abc"]]
102
, ["?************c****?****", [], { null: true }, ["abc"]]
103
, ["*c*?**", [], { null: true }, ["abc"]]
104
, ["a*****c*?**", [], { null: true }, ["abc"]]
105
, ["a********???*******", [], { null: true }, ["abc"]]
106
, ["[]", [], { null: true }, ["a"]]
107
, ["[abc", [], { null: true }, ["["]]
110
, ["XYZ", ["xYz"], { nocase: true, null: true }
111
, ["xYz", "ABC", "IjK"]]
112
, ["ab*", ["ABC"], { nocase: true, null: true }
113
, ["xYz", "ABC", "IjK"]]
114
, ["[ia]?[ck]", ["ABC", "IjK"], { nocase: true, null: true }
115
, ["xYz", "ABC", "IjK"]]
117
// [ pattern, [matches], MM opts, files, TAP opts]
119
, ["{/*,*}", [], {null: true}, ["/asdf/asdf/asdf"]]
120
, ["{/?,*}", ["/a", "bb"], {null: true}
121
, ["/a", "/b/b", "/a/b/c", "bb"]]
123
, "dots should not match unless requested"
124
, ["**", ["a/b"], {}, ["a/b", "a/.d", ".a/.d"]]
126
// .. and . can only match patterns starting with .,
127
// even when options.dot is set.
129
files = ["a/./b", "a/../b", "a/c/b", "a/.d/b"]
131
, ["a/*/b", ["a/c/b", "a/.d/b"], {dot: true}]
132
, ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: true}]
133
, ["a/*/b", ["a/c/b"], {dot:false}]
134
, ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: false}]
137
// this also tests that changing the options needs
138
// to change the cache key, even if the pattern is
140
, ["**", ["a/b","a/.d",".a/.d"], { dot: true }
141
, [ ".a/.d", "a/.d", "a/b"]]
143
, "paren sets cannot contain slashes"
144
, ["*(a/b)", ["*(a/b)"], {nonull: true}, ["a/b"]]
146
// brace sets trump all else.
148
// invalid glob pattern. fails on bash4 and bsdglob.
149
// however, in this implementation, it's easier just
150
// to do the intuitive thing, and let brace-expansion
151
// actually come before parsing any extglob patterns,
152
// like the documentation seems to say.
154
// XXX: if anyone complains about this, either fix it
155
// or tell them to grow up and stop complaining.
157
// bash/bsdglob says this:
158
// , ["*(a|{b),c)}", ["*(a|{b),c)}"], {}, ["a", "ab", "ac", "ad"]]
159
// but we do this instead:
160
, ["*(a|{b),c)}", ["a", "ab", "ac"], {}, ["a", "ab", "ac", "ad"]]
162
// test partial parsing in the presence of comment/negation chars
163
, ["[!a*", ["[!ab"], {}, ["[!ab", "[ab"]]
164
, ["[#a*", ["[#ab"], {}, ["[#ab", "[ab"]]
166
// like: {a,b|c\\,d\\\|e} except it's unclosed, so it has to be escaped.
167
, ["+(a|*\\|c\\\\|d\\\\\\|e\\\\\\\\|f\\\\\\\\\\|g"
168
, ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g"]
170
, ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g", "a", "b\\c"]]
173
// crazy nested {,,} and *(||) tests.
175
files = [ "a", "b", "c", "d"
178
, "bc,d", "c,db", "c,d"
179
, "d)", "(b|c", "*(b|c"
180
, "b|c", "b|cc", "cb|c"
181
, "x(a|b|c)", "x(a|c)"
182
, "(a|b|c)", "(a|c)"]
184
, ["*(a|{b,c})", ["a", "b", "c", "ab", "ac"]]
185
, ["{a,*(b|c,d)}", ["a","(b|c", "*(b|c", "d)"]]
189
, ["{a,*(b|{c,d})}", ["a","b", "bc", "cb", "c", "d"]]
190
, ["*(a|{b|c,c})", ["a", "b", "c", "ab", "ac", "bc", "cb"]]
193
// test various flag settings.
194
, [ "*(a|{b|c,c})", ["x(a|b|c)", "x(a|c)", "(a|b|c)", "(a|c)"]
196
, ["a?b", ["x/y/acb", "acb/"], {matchBase: true}
197
, ["x/y/acb", "acb/", "acb/d/e", "x/y/acb/d"] ]
198
, ["#*", ["#a", "#b"], {nocomment: true}, ["#a", "#b", "c#d"]]
201
// begin channelling Boole and deMorgan...
204
files = ["d", "e", "!ab", "!abc", "a!b", "\\!a"]
207
// anything that is NOT a* matches.
208
, ["!a*", ["\\!a", "d", "e", "!ab", "!abc"]]
210
// anything that IS !a* matches.
211
, ["!a*", ["!ab", "!abc"], {nonegate: true}]
213
// anything that IS a* matches
216
// anything that is NOT !a* matches
217
, ["!\\!a*", ["a!b", "d", "e", "\\!a"]]
219
// negation nestled within a pattern
223
// can't match this one without negative lookbehind.
229
, ["*.!(js)", ["foo.bar", "foo.", "boo.js.boo"] ]
231
// https://github.com/isaacs/minimatch/issues/5
246
, ["**/.x/**", [ '.x/'
258
[ '/^(?:(?=.)a[^/]*?)$/',
259
'/^(?:(?=.)X[^/]*?)$/',
260
'/^(?:(?=.)X[^/]*?)$/',
262
'/^(?:(?=.)\\*[^/]*?)$/',
264
'/^(?:(?=.)b[^/]*?\\/)$/',
265
'/^(?:(?=.)c[^/]*?)$/',
266
'/^(?:(?:(?!(?:\\/|^)\\.).)*?)$/',
267
'/^(?:\\.\\.\\/(?!\\.)(?=.)[^/]*?\\/)$/',
268
'/^(?:s\\/(?=.)\\.\\.[^/]*?\\/)$/',
269
'/^(?:\\/\\^root:\\/\\{s\\/(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$\\/1\\/)$/',
270
'/^(?:\\/\\^root:\\/\\{s\\/(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$\\/\u0001\\/)$/',
271
'/^(?:(?!\\.)(?=.)[a-c]b[^/]*?)$/',
272
'/^(?:(?!\\.)(?=.)[a-y][^/]*?[^c])$/',
273
'/^(?:(?=.)a[^/]*?[^c])$/',
274
'/^(?:(?=.)a[X-]b)$/',
275
'/^(?:(?!\\.)(?=.)[^a-c][^/]*?)$/',
276
'/^(?:a\\*b\\/(?!\\.)(?=.)[^/]*?)$/',
277
'/^(?:(?=.)a\\*[^/]\\/(?!\\.)(?=.)[^/]*?)$/',
278
'/^(?:(?!\\.)(?=.)[^/]*?\\\\\\![^/]*?)$/',
279
'/^(?:(?!\\.)(?=.)[^/]*?\\![^/]*?)$/',
280
'/^(?:(?!\\.)(?=.)[^/]*?\\.\\*)$/',
281
'/^(?:(?=.)a[b]c)$/',
282
'/^(?:(?=.)a[b]c)$/',
283
'/^(?:(?=.)a[^/]c)$/',
286
'/^(?:(?!\\.)(?=.)[^/]*?\\/(?=.)man[^/]*?\\/(?=.)bash\\.[^/]*?)$/',
287
'/^(?:man\\/man1\\/bash\\.1)$/',
288
'/^(?:(?=.)a[^/]*?[^/]*?[^/]*?c)$/',
289
'/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]c)$/',
290
'/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/])$/',
291
'/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/])$/',
292
'/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]c)$/',
293
'/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/',
294
'/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/])$/',
295
'/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?)$/',
296
'/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c)$/',
297
'/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/])$/',
298
'/^(?:(?=.)a[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k)$/',
299
'/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k)$/',
300
'/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k[^/]*?[^/]*?[^/]*?)$/',
301
'/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?k)$/',
302
'/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?k[^/]*?[^/]*?)$/',
303
'/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?)$/',
304
'/^(?:(?!\\.)(?=.)[-abc])$/',
305
'/^(?:(?!\\.)(?=.)[abc-])$/',
307
'/^(?:(?!\\.)(?=.)[\\\\])$/',
308
'/^(?:(?!\\.)(?=.)[\\[])$/',
310
'/^(?:(?=.)\\[(?!\\.)(?=.)[^/]*?)$/',
311
'/^(?:(?!\\.)(?=.)[\\]])$/',
312
'/^(?:(?!\\.)(?=.)[\\]-])$/',
313
'/^(?:(?!\\.)(?=.)[a-z])$/',
314
'/^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/])$/',
315
'/^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/',
316
'/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?)$/',
317
'/^(?:(?!\\.)(?=.)[^/]*?c[^/]*?[^/][^/]*?[^/]*?)$/',
318
'/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/][^/]*?[^/]*?)$/',
319
'/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?)$/',
323
'/^(?:(?=.)ab[^/]*?)$/i',
324
'/^(?:(?!\\.)(?=.)[ia][^/][ck])$/i',
325
'/^(?:\\/(?!\\.)(?=.)[^/]*?|(?!\\.)(?=.)[^/]*?)$/',
326
'/^(?:\\/(?!\\.)(?=.)[^/]|(?!\\.)(?=.)[^/]*?)$/',
327
'/^(?:(?:(?!(?:\\/|^)\\.).)*?)$/',
328
'/^(?:a\\/(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]*?\\/b)$/',
329
'/^(?:a\\/(?=.)\\.[^/]*?\\/b)$/',
330
'/^(?:a\\/(?!\\.)(?=.)[^/]*?\\/b)$/',
331
'/^(?:a\\/(?=.)\\.[^/]*?\\/b)$/',
332
'/^(?:(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?)$/',
333
'/^(?:(?!\\.)(?=.)[^/]*?\\(a\\/b\\))$/',
334
'/^(?:(?!\\.)(?=.)(?:a|b)*|(?!\\.)(?=.)(?:a|c)*)$/',
335
'/^(?:(?=.)\\[(?=.)\\!a[^/]*?)$/',
336
'/^(?:(?=.)\\[(?=.)#a[^/]*?)$/',
337
'/^(?:(?=.)\\+\\(a\\|[^/]*?\\|c\\\\\\\\\\|d\\\\\\\\\\|e\\\\\\\\\\\\\\\\\\|f\\\\\\\\\\\\\\\\\\|g)$/',
338
'/^(?:(?!\\.)(?=.)(?:a|b)*|(?!\\.)(?=.)(?:a|c)*)$/',
339
'/^(?:a|(?!\\.)(?=.)[^/]*?\\(b\\|c|d\\))$/',
340
'/^(?:a|(?!\\.)(?=.)(?:b|c)*|(?!\\.)(?=.)(?:b|d)*)$/',
341
'/^(?:(?!\\.)(?=.)(?:a|b|c)*|(?!\\.)(?=.)(?:a|c)*)$/',
342
'/^(?:(?!\\.)(?=.)[^/]*?\\(a\\|b\\|c\\)|(?!\\.)(?=.)[^/]*?\\(a\\|c\\))$/',
343
'/^(?:(?=.)a[^/]b)$/',
344
'/^(?:(?=.)#[^/]*?)$/',
345
'/^(?!^(?:(?=.)a[^/]*?)$).*$/',
346
'/^(?:(?=.)\\!a[^/]*?)$/',
347
'/^(?:(?=.)a[^/]*?)$/',
348
'/^(?!^(?:(?=.)\\!a[^/]*?)$).*$/',
349
'/^(?:(?!\\.)(?=.)[^/]*?\\.(?:(?!js)[^/]*?))$/',
350
'/^(?:(?:(?!(?:\\/|^)\\.).)*?\\/\\.x\\/(?:(?!(?:\\/|^)\\.).)*?)$/' ]
353
tap.test("basic tests", function (t) {
354
var start = Date.now()
356
// [ pattern, [matches], MM opts, files, TAP opts]
357
patterns.forEach(function (c) {
358
if (typeof c === "function") return c()
359
if (typeof c === "string") return t.comment(c)
362
, expect = c[1].sort(alpha)
363
, options = c[2] || {}
365
, tapOpts = c[4] || {}
367
// options.debug = true
368
var m = new mm.Minimatch(pattern, options)
370
var expectRe = regexps[re++]
371
tapOpts.re = String(r) || JSON.stringify(r)
372
tapOpts.files = JSON.stringify(f)
373
tapOpts.pattern = pattern
375
tapOpts.negated = m.negate
377
var actual = mm.match(f, pattern, options)
380
t.equivalent( actual, expect
381
, JSON.stringify(pattern) + " " + JSON.stringify(expect)
384
t.equal(tapOpts.re, expectRe, tapOpts)
387
t.comment("time=" + (Date.now() - start) + "ms")
391
tap.test("global leak test", function (t) {
392
var globalAfter = Object.keys(global)
393
t.equivalent(globalAfter, globalBefore, "no new globals, please")
397
function alpha (a, b) {
398
return a > b ? 1 : -1