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