/* * JBoss, Home of Professional Open Source * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors * as indicated by the @authors tag. All rights reserved. */ package org.jboss.elasticsearch.river.remote; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.elasticsearch.action.bulk.BulkRequestBuilder; import org.elasticsearch.client.Client; import org.elasticsearch.common.logging.ESLoggerFactory; import org.elasticsearch.river.RiverName; import org.jboss.elasticsearch.river.remote.exception.RemoteDocumentNotFoundException; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; /** * Unit test for {@link SpacePaginatingIndexer}. * * @author Vlastimil Elias (velias at redhat dot com) */ public class SpacePaginatingIndexerTest { @Test public void init() { IRemoteSystemClient remoteClient = new GetJSONClient(); IDocumentIndexStructureBuilder documentIndexStructureBuilderMock = mock(IDocumentIndexStructureBuilder.class); SpacePaginatingIndexer tested = new SpacePaginatingIndexer("ORG", remoteClient, mockEsIntegrationComponent(), documentIndexStructureBuilderMock); Assert.assertEquals("ORG", tested.spaceKey); Assert.assertNotNull(tested.indexingInfo); Assert.assertTrue(tested.indexingInfo.fullUpdate); Assert.assertEquals(remoteClient, tested.remoteSystemClient); Assert.assertEquals(documentIndexStructureBuilderMock, tested.documentIndexStructureBuilder); Assert.assertNotNull(tested.logger); } @Test public void processUpdate_emptyList() throws Exception { SpacePaginatingIndexer tested = getTested(); configureStructureBuilderMockDefaults(tested.documentIndexStructureBuilder); List<Map<String, Object>> docs = new ArrayList<Map<String, Object>>(); when(tested.remoteSystemClient.getChangedDocuments("ORG", 0, true, null)).thenReturn( new ChangedDocumentsResults(docs, 0, null)); tested.processUpdate(); Assert.assertEquals(0, tested.getIndexingInfo().documentsUpdated); Assert.assertEquals(0, tested.indexingInfo.documentsWithError); Assert.assertTrue(tested.getIndexingInfo().fullUpdate); verify(tested.remoteSystemClient, times(1)).getChangedDocuments("ORG", 0, true, null); verify(tested.esIntegrationComponent, times(0)).prepareESBulkRequestBuilder(); verify(tested.esIntegrationComponent, times(0)).executeESBulkRequest(Mockito.any(BulkRequestBuilder.class)); verify(tested.esIntegrationComponent, Mockito.atLeastOnce()).isClosed(); Mockito.verifyNoMoreInteractions(tested.remoteSystemClient); Mockito.verifyNoMoreInteractions(tested.esIntegrationComponent); Mockito.verifyNoMoreInteractions(tested.documentIndexStructureBuilder); } @SuppressWarnings("unchecked") @Test public void processUpdate_onePage_noTotal() throws Exception { SpacePaginatingIndexer tested = getTested(); configureStructureBuilderMockDefaults(tested.documentIndexStructureBuilder); List<Map<String, Object>> docs = new ArrayList<Map<String, Object>>(); addDocumentMock(docs, "AA1"); addDocumentMock(docs, "AA2"); addDocumentMock(docs, "AA3"); when(tested.remoteSystemClient.getChangedDocuments("ORG", 0, true, null)).thenReturn( new ChangedDocumentsResults(docs, 0, null)); when(tested.remoteSystemClient.getChangedDocuments("ORG", docs.size(), true, null)).thenReturn( new ChangedDocumentsResults(null, docs.size(), null)); Client client = Mockito.mock(Client.class); BulkRequestBuilder brb = new BulkRequestBuilder(client); when(tested.esIntegrationComponent.prepareESBulkRequestBuilder()).thenReturn(brb); // test skipping of bad read of remote document detail - issue #11 when( tested.remoteSystemClient.getChangedDocumentDetails(Mockito.eq("ORG"), Mockito.eq("AA2"), (Map<String, Object>) Mockito.notNull())).thenThrow(new RemoteDocumentNotFoundException()); tested.processUpdate(); Assert.assertEquals(2, tested.getIndexingInfo().documentsUpdated); Assert.assertEquals(1, tested.indexingInfo.documentsWithError); Assert.assertTrue(tested.getIndexingInfo().fullUpdate); // next is called twice because no total info is provided verify(tested.remoteSystemClient, times(2)).getChangedDocuments(Mockito.eq("ORG"), Mockito.anyInt(), Mockito.eq(true), Mockito.eq((Date) null)); verify(tested.remoteSystemClient, times(3)).getChangedDocumentDetails(Mockito.eq("ORG"), Mockito.anyString(), Mockito.anyMap()); verify(tested.documentIndexStructureBuilder, times(3)).extractDocumentId(Mockito.anyMap()); verify(tested.documentIndexStructureBuilder, times(2)).extractDocumentDeleted(Mockito.anyMap()); verify(tested.documentIndexStructureBuilder, times(2)).indexDocument(Mockito.eq(brb), Mockito.eq("ORG"), Mockito.any(Map.class)); verify(tested.esIntegrationComponent, times(1)).prepareESBulkRequestBuilder(); verify(tested.esIntegrationComponent, times(1)).executeESBulkRequest(Mockito.any(BulkRequestBuilder.class)); verify(tested.esIntegrationComponent, Mockito.atLeastOnce()).isClosed(); Mockito.verifyNoMoreInteractions(tested.remoteSystemClient); Mockito.verifyNoMoreInteractions(tested.esIntegrationComponent); Mockito.verifyNoMoreInteractions(tested.documentIndexStructureBuilder); } @SuppressWarnings("unchecked") @Test public void processUpdate_onePage_withTotal() throws Exception { SpacePaginatingIndexer tested = getTested(); configureStructureBuilderMockDefaults(tested.documentIndexStructureBuilder); List<Map<String, Object>> docs = new ArrayList<Map<String, Object>>(); addDocumentMock(docs, "AA1"); addDocumentMock(docs, "AA2"); addDocumentMock(docs, "AA3"); when(tested.remoteSystemClient.getChangedDocuments("ORG", 0, true, null)).thenReturn( new ChangedDocumentsResults(docs, 0, 3)); Client client = Mockito.mock(Client.class); BulkRequestBuilder brb = new BulkRequestBuilder(client); when(tested.esIntegrationComponent.prepareESBulkRequestBuilder()).thenReturn(brb); // test skipping of bad read of remote document detail - issue #11 when( tested.remoteSystemClient.getChangedDocumentDetails(Mockito.eq("ORG"), Mockito.eq("AA2"), (Map<String, Object>) Mockito.notNull())).thenThrow(new RemoteDocumentNotFoundException()); tested.processUpdate(); Assert.assertEquals(2, tested.getIndexingInfo().documentsUpdated); Assert.assertEquals(1, tested.indexingInfo.documentsWithError); Assert.assertTrue(tested.getIndexingInfo().fullUpdate); // next is called only once thanks to total info provided verify(tested.remoteSystemClient, times(1)).getChangedDocuments(Mockito.eq("ORG"), Mockito.anyInt(), Mockito.eq(true), Mockito.eq((Date) null)); verify(tested.remoteSystemClient, times(3)).getChangedDocumentDetails(Mockito.eq("ORG"), Mockito.anyString(), Mockito.anyMap()); verify(tested.documentIndexStructureBuilder, times(3)).extractDocumentId(Mockito.anyMap()); verify(tested.documentIndexStructureBuilder, times(2)).extractDocumentDeleted(Mockito.anyMap()); verify(tested.documentIndexStructureBuilder, times(2)).indexDocument(Mockito.eq(brb), Mockito.eq("ORG"), Mockito.any(Map.class)); verify(tested.esIntegrationComponent, times(1)).prepareESBulkRequestBuilder(); verify(tested.esIntegrationComponent, times(1)).executeESBulkRequest(Mockito.any(BulkRequestBuilder.class)); verify(tested.esIntegrationComponent, Mockito.atLeastOnce()).isClosed(); Mockito.verifyNoMoreInteractions(tested.remoteSystemClient); Mockito.verifyNoMoreInteractions(tested.esIntegrationComponent); Mockito.verifyNoMoreInteractions(tested.documentIndexStructureBuilder); } @SuppressWarnings("unchecked") @Test public void processUpdate_morePages_noTotal() throws Exception { SpacePaginatingIndexer tested = getTested(); configureStructureBuilderMockDefaults(tested.documentIndexStructureBuilder); List<Map<String, Object>> docs = new ArrayList<Map<String, Object>>(); addDocumentMock(docs, "AA1"); addDocumentMock(docs, "AA2"); addDocumentMock(docs, "AA3"); List<Map<String, Object>> docs2 = new ArrayList<Map<String, Object>>(); addDocumentMock(docs2, "AA4"); addDocumentMock(docs2, "AA5"); when(tested.remoteSystemClient.getChangedDocuments("ORG", 0, true, null)).thenReturn( new ChangedDocumentsResults(docs, 0, null)); when(tested.remoteSystemClient.getChangedDocuments("ORG", docs.size(), true, null)).thenReturn( new ChangedDocumentsResults(docs2, docs.size(), null)); when(tested.remoteSystemClient.getChangedDocuments("ORG", docs.size() + docs2.size(), true, null)).thenReturn( new ChangedDocumentsResults(null, docs.size() + docs2.size(), null)); Client client = Mockito.mock(Client.class); BulkRequestBuilder brb = new BulkRequestBuilder(client); when(tested.esIntegrationComponent.prepareESBulkRequestBuilder()).thenReturn(brb); // test skipping of bad read of remote document detail - issue #11 when( tested.remoteSystemClient.getChangedDocumentDetails(Mockito.eq("ORG"), Mockito.eq("AA2"), (Map<String, Object>) Mockito.notNull())).thenThrow(new RemoteDocumentNotFoundException()); tested.processUpdate(); Assert.assertEquals(4, tested.getIndexingInfo().documentsUpdated); Assert.assertEquals(1, tested.indexingInfo.documentsWithError); Assert.assertTrue(tested.getIndexingInfo().fullUpdate); verify(tested.remoteSystemClient, times(3)).getChangedDocuments(Mockito.eq("ORG"), Mockito.anyInt(), Mockito.eq(true), Mockito.eq((Date) null)); verify(tested.remoteSystemClient, times(5)).getChangedDocumentDetails(Mockito.eq("ORG"), Mockito.anyString(), Mockito.anyMap()); verify(tested.documentIndexStructureBuilder, times(5)).extractDocumentId(Mockito.anyMap()); verify(tested.documentIndexStructureBuilder, times(4)).extractDocumentDeleted(Mockito.anyMap()); verify(tested.documentIndexStructureBuilder, times(4)).indexDocument(Mockito.eq(brb), Mockito.eq("ORG"), Mockito.any(Map.class)); verify(tested.esIntegrationComponent, times(2)).prepareESBulkRequestBuilder(); verify(tested.esIntegrationComponent, times(2)).executeESBulkRequest(Mockito.any(BulkRequestBuilder.class)); verify(tested.esIntegrationComponent, Mockito.atLeastOnce()).isClosed(); Mockito.verifyNoMoreInteractions(tested.remoteSystemClient); Mockito.verifyNoMoreInteractions(tested.esIntegrationComponent); Mockito.verifyNoMoreInteractions(tested.documentIndexStructureBuilder); } @SuppressWarnings("unchecked") @Test public void processUpdate_morePages_withTotal() throws Exception { SpacePaginatingIndexer tested = getTested(); configureStructureBuilderMockDefaults(tested.documentIndexStructureBuilder); List<Map<String, Object>> docs = new ArrayList<Map<String, Object>>(); addDocumentMock(docs, "AA1"); addDocumentMock(docs, "AA2"); addDocumentMock(docs, "AA3"); List<Map<String, Object>> docs2 = new ArrayList<Map<String, Object>>(); addDocumentMock(docs2, "AA4"); addDocumentMock(docs2, "AA5"); when(tested.remoteSystemClient.getChangedDocuments("ORG", 0, true, null)).thenReturn( new ChangedDocumentsResults(docs, 0, 5)); when(tested.remoteSystemClient.getChangedDocuments("ORG", docs.size(), true, null)).thenReturn( new ChangedDocumentsResults(docs2, docs.size(), 5)); Client client = Mockito.mock(Client.class); BulkRequestBuilder brb = new BulkRequestBuilder(client); when(tested.esIntegrationComponent.prepareESBulkRequestBuilder()).thenReturn(brb); // test skipping of bad read of remote document detail - issue #11 when( tested.remoteSystemClient.getChangedDocumentDetails(Mockito.eq("ORG"), Mockito.eq("AA2"), (Map<String, Object>) Mockito.notNull())).thenThrow(new RemoteDocumentNotFoundException()); tested.processUpdate(); Assert.assertEquals(4, tested.getIndexingInfo().documentsUpdated); Assert.assertEquals(1, tested.indexingInfo.documentsWithError); Assert.assertTrue(tested.getIndexingInfo().fullUpdate); verify(tested.remoteSystemClient, times(2)).getChangedDocuments(Mockito.eq("ORG"), Mockito.anyInt(), Mockito.eq(true), Mockito.eq((Date) null)); verify(tested.remoteSystemClient, times(5)).getChangedDocumentDetails(Mockito.eq("ORG"), Mockito.anyString(), Mockito.anyMap()); verify(tested.documentIndexStructureBuilder, times(5)).extractDocumentId(Mockito.anyMap()); verify(tested.documentIndexStructureBuilder, times(4)).extractDocumentDeleted(Mockito.anyMap()); verify(tested.documentIndexStructureBuilder, times(4)).indexDocument(Mockito.eq(brb), Mockito.eq("ORG"), Mockito.any(Map.class)); verify(tested.esIntegrationComponent, times(2)).prepareESBulkRequestBuilder(); verify(tested.esIntegrationComponent, times(2)).executeESBulkRequest(Mockito.any(BulkRequestBuilder.class)); verify(tested.esIntegrationComponent, Mockito.atLeastOnce()).isClosed(); Mockito.verifyNoMoreInteractions(tested.remoteSystemClient); Mockito.verifyNoMoreInteractions(tested.esIntegrationComponent); Mockito.verifyNoMoreInteractions(tested.documentIndexStructureBuilder); } protected SpacePaginatingIndexer getTested() { IRemoteSystemClient remoteClientMock = mock(IRemoteSystemClient.class); IESIntegration esIntegrationMock = mockEsIntegrationComponent(); IDocumentIndexStructureBuilder documentIndexStructureBuilderMock = mock(IDocumentIndexStructureBuilder.class); SpacePaginatingIndexer tested = new SpacePaginatingIndexer("ORG", remoteClientMock, esIntegrationMock, documentIndexStructureBuilderMock); return tested; } /** * Add document info structure into list of documents. Used to build mock {@link ChangedDocumentsResults} instances. * * @param documents list to add document into * @param key of document * @return document Map structure */ public static Map<String, Object> addDocumentMock(List<Map<String, Object>> documents, String key) { Map<String, Object> doc = new HashMap<String, Object>(); documents.add(doc); doc.put("key", key); return doc; } /** * @param documentIndexStructureBuilderMock */ @SuppressWarnings("unchecked") protected static void configureStructureBuilderMockDefaults( IDocumentIndexStructureBuilder documentIndexStructureBuilderMock) { when(documentIndexStructureBuilderMock.extractDocumentId(Mockito.anyMap())).thenAnswer(new Answer<String>() { public String answer(InvocationOnMock invocation) throws Throwable { return (String) ((Map<String, Object>) invocation.getArguments()[0]).get("key"); } }); } protected static IESIntegration mockEsIntegrationComponent() { IESIntegration esIntegrationMock = mock(IESIntegration.class); Mockito.when(esIntegrationMock.createLogger(Mockito.any(Class.class))).thenReturn( ESLoggerFactory.getLogger(SpacePaginatingIndexer.class.getName())); RiverName riverName = new RiverName("remote", "river_name"); Mockito.when(esIntegrationMock.riverName()).thenReturn(riverName); return esIntegrationMock; } }