blob: a3a36ffc7b72cc8308fe0102f13a3325e5873bd8 [file] [log] [blame]
Colin Cross4b793e52015-04-23 13:29:28 -07001// 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"
Colin Crossa4cc6832019-03-25 15:04:17 -070021 "strings"
Colin Cross4b793e52015-04-23 13:29:28 -070022 "testing"
23)
24
25var pwd, _ = os.Getwd()
26
Colin Crossa4fae902017-10-03 15:58:50 -070027type globTestCase struct {
Colin Cross5d6d4c72015-04-23 17:56:11 -070028 pattern string
29 matches []string
30 excludes []string
Dan Willemsen75fec882017-06-22 17:01:24 -070031 deps []string
Colin Cross5d6d4c72015-04-23 17:56:11 -070032 err error
Colin Crossa4fae902017-10-03 15:58:50 -070033}
34
35var globTestCases = []globTestCase{
Colin Cross4b793e52015-04-23 13:29:28 -070036 // Current directory tests
37 {
38 pattern: "*",
Dan Willemsenb6c90232018-02-23 14:49:45 -080039 matches: []string{"a/", "b/", "c/", "d.ext", "e.ext"},
Dan Willemsen75fec882017-06-22 17:01:24 -070040 deps: []string{"."},
Colin Cross4b793e52015-04-23 13:29:28 -070041 },
42 {
43 pattern: "*.ext",
44 matches: []string{"d.ext", "e.ext"},
Dan Willemsen75fec882017-06-22 17:01:24 -070045 deps: []string{"."},
Colin Cross4b793e52015-04-23 13:29:28 -070046 },
47 {
48 pattern: "*/a",
Dan Willemsenb6c90232018-02-23 14:49:45 -080049 matches: []string{"a/a/", "b/a"},
Dan Willemsen75fec882017-06-22 17:01:24 -070050 deps: []string{".", "a", "b", "c"},
Colin Cross4b793e52015-04-23 13:29:28 -070051 },
52 {
53 pattern: "*/*/a",
54 matches: []string{"a/a/a"},
Dan Willemsen75fec882017-06-22 17:01:24 -070055 deps: []string{".", "a", "b", "c", "a/a", "a/b", "c/f", "c/g", "c/h"},
Colin Cross4b793e52015-04-23 13:29:28 -070056 },
57 {
58 pattern: "*/a/a",
59 matches: []string{"a/a/a"},
Dan Willemsen75fec882017-06-22 17:01:24 -070060 deps: []string{".", "a", "b", "c", "a/a"},
Colin Cross4b793e52015-04-23 13:29:28 -070061 },
Colin Crossa4706122018-09-19 13:36:42 -070062 {
63 pattern: "c/*/?",
64 matches: []string{"c/h/h"},
65 deps: []string{"c", "c/f", "c/g", "c/h"},
66 },
67 {
68 pattern: "c/*/[gh]*",
69 matches: []string{"c/g/g.ext", "c/h/h"},
70 deps: []string{"c", "c/f", "c/g", "c/h"},
71 },
72 {
73 pattern: "c/*/[fgh]*",
74 matches: []string{"c/f/f.ext", "c/g/g.ext", "c/h/h"},
75 deps: []string{"c", "c/f", "c/g", "c/h"},
76 },
77 {
78 pattern: "c/*/[f-h]*",
79 matches: []string{"c/f/f.ext", "c/g/g.ext", "c/h/h"},
80 deps: []string{"c", "c/f", "c/g", "c/h"},
81 },
Colin Cross4b793e52015-04-23 13:29:28 -070082 // ./ directory tests
83 {
84 pattern: "./*",
Dan Willemsenb6c90232018-02-23 14:49:45 -080085 matches: []string{"a/", "b/", "c/", "d.ext", "e.ext"},
Dan Willemsen75fec882017-06-22 17:01:24 -070086 deps: []string{"."},
Colin Cross4b793e52015-04-23 13:29:28 -070087 },
88 {
89 pattern: "./*.ext",
90 matches: []string{"d.ext", "e.ext"},
Dan Willemsen75fec882017-06-22 17:01:24 -070091 deps: []string{"."},
Colin Cross4b793e52015-04-23 13:29:28 -070092 },
93 {
94 pattern: "./*/a",
Dan Willemsenb6c90232018-02-23 14:49:45 -080095 matches: []string{"a/a/", "b/a"},
Dan Willemsen75fec882017-06-22 17:01:24 -070096 deps: []string{".", "a", "b", "c"},
Colin Cross4b793e52015-04-23 13:29:28 -070097 },
98 {
99 pattern: "./[ac]/a",
Dan Willemsenb6c90232018-02-23 14:49:45 -0800100 matches: []string{"a/a/"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700101 deps: []string{".", "a", "c"},
Colin Cross4b793e52015-04-23 13:29:28 -0700102 },
103
104 // subdirectory tests
105 {
106 pattern: "c/*/*.ext",
107 matches: []string{"c/f/f.ext", "c/g/g.ext"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700108 deps: []string{"c", "c/f", "c/g", "c/h"},
Colin Cross4b793e52015-04-23 13:29:28 -0700109 },
110 {
111 pattern: "a/*/a",
112 matches: []string{"a/a/a"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700113 deps: []string{"a", "a/a", "a/b"},
Colin Cross4b793e52015-04-23 13:29:28 -0700114 },
115
116 // absolute tests
117 {
Colin Crossd9bea8f2018-09-21 14:13:03 -0700118 pattern: filepath.Join(pwd, "testdata/glob/c/*/*.ext"),
Colin Cross4b793e52015-04-23 13:29:28 -0700119 matches: []string{
Colin Crossd9bea8f2018-09-21 14:13:03 -0700120 filepath.Join(pwd, "testdata/glob/c/f/f.ext"),
121 filepath.Join(pwd, "testdata/glob/c/g/g.ext"),
Colin Cross4b793e52015-04-23 13:29:28 -0700122 },
Dan Willemsen75fec882017-06-22 17:01:24 -0700123 deps: []string{
Colin Crossd9bea8f2018-09-21 14:13:03 -0700124 filepath.Join(pwd, "testdata/glob/c"),
125 filepath.Join(pwd, "testdata/glob/c/f"),
126 filepath.Join(pwd, "testdata/glob/c/g"),
127 filepath.Join(pwd, "testdata/glob/c/h"),
Colin Cross4b793e52015-04-23 13:29:28 -0700128 },
129 },
130
131 // no-wild tests
132 {
133 pattern: "a",
Dan Willemsenb6c90232018-02-23 14:49:45 -0800134 matches: []string{"a/"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700135 deps: []string{"a"},
Colin Cross4b793e52015-04-23 13:29:28 -0700136 },
137 {
138 pattern: "a/a",
Dan Willemsenb6c90232018-02-23 14:49:45 -0800139 matches: []string{"a/a/"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700140 deps: []string{"a/a"},
Colin Cross4b793e52015-04-23 13:29:28 -0700141 },
142
143 // clean tests
144 {
Colin Cross5d6d4c72015-04-23 17:56:11 -0700145 pattern: "./c/*/*.ext",
146 matches: []string{"c/f/f.ext", "c/g/g.ext"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700147 deps: []string{"c", "c/f", "c/g", "c/h"},
Colin Cross4b793e52015-04-23 13:29:28 -0700148 },
149 {
Colin Cross5d6d4c72015-04-23 17:56:11 -0700150 pattern: "c/../c/*/*.ext",
151 matches: []string{"c/f/f.ext", "c/g/g.ext"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700152 deps: []string{"c", "c/f", "c/g", "c/h"},
Colin Cross4b793e52015-04-23 13:29:28 -0700153 },
Colin Cross7bac3c62015-04-23 15:45:25 -0700154
155 // recursive tests
156 {
157 pattern: "**/a",
Dan Willemsenb6c90232018-02-23 14:49:45 -0800158 matches: []string{"a/", "a/a/", "a/a/a", "b/a"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700159 deps: []string{".", "a", "a/a", "a/b", "b", "c", "c/f", "c/g", "c/h"},
Colin Cross7bac3c62015-04-23 15:45:25 -0700160 },
161 {
162 pattern: "a/**/a",
Dan Willemsenb6c90232018-02-23 14:49:45 -0800163 matches: []string{"a/a/", "a/a/a"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700164 deps: []string{"a", "a/a", "a/b"},
Colin Cross7bac3c62015-04-23 15:45:25 -0700165 },
166 {
167 pattern: "a/**/*",
Dan Willemsenb6c90232018-02-23 14:49:45 -0800168 matches: []string{"a/a/", "a/b/", "a/a/a", "a/b/b"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700169 deps: []string{"a", "a/a", "a/b"},
Colin Cross7bac3c62015-04-23 15:45:25 -0700170 },
171
172 // absolute recursive tests
173 {
Colin Crossd9bea8f2018-09-21 14:13:03 -0700174 pattern: filepath.Join(pwd, "testdata/glob/**/*.ext"),
Colin Cross7bac3c62015-04-23 15:45:25 -0700175 matches: []string{
Colin Crossd9bea8f2018-09-21 14:13:03 -0700176 filepath.Join(pwd, "testdata/glob/d.ext"),
177 filepath.Join(pwd, "testdata/glob/e.ext"),
178 filepath.Join(pwd, "testdata/glob/c/f/f.ext"),
179 filepath.Join(pwd, "testdata/glob/c/g/g.ext"),
Colin Cross7bac3c62015-04-23 15:45:25 -0700180 },
Dan Willemsen75fec882017-06-22 17:01:24 -0700181 deps: []string{
Colin Crossd9bea8f2018-09-21 14:13:03 -0700182 filepath.Join(pwd, "testdata/glob"),
183 filepath.Join(pwd, "testdata/glob/a"),
184 filepath.Join(pwd, "testdata/glob/a/a"),
185 filepath.Join(pwd, "testdata/glob/a/b"),
186 filepath.Join(pwd, "testdata/glob/b"),
187 filepath.Join(pwd, "testdata/glob/c"),
188 filepath.Join(pwd, "testdata/glob/c/f"),
189 filepath.Join(pwd, "testdata/glob/c/g"),
190 filepath.Join(pwd, "testdata/glob/c/h"),
Colin Cross7bac3c62015-04-23 15:45:25 -0700191 },
192 },
193
194 // recursive error tests
195 {
196 pattern: "**/**/*",
197 err: GlobMultipleRecursiveErr,
198 },
199 {
200 pattern: "a/**/**/*",
201 err: GlobMultipleRecursiveErr,
202 },
203 {
204 pattern: "**/a/**/*",
205 err: GlobMultipleRecursiveErr,
206 },
207 {
208 pattern: "**/**/a/*",
209 err: GlobMultipleRecursiveErr,
210 },
211 {
212 pattern: "a/**",
213 err: GlobLastRecursiveErr,
214 },
215 {
216 pattern: "**/**",
217 err: GlobLastRecursiveErr,
218 },
Colin Crossa4cc6832019-03-25 15:04:17 -0700219 {
220 pattern: "a**/",
221 err: GlobInvalidRecursiveErr,
222 },
223 {
224 pattern: "**a/",
225 err: GlobInvalidRecursiveErr,
226 },
Colin Cross5d6d4c72015-04-23 17:56:11 -0700227
228 // exclude tests
229 {
230 pattern: "*.ext",
231 excludes: []string{"d.ext"},
232 matches: []string{"e.ext"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700233 deps: []string{"."},
Colin Cross5d6d4c72015-04-23 17:56:11 -0700234 },
235 {
236 pattern: "*/*",
237 excludes: []string{"a/b"},
Dan Willemsenb6c90232018-02-23 14:49:45 -0800238 matches: []string{"a/a/", "b/a", "c/c", "c/f/", "c/g/", "c/h/"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700239 deps: []string{".", "a", "b", "c"},
Colin Cross5d6d4c72015-04-23 17:56:11 -0700240 },
241 {
242 pattern: "*/*",
243 excludes: []string{"a/b", "c/c"},
Dan Willemsenb6c90232018-02-23 14:49:45 -0800244 matches: []string{"a/a/", "b/a", "c/f/", "c/g/", "c/h/"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700245 deps: []string{".", "a", "b", "c"},
Colin Cross5d6d4c72015-04-23 17:56:11 -0700246 },
247 {
248 pattern: "*/*",
249 excludes: []string{"c/*", "*/a"},
Dan Willemsenb6c90232018-02-23 14:49:45 -0800250 matches: []string{"a/b/"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700251 deps: []string{".", "a", "b", "c"},
Colin Cross5d6d4c72015-04-23 17:56:11 -0700252 },
253 {
254 pattern: "*/*",
255 excludes: []string{"*/*"},
256 matches: nil,
Dan Willemsen75fec882017-06-22 17:01:24 -0700257 deps: []string{".", "a", "b", "c"},
Colin Cross5d6d4c72015-04-23 17:56:11 -0700258 },
259
260 // absolute exclude tests
261 {
Colin Crossd9bea8f2018-09-21 14:13:03 -0700262 pattern: filepath.Join(pwd, "testdata/glob/c/*/*.ext"),
263 excludes: []string{filepath.Join(pwd, "testdata/glob/c/*/f.ext")},
Colin Cross5d6d4c72015-04-23 17:56:11 -0700264 matches: []string{
Colin Crossd9bea8f2018-09-21 14:13:03 -0700265 filepath.Join(pwd, "testdata/glob/c/g/g.ext"),
Colin Cross5d6d4c72015-04-23 17:56:11 -0700266 },
Dan Willemsen75fec882017-06-22 17:01:24 -0700267 deps: []string{
Colin Crossd9bea8f2018-09-21 14:13:03 -0700268 filepath.Join(pwd, "testdata/glob/c"),
269 filepath.Join(pwd, "testdata/glob/c/f"),
270 filepath.Join(pwd, "testdata/glob/c/g"),
271 filepath.Join(pwd, "testdata/glob/c/h"),
Colin Cross5d6d4c72015-04-23 17:56:11 -0700272 },
273 },
274 {
Colin Crossd9bea8f2018-09-21 14:13:03 -0700275 pattern: filepath.Join(pwd, "testdata/glob/c/*/*.ext"),
276 excludes: []string{filepath.Join(pwd, "testdata/glob/c/f/*.ext")},
Colin Cross5d6d4c72015-04-23 17:56:11 -0700277 matches: []string{
Colin Crossd9bea8f2018-09-21 14:13:03 -0700278 filepath.Join(pwd, "testdata/glob/c/g/g.ext"),
Colin Cross5d6d4c72015-04-23 17:56:11 -0700279 },
Dan Willemsen75fec882017-06-22 17:01:24 -0700280 deps: []string{
Colin Crossd9bea8f2018-09-21 14:13:03 -0700281 filepath.Join(pwd, "testdata/glob/c"),
282 filepath.Join(pwd, "testdata/glob/c/f"),
283 filepath.Join(pwd, "testdata/glob/c/g"),
284 filepath.Join(pwd, "testdata/glob/c/h"),
Colin Cross5d6d4c72015-04-23 17:56:11 -0700285 },
286 },
287
288 // recursive exclude tests
289 {
290 pattern: "*.ext",
291 excludes: []string{"**/*.ext"},
292 matches: nil,
Dan Willemsen75fec882017-06-22 17:01:24 -0700293 deps: []string{"."},
Colin Cross5d6d4c72015-04-23 17:56:11 -0700294 },
295 {
296 pattern: "*/*",
297 excludes: []string{"**/b"},
Dan Willemsenb6c90232018-02-23 14:49:45 -0800298 matches: []string{"a/a/", "b/a", "c/c", "c/f/", "c/g/", "c/h/"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700299 deps: []string{".", "a", "b", "c"},
Colin Cross5d6d4c72015-04-23 17:56:11 -0700300 },
301 {
302 pattern: "*/*",
303 excludes: []string{"a/**/*"},
Dan Willemsenb6c90232018-02-23 14:49:45 -0800304 matches: []string{"b/a", "c/c", "c/f/", "c/g/", "c/h/"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700305 deps: []string{".", "a", "b", "c"},
Colin Cross5d6d4c72015-04-23 17:56:11 -0700306 },
307 {
308 pattern: "**/*",
309 excludes: []string{"**/*"},
310 matches: nil,
Dan Willemsen75fec882017-06-22 17:01:24 -0700311 deps: []string{".", "a", "a/a", "a/b", "b", "c", "c/f", "c/g", "c/h"},
Colin Cross5d6d4c72015-04-23 17:56:11 -0700312 },
313 {
314 pattern: "*/*/*",
315 excludes: []string{"a/**/a"},
316 matches: []string{"a/b/b", "c/f/f.ext", "c/g/g.ext", "c/h/h"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700317 deps: []string{".", "a", "b", "c", "a/a", "a/b", "c/f", "c/g", "c/h"},
Colin Cross5d6d4c72015-04-23 17:56:11 -0700318 },
319 {
320 pattern: "*/*/*",
321 excludes: []string{"**/a"},
322 matches: []string{"a/b/b", "c/f/f.ext", "c/g/g.ext", "c/h/h"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700323 deps: []string{".", "a", "b", "c", "a/a", "a/b", "c/f", "c/g", "c/h"},
Colin Cross5d6d4c72015-04-23 17:56:11 -0700324 },
325 {
326 pattern: "c/*/*.ext",
327 excludes: []string{"c/**/f.ext"},
328 matches: []string{"c/g/g.ext"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700329 deps: []string{"c", "c/f", "c/g", "c/h"},
Colin Cross5d6d4c72015-04-23 17:56:11 -0700330 },
331
332 // absoulte recursive exclude tests
333 {
Colin Crossd9bea8f2018-09-21 14:13:03 -0700334 pattern: filepath.Join(pwd, "testdata/glob/c/*/*.ext"),
335 excludes: []string{filepath.Join(pwd, "testdata/glob/**/f.ext")},
Colin Cross5d6d4c72015-04-23 17:56:11 -0700336 matches: []string{
Colin Crossd9bea8f2018-09-21 14:13:03 -0700337 filepath.Join(pwd, "testdata/glob/c/g/g.ext"),
Colin Cross5d6d4c72015-04-23 17:56:11 -0700338 },
Dan Willemsen75fec882017-06-22 17:01:24 -0700339 deps: []string{
Colin Crossd9bea8f2018-09-21 14:13:03 -0700340 filepath.Join(pwd, "testdata/glob/c"),
341 filepath.Join(pwd, "testdata/glob/c/f"),
342 filepath.Join(pwd, "testdata/glob/c/g"),
343 filepath.Join(pwd, "testdata/glob/c/h"),
Colin Cross5d6d4c72015-04-23 17:56:11 -0700344 },
345 },
346
347 // clean exclude tests
348 {
349 pattern: "./c/*/*.ext",
350 excludes: []string{"./c/*/f.ext"},
351 matches: []string{"c/g/g.ext"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700352 deps: []string{"c", "c/f", "c/g", "c/h"},
Colin Cross5d6d4c72015-04-23 17:56:11 -0700353 },
354 {
355 pattern: "c/*/*.ext",
356 excludes: []string{"./c/*/f.ext"},
357 matches: []string{"c/g/g.ext"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700358 deps: []string{"c", "c/f", "c/g", "c/h"},
Colin Cross5d6d4c72015-04-23 17:56:11 -0700359 },
360 {
361 pattern: "./c/*/*.ext",
362 excludes: []string{"c/*/f.ext"},
363 matches: []string{"c/g/g.ext"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700364 deps: []string{"c", "c/f", "c/g", "c/h"},
Colin Cross5d6d4c72015-04-23 17:56:11 -0700365 },
366
Colin Cross7d2ee0d2015-06-18 10:48:15 -0700367 // non-existant non-wild path tests
368 {
369 pattern: "d/*",
370 matches: nil,
Dan Willemsen75fec882017-06-22 17:01:24 -0700371 deps: []string{"."},
Colin Cross7d2ee0d2015-06-18 10:48:15 -0700372 },
373 {
374 pattern: "d",
375 matches: nil,
Dan Willemsen75fec882017-06-22 17:01:24 -0700376 deps: []string{"."},
Colin Cross7d2ee0d2015-06-18 10:48:15 -0700377 },
378 {
379 pattern: "a/d/*",
380 matches: nil,
Dan Willemsen75fec882017-06-22 17:01:24 -0700381 deps: []string{"a"},
Colin Cross7d2ee0d2015-06-18 10:48:15 -0700382 },
383 {
384 pattern: "a/d",
385 matches: nil,
Dan Willemsen75fec882017-06-22 17:01:24 -0700386 deps: []string{"a"},
Colin Cross7d2ee0d2015-06-18 10:48:15 -0700387 },
388 {
389 pattern: "a/a/d/*",
390 matches: nil,
Dan Willemsen75fec882017-06-22 17:01:24 -0700391 deps: []string{"a/a"},
Colin Cross7d2ee0d2015-06-18 10:48:15 -0700392 },
393 {
394 pattern: "a/a/d",
395 matches: nil,
Dan Willemsen75fec882017-06-22 17:01:24 -0700396 deps: []string{"a/a"},
Colin Cross7d2ee0d2015-06-18 10:48:15 -0700397 },
398 {
399 pattern: "a/d/a/*",
400 matches: nil,
Dan Willemsen75fec882017-06-22 17:01:24 -0700401 deps: []string{"a"},
Colin Cross7d2ee0d2015-06-18 10:48:15 -0700402 },
403 {
404 pattern: "a/d/a",
405 matches: nil,
Dan Willemsen75fec882017-06-22 17:01:24 -0700406 deps: []string{"a"},
Colin Cross7d2ee0d2015-06-18 10:48:15 -0700407 },
408 {
409 pattern: "a/d/a/*/a",
410 matches: nil,
Dan Willemsen75fec882017-06-22 17:01:24 -0700411 deps: []string{"a"},
Colin Cross7d2ee0d2015-06-18 10:48:15 -0700412 },
413 {
414 pattern: "a/d/a/**/a",
415 matches: nil,
Dan Willemsen75fec882017-06-22 17:01:24 -0700416 deps: []string{"a"},
Colin Cross7d2ee0d2015-06-18 10:48:15 -0700417 },
418
Colin Cross5d6d4c72015-04-23 17:56:11 -0700419 // recursive exclude error tests
420 {
421 pattern: "**/*",
422 excludes: []string{"**/**/*"},
423 err: GlobMultipleRecursiveErr,
424 },
425 {
426 pattern: "**/*",
427 excludes: []string{"a/**/**/*"},
428 err: GlobMultipleRecursiveErr,
429 },
430 {
431 pattern: "**/*",
432 excludes: []string{"**/a/**/*"},
433 err: GlobMultipleRecursiveErr,
434 },
435 {
436 pattern: "**/*",
437 excludes: []string{"**/**/a/*"},
438 err: GlobMultipleRecursiveErr,
439 },
440 {
441 pattern: "**/*",
442 excludes: []string{"a/**"},
443 err: GlobLastRecursiveErr,
444 },
445 {
446 pattern: "**/*",
447 excludes: []string{"**/**"},
448 err: GlobLastRecursiveErr,
449 },
Dan Willemsen53f49502016-07-25 18:40:02 -0700450
451 // If names are excluded by default, but referenced explicitly, they should return results
452 {
453 pattern: ".test/*",
454 matches: []string{".test/a"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700455 deps: []string{".test"},
Dan Willemsen53f49502016-07-25 18:40:02 -0700456 },
457 {
458 pattern: ".t*/a",
459 matches: []string{".test/a"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700460 deps: []string{".", ".test"},
Dan Willemsen53f49502016-07-25 18:40:02 -0700461 },
462 {
463 pattern: ".*/.*",
464 matches: []string{".test/.ing"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700465 deps: []string{".", ".test"},
Dan Willemsen53f49502016-07-25 18:40:02 -0700466 },
467 {
468 pattern: ".t*",
Dan Willemsenb6c90232018-02-23 14:49:45 -0800469 matches: []string{".test/", ".testing"},
Dan Willemsen75fec882017-06-22 17:01:24 -0700470 deps: []string{"."},
Dan Willemsen53f49502016-07-25 18:40:02 -0700471 },
Colin Cross4b793e52015-04-23 13:29:28 -0700472}
473
Colin Crossa4fae902017-10-03 15:58:50 -0700474func TestMockGlob(t *testing.T) {
475 files := []string{
476 "a/a/a",
477 "a/b/b",
478 "b/a",
479 "c/c",
480 "c/f/f.ext",
481 "c/g/g.ext",
482 "c/h/h",
483 "d.ext",
484 "e.ext",
485 ".test/a",
486 ".testing",
487 ".test/.ing",
488 }
489
490 mockFiles := make(map[string][]byte)
491
492 for _, f := range files {
493 mockFiles[f] = nil
Colin Crossd9bea8f2018-09-21 14:13:03 -0700494 mockFiles[filepath.Join(pwd, "testdata/glob", f)] = nil
Colin Crossa4fae902017-10-03 15:58:50 -0700495 }
496
497 mock := MockFs(mockFiles)
498
Colin Crossa4706122018-09-19 13:36:42 -0700499 for _, testCase := range globTestCases {
500 t.Run(testCase.pattern, func(t *testing.T) {
Colin Crosse98d0822018-09-21 15:30:13 -0700501 testGlob(t, mock, testCase, FollowSymlinks)
Colin Crossa4fae902017-10-03 15:58:50 -0700502 })
503 }
504}
505
Colin Cross4b793e52015-04-23 13:29:28 -0700506func TestGlob(t *testing.T) {
Colin Crossd9bea8f2018-09-21 14:13:03 -0700507 os.Chdir("testdata/glob")
508 defer os.Chdir("../..")
Colin Crossa4706122018-09-19 13:36:42 -0700509 for _, testCase := range globTestCases {
510 t.Run(testCase.pattern, func(t *testing.T) {
Colin Crosse98d0822018-09-21 15:30:13 -0700511 testGlob(t, OsFs, testCase, FollowSymlinks)
Colin Crossa4fae902017-10-03 15:58:50 -0700512 })
513 }
514}
Colin Cross4b793e52015-04-23 13:29:28 -0700515
Colin Crossa4706122018-09-19 13:36:42 -0700516var globEscapeTestCases = []globTestCase{
517 {
518 pattern: `**/*`,
519 matches: []string{`*`, `**/`, `?`, `a/`, `b`, `**/*`, `**/a`, `**/b/`, `**/b/b`, `a/a`},
520 deps: []string{`.`, `**`, `**/b`, `a`},
521 },
522 {
523 pattern: `**/\*`,
524 matches: []string{`*`, `**/*`},
525 deps: []string{`.`, `**`, `**/b`, `a`},
526 },
527 {
528 pattern: `\*\*/*`,
529 matches: []string{`**/*`, `**/a`, `**/b/`},
530 deps: []string{`.`, `**`},
531 },
532 {
533 pattern: `\*\*/**/*`,
534 matches: []string{`**/*`, `**/a`, `**/b/`, `**/b/b`},
535 deps: []string{`.`, `**`, `**/b`},
536 },
537}
538
Colin Crossd9bea8f2018-09-21 14:13:03 -0700539func TestMockGlobEscapes(t *testing.T) {
Colin Crossa4706122018-09-19 13:36:42 -0700540 files := []string{
541 `*`,
542 `**/*`,
543 `**/a`,
544 `**/b/b`,
545 `?`,
546 `a/a`,
547 `b`,
548 }
549
550 mockFiles := make(map[string][]byte)
551
552 for _, f := range files {
553 mockFiles[f] = nil
554 }
555
556 mock := MockFs(mockFiles)
557
558 for _, testCase := range globEscapeTestCases {
559 t.Run(testCase.pattern, func(t *testing.T) {
Colin Crosse98d0822018-09-21 15:30:13 -0700560 testGlob(t, mock, testCase, FollowSymlinks)
Colin Crossa4706122018-09-19 13:36:42 -0700561 })
562 }
563
564}
565
Colin Crossd9bea8f2018-09-21 14:13:03 -0700566func TestGlobEscapes(t *testing.T) {
567 os.Chdir("testdata/escapes")
568 defer os.Chdir("../..")
569 for _, testCase := range globEscapeTestCases {
570 t.Run(testCase.pattern, func(t *testing.T) {
Colin Crosse98d0822018-09-21 15:30:13 -0700571 testGlob(t, OsFs, testCase, FollowSymlinks)
Colin Crossd9bea8f2018-09-21 14:13:03 -0700572 })
573 }
574
575}
576
Colin Cross9e1ff742018-09-20 22:44:36 -0700577var globSymlinkTestCases = []globTestCase{
578 {
579 pattern: `**/*`,
580 matches: []string{"a/", "b/", "c/", "d/", "e", "a/a/", "a/a/a", "b/a/", "b/a/a", "c/a", "d/a"},
581 deps: []string{".", "a", "a/a", "b", "b/a", "c", "d"},
582 },
Colin Crosse98d0822018-09-21 15:30:13 -0700583 {
584 pattern: `b/**/*`,
585 matches: []string{"b/a/", "b/a/a"},
586 deps: []string{"b", "b/a"},
587 },
Colin Cross9e1ff742018-09-20 22:44:36 -0700588}
589
590func TestMockGlobSymlinks(t *testing.T) {
591 files := []string{
592 "a/a/a",
593 "b -> a",
594 "c -> a/a",
595 "d -> c",
596 "e -> a/a/a",
597 }
598
599 mockFiles := make(map[string][]byte)
600
601 for _, f := range files {
602 mockFiles[f] = nil
603 }
604
605 mock := MockFs(mockFiles)
606
607 for _, testCase := range globSymlinkTestCases {
608 t.Run(testCase.pattern, func(t *testing.T) {
Colin Crosse98d0822018-09-21 15:30:13 -0700609 testGlob(t, mock, testCase, FollowSymlinks)
Colin Cross9e1ff742018-09-20 22:44:36 -0700610 })
611 }
612}
613
614func TestGlobSymlinks(t *testing.T) {
615 os.Chdir("testdata/symlinks")
616 defer os.Chdir("../..")
617
618 for _, testCase := range globSymlinkTestCases {
619 t.Run(testCase.pattern, func(t *testing.T) {
Colin Crosse98d0822018-09-21 15:30:13 -0700620 testGlob(t, OsFs, testCase, FollowSymlinks)
Colin Cross9e1ff742018-09-20 22:44:36 -0700621 })
622 }
623}
624
Colin Crosse98d0822018-09-21 15:30:13 -0700625var globDontFollowSymlinkTestCases = []globTestCase{
626 {
627 pattern: `**/*`,
628 matches: []string{"a/", "b", "c", "d", "e", "a/a/", "a/a/a"},
629 deps: []string{".", "a", "a/a"},
630 },
631 {
632 pattern: `b/**/*`,
633 matches: []string{"b/a/", "b/a/a"},
634 deps: []string{"b", "b/a"},
635 },
636}
637
638func TestMockGlobDontFollowSymlinks(t *testing.T) {
639 files := []string{
640 "a/a/a",
641 "b -> a",
642 "c -> a/a",
643 "d -> c",
644 "e -> a/a/a",
645 }
646
647 mockFiles := make(map[string][]byte)
648
649 for _, f := range files {
650 mockFiles[f] = nil
651 }
652
653 mock := MockFs(mockFiles)
654
655 for _, testCase := range globDontFollowSymlinkTestCases {
656 t.Run(testCase.pattern, func(t *testing.T) {
657 testGlob(t, mock, testCase, DontFollowSymlinks)
658 })
659 }
660}
661
662func TestGlobDontFollowSymlinks(t *testing.T) {
663 os.Chdir("testdata/symlinks")
664 defer os.Chdir("../..")
665
666 for _, testCase := range globDontFollowSymlinkTestCases {
667 t.Run(testCase.pattern, func(t *testing.T) {
668 testGlob(t, OsFs, testCase, DontFollowSymlinks)
669 })
670 }
671}
672
673var globDontFollowDanglingSymlinkTestCases = []globTestCase{
674 {
675 pattern: `**/*`,
676 matches: []string{"a/", "b", "c", "d", "dangling", "e", "f", "a/a/", "a/a/a", "a/a/f"},
677 deps: []string{".", "a", "a/a"},
678 },
679 {
680 pattern: `dangling`,
681 matches: []string{"dangling"},
682 deps: []string{"dangling"},
683 },
684}
685
686func TestMockGlobDontFollowDanglingSymlinks(t *testing.T) {
687 files := []string{
688 "a/a/a",
689 "a/a/f -> ../../f",
690 "b -> a",
691 "c -> a/a",
692 "d -> c",
693 "e -> a/a/a",
694 "f",
695 "dangling -> missing",
696 }
697
698 mockFiles := make(map[string][]byte)
699
700 for _, f := range files {
701 mockFiles[f] = nil
702 }
703
704 mock := MockFs(mockFiles)
705
706 for _, testCase := range globDontFollowDanglingSymlinkTestCases {
707 t.Run(testCase.pattern, func(t *testing.T) {
708 testGlob(t, mock, testCase, DontFollowSymlinks)
709 })
710 }
711}
712
713func TestGlobDontFollowDanglingSymlinks(t *testing.T) {
714 os.Chdir("testdata/dangling")
715 defer os.Chdir("../..")
716
717 for _, testCase := range globDontFollowDanglingSymlinkTestCases {
718 t.Run(testCase.pattern, func(t *testing.T) {
719 testGlob(t, OsFs, testCase, DontFollowSymlinks)
720 })
721 }
722}
723
724func testGlob(t *testing.T, fs FileSystem, testCase globTestCase, follow ShouldFollowSymlinks) {
Colin Crossd9bea8f2018-09-21 14:13:03 -0700725 t.Helper()
Colin Crosse98d0822018-09-21 15:30:13 -0700726 matches, deps, err := fs.Glob(testCase.pattern, testCase.excludes, follow)
Colin Crossa4fae902017-10-03 15:58:50 -0700727 if err != testCase.err {
Colin Crossa4706122018-09-19 13:36:42 -0700728 if err == nil {
729 t.Fatalf("missing error: %s", testCase.err)
730 } else {
731 t.Fatalf("error: %s", err)
Colin Cross4b793e52015-04-23 13:29:28 -0700732 }
Colin Crossa4fae902017-10-03 15:58:50 -0700733 return
734 }
735
736 if !reflect.DeepEqual(matches, testCase.matches) {
737 t.Errorf("incorrect matches list:")
738 t.Errorf(" pattern: %q", testCase.pattern)
739 if testCase.excludes != nil {
740 t.Errorf("excludes: %q", testCase.excludes)
Colin Cross4b793e52015-04-23 13:29:28 -0700741 }
Colin Crossa4fae902017-10-03 15:58:50 -0700742 t.Errorf(" got: %#v", matches)
743 t.Errorf("expected: %#v", testCase.matches)
744 }
745 if !reflect.DeepEqual(deps, testCase.deps) {
746 t.Errorf("incorrect deps list:")
747 t.Errorf(" pattern: %q", testCase.pattern)
748 if testCase.excludes != nil {
749 t.Errorf("excludes: %q", testCase.excludes)
750 }
751 t.Errorf(" got: %#v", deps)
752 t.Errorf("expected: %#v", testCase.deps)
Colin Cross4b793e52015-04-23 13:29:28 -0700753 }
754}
Colin Crossc0c3b0f2018-07-13 21:17:48 -0700755
756func TestMatch(t *testing.T) {
757 testCases := []struct {
758 pattern, name string
759 match bool
760 }{
761 {"a/*", "b/", false},
762 {"a/*", "b/a", false},
763 {"a/*", "b/b/", false},
764 {"a/*", "b/b/c", false},
765 {"a/**/*", "b/", false},
766 {"a/**/*", "b/a", false},
767 {"a/**/*", "b/b/", false},
768 {"a/**/*", "b/b/c", false},
769
770 {"a/*", "a/", false},
771 {"a/*", "a/a", true},
772 {"a/*", "a/b/", false},
773 {"a/*", "a/b/c", false},
774
775 {"a/*/", "a/", false},
776 {"a/*/", "a/a", false},
777 {"a/*/", "a/b/", true},
778 {"a/*/", "a/b/c", false},
779
780 {"a/**/*", "a/", false},
781 {"a/**/*", "a/a", true},
782 {"a/**/*", "a/b/", false},
783 {"a/**/*", "a/b/c", true},
784
785 {"a/**/*/", "a/", false},
786 {"a/**/*/", "a/a", false},
787 {"a/**/*/", "a/b/", true},
788 {"a/**/*/", "a/b/c", false},
Colin Crossa4706122018-09-19 13:36:42 -0700789
Colin Crossa4cc6832019-03-25 15:04:17 -0700790 {"**/*", "a/", false},
791 {"**/*", "a/a", true},
792 {"**/*", "a/b/", false},
793 {"**/*", "a/b/c", true},
794
795 {"**/*/", "a/", true},
796 {"**/*/", "a/a", false},
797 {"**/*/", "a/b/", true},
798 {"**/*/", "a/b/c", false},
799
Colin Crossa4706122018-09-19 13:36:42 -0700800 {`a/\*\*/\*`, `a/**/*`, true},
801 {`a/\*\*/\*`, `a/a/*`, false},
802 {`a/\*\*/\*`, `a/**/a`, false},
803 {`a/\*\*/\*`, `a/a/a`, false},
804
805 {`a/**/\*`, `a/**/*`, true},
806 {`a/**/\*`, `a/a/*`, true},
807 {`a/**/\*`, `a/**/a`, false},
808 {`a/**/\*`, `a/a/a`, false},
809
810 {`a/\*\*/*`, `a/**/*`, true},
811 {`a/\*\*/*`, `a/a/*`, false},
812 {`a/\*\*/*`, `a/**/a`, true},
813 {`a/\*\*/*`, `a/a/a`, false},
814
815 {`*/**/a`, `a/a/a`, true},
816 {`*/**/a`, `*/a/a`, true},
817 {`*/**/a`, `a/**/a`, true},
818 {`*/**/a`, `*/**/a`, true},
819
820 {`\*/\*\*/a`, `a/a/a`, false},
821 {`\*/\*\*/a`, `*/a/a`, false},
822 {`\*/\*\*/a`, `a/**/a`, false},
823 {`\*/\*\*/a`, `*/**/a`, true},
824
825 {`a/?`, `a/?`, true},
826 {`a/?`, `a/a`, true},
827 {`a/\?`, `a/?`, true},
828 {`a/\?`, `a/a`, false},
829
830 {`a/?`, `a/?`, true},
831 {`a/?`, `a/a`, true},
832 {`a/\?`, `a/?`, true},
833 {`a/\?`, `a/a`, false},
834
835 {`a/[a-c]`, `a/b`, true},
836 {`a/[abc]`, `a/b`, true},
837
838 {`a/\[abc]`, `a/b`, false},
839 {`a/\[abc]`, `a/[abc]`, true},
840
841 {`a/\[abc\]`, `a/b`, false},
842 {`a/\[abc\]`, `a/[abc]`, true},
843
844 {`a/?`, `a/?`, true},
845 {`a/?`, `a/a`, true},
846 {`a/\?`, `a/?`, true},
847 {`a/\?`, `a/a`, false},
Colin Crossa4cc6832019-03-25 15:04:17 -0700848
849 {"/a/*", "/a/", false},
850 {"/a/*", "/a/a", true},
851 {"/a/*", "/a/b/", false},
852 {"/a/*", "/a/b/c", false},
853
854 {"/a/*/", "/a/", false},
855 {"/a/*/", "/a/a", false},
856 {"/a/*/", "/a/b/", true},
857 {"/a/*/", "/a/b/c", false},
858
859 {"/a/**/*", "/a/", false},
860 {"/a/**/*", "/a/a", true},
861 {"/a/**/*", "/a/b/", false},
862 {"/a/**/*", "/a/b/c", true},
863
864 {"/**/*", "/a/", false},
865 {"/**/*", "/a/a", true},
866 {"/**/*", "/a/b/", false},
867 {"/**/*", "/a/b/c", true},
868
869 {"/**/*/", "/a/", true},
870 {"/**/*/", "/a/a", false},
871 {"/**/*/", "/a/b/", true},
872 {"/**/*/", "/a/b/c", false},
873
874 {`a`, `/a`, false},
875 {`/a`, `a`, false},
876 {`*`, `/a`, false},
877 {`/*`, `a`, false},
878 {`**/*`, `/a`, false},
879 {`/**/*`, `a`, false},
Colin Crossc0c3b0f2018-07-13 21:17:48 -0700880 }
881
882 for _, test := range testCases {
883 t.Run(test.pattern+","+test.name, func(t *testing.T) {
884 match, err := Match(test.pattern, test.name)
885 if err != nil {
886 t.Fatal(err)
887 }
888 if match != test.match {
889 t.Errorf("want: %v, got %v", test.match, match)
890 }
891 })
892 }
Colin Crossa4cc6832019-03-25 15:04:17 -0700893
894 // Run the same test cases through Glob
895 for _, test := range testCases {
896 // Glob and Match disagree on matching directories
897 if strings.HasSuffix(test.name, "/") || strings.HasSuffix(test.pattern, "/") {
898 continue
899 }
900 t.Run("glob:"+test.pattern+","+test.name, func(t *testing.T) {
901 mockFiles := map[string][]byte{
902 test.name: nil,
903 }
904
905 mock := MockFs(mockFiles)
906
907 matches, _, err := mock.Glob(test.pattern, nil, DontFollowSymlinks)
908 t.Log(test.name, test.pattern, matches)
909 if err != nil {
910 t.Fatal(err)
911 }
912
913 match := false
914 for _, x := range matches {
915 if x == test.name {
916 match = true
917 }
918 }
919
920 if match != test.match {
921 t.Errorf("want: %v, got %v", test.match, match)
922 }
923 })
924 }
Colin Crossc0c3b0f2018-07-13 21:17:48 -0700925}