blob: 68140c7ada316e1a5f63ee1514b4a738536a158d [file] [log] [blame]
/*
* Copyright 2016 Google Inc.
*
* 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 com.google.gwt.emultest.java8.util.stream;
import com.google.gwt.emultest.java.util.EmulTestBase;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.DoubleSummaryStatistics;
import java.util.Iterator;
import java.util.List;
import java.util.OptionalDouble;
import java.util.Spliterator;
import java.util.function.DoubleSupplier;
import java.util.function.Supplier;
import java.util.stream.DoubleStream;
import java.util.stream.Stream;
/**
* Tests {@link DoubleStream}.
*/
public class DoubleStreamTest extends EmulTestBase {
public void testEmptyStream() {
DoubleStream empty = DoubleStream.empty();
assertEquals(0, empty.count());
try {
empty.count();
fail("second terminal operation should have thrown IllegalStateEx");
} catch (IllegalStateException expected) {
// expected
}
assertEquals(0, DoubleStream.empty().limit(2).toArray().length);
assertEquals(0L, DoubleStream.empty().count());
assertEquals(0L, DoubleStream.empty().limit(2).count());
assertFalse(DoubleStream.empty().findFirst().isPresent());
assertFalse(DoubleStream.empty().findAny().isPresent());
assertFalse(DoubleStream.empty().max().isPresent());
assertFalse(DoubleStream.empty().min().isPresent());
assertTrue(DoubleStream.empty().noneMatch(item -> true));
assertTrue(DoubleStream.empty().allMatch(item -> true));
assertFalse(DoubleStream.empty().anyMatch(item -> true));
assertEquals(new double[0], DoubleStream.empty().toArray());
}
public void testStreamOfOne() {
Supplier<DoubleStream> one = () -> DoubleStream.of(1);
assertEquals(new double[] {1d}, one.get().toArray());
assertEquals(1L, one.get().count());
assertEquals(1d, one.get().findFirst().getAsDouble(), 0d);
assertEquals(1d, one.get().findAny().getAsDouble(), 0d);
}
public void testBuilder() {
DoubleStream s = DoubleStream.builder().add(1d).add(3d).add(2d).build();
assertEquals(new double[] {1d, 3d, 2d}, s.toArray());
DoubleStream.Builder builder = DoubleStream.builder();
DoubleStream built = builder.build();
assertEquals(0, built.count());
try {
builder.build();
fail("build() after build() should fail");
} catch (IllegalStateException expected) {
// expected
}
try {
builder.add(10d);
fail("add() after build() should fail");
} catch (IllegalStateException expected) {
// expected
}
}
public void testConcat() {
Supplier<DoubleStream> adbc =
() -> {
return DoubleStream.concat(DoubleStream.of(1, 4), DoubleStream.of(2, 3));
};
assertEquals(new double[] {1d, 4d, 2d, 3d}, adbc.get().toArray());
assertEquals(new double[] {1d, 2d, 3d, 4d}, adbc.get().sorted().toArray());
List<String> closed = new ArrayList<>();
DoubleStream first = DoubleStream.of(1d).onClose(() -> closed.add("first"));
DoubleStream second = DoubleStream.of(2d).onClose(() -> closed.add("second"));
DoubleStream concat = DoubleStream.concat(first, second);
// read everything, make sure we saw it all and didn't close automatically
double collectedAll = concat.sum();
assertEquals(3d, collectedAll);
assertEquals(0, closed.size());
concat.close();
assertEquals(Arrays.asList("first", "second"), closed);
}
public void testIterate() {
assertEquals(
new double[] {10d, 11d, 12d, 13d, 14d},
DoubleStream.iterate(0d, l -> l + 1d).skip(10).limit(5).toArray());
}
public void testGenerate() {
// infinite, but if you limit it is already too short to skip much
assertEquals(new double[0], DoubleStream.generate(makeGenerator()).limit(4).skip(5).toArray());
assertEquals(
new double[] {10d, 11d, 12d, 13d, 14d},
DoubleStream.generate(makeGenerator()).skip(10).limit(5).toArray());
}
private DoubleSupplier makeGenerator() {
return new DoubleSupplier() {
double next = 0d;
@Override
public double getAsDouble() {
return next++;
}
};
}
public void testToArray() {
assertEquals(new double[0], DoubleStream.of().toArray());
assertEquals(new double[] {1d}, DoubleStream.of(1d).toArray());
assertEquals(new double[] {3d, 2d, 0d}, DoubleStream.of(3d, 2d, 0d).toArray());
}
public void testReduce() {
double reduced = DoubleStream.of(1d, 2d, 4d).reduce(0, Double::sum);
assertEquals(7d, reduced, 0d);
reduced = DoubleStream.of().reduce(0, Double::sum);
assertEquals(0d, reduced, 0d);
OptionalDouble maybe = DoubleStream.of(1d, 4d, 8d).reduce(Double::sum);
assertTrue(maybe.isPresent());
assertEquals(13, maybe.getAsDouble(), 0d);
maybe = DoubleStream.of().reduce(Double::sum);
assertFalse(maybe.isPresent());
}
public void testFilter() {
// unconsumed stream never runs filter
boolean[] data = {false};
DoubleStream.of(1d, 2d, 3d).filter(i -> data[0] |= true);
assertFalse(data[0]);
// Nothing's *defined* to care about the Spliterator characteristics, but the implementation
// can't actually know the size before executing, so we check the characteristics explicitly.
assertFalse(
DoubleStream.of(1d, 2d, 3d)
.filter(a -> a == 1d)
.spliterator()
.hasCharacteristics(Spliterator.SIZED | Spliterator.SUBSIZED));
// one result
assertEquals(
new double[] {1d}, DoubleStream.of(1d, 2d, 3d, 4d, 3d).filter(a -> a == 1).toArray());
// zero results
assertEquals(new double[0], DoubleStream.of(1d, 2d, 3d, 4d, 3d).filter(a -> false).toArray());
// two results
assertEquals(
new double[] {2d, 4d},
DoubleStream.of(1d, 2d, 3d, 4d, 3d).filter(a -> a % 2 == 0).toArray());
// all
assertEquals(
new double[] {1d, 2d, 3d, 4d, 3d},
DoubleStream.of(1d, 2d, 3d, 4d, 3d).filter(a -> true).toArray());
}
public void testMap() {
// unconsumed stream never runs map
int[] data = {0};
DoubleStream.of(1d, 2d, 3d).map(i -> data[0]++);
assertEquals(0, data[0]);
assertEquals(new double[] {2d, 4d, 6d}, DoubleStream.of(1d, 2d, 3d).map(i -> i * 2).toArray());
}
public void testPeek() {
// unconsumed stream never peeks
boolean[] data = {false};
DoubleStream.of(1d, 2d, 3d).peek(i -> data[0] |= true);
assertFalse(data[0]);
// make sure we saw it all in order
double[] items = new double[] {1d, 2d, 3d};
List<Double> peeked = new ArrayList<>();
DoubleStream.of(items)
.peek(peeked::add)
.forEach(
item -> {
// do nothing, just run
});
assertEquals(items.length, peeked.size());
for (int i = 0; i < items.length; i++) {
assertEquals(items[i], peeked.get(i), 0d);
}
}
// same impl, no parallel in browser
public void testFindFirstOrAny() {
OptionalDouble any = DoubleStream.of(1d, 2d).findAny();
assertTrue(any.isPresent());
assertEquals(1d, any.getAsDouble(), 0d);
}
public void testAnyMatch() {
// all
assertTrue(DoubleStream.of(1d, 2d).anyMatch(s -> true));
// some
assertTrue(DoubleStream.of(1d, 2d).anyMatch(s -> s == 1d));
// none
assertFalse(DoubleStream.of(1d, 2d).anyMatch(s -> false));
}
public void testAllMatch() {
// all
assertTrue(DoubleStream.of(1d, 2d).allMatch(s -> true));
// some
assertFalse(DoubleStream.of(1d, 2d).allMatch(s -> s == 1d));
// none
assertFalse(DoubleStream.of(1d, 2d).allMatch(s -> false));
}
public void testNoneMatch() {
// all
assertFalse(DoubleStream.of(1d, 2d).noneMatch(s -> true));
// some
assertFalse(DoubleStream.of(1d, 2d).noneMatch(s -> s == 1d));
// none
assertTrue(DoubleStream.of(1d, 2d).noneMatch(s -> false));
}
public void testFlatMap() {
assertEquals(0L, DoubleStream.empty().flatMap(value -> DoubleStream.of(1d)).count());
assertEquals(0L, DoubleStream.of(1d).flatMap(value -> DoubleStream.empty()).count());
assertEquals(0L, DoubleStream.of(1d).flatMap(value -> DoubleStream.of()).count());
assertEquals(0L, DoubleStream.of().flatMap(value -> DoubleStream.of(1d)).count());
assertEquals(1L, DoubleStream.of(1d).flatMap(value -> DoubleStream.of(1d)).count());
DoubleStream values = DoubleStream.of(1d, 2d, 3d);
assertEquals(
new double[] {1d, 2d, 2d, 4d, 3d, 6d},
values.flatMap(i -> DoubleStream.of(i, i * 2d)).toArray());
}
public void testMapToOthers() {
Supplier<DoubleStream> s = () -> DoubleStream.of(1d, 2d, 10d);
assertEquals(
new String[] {"1", "2", "10"},
s.get().mapToObj(DoubleStreamTest::toIntegralString).toArray(String[]::new));
assertEquals(new long[] {1L, 2L, 10L}, s.get().mapToLong(i -> (long) i).toArray());
assertEquals(new int[] {1, 2, 10}, s.get().mapToInt(i -> (int) i).toArray());
}
public void testDistinct() {
double[] distinct = DoubleStream.of(1d, 2d, 3d, 2d).distinct().toArray();
assertEquals(3, distinct.length);
assertEquals(1d + 2d + 3d, distinct[0] + distinct[1] + distinct[2], 0d);
}
public void testSorted() {
double[] sorted = DoubleStream.of(3d, 1d, 2d).sorted().toArray();
assertEquals(new double[] {1d, 2d, 3d}, sorted);
}
public void testMinMax() {
Supplier<DoubleStream> stream = () -> DoubleStream.of(2d, 3d, 4d, 1d);
assertEquals(1d, stream.get().min().orElse(0), 0d);
assertEquals(4d, stream.get().max().orElse(0), 0d);
assertFalse(stream.get().filter(a -> false).max().isPresent());
assertFalse(stream.get().filter(a -> false).min().isPresent());
}
public void testCountLimitSkip() {
Supplier<DoubleStream> stream = () -> DoubleStream.of(1d, 2d, 3d, 4d);
assertEquals(4L, stream.get().count());
assertEquals(4L, stream.get().limit(4).count());
assertEquals(4L, stream.get().limit(5).count());
assertEquals(3L, stream.get().limit(3).count());
assertEquals(3L, stream.get().skip(1).limit(3).count());
assertEquals(2L, stream.get().limit(3).skip(1).count());
assertEquals(1L, stream.get().skip(3).count());
assertEquals(new double[] {3d, 4d}, stream.get().skip(2).limit(3).toArray());
assertEquals(new double[] {3d}, stream.get().skip(2).limit(1).toArray());
assertEquals(new double[] {4d}, stream.get().skip(3).toArray());
assertEquals(new double[] {}, stream.get().skip(5).toArray());
assertEquals(new double[] {1d, 2d}, stream.get().limit(2).toArray());
assertEquals(new double[] {2d}, stream.get().limit(2).skip(1).toArray());
}
public void testBoxed() {
Supplier<DoubleStream> stream = () -> DoubleStream.of(1d, 2d);
Stream<Double> expected = stream.get().mapToObj(Double::valueOf);
assertEquals(expected.toArray(), stream.get().boxed().toArray());
}
public void testSummaryStats() {
Supplier<DoubleStream> stream = () -> DoubleStream.of(1d, 2d, 3d);
DoubleSummaryStatistics summaryStats = stream.get().summaryStatistics();
assertEquals(3L, summaryStats.getCount());
assertEquals(1d, summaryStats.getMin(), 0d);
assertEquals(2d, summaryStats.getAverage(), 0d);
assertEquals(3d, summaryStats.getMax(), 0d);
assertEquals(6d, summaryStats.getSum(), 0d);
summaryStats.accept(6L);
assertEquals(4L, summaryStats.getCount());
assertEquals(1d, summaryStats.getMin(), 0d);
assertEquals(3d, summaryStats.getAverage(), 0d);
assertEquals(6d, summaryStats.getMax(), 0d);
assertEquals(12d, summaryStats.getSum(), 0d);
DoubleSummaryStatistics combinedSumStats = stream.get().summaryStatistics();
combinedSumStats.combine(DoubleStream.of(4d, 5d, 6d, 0d).summaryStatistics());
assertEquals(7L, combinedSumStats.getCount());
assertEquals(0d, combinedSumStats.getMin(), 0d);
assertEquals(3d, combinedSumStats.getAverage(), 0d);
assertEquals(6d, combinedSumStats.getMax(), 0d);
assertEquals(21d, combinedSumStats.getSum(), 0d);
}
public void testAverage() {
assertFalse(DoubleStream.empty().average().isPresent());
assertEquals(2.0d, DoubleStream.of(1d, 2d, 3d).average().getAsDouble(), 0d);
assertEquals(0d, DoubleStream.of(1d, 2d, -3d).average().getAsDouble(), 0d);
assertEquals(-2.0d, DoubleStream.of(-1d, -2d, -3d).average().getAsDouble(), 0d);
}
public void testSum() {
assertEquals(6d, DoubleStream.of(1d, 2d, 3d).sum(), 0d);
assertEquals(0d, DoubleStream.of(1d, 2d, -3d).sum(), 0d);
assertEquals(-6d, DoubleStream.of(-1d, -2d, -3d).sum(), 0d);
}
public void testCollect() {
// noinspection StringConcatenationInsideStringBufferAppend
String val =
DoubleStream.of(1d, 2d, 3d, 4d, 5d)
.collect(
StringBuilder::new,
(stringBuilder, d) -> stringBuilder.append(toIntegralString(d)),
StringBuilder::append)
.toString();
assertEquals("12345", val);
}
public void testForEach() {
List<Double> vals = new ArrayList<>();
DoubleStream.of(1d, 2d, 3d, 4d, 5d).forEach(vals::add);
assertEquals(5, vals.size());
assertEquals(new Double[] {1d, 2d, 3d, 4d, 5d}, vals.toArray(new Double[vals.size()]));
}
public void testIterator() {
List<Double> vals = new ArrayList<>();
Iterator<Double> iterator = DoubleStream.of(1d, 2d, 3d, 4d, 5d).iterator();
while (iterator.hasNext()) {
vals.add(iterator.next());
}
assertEquals(5, vals.size());
assertEquals(new Double[] {1d, 2d, 3d, 4d, 5d}, vals.toArray(new Double[vals.size()]));
}
public void testSpliterator() {
Spliterator<Double> spliterator = DoubleStream.of(1d, 2d, 3d, 4d, 5d).spliterator();
assertEquals(5, spliterator.estimateSize());
assertEquals(5, spliterator.getExactSizeIfKnown());
List<Double> vals = new ArrayList<>();
while (spliterator.tryAdvance(vals::add)) {
// work is all done in the condition
}
assertEquals(5, vals.size());
assertEquals(new Double[] {1d, 2d, 3d, 4d, 5d}, vals.toArray(new Double[vals.size()]));
}
// See https://github.com/gwtproject/gwt/issues/8615
private static String toIntegralString(double value) {
return "" + (int) value;
}
}