• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.icu.test.util.regex;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertNull;
22 import static org.junit.Assert.assertTrue;
23 import static org.junit.Assert.fail;
24 
25 import android.icu.testsharding.MainTestShard;
26 
27 import com.android.icu.util.regex.MatcherNative;
28 import com.android.icu.util.regex.PatternNative;
29 
30 import org.junit.Test;
31 import org.junit.runner.RunWith;
32 import org.junit.runners.JUnit4;
33 
34 @MainTestShard
35 @RunWith(JUnit4.class)
36 public class MatcherNativeTest {
37     String[] testPatterns = {
38             "(a|b)*abb",
39             "(1*2*3*4*)*567",
40             "(a|b|c|d)*aab",
41             "(1|2|3|4|5|6|7|8|9|0)(1|2|3|4|5|6|7|8|9|0)*",
42             "(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ)*",
43             "(a|b)*(a|b)*A(a|b)*lice.*",
44             "(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z)(a|b|c|d|e|f|g|h|"
45                     + "i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z)*(1|2|3|4|5|6|7|8|9|0)*|while|for|struct|if|do" };
46 
47     String[] groupPatterns = { "(a|b)*aabb", "((a)|b)*aabb", "((a|b)*)a(abb)",
48             "(((a)|(b))*)aabb", "(((a)|(b))*)aa(b)b", "(((a)|(b))*)a(a(b)b)" };
49 
50     private static class Pattern {
51         private final PatternNative patternNative;
52         private final String pattern;
53 
compile(String pattern)54         private static Pattern compile(String pattern) {
55             return new Pattern(pattern, 0);
56         }
57 
Pattern(String p, int flags)58         private Pattern(String p, int flags) {
59             this.pattern = p;
60             this.patternNative = PatternNative.create(p, flags);
61         }
62 
matches(String pattern, String input)63         public static boolean matches(String pattern, String input) {
64             Pattern p = compile(pattern);
65             Matcher m = p.matcher(input);
66             return m.find();
67         }
68 
compile(String pattern, int flags)69         public static Pattern compile(String pattern, int flags) {
70             return new Pattern(pattern, flags);
71         }
72 
matcher(String input)73         private Matcher matcher(String input) {
74             Matcher matcher = new Matcher(this, input);
75             return matcher;
76         }
77 
matcher(StringBuilder sb)78         public Matcher matcher(StringBuilder sb) {
79             return matcher(sb.toString());
80         }
81 
pattern()82         public String pattern() {
83             return pattern;
84         }
85     }
86 
87     private static class Matcher {
88 
89         private final MatcherNative matcherNative;
90         private final PatternNative patternNative;
91         private final Pattern pattern;
92         private int[] groups;
93         private String input;
94         private int inputStart, inputEnd;
95 
Matcher(Pattern pattern, String input)96         private Matcher(Pattern pattern, String input) {
97             this.pattern = pattern;
98             this.patternNative = pattern.patternNative;
99             this.matcherNative = MatcherNative.create(patternNative);
100             reset(input);
101         }
102 
matches()103         public boolean matches() {
104             return matcherNative.matches(groups);
105         }
106 
region(int start, int end)107         public void region(int start, int end) {
108             reset(input, start, end);
109         }
110 
regionStart()111         public int regionStart() {
112             return inputStart;
113         }
114 
regionEnd()115         public int regionEnd() {
116             return inputEnd;
117         }
118 
find()119         public boolean find() {
120             return matcherNative.findNext(groups);
121         }
122 
reset(String input, int start, int end)123         public void reset(String input, int start, int end) {
124             this.input = input;
125             inputStart = start;
126             inputEnd = end;
127             matcherNative.setInput(input, inputStart, inputEnd);
128             this.groups = new int[2 * (matcherNative.groupCount() + 1)];
129         }
130 
reset(String input)131         public void reset(String input) {
132             reset(input, 0, input.length());
133         }
134 
pattern()135         public Pattern pattern() {
136             return pattern;
137         }
138 
group(int group)139         public String group(int group) {
140             return input.substring(start(group), end(group));
141         }
142 
groupCount()143         public int groupCount() {
144             return matcherNative.groupCount();
145         }
146 
start(int group)147         public int start(int group) {
148             return groups[group * 2];
149         }
150 
start(String groupName)151         public int start(String groupName) {
152             return start(groupId(groupName));
153         }
154 
end(int group)155         public int end(int group) {
156             return groups[group * 2 + 1];
157         }
158 
end(String groupName)159         public int end(String groupName) {
160             return end(groupId(groupName));
161         }
162 
hitEnd()163         public boolean hitEnd() {
164             return matcherNative.hitEnd();
165         }
166 
requireEnd()167         public boolean requireEnd() {
168             return matcherNative.requireEnd();
169         }
170 
lookingAt()171         public boolean lookingAt() {
172             return matcherNative.lookingAt(groups);
173         }
174 
group()175         public String group() {
176             return group(0);
177         }
178 
start()179         public int start() {
180             return start(0);
181         }
182 
find(int start)183         public boolean find(int start) {
184             reset();
185             return matcherNative.find(start, groups);
186         }
187 
reset()188         public void reset() {
189             reset(input);
190         }
191 
group(String groupName)192         public String group(String groupName) {
193             return group(groupId(groupName));
194         }
195 
groupId(String groupName)196         public int groupId(String groupName) {
197             return matcherNative.getMatchedGroupIndex(groupName);
198         }
199 
useAnchoringBounds(boolean useAnchoringBounds)200         public Matcher useAnchoringBounds(boolean useAnchoringBounds) {
201             matcherNative.useAnchoringBounds(useAnchoringBounds);
202             return this;
203         }
204 
useTransparentBounds(boolean useTransparentBounds)205         public Matcher useTransparentBounds(boolean useTransparentBounds) {
206             matcherNative.useTransparentBounds(useTransparentBounds);
207             return this;
208         }
209     }
210 
211     @Test
testRegionsIntInt()212     public void testRegionsIntInt() {
213         Pattern p = Pattern.compile("x*");
214         Matcher m = p.matcher("axxxxxa");
215         assertFalse(m.matches());
216 
217         m.region(1, 6);
218         assertEquals(1, m.regionStart());
219         assertEquals(6, m.regionEnd());
220         assertTrue(m.matches());
221     }
222 
223     @Test
testLookingAt()224     public void testLookingAt() {
225         Pattern p = Pattern.compile("abc");
226         Matcher m = p.matcher("aabc");
227         assertTrue(m.find());
228 
229         m.reset();
230         assertFalse(m.lookingAt());
231     }
232 
233     @Test
testRequireEnd()234     public void testRequireEnd() {
235         Pattern p = Pattern.compile("abc$");
236         Matcher m = p.matcher("abc");
237         assertTrue(m.find());
238         assertTrue(m.requireEnd());
239     }
240 
241     @Test
testResetCharSequence()242     public void testResetCharSequence() {
243         Pattern p = Pattern.compile("abcd");
244         Matcher m = p.matcher("abcd");
245         assertTrue(m.matches());
246         m.reset("efgh");
247         assertFalse(m.matches());
248 
249         try {
250             m.reset(null);
251             fail("expected a NPE");
252         } catch (NullPointerException e) {
253         }
254     }
255 
256     @Test
testPattern()257     public void testPattern() {
258         for (String element : testPatterns) {
259             Pattern test = Pattern.compile(element);
260             assertEquals(test, test.matcher("aaa").pattern());
261         }
262     }
263 
264     @Test
testGroupint()265     public void testGroupint() {
266         String positiveTestString = "ababababbaaabb";
267 
268         // test IndexOutOfBoundsException
269         // //
270         for (int i = 0; i < groupPatterns.length; i++) {
271             Pattern test = Pattern.compile(groupPatterns[i]);
272             Matcher mat = test.matcher(positiveTestString);
273             mat.matches();
274             try {
275                 // groupPattern <index + 1> equals to number of groups
276                 // of the specified pattern
277                 // //
278                 mat.group(i + 2);
279                 fail("IndexOutBoundsException expected");
280                 mat.group(i + 100);
281                 fail("IndexOutBoundsException expected");
282                 mat.group(-1);
283                 fail("IndexOutBoundsException expected");
284                 mat.group(-100);
285                 fail("IndexOutBoundsException expected");
286             } catch (IndexOutOfBoundsException iobe) {
287             }
288         }
289 
290         String[][] groupResults = { { "a" }, { "a", "a" },
291                 { "ababababba", "a", "abb" }, { "ababababba", "a", "a", "b" },
292                 { "ababababba", "a", "a", "b", "b" },
293                 { "ababababba", "a", "a", "b", "abb", "b" }, };
294 
295         for (int i = 0; i < groupPatterns.length; i++) {
296             Pattern test = Pattern.compile(groupPatterns[i]);
297             Matcher mat = test.matcher(positiveTestString);
298             mat.matches();
299             for (int j = 0; j < groupResults[i].length; j++) {
300                 assertEquals("i: " + i + " j: " + j, groupResults[i][j], mat
301                         .group(j + 1));
302             }
303 
304         }
305 
306     }
307 
308     @Test
testGroup()309     public void testGroup() {
310         String positiveTestString = "ababababbaaabb";
311         String negativeTestString = "gjhfgdsjfhgcbv";
312         for (String element : groupPatterns) {
313             Pattern test = Pattern.compile(element);
314             Matcher mat = test.matcher(positiveTestString);
315             mat.matches();
316             // test result
317             assertEquals(positiveTestString, mat.group());
318 
319             // test equal to group(0) result
320             assertEquals(mat.group(0), mat.group());
321         }
322     }
323 
324     @Test
testGroupPossessive()325     public void testGroupPossessive() {
326         Pattern pat = Pattern.compile("((a)|(b))++c");
327         Matcher mat = pat.matcher("aac");
328 
329         mat.matches();
330         assertEquals("a", mat.group(1));
331     }
332 
333     @Test
testMatchesMisc()334     public void testMatchesMisc() {
335         String[][] posSeq = {
336                 { "abb", "ababb", "abababbababb", "abababbababbabababbbbbabb" },
337                 { "213567", "12324567", "1234567", "213213567",
338                         "21312312312567", "444444567" },
339                 { "abcdaab", "aab", "abaab", "cdaab", "acbdadcbaab" },
340                 { "213234567", "3458", "0987654", "7689546432", "0398576",
341                         "98432", "5" },
342                 {
343                         "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
344                         "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
345                                 + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" },
346                 { "ababbaAabababblice", "ababbaAliceababab", "ababbAabliceaaa",
347                         "abbbAbbbliceaaa", "Alice" },
348                 { "a123", "bnxnvgds156", "for", "while", "if", "struct" }
349 
350         };
351 
352         for (int i = 0; i < testPatterns.length; i++) {
353             Pattern pat = Pattern.compile(testPatterns[i]);
354             for (int j = 0; j < posSeq[i].length; j++) {
355                 Matcher mat = pat.matcher(posSeq[i][j]);
356                 assertTrue("Incorrect match: " + testPatterns[i] + " vs "
357                         + posSeq[i][j], mat.matches());
358             }
359         }
360     }
361 
362     @Test
testMatchesQuantifiers()363     public void testMatchesQuantifiers() {
364         String[] testPatternsSingles = { "a{5}", "a{2,4}", "a{3,}" };
365         String[] testPatternsMultiple = { "((a)|(b)){1,2}abb",
366                 "((a)|(b)){2,4}", "((a)|(b)){3,}" };
367 
368         String[][] stringSingles = { { "aaaaa", "aaa" },
369                 { "aa", "a", "aaa", "aaaaaa", "aaaa", "aaaaa" },
370                 { "aaa", "a", "aaaa", "aa" }, };
371 
372         String[][] stringMultiples = { { "ababb", "aba" },
373                 { "ab", "b", "bab", "ababa", "abba", "abababbb" },
374                 { "aba", "b", "abaa", "ba" }, };
375 
376         for (int i = 0; i < testPatternsSingles.length; i++) {
377             Pattern pat = Pattern.compile(testPatternsSingles[i]);
378             for (int j = 0; j < stringSingles.length / 2; j++) {
379                 assertTrue("Match expected, but failed: " + pat.pattern()
380                         + " : " + stringSingles[i][j], pat.matcher(
381                         stringSingles[i][j * 2]).matches());
382                 assertFalse("Match failure expected, but match succeed: "
383                                 + pat.pattern() + " : " + stringSingles[i][j * 2 + 1],
384                         pat.matcher(stringSingles[i][j * 2 + 1]).matches());
385             }
386         }
387 
388         for (int i = 0; i < testPatternsMultiple.length; i++) {
389             Pattern pat = Pattern.compile(testPatternsMultiple[i]);
390             for (int j = 0; j < stringMultiples.length / 2; j++) {
391                 assertTrue("Match expected, but failed: " + pat.pattern()
392                         + " : " + stringMultiples[i][j], pat.matcher(
393                         stringMultiples[i][j * 2]).matches());
394                 assertFalse(
395                         "Match failure expected, but match succeed: "
396                                 + pat.pattern() + " : "
397                                 + stringMultiples[i][j * 2 + 1], pat.matcher(
398                                 stringMultiples[i][j * 2 + 1]).matches());
399             }
400         }
401     }
402 
403     @Test
testQuantVsGroup()404     public void testQuantVsGroup() {
405         String patternString = "(d{1,3})((a|c)*)(d{1,3})((a|c)*)(d{1,3})";
406         String testString = "dacaacaacaaddaaacaacaaddd";
407 
408         Pattern pat = Pattern.compile(patternString);
409         Matcher mat = pat.matcher(testString);
410 
411         mat.matches();
412         assertEquals("dacaacaacaaddaaacaacaaddd", mat.group());
413         assertEquals("d", mat.group(1));
414         assertEquals("acaacaacaa", mat.group(2));
415         assertEquals("dd", mat.group(4));
416         assertEquals("aaacaacaa", mat.group(5));
417         assertEquals("ddd", mat.group(7));
418     }
419 
420 
421     @Test
testFind()422     public void testFind() {
423         String testPattern = "(abb)";
424         String testString = "cccabbabbabbabbabb";
425         Pattern pat = Pattern.compile(testPattern);
426         Matcher mat = pat.matcher(testString);
427         int start = 3;
428         int end = 6;
429         while (mat.find()) {
430             assertEquals(start, mat.start(1));
431             assertEquals(end, mat.end(1));
432 
433             start = end;
434             end += 3;
435         }
436 
437         testPattern = "(\\d{1,3})";
438         testString = "aaaa123456789045";
439 
440         Pattern pat2 = Pattern.compile(testPattern);
441         Matcher mat2 = pat2.matcher(testString);
442         start = 4;
443         int length = 3;
444         while (mat2.find()) {
445             assertEquals(testString.substring(start, start + length), mat2
446                     .group(1));
447             start += length;
448         }
449     }
450 
451     @Test
testSEOLsymbols()452     public void testSEOLsymbols() {
453         Pattern pat = Pattern.compile("^a\\(bb\\[$");
454         Matcher mat = pat.matcher("a(bb[");
455 
456         assertTrue(mat.matches());
457     }
458 
459     @Test
testGroupCount()460     public void testGroupCount() {
461         for (int i = 0; i < groupPatterns.length; i++) {
462             Pattern test = Pattern.compile(groupPatterns[i]);
463             Matcher mat = test.matcher("ababababbaaabb");
464             mat.matches();
465             assertEquals(i + 1, mat.groupCount());
466 
467         }
468     }
469 
470     @Test
testRelactantQuantifiers()471     public void testRelactantQuantifiers() {
472         Pattern pat = Pattern.compile("(ab*)*b");
473         Matcher mat = pat.matcher("abbbb");
474 
475         if (mat.matches()) {
476             assertEquals("abbb", mat.group(1));
477         } else {
478             fail("Match expected: (ab*)*b vs abbbb");
479         }
480     }
481 
482     @Test
testStart_groupIndexOutOfBounds()483     public void testStart_groupIndexOutOfBounds() {
484         Matcher matcher = Pattern.compile("(Hello)").matcher("Hello, world!");
485         assertTrue(matcher.find());
486         try {
487             matcher.start(-1 /* out of bounds */);
488             fail();
489         } catch (ArrayIndexOutOfBoundsException expected) {
490         }
491 
492         try {
493             matcher.start(2 /* out of bounds */);
494             fail();
495         } catch (ArrayIndexOutOfBoundsException expected) {
496         }
497     }
498 
499     @Test
testEnhancedFind()500     public void testEnhancedFind() {
501         String input = "foob";
502         String pattern = "a*b";
503         Pattern pat = Pattern.compile(pattern);
504         Matcher mat = pat.matcher(input);
505 
506         mat.find();
507         assertEquals("b", mat.group());
508     }
509 
510     @Test
testPosCompositeGroup()511     public void testPosCompositeGroup() {
512         String[] posExamples = { "aabbcc", "aacc", "bbaabbcc" };
513         String[] negExamples = { "aabb", "bb", "bbaabb" };
514         Pattern posPat = Pattern.compile("(aa|bb){1,3}+cc");
515         Pattern negPat = Pattern.compile("(aa|bb){1,3}+bb");
516 
517         Matcher mat;
518         for (String element : posExamples) {
519             mat = posPat.matcher(element);
520             assertTrue(mat.matches());
521         }
522 
523         for (String element : negExamples) {
524             mat = negPat.matcher(element);
525             assertFalse(mat.matches());
526         }
527 
528         assertTrue(Pattern.matches("(aa|bb){1,3}+bb", "aabbaabb"));
529 
530     }
531 
532     @Test
testPosAltGroup()533     public void testPosAltGroup() {
534         String[] posExamples = { "aacc", "bbcc", "cc" };
535         String[] negExamples = { "bb", "aa" };
536         Pattern posPat = Pattern.compile("(aa|bb)?+cc");
537         Pattern negPat = Pattern.compile("(aa|bb)?+bb");
538 
539         Matcher mat;
540         for (String element : posExamples) {
541             mat = posPat.matcher(element);
542             assertTrue(posPat.toString() + " vs: " + element, mat.matches());
543         }
544 
545         for (String element : negExamples) {
546             mat = negPat.matcher(element);
547             assertFalse(mat.matches());
548         }
549 
550         assertTrue(Pattern.matches("(aa|bb)?+bb", "aabb"));
551     }
552 
553     @Test
testRelCompGroup()554     public void testRelCompGroup() {
555 
556         Matcher mat;
557         Pattern pat;
558         String res = "";
559         for (int i = 0; i < 4; i++) {
560             pat = Pattern.compile("((aa|bb){" + i + ",3}?).*cc");
561             mat = pat.matcher("aaaaaacc");
562             assertTrue(pat.toString() + " vs: " + "aaaaaacc", mat.matches());
563             assertEquals(res, mat.group(1));
564             res += "aa";
565         }
566     }
567 
568     @Test
testRelAltGroup()569     public void testRelAltGroup() {
570 
571         Matcher mat;
572         Pattern pat;
573 
574         pat = Pattern.compile("((aa|bb)??).*cc");
575         mat = pat.matcher("aacc");
576         assertTrue(pat.toString() + " vs: " + "aacc", mat.matches());
577         assertEquals("", mat.group(1));
578 
579         pat = Pattern.compile("((aa|bb)??)cc");
580         mat = pat.matcher("aacc");
581         assertTrue(pat.toString() + " vs: " + "aacc", mat.matches());
582         assertEquals("aa", mat.group(1));
583     }
584 
585     @Test
testIgnoreCase()586     public void testIgnoreCase() {
587         Pattern pat = Pattern.compile("(aa|bb)*", java.util.regex.Pattern.CASE_INSENSITIVE);
588         Matcher mat = pat.matcher("aAbb");
589 
590         assertTrue(mat.matches());
591 
592         pat = Pattern.compile("(a|b|c|d|e)*", java.util.regex.Pattern.CASE_INSENSITIVE);
593         mat = pat.matcher("aAebbAEaEdebbedEccEdebbedEaedaebEbdCCdbBDcdcdADa");
594         assertTrue(mat.matches());
595 
596         pat = Pattern.compile("[a-e]*", java.util.regex.Pattern.CASE_INSENSITIVE);
597         mat = pat.matcher("aAebbAEaEdebbedEccEdebbedEaedaebEbdCCdbBDcdcdADa");
598         assertTrue(mat.matches());
599     }
600 
601     @Test
testOverFlow()602     public void testOverFlow() {
603         Pattern tp = Pattern.compile("(a*)*");
604         Matcher tm = tp.matcher("aaa");
605         assertTrue(tm.matches());
606         assertEquals("", tm.group(1));
607 
608         assertTrue(Pattern.matches("(1+)\\1+", "11"));
609         assertTrue(Pattern.matches("(1+)(2*)\\2+", "11"));
610 
611         Pattern pat = Pattern.compile("(1+)\\1*");
612         Matcher mat = pat.matcher("11");
613 
614         assertTrue(mat.matches());
615         assertEquals("11", mat.group(1));
616 
617         pat = Pattern.compile("((1+)|(2+))(\\2+)");
618         mat = pat.matcher("11");
619 
620         assertTrue(mat.matches());
621         assertEquals("1", mat.group(2));
622         assertEquals("1", mat.group(1));
623         assertEquals("1", mat.group(4));
624     }
625 
626     @Test
testUnicode()627     public void testUnicode() {
628 
629         assertTrue(Pattern.matches("\\x61a", "aa"));
630         assertTrue(Pattern.matches("\\u0061a", "aa"));
631         assertTrue(Pattern.matches("\\0141a", "aa"));
632         assertTrue(Pattern.matches("\\0777", "?7"));
633 
634     }
635 
636     @Test
testUnicodeCategory()637     public void testUnicodeCategory() {
638         assertTrue(Pattern.matches("\\p{Ll}", "k")); // Unicode lower case
639         assertTrue(Pattern.matches("\\P{Ll}", "K")); // Unicode non-lower
640         // case
641         assertTrue(Pattern.matches("\\p{Lu}", "K")); // Unicode upper case
642         assertTrue(Pattern.matches("\\P{Lu}", "k")); // Unicode non-upper
643         // case
644         // combinations
645         assertTrue(Pattern.matches("[\\p{L}&&[^\\p{Lu}]]", "k"));
646         assertTrue(Pattern.matches("[\\p{L}&&[^\\p{Ll}]]", "K"));
647         assertFalse(Pattern.matches("[\\p{L}&&[^\\p{Lu}]]", "K"));
648         assertFalse(Pattern.matches("[\\p{L}&&[^\\p{Ll}]]", "k"));
649 
650         // category/character combinations
651         assertFalse(Pattern.matches("[\\p{L}&&[^a-z]]", "k"));
652         assertTrue(Pattern.matches("[\\p{L}&&[^a-z]]", "K"));
653 
654         assertTrue(Pattern.matches("[\\p{Lu}a-z]", "k"));
655         assertTrue(Pattern.matches("[a-z\\p{Lu}]", "k"));
656 
657         assertFalse(Pattern.matches("[\\p{Lu}a-d]", "k"));
658         assertTrue(Pattern.matches("[a-d\\p{Lu}]", "K"));
659 
660         // assertTrue(Pattern.matches("[\\p{L}&&[^\\p{Lu}&&[^K]]]", "K"));
661         assertFalse(Pattern.matches("[\\p{L}&&[^\\p{Lu}&&[^G]]]", "K"));
662 
663     }
664 
665     @Test
testFindDollar()666     public void testFindDollar() {
667         Matcher mat = Pattern.compile("a$").matcher("a\n");
668         assertTrue(mat.find());
669         assertEquals("a", mat.group());
670     }
671 
672     @Test
testMatchesRegionChanged()673     public void testMatchesRegionChanged() {
674         // Regression for HARMONY-610
675         // Verify if the Matcher can match the input when region is changed
676         String input = " word ";
677         Pattern pattern = Pattern.compile("\\w+");
678         Matcher matcher = pattern.matcher(input);
679         matcher.region(1, 5);
680         assertTrue(matcher.matches());
681     }
682 
683     @Test
testFindRegionChanged()684     public void testFindRegionChanged() {
685         // Regression for HARMONY-625
686         // Verify if the Matcher behaves correct when region is changed.
687         Pattern pattern = Pattern.compile("(?s).*");
688         Matcher matcher = pattern.matcher("abcde");
689         matcher.find();
690         assertEquals("abcde", matcher.group());
691 
692         matcher = pattern.matcher("abcde");
693         matcher.region(0, 2);
694         matcher.find();
695         assertEquals("ab", matcher.group());
696 
697     }
698 
699     @Test
testFindRegionChanged2()700     public void testFindRegionChanged2() {
701         // Regression for HARMONY-713
702         // Verify if the Matcher behaves correct with pattern "c" when region is changed.
703         Pattern pattern = Pattern.compile("c");
704 
705         String inputStr = "aabb.c";
706         Matcher matcher = pattern.matcher(inputStr);
707         matcher.region(0, 3);
708 
709         assertFalse(matcher.find());
710     }
711 
712     @Test
testPatternMatcher()713     public void testPatternMatcher() throws Exception {
714         // Regression test for HARMONY-674
715         Pattern pattern = Pattern.compile("(?:\\d+)(?:pt)");
716         assertTrue(pattern.matcher("14pt").matches());
717     }
718 
719     @Test
test3360()720     public void test3360() {
721         // Inspired by HARMONY-3360
722         String str = "!\"#%&'(),-./";
723         Pattern p = Pattern.compile("\\s");
724         Matcher m = p.matcher(str);
725 
726         assertFalse(m.find());
727     }
728 
729     @Test
testGeneralPunctuationCategory()730     public void testGeneralPunctuationCategory() {
731         // Regression test for HARMONY-3360
732         String[] s = { ",", "!", "\"", "#", "%", "&", "'", "(", ")", "-", ".", "/" };
733         String regexp = "\\p{P}";
734 
735         for (int i = 0; i < s.length; i++) {
736             Pattern pattern = Pattern.compile(regexp);
737             Matcher matcher = pattern.matcher(s[i]);
738             assertTrue(matcher.find());
739         }
740     }
741 
742     @Test
testHitEndAfterFind()743     public void testHitEndAfterFind() {
744         // Regression test for HARMONY-4396
745         hitEndTest(true, "#01.0", "r((ege)|(geg))x", "regexx", false);
746         hitEndTest(true, "#01.1", "r((ege)|(geg))x", "regex", false);
747         hitEndTest(true, "#01.2", "r((ege)|(geg))x", "rege", true);
748         hitEndTest(true, "#01.2", "r((ege)|(geg))x", "xregexx", false);
749 
750         hitEndTest(true, "#02.0", "regex", "rexreger", true);
751         hitEndTest(true, "#02.1", "regex", "raxregexr", false);
752 
753         String floatRegex = getHexFloatRegex();
754         hitEndTest(true, "#03.0", floatRegex, Double.toHexString(-1.234d), true);
755         hitEndTest(true, "#03.1", floatRegex, "1 ABC"
756                 + Double.toHexString(Double.NaN) + "buhuhu", false);
757         hitEndTest(true, "#03.2", floatRegex, Double.toHexString(-0.0) + "--",
758                 false);
759         hitEndTest(true, "#03.3", floatRegex, "--"
760                 + Double.toHexString(Double.MIN_VALUE) + "--", false);
761 
762         hitEndTest(true, "#04.0", "(\\d+) fish (\\d+) fish (\\w+) fish (\\d+)",
763                 "1 fish 2 fish red fish 5", true);
764         hitEndTest(true, "#04.1", "(\\d+) fish (\\d+) fish (\\w+) fish (\\d+)",
765                 "----1 fish 2 fish red fish 5----", false);
766     }
767 
hitEndTest(boolean callFind, String testNo, String regex, String input, boolean hit)768     private void hitEndTest(boolean callFind, String testNo, String regex,
769             String input, boolean hit) {
770         Pattern pattern = Pattern.compile(regex);
771         Matcher matcher = pattern.matcher(input);
772         if (callFind) {
773             matcher.find();
774         } else {
775             matcher.matches();
776         }
777         boolean h = matcher.hitEnd();
778 
779         assertTrue(testNo, h == hit);
780     }
781 
getHexFloatRegex()782     private String getHexFloatRegex() {
783         String hexDecimal = "(-|\\+)?0[xX][0-9a-fA-F]*\\.[0-9a-fA-F]+([pP](-|\\+)?[0-9]+)?";
784         String notANumber = "((-|\\+)?Infinity)|([nN]a[nN])";
785         return new StringBuilder("((").append(hexDecimal).append(")|(").append(
786                 notANumber).append("))").toString();
787     }
788 
789     @Test
testNamedGroupCapture()790     public void testNamedGroupCapture() {
791         Matcher m = Pattern.compile("(?<first>[a-f]*)(?<second>[h-k]*)")
792                 .matcher("abcdefhkhk");
793 
794         assertTrue(m.matches());
795         assertEquals("abcdef", m.group("first"));
796         assertEquals(0, m.start("first"));
797         assertEquals(6, m.end("first"));
798 
799         assertEquals("hkhk", m.group("second"));
800         assertEquals(6, m.start("second"));
801         assertEquals(10, m.end("second"));
802     }
803 
804     @Test
test_anchoringBounds()805     public void test_anchoringBounds() {
806         String testPattern = "^ro$";
807         String testString = "android";
808         Pattern pat = Pattern.compile(testPattern);
809         Matcher mat = pat.matcher(testString);
810 
811         mat.region(2, 5);
812         mat.useAnchoringBounds(false);
813         assertFalse("Shouldn't find pattern with non-anchoring bounds", mat.find(0));
814 
815         mat.region(2, 5);
816         mat.useAnchoringBounds(true);
817         assertFalse("Should find pattern with anchoring bounds", mat.find(0));
818     }
819 
820     @Test
test_transparentBounds()821     public void test_transparentBounds() {
822         String testPattern = "and(?=roid)";
823         String testString = "android";
824         Pattern pat = Pattern.compile(testPattern);
825         Matcher mat = pat.matcher(testString);
826 
827         mat.region(0, 3);
828         mat.useTransparentBounds(false);
829         assertFalse("Shouldn't find pattern with opaque bounds", mat.matches());
830 
831         mat.useTransparentBounds(true);
832         assertTrue("Should find pattern transparent bounds", mat.matches()); // ***
833 
834         testPattern = "and(?!roid)";
835         testString = "android";
836         pat = Pattern.compile(testPattern);
837         mat = pat.matcher(testString);
838 
839         mat.region(0, 3);
840         mat.useTransparentBounds(false);
841         assertTrue("Should find pattern with opaque bounds", mat.matches());
842 
843         mat.useTransparentBounds(true);
844         assertFalse("Shouldn't find pattern transparent bounds", mat.matches()); // ***
845     }
846 
847 }
848