1 /*
   2  * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  * @test
  26  * @bug 4313885 4926319 4927634 5032610 5032622 5049968 5059533 6223711 6277261 6269946 6288823
  27  *      8072722 8139414 8166261
  28  * @summary Basic tests of java.util.Scanner methods
  29  * @key randomness
  30  * @modules jdk.localedata
  31  * @run main/othervm ScanTest
  32  */
  33 
  34 import java.io.*;
  35 import java.math.*;
  36 import java.nio.*;
  37 import java.text.*;
  38 import java.util.*;
  39 import java.util.function.BiConsumer;
  40 import java.util.function.Consumer;
  41 import java.util.regex.*;
  42 import java.util.stream.*;
  43 
  44 public class ScanTest {
  45 
  46     private static boolean failure = false;
  47     private static int failCount = 0;
  48     private static int NUM_SOURCE_TYPES = 2;
  49     private static File inputFile = new File(System.getProperty("test.src", "."), "input.txt");
  50 
  51     public static void main(String[] args) throws Exception {
  52         final List<Locale> supportedLocales = List.of(
  53                 Locale.US,
  54                 Locale.UK,
  55                 Locale.CHINA,
  56                 Locale.KOREA,
  57                 Locale.JAPAN,
  58                 Locale.GERMANY);
  59         Locale defaultLocale = Locale.getDefault();
  60         try {
  61             if (!supportedLocales.contains(defaultLocale)) {
  62                 //Before we have resource to improve the test to be ready for
  63                 //arbitrary locale, force the default locale to be "English"
  64                 //for now. First we check whether the "English" locale is
  65                 //available on the system as it could be absent due to varying
  66                 //configurations.
  67                 System.out.println("Default locale " + defaultLocale +
  68                         " is not supported in this test, trying to change to ENGLISH.");
  69                 if (!Arrays.asList(Locale.getAvailableLocales())
  70                     .contains(Locale.ENGLISH)) {
  71                     throw new RuntimeException
  72                        ("The \"English\" Locale is unavailable on this system");
  73                 }
  74                 Locale.setDefault(Locale.ENGLISH);
  75             }
  76             skipTest();
  77             findInLineTest();
  78             findWithinHorizonTest();
  79             findInEmptyLineTest();
  80             removeTest();
  81             fromFileTest();
  82             ioExceptionTest();
  83             matchTest();
  84             delimiterTest();
  85             boundaryDelimTest();
  86             useLocaleTest();
  87             closeTest();
  88             cacheTest();
  89             cacheTest2();
  90             nonASCIITest();
  91             resetTest();
  92             streamCloseTest();
  93             streamComodTest();
  94             outOfRangeRadixTest();
  95 
  96             for (int j = 0; j < NUM_SOURCE_TYPES; j++) {
  97                 hasNextTest(j);
  98                 nextTest(j);
  99                 hasNextPatternTest(j);
 100                 nextPatternTest(j);
 101                 booleanTest(j);
 102                 byteTest(j);
 103                 shortTest(j);
 104                 intTest(j);
 105                 longTest(j);
 106                 floatTest(j);
 107                 doubleTest(j);
 108                 integerPatternTest(j);
 109                 floatPatternTest(j);
 110                 bigIntegerPatternTest(j);
 111                 bigDecimalPatternTest(j);
 112                 hasNextLineTest(j);
 113                 nextLineTest(j);
 114                 singleDelimTest(j);
 115             }
 116 
 117             // Examples
 118             //example1();
 119             //example2();
 120             //example3();
 121 
 122             // Usage cases
 123             useCase1();
 124             useCase2();
 125             useCase3();
 126             useCase4();
 127             useCase5();
 128 
 129             if (failure)
 130                 throw new RuntimeException("Failure in the scanning tests.");
 131             else
 132                 System.err.println("OKAY: All tests passed.");
 133         } finally {
 134             // restore the default locale
 135             Locale.setDefault(defaultLocale);
 136         }
 137     }
 138 
 139     public static void useCase1() throws Exception {
 140         try (Scanner sc = new Scanner(inputFile)) {
 141             sc.findWithinHorizon("usage case 1", 0);
 142             String[] names = new String[4];
 143             for (int i=0; i<4; i++) {
 144                 while (sc.hasNextFloat())
 145                     sc.nextFloat();
 146                 names[i] = sc.next();
 147                 sc.nextLine();
 148             }
 149             if (!names[0].equals("Frank"))
 150                 failCount++;
 151             if (!names[1].equals("Joe"))
 152                 failCount++;
 153             if (!names[2].equals("Mary"))
 154                 failCount++;
 155             if (!names[3].equals("Michelle"))
 156                 failCount++;
 157         }
 158         report("Use case 1");
 159     }
 160 
 161     public static void useCase2() throws Exception {
 162         try (Scanner sc = new Scanner(inputFile).useDelimiter("-")) {
 163             String testDataTag = sc.findWithinHorizon("usage case 2\n", 0);
 164             if (!testDataTag.equals("usage case 2\n"))
 165                 failCount++;
 166             if (!sc.next().equals("cat"))
 167                 failCount++;
 168             if (sc.nextInt() != 9)
 169                 failCount++;
 170             if (!sc.next().equals("dog"))
 171                 failCount++;
 172             if (sc.nextInt() != 6)
 173                 failCount++;
 174             if (!sc.next().equals("pig"))
 175                 failCount++;
 176             if (sc.nextInt() != 2)
 177                 failCount++;
 178             if (!sc.next().equals(""))
 179                 failCount++;
 180             if (sc.nextInt() != 5)
 181                 failCount++;
 182         }
 183         report("Use case 2");
 184     }
 185 
 186     public static void useCase3() throws Exception {
 187         try (Scanner sc = new Scanner(inputFile)) {
 188             String testDataTag = sc.findWithinHorizon("usage case 3\n", 0);
 189             if (!testDataTag.equals("usage case 3\n"))
 190                 failCount++;
 191             Pattern tagPattern = Pattern.compile("@[a-z]+");
 192             Pattern endPattern = Pattern.compile("\\*\\/");
 193             String tag;
 194             String end = sc.findInLine(endPattern);
 195 
 196             while (end == null) {
 197                 if ((tag = sc.findInLine(tagPattern)) != null) {
 198                     String text = sc.nextLine();
 199                     text = text.substring(0, text.length() - 1);
 200                     //System.out.println(text);
 201                 } else {
 202                     sc.nextLine();
 203                 }
 204                 end = sc.findInLine(endPattern);
 205             }
 206         }
 207         report("Use case 3");
 208     }
 209 
 210     public static void useCase4() throws Exception {
 211         try (Scanner sc = new Scanner(inputFile)) {
 212             String testDataTag = sc.findWithinHorizon("usage case 4\n", 0);
 213             if (!testDataTag.equals("usage case 4\n"))
 214                 failCount++;
 215 
 216             // Read some text parts of four hrefs
 217             String[] expected = { "Diffs", "Sdiffs", "Old", "New" };
 218             for (int i=0; i<4; i++) {
 219                 sc.findWithinHorizon("<a href", 1000);
 220                 sc.useDelimiter("[<>\n]+");
 221                 sc.next();
 222                 String textOfRef = sc.next();
 223                 if (!textOfRef.equals(expected[i]))
 224                     failCount++;
 225             }
 226             // Read some html tags using < and > as delimiters
 227             if (!sc.next().equals("/a"))
 228                 failCount++;
 229             if (!sc.next().equals("b"))
 230                 failCount++;
 231 
 232             // Scan some html tags using skip and next
 233             Pattern nonTagStart = Pattern.compile("[^<]+");
 234             Pattern tag = Pattern.compile("<[^>]+?>");
 235             Pattern spotAfterTag = Pattern.compile("(?<=>)");
 236             String[] expected2 = { "</b>", "<p>", "<ul>", "<li>" };
 237             sc.useDelimiter(spotAfterTag);
 238             int tagsFound = 0;
 239             while (tagsFound < 4) {
 240                 if (!sc.hasNext(tag)) {
 241                     // skip text between tags
 242                     sc.skip(nonTagStart);
 243                 }
 244                 String tagContents = sc.next(tag);
 245                 if (!tagContents.equals(expected2[tagsFound]))
 246                     failCount++;
 247                 tagsFound++;
 248             }
 249         }
 250 
 251         report("Use case 4");
 252     }
 253 
 254     public static void useCase5() throws Exception {
 255         try (Scanner sc = new Scanner(inputFile)) {
 256             String testDataTag = sc.findWithinHorizon("usage case 5\n", 0);
 257             if (!testDataTag.equals("usage case 5\n"))
 258                 failCount++;
 259 
 260             sc.findWithinHorizon("Share Definitions", 0);
 261             sc.nextLine();
 262             sc.next("\\[([a-z]+)\\]");
 263             String shareName = sc.match().group(1);
 264             if (!shareName.equals("homes"))
 265                 failCount++;
 266 
 267             String[] keys = { "comment", "browseable", "writable", "valid users" };
 268             String[] vals = { "Home Directories", "no", "yes", "%S" };
 269             for (int i=0; i<4; i++) {
 270                 sc.useDelimiter("=");
 271                 String key = sc.next().trim();
 272                 if (!key.equals(keys[i]))
 273                     failCount++;
 274                 sc.skip("[ =]+");
 275                 sc.useDelimiter("\n");
 276                 String value = sc.next();
 277                 if (!value.equals(vals[i]))
 278                     failCount++;
 279                 sc.nextLine();
 280             }
 281         }
 282 
 283         report("Use case 5");
 284     }
 285 
 286     public static void nonASCIITest() throws Exception {
 287         String yourBasicTibetanNumberZero = "\u0f20";
 288         String yourBasicTibetanFloatingNumber = "\u0f23.\u0f27";
 289         String weirdMixtureOfTibetanAndASCII = "\u0f23.7";
 290         String weirdMixtureOfASCIIAndTibetan = "3.\u0f27";
 291         Scanner sc = new Scanner(yourBasicTibetanNumberZero);
 292         int i = sc.nextInt();
 293         if (i != 0)
 294             failCount++;
 295         sc = new Scanner(yourBasicTibetanFloatingNumber);
 296         float f = sc.nextFloat();
 297         if (f != Float.parseFloat("3.7"))
 298             failCount++;
 299         sc = new Scanner(weirdMixtureOfTibetanAndASCII);
 300         f = sc.nextFloat();
 301         if (f != Float.parseFloat("3.7"))
 302             failCount++;
 303         sc = new Scanner(weirdMixtureOfASCIIAndTibetan);
 304         f = sc.nextFloat();
 305         if (f != Float.parseFloat("3.7"))
 306             failCount++;
 307         report("Scanning non ASCII digits");
 308     }
 309 
 310     public static void findWithinHorizonTest() throws Exception {
 311         // Test with a string source
 312         Scanner sc = new Scanner("dog  cat     cat    dog     cat");
 313         try {
 314             sc.findWithinHorizon("dog", -1);
 315             failCount++;
 316         } catch (IllegalArgumentException iae) {
 317             // Correct result
 318         }
 319         if (sc.findWithinHorizon("dog", 2) != null)
 320             failCount++;
 321         if (!sc.findWithinHorizon("dog", 3).equals("dog"))
 322             failCount++;
 323         if (sc.findWithinHorizon("cat", 4) != null)
 324             failCount++;
 325         if (!sc.findWithinHorizon("cat", 5).equals("cat"))
 326             failCount++;
 327          if (sc.findWithinHorizon("cat", 7) != null)
 328             failCount++;
 329         if (sc.findWithinHorizon("dog", 7) != null)
 330             failCount++;
 331         if (!sc.findWithinHorizon("cat", 0).equals("cat"))
 332             failCount++;
 333         if (!sc.findWithinHorizon("dog", 0).equals("dog"))
 334             failCount++;
 335         if (!sc.findWithinHorizon("cat", 0).equals("cat"))
 336             failCount++;
 337 
 338         // Test with a stream source
 339         StutteringInputStream stutter = new StutteringInputStream();
 340         for (int index=0; index<stutter.length(); index++) {
 341             //System.out.println("index is now "+index);
 342             sc = new Scanner(stutter);
 343             String word = stutter.wordInIndex(index);
 344             if (word != null) {
 345                 String result = sc.findWithinHorizon(word, index);
 346                 if ((result == null) || (!result.equals(word)))
 347                     failCount++;
 348             }
 349             stutter.reset();
 350             word = stutter.wordBeyondIndex(index);
 351             sc = new Scanner(stutter);
 352             String result = sc.findWithinHorizon(word, index);
 353             if ((result != null) && (index > 0))
 354                 failCount++;
 355             stutter.reset();
 356         }
 357 
 358         // We must loop to let StutteringInputStream do its magic
 359         for (int j=0; j<10; j++) {
 360             // An anchor at the end of stream should work
 361             stutter.reset();
 362             sc = new Scanner(stutter);
 363             String result = sc.findWithinHorizon("phant$", 0);
 364             if (!result.equals("phant"))
 365                 failCount++;
 366             stutter.reset();
 367             sc = new Scanner(stutter);
 368             result = sc.findWithinHorizon("phant$", 54);
 369             if (!result.equals("phant"))
 370                 failCount++;
 371             // An anchor at the end of horizon should not
 372             stutter.reset();
 373             sc = new Scanner(stutter);
 374             result = sc.findWithinHorizon("brummer$", 7);
 375             if (result != null)
 376                 failCount++;
 377             // An anchor at start should work
 378             stutter.reset();
 379             sc = new Scanner(stutter);
 380             result = sc.findWithinHorizon("^brummer", 0);
 381             if (!result.equals("brummer"))
 382                 failCount++;
 383         }
 384 
 385         report("Find to horizon test");
 386     }
 387 
 388     // StutteringInputStream returns 1 to 3 characters at a time
 389     static class StutteringInputStream implements Readable {
 390         StutteringInputStream() {
 391             text = "brummer hisser tort zardzard rantrant caimagator phant";
 392             datalen = 54;
 393         }
 394         StutteringInputStream(String text) {
 395             this.text = text;
 396             datalen = text.length();
 397         }
 398         Random generator = new Random();
 399         String text;
 400         int datalen;
 401         int index = 0;
 402         public int length() {
 403             return datalen;
 404         }
 405         public void reset() {
 406             index = 0;
 407         }
 408         public String wordInIndex(int index) {
 409             if (index < 7)  return null;
 410             if (index < 14) return "brummer";
 411             if (index < 19) return "hisser";
 412             if (index < 28) return "tort";
 413             if (index < 37) return "zardzard";
 414             if (index < 48) return "rantrant";
 415             return "caimagator";
 416         }
 417         public String wordBeyondIndex(int index) {
 418             if (index < 7)  return "brummer";
 419             if (index < 14) return "hisser";
 420             if (index < 19) return "tort";
 421             if (index < 28) return "zardzard";
 422             if (index < 37) return "rantrant";
 423             if (index < 48) return "caimagator";
 424             return "phantphant";
 425         }
 426         public int read(java.nio.CharBuffer target) throws IOException {
 427             if (index > datalen-1)
 428                 return -1; // EOS
 429             int len = target.remaining();
 430             if (len > 4) // return 1 to 3 characters
 431                 len = generator.nextInt(3) + 1;
 432             while ((index + len) > datalen)
 433                 len--;
 434             for (int i=0; i<len; i++)
 435                 target.put(text.charAt(index++));
 436             return len;
 437         }
 438     }
 439 
 440     public static void hasNextLineTest(int sourceType) throws Exception {
 441         Scanner sc = scannerFor("1\n2\n3 3\r\n4 4 4\r5", sourceType);
 442         if (!sc.hasNextLine()) failCount++;
 443         if (!sc.nextLine().equals("1")) failCount++;
 444         if (!sc.hasNextLine()) failCount++;
 445         if (sc.nextInt() != 2) failCount++;
 446         if (!sc.hasNextLine()) failCount++;
 447         if (!sc.nextLine().equals("")) failCount++;
 448         if (!sc.hasNextLine()) failCount++;
 449         if (sc.nextInt() != 3) failCount++;
 450         if (!sc.hasNextLine()) failCount++;
 451         if (!sc.nextLine().equals(" 3")) failCount++;
 452         if (!sc.hasNextLine()) failCount++;
 453         if (sc.nextInt() != 4) failCount++;
 454         if (!sc.hasNextLine()) failCount++;
 455         if (sc.nextInt() != 4) failCount++;
 456         if (!sc.hasNextLine()) failCount++;
 457         if (!sc.nextLine().equals(" 4")) failCount++;
 458         if (!sc.hasNextLine()) failCount++;
 459         if (!sc.nextLine().equals("5")) failCount++;
 460         if (sc.hasNextLine()) failCount++;
 461         sc = new Scanner("blah blah blah blah blah blah");
 462         if (!sc.hasNextLine()) failCount++;
 463         if (!sc.nextLine().equals("blah blah blah blah blah blah"))
 464            failCount++;
 465         if (sc.hasNextLine()) failCount++;
 466 
 467         // Go through all the lines in a file
 468         try (Scanner sc2 = new Scanner(inputFile)) {
 469             String lastLine = "blah";
 470             while (sc2.hasNextLine())
 471                 lastLine = sc2.nextLine();
 472             if (!lastLine.equals("# Data for usage case 6")) failCount++;
 473         }
 474 
 475         report("Has next line test");
 476     }
 477 
 478     public static void nextLineTest(int sourceType) throws Exception {
 479         Scanner sc = scannerFor("1\n2\n3 3\r\n4 4 4\r5", sourceType);
 480         if (!sc.nextLine().equals("1"))
 481             failCount++;
 482         if (sc.nextInt() != 2)
 483             failCount++;
 484         if (!sc.nextLine().equals(""))
 485            failCount++;
 486         if (sc.nextInt() != 3)
 487             failCount++;
 488         if (!sc.nextLine().equals(" 3"))
 489            failCount++;
 490         if (sc.nextInt() != 4)
 491             failCount++;
 492         if (sc.nextInt() != 4)
 493             failCount++;
 494         if (!sc.nextLine().equals(" 4"))
 495            failCount++;
 496         if (!sc.nextLine().equals("5"))
 497            failCount++;
 498         sc = new Scanner("blah blah blah blah blah blah");
 499         if (!sc.nextLine().equals("blah blah blah blah blah blah"))
 500            failCount++;
 501         report("Next line test");
 502     }
 503 
 504     public static void singleDelimTest(int sourceType) throws Exception {
 505         Scanner sc = scannerFor("12 13  14   15    16     17      ",
 506                                 sourceType);
 507         sc.useDelimiter(" ");
 508         for (int i=0; i<6; i++) {
 509             int j = sc.nextInt();
 510             if (j != 12 + i)
 511                 failCount++;
 512             for (int k=0; k<i; k++) {
 513                 String empty = sc.next();
 514                 if (!empty.equals(""))
 515                     failCount++;
 516             }
 517         }
 518         report("Single delim test");
 519     }
 520 
 521     private static void append(StringBuilder sb, char c, int n) {
 522         for (int i = 0; i < n; i++) {
 523             sb.append(c);
 524         }
 525     }
 526 
 527     public static void boundaryDelimTest() throws Exception {
 528         // 8139414
 529         int i = 1019;
 530         StringBuilder sb = new StringBuilder();
 531         sb.append("--;");
 532         for (int j = 0; j < 1019; ++j) {
 533             sb.append(j%10);
 534         }
 535         sb.append("-;-");
 536         String text = sb.toString();
 537         try (Scanner scanner = new Scanner(text)) {
 538             scanner.useDelimiter("-;(-)?");
 539             while (scanner.hasNext()) {
 540                 scanner.next();
 541             }
 542         } catch (NoSuchElementException e) {
 543             System.out.println("Caught NoSuchElementException " + e);
 544             e.printStackTrace();
 545             failCount++;
 546         }
 547 
 548         report("delim at boundary test");
 549     }
 550 
 551     /*
 552      * The hasNextPattern caches a match of a pattern called the regular cache
 553      * The hasNextType caches a match of that type called the type cache
 554      * Any next must clear the caches whether it uses them or not, because
 555      * it advances past a token thus invalidating any cached token; any
 556      * hasNext must set a cache to what it finds.
 557      */
 558     public static void cacheTest() throws Exception {
 559         // Test clearing of the type cache
 560         Scanner scanner = new Scanner("777 dog");
 561         scanner.hasNextInt();
 562         scanner.findInLine("777");
 563         try {
 564             scanner.nextInt();
 565             System.out.println("type cache not cleared by find");
 566             failCount++;
 567         } catch (InputMismatchException ime) {
 568             // Correct
 569         }
 570 
 571         scanner = new Scanner("777 dog");
 572         scanner.hasNextInt();
 573         scanner.skip("777");
 574         try {
 575             scanner.nextInt();
 576             System.out.println("type cache not cleared by skip");
 577             failCount++;
 578         } catch (InputMismatchException ime) {
 579             // Correct
 580         }
 581 
 582         // Test clearing of the regular cache
 583         scanner = new Scanner("777 dog");
 584         scanner.hasNext("777");
 585         scanner.findInLine("777");
 586         try {
 587             scanner.next("777");
 588             System.out.println("regular cache not cleared by find");
 589             failCount++;
 590         } catch (InputMismatchException ime) {
 591             // Correct
 592         }
 593 
 594         // Test two primitive next clearing of type cache
 595         scanner = new Scanner("777 dog");
 596         scanner.hasNextInt();
 597         scanner.nextLong();
 598         try {
 599             scanner.nextInt();
 600             System.out.println("type cache not cleared by primitive next");
 601             failCount++;
 602         } catch (InputMismatchException ime) {
 603             // Correct
 604         }
 605 
 606         // Test using both of them, type first
 607         scanner = new Scanner("777 dog");
 608         scanner.hasNext("777");
 609         scanner.nextInt();
 610         try {
 611             scanner.next("777");
 612             System.out.println("regular cache not cleared by primitive next");
 613             failCount++;
 614         } catch (InputMismatchException ime) {
 615             // Correct
 616         }
 617 
 618         // Test using both of them, regular first
 619         scanner = new Scanner("777 dog");
 620         scanner.hasNext("777");
 621         scanner.hasNextInt();
 622         scanner.next("777");
 623         try {
 624             scanner.nextInt();
 625             System.out.println("type cache not cleared by regular next");
 626             failCount++;
 627         } catch (InputMismatchException ime) {
 628             // Correct
 629         }
 630         report("Cache test");
 631     }
 632 
 633     /*
 634      * The hasNext<IntegerType>(radix) method caches a matched integer type
 635      * with specified radix for the next next<IntegerType>(radix) invoke.
 636      * The cache value should not be used if the next<IntegerType>(radix)
 637      * has different radix value with the last hasNext<IntegerType>(radix).
 638      */
 639     public static void cacheTest2() throws Exception {
 640         // Test clearing of the type cache
 641         Scanner scanner = new Scanner("10");
 642         scanner.hasNextByte(16);
 643         if (scanner.nextByte(10) != 10) {
 644             System.out.println("wrong radix cache is used");
 645             failCount++;
 646         }
 647         scanner = new Scanner("10");
 648         scanner.hasNextShort(16);
 649         if (scanner.nextShort(10) != 10) {
 650             System.out.println("wrong radix cache is used");
 651             failCount++;
 652         }
 653         scanner = new Scanner("10");
 654         scanner.hasNextInt(16);
 655         if (scanner.nextInt(10) != 10) {
 656             System.out.println("wrong radix cache is used");
 657             failCount++;
 658         }
 659         scanner = new Scanner("10");
 660         scanner.hasNextLong(16);
 661         if (scanner.nextLong(10) != 10) {
 662             System.out.println("wrong radix cache is used");
 663             failCount++;
 664         }
 665         scanner = new Scanner("10");
 666         scanner.hasNextBigInteger(16);
 667         if (scanner.nextBigInteger(10).intValue() != 10) {
 668             System.out.println("wrong radix cache is used");
 669             failCount++;
 670         }
 671         report("Cache test2");
 672     }
 673 
 674 
 675     public static void closeTest() throws Exception {
 676         Scanner sc = new Scanner("testing");
 677         sc.close();
 678         sc.ioException();
 679         sc.delimiter();
 680         sc.useDelimiter("blah");
 681         sc.useDelimiter(Pattern.compile("blah"));
 682 
 683         for (Consumer<Scanner> method : methodList) {
 684             try {
 685                 method.accept(sc);
 686                 failCount++;
 687             } catch (IllegalStateException ise) {
 688                 // Correct
 689             }
 690         }
 691 
 692         report("Close test");
 693     }
 694 
 695     static List<Consumer<Scanner>> methodList = Arrays.asList(
 696         Scanner::hasNext,
 697         Scanner::next,
 698         sc -> sc.hasNext(Pattern.compile("blah")),
 699         sc -> sc.next(Pattern.compile("blah")),
 700         Scanner::hasNextBoolean,
 701         Scanner::nextBoolean,
 702         Scanner::hasNextByte,
 703         Scanner::nextByte,
 704         Scanner::hasNextShort,
 705         Scanner::nextShort,
 706         Scanner::hasNextInt,
 707         Scanner::nextInt,
 708         Scanner::hasNextLong,
 709         Scanner::nextLong,
 710         Scanner::hasNextFloat,
 711         Scanner::nextFloat,
 712         Scanner::hasNextDouble,
 713         Scanner::nextDouble,
 714         Scanner::hasNextBigInteger,
 715         Scanner::nextBigInteger,
 716         Scanner::hasNextBigDecimal,
 717         Scanner::nextBigDecimal,
 718         Scanner::hasNextLine,
 719         Scanner::tokens,
 720         sc -> sc.findAll(Pattern.compile("blah")),
 721         sc -> sc.findAll("blah")
 722     );
 723 
 724     public static void removeTest() throws Exception {
 725         Scanner sc = new Scanner("testing");
 726         try {
 727             sc.remove();
 728             failCount++;
 729         } catch (UnsupportedOperationException uoe) {
 730             // Correct result
 731         }
 732         report("Remove test");
 733     }
 734 
 735     public static void delimiterTest() throws Exception {
 736         Scanner sc = new Scanner("blah");
 737         Pattern test = sc.delimiter();
 738         if (!test.toString().equals("\\p{javaWhitespace}+"))
 739             failCount++;
 740         sc.useDelimiter("a");
 741         test = sc.delimiter();
 742         if (!test.toString().equals("a"))
 743             failCount++;
 744         sc.useDelimiter(Pattern.compile("b"));
 745         test = sc.delimiter();
 746         if (!test.toString().equals("b"))
 747             failCount++;
 748         report("Delimiter test");
 749     }
 750 
 751     public static void ioExceptionTest() throws Exception {
 752         Readable thrower = new ThrowingReadable();
 753         Scanner sc = new Scanner(thrower);
 754         try {
 755             sc.nextInt();
 756             failCount++;
 757         } catch (NoSuchElementException nsee) {
 758             // Correct result
 759         }
 760         Exception thrown = sc.ioException();
 761         String detail = thrown.getMessage();
 762         if (!detail.equals("ThrowingReadable always throws"))
 763             failCount++;
 764 
 765         report("IOException test");
 766     }
 767 
 768     public static void bigIntegerPatternTest(int sourceType) throws Exception {
 769         Scanner sc = scannerFor("23 9223372036854775817", sourceType);
 770         if (!sc.nextBigInteger().equals(BigInteger.valueOf(23)))
 771             failCount++;
 772         if (!sc.nextBigInteger().equals(new BigInteger(
 773             "9223372036854775817", 10)))
 774             failCount++;
 775 
 776         // Test another radix
 777         sc = new Scanner("4a4 4A4").useRadix(16);
 778         if (!sc.nextBigInteger().equals(new BigInteger("4a4", 16)))
 779             failCount++;
 780         if (!sc.nextBigInteger().equals(new BigInteger("4A4", 16)))
 781             failCount++;
 782 
 783         // Test alternating radices
 784         sc = new Scanner("12 4a4 14 4f4");
 785         if (!sc.nextBigInteger(10).equals(new BigInteger("12", 10)))
 786             failCount++;
 787         if (!sc.nextBigInteger(16).equals(new BigInteger("4a4", 16)))
 788             failCount++;
 789         if (!sc.nextBigInteger(10).equals(new BigInteger("14", 10)))
 790             failCount++;
 791         if (!sc.nextBigInteger(16).equals(new BigInteger("4f4", 16)))
 792             failCount++;
 793 
 794         // Test use of a lot of radices
 795         for (int i=2; i<17; i++) {
 796             sc = new Scanner("1111");
 797             if (!sc.nextBigInteger(i).equals(new BigInteger("1111", i)))
 798                 failCount++;
 799         }
 800 
 801         report("BigInteger pattern");
 802     }
 803 
 804     public static void bigDecimalPatternTest(int sourceType) throws Exception {
 805         Scanner sc = scannerFor("23 45.99 -45,067.444 3.4e10", sourceType);
 806         if (!sc.nextBigDecimal().equals(BigDecimal.valueOf(23)))
 807             failCount++;
 808         if (!sc.nextBigDecimal().equals(new BigDecimal("45.99")))
 809             failCount++;
 810         if (!sc.nextBigDecimal().equals(new BigDecimal("-45067.444")))
 811             failCount++;
 812         if (!sc.nextBigDecimal().equals(new BigDecimal("3.4e10")))
 813             failCount++;
 814         report("BigDecimal pattern");
 815     }
 816 
 817     public static void integerPatternTest(int sourceType) throws Exception {
 818         String input =
 819             "1 22 f FF Z -3 -44 123 1,200 -123 -3,400,000 5,40 ,500 ";
 820         Scanner sc = scannerFor(input, sourceType);
 821         integerPatternBody(sc);
 822         CharBuffer cb = CharBuffer.wrap(input);
 823         sc = new Scanner(cb);
 824         integerPatternBody(sc);
 825         report("Integer pattern");
 826     }
 827 
 828     public static void integerPatternBody(Scanner sc) throws Exception {
 829         if (sc.nextInt() != 1)        failCount++;
 830         if (sc.nextShort() != 22)     failCount++;
 831         if (sc.nextShort(16) != 15)   failCount++;
 832         if (sc.nextShort(16) != 255)  failCount++;
 833         if (sc.nextShort(36) != 35)   failCount++;
 834         if (!sc.hasNextInt())         failCount++;
 835         if (sc.nextInt() != -3)       failCount++;
 836         if (sc.nextInt() != -44)      failCount++;
 837         if (sc.nextLong() != 123)     failCount++;
 838         if (!sc.hasNextInt())         failCount++;
 839         if (sc.nextInt() != 1200)     failCount++;
 840         if (sc.nextInt() != -123)     failCount++;
 841         if (sc.nextInt() != -3400000) failCount++;
 842         try {
 843             sc.nextInt();
 844             failCount++;
 845         } catch (InputMismatchException ime) {
 846             // Correct result
 847         }
 848         sc.next();
 849         try {
 850             sc.nextLong();
 851             failCount++;
 852         } catch (InputMismatchException ime) {
 853             // Correct result
 854         }
 855         sc.next();
 856         try {
 857             sc.next();
 858             failCount++;
 859         } catch (InputMismatchException ime) {
 860             failCount++;
 861         } catch (NoSuchElementException nse) {
 862             // Correct result
 863         }
 864     }
 865 
 866     public static void floatPatternTest(int sourceType) throws Exception {
 867         String input =
 868             "090.090 1 22.0 -3 -44.05 +.123 -.1234 -3400000 56,566.6 " +
 869             "Infinity +Infinity -Infinity NaN -NaN +NaN 5.4.0 5-.00 ++6.07";
 870         Scanner sc = scannerFor(input, sourceType);
 871         floatPatternBody(sc);
 872         CharBuffer cb = CharBuffer.wrap(input);
 873         sc = new Scanner(cb);
 874         floatPatternBody(sc);
 875         report("Float pattern");
 876     }
 877 
 878     public static void floatPatternBody(Scanner sc) throws Exception {
 879         if (sc.nextFloat() != 090.090f)                   failCount++;
 880         if (sc.nextFloat() != 1f)                         failCount++;
 881         if (sc.nextFloat() != 22.0f)                      failCount++;
 882         if (sc.nextDouble() != -3d)                       failCount++;
 883         if (sc.nextDouble() != -44.05d)                   failCount++;
 884         if (sc.nextFloat() != .123f)                      failCount++;
 885         if (sc.nextFloat() != -.1234f)                    failCount++;
 886         if (sc.nextDouble() != -3400000d)                 failCount++;
 887         if (sc.nextDouble() != 56566.6d)                  failCount++;
 888         if (sc.nextDouble() != Double.POSITIVE_INFINITY)  failCount++;
 889         if (sc.nextDouble() != Double.POSITIVE_INFINITY)  failCount++;
 890         if (sc.nextDouble() != Double.NEGATIVE_INFINITY)  failCount++;
 891         if (!Double.valueOf(sc.nextDouble()).isNaN())     failCount++;
 892         if (!Double.valueOf(sc.nextDouble()).isNaN())     failCount++;
 893         if (!Double.valueOf(sc.nextDouble()).isNaN())     failCount++;
 894         try {
 895             sc.nextFloat();
 896             failCount++;
 897         } catch (NoSuchElementException nse) {
 898             // Correct result
 899         }
 900         try {
 901             sc.nextDouble();
 902             failCount++;
 903         } catch (NoSuchElementException nse) {
 904             // Correct result
 905         }
 906         try {
 907             sc.nextDouble();
 908             failCount++;
 909         } catch (NoSuchElementException nse) {
 910             // Correct result
 911         }
 912     }
 913 
 914     public static void fromFileTest() throws Exception {
 915         File f = new File(System.getProperty("test.src", "."), "input.txt");
 916         try (Scanner sc = new Scanner(f)) {
 917             sc.useDelimiter("\n+");
 918             String testDataTag = sc.findWithinHorizon("fromFileTest", 0);
 919             if (!testDataTag.equals("fromFileTest"))
 920                 failCount++;
 921 
 922             int count = 0;
 923             while (sc.hasNextLong()) {
 924                 long blah = sc.nextLong();
 925                 count++;
 926             }
 927             if (count != 7)
 928                 failCount++;
 929         }
 930         report("From file");
 931     }
 932 
 933     private static void example1() throws Exception {
 934         Scanner s = new Scanner("1 fish 2 fish red fish blue fish");
 935         s.useDelimiter("\\s*fish\\s*");
 936         List <String> results = new ArrayList<String>();
 937         while (s.hasNext())
 938             results.add(s.next());
 939         System.out.println(results);
 940     }
 941 
 942     private static void example2() throws Exception {
 943         Scanner s = new Scanner("1 fish 2 fish red fish blue fish");
 944         s.useDelimiter("\\s*fish\\s*");
 945         System.out.println(s.nextInt());
 946         System.out.println(s.nextInt());
 947         System.out.println(s.next());
 948         System.out.println(s.next());
 949     }
 950 
 951     private static void example3() throws Exception {
 952         Scanner s = new Scanner("1 fish 2 fish red fish blue fish");
 953         s.findInLine("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)");
 954         for (int i=1; i<=s.match().groupCount(); i++)
 955             System.out.println(s.match().group(i));
 956     }
 957 
 958     private static void findInLineTest() throws Exception {
 959         Scanner s = new Scanner("abc def ghi jkl mno");
 960         Pattern letters = Pattern.compile("[a-z]+");
 961         Pattern frogs = Pattern.compile("frogs");
 962         String str = s.findInLine(letters);
 963         if (!str.equals("abc"))
 964             failCount++;
 965         if (!s.hasNext(letters))
 966             failCount++;
 967         try {
 968             str = s.findInLine(frogs);
 969         } catch (NoSuchElementException nsee) {
 970             // Correct
 971         }
 972         if (!s.hasNext())
 973             failCount++;
 974         if (!s.hasNext(letters))
 975             failCount++;
 976         str = s.findInLine(letters);
 977         if (!str.equals("def"))
 978             failCount++;
 979 
 980         report("Find patterns");
 981     }
 982 
 983     private static void findInEmptyLineTest() throws Exception {
 984         String eol = System.getProperty("line.separator");
 985         Scanner s = new Scanner("line 1" + eol + "" + eol + "line 3" + eol);
 986         int lineNo = 0;
 987         while (s.hasNextLine()) {
 988             lineNo++;
 989             s.findInLine("3");
 990             s.nextLine();
 991         }
 992         if (lineNo != 3)
 993             failCount++;
 994         report("findInEmptyLine test");
 995     }
 996 
 997     private static void matchTest() throws Exception {
 998         Scanner s = new Scanner("1 fish 2 fish red fish blue fish");
 999         s.findInLine("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)");
1000 
1001         MatchResult result = s.match();
1002         if (!result.group(1).equals("1"))
1003             failCount++;
1004         if (!result.group(2).equals("2"))
1005             failCount++;
1006         if (!result.group(3).equals("red"))
1007             failCount++;
1008         if (!result.group(4).equals("blue"))
1009             failCount++;
1010 
1011         report("Match patterns");
1012     }
1013 
1014     private static void skipTest() throws Exception {
1015         Scanner s = new Scanner("abc def ghi jkl mno");
1016         Pattern letters = Pattern.compile("[a-z]+");
1017         Pattern spaceLetters = Pattern.compile(" [a-z]+");
1018         Pattern frogs = Pattern.compile("frogs");
1019         try {
1020             s.skip(letters);
1021         } catch (NoSuchElementException ime) {
1022             failCount++;
1023         }
1024         String token = s.next(letters);
1025         if (!token.equals("def")) {
1026             System.out.println("expected def");
1027             System.out.println("I found "+token);
1028             failCount++;
1029         }
1030         try {
1031             s.skip(letters);
1032             failCount++;
1033         } catch (NoSuchElementException ime) {
1034             // Correct result
1035         }
1036         token = s.next(letters);
1037         if (!token.equals("ghi")) {
1038             System.out.println("expected ghi");
1039             System.out.println("I found "+token);
1040             failCount++;
1041         }
1042         try {
1043             s.skip(letters);
1044             failCount++;
1045         } catch (NoSuchElementException ime) {
1046             // Correct result because skip ignores delims
1047         }
1048         try {
1049             s.skip(spaceLetters);
1050         } catch (NoSuchElementException ime) {
1051             failCount++;
1052         }
1053         token = s.next(letters);
1054         if (!token.equals("mno")) {
1055             System.out.println("expected mno");
1056             System.out.println("I found "+token);
1057             failCount++;
1058         }
1059         try {
1060             s.skip(letters);
1061             failCount++;
1062         } catch (NoSuchElementException ime) {
1063             // Correct result
1064         }
1065         report("Skip patterns");
1066     }
1067 
1068     private static void byteTest(int sourceType) throws Exception {
1069         String input = " 3 0 00 b -B 012 44 -55 12 127 129 -131 dog 0x12";
1070         Scanner s = scannerFor(input, sourceType);
1071         if (!s.hasNextByte())          failCount++;
1072         if (s.nextByte() != (byte)3)   failCount++;
1073         if (!s.hasNextByte())          failCount++;
1074         if (s.nextByte() != (byte)0)   failCount++;
1075         if (!s.hasNextByte())          failCount++;
1076         if (s.nextByte() != (byte)0)   failCount++;
1077         if (!s.hasNextByte(16))        failCount++;
1078         if (s.nextByte(16) != (byte)11)failCount++;
1079         if (!s.hasNextByte(16))        failCount++;
1080         if (s.nextByte(16) != (byte)-11) failCount++;
1081         if (!s.hasNextByte())          failCount++;
1082         if (s.nextByte() != (byte)12)  failCount++;
1083         if (!s.hasNextByte())          failCount++;
1084         if (s.nextByte() != (byte)44)  failCount++;
1085         if (!s.hasNextByte())          failCount++;
1086         if (s.nextByte() != (byte)-55) failCount++;
1087         if (!s.hasNextByte())          failCount++;
1088         if (s.nextByte() != (byte)12)  failCount++;
1089         if (!s.hasNextByte())          failCount++;
1090         if (s.nextByte() != (byte)127) failCount++;
1091         if (s.hasNextByte())           failCount++;
1092 
1093         try {
1094             s.nextByte();
1095             failCount++;
1096         } catch (InputMismatchException ime) {
1097             // Correct result
1098         }
1099         if (s.hasNextByte())           failCount++;
1100         if (s.nextInt() != 129)        failCount++;
1101         if (s.hasNextByte())           failCount++;
1102         try {
1103             s.nextByte();
1104             failCount++;
1105         } catch (InputMismatchException ime) {
1106             // Correct result
1107         }
1108         if (s.nextInt() != -131)       failCount++;
1109         if (s.hasNextByte())           failCount++;
1110         try {
1111             s.nextByte();
1112             failCount++;
1113         } catch (InputMismatchException ime) {
1114             // Correct result
1115         }
1116         s.next(Pattern.compile("\\w+"));
1117         if (s.hasNextByte())
1118             failCount++;
1119         try {
1120             s.nextByte();
1121             failCount++;
1122         } catch (NoSuchElementException nsee) {
1123             // Correct result
1124         }
1125         s.next();
1126         if (s.hasNextByte())
1127             failCount++;
1128         try {
1129             byte bb = s.nextByte();
1130             failCount++;
1131         } catch (NoSuchElementException nsee) {
1132             // Correct result
1133         }
1134         report("Scan bytes");
1135     }
1136 
1137     private static void shortTest(int sourceType) throws Exception {
1138         String input = "  017 22 00E -34 44,333 -53999 0x19 dog";
1139         Scanner s = scannerFor(input, sourceType);
1140         if (!s.hasNextShort())             failCount++;
1141         if (s.nextShort() != (short)17)   failCount++;
1142         if (!s.hasNextShort())            failCount++;
1143         if (s.nextShort() != (short)22)   failCount++;
1144         if (!s.hasNextShort(16))          failCount++;
1145         if (s.nextShort(16) != (short)14) failCount++;
1146         if (!s.hasNextShort())            failCount++;
1147         if (s.nextShort() != (short)-34)  failCount++;
1148         for (int i=0; i<4; i++) {
1149             if (s.hasNextShort())
1150                 failCount++;
1151             try {
1152                 s.nextShort();
1153                 failCount++;
1154             } catch (InputMismatchException ime) {
1155                 // Correct result
1156             }
1157             s.next();
1158         }
1159         try {
1160             s.next();
1161             failCount++;
1162         } catch (InputMismatchException ime) {
1163             failCount++;
1164         } catch (NoSuchElementException nse) {
1165             // Correct result
1166         }
1167         report("Scan shorts");
1168     }
1169 
1170     private static void intTest(int sourceType) throws Exception {
1171         Scanner s = scannerFor(
1172             "22 022 C -34 0x80000000 -2147483649 dog ", sourceType);
1173         if (!s.hasNextInt())      failCount++;
1174         if (s.nextInt() != 22)    failCount++;
1175         if (!s.hasNextInt())      failCount++;
1176         if (s.nextInt() != 22)    failCount++;
1177         if (!s.hasNextInt(16))    failCount++;
1178         if (s.nextInt(16) != 12)  failCount++;
1179         if (!s.hasNextInt())      failCount++;
1180         if (s.nextInt() != -34)   failCount++;
1181         for (int i=0; i<3; i++) {
1182             if (s.hasNextInt())
1183                 failCount++;
1184             try {
1185                 s.nextInt();
1186                 failCount++;
1187             } catch (InputMismatchException ime) {
1188                 // Correct result
1189             }
1190             s.next();
1191         }
1192         try {
1193             s.next();
1194             failCount++;
1195         } catch (InputMismatchException ime) {
1196             failCount++;
1197         } catch (NoSuchElementException nse) {
1198             // Correct result
1199         }
1200         report("Scan ints");
1201     }
1202 
1203     private static void longTest(int sourceType) throws Exception {
1204         Scanner s = scannerFor(
1205         "022 9223372036854775807 0x8000000000000000 9223372036854775808 dog ",
1206               sourceType);
1207         if (!s.hasNextLong())                        failCount++;
1208         if (s.nextLong() != (long)22)                failCount++;
1209         if (!s.hasNextLong())                        failCount++;
1210         if (s.nextLong() != 9223372036854775807L)    failCount++;
1211         for (int i=0; i<3; i++) {
1212             if (s.hasNextLong())
1213                 failCount++;
1214             try {
1215                 s.nextLong();
1216                 failCount++;
1217             } catch (InputMismatchException ime) {
1218                 // Correct result
1219             }
1220             s.next();
1221         }
1222         try {
1223             s.next();
1224             failCount++;
1225         } catch (InputMismatchException ime) {
1226             failCount++;
1227         } catch (NoSuchElementException nse) {
1228             // Correct result
1229         }
1230         report("Scan longs");
1231     }
1232 
1233     private static void floatTest(int sourceType) throws Exception {
1234         Scanner s = scannerFor(
1235             "0 0. 0.0 2 2. 2.0 2.3 -2 -2.0 -2.3 -. 2-. 2..3", sourceType);
1236         if (!s.hasNextFloat())      failCount++;
1237         if (s.nextFloat() != 0f)    failCount++;
1238         if (!s.hasNextFloat())      failCount++;
1239         if (s.nextFloat() != 0f)    failCount++;
1240         if (!s.hasNextFloat())      failCount++;
1241         if (s.nextFloat() != 0f)    failCount++;
1242         if (!s.hasNextFloat())      failCount++;
1243         if (s.nextFloat() != 2f)    failCount++;
1244         if (!s.hasNextFloat())      failCount++;
1245         if (s.nextFloat() != 2f)    failCount++;
1246         if (!s.hasNextFloat())      failCount++;
1247         if (s.nextFloat() != 2f)    failCount++;
1248         if (!s.hasNextFloat())      failCount++;
1249         if (s.nextFloat() != 2.3f)  failCount++;
1250         if (!s.hasNextFloat())      failCount++;
1251         if (s.nextFloat() != -2f)   failCount++;
1252         if (!s.hasNextFloat())      failCount++;
1253         if (s.nextFloat() != -2f)   failCount++;
1254         if (!s.hasNextFloat())      failCount++;
1255         if (s.nextFloat() != -2.3f) failCount++;
1256         for (int i=0; i<3; i++) {
1257             if (s.hasNextLong())
1258                 failCount++;
1259             try {
1260                 s.nextFloat();
1261                 failCount++;
1262             } catch (InputMismatchException ime) {
1263                 // Correct result
1264             }
1265             s.next();
1266         }
1267         try {
1268             s.next();
1269             failCount++;
1270         } catch (InputMismatchException ime) {
1271             failCount++;
1272         } catch (NoSuchElementException nse) {
1273             // Correct result
1274         }
1275         report("Scan floats");
1276     }
1277 
1278     private static void doubleTest(int sourceType) throws Exception {
1279         Scanner s = scannerFor(
1280             "0 0. 0.0 2 2. 2.0 2.3 -2 -2.0 -2.3 -. 2-. 2..3", sourceType);
1281         if (!s.hasNextDouble())             failCount++;
1282         if (s.nextDouble() != 0d)           failCount++;
1283         if (!s.hasNextDouble())             failCount++;
1284         if (s.nextDouble() != 0d)           failCount++;
1285         if (!s.hasNextDouble())             failCount++;
1286         if (s.nextDouble() != 0d)           failCount++;
1287         if (!s.hasNextDouble())             failCount++;
1288         if (s.nextDouble() != 2d)           failCount++;
1289         if (!s.hasNextDouble())             failCount++;
1290         if (s.nextDouble() != 2d)           failCount++;
1291         if (!s.hasNextDouble())             failCount++;
1292         if (s.nextDouble() != 2d)           failCount++;
1293         if (!s.hasNextDouble())             failCount++;
1294         if (s.nextDouble() != 2.3d)         failCount++;
1295         if (!s.hasNextDouble())             failCount++;
1296         if (s.nextDouble() != -2d)          failCount++;
1297         if (!s.hasNextDouble())             failCount++;
1298         if (s.nextDouble() != -2d)          failCount++;
1299         if (!s.hasNextDouble())             failCount++;
1300         if (s.nextDouble() != -2.3d)        failCount++;
1301         for (int i=0; i<3; i++) {
1302             if (s.hasNextLong())
1303                 failCount++;
1304             try {
1305                 s.nextDouble();
1306                 failCount++;
1307             } catch (InputMismatchException ime) {
1308                 // Correct result
1309             }
1310             s.next();
1311         }
1312         try {
1313             s.next();
1314             failCount++;
1315         } catch (InputMismatchException ime) {
1316             failCount++;
1317         } catch (NoSuchElementException nse) {
1318             // Correct result
1319         }
1320         report("Scan doubles");
1321     }
1322 
1323     private static void booleanTest(int sourceType) throws Exception {
1324         Scanner s = scannerFor(
1325             " true false\t \r\n true FaLse \n  True Tru", sourceType);
1326         if (!s.nextBoolean())     failCount++;
1327         if (!s.hasNextBoolean())  failCount++;
1328         if (s.nextBoolean())      failCount++;
1329         if (!s.nextBoolean())     failCount++;
1330         if (s.nextBoolean())      failCount++;
1331         if (!s.nextBoolean())     failCount++;
1332         if (s.hasNextBoolean())   failCount++;
1333         try {
1334             s.nextBoolean();
1335             failCount++;
1336         } catch (NoSuchElementException nsee) {
1337             // Expected result
1338         }
1339         report("Scan booleans");
1340     }
1341 
1342     private static void hasNextTest(int sourceType) throws Exception {
1343         Scanner s = scannerFor(
1344             " blah blech\t blather  alongblatherindeed", sourceType);
1345         if (!s.hasNext())            failCount++;
1346         if (!s.hasNext())            failCount++;
1347         String result = s.next();
1348         if (!result.equals("blah"))  failCount++;
1349         if (!s.hasNext())            failCount++;
1350         if (!s.hasNext())            failCount++;
1351         result = s.next();
1352         if (!result.equals("blech")) failCount++;
1353         if (!s.hasNext())            failCount++;
1354         result = s.next();
1355         if (!result.equals("blather")) failCount++;
1356         if (!s.hasNext())              failCount++;
1357         if (!s.hasNext())              failCount++;
1358         result = s.next();
1359         if (!result.equals("alongblatherindeed")) failCount++;
1360         if (s.hasNext())                          failCount++;
1361         try {
1362             result = s.next();
1363             failCount++;
1364         } catch (NoSuchElementException nsee) {
1365             // Correct result
1366         }
1367         report("Has next test");
1368     }
1369 
1370     private static void nextTest(int sourceType) throws Exception {
1371         Scanner s = scannerFor(
1372             " blah blech\t blather  alongblatherindeed", sourceType);
1373         String result = (String)s.next();
1374         if (!result.equals("blah"))    failCount++;
1375         result = (String)s.next();
1376         if (!result.equals("blech"))   failCount++;
1377         result = (String)s.next();
1378         if (!result.equals("blather")) failCount++;
1379         result = (String)s.next();
1380         if (!result.equals("alongblatherindeed"))
1381             failCount++;
1382         try {
1383             result = (String)s.next();
1384             failCount++;
1385         } catch (NoSuchElementException nsee) {
1386             // Correct result
1387         }
1388         report("Next test");
1389     }
1390 
1391     private static void hasNextPatternTest(int sourceType) throws Exception {
1392         Scanner s = scannerFor(
1393             " blah blech\t blather  alongblatherindeed", sourceType);
1394         Pattern p1 = Pattern.compile("\\w+");
1395         Pattern p2 = Pattern.compile("blech");
1396         if (!s.hasNext(p1))    failCount++;
1397         if (!s.hasNext(p1))    failCount++;
1398         if (s.hasNext(p2))     failCount++;
1399         String result = (String)s.next();
1400         if (!result.equals("blah"))  failCount++;
1401         if (!s.hasNext(p1))          failCount++;
1402         if (!s.hasNext(p2))          failCount++;
1403         result = (String)s.next();
1404         if (!result.equals("blech")) failCount++;
1405         if (!s.hasNext(p1))          failCount++;
1406         if (s.hasNext(p2))           failCount++;
1407         result = (String)s.next();
1408         if (!result.equals("blather")) failCount++;
1409         if (!s.hasNext(p1))            failCount++;
1410         if (s.hasNext(p2))             failCount++;
1411         result = (String)s.next();
1412         if (!result.equals("alongblatherindeed")) failCount++;
1413         if (s.hasNext(p1))  failCount++;
1414         if (s.hasNext(p2))  failCount++;
1415         report("Has Next Pattern test");
1416     }
1417 
1418     private static void nextPatternTest(int sourceType) throws Exception {
1419         Scanner s = scannerFor(
1420             " blah blech\t blather  alongblatherindeed", sourceType);
1421         Pattern p1 = Pattern.compile("blah");
1422         Pattern p2 = Pattern.compile("blech");
1423         Pattern p3 = Pattern.compile("blather");
1424         Pattern p4 = Pattern.compile("alongblatherindeed");
1425         String result = null;
1426         try {
1427             result = (String)s.next(p2);
1428             failCount++;
1429         } catch (NoSuchElementException nsee) {
1430             // Correct result
1431         }
1432         result = (String)s.next(p1);
1433         if (!result.equals("blah"))
1434             failCount++;
1435         try {
1436             result = (String)s.next(p1);
1437             failCount++;
1438         } catch (NoSuchElementException nsee) {
1439             // Correct result
1440         }
1441         result = (String)s.next(p2);
1442         if (!result.equals("blech"))
1443             failCount++;
1444         try {
1445             result = (String)s.next(p4);
1446             failCount++;
1447         } catch (NoSuchElementException nsee) {
1448             // Correct result
1449         }
1450         result = (String)s.next(p3);
1451         if (!result.equals("blather"))
1452             failCount++;
1453         try {
1454             result = (String)s.next(p3);
1455             failCount++;
1456         } catch (NoSuchElementException nsee) {
1457             // Correct result
1458         }
1459         result = (String)s.next(p4);
1460         if (!result.equals("alongblatherindeed"))
1461             failCount++;
1462         try {
1463             result = (String)s.next();
1464             failCount++;
1465         } catch (NoSuchElementException nsee) {
1466             // Correct result
1467         }
1468         report("Next pattern test");
1469     }
1470 
1471     private static void useLocaleTest() throws Exception {
1472         Scanner s = new Scanner("334.65").useLocale(Locale.ENGLISH);
1473         if (!s.hasNextFloat())           failCount++;
1474         if (s.nextFloat() != 334.65f)    failCount++;
1475 
1476         s = new Scanner("334,65").useLocale(Locale.FRENCH);
1477         if (!s.hasNextFloat())           failCount++;
1478         if (s.nextFloat() != 334.65f)    failCount++;
1479 
1480         s = new Scanner("4.334,65").useLocale(Locale.GERMAN);
1481         if (!s.hasNextFloat())           failCount++;
1482         if (s.nextFloat() != 4334.65f)    failCount++;
1483 
1484         // Test case reported from India
1485         try {
1486             String Message = "123978.90 $";
1487             Locale locale = new Locale("hi","IN");
1488             NumberFormat form = NumberFormat.getInstance(locale);
1489             double myNumber = 1902.09;
1490             Scanner scanner = new Scanner(form.format(myNumber).toString());
1491             scanner.useLocale(locale);
1492             double d = scanner.nextDouble();
1493         } catch (InputMismatchException ime) {
1494             failCount++;
1495         }
1496         report("Use locale test");
1497     }
1498 
1499     public static void resetTest() throws Exception {
1500         Scanner sc = new Scanner("");
1501         int radix = sc.radix();
1502         Locale locale = sc.locale();
1503         Pattern delimiter = sc.delimiter();
1504         Pattern a = Pattern.compile("A");
1505         sc.useDelimiter(a);
1506         Locale dummy = new Locale("en", "US", "dummy");
1507         sc.useLocale(dummy);
1508         sc.useRadix(16);
1509         if (sc.radix() != 16 ||
1510             !sc.locale().equals(dummy) ||
1511             !sc.delimiter().pattern().equals(a.pattern())) {
1512             failCount++;
1513         } else {
1514             sc.reset();
1515             if (sc.radix() != radix ||
1516                 !sc.locale().equals(locale) ||
1517                 !sc.delimiter().pattern().equals(delimiter.pattern())) {
1518                 failCount++;
1519             }
1520         }
1521         sc.close();
1522         report("Reset test");
1523     }
1524 
1525     static List<BiConsumer <Scanner, Integer>> methodWRList = Arrays.asList(
1526         (s, r) -> s.hasNextByte(r),
1527         (s, r) -> s.nextByte(r),
1528         (s, r) -> s.hasNextShort(r),
1529         (s, r) -> s.nextShort(r),
1530         (s, r) -> s.hasNextInt(r),
1531         (s, r) -> s.nextInt(r),
1532         (s, r) -> s.hasNextLong(r),
1533         (s, r) -> s.nextLong(r),
1534         (s, r) -> s.hasNextBigInteger(r),
1535         (s, r) -> s.nextBigInteger(r)
1536     );
1537 
1538     /*
1539      * Test that setting the radix to an out of range value triggers
1540      * an IllegalArgumentException
1541      */
1542     public static void outOfRangeRadixTest() throws Exception {
1543         int[] bad = new int[] { -1, 0,  1, 37, 38 };
1544         int[] good = IntStream.rangeClosed(Character.MIN_RADIX, Character.MAX_RADIX)
1545                               .toArray();
1546 
1547         methodWRList.stream().forEach( m -> {
1548             for (int r : bad) {
1549                 try (Scanner sc = new Scanner("10 10 10 10")) {
1550                     m.accept(sc, r);
1551                     failCount++;
1552                 } catch (IllegalArgumentException ise) {}
1553             }
1554         });
1555         methodWRList.stream().forEach( m -> {
1556             for (int r : good) {
1557                 try (Scanner sc = new Scanner("10 10 10 10")) {
1558                     m.accept(sc, r);
1559                 } catch (Exception x) {
1560                     failCount++;
1561                 }
1562             }
1563         });
1564         report("Radix out of range test");
1565     }
1566 
1567     /*
1568      * Test that closing the stream also closes the underlying Scanner.
1569      * The cases of attempting to open streams on a closed Scanner are
1570      * covered by closeTest().
1571      */
1572     public static void streamCloseTest() throws Exception {
1573         Scanner sc;
1574 
1575         Scanner sc1 = new Scanner("xyzzy");
1576         sc1.tokens().close();
1577         try {
1578             sc1.hasNext();
1579             failCount++;
1580         } catch (IllegalStateException ise) {
1581             // Correct result
1582         }
1583 
1584         Scanner sc2 = new Scanner("a b c d e f");
1585         try {
1586             sc2.tokens()
1587                .peek(s -> sc2.close())
1588                .count();
1589         } catch (IllegalStateException ise) {
1590             // Correct result
1591         }
1592 
1593         Scanner sc3 = new Scanner("xyzzy");
1594         sc3.findAll("q").close();
1595         try {
1596             sc3.hasNext();
1597             failCount++;
1598         } catch (IllegalStateException ise) {
1599             // Correct result
1600         }
1601 
1602         try (Scanner sc4 = new Scanner(inputFile)) {
1603             sc4.findAll("[0-9]+")
1604                .peek(s -> sc4.close())
1605                .count();
1606             failCount++;
1607         } catch (IllegalStateException ise) {
1608             // Correct result
1609         }
1610 
1611         report("Streams Close test");
1612     }
1613 
1614     /*
1615      * Test ConcurrentModificationException
1616      */
1617     public static void streamComodTest() {
1618         try {
1619             Scanner sc = new Scanner("a b c d e f");
1620             sc.tokens()
1621               .peek(s -> sc.hasNext())
1622               .count();
1623             failCount++;
1624         } catch (ConcurrentModificationException cme) {
1625             // Correct result
1626         }
1627 
1628         try {
1629             Scanner sc = new Scanner("a b c d e f");
1630             Iterator<String> it = sc.tokens().iterator();
1631             it.next();
1632             sc.next();
1633             it.next();
1634             failCount++;
1635         } catch (ConcurrentModificationException cme) {
1636             // Correct result
1637         }
1638 
1639         try {
1640             String input = IntStream.range(0, 100)
1641                                     .mapToObj(String::valueOf)
1642                                     .collect(Collectors.joining(" "));
1643             Scanner sc = new Scanner(input);
1644             sc.findAll("[0-9]+")
1645               .peek(s -> sc.hasNext())
1646               .count();
1647             failCount++;
1648         } catch (ConcurrentModificationException cme) {
1649             // Correct result
1650         }
1651 
1652         try {
1653             String input = IntStream.range(0, 100)
1654                                     .mapToObj(String::valueOf)
1655                                     .collect(Collectors.joining(" "));
1656             Scanner sc = new Scanner(input);
1657             Iterator<MatchResult> it = sc.findAll("[0-9]+").iterator();
1658             it.next();
1659             sc.next();
1660             it.next();
1661             failCount++;
1662         } catch (ConcurrentModificationException cme) {
1663             // Correct result
1664         }
1665 
1666         report("Streams Comod test");
1667     }
1668 
1669     private static void report(String testName) {
1670         System.err.printf("%-30s: %s%n", testName,
1671                           (failCount == 0) ? "Passed" : String.format("Failed(%d)", failCount));
1672 
1673         if (failCount > 0)
1674             failure = true;
1675         failCount = 0;
1676     }
1677 
1678     static Scanner scannerFor(String input, int sourceType) {
1679         if (sourceType == 1)
1680             return new Scanner(input);
1681         else
1682             return new Scanner(new StutteringInputStream(input));
1683     }
1684 
1685     static class ThrowingReadable implements Readable {
1686         ThrowingReadable() {
1687         }
1688         public int read(java.nio.CharBuffer cb) throws IOException {
1689             throw new IOException("ThrowingReadable always throws");
1690         }
1691     }
1692 }