/* __ __ __ __ __ ___
* \ \ / / \ \ / / __/
* \ \/ / /\ \ \/ / /
* \____/__/ \__\____/__/.ɪᴏ
* ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ
*/
package io.vavr.collection;
import io.vavr.Serializables;
import io.vavr.Tuple;
import io.vavr.Value;
import io.vavr.Tuple2;
import io.vavr.control.Option;
import org.junit.Test;
import java.io.InvalidObjectException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.NoSuchElementException;
import java.util.Spliterator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
public class ListTest extends AbstractLinearSeqTest {
// -- construction
@Override
protected <T> Collector<T, ArrayList<T>, List<T>> collector() {
return List.collector();
}
@Override
protected <T> List<T> empty() {
return List.empty();
}
@Override
protected <T> List<T> of(T element) {
return List.of(element);
}
@SuppressWarnings("varargs")
@SafeVarargs
@Override
protected final <T> List<T> of(T... elements) {
return List.of(elements);
}
@Override
protected <T> List<T> ofAll(Iterable<? extends T> elements) {
return List.ofAll(elements);
}
@Override
protected <T extends Comparable<? super T>> List<T> ofJavaStream(java.util.stream.Stream<? extends T> javaStream) {
return List.ofAll(javaStream);
}
@Override
protected List<Boolean> ofAll(boolean... elements) {
return List.ofAll(elements);
}
@Override
protected List<Byte> ofAll(byte... elements) {
return List.ofAll(elements);
}
@Override
protected List<Character> ofAll(char... elements) {
return List.ofAll(elements);
}
@Override
protected List<Double> ofAll(double... elements) {
return List.ofAll(elements);
}
@Override
protected List<Float> ofAll(float... elements) {
return List.ofAll(elements);
}
@Override
protected List<Integer> ofAll(int... elements) {
return List.ofAll(elements);
}
@Override
protected List<Long> ofAll(long... elements) {
return List.ofAll(elements);
}
@Override
protected List<Short> ofAll(short... elements) {
return List.ofAll(elements);
}
@Override
protected <T> List<T> tabulate(int n, Function<? super Integer, ? extends T> f) {
return List.tabulate(n, f);
}
@Override
protected <T> List<T> fill(int n, Supplier<? extends T> s) {
return List.fill(n, s);
}
@Override
protected List<Character> range(char from, char toExclusive) {
return List.range(from, toExclusive);
}
@Override
protected List<Character> rangeBy(char from, char toExclusive, int step) {
return List.rangeBy(from, toExclusive, step);
}
@Override
protected List<Double> rangeBy(double from, double toExclusive, double step) {
return List.rangeBy(from, toExclusive, step);
}
@Override
protected List<Integer> range(int from, int toExclusive) {
return List.range(from, toExclusive);
}
@Override
protected List<Integer> rangeBy(int from, int toExclusive, int step) {
return List.rangeBy(from, toExclusive, step);
}
@Override
protected List<Long> range(long from, long toExclusive) {
return List.range(from, toExclusive);
}
@Override
protected List<Long> rangeBy(long from, long toExclusive, long step) {
return List.rangeBy(from, toExclusive, step);
}
@Override
protected List<Character> rangeClosed(char from, char toInclusive) {
return List.rangeClosed(from, toInclusive);
}
@Override
protected List<Character> rangeClosedBy(char from, char toInclusive, int step) {
return List.rangeClosedBy(from, toInclusive, step);
}
@Override
protected List<Double> rangeClosedBy(double from, double toInclusive, double step) {
return List.rangeClosedBy(from, toInclusive, step);
}
@Override
protected List<Integer> rangeClosed(int from, int toInclusive) {
return List.rangeClosed(from, toInclusive);
}
@Override
protected List<Integer> rangeClosedBy(int from, int toInclusive, int step) {
return List.rangeClosedBy(from, toInclusive, step);
}
@Override
protected List<Long> rangeClosed(long from, long toInclusive) {
return List.rangeClosed(from, toInclusive);
}
@Override
protected List<Long> rangeClosedBy(long from, long toInclusive, long step) {
return List.rangeClosedBy(from, toInclusive, step);
}
@Override
@SuppressWarnings("unchecked")
protected <T> List<List<T>> transpose(Seq<? extends Seq<T>> rows) {
return List.transpose((List<List<T>>) rows);
}
@Override
protected int getPeekNonNilPerformingAnAction() {
return 1;
}
// -- static narrow
@Test
public void shouldNarrowList() {
final List<Double> doubles = of(1.0d);
final List<Number> numbers = List.narrow(doubles);
final int actual = numbers.append(new BigDecimal("2.0")).sum().intValue();
assertThat(actual).isEqualTo(3);
}
// -- ofAll(NavigableSet)
@Test
public void shouldAcceptNavigableSet() {
final java.util.TreeSet<Integer> javaSet = new java.util.TreeSet<>();
javaSet.add(2);
javaSet.add(1);
assertThat(List.ofAll(javaSet)).isEqualTo(List.of(1, 2));
}
// -- peek
@Test(expected = NoSuchElementException.class)
public void shouldFailPeekOfNil() {
empty().peek();
}
@Test
public void shouldPeekOfNonNil() {
assertThat(of(1).peek()).isEqualTo(1);
assertThat(of(1, 2).peek()).isEqualTo(1);
}
// -- peekOption
@Test
public void shouldPeekOption() {
assertThat(empty().peekOption()).isSameAs(Option.none());
assertThat(of(1).peekOption()).isEqualTo(Option.of(1));
assertThat(of(1, 2).peekOption()).isEqualTo(Option.of(1));
}
// -- pop
@Test(expected = NoSuchElementException.class)
public void shouldFailPopOfNil() {
empty().pop();
}
@Test
public void shouldPopOfNonNil() {
assertThat(of(1).pop()).isSameAs(empty());
assertThat(of(1, 2).pop()).isEqualTo(of(2));
}
// -- popOption
@Test
public void shouldPopOption() {
assertThat(empty().popOption()).isSameAs(Option.none());
assertThat(of(1).popOption()).isEqualTo(Option.of(empty()));
assertThat(of(1, 2).popOption()).isEqualTo(Option.of(of(2)));
}
// -- pop2
@Test(expected = NoSuchElementException.class)
public void shouldFailPop2OfNil() {
empty().pop2();
}
@Test
public void shouldPop2OfNonNil() {
assertThat(of(1).pop2()).isEqualTo(Tuple.of(1, empty()));
assertThat(of(1, 2).pop2()).isEqualTo(Tuple.of(1, of(2)));
}
// -- pop2Option
@Test
public void shouldPop2Option() {
assertThat(empty().pop2Option()).isSameAs(Option.none());
assertThat(of(1).pop2Option()).isEqualTo(Option.of(Tuple.of(1, empty())));
assertThat(of(1, 2).pop2Option()).isEqualTo(Option.of(Tuple.of(1, of(2))));
}
// -- push
@Test
public void shouldPushElements() {
assertThat(empty().push(1)).isEqualTo(of(1));
assertThat(empty().push(1, 2, 3)).isEqualTo(of(3, 2, 1));
assertThat(empty().pushAll(of(1, 2, 3))).isEqualTo(of(3, 2, 1));
assertThat(of(0).push(1)).isEqualTo(of(1, 0));
assertThat(of(0).push(1, 2, 3)).isEqualTo(of(3, 2, 1, 0));
assertThat(of(0).pushAll(of(1, 2, 3))).isEqualTo(of(3, 2, 1, 0));
}
// -- transform()
@Test
public void shouldTransform() {
final String transformed = of(42).transform(v -> String.valueOf(v.get()));
assertThat(transformed).isEqualTo("42");
}
// -- toString
@Test
public void shouldStringifyNil() {
assertThat(empty().toString()).isEqualTo("List()");
}
@Test
public void shouldStringifyNonNil() {
assertThat(of(1, 2, 3).toString()).isEqualTo("List(1, 2, 3)");
}
// -- unfold
@Test
public void shouldUnfoldRightToEmpty() {
assertThat(List.unfoldRight(0, x -> Option.none())).isEqualTo(empty());
}
@Test
public void shouldUnfoldRightSimpleList() {
assertThat(
List.unfoldRight(10, x -> x == 0
? Option.none()
: Option.of(new Tuple2<>(x, x - 1))))
.isEqualTo(of(10, 9, 8, 7, 6, 5, 4, 3, 2, 1));
}
@Test
public void shouldUnfoldLeftToEmpty() {
assertThat(List.unfoldLeft(0, x -> Option.none())).isEqualTo(empty());
}
@Test
public void shouldUnfoldLeftSimpleList() {
assertThat(
List.unfoldLeft(10, x -> x == 0
? Option.none()
: Option.of(new Tuple2<>(x - 1, x))))
.isEqualTo(of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
}
@Test
public void shouldUnfoldToEmpty() {
assertThat(List.unfold(0, x -> Option.none())).isEqualTo(empty());
}
@Test
public void shouldUnfoldSimpleList() {
assertThat(
List.unfold(10, x -> x == 0
? Option.none()
: Option.of(new Tuple2<>(x - 1, x))))
.isEqualTo(of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
}
// -- Cons test
@Test(expected = InvalidObjectException.class)
public void shouldNotSerializeEnclosingClass() throws Throwable {
Serializables.callReadObject(List.of(1));
}
@Test(expected = InvalidObjectException.class)
public void shouldNotDeserializeListWithSizeLessThanOne() throws Throwable {
try {
/*
* This implementation is stable regarding jvm impl changes of object serialization. The index of the number
* of List elements is gathered dynamically.
*/
final byte[] listWithOneElement = Serializables.serialize(List.of(0));
final byte[] listWithTwoElements = Serializables.serialize(List.of(0, 0));
int index = -1;
for (int i = 0; i < listWithOneElement.length && index == -1; i++) {
final byte b1 = listWithOneElement[i];
final byte b2 = listWithTwoElements[i];
if (b1 != b2) {
if (b1 != 1 || b2 != 2) {
throw new IllegalStateException("Difference does not indicate number of elements.");
} else {
index = i;
}
}
}
if (index == -1) {
throw new IllegalStateException("Hack incomplete - index not found");
}
/*
* Hack the serialized data and fake zero elements.
*/
listWithOneElement[index] = 0;
Serializables.deserialize(listWithOneElement);
} catch (IllegalStateException x) {
throw (x.getCause() != null) ? x.getCause() : x;
}
}
@Override
protected boolean useIsEqualToInsteadOfIsSameAs() {
return false;
}
// -- toList
@Test
public void shouldReturnSelfOnConvertToList() {
final Value<Integer> value = of(1, 2, 3);
assertThat(value.toList()).isSameAs(value);
}
// -- spliterator
@Test
public void shouldHaveSizedSpliterator() {
assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.SIZED | Spliterator.SUBSIZED)).isTrue();
}
@Test
public void shouldReturnSizeWhenSpliterator() {
assertThat(of(1, 2, 3).spliterator().getExactSizeIfKnown()).isEqualTo(3);
}
}