• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 only, as
8  * published by the Free Software Foundation.
9  *
10  * This code is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * version 2 for more details (a copy is included in the LICENSE file that
14  * accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License version
17  * 2 along with this work; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21  * or visit www.oracle.com if you need additional information or have any
22  * questions.
23  */
24 package org.openjdk.tests.java.util.stream;
25 
26 import org.testng.annotations.DataProvider;
27 import org.testng.annotations.Factory;
28 import org.testng.annotations.Test;
29 import org.testng.annotations.BeforeClass;
30 
31 import java.util.Arrays;
32 import java.util.Collection;
33 import java.util.Collections;
34 import java.util.LinkedHashSet;
35 import java.util.LinkedList;
36 import java.util.List;
37 import java.util.Spliterator;
38 import java.util.TreeSet;
39 import java.util.stream.DoubleStream;
40 import java.util.stream.IntStream;
41 import java.util.stream.LongStream;
42 import java.util.stream.Stream;
43 
44 import static org.openjdk.testlib.java.util.stream.LambdaTestHelpers.*;
45 import static org.testng.Assert.*;
46 
47 @Test
48 public class ConcatTest {
49     private static Object[][] cases;
50 
51     static {
52         List<Integer> part1 = Arrays.asList(5, 3, 4, 1, 2, 6, 2, 4);
53         List<Integer> part2 = Arrays.asList(8, 8, 6, 6, 9, 7, 10, 9);
54         List<Integer> p1p2 = Arrays.asList(5, 3, 4, 1, 2, 6, 2, 4, 8, 8, 6, 6, 9, 7, 10, 9);
55         List<Integer> p2p1 = Arrays.asList(8, 8, 6, 6, 9, 7, 10, 9, 5, 3, 4, 1, 2, 6, 2, 4);
56         List<Integer> empty = new LinkedList<>(); // To be ordered
empty.isEmpty()57         assertTrue(empty.isEmpty());
58         LinkedHashSet<Integer> distinctP1 = new LinkedHashSet<>(part1);
59         LinkedHashSet<Integer> distinctP2 = new LinkedHashSet<>(part2);
60         TreeSet<Integer> sortedP1 = new TreeSet<>(part1);
61         TreeSet<Integer> sortedP2 = new TreeSet<>(part2);
62 
63         cases = new Object[][] {
64             { "regular", part1, part2, p1p2 },
65             { "reverse regular", part2, part1, p2p1 },
66             { "front distinct", distinctP1, part2, Arrays.asList(5, 3, 4, 1, 2, 6, 8, 8, 6, 6, 9, 7, 10, 9) },
67             { "back distinct", part1, distinctP2, Arrays.asList(5, 3, 4, 1, 2, 6, 2, 4, 8, 6, 9, 7, 10) },
68             { "both distinct", distinctP1, distinctP2, Arrays.asList(5, 3, 4, 1, 2, 6, 8, 6, 9, 7, 10) },
69             { "front sorted", sortedP1, part2, Arrays.asList(1, 2, 3, 4, 5, 6, 8, 8, 6, 6, 9, 7, 10, 9) },
70             { "back sorted", part1, sortedP2, Arrays.asList(5, 3, 4, 1, 2, 6, 2, 4, 6, 7, 8, 9, 10) },
71             { "both sorted", sortedP1, sortedP2, Arrays.asList(1, 2, 3, 4, 5, 6, 6, 7, 8, 9, 10) },
72             { "reverse both sorted", sortedP2, sortedP1, Arrays.asList(6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6) },
73             { "empty something", empty, part1, part1 },
74             { "something empty", part1, empty, part1 },
75             { "empty empty", empty, empty, empty }
76         };
77     }
78 
79     @DataProvider(name = "cases")
getCases()80     private static Object[][] getCases() {
81         return cases;
82     }
83 
84     @Factory(dataProvider = "cases")
createTests(String scenario, Collection<Integer> c1, Collection<Integer> c2, Collection<Integer> expected)85     public static Object[] createTests(String scenario, Collection<Integer> c1, Collection<Integer> c2, Collection<Integer> expected) {
86         return new Object[] {
87             new ConcatTest(scenario, c1, c2, expected)
88         };
89     }
90 
91     protected final String scenario;
92     protected final Collection<Integer> c1;
93     protected final Collection<Integer> c2;
94     protected final Collection<Integer> expected;
95 
ConcatTest(String scenario, Collection<Integer> c1, Collection<Integer> c2, Collection<Integer> expected)96     public ConcatTest(String scenario, Collection<Integer> c1, Collection<Integer> c2, Collection<Integer> expected) {
97         this.scenario = scenario;
98         this.c1 = c1;
99         this.c2 = c2;
100         this.expected = expected;
101     }
102 
103     // Android-changed: Factor out the prerequisites check out of the constructor.
104     // TestNG crashes hard if an assert is thrown in the constructor.
105     // This is done for test readability only and doesn't impact test logic.
106     @BeforeClass
checkPrerequisites()107     public void checkPrerequisites() {
108         // verify prerequisite
109         Stream<Integer> s1s = c1.stream();
110         Stream<Integer> s2s = c2.stream();
111         Stream<Integer> s1p = c1.parallelStream();
112         Stream<Integer> s2p = c2.parallelStream();
113         assertTrue(s1p.isParallel());
114         assertTrue(s2p.isParallel());
115         assertFalse(s1s.isParallel());
116         assertFalse(s2s.isParallel());
117 
118         // Android-changed: Also add the class name to easier debug. Doesn't impact logic.
119         assertTrue(s1s.spliterator().hasCharacteristics(Spliterator.ORDERED), c1.getClass().toString());
120         assertTrue(s1p.spliterator().hasCharacteristics(Spliterator.ORDERED), c2.getClass().toString());
121         assertTrue(s2s.spliterator().hasCharacteristics(Spliterator.ORDERED), c1.getClass().toString());
122         assertTrue(s2p.spliterator().hasCharacteristics(Spliterator.ORDERED), c2.getClass().toString());
123     }
124 
assertConcatContent(Spliterator<T> sp, boolean ordered, Spliterator<T> expected)125     private <T> void assertConcatContent(Spliterator<T> sp, boolean ordered, Spliterator<T> expected) {
126         // concat stream cannot guarantee uniqueness
127         assertFalse(sp.hasCharacteristics(Spliterator.DISTINCT), scenario);
128         // concat stream cannot guarantee sorted
129         assertFalse(sp.hasCharacteristics(Spliterator.SORTED), scenario);
130         // concat stream is ordered if both are ordered
131         assertEquals(sp.hasCharacteristics(Spliterator.ORDERED), ordered, scenario);
132 
133         // Verify elements
134         if (ordered) {
135             assertEquals(toBoxedList(sp),
136                          toBoxedList(expected),
137                          scenario);
138         } else {
139             assertEquals(toBoxedMultiset(sp),
140                          toBoxedMultiset(expected),
141                          scenario);
142         }
143     }
144 
assertRefConcat(Stream<Integer> s1, Stream<Integer> s2, boolean parallel, boolean ordered)145     private void assertRefConcat(Stream<Integer> s1, Stream<Integer> s2, boolean parallel, boolean ordered) {
146         Stream<Integer> result = Stream.concat(s1, s2);
147         assertEquals(result.isParallel(), parallel);
148         assertConcatContent(result.spliterator(), ordered, expected.spliterator());
149     }
150 
assertIntConcat(Stream<Integer> s1, Stream<Integer> s2, boolean parallel, boolean ordered)151     private void assertIntConcat(Stream<Integer> s1, Stream<Integer> s2, boolean parallel, boolean ordered) {
152         IntStream result = IntStream.concat(s1.mapToInt(Integer::intValue),
153                                             s2.mapToInt(Integer::intValue));
154         assertEquals(result.isParallel(), parallel);
155         assertConcatContent(result.spliterator(), ordered,
156                             expected.stream().mapToInt(Integer::intValue).spliterator());
157     }
158 
assertLongConcat(Stream<Integer> s1, Stream<Integer> s2, boolean parallel, boolean ordered)159     private void assertLongConcat(Stream<Integer> s1, Stream<Integer> s2, boolean parallel, boolean ordered) {
160         LongStream result = LongStream.concat(s1.mapToLong(Integer::longValue),
161                                               s2.mapToLong(Integer::longValue));
162         assertEquals(result.isParallel(), parallel);
163         assertConcatContent(result.spliterator(), ordered,
164                             expected.stream().mapToLong(Integer::longValue).spliterator());
165     }
166 
assertDoubleConcat(Stream<Integer> s1, Stream<Integer> s2, boolean parallel, boolean ordered)167     private void assertDoubleConcat(Stream<Integer> s1, Stream<Integer> s2, boolean parallel, boolean ordered) {
168         DoubleStream result = DoubleStream.concat(s1.mapToDouble(Integer::doubleValue),
169                                                   s2.mapToDouble(Integer::doubleValue));
170         assertEquals(result.isParallel(), parallel);
171         assertConcatContent(result.spliterator(), ordered,
172                             expected.stream().mapToDouble(Integer::doubleValue).spliterator());
173     }
174 
testRefConcat()175     public void testRefConcat() {
176         // sequential + sequential -> sequential
177         assertRefConcat(c1.stream(), c2.stream(), false, true);
178         // parallel + parallel -> parallel
179         assertRefConcat(c1.parallelStream(), c2.parallelStream(), true, true);
180         // sequential + parallel -> parallel
181         assertRefConcat(c1.stream(), c2.parallelStream(), true, true);
182         // parallel + sequential -> parallel
183         assertRefConcat(c1.parallelStream(), c2.stream(), true, true);
184 
185         // not ordered
186         assertRefConcat(c1.stream().unordered(), c2.stream(), false, false);
187         assertRefConcat(c1.stream(), c2.stream().unordered(), false, false);
188         assertRefConcat(c1.parallelStream().unordered(), c2.stream().unordered(), true, false);
189     }
190 
testIntConcat()191     public void testIntConcat() {
192         // sequential + sequential -> sequential
193         assertIntConcat(c1.stream(), c2.stream(), false, true);
194         // parallel + parallel -> parallel
195         assertIntConcat(c1.parallelStream(), c2.parallelStream(), true, true);
196         // sequential + parallel -> parallel
197         assertIntConcat(c1.stream(), c2.parallelStream(), true, true);
198         // parallel + sequential -> parallel
199         assertIntConcat(c1.parallelStream(), c2.stream(), true, true);
200 
201         // not ordered
202         assertIntConcat(c1.stream().unordered(), c2.stream(), false, false);
203         assertIntConcat(c1.stream(), c2.stream().unordered(), false, false);
204         assertIntConcat(c1.parallelStream().unordered(), c2.stream().unordered(), true, false);
205     }
206 
testLongConcat()207     public void testLongConcat() {
208         // sequential + sequential -> sequential
209         assertLongConcat(c1.stream(), c2.stream(), false, true);
210         // parallel + parallel -> parallel
211         assertLongConcat(c1.parallelStream(), c2.parallelStream(), true, true);
212         // sequential + parallel -> parallel
213         assertLongConcat(c1.stream(), c2.parallelStream(), true, true);
214         // parallel + sequential -> parallel
215         assertLongConcat(c1.parallelStream(), c2.stream(), true, true);
216 
217         // not ordered
218         assertLongConcat(c1.stream().unordered(), c2.stream(), false, false);
219         assertLongConcat(c1.stream(), c2.stream().unordered(), false, false);
220         assertLongConcat(c1.parallelStream().unordered(), c2.stream().unordered(), true, false);
221     }
222 
testDoubleConcat()223     public void testDoubleConcat() {
224         // sequential + sequential -> sequential
225         assertDoubleConcat(c1.stream(), c2.stream(), false, true);
226         // parallel + parallel -> parallel
227         assertDoubleConcat(c1.parallelStream(), c2.parallelStream(), true, true);
228         // sequential + parallel -> parallel
229         assertDoubleConcat(c1.stream(), c2.parallelStream(), true, true);
230         // parallel + sequential -> parallel
231         assertDoubleConcat(c1.parallelStream(), c2.stream(), true, true);
232 
233         // not ordered
234         assertDoubleConcat(c1.stream().unordered(), c2.stream(), false, false);
235         assertDoubleConcat(c1.stream(), c2.stream().unordered(), false, false);
236         assertDoubleConcat(c1.parallelStream().unordered(), c2.stream().unordered(), true, false);
237     }
238 }
239