1 /*
2  * Copyright (c) 2012, 2013, 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 package org.openjdk.tests.java.util.stream;
24 
25 import org.testng.annotations.Test;
26 
27 import java.util.Spliterator;
28 import org.openjdk.testlib.java.util.stream.CollectorOps;
29 import org.openjdk.testlib.java.util.stream.OpTestCase;
30 import org.openjdk.testlib.java.util.stream.StreamTestDataProvider;
31 import org.openjdk.testlib.java.util.stream.TestData;
32 
33 import java.util.ArrayList;
34 import java.util.Collection;
35 import java.util.Comparator;
36 import java.util.List;
37 import java.util.Optional;
38 import java.util.Spliterator;
39 import java.util.Spliterators;
40 import java.util.concurrent.ThreadLocalRandom;
41 import java.util.stream.Collectors;
42 import java.util.stream.DoubleStream;
43 import java.util.stream.IntStream;
44 import java.util.stream.LongStream;
45 import java.util.stream.Stream;
46 import java.util.stream.StreamSupport;
47 
48 import static org.openjdk.testlib.java.util.stream.LambdaTestHelpers.*;
49 
50 /**
51  * DistinctOpTest
52  */
53 @Test
54 public class DistinctOpTest extends OpTestCase {
55 
testUniqOp()56     public void testUniqOp() {
57         assertCountSum(repeat(0, 10).stream().distinct(), 1, 0);
58         assertCountSum(repeat(1, 10).stream().distinct(), 1, 1);
59         assertCountSum(countTo(0).stream().distinct(), 0, 0);
60         assertCountSum(countTo(10).stream().distinct(), 10, 55);
61         assertCountSum(countTo(10).stream().distinct(), 10, 55);
62     }
63 
testWithUnorderedInfiniteStream()64     public void testWithUnorderedInfiniteStream() {
65         // These tests should short-circuit, otherwise will fail with a time-out
66         // or an OOME
67 
68         // Note that since the streams are unordered and any element is requested
69         // (a non-deterministic process) the only assertion that can be made is
70         // that an element should be found
71 
72         Optional<Integer> oi = Stream.iterate(1, i -> i + 1).unordered().parallel().distinct().findAny();
73         assertTrue(oi.isPresent());
74 
75         oi = ThreadLocalRandom.current().ints().boxed().parallel().distinct().findAny();
76         assertTrue(oi.isPresent());
77     }
78 
79     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
testOp(String name, TestData.OfRef<Integer> data)80     public void testOp(String name, TestData.OfRef<Integer> data) {
81         Collection<Integer> result = exerciseOpsInt(
82                 data,
83                 Stream::distinct,
84                 IntStream::distinct,
85                 LongStream::distinct,
86                 DoubleStream::distinct);
87 
88         assertUnique(result);
89         assertTrue((data.size() > 0) ? result.size() > 0 : result.size() == 0);
90         assertTrue(result.size() <= data.size());
91     }
92 
93     @Test(dataProvider = "withNull:StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
testOpWithNull(String name, TestData.OfRef<Integer> data)94     public void testOpWithNull(String name, TestData.OfRef<Integer> data) {
95         Collection<Integer> node = exerciseOps(data, Stream::distinct);
96         assertUnique(node);
97 
98         node = withData(data).
99                 stream(s -> s.unordered().distinct()).
100                 exercise();
101         assertUnique(node);
102 
103         node = exerciseOps(data, s -> s.distinct().distinct());
104         assertUnique(node);
105     }
106 
107     @Test(dataProvider = "withNull:StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
testOpWithNullSorted(String name, TestData.OfRef<Integer> data)108     public void testOpWithNullSorted(String name, TestData.OfRef<Integer> data) {
109         ArrayList<Integer> l = new ArrayList<>();
110         data.into(l).sort(cNullInteger);
111         // Need to inject SORTED into the sorted list source since
112         // sorted() with a comparator ironically clears SORTED
113         Collection<Integer> node = exerciseOps(new SortedTestData<>(l), Stream::distinct);
114         assertUnique(node);
115         assertSorted(node, cNullInteger);
116     }
117 
118     @SuppressWarnings("serial")
119     static class SortedTestData<T> extends TestData.AbstractTestData.RefTestData<T, List<T>> {
SortedTestData(List<T> coll)120         SortedTestData(List<T> coll) {
121             super("SortedTestData", coll,
122                   c -> StreamSupport.stream(Spliterators.spliterator(c.toArray(), Spliterator.ORDERED | Spliterator.SORTED), false),
123                   c -> StreamSupport.stream(Spliterators.spliterator(c.toArray(), Spliterator.ORDERED | Spliterator.SORTED), true),
124                   c -> Spliterators.spliterator(c.toArray(), Spliterator.ORDERED | Spliterator.SORTED),
125                   List::size);
126         }
127     }
128 
129     public static final Comparator<Integer> cNullInteger = (a, b) -> {
130         if (a == null && b == null) {
131             return 0;
132         }
133         else if (a == null) {
134             return -1;
135         }
136         else if (b == null) {
137             return 1;
138         }
139         else {
140             return Integer.compare(a, b);
141         }
142     };
143 
144     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
testDistinctDistinct(String name, TestData.OfRef<Integer> data)145     public void testDistinctDistinct(String name, TestData.OfRef<Integer> data) {
146         Collection<Integer> result = exerciseOpsInt(
147                 data,
148                 s -> s.distinct().distinct(),
149                 s -> s.distinct().distinct(),
150                 s -> s.distinct().distinct(),
151                 s -> s.distinct().distinct());
152 
153          assertUnique(result);
154     }
155 
156     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
testDistinctSorted(String name, TestData.OfRef<Integer> data)157     public void testDistinctSorted(String name, TestData.OfRef<Integer> data) {
158         Collection<Integer> result = withData(data)
159                 .stream(s -> s.distinct().sorted(),
160                         new CollectorOps.TestParallelSizedOp<>())
161                 .exercise();
162         assertUnique(result);
163         assertSorted(result);
164     }
165 
166     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
testSortedDistinct(String name, TestData.OfRef<Integer> data)167     public void testSortedDistinct(String name, TestData.OfRef<Integer> data) {
168         Collection<Integer> result = withData(data)
169                 .stream(s -> s.sorted().distinct(),
170                         new CollectorOps.TestParallelSizedOp<>())
171                 .exercise();
172         assertUnique(result);
173         assertSorted(result);
174     }
175 
176     @Test
testStable()177     public void testStable() {
178         // Create N instances of Integer all with the same value
179         List<Integer> input = IntStream.rangeClosed(0, 1000)
180                 .mapToObj(i -> new Integer(1000)) // explicit construction
181                 .collect(Collectors.toList());
182         Integer expectedElement = input.get(0);
183         TestData<Integer, Stream<Integer>> data = TestData.Factory.ofCollection(
184                 "1000 instances of Integer with the same value", input);
185 
186         withData(data)
187                 .stream(Stream::distinct)
188                 .resultAsserter((actual, expected, isOrdered, isParallel) -> {
189                     List<Integer> l = new ArrayList<>();
190                     actual.forEach(l::add);
191 
192                     // Assert stability
193                     // The single result element should be equal in identity to
194                     // the first input element
195                     assertEquals(l.size(), 1);
196                     assertEquals(System.identityHashCode(l.get(0)),
197                                  System.identityHashCode(expectedElement));
198 
199                 })
200                 .exercise();
201     }
202 }
203