package com.aconex.scrutineer.elasticsearch; import static com.aconex.scrutineer.elasticsearch.ElasticSearchDownloader.BATCH_SIZE; import static com.aconex.scrutineer.elasticsearch.ElasticSearchDownloader.SCROLL_TIME_IN_MINUTES; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; import java.io.IOException; import java.io.ObjectOutputStream; import org.elasticsearch.action.ListenableActionFuture; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchType; import org.elasticsearch.client.Client; import org.elasticsearch.action.search.SearchRequestBuilder; import org.elasticsearch.action.search.SearchScrollRequestBuilder; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.index.query.QueryStringQueryBuilder; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import com.aconex.scrutineer.IdAndVersionFactory; import com.aconex.scrutineer.StringIdAndVersion; @SuppressWarnings("unchecked") public class ElasticSearchDownloaderTest { private static final String INDEX_NAME = "indexName"; private static final String ID = "123"; private static final long VERSION = 123L; private static final String QUERY = "*"; private final IdAndVersionFactory idAndVersionFactory = StringIdAndVersion.FACTORY; @Mock private Client client; @Mock private SearchRequestBuilder searchRequestBuilder; @Mock private SearchScrollRequestBuilder searchScrollRequestBuilder; @Mock private ListenableActionFuture listenableActionFuture; @Mock private SearchHits hits; @Mock private SearchHit hit; @Mock private SearchResponse searchResponse; @Mock private ObjectOutputStream objectOutputStream; @Mock private QueryStringQueryBuilder queryBuilder; @Before public void setup() { initMocks(this); } @Test public void shouldEndAfterOnlyOneBatch() throws IOException { ElasticSearchDownloader elasticSearchDownloader = spy(new ElasticSearchDownloader(client, INDEX_NAME, QUERY, idAndVersionFactory)); doReturn(false).when(elasticSearchDownloader).writeSearchResponseToOutputStream(any(ObjectOutputStream.class),any(SearchResponse.class)); when(client.prepareSearchScroll(any(String.class))).thenReturn(searchScrollRequestBuilder); when(searchScrollRequestBuilder.execute()).thenReturn(listenableActionFuture); when(searchScrollRequestBuilder.setScroll(any(TimeValue.class))).thenReturn(searchScrollRequestBuilder); when(listenableActionFuture.actionGet()).thenReturn(searchResponse); elasticSearchDownloader.consumeBatches(eq(objectOutputStream), anyString()); verify(client).prepareSearchScroll(any(String.class)); } @Test public void shouldRequestAndProcessNextBatch() throws IOException { ElasticSearchDownloader elasticSearchDownloader = spy(new ElasticSearchDownloader(client, INDEX_NAME, QUERY, idAndVersionFactory)); doReturn(true).doReturn(false).when(elasticSearchDownloader).writeSearchResponseToOutputStream(any(ObjectOutputStream.class),any(SearchResponse.class)); when(client.prepareSearchScroll(any(String.class))).thenReturn(searchScrollRequestBuilder); when(searchScrollRequestBuilder.execute()).thenReturn(listenableActionFuture); when(searchScrollRequestBuilder.setScroll(any(TimeValue.class))).thenReturn(searchScrollRequestBuilder); when(listenableActionFuture.actionGet()).thenReturn(searchResponse); elasticSearchDownloader.consumeBatches(eq(objectOutputStream), anyString()); verify(client,times(2)).prepareSearchScroll(any(String.class)); verify(searchResponse, times(2)).getScrollId(); } @Test public void shouldShouldReturnFalseWhenBatchIsEmpty() throws IOException { ElasticSearchDownloader elasticSearchDownloader = new ElasticSearchDownloader(client, INDEX_NAME, QUERY, idAndVersionFactory); when(searchResponse.getHits()).thenReturn(hits); when(hits.hits()).thenReturn(new SearchHit[0]); assertThat(elasticSearchDownloader.writeSearchResponseToOutputStream(objectOutputStream, searchResponse), is(false)); } @Test public void shouldWriteHitsToOutputStream() throws IOException { ElasticSearchDownloader elasticSearchDownloader = new ElasticSearchDownloader(client, INDEX_NAME, QUERY, idAndVersionFactory); when(searchResponse.getHits()).thenReturn(hits); when(hits.hits()).thenReturn(new SearchHit[]{hit}); when(hit.getId()).thenReturn(ID); when(hit.getVersion()).thenReturn(VERSION); assertThat(elasticSearchDownloader.writeSearchResponseToOutputStream(objectOutputStream, searchResponse), is(true)); verify(objectOutputStream).writeUTF(ID); verify(objectOutputStream).writeLong(VERSION); verifyNoMoreInteractions(objectOutputStream); } @Test public void shouldDoElasticSearchRequest() { when(client.prepareSearch(INDEX_NAME)).thenReturn(searchRequestBuilder); when(searchRequestBuilder.execute()).thenReturn(listenableActionFuture); when(listenableActionFuture.actionGet()).thenReturn(searchResponse); ElasticSearchDownloader elasticSearchDownloader = spy(new ElasticSearchDownloader(client, INDEX_NAME, QUERY, idAndVersionFactory)); doReturn(queryBuilder).when(elasticSearchDownloader).createQuery(); assertThat(elasticSearchDownloader.startScroll(), is(searchResponse)); verify(searchRequestBuilder).setSearchType(SearchType.SCAN); verify(searchRequestBuilder).setNoFields(); verify(searchRequestBuilder).setVersion(true); verify(searchRequestBuilder).setSize(BATCH_SIZE); verify(searchRequestBuilder).setScroll(TimeValue.timeValueMinutes(SCROLL_TIME_IN_MINUTES)); verify(searchRequestBuilder).setQuery(queryBuilder); } @Test public void shouldCreateQueryBuilderWithQuery() { ElasticSearchDownloader elasticSearchDownloader = spy(new ElasticSearchDownloader(client, INDEX_NAME, QUERY, idAndVersionFactory)); assertThat(elasticSearchDownloader.createQuery().toString(), containsString(QUERY)); } @Test public void shouldCreateQueryBuilderWithDefaultAllField() { ElasticSearchDownloader elasticSearchDownloader = spy(new ElasticSearchDownloader(client, INDEX_NAME, QUERY, idAndVersionFactory)); assertThat(elasticSearchDownloader.createQuery().toString(), containsString("_all")); } @Test public void shouldCreateQueryBuilderWithDefaultAndOperator() { ElasticSearchDownloader elasticSearchDownloader = spy(new ElasticSearchDownloader(client, INDEX_NAME, QUERY, idAndVersionFactory)); assertThat(elasticSearchDownloader.createQuery().toString(), containsString("and")); } }