1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements.  See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License.  You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package libcore.java.util;
17
18import java.io.IOException;
19import java.io.StringReader;
20import java.net.InetSocketAddress;
21import java.nio.CharBuffer;
22import java.nio.channels.IllegalBlockingModeException;
23import java.nio.channels.ServerSocketChannel;
24import java.nio.channels.SocketChannel;
25import java.util.Arrays;
26import java.util.NoSuchElementException;
27import java.util.Scanner;
28import java.util.regex.MatchResult;
29import java.util.regex.Pattern;
30import junit.framework.TestCase;
31
32public final class OldScannerTest extends TestCase {
33
34    private Scanner s;
35
36    public void test_findWithinHorizon_Ljava_lang_StringI() {
37        // This method searches through the input up to the specified search
38        // horizon(exclusive).
39        s = new Scanner("123test");
40        String result = s.findWithinHorizon("\\p{Lower}", 5);
41        assertEquals("t", result);
42        MatchResult mresult = s.match();
43        assertEquals(3, mresult.start());
44        assertEquals(4, mresult.end());
45
46        s = new Scanner("12345test1234test next");
47        /*
48         * If the pattern is found the scanner advances past the input that
49         * matched and returns the string that matched the pattern.
50         */
51        result = s.findWithinHorizon("\\p{Digit}+", 2);
52        assertEquals("12", result);
53        mresult = s.match();
54        assertEquals(0, mresult.start());
55        assertEquals(2, mresult.end());
56        // Position is now pointing at the bar. "12|345test1234test next"
57
58        result = s.findWithinHorizon("\\p{Digit}+", 6);
59        assertEquals("345", result);
60
61        mresult = s.match();
62        assertEquals(2, mresult.start());
63        assertEquals(5, mresult.end());
64        // Position is now pointing at the bar. "12345|test1234test next"
65
66        // If no such pattern is detected then the null is returned and the
67        // scanner's position remains unchanged.
68        result = s.findWithinHorizon("\\p{Digit}+", 3);
69        assertNull(result);
70
71        try {
72            s.match();
73            fail("Should throw IllegalStateException");
74        } catch (IllegalStateException e) {
75            // expected
76        }
77        assertEquals("345", mresult.group());
78        assertEquals(2, mresult.start());
79        assertEquals(5, mresult.end());
80        // Position is now still pointing at the bar. "12345|test1234test next"
81
82        // If horizon is 0, then the horizon is ignored and this method
83        // continues to search through the input looking for the specified
84        // pattern without bound.
85        result = s.findWithinHorizon("\\p{Digit}+", 0);
86        mresult = s.match();
87        assertEquals(9, mresult.start());
88        assertEquals(13, mresult.end());
89        // Position is now pointing at the bar. "12345test1234|test next"
90
91        assertEquals("test", s.next());
92        mresult = s.match();
93        assertEquals(13, mresult.start());
94        assertEquals(17, mresult.end());
95
96        assertEquals("next", s.next());
97        mresult = s.match();
98        assertEquals(18, mresult.start());
99        assertEquals(22, mresult.end());
100
101        try {
102            s.findWithinHorizon((String)null, 1);
103            fail("Should throw NullPointerException");
104        } catch (NullPointerException e) {
105            // expected
106        }
107
108        try {
109            s.findWithinHorizon("\\p{Digit}+", -1);
110            fail("Should throw IllegalArgumentException");
111        } catch (IllegalArgumentException e) {
112            // expected
113        }
114
115        s.close();
116        // on RI throws NullPointerException
117        /*
118         * try { System.out.println("fsdfs"); s.findWithinHorizon((String) null,
119         * -1); System.out.println("fsdfs"); fail("Should throw
120         * IllegalStateException"); } catch (IllegalStateException e) { //
121         * expected }
122         */
123        s = new Scanner("test");
124        result = s.findWithinHorizon("\\w+", 10);
125        assertEquals("test", result);
126
127        s = new Scanner("aa\n\rb");
128        String patternStr = "^(a)$";
129        result = s.findWithinHorizon("a", 5);
130        assertEquals("a", result);
131        mresult = s.match();
132        assertEquals(0, mresult.start());
133        assertEquals(1, mresult.end());
134
135        result = s.findWithinHorizon(patternStr, 5);
136        assertNull(result);
137
138        try {
139            mresult = s.match();
140            fail("Should throw IllegalStateException");
141        } catch (IllegalStateException e) {
142            // expected
143        }
144
145        s = new Scanner("");
146        result = s.findWithinHorizon("^", 0);
147        assertEquals("", result);
148        MatchResult matchResult = s.match();
149        assertEquals(0, matchResult.start());
150        assertEquals(0, matchResult.end());
151
152        result = s.findWithinHorizon("$", 0);
153        assertEquals("", result);
154        matchResult = s.match();
155        assertEquals(0, matchResult.start());
156        assertEquals(0, matchResult.end());
157
158        s = new Scanner("1 fish 2 fish red fish blue fish");
159        result = s.findWithinHorizon("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)", 10);
160        assertNull(result);
161
162        try {
163            mresult = s.match();
164            fail("Should throw IllegalStateException");
165        } catch (IllegalStateException e) {
166            // expected
167        }
168        assertEquals(0, mresult.groupCount());
169
170        result = s.findWithinHorizon("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)", 100);
171        assertEquals("1 fish 2 fish red fish blue", result);
172        mresult = s.match();
173        assertEquals(4, mresult.groupCount());
174        assertEquals("1", mresult.group(1));
175        assertEquals("2", mresult.group(2));
176        assertEquals("red", mresult.group(3));
177        assertEquals("blue", mresult.group(4));
178
179        s = new Scanner("test");
180        s.close();
181        try {
182            s.findWithinHorizon("test", 1);
183            fail("Should throw IllegalStateException");
184        } catch (IllegalStateException e) {
185            // expected
186        }
187
188        s = new Scanner("word1 WorD2  ");
189        s.close();
190        try {
191            s.findWithinHorizon("\\d+", 10);
192            fail("should throw IllegalStateException");
193        } catch (IllegalStateException e) {
194            // expected
195        }
196
197        s = new Scanner("word1 WorD2 wOrd3 ");
198        patternStr = "\\d+";
199        assertEquals("1", s.findWithinHorizon(patternStr, 10));
200        assertEquals("WorD2", s.next());
201        assertEquals("3", s.findWithinHorizon(patternStr, 15));
202
203        // Regression test
204        s = new Scanner(new MockStringReader("MockStringReader"));
205        patternStr = "test";
206        result = s.findWithinHorizon(patternStr, 10);
207        assertEquals("test", result);
208
209        // Test the situation when input length is longer than buffer size.
210        StringBuilder stringBuilder = new StringBuilder();
211        for (int i = 0; i < 1026; i++) {
212            stringBuilder.append('a');
213        }
214        s = new Scanner(stringBuilder.toString());
215        patternStr = "\\p{Lower}+";
216        result = s.findWithinHorizon(patternStr, 1026);
217        assertEquals(stringBuilder.toString(), result);
218
219        // Test the situation when input length is longer than buffer size and
220        // set horizon to buffer size.
221        stringBuilder = new StringBuilder();
222        for (int i = 0; i < 1026; i++) {
223            stringBuilder.append('a');
224        }
225        s = new Scanner(stringBuilder.toString());
226        patternStr = "\\p{Lower}+";
227        result = s.findWithinHorizon(patternStr, 1022);
228        assertEquals(1022, result.length());
229        assertEquals(stringBuilder.subSequence(0, 1022), result);
230
231        // Test the situation, under which pattern is clipped by buffer.
232        stringBuilder = new StringBuilder();
233        for (int i = 0; i < 1022; i++) {
234            stringBuilder.append(' ');
235        }
236        stringBuilder.append("bbc");
237        assertEquals(1025, stringBuilder.length());
238        s = new Scanner(stringBuilder.toString());
239        patternStr = "bbc";
240        result = s.findWithinHorizon(patternStr, 1025);
241        assertEquals(3, result.length());
242        assertEquals(stringBuilder.subSequence(1022, 1025), result);
243
244        stringBuilder = new StringBuilder();
245        for (int i = 0; i < 1026; i++) {
246            stringBuilder.append('a');
247        }
248        s = new Scanner(stringBuilder.toString());
249        patternStr = "\\p{Lower}+";
250        result = s.findWithinHorizon(patternStr, 0);
251        assertEquals(stringBuilder.toString(), result);
252
253        stringBuilder = new StringBuilder();
254        for (int i = 0; i < 10240; i++) {
255            stringBuilder.append('-');
256        }
257        stringBuilder.replace(0, 2, "aa");
258        s = new Scanner(stringBuilder.toString());
259        result = s.findWithinHorizon("aa", 0);
260        assertEquals("aa", result);
261
262        s = new Scanner("aaaa");
263        result = s.findWithinHorizon("a*", 0);
264        assertEquals("aaaa", result);
265    }
266
267    public void test_findInLine_LString() {
268        s = new Scanner("test");
269        try {
270            s.findInLine((String) null);
271            fail("Should throw NullPointerException");
272        } catch (NullPointerException e) {
273            // expected
274        }
275
276        s.close();
277        try {
278            s.findInLine((String) null);
279            fail("Should throw NullPointerException");
280        } catch (NullPointerException e) {
281            // expected
282        }
283        try {
284            s.findInLine("test");
285            fail("Should throw IllegalStateException");
286        } catch (IllegalStateException e) {
287            // exptected
288        }
289
290        s = new Scanner("");
291
292        String result = s.findInLine("^");
293        assertEquals("", result);
294        MatchResult matchResult = s.match();
295        assertEquals(0, matchResult.start());
296        assertEquals(0, matchResult.end());
297
298        result = s.findInLine("$");
299        assertEquals("", result);
300        matchResult = s.match();
301        assertEquals(0, matchResult.start());
302        assertEquals(0, matchResult.end());
303
304        /*
305         * When we use the operation of findInLine(Pattern), the match region
306         * should not span the line separator.
307         */
308        s = new Scanner("aa\nb.b");
309        result = s.findInLine("a\nb*");
310        assertNull(result);
311
312        s = new Scanner("aa\nbb.b");
313        result = s.findInLine("\\.");
314        assertNull(result);
315
316        s = new Scanner("abcd1234test\n");
317        result = s.findInLine("\\p{Lower}+");
318        assertEquals("abcd", result);
319        matchResult = s.match();
320        assertEquals(0, matchResult.start());
321        assertEquals(4, matchResult.end());
322
323        result = s.findInLine("\\p{Digit}{5}");
324        assertNull(result);
325        try {
326            matchResult = s.match();
327            fail("Should throw IllegalStateException");
328        } catch (IllegalStateException e) {
329            // expected
330        }
331        assertEquals(0, matchResult.start());
332        assertEquals(4, matchResult.end());
333
334        result = s.findInLine("\\p{Lower}+");
335        assertEquals("test", result);
336        matchResult = s.match();
337        assertEquals(8, matchResult.start());
338        assertEquals(12, matchResult.end());
339
340        char[] chars = new char[2048];
341        Arrays.fill(chars, 'a');
342        StringBuilder stringBuilder = new StringBuilder();
343        stringBuilder.append(chars);
344        stringBuilder.append("1234");
345        s = new Scanner(stringBuilder.toString());
346        result = s.findInLine("\\p{Digit}+");
347        assertEquals("1234", result);
348        matchResult = s.match();
349        assertEquals(2048, matchResult.start());
350        assertEquals(2052, matchResult.end());
351
352        s = new Scanner("test1234\n1234 test");
353        result = s.findInLine("test");
354        assertEquals("test", result);
355        matchResult = s.match();
356        assertEquals(0, matchResult.start());
357        assertEquals(4, matchResult.end());
358
359        int number = s.nextInt();
360        assertEquals(1234, number);
361        matchResult = s.match();
362        assertEquals(4, matchResult.start());
363        assertEquals(8, matchResult.end());
364
365        result = s.next();
366        assertEquals("1234", result);
367        matchResult = s.match();
368        assertEquals(9, matchResult.start());
369        assertEquals(13, matchResult.end());
370
371        result = s.findInLine("test");
372        assertEquals("test", result);
373        matchResult = s.match();
374        assertEquals(14, matchResult.start());
375        assertEquals(18, matchResult.end());
376
377        s = new Scanner("test\u0085\ntest");
378        result = s.findInLine("est");
379        assertEquals("est", result);
380        result = s.findInLine("est");
381        assertEquals("est", result);
382
383        s = new Scanner("test\ntest");
384        result = s.findInLine("est");
385        assertEquals("est", result);
386        result = s.findInLine("est");
387        assertEquals("est", result);
388
389        s = new Scanner("test\n123\ntest");
390        result = s.findInLine("est");
391        assertEquals("est", result);
392        result = s.findInLine("est");
393    }
394
395    public void test_skip_LPattern() {
396        s = new Scanner("test");
397        try {
398            s.skip((String) null);
399            fail("Should throw NullPointerException");
400        } catch (NullPointerException e) {
401            // expected
402        }
403
404        // If pattern does not match, NoSuchElementException will be thrown out.
405        s = new Scanner("1234");
406        try {
407            s.skip(Pattern.compile("\\p{Lower}"));
408            fail("Should throw NoSuchElementException");
409        } catch (NoSuchElementException e) {
410            // expected
411        }
412        // Then, no matchResult will be thrown out.
413        try {
414            s.match();
415            fail("Should throw IllegalStateException");
416        } catch (IllegalStateException e) {
417            // expected
418        }
419
420        s.skip(Pattern.compile("\\p{Digit}"));
421        MatchResult matchResult = s.match();
422        assertEquals(0, matchResult.start());
423        assertEquals(1, matchResult.end());
424
425        s.skip(Pattern.compile("\\p{Digit}+"));
426        matchResult = s.match();
427        assertEquals(1, matchResult.start());
428        assertEquals(4, matchResult.end());
429
430        s.close();
431        try {
432            s.skip(Pattern.compile("test"));
433            fail("Should throw IllegalStateException");
434        } catch (IllegalStateException e) {
435            // expected
436        }
437
438        MockStringReader2Read reader = new MockStringReader2Read("test");
439        s = new Scanner(reader);
440        try {
441            s.skip(Pattern.compile("\\p{Digit}{4}"));
442            fail("Should throw NoSuchElementException");
443        } catch (NoSuchElementException e) {
444            // expected
445        }
446        try {
447            s.match();
448            fail("Should throw IllegalStateException");
449        } catch (IllegalStateException e) {
450            // expected
451        }
452        s.skip(Pattern.compile("\\p{Digit}{3}\\p{Lower}"));
453        matchResult = s.match();
454        assertEquals(0, matchResult.start());
455        assertEquals(4, matchResult.end());
456
457        s.close();
458        try {
459            s.skip((Pattern) null);
460            fail("Should throw IllegalStateException");
461        } catch (IllegalStateException e) {
462            // expected
463        }
464
465        StringBuilder stringBuilder = new StringBuilder();
466        char [] chars = new char[1024];
467        Arrays.fill(chars, 'a');
468        stringBuilder.append(chars);
469        stringBuilder.append('3');
470        s = new Scanner(stringBuilder.toString());
471        s.skip(Pattern.compile("\\p{Lower}+\\p{Digit}"));
472        matchResult = s.match();
473        assertEquals(0, matchResult.start());
474        assertEquals(1025, matchResult.end());
475
476        // Large amount of input may be cached
477        chars = new char[102400];
478        Arrays.fill(chars, 'a');
479        stringBuilder = new StringBuilder();
480        stringBuilder.append(chars);
481        s = new Scanner(stringBuilder.toString());
482        s.skip(Pattern.compile(".*"));
483        matchResult = s.match();
484        assertEquals(0, matchResult.start());
485        assertEquals(102400, matchResult.end());
486
487        // skip something without risking a NoSuchElementException
488        s.skip(Pattern.compile("[ \t]*"));
489        matchResult = s.match();
490        assertEquals(102400, matchResult.start());
491        assertEquals(102400, matchResult.end());
492    }
493
494    public void test_Constructor_LReadableByteChannel() throws IOException {
495        ServerSocketChannel ssc = ServerSocketChannel.open();
496        ssc.socket().bind(null);
497
498        SocketChannel sc = SocketChannel.open();
499        sc.connect(ssc.socket().getLocalSocketAddress());
500        sc.configureBlocking(false);
501        assertFalse(sc.isBlocking());
502
503        ssc.accept().close();
504        ssc.close();
505        assertFalse(sc.isBlocking());
506
507        Scanner s = new Scanner(sc);
508        try {
509            s.hasNextInt();
510            fail();
511        } catch (IllegalBlockingModeException expected) {
512        }
513
514        sc.close();
515    }
516
517    private static class MockStringReader extends StringReader {
518
519        public MockStringReader(String param) {
520            super(param);
521        }
522
523        public int read(CharBuffer target) throws IOException {
524            target.append('t');
525            target.append('e');
526            target.append('s');
527            target.append('t');
528            throw new IOException();
529        }
530    }
531
532    private static class MockStringReader2Read extends StringReader {
533        private int timesRead = 1;
534
535        public MockStringReader2Read(String param) {
536            super(param);
537        }
538
539        public int read(CharBuffer target) throws IOException {
540            if (timesRead == 1) {
541                target.append('1');
542                target.append('2');
543                target.append('3');
544                timesRead++;
545                return 3;
546            } else if (timesRead == 2) {
547                target.append('t');
548                timesRead++;
549                return 1;
550            } else {
551                throw new IOException();
552            }
553        }
554    }
555}
556