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