1 /*
2  * Copyright (c) 2014, 2021, 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 /**
25  * @test
26  * @summary Tests counting of streams
27  * @bug 8031187 8067969 8075307 8265029
28  */
29 
30 package org.openjdk.tests.java.util.stream;
31 
32 import org.openjdk.testlib.java.util.stream.DoubleStreamTestDataProvider;
33 import org.openjdk.testlib.java.util.stream.IntStreamTestDataProvider;
34 import org.openjdk.testlib.java.util.stream.LambdaTestHelpers;
35 import org.openjdk.testlib.java.util.stream.LongStreamTestDataProvider;
36 import org.openjdk.testlib.java.util.stream.OpTestCase;
37 import org.openjdk.testlib.java.util.stream.StreamTestDataProvider;
38 import org.openjdk.testlib.java.util.stream.TestData;
39 
40 import java.util.concurrent.atomic.AtomicLong;
41 import java.util.stream.DoubleStream;
42 import java.util.stream.IntStream;
43 import java.util.stream.LongStream;
44 import java.util.stream.Stream;
45 import java.util.HashSet;
46 import java.util.concurrent.atomic.AtomicInteger;
47 import java.util.function.Supplier;
48 import java.util.stream.Collectors;
49 
50 import org.testng.annotations.Test;
51 
52 public class CountTest extends OpTestCase {
53 
54     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
testOps(String name, TestData.OfRef<Integer> data)55     public void testOps(String name, TestData.OfRef<Integer> data) {
56         long expectedCount = data.size();
57 
58         withData(data).
59                 terminal(Stream::count).
60                 expectedResult(expectedCount).
61                 exercise();
62 
63         withData(data).
64                 terminal(s -> s.skip(1), Stream::count).
65                 expectedResult(Math.max(0, expectedCount - 1)).
66                 exercise();
67 
68         // Test with an unknown sized stream
69         withData(data).
70                 terminal(s -> s.filter(e -> true), Stream::count).
71                 expectedResult(expectedCount).
72                 exercise();
73 
74         // Test counting collector
75         withData(data).
76                 terminal(s -> s, s -> s.collect(Collectors.counting())).
77                 expectedResult(expectedCount).
78                 exercise();
79 
80         // Test with stateful distinct op that is a barrier or lazy
81         // depending if source is not already distinct and encounter order is
82         // preserved or not
83         expectedCount = data.into(new HashSet<>()).size();
84         withData(data).
85                 terminal(Stream::distinct, Stream::count).
86                 expectedResult(expectedCount).
87                 exercise();
88         withData(data).
89                 terminal(s -> s.unordered().distinct(), Stream::count).
90                 expectedResult(expectedCount).
91                 exercise();
92     }
93 
94     @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
testOps(String name, TestData.OfInt data)95     public void testOps(String name, TestData.OfInt data) {
96         long expectedCount = data.size();
97 
98         withData(data).
99                 terminal(IntStream::count).
100                 expectedResult(expectedCount).
101                 exercise();
102 
103         withData(data).
104             terminal(s -> s.skip(1), IntStream::count).
105             expectedResult(Math.max(0, expectedCount - 1)).
106             exercise();
107 
108         withData(data).
109                 terminal(s -> s.filter(e -> true), IntStream::count).
110                 expectedResult(expectedCount).
111                 exercise();
112 
113         expectedCount = data.into(new HashSet<>()).size();
114         withData(data).
115                 terminal(IntStream::distinct, IntStream::count).
116                 expectedResult(expectedCount).
117                 exercise();
118         withData(data).
119                 terminal(s -> s.unordered().distinct(), IntStream::count).
120                 expectedResult(expectedCount).
121                 exercise();
122     }
123 
124     @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class)
testOps(String name, TestData.OfLong data)125     public void testOps(String name, TestData.OfLong data) {
126         long expectedCount = data.size();
127 
128         withData(data).
129                 terminal(LongStream::count).
130                 expectedResult(expectedCount).
131                 exercise();
132 
133         withData(data).
134             terminal(s -> s.skip(1), LongStream::count).
135             expectedResult(Math.max(0, expectedCount - 1)).
136             exercise();
137 
138         withData(data).
139                 terminal(s -> s.filter(e -> true), LongStream::count).
140                 expectedResult(expectedCount).
141                 exercise();
142 
143         expectedCount = data.into(new HashSet<>()).size();
144         withData(data).
145                 terminal(LongStream::distinct, LongStream::count).
146                 expectedResult(expectedCount).
147                 exercise();
148         withData(data).
149                 terminal(s -> s.unordered().distinct(), LongStream::count).
150                 expectedResult(expectedCount).
151                 exercise();
152     }
153 
154     @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class)
testOps(String name, TestData.OfDouble data)155     public void testOps(String name, TestData.OfDouble data) {
156         long expectedCount = data.size();
157 
158         withData(data).
159                 terminal(DoubleStream::count).
160                 expectedResult(expectedCount).
161                 exercise();
162 
163         withData(data).
164             terminal(s -> s.skip(1), DoubleStream::count).
165             expectedResult(Math.max(0, expectedCount - 1)).
166             exercise();
167 
168         withData(data).
169                 terminal(s -> s.filter(e -> true), DoubleStream::count).
170                 expectedResult(expectedCount).
171                 exercise();
172 
173         expectedCount = data.into(new HashSet<>()).size();
174         withData(data).
175                 terminal(DoubleStream::distinct, DoubleStream::count).
176                 expectedResult(expectedCount).
177                 exercise();
178         withData(data).
179                 terminal(s -> s.unordered().distinct(), DoubleStream::count).
180                 expectedResult(expectedCount).
181                 exercise();
182     }
183 
184     @Test
testNoEvaluationForSizedStream()185     public void testNoEvaluationForSizedStream() {
186         checkStreamDoesNotConsumeElements(() -> Stream.of(1, 2, 3, 4), 4);
187         checkStreamDoesNotConsumeElements(() -> Stream.of(1, 2, 3, 4).skip(1).limit(2).skip(1), 1);
188         checkIntStreamDoesNotConsumeElements(() -> IntStream.of(1, 2, 3, 4), 4);
189         checkIntStreamDoesNotConsumeElements(() -> IntStream.of(1, 2, 3, 4).skip(1).limit(2).skip(1), 1);
190         checkLongStreamDoesNotConsumeElements(() -> LongStream.of(1, 2, 3, 4), 4);
191         checkLongStreamDoesNotConsumeElements(() -> LongStream.of(1, 2, 3, 4).skip(1).limit(2).skip(1), 1);
192         checkDoubleStreamDoesNotConsumeElements(() -> DoubleStream.of(1, 2, 3, 4), 4);
193         checkDoubleStreamDoesNotConsumeElements(() -> DoubleStream.of(1, 2, 3, 4).skip(1).limit(2).skip(1), 1);
194     }
195 
checkStreamDoesNotConsumeElements(Supplier<Stream<?>> supplier, long expectedCount)196     private void checkStreamDoesNotConsumeElements(Supplier<Stream<?>> supplier, long expectedCount) {
197         AtomicInteger ai = new AtomicInteger();
198         assertEquals(supplier.get().peek(e -> ai.getAndIncrement()).count(), expectedCount);
199         assertEquals(ai.get(), 0);
200 
201         assertEquals(supplier.get().peek(e -> ai.getAndIncrement()).parallel().count(), expectedCount);
202         assertEquals(ai.get(), 0);
203     }
204 
checkIntStreamDoesNotConsumeElements(Supplier<IntStream> supplier, long expectedCount)205     private void checkIntStreamDoesNotConsumeElements(Supplier<IntStream> supplier, long expectedCount) {
206         AtomicInteger ai = new AtomicInteger();
207         assertEquals(supplier.get().peek(e -> ai.getAndIncrement()).count(), expectedCount);
208         assertEquals(ai.get(), 0);
209 
210         assertEquals(supplier.get().peek(e -> ai.getAndIncrement()).parallel().count(), expectedCount);
211         assertEquals(ai.get(), 0);
212     }
213 
checkLongStreamDoesNotConsumeElements(Supplier<LongStream> supplier, long expectedCount)214     private void checkLongStreamDoesNotConsumeElements(Supplier<LongStream> supplier, long expectedCount) {
215         AtomicInteger ai = new AtomicInteger();
216         assertEquals(supplier.get().peek(e -> ai.getAndIncrement()).count(), expectedCount);
217         assertEquals(ai.get(), 0);
218 
219         assertEquals(supplier.get().peek(e -> ai.getAndIncrement()).parallel().count(), expectedCount);
220         assertEquals(ai.get(), 0);
221     }
222 
checkDoubleStreamDoesNotConsumeElements(Supplier<DoubleStream> supplier, long expectedCount)223     private void checkDoubleStreamDoesNotConsumeElements(Supplier<DoubleStream> supplier, long expectedCount) {
224         AtomicInteger ai = new AtomicInteger();
225         assertEquals(supplier.get().peek(e -> ai.getAndIncrement()).count(), expectedCount);
226         assertEquals(ai.get(), 0);
227 
228         assertEquals(supplier.get().peek(e -> ai.getAndIncrement()).parallel().count(), expectedCount);
229         assertEquals(ai.get(), 0);
230     }
231 }
232