1 /*
   2  * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  * @test
  26  * @summary tests RegExp framework
  27  * @author Mike McCloskey
  28  * @bug 4481568 4482696 4495089 4504687 4527731 4599621 4631553 4619345
  29  * 4630911 4672616 4711773 4727935 4750573 4792284 4803197 4757029 4808962
  30  * 4872664 4803179 4892980 4900747 4945394 4938995 4979006 4994840 4997476
  31  * 5013885 5003322 4988891 5098443 5110268 6173522 4829857 5027748 6376940
  32  * 6358731 6178785 6284152 6231989 6497148 6486934 6233084 6504326 6635133
  33  * 6350801 6676425 6878475 6919132 6931676 6948903 6990617 7014645 7039066
  34  * 7067045 7014640 7189363 8007395 8013252 8013254 8012646 8023647 6559590
  35  * 8027645 6854417 8169056
  36  */
  37 
  38 import java.util.regex.*;
  39 import java.util.Random;
  40 import java.io.*;
  41 import java.util.*;
  42 import java.nio.CharBuffer;
  43 import java.util.function.Predicate;
  44 
  45 /**
  46  * This is a test class created to check the operation of
  47  * the Pattern and Matcher classes.
  48  */
  49 public class RegExTest {
  50 
  51     private static Random generator = new Random();
  52     private static boolean failure = false;
  53     private static int failCount = 0;
  54     private static String firstFailure = null;
  55 
  56     /**
  57      * Main to interpret arguments and run several tests.
  58      *
  59      */
  60     public static void main(String[] args) throws Exception {
  61         // Most of the tests are in a file
  62         processFile("TestCases.txt");
  63         //processFile("PerlCases.txt");
  64         processFile("BMPTestCases.txt");
  65         processFile("SupplementaryTestCases.txt");
  66 
  67         // These test many randomly generated char patterns
  68         bm();
  69         slice();
  70 
  71         // These are hard to put into the file
  72         escapes();
  73         blankInput();
  74 
  75         // Substitition tests on randomly generated sequences
  76         globalSubstitute();
  77         stringbufferSubstitute();
  78         substitutionBasher();
  79 
  80         // Canonical Equivalence
  81         ceTest();
  82 
  83         // Anchors
  84         anchorTest();
  85 
  86         // boolean match calls
  87         matchesTest();
  88         lookingAtTest();
  89 
  90         // Pattern API
  91         patternMatchesTest();
  92 
  93         // Misc
  94         lookbehindTest();
  95         nullArgumentTest();
  96         backRefTest();
  97         groupCaptureTest();
  98         caretTest();
  99         charClassTest();
 100         emptyPatternTest();
 101         findIntTest();
 102         group0Test();
 103         longPatternTest();
 104         octalTest();
 105         ampersandTest();
 106         negationTest();
 107         splitTest();
 108         appendTest();
 109         caseFoldingTest();
 110         commentsTest();
 111         unixLinesTest();
 112         replaceFirstTest();
 113         gTest();
 114         zTest();
 115         serializeTest();
 116         reluctantRepetitionTest();
 117         multilineDollarTest();
 118         dollarAtEndTest();
 119         caretBetweenTerminatorsTest();
 120         // This RFE rejected in Tiger numOccurrencesTest();
 121         javaCharClassTest();
 122         nonCaptureRepetitionTest();
 123         notCapturedGroupCurlyMatchTest();
 124         escapedSegmentTest();
 125         literalPatternTest();
 126         literalReplacementTest();
 127         regionTest();
 128         toStringTest();
 129         negatedCharClassTest();
 130         findFromTest();
 131         boundsTest();
 132         unicodeWordBoundsTest();
 133         caretAtEndTest();
 134         wordSearchTest();
 135         hitEndTest();
 136         toMatchResultTest();
 137         surrogatesInClassTest();
 138         removeQEQuotingTest();
 139         namedGroupCaptureTest();
 140         nonBmpClassComplementTest();
 141         unicodePropertiesTest();
 142         unicodeHexNotationTest();
 143         unicodeClassesTest();
 144         horizontalAndVerticalWSTest();
 145         linebreakTest();
 146         branchTest();
 147         groupCurlyNotFoundSuppTest();
 148         groupCurlyBackoffTest();
 149         patternAsPredicate();
 150 
 151         if (failure) {
 152             throw new
 153                 RuntimeException("RegExTest failed, 1st failure: " +
 154                                  firstFailure);
 155         } else {
 156             System.err.println("OKAY: All tests passed.");
 157         }
 158     }
 159 
 160     // Utility functions
 161 
 162     private static String getRandomAlphaString(int length) {
 163         StringBuffer buf = new StringBuffer(length);
 164         for (int i=0; i<length; i++) {
 165             char randChar = (char)(97 + generator.nextInt(26));
 166             buf.append(randChar);
 167         }
 168         return buf.toString();
 169     }
 170 
 171     private static void check(Matcher m, String expected) {
 172         m.find();
 173         if (!m.group().equals(expected))
 174             failCount++;
 175     }
 176 
 177     private static void check(Matcher m, String result, boolean expected) {
 178         m.find();
 179         if (m.group().equals(result) != expected)
 180             failCount++;
 181     }
 182 
 183     private static void check(Pattern p, String s, boolean expected) {
 184         if (p.matcher(s).find() != expected)
 185             failCount++;
 186     }
 187 
 188     private static void check(String p, String s, boolean expected) {
 189         Matcher matcher = Pattern.compile(p).matcher(s);
 190         if (matcher.find() != expected)
 191             failCount++;
 192     }
 193 
 194     private static void check(String p, char c, boolean expected) {
 195         String propertyPattern = expected ? "\\p" + p : "\\P" + p;
 196         Pattern pattern = Pattern.compile(propertyPattern);
 197         char[] ca = new char[1]; ca[0] = c;
 198         Matcher matcher = pattern.matcher(new String(ca));
 199         if (!matcher.find())
 200             failCount++;
 201     }
 202 
 203     private static void check(String p, int codePoint, boolean expected) {
 204         String propertyPattern = expected ? "\\p" + p : "\\P" + p;
 205         Pattern pattern = Pattern.compile(propertyPattern);
 206         char[] ca = Character.toChars(codePoint);
 207         Matcher matcher = pattern.matcher(new String(ca));
 208         if (!matcher.find())
 209             failCount++;
 210     }
 211 
 212     private static void check(String p, int flag, String input, String s,
 213                               boolean expected)
 214     {
 215         Pattern pattern = Pattern.compile(p, flag);
 216         Matcher matcher = pattern.matcher(input);
 217         if (expected)
 218             check(matcher, s, expected);
 219         else
 220             check(pattern, input, false);
 221     }
 222 
 223     private static void report(String testName) {
 224         int spacesToAdd = 30 - testName.length();
 225         StringBuffer paddedNameBuffer = new StringBuffer(testName);
 226         for (int i=0; i<spacesToAdd; i++)
 227             paddedNameBuffer.append(" ");
 228         String paddedName = paddedNameBuffer.toString();
 229         System.err.println(paddedName + ": " +
 230                            (failCount==0 ? "Passed":"Failed("+failCount+")"));
 231         if (failCount > 0) {
 232             failure = true;
 233 
 234             if (firstFailure == null) {
 235                 firstFailure = testName;
 236             }
 237         }
 238 
 239         failCount = 0;
 240     }
 241 
 242     /**
 243      * Converts ASCII alphabet characters [A-Za-z] in the given 's' to
 244      * supplementary characters. This method does NOT fully take care
 245      * of the regex syntax.
 246      */
 247     private static String toSupplementaries(String s) {
 248         int length = s.length();
 249         StringBuffer sb = new StringBuffer(length * 2);
 250 
 251         for (int i = 0; i < length; ) {
 252             char c = s.charAt(i++);
 253             if (c == '\\') {
 254                 sb.append(c);
 255                 if (i < length) {
 256                     c = s.charAt(i++);
 257                     sb.append(c);
 258                     if (c == 'u') {
 259                         // assume no syntax error
 260                         sb.append(s.charAt(i++));
 261                         sb.append(s.charAt(i++));
 262                         sb.append(s.charAt(i++));
 263                         sb.append(s.charAt(i++));
 264                     }
 265                 }
 266             } else if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
 267                 sb.append('\ud800').append((char)('\udc00'+c));
 268             } else {
 269                 sb.append(c);
 270             }
 271         }
 272         return sb.toString();
 273     }
 274 
 275     // Regular expression tests
 276 
 277     // This is for bug 6178785
 278     // Test if an expected NPE gets thrown when passing in a null argument
 279     private static boolean check(Runnable test) {
 280         try {
 281             test.run();
 282             failCount++;
 283             return false;
 284         } catch (NullPointerException npe) {
 285             return true;
 286         }
 287     }
 288 
 289     private static void nullArgumentTest() {
 290         check(new Runnable() { public void run() { Pattern.compile(null); }});
 291         check(new Runnable() { public void run() { Pattern.matches(null, null); }});
 292         check(new Runnable() { public void run() { Pattern.matches("xyz", null);}});
 293         check(new Runnable() { public void run() { Pattern.quote(null);}});
 294         check(new Runnable() { public void run() { Pattern.compile("xyz").split(null);}});
 295         check(new Runnable() { public void run() { Pattern.compile("xyz").matcher(null);}});
 296 
 297         final Matcher m = Pattern.compile("xyz").matcher("xyz");
 298         m.matches();
 299         check(new Runnable() { public void run() { m.appendTail(null);}});
 300         check(new Runnable() { public void run() { m.replaceAll(null);}});
 301         check(new Runnable() { public void run() { m.replaceFirst(null);}});
 302         check(new Runnable() { public void run() { m.appendReplacement(null, null);}});
 303         check(new Runnable() { public void run() { m.reset(null);}});
 304         check(new Runnable() { public void run() { Matcher.quoteReplacement(null);}});
 305         //check(new Runnable() { public void run() { m.usePattern(null);}});
 306 
 307         report("Null Argument");
 308     }
 309 
 310     // This is for bug6635133
 311     // Test if surrogate pair in Unicode escapes can be handled correctly.
 312     private static void surrogatesInClassTest() throws Exception {
 313         Pattern pattern = Pattern.compile("[\\ud834\\udd21-\\ud834\\udd24]");
 314         Matcher matcher = pattern.matcher("\ud834\udd22");
 315         if (!matcher.find())
 316             failCount++;
 317 
 318         report("Surrogate pair in Unicode escape");
 319     }
 320 
 321     // This is for bug6990617
 322     // Test if Pattern.RemoveQEQuoting works correctly if the octal unicode
 323     // char encoding is only 2 or 3 digits instead of 4 and the first quoted
 324     // char is an octal digit.
 325     private static void removeQEQuotingTest() throws Exception {
 326         Pattern pattern =
 327             Pattern.compile("\\011\\Q1sometext\\E\\011\\Q2sometext\\E");
 328         Matcher matcher = pattern.matcher("\t1sometext\t2sometext");
 329         if (!matcher.find())
 330             failCount++;
 331 
 332         report("Remove Q/E Quoting");
 333     }
 334 
 335     // This is for bug 4988891
 336     // Test toMatchResult to see that it is a copy of the Matcher
 337     // that is not affected by subsequent operations on the original
 338     private static void toMatchResultTest() throws Exception {
 339         Pattern pattern = Pattern.compile("squid");
 340         Matcher matcher = pattern.matcher(
 341             "agiantsquidofdestinyasmallsquidoffate");
 342         matcher.find();
 343         int matcherStart1 = matcher.start();
 344         MatchResult mr = matcher.toMatchResult();
 345         if (mr == matcher)
 346             failCount++;
 347         int resultStart1 = mr.start();
 348         if (matcherStart1 != resultStart1)
 349             failCount++;
 350         matcher.find();
 351         int matcherStart2 = matcher.start();
 352         int resultStart2 = mr.start();
 353         if (matcherStart2 == resultStart2)
 354             failCount++;
 355         if (resultStart1 != resultStart2)
 356             failCount++;
 357         MatchResult mr2 = matcher.toMatchResult();
 358         if (mr == mr2)
 359             failCount++;
 360         if (mr2.start() != matcherStart2)
 361             failCount++;
 362         report("toMatchResult is a copy");
 363     }
 364 
 365     // This is for bug 5013885
 366     // Must test a slice to see if it reports hitEnd correctly
 367     private static void hitEndTest() throws Exception {
 368         // Basic test of Slice node
 369         Pattern p = Pattern.compile("^squidattack");
 370         Matcher m = p.matcher("squack");
 371         m.find();
 372         if (m.hitEnd())
 373             failCount++;
 374         m.reset("squid");
 375         m.find();
 376         if (!m.hitEnd())
 377             failCount++;
 378 
 379         // Test Slice, SliceA and SliceU nodes
 380         for (int i=0; i<3; i++) {
 381             int flags = 0;
 382             if (i==1) flags = Pattern.CASE_INSENSITIVE;
 383             if (i==2) flags = Pattern.UNICODE_CASE;
 384             p = Pattern.compile("^abc", flags);
 385             m = p.matcher("ad");
 386             m.find();
 387             if (m.hitEnd())
 388                 failCount++;
 389             m.reset("ab");
 390             m.find();
 391             if (!m.hitEnd())
 392                 failCount++;
 393         }
 394 
 395         // Test Boyer-Moore node
 396         p = Pattern.compile("catattack");
 397         m = p.matcher("attack");
 398         m.find();
 399         if (!m.hitEnd())
 400             failCount++;
 401 
 402         p = Pattern.compile("catattack");
 403         m = p.matcher("attackattackattackcatatta");
 404         m.find();
 405         if (!m.hitEnd())
 406             failCount++;
 407         report("hitEnd from a Slice");
 408     }
 409 
 410     // This is for bug 4997476
 411     // It is weird code submitted by customer demonstrating a regression
 412     private static void wordSearchTest() throws Exception {
 413         String testString = new String("word1 word2 word3");
 414         Pattern p = Pattern.compile("\\b");
 415         Matcher m = p.matcher(testString);
 416         int position = 0;
 417         int start = 0;
 418         while (m.find(position)) {
 419             start = m.start();
 420             if (start == testString.length())
 421                 break;
 422             if (m.find(start+1)) {
 423                 position = m.start();
 424             } else {
 425                 position = testString.length();
 426             }
 427             if (testString.substring(start, position).equals(" "))
 428                 continue;
 429             if (!testString.substring(start, position-1).startsWith("word"))
 430                 failCount++;
 431         }
 432         report("Customer word search");
 433     }
 434 
 435     // This is for bug 4994840
 436     private static void caretAtEndTest() throws Exception {
 437         // Problem only occurs with multiline patterns
 438         // containing a beginning-of-line caret "^" followed
 439         // by an expression that also matches the empty string.
 440         Pattern pattern = Pattern.compile("^x?", Pattern.MULTILINE);
 441         Matcher matcher = pattern.matcher("\r");
 442         matcher.find();
 443         matcher.find();
 444         report("Caret at end");
 445     }
 446 
 447     // This test is for 4979006
 448     // Check to see if word boundary construct properly handles unicode
 449     // non spacing marks
 450     private static void unicodeWordBoundsTest() throws Exception {
 451         String spaces = "  ";
 452         String wordChar = "a";
 453         String nsm = "\u030a";
 454 
 455         assert (Character.getType('\u030a') == Character.NON_SPACING_MARK);
 456 
 457         Pattern pattern = Pattern.compile("\\b");
 458         Matcher matcher = pattern.matcher("");
 459         // S=other B=word character N=non spacing mark .=word boundary
 460         // SS.BB.SS
 461         String input = spaces + wordChar + wordChar + spaces;
 462         twoFindIndexes(input, matcher, 2, 4);
 463         // SS.BBN.SS
 464         input = spaces + wordChar +wordChar + nsm + spaces;
 465         twoFindIndexes(input, matcher, 2, 5);
 466         // SS.BN.SS
 467         input = spaces + wordChar + nsm + spaces;
 468         twoFindIndexes(input, matcher, 2, 4);
 469         // SS.BNN.SS
 470         input = spaces + wordChar + nsm + nsm + spaces;
 471         twoFindIndexes(input, matcher, 2, 5);
 472         // SSN.BB.SS
 473         input = spaces + nsm + wordChar + wordChar + spaces;
 474         twoFindIndexes(input, matcher, 3, 5);
 475         // SS.BNB.SS
 476         input = spaces + wordChar + nsm + wordChar + spaces;
 477         twoFindIndexes(input, matcher, 2, 5);
 478         // SSNNSS
 479         input = spaces + nsm + nsm + spaces;
 480         matcher.reset(input);
 481         if (matcher.find())
 482             failCount++;
 483         // SSN.BBN.SS
 484         input = spaces + nsm + wordChar + wordChar + nsm + spaces;
 485         twoFindIndexes(input, matcher, 3, 6);
 486 
 487         report("Unicode word boundary");
 488     }
 489 
 490     private static void twoFindIndexes(String input, Matcher matcher, int a,
 491                                        int b) throws Exception
 492     {
 493         matcher.reset(input);
 494         matcher.find();
 495         if (matcher.start() != a)
 496             failCount++;
 497         matcher.find();
 498         if (matcher.start() != b)
 499             failCount++;
 500     }
 501 
 502     // This test is for 6284152
 503     static void check(String regex, String input, String[] expected) {
 504         List<String> result = new ArrayList<String>();
 505         Pattern p = Pattern.compile(regex);
 506         Matcher m = p.matcher(input);
 507         while (m.find()) {
 508             result.add(m.group());
 509         }
 510         if (!Arrays.asList(expected).equals(result))
 511             failCount++;
 512     }
 513 
 514     private static void lookbehindTest() throws Exception {
 515         //Positive
 516         check("(?<=%.{0,5})foo\\d",
 517               "%foo1\n%bar foo2\n%bar  foo3\n%blahblah foo4\nfoo5",
 518               new String[]{"foo1", "foo2", "foo3"});
 519 
 520         //boundary at end of the lookbehind sub-regex should work consistently
 521         //with the boundary just after the lookbehind sub-regex
 522         check("(?<=.*\\b)foo", "abcd foo", new String[]{"foo"});
 523         check("(?<=.*)\\bfoo", "abcd foo", new String[]{"foo"});
 524         check("(?<!abc )\\bfoo", "abc foo", new String[0]);
 525         check("(?<!abc \\b)foo", "abc foo", new String[0]);
 526 
 527         //Negative
 528         check("(?<!%.{0,5})foo\\d",
 529               "%foo1\n%bar foo2\n%bar  foo3\n%blahblah foo4\nfoo5",
 530               new String[] {"foo4", "foo5"});
 531 
 532         //Positive greedy
 533         check("(?<=%b{1,4})foo", "%bbbbfoo", new String[] {"foo"});
 534 
 535         //Positive reluctant
 536         check("(?<=%b{1,4}?)foo", "%bbbbfoo", new String[] {"foo"});
 537 
 538         //supplementary
 539         check("(?<=%b{1,4})fo\ud800\udc00o", "%bbbbfo\ud800\udc00o",
 540               new String[] {"fo\ud800\udc00o"});
 541         check("(?<=%b{1,4}?)fo\ud800\udc00o", "%bbbbfo\ud800\udc00o",
 542               new String[] {"fo\ud800\udc00o"});
 543         check("(?<!%b{1,4})fo\ud800\udc00o", "%afo\ud800\udc00o",
 544               new String[] {"fo\ud800\udc00o"});
 545         check("(?<!%b{1,4}?)fo\ud800\udc00o", "%afo\ud800\udc00o",
 546               new String[] {"fo\ud800\udc00o"});
 547         report("Lookbehind");
 548     }
 549 
 550     // This test is for 4938995
 551     // Check to see if weak region boundaries are transparent to
 552     // lookahead and lookbehind constructs
 553     private static void boundsTest() throws Exception {
 554         String fullMessage = "catdogcat";
 555         Pattern pattern = Pattern.compile("(?<=cat)dog(?=cat)");
 556         Matcher matcher = pattern.matcher("catdogca");
 557         matcher.useTransparentBounds(true);
 558         if (matcher.find())
 559             failCount++;
 560         matcher.reset("atdogcat");
 561         if (matcher.find())
 562             failCount++;
 563         matcher.reset(fullMessage);
 564         if (!matcher.find())
 565             failCount++;
 566         matcher.reset(fullMessage);
 567         matcher.region(0,9);
 568         if (!matcher.find())
 569             failCount++;
 570         matcher.reset(fullMessage);
 571         matcher.region(0,6);
 572         if (!matcher.find())
 573             failCount++;
 574         matcher.reset(fullMessage);
 575         matcher.region(3,6);
 576         if (!matcher.find())
 577             failCount++;
 578         matcher.useTransparentBounds(false);
 579         if (matcher.find())
 580             failCount++;
 581 
 582         // Negative lookahead/lookbehind
 583         pattern = Pattern.compile("(?<!cat)dog(?!cat)");
 584         matcher = pattern.matcher("dogcat");
 585         matcher.useTransparentBounds(true);
 586         matcher.region(0,3);
 587         if (matcher.find())
 588             failCount++;
 589         matcher.reset("catdog");
 590         matcher.region(3,6);
 591         if (matcher.find())
 592             failCount++;
 593         matcher.useTransparentBounds(false);
 594         matcher.reset("dogcat");
 595         matcher.region(0,3);
 596         if (!matcher.find())
 597             failCount++;
 598         matcher.reset("catdog");
 599         matcher.region(3,6);
 600         if (!matcher.find())
 601             failCount++;
 602 
 603         report("Region bounds transparency");
 604     }
 605 
 606     // This test is for 4945394
 607     private static void findFromTest() throws Exception {
 608         String message = "This is 40 $0 message.";
 609         Pattern pat = Pattern.compile("\\$0");
 610         Matcher match = pat.matcher(message);
 611         if (!match.find())
 612             failCount++;
 613         if (match.find())
 614             failCount++;
 615         if (match.find())
 616             failCount++;
 617         report("Check for alternating find");
 618     }
 619 
 620     // This test is for 4872664 and 4892980
 621     private static void negatedCharClassTest() throws Exception {
 622         Pattern pattern = Pattern.compile("[^>]");
 623         Matcher matcher = pattern.matcher("\u203A");
 624         if (!matcher.matches())
 625             failCount++;
 626         pattern = Pattern.compile("[^fr]");
 627         matcher = pattern.matcher("a");
 628         if (!matcher.find())
 629             failCount++;
 630         matcher.reset("\u203A");
 631         if (!matcher.find())
 632             failCount++;
 633         String s = "for";
 634         String result[] = s.split("[^fr]");
 635         if (!result[0].equals("f"))
 636             failCount++;
 637         if (!result[1].equals("r"))
 638             failCount++;
 639         s = "f\u203Ar";
 640         result = s.split("[^fr]");
 641         if (!result[0].equals("f"))
 642             failCount++;
 643         if (!result[1].equals("r"))
 644             failCount++;
 645 
 646         // Test adding to bits, subtracting a node, then adding to bits again
 647         pattern = Pattern.compile("[^f\u203Ar]");
 648         matcher = pattern.matcher("a");
 649         if (!matcher.find())
 650             failCount++;
 651         matcher.reset("f");
 652         if (matcher.find())
 653             failCount++;
 654         matcher.reset("\u203A");
 655         if (matcher.find())
 656             failCount++;
 657         matcher.reset("r");
 658         if (matcher.find())
 659             failCount++;
 660         matcher.reset("\u203B");
 661         if (!matcher.find())
 662             failCount++;
 663 
 664         // Test subtracting a node, adding to bits, subtracting again
 665         pattern = Pattern.compile("[^\u203Ar\u203B]");
 666         matcher = pattern.matcher("a");
 667         if (!matcher.find())
 668             failCount++;
 669         matcher.reset("\u203A");
 670         if (matcher.find())
 671             failCount++;
 672         matcher.reset("r");
 673         if (matcher.find())
 674             failCount++;
 675         matcher.reset("\u203B");
 676         if (matcher.find())
 677             failCount++;
 678         matcher.reset("\u203C");
 679         if (!matcher.find())
 680             failCount++;
 681 
 682         report("Negated Character Class");
 683     }
 684 
 685     // This test is for 4628291
 686     private static void toStringTest() throws Exception {
 687         Pattern pattern = Pattern.compile("b+");
 688         if (pattern.toString() != "b+")
 689             failCount++;
 690         Matcher matcher = pattern.matcher("aaabbbccc");
 691         String matcherString = matcher.toString(); // unspecified
 692         matcher.find();
 693         matcherString = matcher.toString(); // unspecified
 694         matcher.region(0,3);
 695         matcherString = matcher.toString(); // unspecified
 696         matcher.reset();
 697         matcherString = matcher.toString(); // unspecified
 698         report("toString");
 699     }
 700 
 701     // This test is for 4808962
 702     private static void literalPatternTest() throws Exception {
 703         int flags = Pattern.LITERAL;
 704 
 705         Pattern pattern = Pattern.compile("abc\\t$^", flags);
 706         check(pattern, "abc\\t$^", true);
 707 
 708         pattern = Pattern.compile(Pattern.quote("abc\\t$^"));
 709         check(pattern, "abc\\t$^", true);
 710 
 711         pattern = Pattern.compile("\\Qa^$bcabc\\E", flags);
 712         check(pattern, "\\Qa^$bcabc\\E", true);
 713         check(pattern, "a^$bcabc", false);
 714 
 715         pattern = Pattern.compile("\\\\Q\\\\E");
 716         check(pattern, "\\Q\\E", true);
 717 
 718         pattern = Pattern.compile("\\Qabc\\Eefg\\\\Q\\\\Ehij");
 719         check(pattern, "abcefg\\Q\\Ehij", true);
 720 
 721         pattern = Pattern.compile("\\\\\\Q\\\\E");
 722         check(pattern, "\\\\\\\\", true);
 723 
 724         pattern = Pattern.compile(Pattern.quote("\\Qa^$bcabc\\E"));
 725         check(pattern, "\\Qa^$bcabc\\E", true);
 726         check(pattern, "a^$bcabc", false);
 727 
 728         pattern = Pattern.compile(Pattern.quote("\\Qabc\\Edef"));
 729         check(pattern, "\\Qabc\\Edef", true);
 730         check(pattern, "abcdef", false);
 731 
 732         pattern = Pattern.compile(Pattern.quote("abc\\Edef"));
 733         check(pattern, "abc\\Edef", true);
 734         check(pattern, "abcdef", false);
 735 
 736         pattern = Pattern.compile(Pattern.quote("\\E"));
 737         check(pattern, "\\E", true);
 738 
 739         pattern = Pattern.compile("((((abc.+?:)", flags);
 740         check(pattern, "((((abc.+?:)", true);
 741 
 742         flags |= Pattern.MULTILINE;
 743 
 744         pattern = Pattern.compile("^cat$", flags);
 745         check(pattern, "abc^cat$def", true);
 746         check(pattern, "cat", false);
 747 
 748         flags |= Pattern.CASE_INSENSITIVE;
 749 
 750         pattern = Pattern.compile("abcdef", flags);
 751         check(pattern, "ABCDEF", true);
 752         check(pattern, "AbCdEf", true);
 753 
 754         flags |= Pattern.DOTALL;
 755 
 756         pattern = Pattern.compile("a...b", flags);
 757         check(pattern, "A...b", true);
 758         check(pattern, "Axxxb", false);
 759 
 760         flags |= Pattern.CANON_EQ;
 761 
 762         Pattern p = Pattern.compile("testa\u030a", flags);
 763         check(pattern, "testa\u030a", false);
 764         check(pattern, "test\u00e5", false);
 765 
 766         // Supplementary character test
 767         flags = Pattern.LITERAL;
 768 
 769         pattern = Pattern.compile(toSupplementaries("abc\\t$^"), flags);
 770         check(pattern, toSupplementaries("abc\\t$^"), true);
 771 
 772         pattern = Pattern.compile(Pattern.quote(toSupplementaries("abc\\t$^")));
 773         check(pattern, toSupplementaries("abc\\t$^"), true);
 774 
 775         pattern = Pattern.compile(toSupplementaries("\\Qa^$bcabc\\E"), flags);
 776         check(pattern, toSupplementaries("\\Qa^$bcabc\\E"), true);
 777         check(pattern, toSupplementaries("a^$bcabc"), false);
 778 
 779         pattern = Pattern.compile(Pattern.quote(toSupplementaries("\\Qa^$bcabc\\E")));
 780         check(pattern, toSupplementaries("\\Qa^$bcabc\\E"), true);
 781         check(pattern, toSupplementaries("a^$bcabc"), false);
 782 
 783         pattern = Pattern.compile(Pattern.quote(toSupplementaries("\\Qabc\\Edef")));
 784         check(pattern, toSupplementaries("\\Qabc\\Edef"), true);
 785         check(pattern, toSupplementaries("abcdef"), false);
 786 
 787         pattern = Pattern.compile(Pattern.quote(toSupplementaries("abc\\Edef")));
 788         check(pattern, toSupplementaries("abc\\Edef"), true);
 789         check(pattern, toSupplementaries("abcdef"), false);
 790 
 791         pattern = Pattern.compile(toSupplementaries("((((abc.+?:)"), flags);
 792         check(pattern, toSupplementaries("((((abc.+?:)"), true);
 793 
 794         flags |= Pattern.MULTILINE;
 795 
 796         pattern = Pattern.compile(toSupplementaries("^cat$"), flags);
 797         check(pattern, toSupplementaries("abc^cat$def"), true);
 798         check(pattern, toSupplementaries("cat"), false);
 799 
 800         flags |= Pattern.DOTALL;
 801 
 802         // note: this is case-sensitive.
 803         pattern = Pattern.compile(toSupplementaries("a...b"), flags);
 804         check(pattern, toSupplementaries("a...b"), true);
 805         check(pattern, toSupplementaries("axxxb"), false);
 806 
 807         flags |= Pattern.CANON_EQ;
 808 
 809         String t = toSupplementaries("test");
 810         p = Pattern.compile(t + "a\u030a", flags);
 811         check(pattern, t + "a\u030a", false);
 812         check(pattern, t + "\u00e5", false);
 813 
 814         report("Literal pattern");
 815     }
 816 
 817     // This test is for 4803179
 818     // This test is also for 4808962, replacement parts
 819     private static void literalReplacementTest() throws Exception {
 820         int flags = Pattern.LITERAL;
 821 
 822         Pattern pattern = Pattern.compile("abc", flags);
 823         Matcher matcher = pattern.matcher("zzzabczzz");
 824         String replaceTest = "$0";
 825         String result = matcher.replaceAll(replaceTest);
 826         if (!result.equals("zzzabczzz"))
 827             failCount++;
 828 
 829         matcher.reset();
 830         String literalReplacement = matcher.quoteReplacement(replaceTest);
 831         result = matcher.replaceAll(literalReplacement);
 832         if (!result.equals("zzz$0zzz"))
 833             failCount++;
 834 
 835         matcher.reset();
 836         replaceTest = "\\t$\\$";
 837         literalReplacement = matcher.quoteReplacement(replaceTest);
 838         result = matcher.replaceAll(literalReplacement);
 839         if (!result.equals("zzz\\t$\\$zzz"))
 840             failCount++;
 841 
 842         // Supplementary character test
 843         pattern = Pattern.compile(toSupplementaries("abc"), flags);
 844         matcher = pattern.matcher(toSupplementaries("zzzabczzz"));
 845         replaceTest = "$0";
 846         result = matcher.replaceAll(replaceTest);
 847         if (!result.equals(toSupplementaries("zzzabczzz")))
 848             failCount++;
 849 
 850         matcher.reset();
 851         literalReplacement = matcher.quoteReplacement(replaceTest);
 852         result = matcher.replaceAll(literalReplacement);
 853         if (!result.equals(toSupplementaries("zzz$0zzz")))
 854             failCount++;
 855 
 856         matcher.reset();
 857         replaceTest = "\\t$\\$";
 858         literalReplacement = matcher.quoteReplacement(replaceTest);
 859         result = matcher.replaceAll(literalReplacement);
 860         if (!result.equals(toSupplementaries("zzz\\t$\\$zzz")))
 861             failCount++;
 862 
 863         // IAE should be thrown if backslash or '$' is the last character
 864         // in replacement string
 865         try {
 866             "\uac00".replaceAll("\uac00", "$");
 867             failCount++;
 868         } catch (IllegalArgumentException iie) {
 869         } catch (Exception e) {
 870             failCount++;
 871         }
 872         try {
 873             "\uac00".replaceAll("\uac00", "\\");
 874             failCount++;
 875         } catch (IllegalArgumentException iie) {
 876         } catch (Exception e) {
 877             failCount++;
 878         }
 879         report("Literal replacement");
 880     }
 881 
 882     // This test is for 4757029
 883     private static void regionTest() throws Exception {
 884         Pattern pattern = Pattern.compile("abc");
 885         Matcher matcher = pattern.matcher("abcdefabc");
 886 
 887         matcher.region(0,9);
 888         if (!matcher.find())
 889             failCount++;
 890         if (!matcher.find())
 891             failCount++;
 892         matcher.region(0,3);
 893         if (!matcher.find())
 894            failCount++;
 895         matcher.region(3,6);
 896         if (matcher.find())
 897            failCount++;
 898         matcher.region(0,2);
 899         if (matcher.find())
 900            failCount++;
 901 
 902         expectRegionFail(matcher, 1, -1);
 903         expectRegionFail(matcher, -1, -1);
 904         expectRegionFail(matcher, -1, 1);
 905         expectRegionFail(matcher, 5, 3);
 906         expectRegionFail(matcher, 5, 12);
 907         expectRegionFail(matcher, 12, 12);
 908 
 909         pattern = Pattern.compile("^abc$");
 910         matcher = pattern.matcher("zzzabczzz");
 911         matcher.region(0,9);
 912         if (matcher.find())
 913             failCount++;
 914         matcher.region(3,6);
 915         if (!matcher.find())
 916            failCount++;
 917         matcher.region(3,6);
 918         matcher.useAnchoringBounds(false);
 919         if (matcher.find())
 920            failCount++;
 921 
 922         // Supplementary character test
 923         pattern = Pattern.compile(toSupplementaries("abc"));
 924         matcher = pattern.matcher(toSupplementaries("abcdefabc"));
 925         matcher.region(0,9*2);
 926         if (!matcher.find())
 927             failCount++;
 928         if (!matcher.find())
 929             failCount++;
 930         matcher.region(0,3*2);
 931         if (!matcher.find())
 932            failCount++;
 933         matcher.region(1,3*2);
 934         if (matcher.find())
 935            failCount++;
 936         matcher.region(3*2,6*2);
 937         if (matcher.find())
 938            failCount++;
 939         matcher.region(0,2*2);
 940         if (matcher.find())
 941            failCount++;
 942         matcher.region(0,2*2+1);
 943         if (matcher.find())
 944            failCount++;
 945 
 946         expectRegionFail(matcher, 1*2, -1);
 947         expectRegionFail(matcher, -1, -1);
 948         expectRegionFail(matcher, -1, 1*2);
 949         expectRegionFail(matcher, 5*2, 3*2);
 950         expectRegionFail(matcher, 5*2, 12*2);
 951         expectRegionFail(matcher, 12*2, 12*2);
 952 
 953         pattern = Pattern.compile(toSupplementaries("^abc$"));
 954         matcher = pattern.matcher(toSupplementaries("zzzabczzz"));
 955         matcher.region(0,9*2);
 956         if (matcher.find())
 957             failCount++;
 958         matcher.region(3*2,6*2);
 959         if (!matcher.find())
 960            failCount++;
 961         matcher.region(3*2+1,6*2);
 962         if (matcher.find())
 963            failCount++;
 964         matcher.region(3*2,6*2-1);
 965         if (matcher.find())
 966            failCount++;
 967         matcher.region(3*2,6*2);
 968         matcher.useAnchoringBounds(false);
 969         if (matcher.find())
 970            failCount++;
 971         report("Regions");
 972     }
 973 
 974     private static void expectRegionFail(Matcher matcher, int index1,
 975                                          int index2)
 976     {
 977         try {
 978             matcher.region(index1, index2);
 979             failCount++;
 980         } catch (IndexOutOfBoundsException ioobe) {
 981             // Correct result
 982         } catch (IllegalStateException ise) {
 983             // Correct result
 984         }
 985     }
 986 
 987     // This test is for 4803197
 988     private static void escapedSegmentTest() throws Exception {
 989 
 990         Pattern pattern = Pattern.compile("\\Qdir1\\dir2\\E");
 991         check(pattern, "dir1\\dir2", true);
 992 
 993         pattern = Pattern.compile("\\Qdir1\\dir2\\\\E");
 994         check(pattern, "dir1\\dir2\\", true);
 995 
 996         pattern = Pattern.compile("(\\Qdir1\\dir2\\\\E)");
 997         check(pattern, "dir1\\dir2\\", true);
 998 
 999         // Supplementary character test
1000         pattern = Pattern.compile(toSupplementaries("\\Qdir1\\dir2\\E"));
1001         check(pattern, toSupplementaries("dir1\\dir2"), true);
1002 
1003         pattern = Pattern.compile(toSupplementaries("\\Qdir1\\dir2")+"\\\\E");
1004         check(pattern, toSupplementaries("dir1\\dir2\\"), true);
1005 
1006         pattern = Pattern.compile(toSupplementaries("(\\Qdir1\\dir2")+"\\\\E)");
1007         check(pattern, toSupplementaries("dir1\\dir2\\"), true);
1008 
1009         report("Escaped segment");
1010     }
1011 
1012     // This test is for 4792284
1013     private static void nonCaptureRepetitionTest() throws Exception {
1014         String input = "abcdefgh;";
1015 
1016         String[] patterns = new String[] {
1017             "(?:\\w{4})+;",
1018             "(?:\\w{8})*;",
1019             "(?:\\w{2}){2,4};",
1020             "(?:\\w{4}){2,};",   // only matches the
1021             ".*?(?:\\w{5})+;",   //     specified minimum
1022             ".*?(?:\\w{9})*;",   //     number of reps - OK
1023             "(?:\\w{4})+?;",     // lazy repetition - OK
1024             "(?:\\w{4})++;",     // possessive repetition - OK
1025             "(?:\\w{2,}?)+;",    // non-deterministic - OK
1026             "(\\w{4})+;",        // capturing group - OK
1027         };
1028 
1029         for (int i = 0; i < patterns.length; i++) {
1030             // Check find()
1031             check(patterns[i], 0, input, input, true);
1032             // Check matches()
1033             Pattern p = Pattern.compile(patterns[i]);
1034             Matcher m = p.matcher(input);
1035 
1036             if (m.matches()) {
1037                 if (!m.group(0).equals(input))
1038                     failCount++;
1039             } else {
1040                 failCount++;
1041             }
1042         }
1043 
1044         report("Non capturing repetition");
1045     }
1046 
1047     // This test is for 6358731
1048     private static void notCapturedGroupCurlyMatchTest() throws Exception {
1049         Pattern pattern = Pattern.compile("(abc)+|(abcd)+");
1050         Matcher matcher = pattern.matcher("abcd");
1051         if (!matcher.matches() ||
1052              matcher.group(1) != null ||
1053              !matcher.group(2).equals("abcd")) {
1054             failCount++;
1055         }
1056         report("Not captured GroupCurly");
1057     }
1058 
1059     // This test is for 4706545
1060     private static void javaCharClassTest() throws Exception {
1061         for (int i=0; i<1000; i++) {
1062             char c = (char)generator.nextInt();
1063             check("{javaLowerCase}", c, Character.isLowerCase(c));
1064             check("{javaUpperCase}", c, Character.isUpperCase(c));
1065             check("{javaUpperCase}+", c, Character.isUpperCase(c));
1066             check("{javaTitleCase}", c, Character.isTitleCase(c));
1067             check("{javaDigit}", c, Character.isDigit(c));
1068             check("{javaDefined}", c, Character.isDefined(c));
1069             check("{javaLetter}", c, Character.isLetter(c));
1070             check("{javaLetterOrDigit}", c, Character.isLetterOrDigit(c));
1071             check("{javaJavaIdentifierStart}", c,
1072                   Character.isJavaIdentifierStart(c));
1073             check("{javaJavaIdentifierPart}", c,
1074                   Character.isJavaIdentifierPart(c));
1075             check("{javaUnicodeIdentifierStart}", c,
1076                   Character.isUnicodeIdentifierStart(c));
1077             check("{javaUnicodeIdentifierPart}", c,
1078                   Character.isUnicodeIdentifierPart(c));
1079             check("{javaIdentifierIgnorable}", c,
1080                   Character.isIdentifierIgnorable(c));
1081             check("{javaSpaceChar}", c, Character.isSpaceChar(c));
1082             check("{javaWhitespace}", c, Character.isWhitespace(c));
1083             check("{javaISOControl}", c, Character.isISOControl(c));
1084             check("{javaMirrored}", c, Character.isMirrored(c));
1085 
1086         }
1087 
1088         // Supplementary character test
1089         for (int i=0; i<1000; i++) {
1090             int c = generator.nextInt(Character.MAX_CODE_POINT
1091                                       - Character.MIN_SUPPLEMENTARY_CODE_POINT)
1092                         + Character.MIN_SUPPLEMENTARY_CODE_POINT;
1093             check("{javaLowerCase}", c, Character.isLowerCase(c));
1094             check("{javaUpperCase}", c, Character.isUpperCase(c));
1095             check("{javaUpperCase}+", c, Character.isUpperCase(c));
1096             check("{javaTitleCase}", c, Character.isTitleCase(c));
1097             check("{javaDigit}", c, Character.isDigit(c));
1098             check("{javaDefined}", c, Character.isDefined(c));
1099             check("{javaLetter}", c, Character.isLetter(c));
1100             check("{javaLetterOrDigit}", c, Character.isLetterOrDigit(c));
1101             check("{javaJavaIdentifierStart}", c,
1102                   Character.isJavaIdentifierStart(c));
1103             check("{javaJavaIdentifierPart}", c,
1104                   Character.isJavaIdentifierPart(c));
1105             check("{javaUnicodeIdentifierStart}", c,
1106                   Character.isUnicodeIdentifierStart(c));
1107             check("{javaUnicodeIdentifierPart}", c,
1108                   Character.isUnicodeIdentifierPart(c));
1109             check("{javaIdentifierIgnorable}", c,
1110                   Character.isIdentifierIgnorable(c));
1111             check("{javaSpaceChar}", c, Character.isSpaceChar(c));
1112             check("{javaWhitespace}", c, Character.isWhitespace(c));
1113             check("{javaISOControl}", c, Character.isISOControl(c));
1114             check("{javaMirrored}", c, Character.isMirrored(c));
1115         }
1116 
1117         report("Java character classes");
1118     }
1119 
1120     // This test is for 4523620
1121     /*
1122     private static void numOccurrencesTest() throws Exception {
1123         Pattern pattern = Pattern.compile("aaa");
1124 
1125         if (pattern.numOccurrences("aaaaaa", false) != 2)
1126             failCount++;
1127         if (pattern.numOccurrences("aaaaaa", true) != 4)
1128             failCount++;
1129 
1130         pattern = Pattern.compile("^");
1131         if (pattern.numOccurrences("aaaaaa", false) != 1)
1132             failCount++;
1133         if (pattern.numOccurrences("aaaaaa", true) != 1)
1134             failCount++;
1135 
1136         report("Number of Occurrences");
1137     }
1138     */
1139 
1140     // This test is for 4776374
1141     private static void caretBetweenTerminatorsTest() throws Exception {
1142         int flags1 = Pattern.DOTALL;
1143         int flags2 = Pattern.DOTALL | Pattern.UNIX_LINES;
1144         int flags3 = Pattern.DOTALL | Pattern.UNIX_LINES | Pattern.MULTILINE;
1145         int flags4 = Pattern.DOTALL | Pattern.MULTILINE;
1146 
1147         check("^....", flags1, "test\ntest", "test", true);
1148         check(".....^", flags1, "test\ntest", "test", false);
1149         check(".....^", flags1, "test\n", "test", false);
1150         check("....^", flags1, "test\r\n", "test", false);
1151 
1152         check("^....", flags2, "test\ntest", "test", true);
1153         check("....^", flags2, "test\ntest", "test", false);
1154         check(".....^", flags2, "test\n", "test", false);
1155         check("....^", flags2, "test\r\n", "test", false);
1156 
1157         check("^....", flags3, "test\ntest", "test", true);
1158         check(".....^", flags3, "test\ntest", "test\n", true);
1159         check(".....^", flags3, "test\u0085test", "test\u0085", false);
1160         check(".....^", flags3, "test\n", "test", false);
1161         check(".....^", flags3, "test\r\n", "test", false);
1162         check("......^", flags3, "test\r\ntest", "test\r\n", true);
1163 
1164         check("^....", flags4, "test\ntest", "test", true);
1165         check(".....^", flags3, "test\ntest", "test\n", true);
1166         check(".....^", flags4, "test\u0085test", "test\u0085", true);
1167         check(".....^", flags4, "test\n", "test\n", false);
1168         check(".....^", flags4, "test\r\n", "test\r", false);
1169 
1170         // Supplementary character test
1171         String t = toSupplementaries("test");
1172         check("^....", flags1, t+"\n"+t, t, true);
1173         check(".....^", flags1, t+"\n"+t, t, false);
1174         check(".....^", flags1, t+"\n", t, false);
1175         check("....^", flags1, t+"\r\n", t, false);
1176 
1177         check("^....", flags2, t+"\n"+t, t, true);
1178         check("....^", flags2, t+"\n"+t, t, false);
1179         check(".....^", flags2, t+"\n", t, false);
1180         check("....^", flags2, t+"\r\n", t, false);
1181 
1182         check("^....", flags3, t+"\n"+t, t, true);
1183         check(".....^", flags3, t+"\n"+t, t+"\n", true);
1184         check(".....^", flags3, t+"\u0085"+t, t+"\u0085", false);
1185         check(".....^", flags3, t+"\n", t, false);
1186         check(".....^", flags3, t+"\r\n", t, false);
1187         check("......^", flags3, t+"\r\n"+t, t+"\r\n", true);
1188 
1189         check("^....", flags4, t+"\n"+t, t, true);
1190         check(".....^", flags3, t+"\n"+t, t+"\n", true);
1191         check(".....^", flags4, t+"\u0085"+t, t+"\u0085", true);
1192         check(".....^", flags4, t+"\n", t+"\n", false);
1193         check(".....^", flags4, t+"\r\n", t+"\r", false);
1194 
1195         report("Caret between terminators");
1196     }
1197 
1198     // This test is for 4727935
1199     private static void dollarAtEndTest() throws Exception {
1200         int flags1 = Pattern.DOTALL;
1201         int flags2 = Pattern.DOTALL | Pattern.UNIX_LINES;
1202         int flags3 = Pattern.DOTALL | Pattern.MULTILINE;
1203 
1204         check("....$", flags1, "test\n", "test", true);
1205         check("....$", flags1, "test\r\n", "test", true);
1206         check(".....$", flags1, "test\n", "test\n", true);
1207         check(".....$", flags1, "test\u0085", "test\u0085", true);
1208         check("....$", flags1, "test\u0085", "test", true);
1209 
1210         check("....$", flags2, "test\n", "test", true);
1211         check(".....$", flags2, "test\n", "test\n", true);
1212         check(".....$", flags2, "test\u0085", "test\u0085", true);
1213         check("....$", flags2, "test\u0085", "est\u0085", true);
1214 
1215         check("....$.blah", flags3, "test\nblah", "test\nblah", true);
1216         check(".....$.blah", flags3, "test\n\nblah", "test\n\nblah", true);
1217         check("....$blah", flags3, "test\nblah", "!!!!", false);
1218         check(".....$blah", flags3, "test\nblah", "!!!!", false);
1219 
1220         // Supplementary character test
1221         String t = toSupplementaries("test");
1222         String b = toSupplementaries("blah");
1223         check("....$", flags1, t+"\n", t, true);
1224         check("....$", flags1, t+"\r\n", t, true);
1225         check(".....$", flags1, t+"\n", t+"\n", true);
1226         check(".....$", flags1, t+"\u0085", t+"\u0085", true);
1227         check("....$", flags1, t+"\u0085", t, true);
1228 
1229         check("....$", flags2, t+"\n", t, true);
1230         check(".....$", flags2, t+"\n", t+"\n", true);
1231         check(".....$", flags2, t+"\u0085", t+"\u0085", true);
1232         check("....$", flags2, t+"\u0085", toSupplementaries("est\u0085"), true);
1233 
1234         check("....$."+b, flags3, t+"\n"+b, t+"\n"+b, true);
1235         check(".....$."+b, flags3, t+"\n\n"+b, t+"\n\n"+b, true);
1236         check("....$"+b, flags3, t+"\n"+b, "!!!!", false);
1237         check(".....$"+b, flags3, t+"\n"+b, "!!!!", false);
1238 
1239         report("Dollar at End");
1240     }
1241 
1242     // This test is for 4711773
1243     private static void multilineDollarTest() throws Exception {
1244         Pattern findCR = Pattern.compile("$", Pattern.MULTILINE);
1245         Matcher matcher = findCR.matcher("first bit\nsecond bit");
1246         matcher.find();
1247         if (matcher.start(0) != 9)
1248             failCount++;
1249         matcher.find();
1250         if (matcher.start(0) != 20)
1251             failCount++;
1252 
1253         // Supplementary character test
1254         matcher = findCR.matcher(toSupplementaries("first  bit\n second  bit")); // double BMP chars
1255         matcher.find();
1256         if (matcher.start(0) != 9*2)
1257             failCount++;
1258         matcher.find();
1259         if (matcher.start(0) != 20*2)
1260             failCount++;
1261 
1262         report("Multiline Dollar");
1263     }
1264 
1265     private static void reluctantRepetitionTest() throws Exception {
1266         Pattern p = Pattern.compile("1(\\s\\S+?){1,3}?[\\s,]2");
1267         check(p, "1 word word word 2", true);
1268         check(p, "1 wor wo w 2", true);
1269         check(p, "1 word word 2", true);
1270         check(p, "1 word 2", true);
1271         check(p, "1 wo w w 2", true);
1272         check(p, "1 wo w 2", true);
1273         check(p, "1 wor w 2", true);
1274 
1275         p = Pattern.compile("([a-z])+?c");
1276         Matcher m = p.matcher("ababcdefdec");
1277         check(m, "ababc");
1278 
1279         // Supplementary character test
1280         p = Pattern.compile(toSupplementaries("([a-z])+?c"));
1281         m = p.matcher(toSupplementaries("ababcdefdec"));
1282         check(m, toSupplementaries("ababc"));
1283 
1284         report("Reluctant Repetition");
1285     }
1286 
1287     private static void serializeTest() throws Exception {
1288         String patternStr = "(b)";
1289         String matchStr = "b";
1290         Pattern pattern = Pattern.compile(patternStr);
1291         ByteArrayOutputStream baos = new ByteArrayOutputStream();
1292         ObjectOutputStream oos = new ObjectOutputStream(baos);
1293         oos.writeObject(pattern);
1294         oos.close();
1295         ObjectInputStream ois = new ObjectInputStream(
1296             new ByteArrayInputStream(baos.toByteArray()));
1297         Pattern serializedPattern = (Pattern)ois.readObject();
1298         ois.close();
1299         Matcher matcher = serializedPattern.matcher(matchStr);
1300         if (!matcher.matches())
1301             failCount++;
1302         if (matcher.groupCount() != 1)
1303             failCount++;
1304 
1305         report("Serialization");
1306     }
1307 
1308     private static void gTest() {
1309         Pattern pattern = Pattern.compile("\\G\\w");
1310         Matcher matcher = pattern.matcher("abc#x#x");
1311         matcher.find();
1312         matcher.find();
1313         matcher.find();
1314         if (matcher.find())
1315             failCount++;
1316 
1317         pattern = Pattern.compile("\\GA*");
1318         matcher = pattern.matcher("1A2AA3");
1319         matcher.find();
1320         if (matcher.find())
1321             failCount++;
1322 
1323         pattern = Pattern.compile("\\GA*");
1324         matcher = pattern.matcher("1A2AA3");
1325         if (!matcher.find(1))
1326             failCount++;
1327         matcher.find();
1328         if (matcher.find())
1329             failCount++;
1330 
1331         report("\\G");
1332     }
1333 
1334     private static void zTest() {
1335         Pattern pattern = Pattern.compile("foo\\Z");
1336         // Positives
1337         check(pattern, "foo\u0085", true);
1338         check(pattern, "foo\u2028", true);
1339         check(pattern, "foo\u2029", true);
1340         check(pattern, "foo\n", true);
1341         check(pattern, "foo\r", true);
1342         check(pattern, "foo\r\n", true);
1343         // Negatives
1344         check(pattern, "fooo", false);
1345         check(pattern, "foo\n\r", false);
1346 
1347         pattern = Pattern.compile("foo\\Z", Pattern.UNIX_LINES);
1348         // Positives
1349         check(pattern, "foo", true);
1350         check(pattern, "foo\n", true);
1351         // Negatives
1352         check(pattern, "foo\r", false);
1353         check(pattern, "foo\u0085", false);
1354         check(pattern, "foo\u2028", false);
1355         check(pattern, "foo\u2029", false);
1356 
1357         report("\\Z");
1358     }
1359 
1360     private static void replaceFirstTest() {
1361         Pattern pattern = Pattern.compile("(ab)(c*)");
1362         Matcher matcher = pattern.matcher("abccczzzabcczzzabccc");
1363         if (!matcher.replaceFirst("test").equals("testzzzabcczzzabccc"))
1364             failCount++;
1365 
1366         matcher.reset("zzzabccczzzabcczzzabccczzz");
1367         if (!matcher.replaceFirst("test").equals("zzztestzzzabcczzzabccczzz"))
1368             failCount++;
1369 
1370         matcher.reset("zzzabccczzzabcczzzabccczzz");
1371         String result = matcher.replaceFirst("$1");
1372         if (!result.equals("zzzabzzzabcczzzabccczzz"))
1373             failCount++;
1374 
1375         matcher.reset("zzzabccczzzabcczzzabccczzz");
1376         result = matcher.replaceFirst("$2");
1377         if (!result.equals("zzzccczzzabcczzzabccczzz"))
1378             failCount++;
1379 
1380         pattern = Pattern.compile("a*");
1381         matcher = pattern.matcher("aaaaaaaaaa");
1382         if (!matcher.replaceFirst("test").equals("test"))
1383             failCount++;
1384 
1385         pattern = Pattern.compile("a+");
1386         matcher = pattern.matcher("zzzaaaaaaaaaa");
1387         if (!matcher.replaceFirst("test").equals("zzztest"))
1388             failCount++;
1389 
1390         // Supplementary character test
1391         pattern = Pattern.compile(toSupplementaries("(ab)(c*)"));
1392         matcher = pattern.matcher(toSupplementaries("abccczzzabcczzzabccc"));
1393         if (!matcher.replaceFirst(toSupplementaries("test"))
1394                 .equals(toSupplementaries("testzzzabcczzzabccc")))
1395             failCount++;
1396 
1397         matcher.reset(toSupplementaries("zzzabccczzzabcczzzabccczzz"));
1398         if (!matcher.replaceFirst(toSupplementaries("test")).
1399             equals(toSupplementaries("zzztestzzzabcczzzabccczzz")))
1400             failCount++;
1401 
1402         matcher.reset(toSupplementaries("zzzabccczzzabcczzzabccczzz"));
1403         result = matcher.replaceFirst("$1");
1404         if (!result.equals(toSupplementaries("zzzabzzzabcczzzabccczzz")))
1405             failCount++;
1406 
1407         matcher.reset(toSupplementaries("zzzabccczzzabcczzzabccczzz"));
1408         result = matcher.replaceFirst("$2");
1409         if (!result.equals(toSupplementaries("zzzccczzzabcczzzabccczzz")))
1410             failCount++;
1411 
1412         pattern = Pattern.compile(toSupplementaries("a*"));
1413         matcher = pattern.matcher(toSupplementaries("aaaaaaaaaa"));
1414         if (!matcher.replaceFirst(toSupplementaries("test")).equals(toSupplementaries("test")))
1415             failCount++;
1416 
1417         pattern = Pattern.compile(toSupplementaries("a+"));
1418         matcher = pattern.matcher(toSupplementaries("zzzaaaaaaaaaa"));
1419         if (!matcher.replaceFirst(toSupplementaries("test")).equals(toSupplementaries("zzztest")))
1420             failCount++;
1421 
1422         report("Replace First");
1423     }
1424 
1425     private static void unixLinesTest() {
1426         Pattern pattern = Pattern.compile(".*");
1427         Matcher matcher = pattern.matcher("aa\u2028blah");
1428         matcher.find();
1429         if (!matcher.group(0).equals("aa"))
1430             failCount++;
1431 
1432         pattern = Pattern.compile(".*", Pattern.UNIX_LINES);
1433         matcher = pattern.matcher("aa\u2028blah");
1434         matcher.find();
1435         if (!matcher.group(0).equals("aa\u2028blah"))
1436             failCount++;
1437 
1438         pattern = Pattern.compile("[az]$",
1439                                   Pattern.MULTILINE | Pattern.UNIX_LINES);
1440         matcher = pattern.matcher("aa\u2028zz");
1441         check(matcher, "a\u2028", false);
1442 
1443         // Supplementary character test
1444         pattern = Pattern.compile(".*");
1445         matcher = pattern.matcher(toSupplementaries("aa\u2028blah"));
1446         matcher.find();
1447         if (!matcher.group(0).equals(toSupplementaries("aa")))
1448             failCount++;
1449 
1450         pattern = Pattern.compile(".*", Pattern.UNIX_LINES);
1451         matcher = pattern.matcher(toSupplementaries("aa\u2028blah"));
1452         matcher.find();
1453         if (!matcher.group(0).equals(toSupplementaries("aa\u2028blah")))
1454             failCount++;
1455 
1456         pattern = Pattern.compile(toSupplementaries("[az]$"),
1457                                   Pattern.MULTILINE | Pattern.UNIX_LINES);
1458         matcher = pattern.matcher(toSupplementaries("aa\u2028zz"));
1459         check(matcher, toSupplementaries("a\u2028"), false);
1460 
1461         report("Unix Lines");
1462     }
1463 
1464     private static void commentsTest() {
1465         int flags = Pattern.COMMENTS;
1466 
1467         Pattern pattern = Pattern.compile("aa \\# aa", flags);
1468         Matcher matcher = pattern.matcher("aa#aa");
1469         if (!matcher.matches())
1470             failCount++;
1471 
1472         pattern = Pattern.compile("aa  # blah", flags);
1473         matcher = pattern.matcher("aa");
1474         if (!matcher.matches())
1475             failCount++;
1476 
1477         pattern = Pattern.compile("aa blah", flags);
1478         matcher = pattern.matcher("aablah");
1479         if (!matcher.matches())
1480              failCount++;
1481 
1482         pattern = Pattern.compile("aa  # blah blech  ", flags);
1483         matcher = pattern.matcher("aa");
1484         if (!matcher.matches())
1485             failCount++;
1486 
1487         pattern = Pattern.compile("aa  # blah\n  ", flags);
1488         matcher = pattern.matcher("aa");
1489         if (!matcher.matches())
1490             failCount++;
1491 
1492         pattern = Pattern.compile("aa  # blah\nbc # blech", flags);
1493         matcher = pattern.matcher("aabc");
1494         if (!matcher.matches())
1495              failCount++;
1496 
1497         pattern = Pattern.compile("aa  # blah\nbc# blech", flags);
1498         matcher = pattern.matcher("aabc");
1499         if (!matcher.matches())
1500              failCount++;
1501 
1502         pattern = Pattern.compile("aa  # blah\nbc\\# blech", flags);
1503         matcher = pattern.matcher("aabc#blech");
1504         if (!matcher.matches())
1505              failCount++;
1506 
1507         // Supplementary character test
1508         pattern = Pattern.compile(toSupplementaries("aa \\# aa"), flags);
1509         matcher = pattern.matcher(toSupplementaries("aa#aa"));
1510         if (!matcher.matches())
1511             failCount++;
1512 
1513         pattern = Pattern.compile(toSupplementaries("aa  # blah"), flags);
1514         matcher = pattern.matcher(toSupplementaries("aa"));
1515         if (!matcher.matches())
1516             failCount++;
1517 
1518         pattern = Pattern.compile(toSupplementaries("aa blah"), flags);
1519         matcher = pattern.matcher(toSupplementaries("aablah"));
1520         if (!matcher.matches())
1521              failCount++;
1522 
1523         pattern = Pattern.compile(toSupplementaries("aa  # blah blech  "), flags);
1524         matcher = pattern.matcher(toSupplementaries("aa"));
1525         if (!matcher.matches())
1526             failCount++;
1527 
1528         pattern = Pattern.compile(toSupplementaries("aa  # blah\n  "), flags);
1529         matcher = pattern.matcher(toSupplementaries("aa"));
1530         if (!matcher.matches())
1531             failCount++;
1532 
1533         pattern = Pattern.compile(toSupplementaries("aa  # blah\nbc # blech"), flags);
1534         matcher = pattern.matcher(toSupplementaries("aabc"));
1535         if (!matcher.matches())
1536              failCount++;
1537 
1538         pattern = Pattern.compile(toSupplementaries("aa  # blah\nbc# blech"), flags);
1539         matcher = pattern.matcher(toSupplementaries("aabc"));
1540         if (!matcher.matches())
1541              failCount++;
1542 
1543         pattern = Pattern.compile(toSupplementaries("aa  # blah\nbc\\# blech"), flags);
1544         matcher = pattern.matcher(toSupplementaries("aabc#blech"));
1545         if (!matcher.matches())
1546              failCount++;
1547 
1548         report("Comments");
1549     }
1550 
1551     private static void caseFoldingTest() { // bug 4504687
1552         int flags = Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE;
1553         Pattern pattern = Pattern.compile("aa", flags);
1554         Matcher matcher = pattern.matcher("ab");
1555         if (matcher.matches())
1556             failCount++;
1557 
1558         pattern = Pattern.compile("aA", flags);
1559         matcher = pattern.matcher("ab");
1560         if (matcher.matches())
1561             failCount++;
1562 
1563         pattern = Pattern.compile("aa", flags);
1564         matcher = pattern.matcher("aB");
1565         if (matcher.matches())
1566             failCount++;
1567         matcher = pattern.matcher("Ab");
1568         if (matcher.matches())
1569             failCount++;
1570 
1571         // ASCII               "a"
1572         // Latin-1 Supplement  "a" + grave
1573         // Cyrillic            "a"
1574         String[] patterns = new String[] {
1575             //single
1576             "a", "\u00e0", "\u0430",
1577             //slice
1578             "ab", "\u00e0\u00e1", "\u0430\u0431",
1579             //class single
1580             "[a]", "[\u00e0]", "[\u0430]",
1581             //class range
1582             "[a-b]", "[\u00e0-\u00e5]", "[\u0430-\u0431]",
1583             //back reference
1584             "(a)\\1", "(\u00e0)\\1", "(\u0430)\\1"
1585         };
1586 
1587         String[] texts = new String[] {
1588             "A", "\u00c0", "\u0410",
1589             "AB", "\u00c0\u00c1", "\u0410\u0411",
1590             "A", "\u00c0", "\u0410",
1591             "B", "\u00c2", "\u0411",
1592             "aA", "\u00e0\u00c0", "\u0430\u0410"
1593         };
1594 
1595         boolean[] expected = new boolean[] {
1596             true, false, false,
1597             true, false, false,
1598             true, false, false,
1599             true, false, false,
1600             true, false, false
1601         };
1602 
1603         flags = Pattern.CASE_INSENSITIVE;
1604         for (int i = 0; i < patterns.length; i++) {
1605             pattern = Pattern.compile(patterns[i], flags);
1606             matcher = pattern.matcher(texts[i]);
1607             if (matcher.matches() != expected[i]) {
1608                 System.out.println("<1> Failed at " + i);
1609                 failCount++;
1610             }
1611         }
1612 
1613         flags = Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE;
1614         for (int i = 0; i < patterns.length; i++) {
1615             pattern = Pattern.compile(patterns[i], flags);
1616             matcher = pattern.matcher(texts[i]);
1617             if (!matcher.matches()) {
1618                 System.out.println("<2> Failed at " + i);
1619                 failCount++;
1620             }
1621         }
1622         // flag unicode_case alone should do nothing
1623         flags = Pattern.UNICODE_CASE;
1624         for (int i = 0; i < patterns.length; i++) {
1625             pattern = Pattern.compile(patterns[i], flags);
1626             matcher = pattern.matcher(texts[i]);
1627             if (matcher.matches()) {
1628                 System.out.println("<3> Failed at " + i);
1629                 failCount++;
1630             }
1631         }
1632 
1633         // Special cases: i, I, u+0131 and u+0130
1634         flags = Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE;
1635         pattern = Pattern.compile("[h-j]+", flags);
1636         if (!pattern.matcher("\u0131\u0130").matches())
1637             failCount++;
1638         report("Case Folding");
1639     }
1640 
1641     private static void appendTest() {
1642         Pattern pattern = Pattern.compile("(ab)(cd)");
1643         Matcher matcher = pattern.matcher("abcd");
1644         String result = matcher.replaceAll("$2$1");
1645         if (!result.equals("cdab"))
1646             failCount++;
1647 
1648         String  s1 = "Swap all: first = 123, second = 456";
1649         String  s2 = "Swap one: first = 123, second = 456";
1650         String  r  = "$3$2$1";
1651         pattern = Pattern.compile("([a-z]+)( *= *)([0-9]+)");
1652         matcher = pattern.matcher(s1);
1653 
1654         result = matcher.replaceAll(r);
1655         if (!result.equals("Swap all: 123 = first, 456 = second"))
1656             failCount++;
1657 
1658         matcher = pattern.matcher(s2);
1659 
1660         if (matcher.find()) {
1661             StringBuffer sb = new StringBuffer();
1662             matcher.appendReplacement(sb, r);
1663             matcher.appendTail(sb);
1664             result = sb.toString();
1665             if (!result.equals("Swap one: 123 = first, second = 456"))
1666                 failCount++;
1667         }
1668 
1669         // Supplementary character test
1670         pattern = Pattern.compile(toSupplementaries("(ab)(cd)"));
1671         matcher = pattern.matcher(toSupplementaries("abcd"));
1672         result = matcher.replaceAll("$2$1");
1673         if (!result.equals(toSupplementaries("cdab")))
1674             failCount++;
1675 
1676         s1 = toSupplementaries("Swap all: first = 123, second = 456");
1677         s2 = toSupplementaries("Swap one: first = 123, second = 456");
1678         r  = toSupplementaries("$3$2$1");
1679         pattern = Pattern.compile(toSupplementaries("([a-z]+)( *= *)([0-9]+)"));
1680         matcher = pattern.matcher(s1);
1681 
1682         result = matcher.replaceAll(r);
1683         if (!result.equals(toSupplementaries("Swap all: 123 = first, 456 = second")))
1684             failCount++;
1685 
1686         matcher = pattern.matcher(s2);
1687 
1688         if (matcher.find()) {
1689             StringBuffer sb = new StringBuffer();
1690             matcher.appendReplacement(sb, r);
1691             matcher.appendTail(sb);
1692             result = sb.toString();
1693             if (!result.equals(toSupplementaries("Swap one: 123 = first, second = 456")))
1694                 failCount++;
1695         }
1696         report("Append");
1697     }
1698 
1699     private static void splitTest() {
1700         Pattern pattern = Pattern.compile(":");
1701         String[] result = pattern.split("foo:and:boo", 2);
1702         if (!result[0].equals("foo"))
1703             failCount++;
1704         if (!result[1].equals("and:boo"))
1705             failCount++;
1706         // Supplementary character test
1707         Pattern patternX = Pattern.compile(toSupplementaries("X"));
1708         result = patternX.split(toSupplementaries("fooXandXboo"), 2);
1709         if (!result[0].equals(toSupplementaries("foo")))
1710             failCount++;
1711         if (!result[1].equals(toSupplementaries("andXboo")))
1712             failCount++;
1713 
1714         CharBuffer cb = CharBuffer.allocate(100);
1715         cb.put("foo:and:boo");
1716         cb.flip();
1717         result = pattern.split(cb);
1718         if (!result[0].equals("foo"))
1719             failCount++;
1720         if (!result[1].equals("and"))
1721             failCount++;
1722         if (!result[2].equals("boo"))
1723             failCount++;
1724 
1725         // Supplementary character test
1726         CharBuffer cbs = CharBuffer.allocate(100);
1727         cbs.put(toSupplementaries("fooXandXboo"));
1728         cbs.flip();
1729         result = patternX.split(cbs);
1730         if (!result[0].equals(toSupplementaries("foo")))
1731             failCount++;
1732         if (!result[1].equals(toSupplementaries("and")))
1733             failCount++;
1734         if (!result[2].equals(toSupplementaries("boo")))
1735             failCount++;
1736 
1737         String source = "0123456789";
1738         for (int limit=-2; limit<3; limit++) {
1739             for (int x=0; x<10; x++) {
1740                 result = source.split(Integer.toString(x), limit);
1741                 int expectedLength = limit < 1 ? 2 : limit;
1742 
1743                 if ((limit == 0) && (x == 9)) {
1744                     // expected dropping of ""
1745                     if (result.length != 1)
1746                         failCount++;
1747                     if (!result[0].equals("012345678")) {
1748                         failCount++;
1749                     }
1750                 } else {
1751                     if (result.length != expectedLength) {
1752                         failCount++;
1753                     }
1754                     if (!result[0].equals(source.substring(0,x))) {
1755                         if (limit != 1) {
1756                             failCount++;
1757                         } else {
1758                             if (!result[0].equals(source.substring(0,10))) {
1759                                 failCount++;
1760                             }
1761                         }
1762                     }
1763                     if (expectedLength > 1) { // Check segment 2
1764                         if (!result[1].equals(source.substring(x+1,10)))
1765                             failCount++;
1766                     }
1767                 }
1768             }
1769         }
1770         // Check the case for no match found
1771         for (int limit=-2; limit<3; limit++) {
1772             result = source.split("e", limit);
1773             if (result.length != 1)
1774                 failCount++;
1775             if (!result[0].equals(source))
1776                 failCount++;
1777         }
1778         // Check the case for limit == 0, source = "";
1779         // split() now returns 0-length for empty source "" see #6559590
1780         source = "";
1781         result = source.split("e", 0);
1782         if (result.length != 1)
1783             failCount++;
1784         if (!result[0].equals(source))
1785             failCount++;
1786 
1787         // Check both split() and splitAsStraem(), especially for zero-lenth
1788         // input and zero-lenth match cases
1789         String[][] input = new String[][] {
1790             { " ",           "Abc Efg Hij" },   // normal non-zero-match
1791             { " ",           " Abc Efg Hij" },  // leading empty str for non-zero-match
1792             { " ",           "Abc  Efg Hij" },  // non-zero-match in the middle
1793             { "(?=\\p{Lu})", "AbcEfgHij" },     // no leading empty str for zero-match
1794             { "(?=\\p{Lu})", "AbcEfg" },
1795             { "(?=\\p{Lu})", "Abc" },
1796             { " ",           "" },              // zero-length input
1797             { ".*",          "" },
1798 
1799             // some tests from PatternStreamTest.java
1800             { "4",       "awgqwefg1fefw4vssv1vvv1" },
1801             { "\u00a3a", "afbfq\u00a3abgwgb\u00a3awngnwggw\u00a3a\u00a3ahjrnhneerh" },
1802             { "1",       "awgqwefg1fefw4vssv1vvv1" },
1803             { "1",       "a\u4ebafg1fefw\u4eba4\u9f9cvssv\u9f9c1v\u672c\u672cvv" },
1804             { "\u56da",  "1\u56da23\u56da456\u56da7890" },
1805             { "\u56da",  "1\u56da23\u9f9c\u672c\u672c\u56da456\u56da\u9f9c\u672c7890" },
1806             { "\u56da",  "" },
1807             { "[ \t,:.]","This is,testing: with\tdifferent separators." }, //multiple septs
1808             { "o",       "boo:and:foo" },
1809             { "o",       "booooo:and:fooooo" },
1810             { "o",       "fooooo:" },
1811         };
1812 
1813         String[][] expected = new String[][] {
1814             { "Abc", "Efg", "Hij" },
1815             { "", "Abc", "Efg", "Hij" },
1816             { "Abc", "", "Efg", "Hij" },
1817             { "Abc", "Efg", "Hij" },
1818             { "Abc", "Efg" },
1819             { "Abc" },
1820             { "" },
1821             { "" },
1822 
1823             { "awgqwefg1fefw", "vssv1vvv1" },
1824             { "afbfq", "bgwgb", "wngnwggw", "", "hjrnhneerh" },
1825             { "awgqwefg", "fefw4vssv", "vvv" },
1826             { "a\u4ebafg", "fefw\u4eba4\u9f9cvssv\u9f9c", "v\u672c\u672cvv" },
1827             { "1", "23", "456", "7890" },
1828             { "1", "23\u9f9c\u672c\u672c", "456", "\u9f9c\u672c7890" },
1829             { "" },
1830             { "This", "is", "testing", "", "with", "different", "separators" },
1831             { "b", "", ":and:f" },
1832             { "b", "", "", "", "", ":and:f" },
1833             { "f", "", "", "", "", ":" },
1834         };
1835         for (int i = 0; i < input.length; i++) {
1836             pattern = Pattern.compile(input[i][0]);
1837             if (!Arrays.equals(pattern.split(input[i][1]), expected[i])) {
1838                 failCount++;
1839             }
1840             if (input[i][1].length() > 0 &&  // splitAsStream() return empty resulting
1841                                              // array for zero-length input for now
1842                 !Arrays.equals(pattern.splitAsStream(input[i][1]).toArray(),
1843                                expected[i])) {
1844                 failCount++;
1845             }
1846         }
1847         report("Split");
1848     }
1849 
1850     private static void negationTest() {
1851         Pattern pattern = Pattern.compile("[\\[@^]+");
1852         Matcher matcher = pattern.matcher("@@@@[[[[^^^^");
1853         if (!matcher.find())
1854             failCount++;
1855         if (!matcher.group(0).equals("@@@@[[[[^^^^"))
1856             failCount++;
1857         pattern = Pattern.compile("[@\\[^]+");
1858         matcher = pattern.matcher("@@@@[[[[^^^^");
1859         if (!matcher.find())
1860             failCount++;
1861         if (!matcher.group(0).equals("@@@@[[[[^^^^"))
1862             failCount++;
1863         pattern = Pattern.compile("[@\\[^@]+");
1864         matcher = pattern.matcher("@@@@[[[[^^^^");
1865         if (!matcher.find())
1866             failCount++;
1867         if (!matcher.group(0).equals("@@@@[[[[^^^^"))
1868             failCount++;
1869 
1870         pattern = Pattern.compile("\\)");
1871         matcher = pattern.matcher("xxx)xxx");
1872         if (!matcher.find())
1873             failCount++;
1874 
1875         report("Negation");
1876     }
1877 
1878     private static void ampersandTest() {
1879         Pattern pattern = Pattern.compile("[&@]+");
1880         check(pattern, "@@@@&&&&", true);
1881 
1882         pattern = Pattern.compile("[@&]+");
1883         check(pattern, "@@@@&&&&", true);
1884 
1885         pattern = Pattern.compile("[@\\&]+");
1886         check(pattern, "@@@@&&&&", true);
1887 
1888         report("Ampersand");
1889     }
1890 
1891     private static void octalTest() throws Exception {
1892         Pattern pattern = Pattern.compile("\\u0007");
1893         Matcher matcher = pattern.matcher("\u0007");
1894         if (!matcher.matches())
1895             failCount++;
1896         pattern = Pattern.compile("\\07");
1897         matcher = pattern.matcher("\u0007");
1898         if (!matcher.matches())
1899             failCount++;
1900         pattern = Pattern.compile("\\007");
1901         matcher = pattern.matcher("\u0007");
1902         if (!matcher.matches())
1903             failCount++;
1904         pattern = Pattern.compile("\\0007");
1905         matcher = pattern.matcher("\u0007");
1906         if (!matcher.matches())
1907             failCount++;
1908         pattern = Pattern.compile("\\040");
1909         matcher = pattern.matcher("\u0020");
1910         if (!matcher.matches())
1911             failCount++;
1912         pattern = Pattern.compile("\\0403");
1913         matcher = pattern.matcher("\u00203");
1914         if (!matcher.matches())
1915             failCount++;
1916         pattern = Pattern.compile("\\0103");
1917         matcher = pattern.matcher("\u0043");
1918         if (!matcher.matches())
1919             failCount++;
1920 
1921         report("Octal");
1922     }
1923 
1924     private static void longPatternTest() throws Exception {
1925         try {
1926             Pattern pattern = Pattern.compile(
1927                 "a 32-character-long pattern xxxx");
1928             pattern = Pattern.compile("a 33-character-long pattern xxxxx");
1929             pattern = Pattern.compile("a thirty four character long regex");
1930             StringBuffer patternToBe = new StringBuffer(101);
1931             for (int i=0; i<100; i++)
1932                 patternToBe.append((char)(97 + i%26));
1933             pattern = Pattern.compile(patternToBe.toString());
1934         } catch (PatternSyntaxException e) {
1935             failCount++;
1936         }
1937 
1938         // Supplementary character test
1939         try {
1940             Pattern pattern = Pattern.compile(
1941                 toSupplementaries("a 32-character-long pattern xxxx"));
1942             pattern = Pattern.compile(toSupplementaries("a 33-character-long pattern xxxxx"));
1943             pattern = Pattern.compile(toSupplementaries("a thirty four character long regex"));
1944             StringBuffer patternToBe = new StringBuffer(101*2);
1945             for (int i=0; i<100; i++)
1946                 patternToBe.append(Character.toChars(Character.MIN_SUPPLEMENTARY_CODE_POINT
1947                                                      + 97 + i%26));
1948             pattern = Pattern.compile(patternToBe.toString());
1949         } catch (PatternSyntaxException e) {
1950             failCount++;
1951         }
1952         report("LongPattern");
1953     }
1954 
1955     private static void group0Test() throws Exception {
1956         Pattern pattern = Pattern.compile("(tes)ting");
1957         Matcher matcher = pattern.matcher("testing");
1958         check(matcher, "testing");
1959 
1960         matcher.reset("testing");
1961         if (matcher.lookingAt()) {
1962             if (!matcher.group(0).equals("testing"))
1963                 failCount++;
1964         } else {
1965             failCount++;
1966         }
1967 
1968         matcher.reset("testing");
1969         if (matcher.matches()) {
1970             if (!matcher.group(0).equals("testing"))
1971                 failCount++;
1972         } else {
1973             failCount++;
1974         }
1975 
1976         pattern = Pattern.compile("(tes)ting");
1977         matcher = pattern.matcher("testing");
1978         if (matcher.lookingAt()) {
1979             if (!matcher.group(0).equals("testing"))
1980                 failCount++;
1981         } else {
1982             failCount++;
1983         }
1984 
1985         pattern = Pattern.compile("^(tes)ting");
1986         matcher = pattern.matcher("testing");
1987         if (matcher.matches()) {
1988             if (!matcher.group(0).equals("testing"))
1989                 failCount++;
1990         } else {
1991             failCount++;
1992         }
1993 
1994         // Supplementary character test
1995         pattern = Pattern.compile(toSupplementaries("(tes)ting"));
1996         matcher = pattern.matcher(toSupplementaries("testing"));
1997         check(matcher, toSupplementaries("testing"));
1998 
1999         matcher.reset(toSupplementaries("testing"));
2000         if (matcher.lookingAt()) {
2001             if (!matcher.group(0).equals(toSupplementaries("testing")))
2002                 failCount++;
2003         } else {
2004             failCount++;
2005         }
2006 
2007         matcher.reset(toSupplementaries("testing"));
2008         if (matcher.matches()) {
2009             if (!matcher.group(0).equals(toSupplementaries("testing")))
2010                 failCount++;
2011         } else {
2012             failCount++;
2013         }
2014 
2015         pattern = Pattern.compile(toSupplementaries("(tes)ting"));
2016         matcher = pattern.matcher(toSupplementaries("testing"));
2017         if (matcher.lookingAt()) {
2018             if (!matcher.group(0).equals(toSupplementaries("testing")))
2019                 failCount++;
2020         } else {
2021             failCount++;
2022         }
2023 
2024         pattern = Pattern.compile(toSupplementaries("^(tes)ting"));
2025         matcher = pattern.matcher(toSupplementaries("testing"));
2026         if (matcher.matches()) {
2027             if (!matcher.group(0).equals(toSupplementaries("testing")))
2028                 failCount++;
2029         } else {
2030             failCount++;
2031         }
2032 
2033         report("Group0");
2034     }
2035 
2036     private static void findIntTest() throws Exception {
2037         Pattern p = Pattern.compile("blah");
2038         Matcher m = p.matcher("zzzzblahzzzzzblah");
2039         boolean result = m.find(2);
2040         if (!result)
2041             failCount++;
2042 
2043         p = Pattern.compile("$");
2044         m = p.matcher("1234567890");
2045         result = m.find(10);
2046         if (!result)
2047             failCount++;
2048         try {
2049             result = m.find(11);
2050             failCount++;
2051         } catch (IndexOutOfBoundsException e) {
2052             // correct result
2053         }
2054 
2055         // Supplementary character test
2056         p = Pattern.compile(toSupplementaries("blah"));
2057         m = p.matcher(toSupplementaries("zzzzblahzzzzzblah"));
2058         result = m.find(2);
2059         if (!result)
2060             failCount++;
2061 
2062         report("FindInt");
2063     }
2064 
2065     private static void emptyPatternTest() throws Exception {
2066         Pattern p = Pattern.compile("");
2067         Matcher m = p.matcher("foo");
2068 
2069         // Should find empty pattern at beginning of input
2070         boolean result = m.find();
2071         if (result != true)
2072             failCount++;
2073         if (m.start() != 0)
2074             failCount++;
2075 
2076         // Should not match entire input if input is not empty
2077         m.reset();
2078         result = m.matches();
2079         if (result == true)
2080             failCount++;
2081 
2082         try {
2083             m.start(0);
2084             failCount++;
2085         } catch (IllegalStateException e) {
2086             // Correct result
2087         }
2088 
2089         // Should match entire input if input is empty
2090         m.reset("");
2091         result = m.matches();
2092         if (result != true)
2093             failCount++;
2094 
2095         result = Pattern.matches("", "");
2096         if (result != true)
2097             failCount++;
2098 
2099         result = Pattern.matches("", "foo");
2100         if (result == true)
2101             failCount++;
2102         report("EmptyPattern");
2103     }
2104 
2105     private static void charClassTest() throws Exception {
2106         Pattern pattern = Pattern.compile("blah[ab]]blech");
2107         check(pattern, "blahb]blech", true);
2108 
2109         pattern = Pattern.compile("[abc[def]]");
2110         check(pattern, "b", true);
2111 
2112         // Supplementary character tests
2113         pattern = Pattern.compile(toSupplementaries("blah[ab]]blech"));
2114         check(pattern, toSupplementaries("blahb]blech"), true);
2115 
2116         pattern = Pattern.compile(toSupplementaries("[abc[def]]"));
2117         check(pattern, toSupplementaries("b"), true);
2118 
2119         try {
2120             // u00ff when UNICODE_CASE
2121             pattern = Pattern.compile("[ab\u00ffcd]",
2122                                       Pattern.CASE_INSENSITIVE|
2123                                       Pattern.UNICODE_CASE);
2124             check(pattern, "ab\u00ffcd", true);
2125             check(pattern, "Ab\u0178Cd", true);
2126 
2127             // u00b5 when UNICODE_CASE
2128             pattern = Pattern.compile("[ab\u00b5cd]",
2129                                       Pattern.CASE_INSENSITIVE|
2130                                       Pattern.UNICODE_CASE);
2131             check(pattern, "ab\u00b5cd", true);
2132             check(pattern, "Ab\u039cCd", true);
2133         } catch (Exception e) { failCount++; }
2134 
2135         /* Special cases
2136            (1)LatinSmallLetterLongS u+017f
2137            (2)LatinSmallLetterDotlessI u+0131
2138            (3)LatineCapitalLetterIWithDotAbove u+0130
2139            (4)KelvinSign u+212a
2140            (5)AngstromSign u+212b
2141         */
2142         int flags = Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE;
2143         pattern = Pattern.compile("[sik\u00c5]+", flags);
2144         if (!pattern.matcher("\u017f\u0130\u0131\u212a\u212b").matches())
2145             failCount++;
2146 
2147         try {
2148             Pattern.compile("[", Pattern.CANON_EQ);
2149             failCount++;
2150         } catch (PatternSyntaxException expected) {
2151         } catch (Exception unexpected) {
2152             failCount++;
2153         }
2154 
2155         report("CharClass");
2156     }
2157 
2158     private static void caretTest() throws Exception {
2159         Pattern pattern = Pattern.compile("\\w*");
2160         Matcher matcher = pattern.matcher("a#bc#def##g");
2161         check(matcher, "a");
2162         check(matcher, "");
2163         check(matcher, "bc");
2164         check(matcher, "");
2165         check(matcher, "def");
2166         check(matcher, "");
2167         check(matcher, "");
2168         check(matcher, "g");
2169         check(matcher, "");
2170         if (matcher.find())
2171             failCount++;
2172 
2173         pattern = Pattern.compile("^\\w*");
2174         matcher = pattern.matcher("a#bc#def##g");
2175         check(matcher, "a");
2176         if (matcher.find())
2177             failCount++;
2178 
2179         pattern = Pattern.compile("\\w");
2180         matcher = pattern.matcher("abc##x");
2181         check(matcher, "a");
2182         check(matcher, "b");
2183         check(matcher, "c");
2184         check(matcher, "x");
2185         if (matcher.find())
2186             failCount++;
2187 
2188         pattern = Pattern.compile("^\\w");
2189         matcher = pattern.matcher("abc##x");
2190         check(matcher, "a");
2191         if (matcher.find())
2192             failCount++;
2193 
2194         pattern = Pattern.compile("\\A\\p{Alpha}{3}");
2195         matcher = pattern.matcher("abcdef-ghi\njklmno");
2196         check(matcher, "abc");
2197         if (matcher.find())
2198             failCount++;
2199 
2200         pattern = Pattern.compile("^\\p{Alpha}{3}", Pattern.MULTILINE);
2201         matcher = pattern.matcher("abcdef-ghi\njklmno");
2202         check(matcher, "abc");
2203         check(matcher, "jkl");
2204         if (matcher.find())
2205             failCount++;
2206 
2207         pattern = Pattern.compile("^", Pattern.MULTILINE);
2208         matcher = pattern.matcher("this is some text");
2209         String result = matcher.replaceAll("X");
2210         if (!result.equals("Xthis is some text"))
2211             failCount++;
2212 
2213         pattern = Pattern.compile("^");
2214         matcher = pattern.matcher("this is some text");
2215         result = matcher.replaceAll("X");
2216         if (!result.equals("Xthis is some text"))
2217             failCount++;
2218 
2219         pattern = Pattern.compile("^", Pattern.MULTILINE | Pattern.UNIX_LINES);
2220         matcher = pattern.matcher("this is some text\n");
2221         result = matcher.replaceAll("X");
2222         if (!result.equals("Xthis is some text\n"))
2223             failCount++;
2224 
2225         report("Caret");
2226     }
2227 
2228     private static void groupCaptureTest() throws Exception {
2229         // Independent group
2230         Pattern pattern = Pattern.compile("x+(?>y+)z+");
2231         Matcher matcher = pattern.matcher("xxxyyyzzz");
2232         matcher.find();
2233         try {
2234             String blah = matcher.group(1);
2235             failCount++;
2236         } catch (IndexOutOfBoundsException ioobe) {
2237             // Good result
2238         }
2239         // Pure group
2240         pattern = Pattern.compile("x+(?:y+)z+");
2241         matcher = pattern.matcher("xxxyyyzzz");
2242         matcher.find();
2243         try {
2244             String blah = matcher.group(1);
2245             failCount++;
2246         } catch (IndexOutOfBoundsException ioobe) {
2247             // Good result
2248         }
2249 
2250         // Supplementary character tests
2251         // Independent group
2252         pattern = Pattern.compile(toSupplementaries("x+(?>y+)z+"));
2253         matcher = pattern.matcher(toSupplementaries("xxxyyyzzz"));
2254         matcher.find();
2255         try {
2256             String blah = matcher.group(1);
2257             failCount++;
2258         } catch (IndexOutOfBoundsException ioobe) {
2259             // Good result
2260         }
2261         // Pure group
2262         pattern = Pattern.compile(toSupplementaries("x+(?:y+)z+"));
2263         matcher = pattern.matcher(toSupplementaries("xxxyyyzzz"));
2264         matcher.find();
2265         try {
2266             String blah = matcher.group(1);
2267             failCount++;
2268         } catch (IndexOutOfBoundsException ioobe) {
2269             // Good result
2270         }
2271 
2272         report("GroupCapture");
2273     }
2274 
2275     private static void backRefTest() throws Exception {
2276         Pattern pattern = Pattern.compile("(a*)bc\\1");
2277         check(pattern, "zzzaabcazzz", true);
2278 
2279         pattern = Pattern.compile("(a*)bc\\1");
2280         check(pattern, "zzzaabcaazzz", true);
2281 
2282         pattern = Pattern.compile("(abc)(def)\\1");
2283         check(pattern, "abcdefabc", true);
2284 
2285         pattern = Pattern.compile("(abc)(def)\\3");
2286         check(pattern, "abcdefabc", false);
2287 
2288         try {
2289             for (int i = 1; i < 10; i++) {
2290                 // Make sure backref 1-9 are always accepted
2291                 pattern = Pattern.compile("abcdef\\" + i);
2292                 // and fail to match if the target group does not exit
2293                 check(pattern, "abcdef", false);
2294             }
2295         } catch(PatternSyntaxException e) {
2296             failCount++;
2297         }
2298 
2299         pattern = Pattern.compile("(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)\\11");
2300         check(pattern, "abcdefghija", false);
2301         check(pattern, "abcdefghija1", true);
2302 
2303         pattern = Pattern.compile("(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\\11");
2304         check(pattern, "abcdefghijkk", true);
2305 
2306         pattern = Pattern.compile("(a)bcdefghij\\11");
2307         check(pattern, "abcdefghija1", true);
2308 
2309         // Supplementary character tests
2310         pattern = Pattern.compile(toSupplementaries("(a*)bc\\1"));
2311         check(pattern, toSupplementaries("zzzaabcazzz"), true);
2312 
2313         pattern = Pattern.compile(toSupplementaries("(a*)bc\\1"));
2314         check(pattern, toSupplementaries("zzzaabcaazzz"), true);
2315 
2316         pattern = Pattern.compile(toSupplementaries("(abc)(def)\\1"));
2317         check(pattern, toSupplementaries("abcdefabc"), true);
2318 
2319         pattern = Pattern.compile(toSupplementaries("(abc)(def)\\3"));
2320         check(pattern, toSupplementaries("abcdefabc"), false);
2321 
2322         pattern = Pattern.compile(toSupplementaries("(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)\\11"));
2323         check(pattern, toSupplementaries("abcdefghija"), false);
2324         check(pattern, toSupplementaries("abcdefghija1"), true);
2325 
2326         pattern = Pattern.compile(toSupplementaries("(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\\11"));
2327         check(pattern, toSupplementaries("abcdefghijkk"), true);
2328 
2329         report("BackRef");
2330     }
2331 
2332     /**
2333      * Unicode Technical Report #18, section 2.6 End of Line
2334      * There is no empty line to be matched in the sequence \u000D\u000A
2335      * but there is an empty line in the sequence \u000A\u000D.
2336      */
2337     private static void anchorTest() throws Exception {
2338         Pattern p = Pattern.compile("^.*$", Pattern.MULTILINE);
2339         Matcher m = p.matcher("blah1\r\nblah2");
2340         m.find();
2341         m.find();
2342         if (!m.group().equals("blah2"))
2343             failCount++;
2344 
2345         m.reset("blah1\n\rblah2");
2346         m.find();
2347         m.find();
2348         m.find();
2349         if (!m.group().equals("blah2"))
2350             failCount++;
2351 
2352         // Test behavior of $ with \r\n at end of input
2353         p = Pattern.compile(".+$");
2354         m = p.matcher("blah1\r\n");
2355         if (!m.find())
2356             failCount++;
2357        if (!m.group().equals("blah1"))
2358             failCount++;
2359         if (m.find())
2360             failCount++;
2361 
2362         // Test behavior of $ with \r\n at end of input in multiline
2363         p = Pattern.compile(".+$", Pattern.MULTILINE);
2364         m = p.matcher("blah1\r\n");
2365         if (!m.find())
2366             failCount++;
2367         if (m.find())
2368             failCount++;
2369 
2370         // Test for $ recognition of \u0085 for bug 4527731
2371         p = Pattern.compile(".+$", Pattern.MULTILINE);
2372         m = p.matcher("blah1\u0085");
2373         if (!m.find())
2374             failCount++;
2375 
2376         // Supplementary character test
2377         p = Pattern.compile("^.*$", Pattern.MULTILINE);
2378         m = p.matcher(toSupplementaries("blah1\r\nblah2"));
2379         m.find();
2380         m.find();
2381         if (!m.group().equals(toSupplementaries("blah2")))
2382             failCount++;
2383 
2384         m.reset(toSupplementaries("blah1\n\rblah2"));
2385         m.find();
2386         m.find();
2387         m.find();
2388         if (!m.group().equals(toSupplementaries("blah2")))
2389             failCount++;
2390 
2391         // Test behavior of $ with \r\n at end of input
2392         p = Pattern.compile(".+$");
2393         m = p.matcher(toSupplementaries("blah1\r\n"));
2394         if (!m.find())
2395             failCount++;
2396         if (!m.group().equals(toSupplementaries("blah1")))
2397             failCount++;
2398         if (m.find())
2399             failCount++;
2400 
2401         // Test behavior of $ with \r\n at end of input in multiline
2402         p = Pattern.compile(".+$", Pattern.MULTILINE);
2403         m = p.matcher(toSupplementaries("blah1\r\n"));
2404         if (!m.find())
2405             failCount++;
2406         if (m.find())
2407             failCount++;
2408 
2409         // Test for $ recognition of \u0085 for bug 4527731
2410         p = Pattern.compile(".+$", Pattern.MULTILINE);
2411         m = p.matcher(toSupplementaries("blah1\u0085"));
2412         if (!m.find())
2413             failCount++;
2414 
2415         report("Anchors");
2416     }
2417 
2418     /**
2419      * A basic sanity test of Matcher.lookingAt().
2420      */
2421     private static void lookingAtTest() throws Exception {
2422         Pattern p = Pattern.compile("(ab)(c*)");
2423         Matcher m = p.matcher("abccczzzabcczzzabccc");
2424 
2425         if (!m.lookingAt())
2426             failCount++;
2427 
2428         if (!m.group().equals(m.group(0)))
2429             failCount++;
2430 
2431         m = p.matcher("zzzabccczzzabcczzzabccczzz");
2432         if (m.lookingAt())
2433             failCount++;
2434 
2435         // Supplementary character test
2436         p = Pattern.compile(toSupplementaries("(ab)(c*)"));
2437         m = p.matcher(toSupplementaries("abccczzzabcczzzabccc"));
2438 
2439         if (!m.lookingAt())
2440             failCount++;
2441 
2442         if (!m.group().equals(m.group(0)))
2443             failCount++;
2444 
2445         m = p.matcher(toSupplementaries("zzzabccczzzabcczzzabccczzz"));
2446         if (m.lookingAt())
2447             failCount++;
2448 
2449         report("Looking At");
2450     }
2451 
2452     /**
2453      * A basic sanity test of Matcher.matches().
2454      */
2455     private static void matchesTest() throws Exception {
2456         // matches()
2457         Pattern p = Pattern.compile("ulb(c*)");
2458         Matcher m = p.matcher("ulbcccccc");
2459         if (!m.matches())
2460             failCount++;
2461 
2462         // find() but not matches()
2463         m.reset("zzzulbcccccc");
2464         if (m.matches())
2465             failCount++;
2466 
2467         // lookingAt() but not matches()
2468         m.reset("ulbccccccdef");
2469         if (m.matches())
2470             failCount++;
2471 
2472         // matches()
2473         p = Pattern.compile("a|ad");
2474         m = p.matcher("ad");
2475         if (!m.matches())
2476             failCount++;
2477 
2478         // Supplementary character test
2479         // matches()
2480         p = Pattern.compile(toSupplementaries("ulb(c*)"));
2481         m = p.matcher(toSupplementaries("ulbcccccc"));
2482         if (!m.matches())
2483             failCount++;
2484 
2485         // find() but not matches()
2486         m.reset(toSupplementaries("zzzulbcccccc"));
2487         if (m.matches())
2488             failCount++;
2489 
2490         // lookingAt() but not matches()
2491         m.reset(toSupplementaries("ulbccccccdef"));
2492         if (m.matches())
2493             failCount++;
2494 
2495         // matches()
2496         p = Pattern.compile(toSupplementaries("a|ad"));
2497         m = p.matcher(toSupplementaries("ad"));
2498         if (!m.matches())
2499             failCount++;
2500 
2501         report("Matches");
2502     }
2503 
2504     /**
2505      * A basic sanity test of Pattern.matches().
2506      */
2507     private static void patternMatchesTest() throws Exception {
2508         // matches()
2509         if (!Pattern.matches(toSupplementaries("ulb(c*)"),
2510                              toSupplementaries("ulbcccccc")))
2511             failCount++;
2512 
2513         // find() but not matches()
2514         if (Pattern.matches(toSupplementaries("ulb(c*)"),
2515                             toSupplementaries("zzzulbcccccc")))
2516             failCount++;
2517 
2518         // lookingAt() but not matches()
2519         if (Pattern.matches(toSupplementaries("ulb(c*)"),
2520                             toSupplementaries("ulbccccccdef")))
2521             failCount++;
2522 
2523         // Supplementary character test
2524         // matches()
2525         if (!Pattern.matches(toSupplementaries("ulb(c*)"),
2526                              toSupplementaries("ulbcccccc")))
2527             failCount++;
2528 
2529         // find() but not matches()
2530         if (Pattern.matches(toSupplementaries("ulb(c*)"),
2531                             toSupplementaries("zzzulbcccccc")))
2532             failCount++;
2533 
2534         // lookingAt() but not matches()
2535         if (Pattern.matches(toSupplementaries("ulb(c*)"),
2536                             toSupplementaries("ulbccccccdef")))
2537             failCount++;
2538 
2539         report("Pattern Matches");
2540     }
2541 
2542     /**
2543      * Canonical equivalence testing. Tests the ability of the engine
2544      * to match sequences that are not explicitly specified in the
2545      * pattern when they are considered equivalent by the Unicode Standard.
2546      */
2547     private static void ceTest() throws Exception {
2548         // Decomposed char outside char classes
2549         Pattern p = Pattern.compile("testa\u030a", Pattern.CANON_EQ);
2550         Matcher m = p.matcher("test\u00e5");
2551         if (!m.matches())
2552             failCount++;
2553 
2554         m.reset("testa\u030a");
2555         if (!m.matches())
2556             failCount++;
2557 
2558         // Composed char outside char classes
2559         p = Pattern.compile("test\u00e5", Pattern.CANON_EQ);
2560         m = p.matcher("test\u00e5");
2561         if (!m.matches())
2562             failCount++;
2563 
2564         m.reset("testa\u030a");
2565         if (!m.find())
2566             failCount++;
2567 
2568         // Decomposed char inside a char class
2569         p = Pattern.compile("test[abca\u030a]", Pattern.CANON_EQ);
2570         m = p.matcher("test\u00e5");
2571         if (!m.find())
2572             failCount++;
2573 
2574         m.reset("testa\u030a");
2575         if (!m.find())
2576             failCount++;
2577 
2578         // Composed char inside a char class
2579         p = Pattern.compile("test[abc\u00e5def\u00e0]", Pattern.CANON_EQ);
2580         m = p.matcher("test\u00e5");
2581         if (!m.find())
2582             failCount++;
2583 
2584         m.reset("testa\u0300");
2585         if (!m.find())
2586             failCount++;
2587 
2588         m.reset("testa\u030a");
2589         if (!m.find())
2590             failCount++;
2591 
2592         // Marks that cannot legally change order and be equivalent
2593         p = Pattern.compile("testa\u0308\u0300", Pattern.CANON_EQ);
2594         check(p, "testa\u0308\u0300", true);
2595         check(p, "testa\u0300\u0308", false);
2596 
2597         // Marks that can legally change order and be equivalent
2598         p = Pattern.compile("testa\u0308\u0323", Pattern.CANON_EQ);
2599         check(p, "testa\u0308\u0323", true);
2600         check(p, "testa\u0323\u0308", true);
2601 
2602         // Test all equivalences of the sequence a\u0308\u0323\u0300
2603         p = Pattern.compile("testa\u0308\u0323\u0300", Pattern.CANON_EQ);
2604         check(p, "testa\u0308\u0323\u0300", true);
2605         check(p, "testa\u0323\u0308\u0300", true);
2606         check(p, "testa\u0308\u0300\u0323", true);
2607         check(p, "test\u00e4\u0323\u0300", true);
2608         check(p, "test\u00e4\u0300\u0323", true);
2609 
2610         /*
2611          * The following canonical equivalence tests don't work. Bug id: 4916384.
2612          *
2613         // Decomposed hangul (jamos)
2614         p = Pattern.compile("\u1100\u1161", Pattern.CANON_EQ);
2615         m = p.matcher("\u1100\u1161");
2616         if (!m.matches())
2617             failCount++;
2618 
2619         m.reset("\uac00");
2620         if (!m.matches())
2621             failCount++;
2622 
2623         // Composed hangul
2624         p = Pattern.compile("\uac00", Pattern.CANON_EQ);
2625         m = p.matcher("\u1100\u1161");
2626         if (!m.matches())
2627             failCount++;
2628 
2629         m.reset("\uac00");
2630         if (!m.matches())
2631             failCount++;
2632 
2633         // Decomposed supplementary outside char classes
2634         p = Pattern.compile("test\ud834\uddbc\ud834\udd6f", Pattern.CANON_EQ);
2635         m = p.matcher("test\ud834\uddc0");
2636         if (!m.matches())
2637             failCount++;
2638 
2639         m.reset("test\ud834\uddbc\ud834\udd6f");
2640         if (!m.matches())
2641             failCount++;
2642 
2643         // Composed supplementary outside char classes
2644         p = Pattern.compile("test\ud834\uddc0", Pattern.CANON_EQ);
2645         m.reset("test\ud834\uddbc\ud834\udd6f");
2646         if (!m.matches())
2647             failCount++;
2648 
2649         m = p.matcher("test\ud834\uddc0");
2650         if (!m.matches())
2651             failCount++;
2652 
2653         */
2654 
2655         report("Canonical Equivalence");
2656     }
2657 
2658     /**
2659      * A basic sanity test of Matcher.replaceAll().
2660      */
2661     private static void globalSubstitute() throws Exception {
2662         // Global substitution with a literal
2663         Pattern p = Pattern.compile("(ab)(c*)");
2664         Matcher m = p.matcher("abccczzzabcczzzabccc");
2665         if (!m.replaceAll("test").equals("testzzztestzzztest"))
2666             failCount++;
2667 
2668         m.reset("zzzabccczzzabcczzzabccczzz");
2669         if (!m.replaceAll("test").equals("zzztestzzztestzzztestzzz"))
2670             failCount++;
2671 
2672         // Global substitution with groups
2673         m.reset("zzzabccczzzabcczzzabccczzz");
2674         String result = m.replaceAll("$1");
2675         if (!result.equals("zzzabzzzabzzzabzzz"))
2676             failCount++;
2677 
2678         // Supplementary character test
2679         // Global substitution with a literal
2680         p = Pattern.compile(toSupplementaries("(ab)(c*)"));
2681         m = p.matcher(toSupplementaries("abccczzzabcczzzabccc"));
2682         if (!m.replaceAll(toSupplementaries("test")).
2683             equals(toSupplementaries("testzzztestzzztest")))
2684             failCount++;
2685 
2686         m.reset(toSupplementaries("zzzabccczzzabcczzzabccczzz"));
2687         if (!m.replaceAll(toSupplementaries("test")).
2688             equals(toSupplementaries("zzztestzzztestzzztestzzz")))
2689             failCount++;
2690 
2691         // Global substitution with groups
2692         m.reset(toSupplementaries("zzzabccczzzabcczzzabccczzz"));
2693         result = m.replaceAll("$1");
2694         if (!result.equals(toSupplementaries("zzzabzzzabzzzabzzz")))
2695             failCount++;
2696 
2697         report("Global Substitution");
2698     }
2699 
2700     /**
2701      * Tests the usage of Matcher.appendReplacement() with literal
2702      * and group substitutions.
2703      */
2704     private static void stringbufferSubstitute() throws Exception {
2705         // SB substitution with literal
2706         String blah = "zzzblahzzz";
2707         Pattern p = Pattern.compile("blah");
2708         Matcher m = p.matcher(blah);
2709         StringBuffer result = new StringBuffer();
2710         try {
2711             m.appendReplacement(result, "blech");
2712             failCount++;
2713         } catch (IllegalStateException e) {
2714         }
2715         m.find();
2716         m.appendReplacement(result, "blech");
2717         if (!result.toString().equals("zzzblech"))
2718             failCount++;
2719 
2720         m.appendTail(result);
2721         if (!result.toString().equals("zzzblechzzz"))
2722             failCount++;
2723 
2724         // SB substitution with groups
2725         blah = "zzzabcdzzz";
2726         p = Pattern.compile("(ab)(cd)*");
2727         m = p.matcher(blah);
2728         result = new StringBuffer();
2729         try {
2730             m.appendReplacement(result, "$1");
2731             failCount++;
2732         } catch (IllegalStateException e) {
2733         }
2734         m.find();
2735         m.appendReplacement(result, "$1");
2736         if (!result.toString().equals("zzzab"))
2737             failCount++;
2738 
2739         m.appendTail(result);
2740         if (!result.toString().equals("zzzabzzz"))
2741             failCount++;
2742 
2743         // SB substitution with 3 groups
2744         blah = "zzzabcdcdefzzz";
2745         p = Pattern.compile("(ab)(cd)*(ef)");
2746         m = p.matcher(blah);
2747         result = new StringBuffer();
2748         try {
2749             m.appendReplacement(result, "$1w$2w$3");
2750             failCount++;
2751         } catch (IllegalStateException e) {
2752         }
2753         m.find();
2754         m.appendReplacement(result, "$1w$2w$3");
2755         if (!result.toString().equals("zzzabwcdwef"))
2756             failCount++;
2757 
2758         m.appendTail(result);
2759         if (!result.toString().equals("zzzabwcdwefzzz"))
2760             failCount++;
2761 
2762         // SB substitution with groups and three matches
2763         // skipping middle match
2764         blah = "zzzabcdzzzabcddzzzabcdzzz";
2765         p = Pattern.compile("(ab)(cd*)");
2766         m = p.matcher(blah);
2767         result = new StringBuffer();
2768         try {
2769             m.appendReplacement(result, "$1");
2770             failCount++;
2771         } catch (IllegalStateException e) {
2772         }
2773         m.find();
2774         m.appendReplacement(result, "$1");
2775         if (!result.toString().equals("zzzab"))
2776             failCount++;
2777 
2778         m.find();
2779         m.find();
2780         m.appendReplacement(result, "$2");
2781         if (!result.toString().equals("zzzabzzzabcddzzzcd"))
2782             failCount++;
2783 
2784         m.appendTail(result);
2785         if (!result.toString().equals("zzzabzzzabcddzzzcdzzz"))
2786             failCount++;
2787 
2788         // Check to make sure escaped $ is ignored
2789         blah = "zzzabcdcdefzzz";
2790         p = Pattern.compile("(ab)(cd)*(ef)");
2791         m = p.matcher(blah);
2792         result = new StringBuffer();
2793         m.find();
2794         m.appendReplacement(result, "$1w\\$2w$3");
2795         if (!result.toString().equals("zzzabw$2wef"))
2796             failCount++;
2797 
2798         m.appendTail(result);
2799         if (!result.toString().equals("zzzabw$2wefzzz"))
2800             failCount++;
2801 
2802         // Check to make sure a reference to nonexistent group causes error
2803         blah = "zzzabcdcdefzzz";
2804         p = Pattern.compile("(ab)(cd)*(ef)");
2805         m = p.matcher(blah);
2806         result = new StringBuffer();
2807         m.find();
2808         try {
2809             m.appendReplacement(result, "$1w$5w$3");
2810             failCount++;
2811         } catch (IndexOutOfBoundsException ioobe) {
2812             // Correct result
2813         }
2814 
2815         // Check double digit group references
2816         blah = "zzz123456789101112zzz";
2817         p = Pattern.compile("(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)");
2818         m = p.matcher(blah);
2819         result = new StringBuffer();
2820         m.find();
2821         m.appendReplacement(result, "$1w$11w$3");
2822         if (!result.toString().equals("zzz1w11w3"))
2823             failCount++;
2824 
2825         // Check to make sure it backs off $15 to $1 if only three groups
2826         blah = "zzzabcdcdefzzz";
2827         p = Pattern.compile("(ab)(cd)*(ef)");
2828         m = p.matcher(blah);
2829         result = new StringBuffer();
2830         m.find();
2831         m.appendReplacement(result, "$1w$15w$3");
2832         if (!result.toString().equals("zzzabwab5wef"))
2833             failCount++;
2834 
2835 
2836         // Supplementary character test
2837         // SB substitution with literal
2838         blah = toSupplementaries("zzzblahzzz");
2839         p = Pattern.compile(toSupplementaries("blah"));
2840         m = p.matcher(blah);
2841         result = new StringBuffer();
2842         try {
2843             m.appendReplacement(result, toSupplementaries("blech"));
2844             failCount++;
2845         } catch (IllegalStateException e) {
2846         }
2847         m.find();
2848         m.appendReplacement(result, toSupplementaries("blech"));
2849         if (!result.toString().equals(toSupplementaries("zzzblech")))
2850             failCount++;
2851 
2852         m.appendTail(result);
2853         if (!result.toString().equals(toSupplementaries("zzzblechzzz")))
2854             failCount++;
2855 
2856         // SB substitution with groups
2857         blah = toSupplementaries("zzzabcdzzz");
2858         p = Pattern.compile(toSupplementaries("(ab)(cd)*"));
2859         m = p.matcher(blah);
2860         result = new StringBuffer();
2861         try {
2862             m.appendReplacement(result, "$1");
2863             failCount++;
2864         } catch (IllegalStateException e) {
2865         }
2866         m.find();
2867         m.appendReplacement(result, "$1");
2868         if (!result.toString().equals(toSupplementaries("zzzab")))
2869             failCount++;
2870 
2871         m.appendTail(result);
2872         if (!result.toString().equals(toSupplementaries("zzzabzzz")))
2873             failCount++;
2874 
2875         // SB substitution with 3 groups
2876         blah = toSupplementaries("zzzabcdcdefzzz");
2877         p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)"));
2878         m = p.matcher(blah);
2879         result = new StringBuffer();
2880         try {
2881             m.appendReplacement(result, toSupplementaries("$1w$2w$3"));
2882             failCount++;
2883         } catch (IllegalStateException e) {
2884         }
2885         m.find();
2886         m.appendReplacement(result, toSupplementaries("$1w$2w$3"));
2887         if (!result.toString().equals(toSupplementaries("zzzabwcdwef")))
2888             failCount++;
2889 
2890         m.appendTail(result);
2891         if (!result.toString().equals(toSupplementaries("zzzabwcdwefzzz")))
2892             failCount++;
2893 
2894         // SB substitution with groups and three matches
2895         // skipping middle match
2896         blah = toSupplementaries("zzzabcdzzzabcddzzzabcdzzz");
2897         p = Pattern.compile(toSupplementaries("(ab)(cd*)"));
2898         m = p.matcher(blah);
2899         result = new StringBuffer();
2900         try {
2901             m.appendReplacement(result, "$1");
2902             failCount++;
2903         } catch (IllegalStateException e) {
2904         }
2905         m.find();
2906         m.appendReplacement(result, "$1");
2907         if (!result.toString().equals(toSupplementaries("zzzab")))
2908             failCount++;
2909 
2910         m.find();
2911         m.find();
2912         m.appendReplacement(result, "$2");
2913         if (!result.toString().equals(toSupplementaries("zzzabzzzabcddzzzcd")))
2914             failCount++;
2915 
2916         m.appendTail(result);
2917         if (!result.toString().equals(toSupplementaries("zzzabzzzabcddzzzcdzzz")))
2918             failCount++;
2919 
2920         // Check to make sure escaped $ is ignored
2921         blah = toSupplementaries("zzzabcdcdefzzz");
2922         p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)"));
2923         m = p.matcher(blah);
2924         result = new StringBuffer();
2925         m.find();
2926         m.appendReplacement(result, toSupplementaries("$1w\\$2w$3"));
2927         if (!result.toString().equals(toSupplementaries("zzzabw$2wef")))
2928             failCount++;
2929 
2930         m.appendTail(result);
2931         if (!result.toString().equals(toSupplementaries("zzzabw$2wefzzz")))
2932             failCount++;
2933 
2934         // Check to make sure a reference to nonexistent group causes error
2935         blah = toSupplementaries("zzzabcdcdefzzz");
2936         p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)"));
2937         m = p.matcher(blah);
2938         result = new StringBuffer();
2939         m.find();
2940         try {
2941             m.appendReplacement(result, toSupplementaries("$1w$5w$3"));
2942             failCount++;
2943         } catch (IndexOutOfBoundsException ioobe) {
2944             // Correct result
2945         }
2946 
2947         // Check double digit group references
2948         blah = toSupplementaries("zzz123456789101112zzz");
2949         p = Pattern.compile("(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)");
2950         m = p.matcher(blah);
2951         result = new StringBuffer();
2952         m.find();
2953         m.appendReplacement(result, toSupplementaries("$1w$11w$3"));
2954         if (!result.toString().equals(toSupplementaries("zzz1w11w3")))
2955             failCount++;
2956 
2957         // Check to make sure it backs off $15 to $1 if only three groups
2958         blah = toSupplementaries("zzzabcdcdefzzz");
2959         p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)"));
2960         m = p.matcher(blah);
2961         result = new StringBuffer();
2962         m.find();
2963         m.appendReplacement(result, toSupplementaries("$1w$15w$3"));
2964         if (!result.toString().equals(toSupplementaries("zzzabwab5wef")))
2965             failCount++;
2966 
2967         // Check nothing has been appended into the output buffer if
2968         // the replacement string triggers IllegalArgumentException.
2969         p = Pattern.compile("(abc)");
2970         m = p.matcher("abcd");
2971         result = new StringBuffer();
2972         m.find();
2973         try {
2974             m.appendReplacement(result, ("xyz$g"));
2975             failCount++;
2976         } catch (IllegalArgumentException iae) {
2977             if (result.length() != 0)
2978                 failCount++;
2979         }
2980 
2981         report("SB Substitution");
2982     }
2983 
2984     /*
2985      * 5 groups of characters are created to make a substitution string.
2986      * A base string will be created including random lead chars, the
2987      * substitution string, and random trailing chars.
2988      * A pattern containing the 5 groups is searched for and replaced with:
2989      * random group + random string + random group.
2990      * The results are checked for correctness.
2991      */
2992     private static void substitutionBasher() {
2993         for (int runs = 0; runs<1000; runs++) {
2994             // Create a base string to work in
2995             int leadingChars = generator.nextInt(10);
2996             StringBuffer baseBuffer = new StringBuffer(100);
2997             String leadingString = getRandomAlphaString(leadingChars);
2998             baseBuffer.append(leadingString);
2999 
3000             // Create 5 groups of random number of random chars
3001             // Create the string to substitute
3002             // Create the pattern string to search for
3003             StringBuffer bufferToSub = new StringBuffer(25);
3004             StringBuffer bufferToPat = new StringBuffer(50);
3005             String[] groups = new String[5];
3006             for(int i=0; i<5; i++) {
3007                 int aGroupSize = generator.nextInt(5)+1;
3008                 groups[i] = getRandomAlphaString(aGroupSize);
3009                 bufferToSub.append(groups[i]);
3010                 bufferToPat.append('(');
3011                 bufferToPat.append(groups[i]);
3012                 bufferToPat.append(')');
3013             }
3014             String stringToSub = bufferToSub.toString();
3015             String pattern = bufferToPat.toString();
3016 
3017             // Place sub string into working string at random index
3018             baseBuffer.append(stringToSub);
3019 
3020             // Append random chars to end
3021             int trailingChars = generator.nextInt(10);
3022             String trailingString = getRandomAlphaString(trailingChars);
3023             baseBuffer.append(trailingString);
3024             String baseString = baseBuffer.toString();
3025 
3026             // Create test pattern and matcher
3027             Pattern p = Pattern.compile(pattern);
3028             Matcher m = p.matcher(baseString);
3029 
3030             // Reject candidate if pattern happens to start early
3031             m.find();
3032             if (m.start() < leadingChars)
3033                 continue;
3034 
3035             // Reject candidate if more than one match
3036             if (m.find())
3037                 continue;
3038 
3039             // Construct a replacement string with :
3040             // random group + random string + random group
3041             StringBuffer bufferToRep = new StringBuffer();
3042             int groupIndex1 = generator.nextInt(5);
3043             bufferToRep.append("$" + (groupIndex1 + 1));
3044             String randomMidString = getRandomAlphaString(5);
3045             bufferToRep.append(randomMidString);
3046             int groupIndex2 = generator.nextInt(5);
3047             bufferToRep.append("$" + (groupIndex2 + 1));
3048             String replacement = bufferToRep.toString();
3049 
3050             // Do the replacement
3051             String result = m.replaceAll(replacement);
3052 
3053             // Construct expected result
3054             StringBuffer bufferToRes = new StringBuffer();
3055             bufferToRes.append(leadingString);
3056             bufferToRes.append(groups[groupIndex1]);
3057             bufferToRes.append(randomMidString);
3058             bufferToRes.append(groups[groupIndex2]);
3059             bufferToRes.append(trailingString);
3060             String expectedResult = bufferToRes.toString();
3061 
3062             // Check results
3063             if (!result.equals(expectedResult))
3064                 failCount++;
3065         }
3066 
3067         report("Substitution Basher");
3068     }
3069 
3070     /**
3071      * Checks the handling of some escape sequences that the Pattern
3072      * class should process instead of the java compiler. These are
3073      * not in the file because the escapes should be be processed
3074      * by the Pattern class when the regex is compiled.
3075      */
3076     private static void escapes() throws Exception {
3077         Pattern p = Pattern.compile("\\043");
3078         Matcher m = p.matcher("#");
3079         if (!m.find())
3080             failCount++;
3081 
3082         p = Pattern.compile("\\x23");
3083         m = p.matcher("#");
3084         if (!m.find())
3085             failCount++;
3086 
3087         p = Pattern.compile("\\u0023");
3088         m = p.matcher("#");
3089         if (!m.find())
3090             failCount++;
3091 
3092         report("Escape sequences");
3093     }
3094 
3095     /**
3096      * Checks the handling of blank input situations. These
3097      * tests are incompatible with my test file format.
3098      */
3099     private static void blankInput() throws Exception {
3100         Pattern p = Pattern.compile("abc", Pattern.CASE_INSENSITIVE);
3101         Matcher m = p.matcher("");
3102         if (m.find())
3103             failCount++;
3104 
3105         p = Pattern.compile("a*", Pattern.CASE_INSENSITIVE);
3106         m = p.matcher("");
3107         if (!m.find())
3108             failCount++;
3109 
3110         p = Pattern.compile("abc");
3111         m = p.matcher("");
3112         if (m.find())
3113             failCount++;
3114 
3115         p = Pattern.compile("a*");
3116         m = p.matcher("");
3117         if (!m.find())
3118             failCount++;
3119 
3120         report("Blank input");
3121     }
3122 
3123     /**
3124      * Tests the Boyer-Moore pattern matching of a character sequence
3125      * on randomly generated patterns.
3126      */
3127     private static void bm() throws Exception {
3128         doBnM('a');
3129         report("Boyer Moore (ASCII)");
3130 
3131         doBnM(Character.MIN_SUPPLEMENTARY_CODE_POINT - 10);
3132         report("Boyer Moore (Supplementary)");
3133     }
3134 
3135     private static void doBnM(int baseCharacter) throws Exception {
3136         int achar=0;
3137 
3138         for (int i=0; i<100; i++) {
3139             // Create a short pattern to search for
3140             int patternLength = generator.nextInt(7) + 4;
3141             StringBuffer patternBuffer = new StringBuffer(patternLength);
3142             String pattern;
3143             retry: for (;;) {
3144                 for (int x=0; x<patternLength; x++) {
3145                     int ch = baseCharacter + generator.nextInt(26);
3146                     if (Character.isSupplementaryCodePoint(ch)) {
3147                         patternBuffer.append(Character.toChars(ch));
3148                     } else {
3149                         patternBuffer.append((char)ch);
3150                     }
3151                 }
3152                 pattern = patternBuffer.toString();
3153 
3154                 // Avoid patterns that start and end with the same substring
3155                 // See JDK-6854417
3156                 for (int x=1; x <patternLength; x++) {
3157                     if (pattern.startsWith(pattern.substring(x)))
3158                         continue retry;
3159                 }
3160                 break;
3161             }
3162             Pattern p = Pattern.compile(pattern);
3163 
3164             // Create a buffer with random ASCII chars that does
3165             // not match the sample
3166             String toSearch = null;
3167             StringBuffer s = null;
3168             Matcher m = p.matcher("");
3169             do {
3170                 s = new StringBuffer(100);
3171                 for (int x=0; x<100; x++) {
3172                     int ch = baseCharacter + generator.nextInt(26);
3173                     if (Character.isSupplementaryCodePoint(ch)) {
3174                         s.append(Character.toChars(ch));
3175                     } else {
3176                         s.append((char)ch);
3177                     }
3178                 }
3179                 toSearch = s.toString();
3180                 m.reset(toSearch);
3181             } while (m.find());
3182 
3183             // Insert the pattern at a random spot
3184             int insertIndex = generator.nextInt(99);
3185             if (Character.isLowSurrogate(s.charAt(insertIndex)))
3186                 insertIndex++;
3187             s = s.insert(insertIndex, pattern);
3188             toSearch = s.toString();
3189 
3190             // Make sure that the pattern is found
3191             m.reset(toSearch);
3192             if (!m.find())
3193                 failCount++;
3194 
3195             // Make sure that the match text is the pattern
3196             if (!m.group().equals(pattern))
3197                 failCount++;
3198 
3199             // Make sure match occured at insertion point
3200             if (m.start() != insertIndex)
3201                 failCount++;
3202         }
3203     }
3204 
3205     /**
3206      * Tests the matching of slices on randomly generated patterns.
3207      * The Boyer-Moore optimization is not done on these patterns
3208      * because it uses unicode case folding.
3209      */
3210     private static void slice() throws Exception {
3211         doSlice(Character.MAX_VALUE);
3212         report("Slice");
3213 
3214         doSlice(Character.MAX_CODE_POINT);
3215         report("Slice (Supplementary)");
3216     }
3217 
3218     private static void doSlice(int maxCharacter) throws Exception {
3219         Random generator = new Random();
3220         int achar=0;
3221 
3222         for (int i=0; i<100; i++) {
3223             // Create a short pattern to search for
3224             int patternLength = generator.nextInt(7) + 4;
3225             StringBuffer patternBuffer = new StringBuffer(patternLength);
3226             for (int x=0; x<patternLength; x++) {
3227                 int randomChar = 0;
3228                 while (!Character.isLetterOrDigit(randomChar))
3229                     randomChar = generator.nextInt(maxCharacter);
3230                 if (Character.isSupplementaryCodePoint(randomChar)) {
3231                     patternBuffer.append(Character.toChars(randomChar));
3232                 } else {
3233                     patternBuffer.append((char) randomChar);
3234                 }
3235             }
3236             String pattern =  patternBuffer.toString();
3237             Pattern p = Pattern.compile(pattern, Pattern.UNICODE_CASE);
3238 
3239             // Create a buffer with random chars that does not match the sample
3240             String toSearch = null;
3241             StringBuffer s = null;
3242             Matcher m = p.matcher("");
3243             do {
3244                 s = new StringBuffer(100);
3245                 for (int x=0; x<100; x++) {
3246                     int randomChar = 0;
3247                     while (!Character.isLetterOrDigit(randomChar))
3248                         randomChar = generator.nextInt(maxCharacter);
3249                     if (Character.isSupplementaryCodePoint(randomChar)) {
3250                         s.append(Character.toChars(randomChar));
3251                     } else {
3252                         s.append((char) randomChar);
3253                     }
3254                 }
3255                 toSearch = s.toString();
3256                 m.reset(toSearch);
3257             } while (m.find());
3258 
3259             // Insert the pattern at a random spot
3260             int insertIndex = generator.nextInt(99);
3261             if (Character.isLowSurrogate(s.charAt(insertIndex)))
3262                 insertIndex++;
3263             s = s.insert(insertIndex, pattern);
3264             toSearch = s.toString();
3265 
3266             // Make sure that the pattern is found
3267             m.reset(toSearch);
3268             if (!m.find())
3269                 failCount++;
3270 
3271             // Make sure that the match text is the pattern
3272             if (!m.group().equals(pattern))
3273                 failCount++;
3274 
3275             // Make sure match occured at insertion point
3276             if (m.start() != insertIndex)
3277                 failCount++;
3278         }
3279     }
3280 
3281     private static void explainFailure(String pattern, String data,
3282                                        String expected, String actual) {
3283         System.err.println("----------------------------------------");
3284         System.err.println("Pattern = "+pattern);
3285         System.err.println("Data = "+data);
3286         System.err.println("Expected = " + expected);
3287         System.err.println("Actual   = " + actual);
3288     }
3289 
3290     private static void explainFailure(String pattern, String data,
3291                                        Throwable t) {
3292         System.err.println("----------------------------------------");
3293         System.err.println("Pattern = "+pattern);
3294         System.err.println("Data = "+data);
3295         t.printStackTrace(System.err);
3296     }
3297 
3298     // Testing examples from a file
3299 
3300     /**
3301      * Goes through the file "TestCases.txt" and creates many patterns
3302      * described in the file, matching the patterns against input lines in
3303      * the file, and comparing the results against the correct results
3304      * also found in the file. The file format is described in comments
3305      * at the head of the file.
3306      */
3307     private static void processFile(String fileName) throws Exception {
3308         File testCases = new File(System.getProperty("test.src", "."),
3309                                   fileName);
3310         FileInputStream in = new FileInputStream(testCases);
3311         BufferedReader r = new BufferedReader(new InputStreamReader(in));
3312 
3313         // Process next test case.
3314         String aLine;
3315         while((aLine = r.readLine()) != null) {
3316             // Read a line for pattern
3317             String patternString = grabLine(r);
3318             Pattern p = null;
3319             try {
3320                 p = compileTestPattern(patternString);
3321             } catch (PatternSyntaxException e) {
3322                 String dataString = grabLine(r);
3323                 String expectedResult = grabLine(r);
3324                 if (expectedResult.startsWith("error"))
3325                     continue;
3326                 explainFailure(patternString, dataString, e);
3327                 failCount++;
3328                 continue;
3329             }
3330 
3331             // Read a line for input string
3332             String dataString = grabLine(r);
3333             Matcher m = p.matcher(dataString);
3334             StringBuffer result = new StringBuffer();
3335 
3336             // Check for IllegalStateExceptions before a match
3337             failCount += preMatchInvariants(m);
3338 
3339             boolean found = m.find();
3340 
3341             if (found)
3342                 failCount += postTrueMatchInvariants(m);
3343             else
3344                 failCount += postFalseMatchInvariants(m);
3345 
3346             if (found) {
3347                 result.append("true ");
3348                 result.append(m.group(0) + " ");
3349             } else {
3350                 result.append("false ");
3351             }
3352 
3353             result.append(m.groupCount());
3354 
3355             if (found) {
3356                 for (int i=1; i<m.groupCount()+1; i++)
3357                     if (m.group(i) != null)
3358                         result.append(" " +m.group(i));
3359             }
3360 
3361             // Read a line for the expected result
3362             String expectedResult = grabLine(r);
3363 
3364             if (!result.toString().equals(expectedResult)) {
3365                 explainFailure(patternString, dataString, expectedResult, result.toString());
3366                 failCount++;
3367             }
3368         }
3369 
3370         report(fileName);
3371     }
3372 
3373     private static int preMatchInvariants(Matcher m) {
3374         int failCount = 0;
3375         try {
3376             m.start();
3377             failCount++;
3378         } catch (IllegalStateException ise) {}
3379         try {
3380             m.end();
3381             failCount++;
3382         } catch (IllegalStateException ise) {}
3383         try {
3384             m.group();
3385             failCount++;
3386         } catch (IllegalStateException ise) {}
3387         return failCount;
3388     }
3389 
3390     private static int postFalseMatchInvariants(Matcher m) {
3391         int failCount = 0;
3392         try {
3393             m.group();
3394             failCount++;
3395         } catch (IllegalStateException ise) {}
3396         try {
3397             m.start();
3398             failCount++;
3399         } catch (IllegalStateException ise) {}
3400         try {
3401             m.end();
3402             failCount++;
3403         } catch (IllegalStateException ise) {}
3404         return failCount;
3405     }
3406 
3407     private static int postTrueMatchInvariants(Matcher m) {
3408         int failCount = 0;
3409         //assert(m.start() = m.start(0);
3410         if (m.start() != m.start(0))
3411             failCount++;
3412         //assert(m.end() = m.end(0);
3413         if (m.start() != m.start(0))
3414             failCount++;
3415         //assert(m.group() = m.group(0);
3416         if (!m.group().equals(m.group(0)))
3417             failCount++;
3418         try {
3419             m.group(50);
3420             failCount++;
3421         } catch (IndexOutOfBoundsException ise) {}
3422 
3423         return failCount;
3424     }
3425 
3426     private static Pattern compileTestPattern(String patternString) {
3427         if (!patternString.startsWith("'")) {
3428             return Pattern.compile(patternString);
3429         }
3430 
3431         int break1 = patternString.lastIndexOf("'");
3432         String flagString = patternString.substring(
3433                                           break1+1, patternString.length());
3434         patternString = patternString.substring(1, break1);
3435 
3436         if (flagString.equals("i"))
3437             return Pattern.compile(patternString, Pattern.CASE_INSENSITIVE);
3438 
3439         if (flagString.equals("m"))
3440             return Pattern.compile(patternString, Pattern.MULTILINE);
3441 
3442         return Pattern.compile(patternString);
3443     }
3444 
3445     /**
3446      * Reads a line from the input file. Keeps reading lines until a non
3447      * empty non comment line is read. If the line contains a \n then
3448      * these two characters are replaced by a newline char. If a \\uxxxx
3449      * sequence is read then the sequence is replaced by the unicode char.
3450      */
3451     private static String grabLine(BufferedReader r) throws Exception {
3452         int index = 0;
3453         String line = r.readLine();
3454         while (line.startsWith("//") || line.length() < 1)
3455             line = r.readLine();
3456         while ((index = line.indexOf("\\n")) != -1) {
3457             StringBuffer temp = new StringBuffer(line);
3458             temp.replace(index, index+2, "\n");
3459             line = temp.toString();
3460         }
3461         while ((index = line.indexOf("\\u")) != -1) {
3462             StringBuffer temp = new StringBuffer(line);
3463             String value = temp.substring(index+2, index+6);
3464             char aChar = (char)Integer.parseInt(value, 16);
3465             String unicodeChar = "" + aChar;
3466             temp.replace(index, index+6, unicodeChar);
3467             line = temp.toString();
3468         }
3469 
3470         return line;
3471     }
3472 
3473     private static void check(Pattern p, String s, String g, String expected) {
3474         Matcher m = p.matcher(s);
3475         m.find();
3476         if (!m.group(g).equals(expected) ||
3477             s.charAt(m.start(g)) != expected.charAt(0) ||
3478             s.charAt(m.end(g) - 1) != expected.charAt(expected.length() - 1))
3479             failCount++;
3480     }
3481 
3482     private static void checkReplaceFirst(String p, String s, String r, String expected)
3483     {
3484         if (!expected.equals(Pattern.compile(p)
3485                                     .matcher(s)
3486                                     .replaceFirst(r)))
3487             failCount++;
3488     }
3489 
3490     private static void checkReplaceAll(String p, String s, String r, String expected)
3491     {
3492         if (!expected.equals(Pattern.compile(p)
3493                                     .matcher(s)
3494                                     .replaceAll(r)))
3495             failCount++;
3496     }
3497 
3498     private static void checkExpectedFail(String p) {
3499         try {
3500             Pattern.compile(p);
3501         } catch (PatternSyntaxException pse) {
3502             //pse.printStackTrace();
3503             return;
3504         }
3505         failCount++;
3506     }
3507 
3508     private static void checkExpectedIAE(Matcher m, String g) {
3509         m.find();
3510         try {
3511             m.group(g);
3512         } catch (IllegalArgumentException x) {
3513             //iae.printStackTrace();
3514             try {
3515                 m.start(g);
3516             } catch (IllegalArgumentException xx) {
3517                 try {
3518                     m.start(g);
3519                 } catch (IllegalArgumentException xxx) {
3520                     return;
3521                 }
3522             }
3523         }
3524         failCount++;
3525     }
3526 
3527     private static void checkExpectedNPE(Matcher m) {
3528         m.find();
3529         try {
3530             m.group(null);
3531         } catch (NullPointerException x) {
3532             try {
3533                 m.start(null);
3534             } catch (NullPointerException xx) {
3535                 try {
3536                     m.end(null);
3537                 } catch (NullPointerException xxx) {
3538                     return;
3539                 }
3540             }
3541         }
3542         failCount++;
3543     }
3544 
3545     private static void namedGroupCaptureTest() throws Exception {
3546         check(Pattern.compile("x+(?<gname>y+)z+"),
3547               "xxxyyyzzz",
3548               "gname",
3549               "yyy");
3550 
3551         check(Pattern.compile("x+(?<gname8>y+)z+"),
3552               "xxxyyyzzz",
3553               "gname8",
3554               "yyy");
3555 
3556         //backref
3557         Pattern pattern = Pattern.compile("(a*)bc\\1");
3558         check(pattern, "zzzaabcazzz", true);  // found "abca"
3559 
3560         check(Pattern.compile("(?<gname>a*)bc\\k<gname>"),
3561               "zzzaabcaazzz", true);
3562 
3563         check(Pattern.compile("(?<gname>abc)(def)\\k<gname>"),
3564               "abcdefabc", true);
3565 
3566         check(Pattern.compile("(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(?<gname>k)\\k<gname>"),
3567               "abcdefghijkk", true);
3568 
3569         // Supplementary character tests
3570         check(Pattern.compile("(?<gname>" + toSupplementaries("a*)bc") + "\\k<gname>"),
3571               toSupplementaries("zzzaabcazzz"), true);
3572 
3573         check(Pattern.compile("(?<gname>" + toSupplementaries("a*)bc") + "\\k<gname>"),
3574               toSupplementaries("zzzaabcaazzz"), true);
3575 
3576         check(Pattern.compile("(?<gname>" + toSupplementaries("abc)(def)") + "\\k<gname>"),
3577               toSupplementaries("abcdefabc"), true);
3578 
3579         check(Pattern.compile(toSupplementaries("(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)") +
3580                               "(?<gname>" +
3581                               toSupplementaries("k)") + "\\k<gname>"),
3582               toSupplementaries("abcdefghijkk"), true);
3583 
3584         check(Pattern.compile("x+(?<gname>y+)z+\\k<gname>"),
3585               "xxxyyyzzzyyy",
3586               "gname",
3587               "yyy");
3588 
3589         //replaceFirst/All
3590         checkReplaceFirst("(?<gn>ab)(c*)",
3591                           "abccczzzabcczzzabccc",
3592                           "${gn}",
3593                           "abzzzabcczzzabccc");
3594 
3595         checkReplaceAll("(?<gn>ab)(c*)",
3596                         "abccczzzabcczzzabccc",
3597                         "${gn}",
3598                         "abzzzabzzzab");
3599 
3600 
3601         checkReplaceFirst("(?<gn>ab)(c*)",
3602                           "zzzabccczzzabcczzzabccczzz",
3603                           "${gn}",
3604                           "zzzabzzzabcczzzabccczzz");
3605 
3606         checkReplaceAll("(?<gn>ab)(c*)",
3607                         "zzzabccczzzabcczzzabccczzz",
3608                         "${gn}",
3609                         "zzzabzzzabzzzabzzz");
3610 
3611         checkReplaceFirst("(?<gn1>ab)(?<gn2>c*)",
3612                           "zzzabccczzzabcczzzabccczzz",
3613                           "${gn2}",
3614                           "zzzccczzzabcczzzabccczzz");
3615 
3616         checkReplaceAll("(?<gn1>ab)(?<gn2>c*)",
3617                         "zzzabccczzzabcczzzabccczzz",
3618                         "${gn2}",
3619                         "zzzccczzzcczzzccczzz");
3620 
3621         //toSupplementaries("(ab)(c*)"));
3622         checkReplaceFirst("(?<gn1>" + toSupplementaries("ab") +
3623                            ")(?<gn2>" + toSupplementaries("c") + "*)",
3624                           toSupplementaries("abccczzzabcczzzabccc"),
3625                           "${gn1}",
3626                           toSupplementaries("abzzzabcczzzabccc"));
3627 
3628 
3629         checkReplaceAll("(?<gn1>" + toSupplementaries("ab") +
3630                         ")(?<gn2>" + toSupplementaries("c") + "*)",
3631                         toSupplementaries("abccczzzabcczzzabccc"),
3632                         "${gn1}",
3633                         toSupplementaries("abzzzabzzzab"));
3634 
3635         checkReplaceFirst("(?<gn1>" + toSupplementaries("ab") +
3636                            ")(?<gn2>" + toSupplementaries("c") + "*)",
3637                           toSupplementaries("abccczzzabcczzzabccc"),
3638                           "${gn2}",
3639                           toSupplementaries("ccczzzabcczzzabccc"));
3640 
3641 
3642         checkReplaceAll("(?<gn1>" + toSupplementaries("ab") +
3643                         ")(?<gn2>" + toSupplementaries("c") + "*)",
3644                         toSupplementaries("abccczzzabcczzzabccc"),
3645                         "${gn2}",
3646                         toSupplementaries("ccczzzcczzzccc"));
3647 
3648         checkReplaceFirst("(?<dog>Dog)AndCat",
3649                           "zzzDogAndCatzzzDogAndCatzzz",
3650                           "${dog}",
3651                           "zzzDogzzzDogAndCatzzz");
3652 
3653 
3654         checkReplaceAll("(?<dog>Dog)AndCat",
3655                           "zzzDogAndCatzzzDogAndCatzzz",
3656                           "${dog}",
3657                           "zzzDogzzzDogzzz");
3658 
3659         // backref in Matcher & String
3660         if (!"abcdefghij".replaceFirst("cd(?<gn>ef)gh", "${gn}").equals("abefij") ||
3661             !"abbbcbdbefgh".replaceAll("(?<gn>[a-e])b", "${gn}").equals("abcdefgh"))
3662             failCount++;
3663 
3664         // negative
3665         checkExpectedFail("(?<groupnamehasnoascii.in>abc)(def)");
3666         checkExpectedFail("(?<groupnamehasnoascii_in>abc)(def)");
3667         checkExpectedFail("(?<6groupnamestartswithdigit>abc)(def)");
3668         checkExpectedFail("(?<gname>abc)(def)\\k<gnameX>");
3669         checkExpectedFail("(?<gname>abc)(?<gname>def)\\k<gnameX>");
3670         checkExpectedIAE(Pattern.compile("(?<gname>abc)(def)").matcher("abcdef"),
3671                          "gnameX");
3672         checkExpectedNPE(Pattern.compile("(?<gname>abc)(def)").matcher("abcdef"));
3673         report("NamedGroupCapture");
3674     }
3675 
3676     // This is for bug 6969132
3677     private static void nonBmpClassComplementTest() throws Exception {
3678         Pattern p = Pattern.compile("\\P{Lu}");
3679         Matcher m = p.matcher(new String(new int[] {0x1d400}, 0, 1));
3680         if (m.find() && m.start() == 1)
3681             failCount++;
3682 
3683         // from a unicode category
3684         p = Pattern.compile("\\P{Lu}");
3685         m = p.matcher(new String(new int[] {0x1d400}, 0, 1));
3686         if (m.find())
3687             failCount++;
3688         if (!m.hitEnd())
3689             failCount++;
3690 
3691         // block
3692         p = Pattern.compile("\\P{InMathematicalAlphanumericSymbols}");
3693         m = p.matcher(new String(new int[] {0x1d400}, 0, 1));
3694         if (m.find() && m.start() == 1)
3695             failCount++;
3696 
3697         report("NonBmpClassComplement");
3698     }
3699 
3700     private static void unicodePropertiesTest() throws Exception {
3701         // different forms
3702         if (!Pattern.compile("\\p{IsLu}").matcher("A").matches() ||
3703             !Pattern.compile("\\p{Lu}").matcher("A").matches() ||
3704             !Pattern.compile("\\p{gc=Lu}").matcher("A").matches() ||
3705             !Pattern.compile("\\p{general_category=Lu}").matcher("A").matches() ||
3706             !Pattern.compile("\\p{IsLatin}").matcher("B").matches() ||
3707             !Pattern.compile("\\p{sc=Latin}").matcher("B").matches() ||
3708             !Pattern.compile("\\p{script=Latin}").matcher("B").matches() ||
3709             !Pattern.compile("\\p{InBasicLatin}").matcher("c").matches() ||
3710             !Pattern.compile("\\p{blk=BasicLatin}").matcher("c").matches() ||
3711             !Pattern.compile("\\p{block=BasicLatin}").matcher("c").matches())
3712             failCount++;
3713 
3714         Matcher common  = Pattern.compile("\\p{script=Common}").matcher("");
3715         Matcher unknown = Pattern.compile("\\p{IsUnknown}").matcher("");
3716         Matcher lastSM  = common;
3717         Character.UnicodeScript lastScript = Character.UnicodeScript.of(0);
3718 
3719         Matcher latin  = Pattern.compile("\\p{block=basic_latin}").matcher("");
3720         Matcher greek  = Pattern.compile("\\p{InGreek}").matcher("");
3721         Matcher lastBM = latin;
3722         Character.UnicodeBlock lastBlock = Character.UnicodeBlock.of(0);
3723 
3724         for (int cp = 1; cp < Character.MAX_CODE_POINT; cp++) {
3725             if (cp >= 0x30000 && (cp & 0x70) == 0){
3726                 continue;  // only pick couple code points, they are the same
3727             }
3728 
3729             // Unicode Script
3730             Character.UnicodeScript script = Character.UnicodeScript.of(cp);
3731             Matcher m;
3732             String str = new String(Character.toChars(cp));
3733             if (script == lastScript) {
3734                  m = lastSM;
3735                  m.reset(str);
3736             } else {
3737                  m  = Pattern.compile("\\p{Is" + script.name() + "}").matcher(str);
3738             }
3739             if (!m.matches()) {
3740                 failCount++;
3741             }
3742             Matcher other = (script == Character.UnicodeScript.COMMON)? unknown : common;
3743             other.reset(str);
3744             if (other.matches()) {
3745                 failCount++;
3746             }
3747             lastSM = m;
3748             lastScript = script;
3749 
3750             // Unicode Block
3751             Character.UnicodeBlock block = Character.UnicodeBlock.of(cp);
3752             if (block == null) {
3753                 //System.out.printf("Not a Block: cp=%x%n", cp);
3754                 continue;
3755             }
3756             if (block == lastBlock) {
3757                  m = lastBM;
3758                  m.reset(str);
3759             } else {
3760                  m  = Pattern.compile("\\p{block=" + block.toString() + "}").matcher(str);
3761             }
3762             if (!m.matches()) {
3763                 failCount++;
3764             }
3765             other = (block == Character.UnicodeBlock.BASIC_LATIN)? greek : latin;
3766             other.reset(str);
3767             if (other.matches()) {
3768                 failCount++;
3769             }
3770             lastBM = m;
3771             lastBlock = block;
3772         }
3773         report("unicodeProperties");
3774     }
3775 
3776     private static void unicodeHexNotationTest() throws Exception {
3777 
3778         // negative
3779         checkExpectedFail("\\x{-23}");
3780         checkExpectedFail("\\x{110000}");
3781         checkExpectedFail("\\x{}");
3782         checkExpectedFail("\\x{AB[ef]");
3783 
3784         // codepoint
3785         check("^\\x{1033c}$",              "\uD800\uDF3C", true);
3786         check("^\\xF0\\x90\\x8C\\xBC$",    "\uD800\uDF3C", false);
3787         check("^\\x{D800}\\x{DF3c}+$",     "\uD800\uDF3C", false);
3788         check("^\\xF0\\x90\\x8C\\xBC$",    "\uD800\uDF3C", false);
3789 
3790         // in class
3791         check("^[\\x{D800}\\x{DF3c}]+$",   "\uD800\uDF3C", false);
3792         check("^[\\xF0\\x90\\x8C\\xBC]+$", "\uD800\uDF3C", false);
3793         check("^[\\x{D800}\\x{DF3C}]+$",   "\uD800\uDF3C", false);
3794         check("^[\\x{DF3C}\\x{D800}]+$",   "\uD800\uDF3C", false);
3795         check("^[\\x{D800}\\x{DF3C}]+$",   "\uDF3C\uD800", true);
3796         check("^[\\x{DF3C}\\x{D800}]+$",   "\uDF3C\uD800", true);
3797 
3798         for (int cp = 0; cp <= 0x10FFFF; cp++) {
3799              String s = "A" + new String(Character.toChars(cp)) + "B";
3800              String hexUTF16 = (cp <= 0xFFFF)? String.format("\\u%04x", cp)
3801                                              : String.format("\\u%04x\\u%04x",
3802                                                (int) Character.toChars(cp)[0],
3803                                                (int) Character.toChars(cp)[1]);
3804              String hexCodePoint = "\\x{" + Integer.toHexString(cp) + "}";
3805              if (!Pattern.matches("A" + hexUTF16 + "B", s))
3806                  failCount++;
3807              if (!Pattern.matches("A[" + hexUTF16 + "]B", s))
3808                  failCount++;
3809              if (!Pattern.matches("A" + hexCodePoint + "B", s))
3810                  failCount++;
3811              if (!Pattern.matches("A[" + hexCodePoint + "]B", s))
3812                  failCount++;
3813          }
3814          report("unicodeHexNotation");
3815     }
3816 
3817     private static void unicodeClassesTest() throws Exception {
3818 
3819         Matcher lower  = Pattern.compile("\\p{Lower}").matcher("");
3820         Matcher upper  = Pattern.compile("\\p{Upper}").matcher("");
3821         Matcher ASCII  = Pattern.compile("\\p{ASCII}").matcher("");
3822         Matcher alpha  = Pattern.compile("\\p{Alpha}").matcher("");
3823         Matcher digit  = Pattern.compile("\\p{Digit}").matcher("");
3824         Matcher alnum  = Pattern.compile("\\p{Alnum}").matcher("");
3825         Matcher punct  = Pattern.compile("\\p{Punct}").matcher("");
3826         Matcher graph  = Pattern.compile("\\p{Graph}").matcher("");
3827         Matcher print  = Pattern.compile("\\p{Print}").matcher("");
3828         Matcher blank  = Pattern.compile("\\p{Blank}").matcher("");
3829         Matcher cntrl  = Pattern.compile("\\p{Cntrl}").matcher("");
3830         Matcher xdigit = Pattern.compile("\\p{XDigit}").matcher("");
3831         Matcher space  = Pattern.compile("\\p{Space}").matcher("");
3832         Matcher bound  = Pattern.compile("\\b").matcher("");
3833         Matcher word   = Pattern.compile("\\w++").matcher("");
3834         // UNICODE_CHARACTER_CLASS
3835         Matcher lowerU  = Pattern.compile("\\p{Lower}", Pattern.UNICODE_CHARACTER_CLASS).matcher("");
3836         Matcher upperU  = Pattern.compile("\\p{Upper}", Pattern.UNICODE_CHARACTER_CLASS).matcher("");
3837         Matcher ASCIIU  = Pattern.compile("\\p{ASCII}", Pattern.UNICODE_CHARACTER_CLASS).matcher("");
3838         Matcher alphaU  = Pattern.compile("\\p{Alpha}", Pattern.UNICODE_CHARACTER_CLASS).matcher("");
3839         Matcher digitU  = Pattern.compile("\\p{Digit}", Pattern.UNICODE_CHARACTER_CLASS).matcher("");
3840         Matcher alnumU  = Pattern.compile("\\p{Alnum}", Pattern.UNICODE_CHARACTER_CLASS).matcher("");
3841         Matcher punctU  = Pattern.compile("\\p{Punct}", Pattern.UNICODE_CHARACTER_CLASS).matcher("");
3842         Matcher graphU  = Pattern.compile("\\p{Graph}", Pattern.UNICODE_CHARACTER_CLASS).matcher("");
3843         Matcher printU  = Pattern.compile("\\p{Print}", Pattern.UNICODE_CHARACTER_CLASS).matcher("");
3844         Matcher blankU  = Pattern.compile("\\p{Blank}", Pattern.UNICODE_CHARACTER_CLASS).matcher("");
3845         Matcher cntrlU  = Pattern.compile("\\p{Cntrl}", Pattern.UNICODE_CHARACTER_CLASS).matcher("");
3846         Matcher xdigitU = Pattern.compile("\\p{XDigit}", Pattern.UNICODE_CHARACTER_CLASS).matcher("");
3847         Matcher spaceU  = Pattern.compile("\\p{Space}", Pattern.UNICODE_CHARACTER_CLASS).matcher("");
3848         Matcher boundU  = Pattern.compile("\\b", Pattern.UNICODE_CHARACTER_CLASS).matcher("");
3849         Matcher wordU   = Pattern.compile("\\w", Pattern.UNICODE_CHARACTER_CLASS).matcher("");
3850         // embedded flag (?U)
3851         Matcher lowerEU  = Pattern.compile("(?U)\\p{Lower}", Pattern.UNICODE_CHARACTER_CLASS).matcher("");
3852         Matcher graphEU  = Pattern.compile("(?U)\\p{Graph}", Pattern.UNICODE_CHARACTER_CLASS).matcher("");
3853         Matcher wordEU   = Pattern.compile("(?U)\\w", Pattern.UNICODE_CHARACTER_CLASS).matcher("");
3854 
3855         Matcher bwb    = Pattern.compile("\\b\\w\\b").matcher("");
3856         Matcher bwbU   = Pattern.compile("\\b\\w++\\b", Pattern.UNICODE_CHARACTER_CLASS).matcher("");
3857         Matcher bwbEU  = Pattern.compile("(?U)\\b\\w++\\b", Pattern.UNICODE_CHARACTER_CLASS).matcher("");
3858         // properties
3859         Matcher lowerP  = Pattern.compile("\\p{IsLowerCase}").matcher("");
3860         Matcher upperP  = Pattern.compile("\\p{IsUpperCase}").matcher("");
3861         Matcher titleP  = Pattern.compile("\\p{IsTitleCase}").matcher("");
3862         Matcher letterP = Pattern.compile("\\p{IsLetter}").matcher("");
3863         Matcher alphaP  = Pattern.compile("\\p{IsAlphabetic}").matcher("");
3864         Matcher ideogP  = Pattern.compile("\\p{IsIdeographic}").matcher("");
3865         Matcher cntrlP  = Pattern.compile("\\p{IsControl}").matcher("");
3866         Matcher spaceP  = Pattern.compile("\\p{IsWhiteSpace}").matcher("");
3867         Matcher definedP = Pattern.compile("\\p{IsAssigned}").matcher("");
3868         Matcher nonCCPP = Pattern.compile("\\p{IsNoncharacterCodePoint}").matcher("");
3869         Matcher joinCrtl = Pattern.compile("\\p{IsJoinControl}").matcher("");
3870 
3871         // javaMethod
3872         Matcher lowerJ  = Pattern.compile("\\p{javaLowerCase}").matcher("");
3873         Matcher upperJ  = Pattern.compile("\\p{javaUpperCase}").matcher("");
3874         Matcher alphaJ  = Pattern.compile("\\p{javaAlphabetic}").matcher("");
3875         Matcher ideogJ  = Pattern.compile("\\p{javaIdeographic}").matcher("");
3876 
3877         for (int cp = 1; cp < 0x30000; cp++) {
3878             String str = new String(Character.toChars(cp));
3879             int type = Character.getType(cp);
3880             if (// lower
3881                 POSIX_ASCII.isLower(cp)   != lower.reset(str).matches()  ||
3882                 Character.isLowerCase(cp) != lowerU.reset(str).matches() ||
3883                 Character.isLowerCase(cp) != lowerP.reset(str).matches() ||
3884                 Character.isLowerCase(cp) != lowerEU.reset(str).matches()||
3885                 Character.isLowerCase(cp) != lowerJ.reset(str).matches()||
3886                 // upper
3887                 POSIX_ASCII.isUpper(cp)   != upper.reset(str).matches()  ||
3888                 POSIX_Unicode.isUpper(cp) != upperU.reset(str).matches() ||
3889                 Character.isUpperCase(cp) != upperP.reset(str).matches() ||
3890                 Character.isUpperCase(cp) != upperJ.reset(str).matches() ||
3891                 // alpha
3892                 POSIX_ASCII.isAlpha(cp)   != alpha.reset(str).matches()  ||
3893                 POSIX_Unicode.isAlpha(cp) != alphaU.reset(str).matches() ||
3894                 Character.isAlphabetic(cp)!= alphaP.reset(str).matches() ||
3895                 Character.isAlphabetic(cp)!= alphaJ.reset(str).matches() ||
3896                 // digit
3897                 POSIX_ASCII.isDigit(cp)   != digit.reset(str).matches()  ||
3898                 Character.isDigit(cp)     != digitU.reset(str).matches() ||
3899                 // alnum
3900                 POSIX_ASCII.isAlnum(cp)   != alnum.reset(str).matches()  ||
3901                 POSIX_Unicode.isAlnum(cp) != alnumU.reset(str).matches() ||
3902                 // punct
3903                 POSIX_ASCII.isPunct(cp)   != punct.reset(str).matches()  ||
3904                 POSIX_Unicode.isPunct(cp) != punctU.reset(str).matches() ||
3905                 // graph
3906                 POSIX_ASCII.isGraph(cp)   != graph.reset(str).matches()  ||
3907                 POSIX_Unicode.isGraph(cp) != graphU.reset(str).matches() ||
3908                 POSIX_Unicode.isGraph(cp) != graphEU.reset(str).matches()||
3909                 // blank
3910                 POSIX_ASCII.isType(cp, POSIX_ASCII.BLANK)
3911                                           != blank.reset(str).matches()  ||
3912                 POSIX_Unicode.isBlank(cp) != blankU.reset(str).matches() ||
3913                 // print
3914                 POSIX_ASCII.isPrint(cp)   != print.reset(str).matches()  ||
3915                 POSIX_Unicode.isPrint(cp) != printU.reset(str).matches() ||
3916                 // cntrl
3917                 POSIX_ASCII.isCntrl(cp)   != cntrl.reset(str).matches()  ||
3918                 POSIX_Unicode.isCntrl(cp) != cntrlU.reset(str).matches() ||
3919                 (Character.CONTROL == type) != cntrlP.reset(str).matches() ||
3920                 // hexdigit
3921                 POSIX_ASCII.isHexDigit(cp)   != xdigit.reset(str).matches()  ||
3922                 POSIX_Unicode.isHexDigit(cp) != xdigitU.reset(str).matches() ||
3923                 // space
3924                 POSIX_ASCII.isSpace(cp)   != space.reset(str).matches()  ||
3925                 POSIX_Unicode.isSpace(cp) != spaceU.reset(str).matches() ||
3926                 POSIX_Unicode.isSpace(cp) != spaceP.reset(str).matches() ||
3927                 // word
3928                 POSIX_ASCII.isWord(cp)   != word.reset(str).matches()  ||
3929                 POSIX_Unicode.isWord(cp) != wordU.reset(str).matches() ||
3930                 POSIX_Unicode.isWord(cp) != wordEU.reset(str).matches()||
3931                 // bwordb
3932                 POSIX_ASCII.isWord(cp) != bwb.reset(str).matches() ||
3933                 POSIX_Unicode.isWord(cp) != bwbU.reset(str).matches() ||
3934                 // properties
3935                 Character.isTitleCase(cp) != titleP.reset(str).matches() ||
3936                 Character.isLetter(cp)    != letterP.reset(str).matches()||
3937                 Character.isIdeographic(cp) != ideogP.reset(str).matches() ||
3938                 Character.isIdeographic(cp) != ideogJ.reset(str).matches() ||
3939                 (Character.UNASSIGNED == type) == definedP.reset(str).matches() ||
3940                 POSIX_Unicode.isNoncharacterCodePoint(cp) != nonCCPP.reset(str).matches() ||
3941                 POSIX_Unicode.isJoinControl(cp) != joinCrtl.reset(str).matches())
3942                 failCount++;
3943         }
3944 
3945         // bounds/word align
3946         twoFindIndexes(" \u0180sherman\u0400 ", bound, 1, 10);
3947         if (!bwbU.reset("\u0180sherman\u0400").matches())
3948             failCount++;
3949         twoFindIndexes(" \u0180sh\u0345erman\u0400 ", bound, 1, 11);
3950         if (!bwbU.reset("\u0180sh\u0345erman\u0400").matches())
3951             failCount++;
3952         twoFindIndexes(" \u0724\u0739\u0724 ", bound, 1, 4);
3953         if (!bwbU.reset("\u0724\u0739\u0724").matches())
3954             failCount++;
3955         if (!bwbEU.reset("\u0724\u0739\u0724").matches())
3956             failCount++;
3957         report("unicodePredefinedClasses");
3958     }
3959 
3960     private static void horizontalAndVerticalWSTest() throws Exception {
3961         String hws = new String (new char[] {
3962                                      0x09, 0x20, 0xa0, 0x1680, 0x180e,
3963                                      0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005,
3964                                      0x2006, 0x2007, 0x2008, 0x2009, 0x200a,
3965                                      0x202f, 0x205f, 0x3000 });
3966         String vws = new String (new char[] {
3967                                      0x0a, 0x0b, 0x0c, 0x0d, 0x85, 0x2028, 0x2029 });
3968         if (!Pattern.compile("\\h+").matcher(hws).matches() ||
3969             !Pattern.compile("[\\h]+").matcher(hws).matches())
3970             failCount++;
3971         if (Pattern.compile("\\H").matcher(hws).find() ||
3972             Pattern.compile("[\\H]").matcher(hws).find())
3973             failCount++;
3974         if (!Pattern.compile("\\v+").matcher(vws).matches() ||
3975             !Pattern.compile("[\\v]+").matcher(vws).matches())
3976             failCount++;
3977         if (Pattern.compile("\\V").matcher(vws).find() ||
3978             Pattern.compile("[\\V]").matcher(vws).find())
3979             failCount++;
3980         String prefix = "abcd";
3981         String suffix = "efgh";
3982         String ng = "A";
3983         for (int i = 0; i < hws.length(); i++) {
3984             String c = String.valueOf(hws.charAt(i));
3985             Matcher m = Pattern.compile("\\h").matcher(prefix + c + suffix);
3986             if (!m.find() || !c.equals(m.group()))
3987                 failCount++;
3988             m = Pattern.compile("[\\h]").matcher(prefix + c + suffix);
3989             if (!m.find() || !c.equals(m.group()))
3990                 failCount++;
3991 
3992             m = Pattern.compile("\\H").matcher(hws.substring(0, i) + ng + hws.substring(i));
3993             if (!m.find() || !ng.equals(m.group()))
3994                 failCount++;
3995             m = Pattern.compile("[\\H]").matcher(hws.substring(0, i) + ng + hws.substring(i));
3996             if (!m.find() || !ng.equals(m.group()))
3997                 failCount++;
3998         }
3999         for (int i = 0; i < vws.length(); i++) {
4000             String c = String.valueOf(vws.charAt(i));
4001             Matcher m = Pattern.compile("\\v").matcher(prefix + c + suffix);
4002             if (!m.find() || !c.equals(m.group()))
4003                 failCount++;
4004             m = Pattern.compile("[\\v]").matcher(prefix + c + suffix);
4005             if (!m.find() || !c.equals(m.group()))
4006                 failCount++;
4007 
4008             m = Pattern.compile("\\V").matcher(vws.substring(0, i) + ng + vws.substring(i));
4009             if (!m.find() || !ng.equals(m.group()))
4010                 failCount++;
4011             m = Pattern.compile("[\\V]").matcher(vws.substring(0, i) + ng + vws.substring(i));
4012             if (!m.find() || !ng.equals(m.group()))
4013                 failCount++;
4014         }
4015         // \v in range is interpreted as 0x0B. This is the undocumented behavior
4016         if (!Pattern.compile("[\\v-\\v]").matcher(String.valueOf((char)0x0B)).matches())
4017             failCount++;
4018         report("horizontalAndVerticalWSTest");
4019     }
4020 
4021     private static void linebreakTest() throws Exception {
4022         String linebreaks = new String (new char[] {
4023             0x0A, 0x0B, 0x0C, 0x0D, 0x85, 0x2028, 0x2029 });
4024         String crnl = "\r\n";
4025         if (!Pattern.compile("\\R+").matcher(linebreaks).matches() ||
4026             !Pattern.compile("\\R").matcher(crnl).matches() ||
4027             Pattern.compile("\\R\\R").matcher(crnl).matches())
4028             failCount++;
4029         report("linebreakTest");
4030     }
4031 
4032     // #7189363
4033     private static void branchTest() throws Exception {
4034         if (!Pattern.compile("(a)?bc|d").matcher("d").find() ||     // greedy
4035             !Pattern.compile("(a)+bc|d").matcher("d").find() ||
4036             !Pattern.compile("(a)*bc|d").matcher("d").find() ||
4037             !Pattern.compile("(a)??bc|d").matcher("d").find() ||    // reluctant
4038             !Pattern.compile("(a)+?bc|d").matcher("d").find() ||
4039             !Pattern.compile("(a)*?bc|d").matcher("d").find() ||
4040             !Pattern.compile("(a)?+bc|d").matcher("d").find() ||    // possessive
4041             !Pattern.compile("(a)++bc|d").matcher("d").find() ||
4042             !Pattern.compile("(a)*+bc|d").matcher("d").find() ||
4043             !Pattern.compile("(a)?bc|d").matcher("d").matches() ||  // greedy
4044             !Pattern.compile("(a)+bc|d").matcher("d").matches() ||
4045             !Pattern.compile("(a)*bc|d").matcher("d").matches() ||
4046             !Pattern.compile("(a)??bc|d").matcher("d").matches() || // reluctant
4047             !Pattern.compile("(a)+?bc|d").matcher("d").matches() ||
4048             !Pattern.compile("(a)*?bc|d").matcher("d").matches() ||
4049             !Pattern.compile("(a)?+bc|d").matcher("d").matches() || // possessive
4050             !Pattern.compile("(a)++bc|d").matcher("d").matches() ||
4051             !Pattern.compile("(a)*+bc|d").matcher("d").matches() ||
4052             !Pattern.compile("(a)?bc|de").matcher("de").find() ||   // others
4053             !Pattern.compile("(a)??bc|de").matcher("de").find() ||
4054             !Pattern.compile("(a)?bc|de").matcher("de").matches() ||
4055             !Pattern.compile("(a)??bc|de").matcher("de").matches())
4056             failCount++;
4057         report("branchTest");
4058     }
4059 
4060     // This test is for 8007395
4061     private static void groupCurlyNotFoundSuppTest() throws Exception {
4062         String input = "test this as \ud83d\ude0d";
4063         for (String pStr : new String[] { "test(.)+(@[a-zA-Z.]+)",
4064                                           "test(.)*(@[a-zA-Z.]+)",
4065                                           "test([^B])+(@[a-zA-Z.]+)",
4066                                           "test([^B])*(@[a-zA-Z.]+)",
4067                                           "test(\\P{IsControl})+(@[a-zA-Z.]+)",
4068                                           "test(\\P{IsControl})*(@[a-zA-Z.]+)",
4069                                         }) {
4070             Matcher m = Pattern.compile(pStr, Pattern.CASE_INSENSITIVE)
4071                                .matcher(input);
4072             try {
4073                 if (m.find()) {
4074                     failCount++;
4075                 }
4076             } catch (Exception x) {
4077                 failCount++;
4078             }
4079         }
4080         report("GroupCurly NotFoundSupp");
4081     }
4082 
4083     // This test is for 8023647
4084     private static void groupCurlyBackoffTest() throws Exception {
4085         if (!"abc1c".matches("(\\w)+1\\1") ||
4086             "abc11".matches("(\\w)+1\\1")) {
4087             failCount++;
4088         }
4089         report("GroupCurly backoff");
4090     }
4091 
4092     // This test is for 8012646
4093     private static void patternAsPredicate() throws Exception {
4094         Predicate<String> p = Pattern.compile("[a-z]+").asPredicate();
4095 
4096         if (p.test("")) {
4097             failCount++;
4098         }
4099         if (!p.test("word")) {
4100             failCount++;
4101         }
4102         if (p.test("1234")) {
4103             failCount++;
4104         }
4105         report("Pattern.asPredicate");
4106     }
4107 }