1/*
2 * Copyright (c) 1997, 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 org.openjdk.testlib.java.util.stream;
24
25import java.util.*;
26import java.util.stream.*;
27import java.util.function.BiConsumer;
28import java.util.function.BiPredicate;
29import java.util.function.BinaryOperator;
30import java.util.function.Consumer;
31import java.util.function.DoubleBinaryOperator;
32import java.util.function.DoubleConsumer;
33import java.util.function.DoublePredicate;
34import java.util.function.Function;
35import java.util.function.IntBinaryOperator;
36import java.util.function.IntConsumer;
37import java.util.function.IntFunction;
38import java.util.function.IntPredicate;
39import java.util.function.IntUnaryOperator;
40import java.util.function.LongBinaryOperator;
41import java.util.function.LongConsumer;
42import java.util.function.LongPredicate;
43import java.util.function.Predicate;
44import java.util.function.Supplier;
45import java.util.function.ToDoubleFunction;
46import java.util.function.ToIntFunction;
47import java.util.function.ToLongFunction;
48
49import static org.testng.Assert.assertEquals;
50import static org.testng.Assert.assertTrue;
51
52/**
53 * LambdaTestHelpers -- assertion methods and useful objects for lambda test cases
54 */
55public class LambdaTestHelpers {
56    public static final String LONG_STRING = "When in the Course of human events it becomes necessary for one people to dissolve the political bands which have connected them with another and to assume among the powers of the earth, the separate and equal station to which the Laws of Nature and of Nature's God entitle them, a decent respect to the opinions of mankind requires that they should declare the causes which impel them to the separation.";
57
58    @SuppressWarnings("rawtypes")
59    public static final Consumer bEmpty = x -> {  };
60    @SuppressWarnings("rawtypes")
61    public static final IntConsumer bIntEmpty = x -> {  };
62    @SuppressWarnings("rawtypes")
63    public static final BiConsumer bBiEmpty = (x,y) -> { };
64    @SuppressWarnings("rawtypes")
65    public static final Consumer bHashCode = x -> { Objects.hashCode(x); };
66    @SuppressWarnings("rawtypes")
67    public static final BiConsumer bBiHashCode = (x,y) -> { Objects.hash(x, y); };
68    public static final Function<Integer, Integer> mZero = x -> 0;
69    public static final Function<Integer, Integer> mId = x -> x;
70    public static final Function<Integer, Integer> mDoubler = x -> x * 2;
71    public static final Function<Integer, Stream<Integer>> mfId = e -> Collections.singletonList(e).stream();
72    public static final Function<Integer, Stream<Integer>> mfNull = e -> Collections.<Integer>emptyList().stream();
73    public static final Function<Integer, Stream<Integer>> mfLt = e -> {
74        List<Integer> l = new ArrayList<>();
75        for (int i=0; i<e; i++)
76            l.add(i);
77        return l.stream();
78    };
79    public static final ToIntFunction<Integer> imDoubler = x -> x * 2;
80    public static final ToLongFunction<Long> lmDoubler = x -> x * 2;
81    public static final ToDoubleFunction<Double> dmDoubler = x -> x * 2;
82    public static final Predicate<Integer> pFalse = x -> false;
83    public static final Predicate<Integer> pTrue = x -> true;
84    public static final Predicate<Integer> pEven = x -> 0 == x % 2;
85    public static final Predicate<Integer> pOdd = x -> 1 == x % 2;
86    public static final IntPredicate ipFalse = x -> false;
87    public static final IntPredicate ipTrue = x -> true;
88    public static final IntPredicate ipEven = x -> 0 == x % 2;
89    public static final IntPredicate ipOdd = x -> 1 == x % 2;
90    public static final LongPredicate lpFalse = x -> false;
91    public static final LongPredicate lpTrue = x -> true;
92    public static final LongPredicate lpEven = x -> 0 == x % 2;
93    public static final LongPredicate lpOdd = x -> 1 == x % 2;
94    public static final DoublePredicate dpFalse = x -> false;
95    public static final DoublePredicate dpTrue = x -> true;
96    public static final DoublePredicate dpEven = x -> 0 == ((long) x) % 2;
97    public static final DoublePredicate dpOdd = x -> 1 == ((long) x) % 2;
98    public static final BinaryOperator<Integer> rPlus = (x, y) -> x+y;
99    public static final BinaryOperator<Integer> rMax = (x, y) -> Math.max(x, y);
100    public static final BinaryOperator<Integer> rMin = (x, y) -> Math.min(x,y);
101    public static final IntBinaryOperator irPlus = (x, y) -> x+y;
102    public static final IntBinaryOperator irMax = (x, y) -> Math.max(x, y);
103    public static final IntBinaryOperator irMin = (x, y) -> Math.min(x,y);
104    public static final IntUnaryOperator irDoubler = x -> x * 2;
105    public static final LongBinaryOperator lrPlus = (x, y) -> x+y;
106    public static final DoubleBinaryOperator drPlus = (x, y) -> x+y;
107    public static final Comparator<Integer> cInteger = (a, b) -> Integer.compare(a, b);
108    public static final BiPredicate<?, ?> bipFalse = (x, y) -> false;
109    public static final BiPredicate<?, ?> bipTrue = (x, y) -> true;
110    public static final BiPredicate<Integer, Integer> bipBothEven = (x, y) -> 0 == (x % 2 + y % 2);
111    public static final BiPredicate<Integer, Integer> bipBothOdd = (x, y) -> 2 == (x % 2 + y % 2);
112    public static final BiPredicate<?, ?> bipSameString = (x, y) -> String.valueOf(x).equals(String.valueOf(y));
113
114    public static final IntFunction<Integer[]> integerArrayGenerator = s -> new Integer[s];
115
116    public static final IntFunction<Object[]> objectArrayGenerator = s -> new Object[s];
117
118    public static final Function<String, Stream<Character>> flattenChars = string -> {
119        List<Character> l = new ArrayList<>();
120        for (int i=0; i<string.length(); i++)
121            l.add(string.charAt(i));
122        return l.stream();
123    };
124
125    public static final Function<String, IntStream> flattenInt
126            = string -> IntStream.range(0, string.length()).map(string::charAt);
127
128    public static <T, R> Function<T, R> forPredicate(Predicate<? super T> predicate, R forTrue, R forFalse) {
129        Objects.requireNonNull(predicate);
130
131        return t -> predicate.test(t) ? forTrue : forFalse;
132    }
133
134    public static <T> Function<T, T> identity() {
135        return t -> t;
136    }
137
138    public static<V, T, R> Function<V, R> compose(Function<? super T, ? extends R> after, Function<? super V, ? extends T> before) {
139        Objects.requireNonNull(before);
140        return (V v) -> after.apply(before.apply(v));
141    }
142
143    public static List<Integer> empty() {
144        ArrayList<Integer> list = new ArrayList<>();
145        list.add(null);
146        return list;
147    }
148
149    public static List<Integer> countTo(int n) {
150        return range(1, n);
151    }
152
153    public static List<Integer> range(int l, int u) {
154        ArrayList<Integer> list = new ArrayList<>(u - l + 1);
155        for (int i=l; i<=u; i++) {
156            list.add(i);
157        }
158        return list;
159    }
160
161    public static List<Integer> repeat(int value, int n) {
162        ArrayList<Integer> list = new ArrayList<>(n);
163        for (int i=1; i<=n; i++) {
164            list.add(value);
165        }
166        return list;
167    }
168
169    public static List<Double> asDoubles(List<Integer> integers) {
170        ArrayList<Double> list = new ArrayList<>();
171        for (Integer i : integers) {
172            list.add((double) i);
173        }
174        return list;
175    }
176
177    public static List<Long> asLongs(List<Integer> integers) {
178        ArrayList<Long> list = new ArrayList<>();
179        for (Integer i : integers) {
180            list.add((long) i);
181        }
182        return list;
183    }
184
185    public static void assertCountSum(Stream<? super Integer> it, int count, int sum) {
186        assertCountSum(it.iterator(), count, sum);
187    }
188
189    public static void assertCountSum(Iterable<? super Integer> it, int count, int sum) {
190        assertCountSum(it.iterator(), count, sum);
191    }
192
193    public static void assertCountSum(Iterator<? super Integer> it, int count, int sum) {
194        int c = 0;
195        int s = 0;
196        while (it.hasNext()) {
197            int i = (Integer) it.next();
198            c++;
199            s += i;
200        }
201
202        assertEquals(c, count);
203        assertEquals(s, sum);
204    }
205
206    public static void assertConcat(Iterator<Character> it, String result) {
207        StringBuilder sb = new StringBuilder();
208        while (it.hasNext()) {
209            sb.append(it.next());
210        }
211
212        assertEquals(result, sb.toString());
213    }
214
215    public static<T extends Comparable<? super T>> void assertSorted(Iterator<T> i) {
216        i = toBoxedList(i).iterator();
217
218        if (!i.hasNext())
219            return;
220        T last = i.next();
221        while (i.hasNext()) {
222            T t = i.next();
223            assertTrue(last.compareTo(t) <= 0);
224            assertTrue(t.compareTo(last) >= 0);
225            last = t;
226        }
227    }
228
229    public static<T> void assertSorted(Iterator<T> i, Comparator<? super T> comp) {
230        if (i instanceof PrimitiveIterator.OfInt
231                || i instanceof PrimitiveIterator.OfDouble
232                || i instanceof PrimitiveIterator.OfLong) {
233            i = toBoxedList(i).iterator();
234        }
235
236        if (!i.hasNext())
237            return;
238        T last = i.next();
239        while (i.hasNext()) {
240            T t = i.next();
241            assertTrue(comp.compare(last, t) <= 0);
242            assertTrue(comp.compare(t, last) >= 0);
243            last = t;
244        }
245    }
246
247    public static<T extends Comparable<? super T>> void assertSorted(Iterable<T> iter) {
248        assertSorted(iter.iterator());
249    }
250
251    public static<T> void assertSorted(Iterable<T> iter, Comparator<? super T> comp) {
252        assertSorted(iter.iterator(), comp);
253    }
254
255    public static <T> void assertUnique(Iterable<T> iter) {
256        assertUnique(iter.iterator());
257    }
258
259    public static<T> void assertUnique(Iterator<T> iter) {
260        if (!iter.hasNext()) {
261            return;
262        }
263
264        if (iter instanceof PrimitiveIterator.OfInt
265            || iter instanceof PrimitiveIterator.OfDouble
266            || iter instanceof PrimitiveIterator.OfLong) {
267            iter = toBoxedList(iter).iterator();
268        }
269
270        Set<T> uniq = new HashSet<>();
271        while(iter.hasNext()) {
272            T each = iter.next();
273            assertTrue(!uniq.contains(each), "Not unique");
274            uniq.add(each);
275        }
276    }
277
278    public static<T> void assertContents(Iterable<T> actual, Iterable<T> expected) {
279        if (actual instanceof Collection && expected instanceof Collection) {
280            assertEquals(actual, expected);
281        } else {
282            assertContents(actual.iterator(), expected.iterator());
283        }
284    }
285
286    public static<T> void assertContents(Iterator<T> actual, Iterator<T> expected) {
287        assertEquals(toBoxedList(actual), toBoxedList(expected));
288    }
289
290    @SafeVarargs
291    @SuppressWarnings("varargs")
292    public static<T> void assertContents(Iterator<T> actual, T... expected) {
293        assertContents(actual, Arrays.asList(expected).iterator());
294    }
295
296    /**
297     * The all consuming consumer (rampant capitalist) that can accepting a reference or any primitive value.
298     */
299    private static interface OmnivorousConsumer<T>
300            extends Consumer<T>, IntConsumer, LongConsumer, DoubleConsumer { }
301
302    @SuppressWarnings({"rawtypes", "unchecked"})
303    public static<T> Consumer<T> toBoxingConsumer(Consumer<? super T> c) {
304        return (Consumer<T>) new OmnivorousConsumer() {
305            @Override
306            public void accept(Object t) {
307                c.accept((T) t);
308            }
309
310            @Override
311            public void accept(int t) {
312                accept((Object) t);
313            }
314
315            @Override
316            public void accept(long t) {
317                accept((Object) t);
318            }
319
320            @Override
321            public void accept(double t) {
322                accept((Object) t);
323            }
324        };
325    }
326
327    /**
328     * Convert an iterator to a list using forEach with an implementation of
329     * {@link java.util.stream.LambdaTestHelpers.OmnivorousConsumer}.
330     *
331     * This ensures equality comparisons for test results do not trip
332     * the boxing trip-wires.
333     */
334    private static<T> List<T> toBoxedList(Iterator<T> it) {
335        List<T> l = new ArrayList<>();
336        it.forEachRemaining(toBoxingConsumer(l::add));
337        return l;
338    }
339
340    /**
341     * Convert a spliterator to a list using forEach with an implementation of
342     * {@link java.util.stream.LambdaTestHelpers.OmnivorousConsumer}.
343     *
344     * This ensures equality comparisons for test results do not trip
345     * the boxing trip-wires.
346     */
347    public static<T> List<T> toBoxedList(Spliterator<T> sp) {
348        List<T> l = new ArrayList<>();
349        sp.forEachRemaining(toBoxingConsumer(l::add));
350        return l;
351    }
352
353    /**
354     * Convert an iterator to a multi-set, represented as a Map, using forEach with an implementation of
355     * {@link java.util.stream.LambdaTestHelpers.OmnivorousConsumer}.
356     *
357     * This ensures equality comparisons for test results do not trip
358     * the boxing trip-wires.
359     */
360    @SuppressWarnings("unchecked")
361    private static<T> Map<T, Integer> toBoxedMultiset(Iterator<T> it) {
362        Map<Object, Integer> result = new HashMap<>();
363
364        it.forEachRemaining(toBoxingConsumer(o -> {
365                if (result.containsKey(o))
366                    result.put(o, result.get(o) + 1);
367                else
368                    result.put(o, 1);
369            }));
370
371        return (Map<T, Integer>) result;
372    }
373
374    @SuppressWarnings("unchecked")
375    public static<T> Map<T, Integer> toBoxedMultiset(Spliterator<T> it) {
376        Map<Object, Integer> result = new HashMap<>();
377
378        it.forEachRemaining(toBoxingConsumer(o -> {
379                if (result.containsKey(o))
380                    result.put(o, result.get(o) + 1);
381                else
382                    result.put(o, 1);
383            }));
384
385        return (Map<T, Integer>) result;
386    }
387
388    @SuppressWarnings("unchecked")
389    public static void assertContentsEqual(Object a, Object b) {
390        if (a instanceof Iterable && b instanceof Iterable)
391            assertContents((Iterable) a, (Iterable) b);
392        else
393            assertEquals(a, b);
394    }
395
396    public static<T> void assertContentsUnordered(Iterable<T> actual, Iterable<T> expected) {
397        assertContentsUnordered(actual.iterator(), expected.iterator());
398    }
399
400    public static<T> void assertContentsUnordered(Iterator<T> actual, Iterator<T> expected) {
401        assertEquals(toBoxedMultiset(actual), toBoxedMultiset(expected));
402    }
403
404    public static void launderAssertion(Runnable r, Supplier<String> additionalInfo) {
405        try {
406            r.run();
407        }
408        catch (AssertionError ae) {
409            AssertionError cloned = new AssertionError(ae.getMessage() + String.format("%n%s", additionalInfo.get()));
410            cloned.setStackTrace(ae.getStackTrace());
411            if (ae.getCause() != null)
412                cloned.initCause(ae.getCause());
413            throw cloned;
414        }
415    }
416
417    public static <T, S extends BaseStream<T, S>>
418    List<Function<S, S>> permuteStreamFunctions(List<Function<S, S>> opFunctions) {
419        List<List<Function<S, S>>> opFunctionPermutations = perm(opFunctions);
420
421        List<Function<S, S>> appliedFunctions = new ArrayList<>();
422        for (List<Function<S, S>> fs : opFunctionPermutations) {
423            Function<S, S> applied = s -> {
424                for (Function<S, S> f : fs) {
425                    s = f.apply(s);
426                }
427                return s;
428            };
429            appliedFunctions.add(applied);
430        }
431
432        return appliedFunctions;
433    }
434
435    private static <T> List<T> sub(List<T> l, int index) {
436        List<T> subL = new ArrayList<>(l);
437        subL.remove(index);
438        return subL;
439    }
440
441    public static <T> List<List<T>> perm(List<T> l) {
442        List<List<T>> result = new ArrayList<>();
443        for (int i = 0; i < l.size(); i++) {
444            for (List<T> perm : perm(sub(l, i))) {
445                perm.add(0, l.get(i));
446                result.add(perm);
447            }
448        }
449        result.add(new ArrayList<T>());
450
451        return result;
452    }
453
454    public static String flagsToString(int flags) {
455        StringJoiner sj = new StringJoiner(", ", "StreamOpFlag[", "]");
456        if (StreamOpFlag.DISTINCT.isKnown(flags)) sj.add("IS_DISTINCT");
457        if (StreamOpFlag.ORDERED.isKnown(flags)) sj.add("IS_ORDERED");
458        if (StreamOpFlag.SIZED.isKnown(flags)) sj.add("IS_SIZED");
459        if (StreamOpFlag.SORTED.isKnown(flags)) sj.add("IS_SORTED");
460        if (StreamOpFlag.SHORT_CIRCUIT.isKnown(flags)) sj.add("IS_SHORT_CIRCUIT");
461        return sj.toString();
462    }
463}
464