package com.nurkiewicz.lazyseq;
import org.mockito.Mock;
import org.testng.annotations.Test;
import java.util.Arrays;
import java.util.NoSuchElementException;
import java.util.function.Supplier;
import static com.nurkiewicz.lazyseq.LazySeq.cons;
import static com.nurkiewicz.lazyseq.LazySeq.empty;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.*;
/**
* @author Tomasz Nurkiewicz
* @since 5/10/13, 9:56 PM
*/
public class LazySeqHeadTest extends AbstractBaseTestCase {
@Mock
private Supplier<LazySeq<Integer>> supplierMock;
@Test
public void shouldFailWhenTryingToAccessHeadOfNil() throws Exception {
//given
final LazySeq<String> empty = empty();
try {
//when
empty.head();
failBecauseExceptionWasNotThrown(NoSuchElementException.class);
} catch (NoSuchElementException e) {
//then
}
}
@Test
public void shouldReturnHeadOfFixedSeqs() throws Exception {
assertThat(LazySeq.of(1).head()).isEqualTo(1);
assertThat(LazySeq.of(2, 3).head()).isEqualTo(2);
assertThat(LazySeq.of(4, 5, 6).head()).isEqualTo(4);
assertThat(LazySeq.of(Arrays.asList(7, 8, 9, 10, 11, 12)).head()).isEqualTo(7);
}
@Test
public void shouldReturnHeadOfDynamicLazySeq() throws Exception {
assertThat(LazySeq.of(1, tail()).head()).isEqualTo(1);
assertThat(LazySeq.of(2, 3, tail()).head()).isEqualTo(2);
assertThat(LazySeq.of(4, 5, 6, tail()).head()).isEqualTo(4);
assertThat(LazySeq.concat(Arrays.asList(7, 8, 9, 10, 11, 12), tail()).head()).isEqualTo(7);
}
@Test
public void shouldReturnHeadOfTail() throws Exception {
assertThat(LazySeq.of(2, 3).tail().head()).isEqualTo(3);
assertThat(LazySeq.of(2, 3, tail()).tail().head()).isEqualTo(3);
assertThat(LazySeq.of(4, 5, 6, tail()).tail().head()).isEqualTo(5);
assertThat(LazySeq.concat(Arrays.asList(7, 8, 9, 10, 11, 12), tail()).tail().head()).isEqualTo(8);
}
@Test
public void shouldNotEvaluateTailIfHeadRequested() throws Exception {
//given
LazySeq<Integer> lazy = cons(1, supplierMock);
//when
lazy.head();
//then
verifyZeroInteractions(supplierMock);
}
@Test
public void shouldEvaluateTailOnlyOnceWhenTailsHeadRequested() throws Exception {
//given
LazySeq<Integer> lazy = cons(1, supplierMock);
given(supplierMock.get()).willReturn(cons(2, supplierMock));
//when
final Integer tailsHead = lazy.tail().head();
//then
verify(supplierMock).get();
assertThat(tailsHead).isEqualTo(2);
}
@Test
public void shouldEvaluateTailOnlyTwiceOnAccessingThirdElement() throws Exception {
//given
LazySeq<Integer> lazy = cons(1, supplierMock);
given(supplierMock.get()).willReturn(cons(2, supplierMock));
//when
final Integer tailsHead = lazy.tail().tail().head();
//then
verify(supplierMock, times(2)).get();
assertThat(tailsHead).isEqualTo(2);
}
@Test
public void shouldThrowWhenTryingToAccessHeadPastTheEndElementOfEmptySeq() throws Exception {
//given
final LazySeq<Integer> twoItems = LazySeq.of(1, 2);
final LazySeq<Integer> tail = twoItems.tail().tail();
try {
//when
tail.head();
failBecauseExceptionWasNotThrown(NoSuchElementException.class);
} catch (NoSuchElementException e) {
//then
}
}
private Supplier<LazySeq<Integer>> tail() {
return () -> LazySeq.of(42);
}
}