1
2
3
4
5
6
7
8
9
10 package org.eclipse.jgit.ignore;
11
12 import static org.eclipse.jgit.ignore.internal.Strings.split;
13 import static org.junit.Assert.assertArrayEquals;
14 import static org.junit.Assert.assertFalse;
15 import static org.junit.Assert.assertTrue;
16 import static org.junit.Assert.fail;
17
18 import org.junit.Before;
19 import org.junit.Test;
20
21 public class FastIgnoreRuleTest {
22
23 private boolean pathMatch;
24
25 @Before
26 public void setup() {
27 pathMatch = false;
28 }
29
30 @Test
31 public void testSimpleCharClass() {
32 assertMatched("][a]", "]a");
33 assertMatched("[a]", "a");
34 assertMatched("][a]", "]a");
35 assertMatched("[a]", "a/");
36 assertMatched("[a]", "a/b");
37
38 assertMatched("[a]", "b/a");
39 assertMatched("[a]", "b/a/");
40 assertMatched("[a]", "b/a/b");
41
42 assertMatched("[a]", "/a/");
43 assertMatched("[a]", "/a/b");
44
45 assertMatched("[a]", "c/a/b");
46 assertMatched("[a]", "c/b/a");
47
48 assertMatched("/[a]", "a");
49 assertMatched("/[a]", "a/");
50 assertMatched("/[a]", "a/b");
51 assertMatched("/[a]", "/a");
52 assertMatched("/[a]", "/a/");
53 assertMatched("/[a]", "/a/b");
54
55 assertMatched("[a]/", "a/");
56 assertMatched("[a]/", "a/b");
57 assertMatched("[a]/", "/a/");
58 assertMatched("[a]/", "/a/b");
59
60 assertMatched("/[a]/", "a/");
61 assertMatched("/[a]/", "a/b");
62 assertMatched("/[a]/", "/a/");
63 assertMatched("/[a]/", "/a/b");
64 }
65
66 @Test
67 public void testCharClass() {
68 assertMatched("[v-z]", "x");
69 assertMatched("[v-z]", "x/");
70 assertMatched("[v-z]", "x/b");
71
72 assertMatched("[v-z]", "b/x");
73 assertMatched("[v-z]", "b/x/");
74 assertMatched("[v-z]", "b/x/b");
75
76 assertMatched("[v-z]", "/x/");
77 assertMatched("[v-z]", "/x/b");
78
79 assertMatched("[v-z]", "c/x/b");
80 assertMatched("[v-z]", "c/b/x");
81
82 assertMatched("/[v-z]", "x");
83 assertMatched("/[v-z]", "x/");
84 assertMatched("/[v-z]", "x/b");
85 assertMatched("/[v-z]", "/x");
86 assertMatched("/[v-z]", "/x/");
87 assertMatched("/[v-z]", "/x/b");
88
89 assertMatched("[v-z]/", "x/");
90 assertMatched("[v-z]/", "x/b");
91 assertMatched("[v-z]/", "/x/");
92 assertMatched("[v-z]/", "/x/b");
93
94 assertMatched("/[v-z]/", "x/");
95 assertMatched("/[v-z]/", "x/b");
96 assertMatched("/[v-z]/", "/x/");
97 assertMatched("/[v-z]/", "/x/b");
98 }
99
100 @Test
101 public void testTrailingSpaces() {
102 assertMatched("a ", "a");
103 assertMatched("a/ ", "a/");
104 assertMatched("a/ ", "a/b");
105 assertMatched("a/\\ ", "a/ ");
106 assertNotMatched("a/\\ ", "a/");
107 assertNotMatched("a/\\ ", "a/b");
108 assertNotMatched("/ ", "a");
109 }
110
111 @Test
112 public void testAsteriskDot() {
113 assertMatched("*.a", ".a");
114 assertMatched("*.a", "/.a");
115 assertMatched("*.a", "a.a");
116 assertMatched("*.a", "/b.a");
117 assertMatched("*.a", "b.a");
118 assertMatched("*.a", "/a/b.a");
119 assertMatched("*.a", "/b/.a");
120 }
121
122 @Test
123 public void testAsteriskDotDoNotMatch() {
124 assertNotMatched("*.a", ".ab");
125 assertNotMatched("*.a", "/.ab");
126 assertNotMatched("*.a", "/b.ba");
127 assertNotMatched("*.a", "a.ab");
128 assertNotMatched("*.a", "/b.ab");
129 assertNotMatched("*.a", "b.ab");
130 assertNotMatched("*.a", "/a/b.ab");
131 assertNotMatched("*.a", "/b/.ab");
132 }
133
134 @Test
135 public void testDotAsteriskMatch() {
136 assertMatched("a.*", "a.");
137 assertMatched("a.*", "a./");
138 assertMatched("a.*", "a.b");
139
140 assertMatched("a.*", "b/a.b");
141 assertMatched("a.*", "b/a.b/");
142 assertMatched("a.*", "b/a.b/b");
143
144 assertMatched("a.*", "/a.b/");
145 assertMatched("a.*", "/a.b/b");
146
147 assertMatched("a.*", "c/a.b/b");
148 assertMatched("a.*", "c/b/a.b");
149
150 assertMatched("/a.*", "a.b");
151 assertMatched("/a.*", "a.b/");
152 assertMatched("/a.*", "a.b/b");
153 assertMatched("/a.*", "/a.b");
154 assertMatched("/a.*", "/a.b/");
155 assertMatched("/a.*", "/a.b/b");
156
157 assertMatched("/a.*/b", "a.b/b");
158 assertMatched("/a.*/b", "/a.b/b");
159 assertMatched("/a.*/b", "/a.bc/b");
160 assertMatched("/a.*/b", "/a./b");
161 }
162
163 @Test
164 public void testAsterisk() {
165 assertMatched("a*", "a");
166 assertMatched("a*", "a/");
167 assertMatched("a*", "ab");
168
169 assertMatched("a*", "b/ab");
170 assertMatched("a*", "b/ab/");
171 assertMatched("a*", "b/ab/b");
172
173 assertMatched("a*", "b/abc");
174 assertMatched("a*", "b/abc/");
175 assertMatched("a*", "b/abc/b");
176
177 assertMatched("a*", "/abc/");
178 assertMatched("a*", "/abc/b");
179
180 assertMatched("a*", "c/abc/b");
181 assertMatched("a*", "c/b/abc");
182
183 assertMatched("/a*", "abc");
184 assertMatched("/a*", "abc/");
185 assertMatched("/a*", "abc/b");
186 assertMatched("/a*", "/abc");
187 assertMatched("/a*", "/abc/");
188 assertMatched("/a*", "/abc/b");
189
190 assertMatched("/a*/b", "abc/b");
191 assertMatched("/a*/b", "/abc/b");
192 assertMatched("/a*/b", "/abcd/b");
193 assertMatched("/a*/b", "/a/b");
194 }
195
196 @Test
197 public void testQuestionmark() {
198 assertMatched("a?", "ab");
199 assertMatched("a?", "ab/");
200
201 assertMatched("a?", "b/ab");
202 assertMatched("a?", "b/ab/");
203 assertMatched("a?", "b/ab/b");
204
205 assertMatched("a?", "/ab/");
206 assertMatched("a?", "/ab/b");
207
208 assertMatched("a?", "c/ab/b");
209 assertMatched("a?", "c/b/ab");
210
211 assertMatched("/a?", "ab");
212 assertMatched("/a?", "ab/");
213 assertMatched("/a?", "ab/b");
214 assertMatched("/a?", "/ab");
215 assertMatched("/a?", "/ab/");
216 assertMatched("/a?", "/ab/b");
217
218 assertMatched("/a?/b", "ab/b");
219 assertMatched("/a?/b", "/ab/b");
220 }
221
222 @Test
223 public void testQuestionmarkDoNotMatch() {
224 assertNotMatched("a?", "a/");
225 assertNotMatched("a?", "abc");
226 assertNotMatched("a?", "abc/");
227
228 assertNotMatched("a?", "b/abc");
229 assertNotMatched("a?", "b/abc/");
230
231 assertNotMatched("a?", "/abc/");
232 assertNotMatched("a?", "/abc/b");
233
234 assertNotMatched("a?", "c/abc/b");
235 assertNotMatched("a?", "c/b/abc");
236
237 assertNotMatched("/a?", "abc");
238 assertNotMatched("/a?", "abc/");
239 assertNotMatched("/a?", "abc/b");
240 assertNotMatched("/a?", "/abc");
241 assertNotMatched("/a?", "/abc/");
242 assertNotMatched("/a?", "/abc/b");
243
244 assertNotMatched("/a?/b", "abc/b");
245 assertNotMatched("/a?/b", "/abc/b");
246 assertNotMatched("/a?/b", "/a/b");
247 }
248
249 @Test
250 public void testSimplePatterns() {
251 assertMatched("a", "a");
252 assertMatched("a", "a/");
253 assertMatched("a", "a/b");
254
255 assertMatched("a", "b/a");
256 assertMatched("a", "b/a/");
257 assertMatched("a", "b/a/b");
258
259 assertMatched("a", "/a/");
260 assertMatched("a", "/a/b");
261
262 assertMatched("a", "c/a/b");
263 assertMatched("a", "c/b/a");
264
265 assertMatched("/a", "a");
266 assertMatched("/a", "a/");
267 assertMatched("/a", "a/b");
268 assertMatched("/a", "/a");
269 assertMatched("/a", "/a/");
270 assertMatched("/a", "/a/b");
271
272 assertMatched("a/", "a/");
273 assertMatched("a/", "a/b");
274 assertMatched("a/", "/a/");
275 assertMatched("a/", "/a/b");
276
277 assertMatched("/a/", "a/");
278 assertMatched("/a/", "a/b");
279 assertMatched("/a/", "/a/");
280 assertMatched("/a/", "/a/b");
281
282 }
283
284 @Test
285 public void testSimplePatternsDoNotMatch() {
286 assertNotMatched("ab", "a");
287 assertNotMatched("abc", "a/");
288 assertNotMatched("abc", "a/b");
289
290 assertNotMatched("a", "ab");
291 assertNotMatched("a", "ba");
292 assertNotMatched("a", "aa");
293
294 assertNotMatched("a", "b/ab");
295 assertNotMatched("a", "b/ba");
296
297 assertNotMatched("a", "b/ba");
298 assertNotMatched("a", "b/ab");
299
300 assertNotMatched("a", "b/ba/");
301 assertNotMatched("a", "b/ba/b");
302
303 assertNotMatched("a", "/aa");
304 assertNotMatched("a", "aa/");
305 assertNotMatched("a", "/aa/");
306
307 assertNotMatched("/a", "b/a");
308 assertNotMatched("/a", "/b/a/");
309
310 assertNotMatched("a/", "a");
311 assertNotMatched("a/", "b/a");
312
313 assertNotMatched("/a/", "a");
314 assertNotMatched("/a/", "/a");
315 assertNotMatched("/a/", "b/a");
316 }
317
318 @Test
319 public void testSegments() {
320 assertMatched("/a/b", "a/b");
321 assertMatched("/a/b", "/a/b");
322 assertMatched("/a/b", "/a/b/");
323 assertMatched("/a/b", "/a/b/c");
324
325 assertMatched("a/b", "a/b");
326 assertMatched("a/b", "/a/b");
327 assertMatched("a/b", "/a/b/");
328 assertMatched("a/b", "/a/b/c");
329
330 assertMatched("a/b/", "a/b/");
331 assertMatched("a/b/", "/a/b/");
332 assertMatched("a/b/", "/a/b/c");
333 }
334
335 @Test
336 public void testSegmentsDoNotMatch() {
337 assertNotMatched("a/b", "/a/bb");
338 assertNotMatched("a/b", "/aa/b");
339 assertNotMatched("a/b", "a/bb");
340 assertNotMatched("a/b", "aa/b");
341 assertNotMatched("a/b", "c/aa/b");
342 assertNotMatched("a/b", "c/a/bb");
343 assertNotMatched("a/b/", "/a/b");
344 assertNotMatched("/a/b/", "/a/b");
345 assertNotMatched("/a/b", "c/a/b");
346 assertNotMatched("/a/b/", "c/a/b");
347 assertNotMatched("/a/b/", "c/a/b/");
348
349
350 assertNotMatched("a/b", "c/a/b");
351 assertNotMatched("a/b", "c/a/b/");
352 assertNotMatched("a/b", "c/a/b/c");
353 assertNotMatched("a/b/", "c/a/b/");
354 assertNotMatched("a/b/", "c/a/b/c");
355 }
356
357 @Test
358 public void testWildmatch() {
359 assertMatched("**/a/b", "a/b");
360 assertMatched("**/a/b", "c/a/b");
361 assertMatched("**/a/b", "c/d/a/b");
362 assertMatched("**/**/a/b", "c/d/a/b");
363
364 assertMatched("/**/a/b", "a/b");
365 assertMatched("/**/a/b", "c/a/b");
366 assertMatched("/**/a/b", "c/d/a/b");
367 assertMatched("/**/**/a/b", "c/d/a/b");
368
369 assertMatched("a/b/**", "a/b/c");
370 assertMatched("a/b/**", "a/b/c/d/");
371 assertMatched("a/b/**/**", "a/b/c/d");
372
373 assertMatched("**/a/**/b", "c/d/a/b");
374 assertMatched("**/a/**/b", "c/d/a/e/b");
375 assertMatched("**/**/a/**/**/b", "c/d/a/e/b");
376
377 assertMatched("/**/a/**/b", "c/d/a/b");
378 assertMatched("/**/a/**/b", "c/d/a/e/b");
379 assertMatched("/**/**/a/**/**/b", "c/d/a/e/b");
380
381 assertMatched("a/**/b", "a/b");
382 assertMatched("a/**/b", "a/c/b");
383 assertMatched("a/**/b", "a/c/d/b");
384 assertMatched("a/**/**/b", "a/c/d/b");
385
386 assertMatched("a/**/b/**/c", "a/c/b/d/c");
387 assertMatched("a/**/**/b/**/**/c", "a/c/b/d/c");
388
389 assertMatched("**/", "a/");
390 assertMatched("**/", "a/b");
391 assertMatched("**/", "a/b/c");
392 assertMatched("**/**/", "a/");
393 assertMatched("**/**/", "a/b");
394 assertMatched("**/**/", "a/b/");
395 assertMatched("**/**/", "a/b/c");
396 assertMatched("x/**/", "x/a/");
397 assertMatched("x/**/", "x/a/b");
398 assertMatched("x/**/", "x/a/b/");
399 assertMatched("**/x/", "a/x/");
400 assertMatched("**/x/", "a/b/x/");
401 }
402
403 @Test
404 public void testWildmatchDoNotMatch() {
405 assertNotMatched("a/**", "a/");
406 assertNotMatched("a/b/**", "a/b/");
407 assertNotMatched("a/**", "a");
408 assertNotMatched("a/b/**", "a/b");
409 assertNotMatched("a/b/**/", "a/b");
410 assertNotMatched("a/b/**/**", "a/b");
411 assertNotMatched("**/a/b", "a/c/b");
412 assertNotMatched("!/**/*.zip", "c/a/b.zip");
413 assertNotMatched("!**/*.zip", "c/a/b.zip");
414 assertNotMatched("a/**/b", "a/c/bb");
415
416 assertNotMatched("**/", "a");
417 assertNotMatched("**/**/", "a");
418 assertNotMatched("**/x/", "a/b/x");
419 }
420
421 @SuppressWarnings("unused")
422 @Test
423 public void testSimpleRules() {
424 try {
425 new FastIgnoreRule(null);
426 fail("Illegal input allowed!");
427 } catch (IllegalArgumentException e) {
428
429 }
430 assertFalse(new FastIgnoreRule("/").isMatch("/", false));
431 assertFalse(new FastIgnoreRule("//").isMatch("//", false));
432 assertFalse(new FastIgnoreRule("#").isMatch("#", false));
433 assertFalse(new FastIgnoreRule("").isMatch("", false));
434 assertFalse(new FastIgnoreRule(" ").isMatch(" ", false));
435 }
436
437 @Test
438 public void testSplit() {
439 try {
440 split("/", '/').toArray();
441 fail("should not allow single slash");
442 } catch (IllegalStateException e) {
443
444 }
445
446 assertArrayEquals(new String[] { "a", "b" }, split("a/b", '/')
447 .toArray());
448 assertArrayEquals(new String[] { "a", "b/" }, split("a/b/", '/')
449 .toArray());
450 assertArrayEquals(new String[] { "/a", "b" }, split("/a/b", '/')
451 .toArray());
452 assertArrayEquals(new String[] { "/a", "b/" }, split("/a/b/", '/')
453 .toArray());
454 assertArrayEquals(new String[] { "/a", "b", "c" }, split("/a/b/c", '/')
455 .toArray());
456 assertArrayEquals(new String[] { "/a", "b", "c/" },
457 split("/a/b/c/", '/').toArray());
458 }
459
460 @Test
461 public void testPathMatch() {
462 pathMatch = true;
463 assertMatched("a", "a");
464 assertMatched("a/", "a/");
465 assertNotMatched("a/", "a/b");
466
467 assertMatched("**", "a");
468 assertMatched("**", "a/");
469 assertMatched("**", "a/b");
470
471 assertNotMatched("**/", "a");
472 assertNotMatched("**/", "a/b");
473 assertMatched("**/", "a/");
474 assertMatched("**/", "a/b/");
475
476 assertNotMatched("x/**/", "x/a");
477 assertNotMatched("x/**/", "x/a/b");
478 assertMatched("x/**/", "x/a/");
479 assertMatched("x/**/", "x/y/a/");
480 }
481
482 @Test
483 public void testFileNameWithLineTerminator() {
484 assertMatched("a?", "a\r");
485 assertMatched("a?", "dir/a\r");
486 assertMatched("a?", "a\r/file");
487 assertMatched("*a", "\ra");
488 assertMatched("dir/*a*", "dir/\ra\r");
489 }
490
491 private void assertMatched(String pattern, String path) {
492 boolean match = match(pattern, path);
493 String result = path + " is " + (match ? "ignored" : "not ignored")
494 + " via '" + pattern + "' rule";
495 if (!match) {
496 System.err.println(result);
497 }
498 assertTrue("Expected a match for: " + pattern + " with: " + path,
499 match);
500
501 if (pattern.startsWith("!")) {
502 pattern = pattern.substring(1);
503 } else {
504 pattern = "!" + pattern;
505 }
506 match = match(pattern, path);
507 assertFalse("Expected no match for: " + pattern + " with: " + path,
508 match);
509 }
510
511 private void assertNotMatched(String pattern, String path) {
512 boolean match = match(pattern, path);
513 String result = path + " is " + (match ? "ignored" : "not ignored")
514 + " via '" + pattern + "' rule";
515 if (match) {
516 System.err.println(result);
517 }
518 assertFalse("Expected no match for: " + pattern + " with: " + path,
519 match);
520
521 if (pattern.startsWith("!")) {
522 pattern = pattern.substring(1);
523 } else {
524 pattern = "!" + pattern;
525 }
526 match = match(pattern, path);
527 assertTrue("Expected a match for: " + pattern + " with: " + path,
528 match);
529 }
530
531
532
533
534
535
536
537
538
539
540
541 private boolean match(String pattern, String target) {
542 boolean isDirectory = target.endsWith("/");
543 FastIgnoreRule r = new FastIgnoreRule(pattern);
544
545
546 boolean match = r.isMatch(target, isDirectory, pathMatch);
547 if (r.getNegation())
548 match = !match;
549 return match;
550 }
551 }