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 15 package pathtools 16 17 import ( 18 "os" 19 "path/filepath" 20 "reflect" 21 "testing" 22 ) 23 24 var pwd, _ = os.Getwd() 25 26 var globTestCases = []struct { 27 pattern string 28 matches []string 29 excludes []string 30 dirs []string 31 err error 32 }{ 33 // Current directory tests 34 { 35 pattern: "*", 36 matches: []string{"a", "b", "c", "d.ext", "e.ext"}, 37 dirs: []string{"."}, 38 }, 39 { 40 pattern: "*.ext", 41 matches: []string{"d.ext", "e.ext"}, 42 dirs: []string{"."}, 43 }, 44 { 45 pattern: "*/a", 46 matches: []string{"a/a", "b/a"}, 47 dirs: []string{".", "a", "b", "c"}, 48 }, 49 { 50 pattern: "*/*/a", 51 matches: []string{"a/a/a"}, 52 dirs: []string{".", "a", "b", "c", "a/a", "a/b", "c/f", "c/g", "c/h"}, 53 }, 54 { 55 pattern: "*/a/a", 56 matches: []string{"a/a/a"}, 57 dirs: []string{".", "a", "b", "c", "a/a"}, 58 }, 59 60 // ./ directory tests 61 { 62 pattern: "./*", 63 matches: []string{"a", "b", "c", "d.ext", "e.ext"}, 64 dirs: []string{"."}, 65 }, 66 { 67 pattern: "./*.ext", 68 matches: []string{"d.ext", "e.ext"}, 69 dirs: []string{"."}, 70 }, 71 { 72 pattern: "./*/a", 73 matches: []string{"a/a", "b/a"}, 74 dirs: []string{".", "a", "b", "c"}, 75 }, 76 { 77 pattern: "./[ac]/a", 78 matches: []string{"a/a"}, 79 dirs: []string{".", "a", "c"}, 80 }, 81 82 // subdirectory tests 83 { 84 pattern: "c/*/*.ext", 85 matches: []string{"c/f/f.ext", "c/g/g.ext"}, 86 dirs: []string{"c", "c/f", "c/g", "c/h"}, 87 }, 88 { 89 pattern: "a/*/a", 90 matches: []string{"a/a/a"}, 91 dirs: []string{"a", "a/a", "a/b"}, 92 }, 93 94 // absolute tests 95 { 96 pattern: filepath.Join(pwd, "testdata/c/*/*.ext"), 97 matches: []string{ 98 filepath.Join(pwd, "testdata/c/f/f.ext"), 99 filepath.Join(pwd, "testdata/c/g/g.ext"), 100 }, 101 dirs: []string{ 102 filepath.Join(pwd, "testdata/c"), 103 filepath.Join(pwd, "testdata/c/f"), 104 filepath.Join(pwd, "testdata/c/g"), 105 filepath.Join(pwd, "testdata/c/h"), 106 }, 107 }, 108 109 // no-wild tests 110 { 111 pattern: "a", 112 matches: []string{"a"}, 113 dirs: nil, 114 }, 115 { 116 pattern: "a/a", 117 matches: []string{"a/a"}, 118 dirs: nil, 119 }, 120 121 // clean tests 122 { 123 pattern: "./c/*/*.ext", 124 matches: []string{"c/f/f.ext", "c/g/g.ext"}, 125 dirs: []string{"c", "c/f", "c/g", "c/h"}, 126 }, 127 { 128 pattern: "c/../c/*/*.ext", 129 matches: []string{"c/f/f.ext", "c/g/g.ext"}, 130 dirs: []string{"c", "c/f", "c/g", "c/h"}, 131 }, 132 133 // recursive tests 134 { 135 pattern: "**/a", 136 matches: []string{"a", "a/a", "a/a/a", "b/a"}, 137 dirs: []string{".", "a", "a/a", "a/b", "b", "c", "c/f", "c/g", "c/h"}, 138 }, 139 { 140 pattern: "a/**/a", 141 matches: []string{"a/a", "a/a/a"}, 142 dirs: []string{"a", "a/a", "a/b"}, 143 }, 144 { 145 pattern: "a/**/*", 146 matches: []string{"a/a", "a/b", "a/a/a", "a/b/b"}, 147 dirs: []string{"a", "a/a", "a/b"}, 148 }, 149 150 // absolute recursive tests 151 { 152 pattern: filepath.Join(pwd, "testdata/**/*.ext"), 153 matches: []string{ 154 filepath.Join(pwd, "testdata/d.ext"), 155 filepath.Join(pwd, "testdata/e.ext"), 156 filepath.Join(pwd, "testdata/c/f/f.ext"), 157 filepath.Join(pwd, "testdata/c/g/g.ext"), 158 }, 159 dirs: []string{ 160 filepath.Join(pwd, "testdata"), 161 filepath.Join(pwd, "testdata/a"), 162 filepath.Join(pwd, "testdata/a/a"), 163 filepath.Join(pwd, "testdata/a/b"), 164 filepath.Join(pwd, "testdata/b"), 165 filepath.Join(pwd, "testdata/c"), 166 filepath.Join(pwd, "testdata/c/f"), 167 filepath.Join(pwd, "testdata/c/g"), 168 filepath.Join(pwd, "testdata/c/h"), 169 }, 170 }, 171 172 // recursive error tests 173 { 174 pattern: "**/**/*", 175 err: GlobMultipleRecursiveErr, 176 }, 177 { 178 pattern: "a/**/**/*", 179 err: GlobMultipleRecursiveErr, 180 }, 181 { 182 pattern: "**/a/**/*", 183 err: GlobMultipleRecursiveErr, 184 }, 185 { 186 pattern: "**/**/a/*", 187 err: GlobMultipleRecursiveErr, 188 }, 189 { 190 pattern: "a/**", 191 err: GlobLastRecursiveErr, 192 }, 193 { 194 pattern: "**/**", 195 err: GlobLastRecursiveErr, 196 }, 197 198 // exclude tests 199 { 200 pattern: "*.ext", 201 excludes: []string{"d.ext"}, 202 matches: []string{"e.ext"}, 203 dirs: []string{"."}, 204 }, 205 { 206 pattern: "*/*", 207 excludes: []string{"a/b"}, 208 matches: []string{"a/a", "b/a", "c/c", "c/f", "c/g", "c/h"}, 209 dirs: []string{".", "a", "b", "c"}, 210 }, 211 { 212 pattern: "*/*", 213 excludes: []string{"a/b", "c/c"}, 214 matches: []string{"a/a", "b/a", "c/f", "c/g", "c/h"}, 215 dirs: []string{".", "a", "b", "c"}, 216 }, 217 { 218 pattern: "*/*", 219 excludes: []string{"c/*", "*/a"}, 220 matches: []string{"a/b"}, 221 dirs: []string{".", "a", "b", "c"}, 222 }, 223 { 224 pattern: "*/*", 225 excludes: []string{"*/*"}, 226 matches: nil, 227 dirs: []string{".", "a", "b", "c"}, 228 }, 229 230 // absolute exclude tests 231 { 232 pattern: filepath.Join(pwd, "testdata/c/*/*.ext"), 233 excludes: []string{filepath.Join(pwd, "testdata/c/*/f.ext")}, 234 matches: []string{ 235 filepath.Join(pwd, "testdata/c/g/g.ext"), 236 }, 237 dirs: []string{ 238 filepath.Join(pwd, "testdata/c"), 239 filepath.Join(pwd, "testdata/c/f"), 240 filepath.Join(pwd, "testdata/c/g"), 241 filepath.Join(pwd, "testdata/c/h"), 242 }, 243 }, 244 { 245 pattern: filepath.Join(pwd, "testdata/c/*/*.ext"), 246 excludes: []string{filepath.Join(pwd, "testdata/c/f/*.ext")}, 247 matches: []string{ 248 filepath.Join(pwd, "testdata/c/g/g.ext"), 249 }, 250 dirs: []string{ 251 filepath.Join(pwd, "testdata/c"), 252 filepath.Join(pwd, "testdata/c/f"), 253 filepath.Join(pwd, "testdata/c/g"), 254 filepath.Join(pwd, "testdata/c/h"), 255 }, 256 }, 257 258 // recursive exclude tests 259 { 260 pattern: "*.ext", 261 excludes: []string{"**/*.ext"}, 262 matches: nil, 263 dirs: []string{"."}, 264 }, 265 { 266 pattern: "*/*", 267 excludes: []string{"**/b"}, 268 matches: []string{"a/a", "b/a", "c/c", "c/f", "c/g", "c/h"}, 269 dirs: []string{".", "a", "b", "c"}, 270 }, 271 { 272 pattern: "*/*", 273 excludes: []string{"a/**/*"}, 274 matches: []string{"b/a", "c/c", "c/f", "c/g", "c/h"}, 275 dirs: []string{".", "a", "b", "c"}, 276 }, 277 { 278 pattern: "**/*", 279 excludes: []string{"**/*"}, 280 matches: nil, 281 dirs: []string{".", "a", "a/a", "a/b", "b", "c", "c/f", "c/g", "c/h"}, 282 }, 283 { 284 pattern: "*/*/*", 285 excludes: []string{"a/**/a"}, 286 matches: []string{"a/b/b", "c/f/f.ext", "c/g/g.ext", "c/h/h"}, 287 dirs: []string{".", "a", "b", "c", "a/a", "a/b", "c/f", "c/g", "c/h"}, 288 }, 289 { 290 pattern: "*/*/*", 291 excludes: []string{"**/a"}, 292 matches: []string{"a/b/b", "c/f/f.ext", "c/g/g.ext", "c/h/h"}, 293 dirs: []string{".", "a", "b", "c", "a/a", "a/b", "c/f", "c/g", "c/h"}, 294 }, 295 { 296 pattern: "c/*/*.ext", 297 excludes: []string{"c/**/f.ext"}, 298 matches: []string{"c/g/g.ext"}, 299 dirs: []string{"c", "c/f", "c/g", "c/h"}, 300 }, 301 302 // absoulte recursive exclude tests 303 { 304 pattern: filepath.Join(pwd, "testdata/c/*/*.ext"), 305 excludes: []string{filepath.Join(pwd, "testdata/**/f.ext")}, 306 matches: []string{ 307 filepath.Join(pwd, "testdata/c/g/g.ext"), 308 }, 309 dirs: []string{ 310 filepath.Join(pwd, "testdata/c"), 311 filepath.Join(pwd, "testdata/c/f"), 312 filepath.Join(pwd, "testdata/c/g"), 313 filepath.Join(pwd, "testdata/c/h"), 314 }, 315 }, 316 317 // clean exclude tests 318 { 319 pattern: "./c/*/*.ext", 320 excludes: []string{"./c/*/f.ext"}, 321 matches: []string{"c/g/g.ext"}, 322 dirs: []string{"c", "c/f", "c/g", "c/h"}, 323 }, 324 { 325 pattern: "c/*/*.ext", 326 excludes: []string{"./c/*/f.ext"}, 327 matches: []string{"c/g/g.ext"}, 328 dirs: []string{"c", "c/f", "c/g", "c/h"}, 329 }, 330 { 331 pattern: "./c/*/*.ext", 332 excludes: []string{"c/*/f.ext"}, 333 matches: []string{"c/g/g.ext"}, 334 dirs: []string{"c", "c/f", "c/g", "c/h"}, 335 }, 336 337 // non-existant non-wild path tests 338 { 339 pattern: "d/*", 340 matches: nil, 341 dirs: []string{"."}, 342 }, 343 { 344 pattern: "d", 345 matches: nil, 346 dirs: []string{"."}, 347 }, 348 { 349 pattern: "a/d/*", 350 matches: nil, 351 dirs: []string{"a"}, 352 }, 353 { 354 pattern: "a/d", 355 matches: nil, 356 dirs: []string{"a"}, 357 }, 358 { 359 pattern: "a/a/d/*", 360 matches: nil, 361 dirs: []string{"a/a"}, 362 }, 363 { 364 pattern: "a/a/d", 365 matches: nil, 366 dirs: []string{"a/a"}, 367 }, 368 { 369 pattern: "a/d/a/*", 370 matches: nil, 371 dirs: []string{"a"}, 372 }, 373 { 374 pattern: "a/d/a", 375 matches: nil, 376 dirs: []string{"a"}, 377 }, 378 { 379 pattern: "a/d/a/*/a", 380 matches: nil, 381 dirs: []string{"a"}, 382 }, 383 { 384 pattern: "a/d/a/**/a", 385 matches: nil, 386 dirs: []string{"a"}, 387 }, 388 389 // recursive exclude error tests 390 { 391 pattern: "**/*", 392 excludes: []string{"**/**/*"}, 393 err: GlobMultipleRecursiveErr, 394 }, 395 { 396 pattern: "**/*", 397 excludes: []string{"a/**/**/*"}, 398 err: GlobMultipleRecursiveErr, 399 }, 400 { 401 pattern: "**/*", 402 excludes: []string{"**/a/**/*"}, 403 err: GlobMultipleRecursiveErr, 404 }, 405 { 406 pattern: "**/*", 407 excludes: []string{"**/**/a/*"}, 408 err: GlobMultipleRecursiveErr, 409 }, 410 { 411 pattern: "**/*", 412 excludes: []string{"a/**"}, 413 err: GlobLastRecursiveErr, 414 }, 415 { 416 pattern: "**/*", 417 excludes: []string{"**/**"}, 418 err: GlobLastRecursiveErr, 419 }, 420 } 421 422 func TestGlob(t *testing.T) { 423 os.Chdir("testdata") 424 defer os.Chdir("..") 425 for _, testCase := range globTestCases { 426 matches, dirs, err := GlobWithExcludes(testCase.pattern, testCase.excludes) 427 if err != testCase.err { 428 t.Errorf(" pattern: %q", testCase.pattern) 429 if testCase.excludes != nil { 430 t.Errorf("excludes: %q", testCase.excludes) 431 } 432 t.Errorf(" error: %s", err) 433 continue 434 } 435 436 if !reflect.DeepEqual(matches, testCase.matches) { 437 t.Errorf("incorrect matches list:") 438 t.Errorf(" pattern: %q", testCase.pattern) 439 if testCase.excludes != nil { 440 t.Errorf("excludes: %q", testCase.excludes) 441 } 442 t.Errorf(" got: %#v", matches) 443 t.Errorf("expected: %#v", testCase.matches) 444 } 445 if !reflect.DeepEqual(dirs, testCase.dirs) { 446 t.Errorf("incorrect dirs list:") 447 t.Errorf(" pattern: %q", testCase.pattern) 448 if testCase.excludes != nil { 449 t.Errorf("excludes: %q", testCase.excludes) 450 } 451 t.Errorf(" got: %#v", dirs) 452 t.Errorf("expected: %#v", testCase.dirs) 453 } 454 } 455 } 456