/*
* Copyright 2015, 2016 Tagir Valeev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package one.util.streamex;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Map.Entry;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinWorkerThread;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import one.util.streamex.DoubleStreamEx;
import one.util.streamex.EntryStream;
import one.util.streamex.IntStreamEx;
import one.util.streamex.LongStreamEx;
import one.util.streamex.MoreCollectors;
import one.util.streamex.StreamEx;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import static org.junit.Assert.*;
/**
* @author Tagir Valeev
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class CustomPoolTest {
ForkJoinPool pool = new ForkJoinPool(3);
private void checkThread(Object element) {
Thread thread = Thread.currentThread();
if (!(thread instanceof ForkJoinWorkerThread))
throw new IllegalStateException("Not inside FJP (element: " + element + ")");
if (((ForkJoinWorkerThread) thread).getPool() != pool)
throw new IllegalStateException("FJP is incorrect (element: " + element + ")");
}
@Test(expected = IllegalStateException.class)
public void testCheckThreadSequential() {
StreamEx.of("a", "b").peek(this::checkThread).joining();
}
@Test(expected = IllegalStateException.class)
public void testCheckThreadParallel() {
StreamEx.of("a", "b").parallel().peek(this::checkThread).joining();
}
@Test
public void testStreamEx() {
StreamEx.of("a", "b", "c").parallel(pool).forEach(this::checkThread);
assertEquals(Arrays.asList(1, 2), StreamEx.of("a", "bb").parallel(pool).peek(this::checkThread).map(
String::length).toList());
assertEquals("a", StreamEx.of("a").parallel(pool).peek(this::checkThread).findAny().get());
assertEquals("a", StreamEx.of("a", "b").parallel(pool).peek(this::checkThread).findFirst().get());
assertTrue(StreamEx.of("a", "b").parallel(pool).peek(this::checkThread).anyMatch("a"::equals));
assertFalse(StreamEx.of("a", "b").parallel(pool).peek(this::checkThread).allMatch("a"::equals));
assertFalse(StreamEx.of("a", "b").parallel(pool).peek(this::checkThread).noneMatch("a"::equals));
assertEquals(Arrays.asList("b", "c"), StreamEx.of("a", "b", "c").parallel(pool).peek(this::checkThread).skip(1)
.collect(Collectors.toList()));
assertEquals(6, StreamEx.of("a", "bb", "ccc").parallel(pool).peek(this::checkThread).collect(
StringBuilder::new, StringBuilder::append, StringBuilder::append).length());
assertArrayEquals(new String[] { "a", "b", "c" }, StreamEx.of("a", "b", "c").parallel(pool).peek(
this::checkThread).toArray(String[]::new));
assertArrayEquals(new Object[] { "a", "b", "c" }, StreamEx.of("a", "b", "c").parallel(pool).peek(
this::checkThread).toArray());
assertEquals("{ccc={bb={a={}}}}", StreamEx.of("a", "bb", "ccc").parallel(pool).peek(this::checkThread)
.foldLeft(Collections.emptyMap(),
(Map<String, Object> acc, String v) -> Collections.singletonMap(v, acc)).toString());
assertEquals(1000, IntStreamEx.constant(1, 1000).boxed().parallel(pool).peek(this::checkThread).foldLeft(0,
Integer::sum).intValue());
assertEquals(2, StreamEx.of("aa", "bbb", "cccc").parallel(pool).peek(this::checkThread).filter(
x -> x.length() > 2).count());
assertEquals("bbbcccc", StreamEx.of("aa", "bbb", "cccc").parallel(pool).peek(this::checkThread).filter(
x -> x.length() > 2).reduce(String::concat).get());
assertEquals("bbbcccc", StreamEx.of("aa", "bbb", "cccc").parallel(pool).peek(this::checkThread).filter(
x -> x.length() > 2).reduce("", String::concat));
assertEquals(7, (int) StreamEx.of("aa", "bbb", "cccc").parallel(pool).peek(this::checkThread).filter(
x -> x.length() > 2).reduce(0, (x, s) -> x + s.length(), Integer::sum));
assertEquals("aabbbcccc", StreamEx.of("aa", "bbb", "cccc").parallel(pool).peek(this::checkThread).foldLeft("",
String::concat));
assertEquals(Arrays.asList(1, 2, 3), StreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).toListAndThen(
list -> {
this.checkThread(list);
return list;
}));
assertEquals(new HashSet<>(Arrays.asList(1, 2, 3)), StreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread)
.toSetAndThen(list -> {
this.checkThread(list);
return list;
}));
assertEquals(Collections.singletonMap(1, 3L), StreamEx.of(1, 1, 1).parallel(pool).peek(this::checkThread)
.runLengths().toMap());
}
@Test
public void testEntryStream() {
EntryStream.of("a", 1).parallel(pool).forEach(this::checkThread);
assertEquals(Integer.valueOf(1), EntryStream.of("a", 1).parallel(pool).peek(this::checkThread).toMap().get("a"));
assertEquals(Integer.valueOf(1), EntryStream.of("a", 1).parallel(pool).peek(this::checkThread).findAny(
e -> e.getKey().equals("a")).get().getValue());
assertEquals(Integer.valueOf(1), EntryStream.of("a", 1).parallel(pool).peek(this::checkThread).findFirst(
e -> e.getKey().equals("a")).get().getValue());
assertTrue(EntryStream.of("a", 1).parallel(pool).peek(this::checkThread).anyMatch(e -> e.getKey().equals("a")));
assertTrue(EntryStream.of("a", 1).parallel(pool).peek(this::checkThread).allMatch(e -> e.getKey().equals("a")));
assertFalse(EntryStream.of("a", 1).parallel(pool).peek(this::checkThread)
.noneMatch(e -> e.getKey().equals("a")));
assertEquals(2, EntryStream.of("a", 1, "b", 2, "c", 3).parallel(pool).peek(this::checkThread).filterValues(
v -> v > 1).count());
List<Integer> res = new ArrayList<>();
EntryStream.of("a", 1, "b", 2, "c", 3).parallel(pool).peek(this::checkThread).filterValues(v -> v > 1)
.forEachOrdered(entry -> res.add(entry.getValue()));
assertEquals(Arrays.asList(2, 3), res);
assertEquals(2L, (long) EntryStream.of("a", 1, "b", 2, "c", 3).parallel(pool).peek(this::checkThread)
.filterValues(v -> v > 1).collect(Collectors.counting()));
assertEquals(6, (int) EntryStream.of("a", 1, "b", 2, "c", 3).parallel(pool).peek(this::checkThread).reduce(0,
(sum, e) -> sum + e.getValue(), Integer::sum));
assertEquals(Arrays.asList(1, 2, 3), EntryStream.of("a", 1, "b", 2, "c", 3).parallel(pool).peek(
this::checkThread).collect(ArrayList::new,
(List<Integer> list, Entry<String, Integer> e) -> list.add(e.getValue()), List::addAll));
@SuppressWarnings("unchecked")
Entry<String, Integer>[] array = EntryStream.of("a", 1, "b", 2, "c", 3).parallel(pool).peek(this::checkThread)
.filterValues(v -> v > 1).toArray(Entry[]::new);
assertEquals(2, array.length);
assertEquals(new SimpleEntry<>("b", 2), array[0]);
assertEquals(new SimpleEntry<>("c", 3), array[1]);
List<Entry<String, Integer>> list = EntryStream.of("a", 1, "b", 2, "c", 3).parallel(pool).peek(
this::checkThread).filterValues(v -> v > 1).toListAndThen(l -> {
this.checkThread(l);
return l;
});
assertEquals(Arrays.asList(array), list);
Map<String, Integer> map = EntryStream.of("a", 1, "b", 2, "c", 3).parallel(pool).peek(
this::checkThread).filterValues(v -> v > 1).toMapAndThen(m -> {
this.checkThread(m);
return m;
});
assertEquals(EntryStream.of("b", 2, "c", 3).toMap(), map);
assertEquals(new SimpleEntry<>("abc", 6), EntryStream.of("a", 1, "b", 2, "c", 3).parallel(pool).peek(
this::checkThread).reduce(
(e1, e2) -> new SimpleEntry<>(e1.getKey() + e2.getKey(), e1.getValue() + e2.getValue())).orElse(null));
assertEquals(new SimpleEntry<>("abc", 6), EntryStream.of("a", 1, "b", 2, "c", 3).parallel(pool).peek(
this::checkThread).reduce(new SimpleEntry<>("", 0),
(e1, e2) -> new SimpleEntry<>(e1.getKey() + e2.getKey(), e1.getValue() + e2.getValue())));
}
@Test
public void testIntStreamEx() {
IntStreamEx.range(0, 4).parallel(pool).forEach(this::checkThread);
assertEquals(6, IntStreamEx.range(0, 4).parallel(pool).peek(this::checkThread).sum());
assertEquals(3, IntStreamEx.range(0, 4).parallel(pool).peek(this::checkThread).max().getAsInt());
assertEquals(0, IntStreamEx.range(0, 4).parallel(pool).peek(this::checkThread).min().getAsInt());
assertEquals(1.5, IntStreamEx.range(0, 4).parallel(pool).peek(this::checkThread).average().getAsDouble(),
0.000001);
assertEquals(4, IntStreamEx.range(0, 4).parallel(pool).peek(this::checkThread).summaryStatistics().getCount());
assertArrayEquals(new int[] { 1, 2, 3 }, IntStreamEx.range(0, 5).parallel(pool).peek(this::checkThread).skip(1)
.limit(3).toArray());
assertEquals(6, IntStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).reduce(Integer::sum).getAsInt());
assertTrue(IntStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).has(1));
assertTrue(IntStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).anyMatch(x -> x == 2));
assertFalse(IntStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).allMatch(x -> x == 2));
assertFalse(IntStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).noneMatch(x -> x == 2));
assertEquals(6, IntStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).reduce(1, (a, b) -> a * b));
assertEquals(2, IntStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).atLeast(2).count());
assertEquals(2, IntStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).findAny(x -> x % 2 == 0)
.getAsInt());
assertEquals(2, IntStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).findFirst(x -> x % 2 == 0)
.getAsInt());
List<Integer> res = new ArrayList<>();
IntStreamEx.of(1, 5, 10, Integer.MAX_VALUE).parallel(pool).peek(this::checkThread).map(x -> x * 2)
.forEachOrdered(res::add);
//noinspection NumericOverflow
assertEquals(Arrays.asList(2, 10, 20, Integer.MAX_VALUE * 2), res);
assertArrayEquals(new int[] { 1, 3, 6, 10 }, IntStreamEx.of(1, 2, 3, 4).parallel(pool).peek(this::checkThread)
.scanLeft((a, b) -> {
checkThread(b);
return a + b;
}));
}
@Test
public void testLongStreamEx() {
LongStreamEx.range(0, 4).parallel(pool).forEach(this::checkThread);
assertEquals(999999000000L, IntStreamEx.range(1000000).parallel(pool).peek(this::checkThread).asLongStream()
.map(x -> x * 2).sum());
assertEquals(6, LongStreamEx.range(0, 4).parallel(pool).peek(this::checkThread).sum());
assertEquals(3, LongStreamEx.range(0, 4).parallel(pool).peek(this::checkThread).max().getAsLong());
assertEquals(0, LongStreamEx.range(0, 4).parallel(pool).peek(this::checkThread).min().getAsLong());
assertEquals(1.5, LongStreamEx.range(0, 4).parallel(pool).peek(this::checkThread).average().getAsDouble(),
0.000001);
assertEquals(4, LongStreamEx.range(0, 4).parallel(pool).peek(this::checkThread).summaryStatistics().getCount());
assertArrayEquals(new long[] { 1, 2, 3 }, LongStreamEx.range(0, 5).parallel(pool).peek(this::checkThread).skip(
1).limit(3).toArray());
assertEquals(6, LongStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).reduce(Long::sum).getAsLong());
assertTrue(LongStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).has(1));
assertTrue(LongStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).anyMatch(x -> x == 2));
assertFalse(LongStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).allMatch(x -> x == 2));
assertFalse(LongStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).noneMatch(x -> x == 2));
assertEquals(6, LongStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).reduce(1, (a, b) -> a * b));
assertEquals(2, LongStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).atLeast(2).count());
assertEquals(2, LongStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).findAny(x -> x % 2 == 0)
.getAsLong());
assertEquals(2, LongStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).findFirst(x -> x % 2 == 0)
.getAsLong());
List<Long> res = new ArrayList<>();
LongStreamEx.of(1, 5, 10, Integer.MAX_VALUE).parallel(pool).peek(this::checkThread).map(x -> x * 2)
.forEachOrdered(res::add);
assertEquals(Arrays.asList(2L, 10L, 20L, Integer.MAX_VALUE * 2L), res);
assertArrayEquals(new long[] { 1, 3, 6, 10 }, LongStreamEx.of(1, 2, 3, 4).parallel(pool)
.peek(this::checkThread).scanLeft((a, b) -> {
checkThread(b);
return a + b;
}));
}
@Test
public void testDoubleStreamEx() {
LongStreamEx.range(0, 4).asDoubleStream().parallel(pool).forEach(this::checkThread);
assertEquals(6, IntStreamEx.range(0, 4).parallel(pool).peek(this::checkThread).asDoubleStream().sum(), 0);
assertEquals(3, IntStreamEx.range(0, 4).parallel(pool).peek(this::checkThread).asDoubleStream().max()
.getAsDouble(), 0);
assertEquals(0, IntStreamEx.range(0, 4).parallel(pool).peek(this::checkThread).asDoubleStream().min()
.getAsDouble(), 0);
assertEquals(1.5, IntStreamEx.range(0, 4).parallel(pool).peek(this::checkThread).asDoubleStream().average()
.getAsDouble(), 0.000001);
assertEquals(4, IntStreamEx.range(0, 4).parallel(pool).peek(this::checkThread).asDoubleStream()
.summaryStatistics().getCount());
assertArrayEquals(new double[] { 1, 2, 3 }, IntStreamEx.range(0, 5).asDoubleStream().skip(1).limit(3).parallel(
pool).peek(this::checkThread).toArray(), 0.0);
assertEquals(6.0, DoubleStreamEx.of(1.0, 2.0, 3.0).parallel(pool).peek(this::checkThread).reduce(Double::sum)
.getAsDouble(), 0.0);
assertTrue(DoubleStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).anyMatch(x -> x == 2));
assertFalse(DoubleStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).allMatch(x -> x == 2));
assertFalse(DoubleStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).noneMatch(x -> x == 2));
assertEquals(6.0, DoubleStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).reduce(1, (a, b) -> a * b),
0.0);
assertEquals(2, DoubleStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).atLeast(2.0).count());
assertEquals(2.0, DoubleStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).findAny(x -> x % 2 == 0)
.getAsDouble(), 0.0);
assertEquals(2.0, DoubleStreamEx.of(1, 2, 3).parallel(pool).peek(this::checkThread).findFirst(x -> x % 2 == 0)
.getAsDouble(), 0.0);
List<Double> res = new ArrayList<>();
DoubleStreamEx.of(1.0, 2.0, 3.5, 4.5).parallel(pool).peek(this::checkThread).map(x -> x * 2).forEachOrdered(
res::add);
assertEquals(Arrays.asList(2.0, 4.0, 7.0, 9.0), res);
assertArrayEquals(new double[] { 1, 3, 6, 10 }, DoubleStreamEx.of(1, 2, 3, 4).parallel(pool).peek(
this::checkThread).scanLeft((a, b) -> {
checkThread(b);
return a + b;
}), 0.0);
}
@Test
public void testPairMap() {
BitSet bits = IntStreamEx.range(3, 199).toBitSet();
IntStreamEx.range(200).parallel(pool).filter(i -> {
checkThread(i);
return i > 2;
}).boxed().pairMap(SimpleEntry<Integer, Integer>::new).forEach(p -> {
checkThread(p);
assertEquals(1, p.getValue() - p.getKey());
assertTrue(p.getKey().toString(), bits.get(p.getKey()));
bits.clear(p.getKey());
});
}
@Test
public void testShortCircuit() {
AtomicInteger counter = new AtomicInteger(0);
assertEquals(Optional.empty(), IntStreamEx.range(0, 10000).boxed().parallel(pool).peek(this::checkThread).peek(
t -> counter.incrementAndGet()).collect(MoreCollectors.onlyOne()));
assertTrue(counter.get() < 10000);
counter.set(0);
assertEquals(Optional.empty(), IntStreamEx.range(0, 10000).boxed().mapToEntry(x -> x).parallel(pool).peek(
this::checkThread).peek(t -> counter.incrementAndGet()).collect(MoreCollectors.onlyOne()));
assertTrue(counter.get() < 10000);
}
}