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 */
23package java.util.stream;
24
25import org.testng.annotations.Test;
26
27import java.util.ArrayList;
28import java.util.Arrays;
29import java.util.Comparator;
30import java.util.EnumSet;
31import java.util.List;
32import java.util.Spliterator;
33import java.util.function.Consumer;
34import java.util.function.Function;
35import java.util.function.ToDoubleFunction;
36import java.util.function.ToIntFunction;
37import java.util.function.ToLongFunction;
38
39import static java.util.stream.Collectors.toList;
40import static java.util.stream.StreamOpFlag.*;
41import static org.testng.Assert.*;
42import static org.testng.Assert.assertEquals;
43
44@Test
45public class StreamOpFlagsTest {
46
47    public void testNullCombine() {
48        int sourceFlags = StreamOpFlag.IS_SIZED;
49
50        assertEquals(sourceFlags, toStreamFlags(combineOpFlags(sourceFlags, StreamOpFlag.INITIAL_OPS_VALUE)));
51    }
52
53    public void testInitialOpFlagsFromSourceFlags() {
54        List<StreamOpFlag> flags = new ArrayList<>(StreamOpFlagTestHelper.allStreamFlags());
55        for (int i = 0; i < (1 << flags.size()); i++)  {
56            int sourceFlags = 0;
57            for (int f = 0; f < flags.size(); f++) {
58                if ((i & (1 << f)) != 0)  {
59                    sourceFlags |= flags.get(f).set();
60                }
61            }
62
63            int opsFlags = combineOpFlags(sourceFlags, StreamOpFlag.INITIAL_OPS_VALUE);
64            assertEquals(opsFlags, (~(sourceFlags << 1)) & StreamOpFlag.INITIAL_OPS_VALUE);
65        }
66    }
67
68    public void testSameCombine() {
69        for (StreamOpFlag f : StreamOpFlagTestHelper.allStreamFlags()) {
70            int sourceFlags = f.set();
71            int opsFlags;
72
73            opsFlags = combineOpFlags(sourceFlags, StreamOpFlag.INITIAL_OPS_VALUE);
74            opsFlags = combineOpFlags(f.set(), opsFlags);
75            assertEquals(sourceFlags, toStreamFlags(opsFlags));
76        }
77    }
78
79    public void testOpClear() {
80        for (StreamOpFlag f : StreamOpFlagTestHelper.allStreamFlags()) {
81            // Clear when source not set
82            int sourceFlags = 0;
83            int opsFlags;
84
85            opsFlags = combineOpFlags(sourceFlags, StreamOpFlag.INITIAL_OPS_VALUE);
86            opsFlags = combineOpFlags(f.clear(), opsFlags);
87            assertEquals(sourceFlags, toStreamFlags(opsFlags));
88
89            // Clear when source set
90            sourceFlags = f.set();
91
92            opsFlags = combineOpFlags(sourceFlags, StreamOpFlag.INITIAL_OPS_VALUE);
93            opsFlags = combineOpFlags(f.clear(), opsFlags);
94            assertEquals(0, toStreamFlags(opsFlags));
95        }
96    }
97
98    public void testOpInject() {
99        for (StreamOpFlag f : StreamOpFlagTestHelper.allStreamFlags()) {
100            // Set when source not set
101            int sourceFlags = 0;
102            int opsFlags;
103
104            opsFlags = combineOpFlags(sourceFlags, StreamOpFlag.INITIAL_OPS_VALUE);
105            opsFlags = combineOpFlags(f.set(), opsFlags);
106            assertEquals(f.set(), toStreamFlags(opsFlags));
107
108            // Set when source set
109            sourceFlags = f.set();
110
111            opsFlags = combineOpFlags(sourceFlags, StreamOpFlag.INITIAL_OPS_VALUE);
112            opsFlags = combineOpFlags(f.set(), opsFlags);
113            assertEquals(sourceFlags, toStreamFlags(opsFlags));
114        }
115    }
116
117    public void testPairSet() {
118        List<Integer> sourceFlagsList
119                = StreamOpFlagTestHelper.allStreamFlags().stream().map(StreamOpFlag::set).collect(toList());
120        sourceFlagsList.add(0, 0);
121
122        for (int sourceFlags : sourceFlagsList) {
123            for (StreamOpFlag f1 : StreamOpFlagTestHelper.allStreamFlags()) {
124                for (StreamOpFlag f2 : StreamOpFlagTestHelper.allStreamFlags()) {
125                    int opsFlags;
126
127                    opsFlags = combineOpFlags(sourceFlags, StreamOpFlag.INITIAL_OPS_VALUE);
128                    opsFlags = combineOpFlags(f1.set(), opsFlags);
129                    opsFlags = combineOpFlags(f2.set(), opsFlags);
130                    assertEquals(sourceFlags | f1.set() | f2.set(), toStreamFlags(opsFlags));
131                }
132            }
133        }
134    }
135
136    public void testPairSetAndClear() {
137        List<Integer> sourceFlagsList
138                = StreamOpFlagTestHelper.allStreamFlags().stream().map(StreamOpFlag::set).collect(toList());
139        sourceFlagsList.add(0, 0);
140
141        for (int sourceFlags : sourceFlagsList) {
142            for (StreamOpFlag f1 : StreamOpFlagTestHelper.allStreamFlags())  {
143                for (StreamOpFlag f2 : StreamOpFlagTestHelper.allStreamFlags()) {
144                    int opsFlags;
145
146                    opsFlags = combineOpFlags(sourceFlags, StreamOpFlag.INITIAL_OPS_VALUE);
147                    opsFlags = combineOpFlags(f1.set(), opsFlags);
148                    opsFlags = combineOpFlags(f2.clear(), opsFlags);
149                    if (f1 == f2)
150                        assertEquals((f2.set() == sourceFlags) ? 0 : sourceFlags, toStreamFlags(opsFlags));
151                    else
152                        assertEquals((f2.set() == sourceFlags) ? f1.set() : sourceFlags | f1.set(), toStreamFlags(opsFlags));
153                }
154            }
155        }
156    }
157
158    public void testShortCircuit() {
159        int opsFlags = combineOpFlags(0, StreamOpFlag.INITIAL_OPS_VALUE);
160        assertFalse(StreamOpFlag.SHORT_CIRCUIT.isKnown(opsFlags));
161
162        opsFlags = combineOpFlags(StreamOpFlag.IS_SHORT_CIRCUIT, opsFlags);
163        assertTrue(StreamOpFlag.SHORT_CIRCUIT.isKnown(opsFlags));
164
165        opsFlags = combineOpFlags(0, opsFlags);
166        assertTrue(StreamOpFlag.SHORT_CIRCUIT.isKnown(opsFlags));
167    }
168
169    public void testApplySourceFlags() {
170        int sourceFlags = StreamOpFlag.IS_SIZED | StreamOpFlag.IS_DISTINCT;
171
172        List<Integer> ops = Arrays.asList(StreamOpFlag.NOT_SIZED, StreamOpFlag.IS_ORDERED | StreamOpFlag.IS_SORTED);
173
174        int opsFlags = StreamOpFlag.combineOpFlags(sourceFlags, StreamOpFlag.INITIAL_OPS_VALUE);
175        for (int opFlags : ops) {
176            opsFlags = combineOpFlags(opFlags, opsFlags);
177        }
178        assertFalse(StreamOpFlag.SIZED.isKnown(opsFlags));
179        assertTrue(StreamOpFlag.SIZED.isCleared(opsFlags));
180        assertFalse(StreamOpFlag.SIZED.isPreserved(opsFlags));
181        assertTrue(StreamOpFlag.DISTINCT.isKnown(opsFlags));
182        assertFalse(StreamOpFlag.DISTINCT.isCleared(opsFlags));
183        assertFalse(StreamOpFlag.DISTINCT.isPreserved(opsFlags));
184        assertTrue(StreamOpFlag.SORTED.isKnown(opsFlags));
185        assertFalse(StreamOpFlag.SORTED.isCleared(opsFlags));
186        assertFalse(StreamOpFlag.SORTED.isPreserved(opsFlags));
187        assertTrue(StreamOpFlag.ORDERED.isKnown(opsFlags));
188        assertFalse(StreamOpFlag.ORDERED.isCleared(opsFlags));
189        assertFalse(StreamOpFlag.ORDERED.isPreserved(opsFlags));
190
191        int streamFlags = toStreamFlags(opsFlags);
192        assertFalse(StreamOpFlag.SIZED.isKnown(streamFlags));
193        assertTrue(StreamOpFlag.DISTINCT.isKnown(streamFlags));
194        assertTrue(StreamOpFlag.SORTED.isKnown(streamFlags));
195        assertTrue(StreamOpFlag.ORDERED.isKnown(streamFlags));
196    }
197
198    public void testSpliteratorMask() {
199        assertSpliteratorMask(StreamOpFlag.DISTINCT.set(), StreamOpFlag.IS_DISTINCT);
200        assertSpliteratorMask(StreamOpFlag.DISTINCT.clear(), 0);
201
202        assertSpliteratorMask(StreamOpFlag.SORTED.set(), StreamOpFlag.IS_SORTED);
203        assertSpliteratorMask(StreamOpFlag.SORTED.clear(), 0);
204
205        assertSpliteratorMask(StreamOpFlag.ORDERED.set(), StreamOpFlag.IS_ORDERED);
206        assertSpliteratorMask(StreamOpFlag.ORDERED.clear(), 0);
207
208        assertSpliteratorMask(StreamOpFlag.SIZED.set(), StreamOpFlag.IS_SIZED);
209        assertSpliteratorMask(StreamOpFlag.SIZED.clear(), 0);
210
211        assertSpliteratorMask(StreamOpFlag.SHORT_CIRCUIT.set(), 0);
212        assertSpliteratorMask(StreamOpFlag.SHORT_CIRCUIT.clear(), 0);
213    }
214
215    private void assertSpliteratorMask(int actual, int expected) {
216        assertEquals(actual & StreamOpFlag.SPLITERATOR_CHARACTERISTICS_MASK, expected);
217    }
218
219    public void testStreamMask() {
220        assertStreamMask(StreamOpFlag.DISTINCT.set(), StreamOpFlag.IS_DISTINCT);
221        assertStreamMask(StreamOpFlag.DISTINCT.clear(), 0);
222
223        assertStreamMask(StreamOpFlag.SORTED.set(), StreamOpFlag.IS_SORTED);
224        assertStreamMask(StreamOpFlag.SORTED.clear(), 0);
225
226        assertStreamMask(StreamOpFlag.ORDERED.set(), StreamOpFlag.IS_ORDERED);
227        assertStreamMask(StreamOpFlag.ORDERED.clear(), 0);
228
229        assertStreamMask(StreamOpFlag.SIZED.set(), StreamOpFlag.IS_SIZED);
230        assertStreamMask(StreamOpFlag.SIZED.clear(), 0);
231
232        assertStreamMask(StreamOpFlag.SHORT_CIRCUIT.set(), 0);
233        assertStreamMask(StreamOpFlag.SHORT_CIRCUIT.clear(), 0);
234    }
235
236    private void assertStreamMask(int actual, int expected) {
237        assertEquals(actual & StreamOpFlag.STREAM_MASK, expected);
238    }
239
240    public void testOpMask() {
241        assertOpMask(StreamOpFlag.DISTINCT.set(), StreamOpFlag.IS_DISTINCT);
242        assertOpMask(StreamOpFlag.DISTINCT.clear(), StreamOpFlag.NOT_DISTINCT);
243
244        assertOpMask(StreamOpFlag.SORTED.set(), StreamOpFlag.IS_SORTED);
245        assertOpMask(StreamOpFlag.SORTED.clear(), StreamOpFlag.NOT_SORTED);
246
247        assertOpMask(StreamOpFlag.ORDERED.set(), StreamOpFlag.IS_ORDERED);
248        assertOpMask(StreamOpFlag.ORDERED.clear(), StreamOpFlag.NOT_ORDERED);
249
250        assertOpMask(StreamOpFlag.SIZED.set(), 0);
251        assertOpMask(StreamOpFlag.SIZED.clear(), StreamOpFlag.NOT_SIZED);
252
253        assertOpMask(StreamOpFlag.SHORT_CIRCUIT.set(), StreamOpFlag.IS_SHORT_CIRCUIT);
254        assertOpMask(StreamOpFlag.SHORT_CIRCUIT.clear(), 0);
255    }
256
257    private void assertOpMask(int actual, int expected) {
258        assertEquals(actual & StreamOpFlag.OP_MASK, expected);
259    }
260
261    public void testTerminalOpMask() {
262        assertTerminalOpMask(StreamOpFlag.DISTINCT.set(), 0);
263        assertTerminalOpMask(StreamOpFlag.DISTINCT.clear(), 0);
264
265        assertTerminalOpMask(StreamOpFlag.SORTED.set(), 0);
266        assertTerminalOpMask(StreamOpFlag.SORTED.clear(), 0);
267
268        assertTerminalOpMask(StreamOpFlag.ORDERED.set(), 0);
269        assertTerminalOpMask(StreamOpFlag.ORDERED.clear(), StreamOpFlag.NOT_ORDERED);
270
271        assertTerminalOpMask(StreamOpFlag.SIZED.set(), 0);
272        assertTerminalOpMask(StreamOpFlag.SIZED.clear(), 0);
273
274        assertTerminalOpMask(StreamOpFlag.SHORT_CIRCUIT.set(), StreamOpFlag.IS_SHORT_CIRCUIT);
275        assertTerminalOpMask(StreamOpFlag.SHORT_CIRCUIT.clear(), 0);
276    }
277
278    private void assertTerminalOpMask(int actual, int expected) {
279        assertEquals(actual & StreamOpFlag.TERMINAL_OP_MASK, expected);
280    }
281
282    public void testUpstreamTerminalOpMask() {
283        assertUpstreamTerminalOpMask(StreamOpFlag.DISTINCT.set(), 0);
284        assertUpstreamTerminalOpMask(StreamOpFlag.DISTINCT.clear(), 0);
285
286        assertUpstreamTerminalOpMask(StreamOpFlag.SORTED.set(), 0);
287        assertUpstreamTerminalOpMask(StreamOpFlag.SORTED.clear(), 0);
288
289        assertUpstreamTerminalOpMask(StreamOpFlag.ORDERED.set(), 0);
290        assertUpstreamTerminalOpMask(StreamOpFlag.ORDERED.clear(), StreamOpFlag.NOT_ORDERED);
291
292        assertUpstreamTerminalOpMask(StreamOpFlag.SIZED.set(), 0);
293        assertUpstreamTerminalOpMask(StreamOpFlag.SIZED.clear(), 0);
294
295        assertUpstreamTerminalOpMask(StreamOpFlag.SHORT_CIRCUIT.set(), 0);
296        assertUpstreamTerminalOpMask(StreamOpFlag.SHORT_CIRCUIT.clear(), 0);
297    }
298
299    private void assertUpstreamTerminalOpMask(int actual, int expected) {
300        assertEquals(actual & StreamOpFlag.UPSTREAM_TERMINAL_OP_MASK, expected);
301    }
302
303    public void testSpliteratorCharacteristics() {
304        assertEquals(Spliterator.DISTINCT, StreamOpFlag.IS_DISTINCT);
305        assertEquals(Spliterator.SORTED, StreamOpFlag.IS_SORTED);
306        assertEquals(Spliterator.ORDERED, StreamOpFlag.IS_ORDERED);
307        assertEquals(Spliterator.SIZED, StreamOpFlag.IS_SIZED);
308
309        List<Integer> others = Arrays.asList(Spliterator.NONNULL, Spliterator.IMMUTABLE,
310                                             Spliterator.CONCURRENT, Spliterator.SUBSIZED);
311        for (int c : others) {
312            assertNotEquals(c, StreamOpFlag.IS_SHORT_CIRCUIT);
313        }
314    }
315
316    public void testSpliteratorCharacteristicsMask() {
317        assertSpliteratorCharacteristicsMask(StreamOpFlag.DISTINCT.set(), StreamOpFlag.IS_DISTINCT);
318        assertSpliteratorCharacteristicsMask(StreamOpFlag.DISTINCT.clear(), 0);
319
320        assertSpliteratorCharacteristicsMask(StreamOpFlag.SORTED.set(), StreamOpFlag.IS_SORTED);
321        assertSpliteratorCharacteristicsMask(StreamOpFlag.SORTED.clear(), 0);
322
323        assertSpliteratorCharacteristicsMask(StreamOpFlag.ORDERED.set(), StreamOpFlag.IS_ORDERED);
324        assertSpliteratorCharacteristicsMask(StreamOpFlag.ORDERED.clear(), 0);
325
326        assertSpliteratorCharacteristicsMask(StreamOpFlag.SIZED.set(), StreamOpFlag.IS_SIZED);
327        assertSpliteratorCharacteristicsMask(StreamOpFlag.SIZED.clear(), 0);
328
329        assertSpliteratorCharacteristicsMask(StreamOpFlag.SHORT_CIRCUIT.set(), 0);
330        assertSpliteratorCharacteristicsMask(StreamOpFlag.SHORT_CIRCUIT.clear(), 0);
331    }
332
333    private void assertSpliteratorCharacteristicsMask(int actual, int expected) {
334        assertEquals(StreamOpFlag.fromCharacteristics(actual), expected);
335    }
336
337    public void testSpliteratorSorted() {
338        class SortedEmptySpliterator implements Spliterator<Object> {
339            final Comparator<Object> c;
340
341            SortedEmptySpliterator(Comparator<Object> c) {
342                this.c = c;
343            }
344
345            @Override
346            public Spliterator<Object> trySplit() {
347                return null;
348            }
349
350            @Override
351            public boolean tryAdvance(Consumer<? super Object> action) {
352                return false;
353            }
354
355            @Override
356            public long estimateSize() {
357                return Long.MAX_VALUE;
358            }
359
360            @Override
361            public int characteristics() {
362                return Spliterator.SORTED;
363            }
364
365            @Override
366            public Comparator<? super Object> getComparator() {
367                return c;
368            }
369        };
370
371        {
372            int flags = StreamOpFlag.fromCharacteristics(new SortedEmptySpliterator(null));
373            assertEquals(flags, StreamOpFlag.IS_SORTED);
374        }
375
376        {
377            int flags = StreamOpFlag.fromCharacteristics(new SortedEmptySpliterator((a, b) -> 0));
378            assertEquals(flags, 0);
379        }
380    }
381}
382