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