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