package pl.edu.icm.saos.search.indexing; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.contains; import static org.mockito.AdditionalAnswers.returnsFirstArg; import static org.mockito.Matchers.any; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import java.io.IOException; import java.util.List; import java.util.stream.Collectors; import org.apache.solr.client.solrj.SolrServer; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.params.SolrParams; import org.apache.solr.common.util.NamedList; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; import org.mockito.stubbing.Answer; import pl.edu.icm.saos.persistence.repository.JudgmentRepository; import pl.edu.icm.saos.search.config.model.JudgmentIndexField; import com.google.common.collect.Lists; /** * @author madryk */ @RunWith(MockitoJUnitRunner.class) public class JudgmentIndexDeleterTest { private JudgmentIndexDeleter judgmentIndexDeleter = new JudgmentIndexDeleter(); @Mock private JudgmentRepository judgmentRepository; @Mock private SolrServer solrJudgmentsServer; @Captor private ArgumentCaptor<SolrParams> solrParamsCaptor; @Captor private ArgumentCaptor<List<Long>> filterExistingIdsCaptor; @Captor private ArgumentCaptor<List<String>> deleteJudgmentIdsCaptor; @Before public void setUp() { judgmentIndexDeleter.setJudgmentRepository(judgmentRepository); judgmentIndexDeleter.setSolrJudgmentsServer(solrJudgmentsServer); judgmentIndexDeleter.setIndexIteratingPageSize(2); } //------------------------ TESTS -------------------------- @Test public void deleteFromIndexWithoutCorrespondingJudgmentInDb_EMPTY_INDEX() throws SolrServerException, IOException { // given when(solrJudgmentsServer.query(any())).thenReturn(createSolrResponse(0, Lists.newArrayList())); // execute judgmentIndexDeleter.deleteFromIndexWithoutCorrespondingJudgmentInDb(); // assert verify(solrJudgmentsServer).query(solrParamsCaptor.capture()); verifyZeroInteractions(judgmentRepository); assertSolrParams(solrParamsCaptor.getValue(), 0, 2); } @Test public void deleteFromIndexWithoutCorrespondingJudgmentInDb_NO_DIFFERENCE() throws SolrServerException, IOException { // given List<Long> indexIds = Lists.newArrayList(1L, 2L, 3L, 4L, 5L, 6L, 7L); when(solrJudgmentsServer.query(any())).thenAnswer(buildSolrResponseAnswer(indexIds)); when(judgmentRepository.filterIdsToExisting(any())).then(returnsFirstArg()); // execute judgmentIndexDeleter.deleteFromIndexWithoutCorrespondingJudgmentInDb(); // assert verify(solrJudgmentsServer, times(5)).query(solrParamsCaptor.capture()); verify(judgmentRepository, times(4)).filterIdsToExisting(filterExistingIdsCaptor.capture()); assertSolrParams(solrParamsCaptor.getAllValues().get(0), 0, 2); assertSolrParams(solrParamsCaptor.getAllValues().get(1), 2, 2); assertSolrParams(solrParamsCaptor.getAllValues().get(2), 4, 2); assertSolrParams(solrParamsCaptor.getAllValues().get(3), 6, 2); assertSolrParams(solrParamsCaptor.getAllValues().get(4), 8, 2); assertThat(filterExistingIdsCaptor.getAllValues().get(0), contains(1L, 2L)); assertThat(filterExistingIdsCaptor.getAllValues().get(1), contains(3L, 4L)); assertThat(filterExistingIdsCaptor.getAllValues().get(2), contains(5L, 6L)); assertThat(filterExistingIdsCaptor.getAllValues().get(3), contains(7L)); verifyNoMoreInteractions(solrJudgmentsServer, judgmentRepository); } @Test public void deleteFromIndexWithoutCorrespondingJudgmentInDb_WITH_DIFFERENCE() throws SolrServerException, IOException { // given List<Long> indexIds = Lists.newArrayList(1L, 2L, 3L, 4L); List<Long> databaseIds = Lists.newArrayList(1L, 7L); when(solrJudgmentsServer.query(any())).then(buildSolrResponseAnswer(indexIds)); when(judgmentRepository.filterIdsToExisting(any())).then(new Answer<List<Long>>() { @SuppressWarnings("unchecked") @Override public List<Long> answer(InvocationOnMock invocation) throws Throwable { List<Long> arg = (List<Long>)invocation.getArguments()[0]; return arg.stream().filter(id -> databaseIds.contains(id)).collect(Collectors.toList()); } }); // execute judgmentIndexDeleter.deleteFromIndexWithoutCorrespondingJudgmentInDb(); // assert verify(solrJudgmentsServer, times(2)).deleteById(deleteJudgmentIdsCaptor.capture()); verify(solrJudgmentsServer, times(3)).query(solrParamsCaptor.capture()); verify(judgmentRepository, times(2)).filterIdsToExisting(filterExistingIdsCaptor.capture()); assertThat(deleteJudgmentIdsCaptor.getAllValues().get(0), contains("2")); assertThat(deleteJudgmentIdsCaptor.getAllValues().get(1), contains("3", "4")); assertSolrParams(solrParamsCaptor.getAllValues().get(0), 0, 2); assertSolrParams(solrParamsCaptor.getAllValues().get(1), 2, 2); assertSolrParams(solrParamsCaptor.getAllValues().get(2), 4, 2); assertThat(filterExistingIdsCaptor.getAllValues().get(0), contains(1L, 2L)); assertThat(filterExistingIdsCaptor.getAllValues().get(1), contains(3L, 4L)); verifyNoMoreInteractions(solrJudgmentsServer, judgmentRepository); } //------------------------ PRIVATE -------------------------- private void assertSolrParams(SolrParams solrParams, int start, int rows) { assertThat(solrParams.getParams("fl"), arrayContaining("databaseId")); assertThat(solrParams.getParams("q"), arrayContaining("*:*")); assertThat(solrParams.getParams("start"), arrayContaining(String.valueOf(start))); assertThat(solrParams.getParams("rows"), arrayContaining(String.valueOf(rows))); assertThat(solrParams.getParams("sort"), arrayContaining("databaseId asc")); } private QueryResponse createSolrResponse(long totalResults, List<Long> judgmentIds) { QueryResponse response = new QueryResponse(); SolrDocumentList documentList = new SolrDocumentList(); documentList.setNumFound(totalResults); for (Long id : judgmentIds) { SolrDocument doc = new SolrDocument(); doc.addField(JudgmentIndexField.DATABASE_ID.getFieldName(), id); documentList.add(doc); } NamedList<Object> namedList = new NamedList<Object>(); namedList.add("response", documentList); response.setResponse(namedList); return response; } private Answer<QueryResponse> buildSolrResponseAnswer(List<Long> indexJudgmentsIds) { return new Answer<QueryResponse>() { @Override public QueryResponse answer(InvocationOnMock invocation) throws Throwable { SolrParams params = (SolrParams)invocation.getArguments()[0]; int start = params.getInt("start"); int rows = params.getInt("rows"); if (start >= indexJudgmentsIds.size()) { return createSolrResponse(indexJudgmentsIds.size(), Lists.newArrayList()); } int end = Math.min(indexJudgmentsIds.size(), start + rows); return createSolrResponse(indexJudgmentsIds.size(), indexJudgmentsIds.subList(start, end)); } }; } }