package com.constellio.data.dao.services.bigVault;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import com.constellio.data.dao.dto.records.QueryResponseDTO;
import com.constellio.data.dao.dto.records.RecordDTO;
import com.constellio.data.dao.services.records.RecordDao;
import com.constellio.data.utils.LazyIteratorRuntimeException.LazyIteratorRuntimeException_IncorrectUsage;
import com.constellio.data.utils.LazyIteratorRuntimeException.LazyIteratorRuntimeException_RemoveNotAvailable;
import com.constellio.sdk.tests.ConstellioTest;
public class LazyResultsIteratorTest extends ConstellioTest {
@Mock RecordDao recordDao;
ModifiableSolrParams modifiableSolrParams;
LazyResultsIterator iterator;
QueryResponseDTO noResultsResponse;
@Mock RecordDTO record1;
@Mock RecordDTO record2;
@Mock RecordDTO record3;
@Mock RecordDTO record4;
@Mock RecordDTO record5;
@Mock RecordDTO record6;
@Before
public void setUp()
throws Exception {
modifiableSolrParams = new ModifiableSolrParams();
modifiableSolrParams.set("q", "zeQ");
modifiableSolrParams.set("fq", "zeFQ");
iterator = spy(new LazyResultsIterator<String>(recordDao, modifiableSolrParams, 3) {
@Override
public String convert(RecordDTO recordDTO) {
return "converted_" + recordDTO.getId();
}
});
when(record1.getId()).thenReturn("1");
when(record2.getId()).thenReturn("2");
when(record3.getId()).thenReturn("3");
when(record4.getId()).thenReturn("4");
when(record5.getId()).thenReturn("5");
when(record6.getId()).thenReturn("6");
noResultsResponse = responseWithElements();
}
@Test
public void givenNoResultsThenHasNextFalse()
throws Exception {
ArgumentCaptor<SolrParams> solrParams = ArgumentCaptor.forClass(SolrParams.class);
when(recordDao.query(solrParams.capture())).thenReturn(noResultsResponse);
assertThat(iterator.hasNext()).isFalse();
verify(iterator).loadNextBatch();
}
@Test
public void givenFirstBatchOf3ResultsAndAnotherBatchOf1ResultsWhenIteratingThenCorrect()
throws Exception {
QueryResponseDTO batch1 = responseWithElements(record1, record2, record3);
QueryResponseDTO batch2 = responseWithElements(record4);
when(recordDao.query(any(SolrParams.class))).thenReturn(batch1).thenReturn(batch2);
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo("converted_1");
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo("converted_2");
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo("converted_3");
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo("converted_4");
assertThat(iterator.hasNext()).isFalse();
}
@Test
public void givenResultsThenCanCallHasNextMultipleTimesWithoutImpacts()
throws Exception {
QueryResponseDTO batch1 = responseWithElements(record1, record2, record3);
QueryResponseDTO batch2 = responseWithElements(record4);
when(recordDao.query(any(SolrParams.class))).thenReturn(batch1).thenReturn(batch2);
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo("converted_1");
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo("converted_2");
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo("converted_3");
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo("converted_4");
assertThat(iterator.hasNext()).isFalse();
assertThat(iterator.hasNext()).isFalse();
assertThat(iterator.hasNext()).isFalse();
}
@Test
public void givenIteratorUsedInHeroicModeThenOk()
throws Exception {
QueryResponseDTO batch1 = responseWithElements(record1, record2, record3);
QueryResponseDTO batch2 = responseWithElements(record4);
when(recordDao.query(any(SolrParams.class))).thenReturn(batch1).thenReturn(batch2);
assertThat(iterator.next()).isEqualTo("converted_1");
assertThat(iterator.next()).isEqualTo("converted_2");
assertThat(iterator.next()).isEqualTo("converted_3");
assertThat(iterator.next()).isEqualTo("converted_4");
}
@Test
public void givenFirstBatchOf3ResultsAndEmptyBatchResultsWhenIteratingThenCorrect()
throws Exception {
QueryResponseDTO batch1 = responseWithElements(record1, record2, record3);
QueryResponseDTO batch2 = noResultsResponse;
when(recordDao.query(any(SolrParams.class))).thenReturn(batch1).thenReturn(batch2);
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo("converted_1");
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo("converted_2");
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo("converted_3");
assertThat(iterator.hasNext()).isFalse();
}
@Test
public void givenRecordsSentMultipleTimesWhileIteratingThenNoProblem()
throws Exception {
QueryResponseDTO batch1 = responseWithElements(record1, record2, record3);
QueryResponseDTO batch2 = responseWithElements(record3, record1, record4);
QueryResponseDTO batch3 = noResultsResponse;
when(recordDao.query(any(SolrParams.class))).thenReturn(batch1).thenReturn(batch2).thenReturn(batch3);
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo("converted_1");
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo("converted_2");
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo("converted_3");
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo("converted_3");
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo("converted_1");
assertThat(iterator.hasNext()).isTrue();
assertThat(iterator.next()).isEqualTo("converted_4");
assertThat(iterator.hasNext()).isFalse();
}
@Test
public void whenLoadNextBatchThenUseSameParamsWithDifferentRowsAndStart()
throws Exception {
QueryResponseDTO batch1 = responseWithElements(record1, record2, record3);
QueryResponseDTO batch2 = responseWithElements(record3, record1, record4);
QueryResponseDTO batch3 = noResultsResponse;
ArgumentCaptor<SolrParams> solrParams = ArgumentCaptor.forClass(SolrParams.class);
when(recordDao.query(solrParams.capture())).thenReturn(batch1).thenReturn(batch2).thenReturn(batch3);
while (iterator.hasNext()) {
iterator.next();
}
assertThat(solrParams.getAllValues()).hasSize(3);
assertThat(solrParams.getAllValues().get(0).get("q")).isEqualTo("zeQ");
assertThat(solrParams.getAllValues().get(0).getParams("fq")).isEqualTo(new String[] { "zeFQ" });
assertThat(solrParams.getAllValues().get(0).get("rows")).isEqualTo("3");
assertThat(solrParams.getAllValues().get(0).get("sort")).isEqualTo("id asc");
assertThat(solrParams.getAllValues().get(1).get("q")).isEqualTo("zeQ");
assertThat(solrParams.getAllValues().get(1).getParams("fq")).isEqualTo(new String[] { "zeFQ", "id:{3 TO *}" });
assertThat(solrParams.getAllValues().get(1).get("rows")).isEqualTo("3");
assertThat(solrParams.getAllValues().get(1).get("sort")).isEqualTo("id asc");
assertThat(solrParams.getAllValues().get(2).get("q")).isEqualTo("zeQ");
assertThat(solrParams.getAllValues().get(2).getParams("fq")).isEqualTo(new String[] { "zeFQ", "id:{4 TO *}" });
assertThat(solrParams.getAllValues().get(2).get("rows")).isEqualTo("3");
assertThat(solrParams.getAllValues().get(2).get("sort")).isEqualTo("id asc");
}
@Test(expected = LazyIteratorRuntimeException_IncorrectUsage.class)
public void givenNoElementWhenNextCalledThenException()
throws Exception {
ArgumentCaptor<SolrParams> solrParams = ArgumentCaptor.forClass(SolrParams.class);
when(recordDao.query(solrParams.capture())).thenReturn(noResultsResponse);
iterator.next();
}
@Test()
public void givenOneElementWhenNextCalledTwiceThenException()
throws Exception {
ArgumentCaptor<SolrParams> solrParams = ArgumentCaptor.forClass(SolrParams.class);
QueryResponseDTO batch1 = responseWithElements(record1);
when(recordDao.query(solrParams.capture())).thenReturn(batch1);
iterator.next();
try {
iterator.next();
fail("IncorrectUsage_LazyResultsIteratorRuntimeException expected");
} catch (LazyIteratorRuntimeException_IncorrectUsage e) {
//OK
}
}
@Test(expected = LazyIteratorRuntimeException_RemoveNotAvailable.class)
public void whenRemoveCallThenThrowUnsupportedOperationException()
throws Exception {
iterator.remove();
}
private QueryResponseDTO responseWithElements(RecordDTO... records) {
QueryResponseDTO response = mock(QueryResponseDTO.class);
when(response.getNumFound()).thenReturn(0L);
when(response.getResults()).thenReturn(Arrays.asList(records));
return response;
}
}