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