1/*
2 * Copyright (c) 2013, 2016, 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
24import org.testng.annotations.DataProvider;
25import org.testng.annotations.Test;
26
27import java.nio.CharBuffer;
28import java.util.ArrayDeque;
29import java.util.ArrayList;
30import java.util.Arrays;
31import java.util.BitSet;
32import java.util.HashMap;
33import java.util.HashSet;
34import java.util.IdentityHashMap;
35import java.util.LinkedHashMap;
36import java.util.LinkedHashSet;
37import java.util.LinkedList;
38import java.util.List;
39import java.util.PriorityQueue;
40import java.util.Set;
41import java.util.Spliterator;
42import java.util.Stack;
43import java.util.TreeMap;
44import java.util.TreeSet;
45import java.util.Vector;
46import java.util.WeakHashMap;
47import java.util.function.Function;
48import java.util.function.Supplier;
49import java.util.stream.Stream;
50
51import static org.testng.Assert.assertEquals;
52
53/**
54 * @test
55 * @bug 8148748 8170155
56 * @summary Spliterator last-binding tests
57 * @run testng SpliteratorLateBindingTest
58 */
59
60@Test
61public class SpliteratorLateBindingTest extends SpliteratorLateBindingFailFastHelper {
62
63    static Object[][] spliteratorDataProvider;
64
65    @DataProvider(name = "Source")
66    public static Object[][] sourceDataProvider() {
67        if (spliteratorDataProvider != null) {
68            return spliteratorDataProvider;
69        }
70
71        List<Object[]> data = new ArrayList<>();
72        SpliteratorDataBuilder<Integer> db =
73                new SpliteratorDataBuilder<>(data, 5, Arrays.asList(1, 2, 3, 4));
74
75        // Collections
76
77        db.addList(ArrayList::new);
78
79        db.addList(LinkedList::new);
80
81        db.addList(Vector::new);
82
83        db.addList(AbstractRandomAccessListImpl::new);
84
85        db.addCollection(HashSet::new);
86
87        db.addCollection(LinkedHashSet::new);
88
89        db.addCollection(TreeSet::new);
90
91        db.addCollection(c -> {
92            Stack<Integer> s = new Stack<>();
93            s.addAll(c);
94            return s;
95        });
96
97        db.addCollection(PriorityQueue::new);
98
99        db.addCollection(ArrayDeque::new);
100
101        // Maps
102
103        db.addMap(HashMap::new);
104
105        db.addMap(LinkedHashMap::new);
106
107        db.addMap(IdentityHashMap::new);
108
109        db.addMap(WeakHashMap::new);
110
111        // @@@  Descending maps etc
112        db.addMap(TreeMap::new);
113
114        // BitSet
115
116        List<Integer> bits = List.of(0, 1, 2);
117        Function<BitSet, Spliterator.OfInt> bitsSource = bs -> bs.stream().spliterator();
118        db.add("new BitSet.stream().spliterator() ADD",
119               () -> new IntSource<>(toBitSet(bits), bitsSource, bs -> bs.set(3)));
120        db.add("new BitSet.stream().spliterator() REMOVE",
121               () -> new IntSource<>(toBitSet(bits), bitsSource, bs -> bs.clear(2)));
122
123        // CharSequence
124
125        Function<CharSequence, Spliterator.OfInt> charsSource = sb -> sb.chars().spliterator();
126        Function<CharSequence, Spliterator.OfInt> pointsSource = sb -> sb.codePoints().spliterator();
127
128        db.add("new StringBuilder.chars().spliterator() ADD",
129               () -> new IntSource<>(new StringBuilder("ABC"), charsSource, bs -> bs.append("D"), true));
130        db.add("new StringBuilder.chars().spliterator() REMOVE",
131               () -> new IntSource<>(new StringBuilder("ABC"), charsSource, bs -> bs.deleteCharAt(2), true));
132        db.add("new StringBuilder.codePoints().spliterator() ADD",
133               () -> new IntSource<>(new StringBuilder("ABC"), pointsSource, bs -> bs.append("D"), true));
134        db.add("new StringBuilder.codePoints().spliterator() REMOVE",
135               () -> new IntSource<>(new StringBuilder("ABC"), pointsSource, bs -> bs.deleteCharAt(2), true));
136
137        db.add("new StringBuffer.chars().spliterator() ADD",
138               () -> new IntSource<>(new StringBuffer("ABC"), charsSource, bs -> bs.append("D"), true));
139        db.add("new StringBuffer.chars().spliterator() REMOVE",
140               () -> new IntSource<>(new StringBuffer("ABC"), charsSource, bs -> bs.deleteCharAt(2), true));
141        db.add("new StringBuffer.codePoints().spliterator() ADD",
142               () -> new IntSource<>(new StringBuffer("ABC"), pointsSource, bs -> bs.append("D"), true));
143        db.add("new StringBuffer.codePoints().spliterator() REMOVE",
144               () -> new IntSource<>(new StringBuffer("ABC"), pointsSource, bs -> bs.deleteCharAt(2), true));
145
146        db.add("CharBuffer.wrap().chars().spliterator() ADD",
147               () -> new IntSource<>(CharBuffer.wrap("ABCD").limit(3), charsSource, bs -> bs.limit(4), true));
148        db.add("CharBuffer.wrap().chars().spliterator() REMOVE",
149               () -> new IntSource<>(CharBuffer.wrap("ABCD"), charsSource, bs -> bs.limit(3), true));
150        db.add("CharBuffer.wrap().codePoints().spliterator() ADD",
151               () -> new IntSource<>(CharBuffer.wrap("ABCD").limit(3), pointsSource, bs -> bs.limit(4), true));
152        db.add("CharBuffer.wrap().codePoints().spliterator() REMOVE",
153               () -> new IntSource<>(CharBuffer.wrap("ABCD"), pointsSource, bs -> bs.limit(3), true));
154
155        return spliteratorDataProvider = data.toArray(new Object[0][]);
156    }
157
158
159    @DataProvider(name = "Source.Non.Binding.Characteristics")
160    public static Object[][] sourceCharacteristicsDataProvider() {
161        return Stream.of(sourceDataProvider()).filter(tc -> {
162            @SuppressWarnings("unchecked")
163            Supplier<Source<?>> s = (Supplier<Source<?>>) tc[1];
164            return !s.get().bindOnCharacteristics();
165        }).toArray(Object[][]::new);
166    }
167
168    static BitSet toBitSet(List<Integer> bits) {
169        BitSet bs = new BitSet();
170        bits.forEach(bs::set);
171        return bs;
172    }
173
174
175    @Test(dataProvider = "Source")
176    public <T> void testForEach(String description, Supplier<Source<T>> ss) {
177        Source<T> source = ss.get();
178        Spliterator<T> s = source.spliterator();
179
180        source.update();
181
182        Set<T> a = new HashSet<>();
183        s.forEachRemaining(a::add);
184
185        Set<T> e = new HashSet<>();
186        source.spliterator().forEachRemaining(e::add);
187        assertEquals(a, e);
188    }
189
190    @Test(dataProvider = "Source")
191    public <T> void testTryAdvance(String description, Supplier<Source<T>> ss) {
192        Source<T> source = ss.get();
193        Spliterator<T> s = source.spliterator();
194
195        source.update();
196
197        Set<T> a = new HashSet<>();
198        while (s.tryAdvance(a::add)) {
199        }
200
201        Set<T> e = new HashSet<>();
202        source.spliterator().forEachRemaining(e::add);
203        assertEquals(a, e);
204    }
205
206    @Test(dataProvider = "Source.Non.Binding.Characteristics")
207    public <T> void testCharacteristics(String description, Supplier<Source<T>> ss) {
208        Source<T> source = ss.get();
209        Spliterator<T> s = source.spliterator();
210
211        s.characteristics();
212        source.update();
213
214        Set<T> a = new HashSet<>();
215        s.forEachRemaining(a::add);
216
217        Set<T> e = new HashSet<>();
218        source.spliterator().forEachRemaining(e::add);
219        assertEquals(a, e);
220    }
221}
222