jdk/test/java/util/regex/PatternStreamTest.java
changeset 29243 80ea8d3d39d0
parent 28964 f4a570561f34
child 33830 9f4be4f1c8b6
equal deleted inserted replaced
29242:33423ec519fd 29243:80ea8d3d39d0
     1 /*
     1 /*
     2  * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2013, 2015 Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    21  * questions.
    21  * questions.
    22  */
    22  */
    23 
    23 
    24 /**
    24 /**
    25  * @test
    25  * @test
    26  * @bug 8016846 8024341
    26  * @bug 8016846 8024341 8071479
    27  * @summary Unit tests for wrapping classes should delegate to default methods
    27  * @summary Unit tests stream and lambda-based methods on Pattern and Matcher
    28  * @library ../stream/bootlib
    28  * @library ../stream/bootlib
    29  * @build java.util.stream.OpTestCase
    29  * @build java.util.stream.OpTestCase
    30  * @run testng/othervm PatternStreamTest
    30  * @run testng/othervm PatternStreamTest
    31  */
    31  */
    32 
    32 
    33 import org.testng.annotations.DataProvider;
    33 import org.testng.annotations.DataProvider;
    34 import org.testng.annotations.Test;
    34 import org.testng.annotations.Test;
    35 
    35 
    36 import java.util.ArrayList;
    36 import java.util.ArrayList;
       
    37 import java.util.Arrays;
       
    38 import java.util.ConcurrentModificationException;
    37 import java.util.List;
    39 import java.util.List;
       
    40 import java.util.concurrent.atomic.AtomicInteger;
    38 import java.util.function.Supplier;
    41 import java.util.function.Supplier;
       
    42 import java.util.regex.MatchResult;
       
    43 import java.util.regex.Matcher;
    39 import java.util.regex.Pattern;
    44 import java.util.regex.Pattern;
    40 import java.util.stream.LambdaTestHelpers;
    45 import java.util.stream.LambdaTestHelpers;
    41 import java.util.stream.OpTestCase;
    46 import java.util.stream.OpTestCase;
    42 import java.util.stream.Stream;
    47 import java.util.stream.Stream;
    43 import java.util.stream.TestData;
    48 import java.util.stream.TestData;
    44 
    49 
       
    50 import static org.testng.Assert.*;
       
    51 
    45 @Test
    52 @Test
    46 public class PatternStreamTest extends OpTestCase {
    53 public class PatternStreamTest extends OpTestCase {
    47 
    54 
    48     @DataProvider(name = "Stream<String>")
    55     @DataProvider(name = "Patterns")
    49     public static Object[][] makeStreamTestData() {
    56     public static Object[][] makeStreamTestData() {
       
    57         // Each item must match the type signature of the consumer of this data
       
    58         // String, String, Pattern
    50         List<Object[]> data = new ArrayList<>();
    59         List<Object[]> data = new ArrayList<>();
    51 
    60 
    52         String description = "";
    61         String description = "All matches";
    53         String input = "awgqwefg1fefw4vssv1vvv1";
    62         String input = "XXXXXX";
    54         Pattern pattern = Pattern.compile("4");
    63         Pattern pattern = Pattern.compile("X");
    55         List<String> expected = new ArrayList<>();
    64         data.add(new Object[]{description, input, pattern});
    56         expected.add("awgqwefg1fefw");
    65 
    57         expected.add("vssv1vvv1");
    66         description = "Bounded every other match";
    58 
    67         input = "XYXYXYYXYX";
    59         // Must match the type signature of the consumer of this data, testStrings
    68         pattern = Pattern.compile("X");
    60         // String, String, Pattern, List<String>
    69         data.add(new Object[]{description, input, pattern});
    61         data.add(new Object[]{description, input, pattern, expected});
    70 
       
    71         description = "Every other match";
       
    72         input = "YXYXYXYYXYXY";
       
    73         pattern = Pattern.compile("X");
       
    74         data.add(new Object[]{description, input, pattern});
       
    75 
       
    76         description = "";
       
    77         input = "awgqwefg1fefw4vssv1vvv1";
       
    78         pattern = Pattern.compile("4");
       
    79         data.add(new Object[]{description, input, pattern});
    62 
    80 
    63         input = "afbfq\u00a3abgwgb\u00a3awngnwggw\u00a3a\u00a3ahjrnhneerh";
    81         input = "afbfq\u00a3abgwgb\u00a3awngnwggw\u00a3a\u00a3ahjrnhneerh";
    64         pattern = Pattern.compile("\u00a3a");
    82         pattern = Pattern.compile("\u00a3a");
    65         expected = new ArrayList<>();
    83         data.add(new Object[]{description, input, pattern});
    66         expected.add("afbfq");
       
    67         expected.add("bgwgb");
       
    68         expected.add("wngnwggw");
       
    69         expected.add("");
       
    70         expected.add("hjrnhneerh");
       
    71 
       
    72         data.add(new Object[]{description, input, pattern, expected});
       
    73 
       
    74 
    84 
    75         input = "awgqwefg1fefw4vssv1vvv1";
    85         input = "awgqwefg1fefw4vssv1vvv1";
    76         pattern = Pattern.compile("1");
    86         pattern = Pattern.compile("1");
    77         expected = new ArrayList<>();
    87         data.add(new Object[]{description, input, pattern});
    78         expected.add("awgqwefg");
       
    79         expected.add("fefw4vssv");
       
    80         expected.add("vvv");
       
    81 
       
    82         data.add(new Object[]{description, input, pattern, expected});
       
    83 
       
    84 
    88 
    85         input = "a\u4ebafg1fefw\u4eba4\u9f9cvssv\u9f9c1v\u672c\u672cvv";
    89         input = "a\u4ebafg1fefw\u4eba4\u9f9cvssv\u9f9c1v\u672c\u672cvv";
    86         pattern = Pattern.compile("1");
    90         pattern = Pattern.compile("1");
    87         expected = new ArrayList<>();
    91         data.add(new Object[]{description, input, pattern});
    88         expected.add("a\u4ebafg");
       
    89         expected.add("fefw\u4eba4\u9f9cvssv\u9f9c");
       
    90         expected.add("v\u672c\u672cvv");
       
    91 
       
    92         data.add(new Object[]{description, input, pattern, expected});
       
    93 
       
    94 
    92 
    95         input = "1\u56da23\u56da456\u56da7890";
    93         input = "1\u56da23\u56da456\u56da7890";
    96         pattern = Pattern.compile("\u56da");
    94         pattern = Pattern.compile("\u56da");
    97         expected = new ArrayList<>();
    95         data.add(new Object[]{description, input, pattern});
    98         expected.add("1");
       
    99         expected.add("23");
       
   100         expected.add("456");
       
   101         expected.add("7890");
       
   102 
       
   103         data.add(new Object[]{description, input, pattern, expected});
       
   104 
       
   105 
    96 
   106         input = "1\u56da23\u9f9c\u672c\u672c\u56da456\u56da\u9f9c\u672c7890";
    97         input = "1\u56da23\u9f9c\u672c\u672c\u56da456\u56da\u9f9c\u672c7890";
   107         pattern = Pattern.compile("\u56da");
    98         pattern = Pattern.compile("\u56da");
   108         expected = new ArrayList<>();
    99         data.add(new Object[]{description, input, pattern});
   109         expected.add("1");
       
   110         expected.add("23\u9f9c\u672c\u672c");
       
   111         expected.add("456");
       
   112         expected.add("\u9f9c\u672c7890");
       
   113 
       
   114         data.add(new Object[]{description, input, pattern, expected});
       
   115 
       
   116 
   100 
   117         description = "Empty input";
   101         description = "Empty input";
   118         input = "";
   102         input = "";
   119         pattern = Pattern.compile("\u56da");
   103         pattern = Pattern.compile("\u56da");
   120         expected = new ArrayList<>();
   104         data.add(new Object[]{description, input, pattern});
   121         expected.add("");
       
   122 
       
   123         data.add(new Object[]{description, input, pattern, expected});
       
   124 
       
   125 
   105 
   126         description = "Empty input with empty pattern";
   106         description = "Empty input with empty pattern";
   127         input = "";
   107         input = "";
   128         pattern = Pattern.compile("");
   108         pattern = Pattern.compile("");
   129         expected = new ArrayList<>();
   109         data.add(new Object[]{description, input, pattern});
   130         expected.add("");
       
   131 
       
   132         data.add(new Object[]{description, input, pattern, expected});
       
   133 
       
   134 
   110 
   135         description = "Multiple separators";
   111         description = "Multiple separators";
   136         input = "This is,testing: with\tdifferent separators.";
   112         input = "This is,testing: with\tdifferent separators.";
   137         pattern = Pattern.compile("[ \t,:.]");
   113         pattern = Pattern.compile("[ \t,:.]");
   138         expected = new ArrayList<>();
   114         data.add(new Object[]{description, input, pattern});
   139         expected.add("This");
       
   140         expected.add("is");
       
   141         expected.add("testing");
       
   142         expected.add("");
       
   143         expected.add("with");
       
   144         expected.add("different");
       
   145         expected.add("separators");
       
   146 
       
   147 
   115 
   148         description = "Repeated separators within and at end";
   116         description = "Repeated separators within and at end";
   149         input = "boo:and:foo";
   117         input = "boo:and:foo";
   150         pattern = Pattern.compile("o");
   118         pattern = Pattern.compile("o");
   151         expected = new ArrayList<>();
   119         data.add(new Object[]{description, input, pattern});
   152         expected.add("b");
       
   153         expected.add("");
       
   154         expected.add(":and:f");
       
   155 
       
   156 
   120 
   157         description = "Many repeated separators within and at end";
   121         description = "Many repeated separators within and at end";
   158         input = "booooo:and:fooooo";
   122         input = "booooo:and:fooooo";
   159         pattern = Pattern.compile("o");
   123         pattern = Pattern.compile("o");
   160         expected = new ArrayList<>();
   124         data.add(new Object[]{description, input, pattern});
   161         expected.add("b");
       
   162         expected.add("");
       
   163         expected.add("");
       
   164         expected.add("");
       
   165         expected.add("");
       
   166         expected.add(":and:f");
       
   167 
   125 
   168         description = "Many repeated separators before last match";
   126         description = "Many repeated separators before last match";
   169         input = "fooooo:";
   127         input = "fooooo:";
   170         pattern = Pattern.compile("o");
   128         pattern = Pattern.compile("o");
   171         expected = new ArrayList<>();
   129         data.add(new Object[] {description, input, pattern});
   172         expected.add("f");
   130 
   173         expected.add("");
       
   174         expected.add("");
       
   175         expected.add("");
       
   176         expected.add("");
       
   177         expected.add(":");
       
   178 
       
   179         data.add(new Object[] {description, input, pattern, expected});
       
   180         return data.toArray(new Object[0][]);
   131         return data.toArray(new Object[0][]);
   181     }
   132     }
   182 
   133 
   183     @Test(dataProvider = "Stream<String>")
   134     @Test(dataProvider = "Patterns")
   184     public void testStrings(String description, String input, Pattern pattern, List<String> expected) {
   135     public void testPatternSplitAsStream(String description, String input, Pattern pattern) {
       
   136         // Derive expected result from pattern.split
       
   137         List<String> expected = Arrays.asList(pattern.split(input));
       
   138 
   185         Supplier<Stream<String>> ss =  () -> pattern.splitAsStream(input);
   139         Supplier<Stream<String>> ss =  () -> pattern.splitAsStream(input);
   186         withData(TestData.Factory.ofSupplier(description, ss))
   140         withData(TestData.Factory.ofSupplier(description, ss))
   187                 .stream(LambdaTestHelpers.identity())
   141                 .stream(LambdaTestHelpers.identity())
   188                 .expectedResult(expected)
   142                 .expectedResult(expected)
   189                 .exercise();
   143                 .exercise();
   190     }
   144     }
       
   145 
       
   146     @Test(dataProvider = "Patterns")
       
   147     public void testReplaceFirst(String description, String input, Pattern pattern) {
       
   148         // Derive expected result from Matcher.replaceFirst(String )
       
   149         String expected = pattern.matcher(input).replaceFirst("R");
       
   150         String actual = pattern.matcher(input).replaceFirst(r -> "R");
       
   151         assertEquals(actual, expected);
       
   152     }
       
   153 
       
   154     @Test(dataProvider = "Patterns")
       
   155     public void testReplaceAll(String description, String input, Pattern pattern) {
       
   156         // Derive expected result from Matcher.replaceAll(String )
       
   157         String expected = pattern.matcher(input).replaceAll("R");
       
   158         String actual = pattern.matcher(input).replaceAll(r -> "R");
       
   159         assertEquals(actual, expected);
       
   160 
       
   161         // Derive expected result from Matcher.find
       
   162         Matcher m = pattern.matcher(input);
       
   163         int expectedMatches = 0;
       
   164         while (m.find()) {
       
   165             expectedMatches++;
       
   166         }
       
   167         AtomicInteger actualMatches = new AtomicInteger();
       
   168         pattern.matcher(input).replaceAll(r -> "R" + actualMatches.incrementAndGet());
       
   169         assertEquals(expectedMatches, actualMatches.get());
       
   170     }
       
   171 
       
   172     @Test(dataProvider = "Patterns")
       
   173     public void testMatchResults(String description, String input, Pattern pattern) {
       
   174         // Derive expected result from Matcher.find
       
   175         Matcher m = pattern.matcher(input);
       
   176         List<MatchResultHolder> expected = new ArrayList<>();
       
   177         while (m.find()) {
       
   178             expected.add(new MatchResultHolder(m));
       
   179         }
       
   180 
       
   181         Supplier<Stream<MatchResult>> ss =  () -> pattern.matcher(input).results();
       
   182         withData(TestData.Factory.ofSupplier(description, ss))
       
   183                 .stream(s -> s.map(MatchResultHolder::new))
       
   184                 .expectedResult(expected)
       
   185                 .exercise();
       
   186     }
       
   187 
       
   188     public void testFailfastMatchResults() {
       
   189         Pattern p = Pattern.compile("X");
       
   190         Matcher m = p.matcher("XX");
       
   191 
       
   192         Stream<MatchResult> s = m.results();
       
   193         m.find();
       
   194         // Should start on the second match
       
   195         assertEquals(s.count(), 1);
       
   196 
       
   197         // Fail fast without short-circuit
       
   198         // Exercises Iterator.forEachRemaining
       
   199         m.reset();
       
   200         try {
       
   201             m.results().peek(mr -> m.reset()).count();
       
   202             fail();
       
   203         } catch (ConcurrentModificationException e) {
       
   204             // Should reach here
       
   205         }
       
   206 
       
   207         m.reset();
       
   208         try {
       
   209             m.results().peek(mr -> m.find()).count();
       
   210             fail();
       
   211         } catch (ConcurrentModificationException e) {
       
   212             // Should reach here
       
   213         }
       
   214 
       
   215         // Fail fast with short-circuit
       
   216         // Exercises Iterator.hasNext/next
       
   217         m.reset();
       
   218         try {
       
   219             m.results().peek(mr -> m.reset()).limit(2).count();
       
   220             fail();
       
   221         } catch (ConcurrentModificationException e) {
       
   222             // Should reach here
       
   223         }
       
   224 
       
   225         m.reset();
       
   226         try {
       
   227             m.results().peek(mr -> m.find()).limit(2).count();
       
   228             fail();
       
   229         } catch (ConcurrentModificationException e) {
       
   230             // Should reach here
       
   231         }
       
   232     }
       
   233 
       
   234     public void testFailfastReplace() {
       
   235         Pattern p = Pattern.compile("X");
       
   236         Matcher m = p.matcher("XX");
       
   237 
       
   238         // Fail fast without short-circuit
       
   239         // Exercises Iterator.forEachRemaining
       
   240         m.reset();
       
   241         try {
       
   242             m.replaceFirst(mr -> { m.reset(); return "Y"; });
       
   243             fail();
       
   244         } catch (ConcurrentModificationException e) {
       
   245             // Should reach here
       
   246         }
       
   247 
       
   248         m.reset();
       
   249         try {
       
   250             m.replaceAll(mr -> { m.reset(); return "Y"; });
       
   251             fail();
       
   252         } catch (ConcurrentModificationException e) {
       
   253             // Should reach here
       
   254         }
       
   255     }
       
   256 
       
   257     // A holder of MatchResult that can compare
       
   258     static class MatchResultHolder implements Comparable<MatchResultHolder> {
       
   259         final MatchResult mr;
       
   260 
       
   261         MatchResultHolder(Matcher m) {
       
   262             this(m.toMatchResult());
       
   263         }
       
   264 
       
   265         MatchResultHolder(MatchResult mr) {
       
   266             this.mr = mr;
       
   267         }
       
   268 
       
   269         @Override
       
   270         public int compareTo(MatchResultHolder that) {
       
   271             int c = that.mr.group().compareTo(this.mr.group());
       
   272             if (c != 0)
       
   273                 return c;
       
   274 
       
   275             c = Integer.compare(that.mr.start(), this.mr.start());
       
   276             if (c != 0)
       
   277                 return c;
       
   278 
       
   279             c = Integer.compare(that.mr.end(), this.mr.end());
       
   280             if (c != 0)
       
   281                 return c;
       
   282 
       
   283             c = Integer.compare(that.mr.groupCount(), this.mr.groupCount());
       
   284             if (c != 0)
       
   285                 return c;
       
   286 
       
   287             for (int g = 0; g < this.mr.groupCount(); g++) {
       
   288                 c = that.mr.group(g).compareTo(this.mr.group(g));
       
   289                 if (c != 0)
       
   290                     return c;
       
   291 
       
   292                 c = Integer.compare(that.mr.start(g), this.mr.start(g));
       
   293                 if (c != 0)
       
   294                     return c;
       
   295 
       
   296                 c = Integer.compare(that.mr.end(g), this.mr.end(g));
       
   297                 if (c != 0)
       
   298                     return c;
       
   299             }
       
   300             return 0;
       
   301         }
       
   302 
       
   303         @Override
       
   304         public boolean equals(Object that) {
       
   305             if (this == that) return true;
       
   306             if (that == null || getClass() != that.getClass()) return false;
       
   307 
       
   308             return this.compareTo((MatchResultHolder) that) == 0;
       
   309         }
       
   310 
       
   311         @Override
       
   312         public int hashCode() {
       
   313             return mr.group().hashCode();
       
   314         }
       
   315     }
   191 }
   316 }