github.com/boyter/gocodewalker@v1.3.2/go-gitignore/defn_test.go (about) 1 // SPDX-License-Identifier: MIT 2 3 package gitignore_test 4 5 import ( 6 "github.com/boyter/gocodewalker/go-gitignore" 7 "path/filepath" 8 "strings" 9 ) 10 11 type token struct { 12 Type gitignore.TokenType 13 Name string 14 Token string 15 Line int 16 Column int 17 NewLine int // token offset for newline end of line 18 CarriageReturn int // token offset for carriage return end of line 19 } // token{} 20 21 type match struct { 22 Path string // test path 23 Pattern string // matching pattern (if any) 24 Ignore bool // whether the path is ignored or included 25 Exclude bool // whether the match comes from the GIT_DIR/info/exclude file 26 } // match{} 27 28 func (m match) Local() string { 29 _path := m.Path 30 if m.IsDir() { 31 _path = strings.TrimSuffix(m.Path, "/") 32 } 33 34 // generate the local representation of the match path 35 return filepath.Join(strings.Split(_path, "/")...) 36 } // Local() 37 38 func (m match) IsDir() bool { 39 return strings.HasSuffix(m.Path, "/") 40 } // IsDir() 41 42 type position struct { 43 File string 44 Line int 45 Column int 46 Offset int 47 String string 48 } // position{} 49 50 // define the constants for the unit tests 51 const ( 52 // define the example .gitignore file contents 53 _GITIGNORE = ` 54 # example .gitignore 55 56 !*.go 57 58 *.o 59 *.a 60 61 /ignore/this/path/ 62 63 # the following line has trailing whitespace 64 /and/**/all/**/these/** 65 !/but/not/this\ 66 67 we support spaces 68 69 /**/this.is.not/a ** valid/pattern 70 /**/nor/is/***/this 71 /nor/is***this 72 northis** x 73 74 but \this\ is / valid\# 75 \ 76 77 so is this# 78 and this is #3 ok too 79 / // 80 ` 81 82 // define the example .gitignore file contents for the Match tests 83 // these tests have been taken from 84 // https://github.com/sdobz/backup/gitignore 85 // 86 // https://github.com/sdobz/backup/blob/master/gitignore/gitignore_test.go 87 _GITMATCH = ` 88 89 *.[oa] 90 *.html 91 *.min.js 92 93 !foo*.html 94 foo-excl.html 95 96 vmlinux* 97 98 \!important!.txt 99 100 log/*.log 101 !/log/foo.log 102 103 **/logdir/log 104 **/foodir/bar 105 exclude/** 106 107 !findthis* 108 109 **/hide/** 110 subdir/subdir2/ 111 112 /rootsubdir/ 113 114 dirpattern/ 115 116 README.md 117 118 # arch/foo/kernel/.gitignore 119 !arch/foo/kernel/vmlinux* 120 121 # htmldoc/.gitignore 122 !htmldoc/*.html 123 124 # git-sample-3/.gitignore 125 git-sample-3/* 126 !git-sample-3/foo 127 git-sample-3/foo/* 128 !git-sample-3/foo/bar 129 130 Documentation/*.pdf 131 Documentation/**/p*.pdf 132 ` 133 134 // define the number of good & bad patterns in the .gitignore above 135 _GITPATTERNS = 12 136 _GITBADPATTERNS = 4 137 138 // define the number of good & bad patterns in the match .gitignore above 139 _GITMATCHPATTERNS = 24 140 _GITBADMATCHPATTERNS = 0 141 142 // define the number of good and bad patterns returned when the 143 // gitignore.Parser error handler returns false upon receiving an error 144 _GITPATTERNSFALSE = 7 145 _GITBADPATTERNSFALSE = 1 146 147 // define the base path for a git repository 148 _GITBASE = "/my/git/repository" 149 150 // define the directory mask for any directories created during testing 151 _GITMASK = 0700 152 153 // define a .gitignore that will trigger lexer errors 154 _GITINVALID = "" + 155 "# the following two lines will trigger repeated lexer errors\n" + 156 "x\rx\rx\rx\n" + 157 "\rx\rx\rx\n" + 158 "!\rx\n" + 159 "/my/valid/pattern\n" + 160 "!\n" + 161 "** *\n" + 162 "/\r" 163 164 // define the number of invalid patterns and errors 165 _GITINVALIDERRORS = 10 166 _GITINVALIDERRORSFALSE = 1 167 _GITINVALIDPATTERNS = 1 168 _GITINVALIDPATTERNSFALSE = 0 169 170 // define the expected number of errors during repository matching 171 _GITREPOSITORYERRORS = 38 172 _GITREPOSITORYERRORSFALSE = 1 173 174 // define a .gitignore file the contains just whitespace & comments 175 _GITIGNORE_WHITESPACE = ` 176 # this is an empty .gitignore file 177 # - the following lines contains just whitespace 178 179 180 ` 181 ) 182 183 var ( 184 // define the positions of the bad patterns 185 _GITBADPOSITION = []gitignore.Position{ 186 {File: "", Line: 17, Column: 19, Offset: 189}, 187 {File: "", Line: 18, Column: 14, Offset: 219}, 188 {File: "", Line: 19, Column: 8, Offset: 233}, 189 {File: "", Line: 20, Column: 8, Offset: 248}, 190 } 191 192 // define the positions of the good patterns 193 _GITPOSITION = []gitignore.Position{ 194 {File: "", Line: 4, Column: 1, Offset: 23}, 195 {File: "", Line: 6, Column: 1, Offset: 30}, 196 {File: "", Line: 7, Column: 1, Offset: 34}, 197 {File: "", Line: 9, Column: 1, Offset: 39}, 198 {File: "", Line: 12, Column: 1, Offset: 104}, 199 {File: "", Line: 13, Column: 1, Offset: 132}, 200 {File: "", Line: 15, Column: 1, Offset: 150}, 201 {File: "", Line: 22, Column: 1, Offset: 256}, 202 {File: "", Line: 23, Column: 1, Offset: 280}, 203 {File: "", Line: 25, Column: 1, Offset: 283}, 204 {File: "", Line: 26, Column: 1, Offset: 295}, 205 {File: "", Line: 27, Column: 1, Offset: 317}, 206 } 207 208 // define the token stream for the _GITIGNORE .gitignore 209 _GITTOKENS = []token{ 210 // 1: 211 {gitignore.EOL, "EOL", "\n", 1, 1, 0, 0}, 212 // 2: # example .gitignore contents 213 {gitignore.COMMENT, "COMMENT", "# example .gitignore", 2, 1, 1, 2}, 214 {gitignore.EOL, "EOL", "\n", 2, 21, 21, 22}, 215 // 3: 216 {gitignore.EOL, "EOL", "\n", 3, 1, 22, 24}, 217 // 4: !*.go 218 {gitignore.NEGATION, "NEGATION", "!", 4, 1, 23, 26}, 219 {gitignore.PATTERN, "PATTERN", "*.go", 4, 2, 24, 27}, 220 {gitignore.EOL, "EOL", "\n", 4, 6, 28, 31}, 221 // 5: 222 {gitignore.EOL, "EOL", "\n", 5, 1, 29, 33}, 223 // 6: *.o 224 {gitignore.PATTERN, "PATTERN", "*.o", 6, 1, 30, 35}, 225 {gitignore.EOL, "EOL", "\n", 6, 4, 33, 38}, 226 // 7: *.a 227 {gitignore.PATTERN, "PATTERN", "*.a", 7, 1, 34, 40}, 228 {gitignore.EOL, "EOL", "\n", 7, 4, 37, 43}, 229 // 8: 230 {gitignore.EOL, "EOL", "\n", 8, 1, 38, 45}, 231 // 9: /ignore/this/path/ 232 {gitignore.SEPARATOR, "SEPARATOR", "/", 9, 1, 39, 47}, 233 {gitignore.PATTERN, "PATTERN", "ignore", 9, 2, 40, 48}, 234 {gitignore.SEPARATOR, "SEPARATOR", "/", 9, 8, 46, 54}, 235 {gitignore.PATTERN, "PATTERN", "this", 9, 9, 47, 55}, 236 {gitignore.SEPARATOR, "SEPARATOR", "/", 9, 13, 51, 59}, 237 {gitignore.PATTERN, "PATTERN", "path", 9, 14, 52, 60}, 238 {gitignore.SEPARATOR, "SEPARATOR", "/", 9, 18, 56, 64}, 239 {gitignore.EOL, "EOL", "\n", 9, 19, 57, 65}, 240 // 10: 241 {gitignore.EOL, "EOL", "\n", 10, 1, 58, 67}, 242 // 11: # the following line has trailing whitespace 243 {gitignore.COMMENT, "COMMENT", 244 "# the following line has trailing whitespace", 245 11, 1, 59, 69}, 246 {gitignore.EOL, "EOL", "\n", 11, 45, 103, 113}, 247 // 12: /and/**/all/**/these/** 248 {gitignore.SEPARATOR, "SEPARATOR", "/", 12, 1, 104, 115}, 249 {gitignore.PATTERN, "PATTERN", "and", 12, 2, 105, 116}, 250 {gitignore.SEPARATOR, "SEPARATOR", "/", 12, 5, 108, 119}, 251 {gitignore.ANY, "ANY", "**", 12, 6, 109, 120}, 252 {gitignore.SEPARATOR, "SEPARATOR", "/", 12, 8, 111, 122}, 253 {gitignore.PATTERN, "PATTERN", "all", 12, 9, 112, 123}, 254 {gitignore.SEPARATOR, "SEPARATOR", "/", 12, 12, 115, 126}, 255 {gitignore.ANY, "ANY", "**", 12, 13, 116, 127}, 256 {gitignore.SEPARATOR, "SEPARATOR", "/", 12, 15, 118, 129}, 257 {gitignore.PATTERN, "PATTERN", "these", 12, 16, 119, 130}, 258 {gitignore.SEPARATOR, "SEPARATOR", "/", 12, 21, 124, 135}, 259 {gitignore.ANY, "ANY", "**", 12, 22, 125, 136}, 260 {gitignore.WHITESPACE, "WHITESPACE", " \t ", 12, 24, 127, 138}, 261 {gitignore.EOL, "EOL", "\n", 12, 28, 131, 142}, 262 // 13: !/but/not/this\ 263 {gitignore.NEGATION, "NEGATION", "!", 13, 1, 132, 144}, 264 {gitignore.SEPARATOR, "SEPARATOR", "/", 13, 2, 133, 145}, 265 {gitignore.PATTERN, "PATTERN", "but", 13, 3, 134, 146}, 266 {gitignore.SEPARATOR, "SEPARATOR", "/", 13, 6, 137, 149}, 267 {gitignore.PATTERN, "PATTERN", "not", 13, 7, 138, 150}, 268 {gitignore.SEPARATOR, "SEPARATOR", "/", 13, 10, 141, 153}, 269 {gitignore.PATTERN, "PATTERN", "this\\ ", 13, 11, 142, 154}, 270 {gitignore.EOL, "EOL", "\n", 13, 17, 148, 160}, 271 // 14: 272 {gitignore.EOL, "EOL", "\n", 14, 1, 149, 162}, 273 // 15: we support spaces 274 {gitignore.PATTERN, "PATTERN", "we", 15, 1, 150, 164}, 275 {gitignore.WHITESPACE, "WHITESPACE", " ", 15, 3, 152, 166}, 276 {gitignore.PATTERN, "PATTERN", "support", 15, 4, 153, 167}, 277 {gitignore.WHITESPACE, "WHITESPACE", " ", 15, 11, 160, 174}, 278 {gitignore.PATTERN, "PATTERN", "spaces", 15, 14, 163, 177}, 279 {gitignore.EOL, "EOL", "\n", 15, 20, 169, 183}, 280 // 16: 281 {gitignore.EOL, "EOL", "\n", 16, 1, 170, 185}, 282 // 17: /**/this.is.not/a ** valid/pattern 283 {gitignore.SEPARATOR, "SEPARATOR", "/", 17, 1, 171, 187}, 284 {gitignore.ANY, "ANY", "**", 17, 2, 172, 188}, 285 {gitignore.SEPARATOR, "SEPARATOR", "/", 17, 4, 174, 190}, 286 {gitignore.PATTERN, "PATTERN", "this.is.not", 17, 5, 175, 191}, 287 {gitignore.SEPARATOR, "SEPARATOR", "/", 17, 16, 186, 202}, 288 {gitignore.PATTERN, "PATTERN", "a", 17, 17, 187, 203}, 289 {gitignore.WHITESPACE, "WHITESPACE", " ", 17, 18, 188, 204}, 290 {gitignore.ANY, "ANY", "**", 17, 19, 189, 205}, 291 {gitignore.WHITESPACE, "WHITESPACE", " ", 17, 21, 191, 207}, 292 {gitignore.PATTERN, "PATTERN", "valid", 17, 22, 192, 208}, 293 {gitignore.SEPARATOR, "SEPARATOR", "/", 17, 27, 197, 213}, 294 {gitignore.PATTERN, "PATTERN", "pattern", 17, 28, 198, 214}, 295 {gitignore.EOL, "EOL", "\n", 17, 35, 205, 221}, 296 // 18: /**/nor/is/***/this 297 {gitignore.SEPARATOR, "SEPARATOR", "/", 18, 1, 206, 223}, 298 {gitignore.ANY, "ANY", "**", 18, 2, 207, 224}, 299 {gitignore.SEPARATOR, "SEPARATOR", "/", 18, 4, 209, 226}, 300 {gitignore.PATTERN, "PATTERN", "nor", 18, 5, 210, 227}, 301 {gitignore.SEPARATOR, "SEPARATOR", "/", 18, 8, 213, 230}, 302 {gitignore.PATTERN, "PATTERN", "is", 18, 9, 214, 231}, 303 {gitignore.SEPARATOR, "SEPARATOR", "/", 18, 11, 216, 233}, 304 {gitignore.ANY, "ANY", "**", 18, 12, 217, 234}, 305 {gitignore.PATTERN, "PATTERN", "*", 18, 14, 219, 236}, 306 {gitignore.SEPARATOR, "SEPARATOR", "/", 18, 15, 220, 237}, 307 {gitignore.PATTERN, "PATTERN", "this", 18, 16, 221, 238}, 308 {gitignore.EOL, "EOL", "\n", 18, 20, 225, 242}, 309 // 19: /nor/is***this 310 {gitignore.SEPARATOR, "SEPARATOR", "/", 19, 1, 226, 244}, 311 {gitignore.PATTERN, "PATTERN", "nor", 19, 2, 227, 245}, 312 {gitignore.SEPARATOR, "SEPARATOR", "/", 19, 5, 230, 248}, 313 {gitignore.PATTERN, "PATTERN", "is", 19, 6, 231, 249}, 314 {gitignore.ANY, "ANY", "**", 19, 8, 233, 251}, 315 {gitignore.PATTERN, "PATTERN", "*this", 19, 10, 235, 253}, 316 {gitignore.EOL, "EOL", "\n", 19, 15, 240, 258}, 317 // 20: northis** x 318 {gitignore.PATTERN, "PATTERN", "northis", 20, 1, 241, 260}, 319 {gitignore.ANY, "ANY", "**", 20, 8, 248, 267}, 320 {gitignore.WHITESPACE, "WHITESPACE", " \t ", 20, 10, 250, 269}, 321 {gitignore.PATTERN, "PATTERN", "x", 20, 13, 253, 272}, 322 {gitignore.EOL, "EOL", "\n", 20, 14, 254, 273}, 323 // 21: 324 {gitignore.EOL, "EOL", "\n", 21, 1, 255, 275}, 325 // 22: but \this\ is / valid 326 {gitignore.PATTERN, "PATTERN", "but", 22, 1, 256, 277}, 327 {gitignore.WHITESPACE, "WHITESPACE", " ", 22, 4, 259, 280}, 328 {gitignore.PATTERN, "PATTERN", "\\this\\ is", 22, 5, 260, 281}, 329 {gitignore.WHITESPACE, "WHITESPACE", " ", 22, 14, 269, 290}, 330 {gitignore.SEPARATOR, "SEPARATOR", "/", 22, 15, 270, 291}, 331 {gitignore.WHITESPACE, "WHITESPACE", " ", 22, 16, 271, 292}, 332 {gitignore.PATTERN, "PATTERN", "valid\\#", 22, 17, 272, 293}, 333 {gitignore.EOL, "EOL", "\n", 22, 24, 279, 300}, 334 // 23: \ 335 {gitignore.PATTERN, "PATTERN", "\\", 23, 1, 280, 302}, 336 {gitignore.EOL, "EOL", "\n", 23, 2, 281, 303}, 337 // 24: 338 {gitignore.EOL, "EOL", "\n", 24, 1, 282, 305}, 339 // 25: so is this# 340 {gitignore.PATTERN, "PATTERN", "so", 25, 1, 283, 307}, 341 {gitignore.WHITESPACE, "WHITESPACE", " ", 25, 3, 285, 309}, 342 {gitignore.PATTERN, "PATTERN", "is", 25, 4, 286, 310}, 343 {gitignore.WHITESPACE, "WHITESPACE", " ", 25, 6, 288, 312}, 344 {gitignore.PATTERN, "PATTERN", "this#", 25, 7, 289, 313}, 345 {gitignore.EOL, "EOL", "\n", 25, 12, 294, 318}, 346 // 26: and this is #3 ok too 347 {gitignore.PATTERN, "PATTERN", "and", 26, 1, 295, 320}, 348 {gitignore.WHITESPACE, "WHITESPACE", " ", 26, 4, 298, 323}, 349 {gitignore.PATTERN, "PATTERN", "this", 26, 5, 299, 324}, 350 {gitignore.WHITESPACE, "WHITESPACE", " ", 26, 9, 303, 328}, 351 {gitignore.PATTERN, "PATTERN", "is", 26, 10, 304, 329}, 352 {gitignore.WHITESPACE, "WHITESPACE", " ", 26, 12, 306, 331}, 353 {gitignore.PATTERN, "PATTERN", "#3", 26, 13, 307, 332}, 354 {gitignore.WHITESPACE, "WHITESPACE", " ", 26, 15, 309, 334}, 355 {gitignore.PATTERN, "PATTERN", "ok", 26, 16, 310, 335}, 356 {gitignore.WHITESPACE, "WHITESPACE", " ", 26, 18, 312, 337}, 357 {gitignore.PATTERN, "PATTERN", "too", 26, 19, 313, 338}, 358 {gitignore.EOL, "EOL", "\n", 26, 22, 316, 341}, 359 // 27: / // 360 {gitignore.WHITESPACE, "WHITESPACE", " ", 27, 1, 317, 343}, 361 {gitignore.SEPARATOR, "SEPARATOR", "/", 27, 2, 318, 344}, 362 {gitignore.WHITESPACE, "WHITESPACE", " ", 27, 3, 319, 345}, 363 {gitignore.SEPARATOR, "SEPARATOR", "/", 27, 4, 320, 346}, 364 {gitignore.SEPARATOR, "SEPARATOR", "/", 27, 5, 321, 347}, 365 {gitignore.EOL, "EOL", "\n", 27, 6, 322, 348}, 366 367 {gitignore.EOF, "EOF", "", 28, 1, 323, 350}, 368 } 369 370 // define match tests and their expected results 371 _GITMATCHES = []match{ 372 {"!important!.txt", "\\!important!.txt", true, false}, 373 {"arch/", "", false, false}, 374 {"arch/foo/", "", false, false}, 375 {"arch/foo/kernel/", "", false, false}, 376 {"arch/foo/kernel/vmlinux.lds.S", "!arch/foo/kernel/vmlinux*", false, false}, 377 {"arch/foo/vmlinux.lds.S", "vmlinux*", true, false}, 378 {"bar/", "", false, false}, 379 {"bar/testfile", "", false, false}, 380 {"dirpattern", "", false, false}, 381 {"my/other/path/to/dirpattern", "", false, false}, 382 {"my/path/to/dirpattern/", "dirpattern/", true, false}, 383 {"my/path/to/dirpattern/some_file.txt", "", false, false}, 384 {"Documentation/", "", false, false}, 385 {"Documentation/foo-excl.html", "foo-excl.html", true, false}, 386 {"Documentation/foo.html", "!foo*.html", false, false}, 387 {"Documentation/gitignore.html", "*.html", true, false}, 388 {"Documentation/test.a.html", "*.html", true, false}, 389 {"exclude/", "exclude/**", true, false}, 390 {"exclude/dir1/", "exclude/**", true, false}, 391 {"exclude/dir1/dir2/", "exclude/**", true, false}, 392 {"exclude/dir1/dir2/dir3/", "exclude/**", true, false}, 393 {"exclude/dir1/dir2/dir3/testfile", "exclude/**", true, false}, 394 {"exclude/other_file.txt", "exclude/**", true, false}, 395 {"file.o", "*.[oa]", true, false}, 396 {"foo/exclude/some_file.txt", "", false, false}, 397 {"foo/exclude/other/file.txt", "", false, false}, 398 {"foodir/", "", false, false}, 399 {"foodir/bar/", "**/foodir/bar", true, false}, 400 {"foodir/bar/testfile", "", false, false}, 401 {"git-sample-3/", "", false, false}, 402 {"git-sample-3/foo/", "!git-sample-3/foo", false, false}, 403 {"git-sample-3/foo/bar/", "!git-sample-3/foo/bar", false, false}, 404 {"git-sample-3/foo/test/", "git-sample-3/foo/*", true, false}, 405 {"git-sample-3/test/", "git-sample-3/*", true, false}, 406 {"htmldoc/", "", false, false}, 407 {"htmldoc/docs.html", "!htmldoc/*.html", false, false}, 408 {"htmldoc/jslib.min.js", "*.min.js", true, false}, 409 {"lib.a", "*.[oa]", true, false}, 410 {"log/", "", false, false}, 411 {"log/foo.log", "!/log/foo.log", false, false}, 412 {"log/test.log", "log/*.log", true, false}, 413 {"rootsubdir/", "/rootsubdir/", true, false}, 414 {"rootsubdir/foo", "", false, false}, 415 {"src/", "", false, false}, 416 {"src/findthis.o", "!findthis*", false, false}, 417 {"src/internal.o", "*.[oa]", true, false}, 418 {"subdir/", "", false, false}, 419 {"subdir/hide/", "**/hide/**", true, false}, 420 {"subdir/hide/foo", "**/hide/**", true, false}, 421 {"subdir/logdir/", "", false, false}, 422 {"subdir/logdir/log/", "**/logdir/log", true, false}, 423 {"subdir/logdir/log/findthis.log", "!findthis*", false, false}, 424 {"subdir/logdir/log/foo.log", "", false, false}, 425 {"subdir/logdir/log/test.log", "", false, false}, 426 {"subdir/rootsubdir/", "", false, false}, 427 {"subdir/rootsubdir/foo", "", false, false}, 428 {"subdir/subdir2/", "subdir/subdir2/", true, false}, 429 {"subdir/subdir2/bar", "", false, false}, 430 {"README.md", "README.md", true, false}, 431 {"my-path/README.md", "README.md", true, false}, 432 {"my-path/also/README.md", "README.md", true, false}, 433 {"Documentation/git.pdf", "Documentation/*.pdf", true, false}, 434 {"Documentation/ppc/ppc.pdf", "Documentation/**/p*.pdf", true, false}, 435 {"tools/perf/Documentation/perf.pdf", "", false, false}, 436 } 437 438 // define the cache tests 439 _CACHETEST = map[string]gitignore.GitIgnore{ 440 "a": null(), 441 "a/b": null(), 442 "a/b/c": nil, 443 } 444 445 // define a set of cache keys known not to be in the cache tests above 446 _CACHEUNKNOWN = []string{ 447 "b", 448 "b/c", 449 } 450 451 // define the set of .gitignore files for a repository 452 _GITREPOSITORY = map[string]string{ 453 // define the top-level .gitignore file 454 "": ` 455 # ignore .bak files 456 *.bak 457 `, 458 // define subdirectory .gitignore files 459 "a": ` 460 # ignore .go files 461 *.go 462 463 # ignore every c directory 464 # - this should be the same as c/ 465 **/c/ 466 `, 467 "a/b": ` 468 # include .go files in this directory 469 !*.go 470 471 # include everything under e 472 !**/e/** 473 `, 474 "a/b/d": ` 475 # include c directories 476 !c/ 477 hidden/ 478 `, 479 } 480 481 // define the patterns for $GIT_DIR/info/exclude 482 _GITEXCLUDE = ` 483 # exclude every file using 'exclude' in its name 484 *exclude* 485 ` 486 487 // define repository match tests and their expected results 488 _REPOSITORYMATCHES = []match{ 489 // matching against the nested .gitignore files 490 {"include.go", "", false, false}, 491 {"ignore.go.bak", "*.bak", true, false}, 492 {"a/ignore.go", "*.go", true, false}, 493 {"a/ignore.go.bak", "*.bak", true, false}, 494 {"a/include.sh", "", false, false}, 495 {"a/c/ignore.go", "**/c/", true, false}, 496 {"a/c/ignore.go.bak", "**/c/", true, false}, 497 {"a/c/ignore.sh", "**/c/", true, false}, 498 {"a/c/", "**/c/", true, false}, 499 {"a/b/c/d/ignore.go", "**/c/", true, false}, 500 {"a/b/c/d/ignore.go.bak", "**/c/", true, false}, 501 {"a/b/c/d/ignore.sh", "**/c/", true, false}, 502 {"a/b/c/d/", "**/c/", true, false}, 503 {"a/b/c/", "**/c/", true, false}, 504 {"a/b/include.go", "!*.go", false, false}, 505 {"a/b/ignore.go.bak", "*.bak", true, false}, 506 {"a/b/include.sh", "", false, false}, 507 {"a/b/d/include.go", "!*.go", false, false}, 508 {"a/b/d/ignore.go.bak", "*.bak", true, false}, 509 {"a/b/d/include.sh", "", false, false}, 510 {"a/b/d/c/", "!c/", false, false}, 511 {"a/b/d/c/include.go", "!*.go", false, false}, 512 {"a/b/d/c/ignore.go.bak", "*.bak", true, false}, 513 {"a/b/d/c/include.sh", "", false, false}, 514 {"a/b/e/c/", "!**/e/**", false, false}, 515 {"a/b/e/c/include.go", "!**/e/**", false, false}, 516 {"a/b/e/c/include.go.bak", "!**/e/**", false, false}, 517 {"a/b/e/c/include.sh", "!**/e/**", false, false}, 518 519 // matching against GIT_DIR/info/exclude 520 {"exclude.me", "*exclude*", true, true}, 521 {"a/exclude.me", "*exclude*", true, true}, 522 {"a/b/exclude.me", "*exclude*", true, true}, 523 {"a/b/c/exclude.me", "**/c/", true, false}, 524 {"a/b/c/d/exclude.me", "**/c/", true, false}, 525 {"a/c/exclude.me", "**/c/", true, false}, 526 {"a/b/exclude.me", "*exclude*", true, true}, 527 {"a/b/d/exclude.me", "*exclude*", true, true}, 528 {"a/b/d/c/exclude.me", "*exclude*", true, true}, 529 {"a/b/e/c/exclude.me", "!**/e/**", false, false}, 530 } 531 532 // define the repository match tests and their expected results when the 533 // error handler returns false 534 _REPOSITORYMATCHESFALSE = []match{ 535 {"a/b/c_/d/e_/f/g/h/include.go~", "", false, false}, 536 } 537 538 // define the position tests 539 _POSITIONS = []position{ 540 {"", 0, 0, 0, "+0"}, 541 {"", 1, 0, 0, "1"}, 542 {"", 0, 1, 0, "+0"}, 543 {"", 0, 0, 1, "+1"}, 544 {"", 1, 2, 0, "1:2"}, 545 {"", 1, 0, 3, "1"}, 546 {"", 1, 2, 3, "1:2"}, 547 {"file", 0, 0, 0, "file: +0"}, 548 {"file", 1, 0, 0, "file: 1"}, 549 {"file", 0, 1, 0, "file: +0"}, 550 {"file", 0, 0, 1, "file: +1"}, 551 {"file", 1, 2, 0, "file: 1:2"}, 552 {"file", 1, 0, 3, "file: 1"}, 553 {"file", 1, 2, 3, "file: 1:2"}, 554 } 555 556 // define the token tests 557 // - we us the same position for all tokens, and ignore the 558 // token string (i.e. the sequence of runes that comprise this 559 // token), since we test the correctness of rune mappings to toknes 560 // in the above tests of example .gitignore files 561 _TOKENS = []token{ 562 {gitignore.ILLEGAL, "ILLEGAL", "", 1, 2, 3, 4}, 563 {gitignore.EOF, "EOF", "", 1, 2, 3, 4}, 564 {gitignore.EOL, "EOL", "", 1, 2, 3, 4}, 565 {gitignore.WHITESPACE, "WHITESPACE", "", 1, 2, 3, 4}, 566 {gitignore.COMMENT, "COMMENT", "", 1, 2, 3, 4}, 567 {gitignore.SEPARATOR, "SEPARATOR", "", 1, 2, 3, 4}, 568 {gitignore.NEGATION, "NEGATION", "", 1, 2, 3, 4}, 569 {gitignore.PATTERN, "PATTERN", "", 1, 2, 3, 4}, 570 {gitignore.ANY, "ANY", "", 1, 2, 3, 4}, 571 {gitignore.BAD, "BAD TOKEN", "", 1, 2, 3, 4}, 572 573 // invalid tokens 574 {-1, "BAD TOKEN", "", 1, 2, 3, 4}, 575 {12345, "BAD TOKEN", "", 1, 2, 3, 4}, 576 } 577 578 // define the beginning position for the parser & lexer 579 _BEGINNING = gitignore.Position{File: "", Line: 1, Column: 1, Offset: 0} 580 581 // define the tokens from the invalid .gitignore above 582 _TOKENSINVALID = []token{ 583 // 1: # the following two lines will trigger repeated lexer errors 584 {gitignore.COMMENT, 585 "COMMENT", 586 "# the following two lines will trigger repeated lexer errors", 587 1, 1, 0, 0}, 588 {gitignore.EOL, "EOL", "\n", 1, 61, 60, 60}, 589 // 2: x\rx\rx\rx 590 {gitignore.PATTERN, "PATTERN", "x", 2, 1, 61, 62}, 591 {gitignore.BAD, "BAD TOKEN", "\r", 2, 2, 62, 63}, 592 {gitignore.PATTERN, "PATTERN", "x", 2, 3, 63, 64}, 593 {gitignore.BAD, "BAD TOKEN", "\r", 2, 4, 64, 65}, 594 {gitignore.PATTERN, "PATTERN", "x", 2, 5, 65, 66}, 595 {gitignore.BAD, "BAD TOKEN", "\r", 2, 6, 66, 67}, 596 {gitignore.PATTERN, "PATTERN", "x", 2, 7, 67, 68}, 597 {gitignore.EOL, "EOL", "\n", 2, 8, 68, 69}, 598 // 3: x\rx\rx\rx 599 {gitignore.BAD, "BAD TOKEN", "\r", 3, 1, 69, 71}, 600 {gitignore.PATTERN, "PATTERN", "x", 3, 2, 70, 72}, 601 {gitignore.BAD, "BAD TOKEN", "\r", 3, 3, 71, 73}, 602 {gitignore.PATTERN, "PATTERN", "x", 3, 4, 72, 74}, 603 {gitignore.BAD, "BAD TOKEN", "\r", 3, 5, 73, 75}, 604 {gitignore.PATTERN, "PATTERN", "x", 3, 6, 74, 76}, 605 {gitignore.EOL, "EOL", "\n", 3, 7, 75, 77}, 606 // 4: !\rx 607 {gitignore.NEGATION, "NEGATION", "!", 4, 1, 76, 79}, 608 {gitignore.BAD, "BAD TOKEN", "\r", 4, 2, 77, 80}, 609 {gitignore.PATTERN, "PATTERN", "x", 4, 3, 78, 81}, 610 {gitignore.EOL, "EOL", "\n", 4, 4, 79, 82}, 611 // 5: /my/valid/pattern 612 {gitignore.SEPARATOR, "SEPARATOR", "/", 5, 1, 80, 84}, 613 {gitignore.PATTERN, "PATTERN", "my", 5, 2, 81, 85}, 614 {gitignore.SEPARATOR, "SEPARATOR", "/", 5, 4, 83, 87}, 615 {gitignore.PATTERN, "PATTERN", "valid", 5, 5, 84, 88}, 616 {gitignore.SEPARATOR, "SEPARATOR", "/", 5, 10, 89, 93}, 617 {gitignore.PATTERN, "PATTERN", "pattern", 5, 11, 90, 94}, 618 {gitignore.EOL, "EOL", "\n", 5, 18, 97, 101}, 619 // 6: ! 620 {gitignore.NEGATION, "NEGATION", "!", 6, 1, 98, 103}, 621 {gitignore.EOL, "EOL", "\n", 6, 2, 99, 104}, 622 // 7: ** * 623 {gitignore.ANY, "ANY", "**", 7, 1, 100, 106}, 624 {gitignore.WHITESPACE, "WHITESPACE", " ", 7, 3, 102, 108}, 625 {gitignore.PATTERN, "PATTERN", "*", 7, 4, 103, 109}, 626 {gitignore.EOL, "EOL", "\n", 7, 5, 104, 110}, 627 // 8: /\r 628 {gitignore.SEPARATOR, "SEPARATOR", "/", 8, 1, 105, 112}, 629 {gitignore.BAD, "BAD TOKEN", "\r", 8, 2, 106, 113}, 630 631 {gitignore.EOF, "EOF", "", 8, 3, 107, 114}, 632 } 633 634 // define the patterns & errors expected during invalid content parsing 635 _GITINVALIDPATTERN = []string{"/my/valid/pattern"} 636 _GITINVALIDERROR = []error{ 637 gitignore.CarriageReturnError, 638 gitignore.CarriageReturnError, 639 gitignore.CarriageReturnError, 640 gitignore.CarriageReturnError, 641 gitignore.CarriageReturnError, 642 gitignore.CarriageReturnError, 643 gitignore.CarriageReturnError, 644 gitignore.InvalidPatternError, 645 gitignore.InvalidPatternError, 646 gitignore.CarriageReturnError, 647 } 648 )