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