1 /* 2 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package test.java.util.Scanner; 25 26 import org.testng.annotations.DataProvider; 27 import org.testng.annotations.Test; 28 29 import java.io.File; 30 import java.io.IOException; 31 import java.io.UncheckedIOException; 32 33 import java.util.ArrayList; 34 import java.util.List; 35 import java.util.Scanner; 36 import java.util.function.Consumer; 37 import java.util.function.Supplier; 38 import java.util.regex.Matcher; 39 import java.util.regex.MatchResult; 40 import java.util.regex.Pattern; 41 import java.util.stream.Stream; 42 import org.openjdk.testlib.java.util.stream.LambdaTestHelpers; 43 import org.openjdk.testlib.java.util.stream.OpTestCase; 44 import org.openjdk.testlib.java.util.stream.TestData; 45 46 import static org.testng.Assert.*; 47 48 /** 49 * @test 50 * @bug 8072722 8150488 51 * @summary Tests of stream support in java.util.Scanner 52 * @library /lib/testlibrary/bootlib 53 * @build java.base/java.util.stream.OpTestCase 54 * @run testng/othervm ScannerStreamTest 55 */ 56 57 @Test 58 public class ScannerStreamTest extends OpTestCase { 59 60 // Android-removed: reading from resources, not local files. 61 // static File inputFile = new File(System.getProperty("test.src", "."), "input.txt"); 62 63 @DataProvider(name = "Tokens") makeTokensTestData()64 public static Object[][] makeTokensTestData() { 65 // each inner array is [String description, String input, String delimiter] 66 // delimiter may be null 67 List<Object[]> data = new ArrayList<>(); 68 69 data.add(new Object[] { "default delimiter", "abc def ghi", null }); 70 data.add(new Object[] { "fixed delimiter", "abc,def,,ghi", "," }); 71 data.add(new Object[] { "regex delimiter", "###abc##def###ghi###j", "#+" }); 72 73 return data.toArray(new Object[0][]); 74 } 75 76 /* 77 * Creates a scanner over the input, applying a delimiter if non-null. 78 */ makeScanner(String input, String delimiter)79 Scanner makeScanner(String input, String delimiter) { 80 Scanner sc = new Scanner(input); 81 if (delimiter != null) { 82 sc.useDelimiter(delimiter); 83 } 84 return sc; 85 } 86 87 /* 88 * Given input and a delimiter, tests that tokens() returns the same 89 * results that would be provided by a Scanner hasNext/next loop. 90 */ 91 @Test(dataProvider = "Tokens") tokensTest(String description, String input, String delimiter)92 public void tokensTest(String description, String input, String delimiter) { 93 // derive expected result by using conventional loop 94 Scanner sc = makeScanner(input, delimiter); 95 List<String> expected = new ArrayList<>(); 96 while (sc.hasNext()) { 97 expected.add(sc.next()); 98 } 99 100 Supplier<Stream<String>> ss = () -> makeScanner(input, delimiter).tokens(); 101 withData(TestData.Factory.ofSupplier(description, ss)) 102 .stream(LambdaTestHelpers.identity()) 103 .expectedResult(expected) 104 .exercise(); 105 } 106 107 /* 108 * Creates a Scanner over the given input file. 109 */ makeFileScanner(File file)110 Scanner makeFileScanner(File file) { 111 try { 112 return new Scanner(file, "UTF-8"); 113 } catch (IOException ioe) { 114 throw new UncheckedIOException(ioe); 115 } 116 } 117 118 // Android-added: reading from resources, not local files. makeResourceScanner()119 Scanner makeResourceScanner() { 120 var inputStream = ScannerStreamTest.class.getResourceAsStream("input.txt"); 121 return new Scanner(inputStream, "UTF-8"); 122 } 123 124 /* 125 * Tests that the matches produced by findAll(pat) are the same 126 * as what are returned by findWithinHorizon(pat, 0). This tests 127 * a single pattern against a single input file. 128 */ findAllFileTest()129 public void findAllFileTest() { 130 // derive expected result by using conventional loop 131 Pattern pat = Pattern.compile("[A-Z]{7,}"); 132 List<String> expected = new ArrayList<>(); 133 134 try (Scanner sc = makeResourceScanner()) { 135 String match; 136 while ((match = sc.findWithinHorizon(pat, 0)) != null) { 137 expected.add(match); 138 } 139 } 140 141 Supplier<Stream<String>> ss = 142 () -> makeResourceScanner().findAll(pat).map(MatchResult::group); 143 144 withData(TestData.Factory.ofSupplier("findAllFileTest", ss)) 145 .stream(LambdaTestHelpers.identity()) 146 .expectedResult(expected) 147 .exercise(); 148 } 149 150 @DataProvider(name = "FindAllZero") makeFindAllZeroTestData()151 public static Object[][] makeFindAllZeroTestData() { 152 // each inner array is [String input, String patternString] 153 List<Object[]> data = new ArrayList<>(); 154 155 data.add(new Object[] { "aaaaa", "a*" }); 156 data.add(new Object[] { "aaaaab", "a*" }); 157 data.add(new Object[] { "aaaaabb", "a*" }); 158 data.add(new Object[] { "aaaaabbb", "a*" }); 159 data.add(new Object[] { "aaabbaaaa", "a*" }); 160 data.add(new Object[] { "aaabbaaaab", "a*" }); 161 data.add(new Object[] { "aaabbaaaabb", "a*" }); 162 data.add(new Object[] { "aaabbaaaabbb", "a*" }); 163 data.add(new Object[] { "aaabbaaaa", "a*|b*" }); 164 data.add(new Object[] { "aaabbaaaab", "a*|b*" }); 165 data.add(new Object[] { "aaabbaaaabb", "a*|b*" }); 166 data.add(new Object[] { "aaabbaaaabbb", "a*|b*" }); 167 168 return data.toArray(new Object[0][]); 169 } 170 171 /* 172 * Tests findAll() using a pattern against an input string. 173 * The results from findAll() should equal the results obtained 174 * using a loop around Matcher.find(). 175 * 176 * The provided regexes should allow zero-length matches. 177 * This primarily tests the auto-advance feature of findAll() that 178 * occurs if the regex match is of zero length to see if it has the 179 * same behavior as Matcher.find()'s auto-advance (JDK-8150488). 180 * Without auto-advance, findAll() would return an infinite stream 181 * of zero-length matches. Apply a limit to the stream so 182 * that an infinite stream will be truncated. The limit must be 183 * high enough that the resulting truncated stream won't be 184 * mistaken for a correct expected result. 185 */ 186 @Test(dataProvider = "FindAllZero") findAllZeroTest(String input, String patternString)187 public void findAllZeroTest(String input, String patternString) { 188 Pattern pattern = Pattern.compile(patternString); 189 190 // generate expected result using Matcher.find() 191 Matcher m = pattern.matcher(input); 192 List<String> expected = new ArrayList<>(); 193 while (m.find()) { 194 expected.add(m.group()); 195 } 196 197 Supplier<Stream<String>> ss = () -> new Scanner(input).findAll(pattern) 198 .limit(100) 199 .map(MatchResult::group); 200 201 withData(TestData.Factory.ofSupplier("findAllZeroTest", ss)) 202 .stream(LambdaTestHelpers.identity()) 203 .expectedResult(expected) 204 .exercise(); 205 } 206 } 207