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