/*
* JBoss, Home of Professional Open Source
* Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
*/
package org.jboss.elasticsearch.river.jira;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import junit.framework.Assert;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.joda.time.format.ISODateTimeFormat;
import org.elasticsearch.common.logging.ESLoggerFactory;
import org.elasticsearch.common.text.StringText;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.internal.InternalSearchHit;
import org.elasticsearch.search.internal.InternalSearchHits;
import org.elasticsearch.search.internal.InternalSearchResponse;
import org.jboss.elasticsearch.river.jira.testtools.ProjectInfoMatcher;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* Unit test for {@link JIRAProjectIndexer}.
*
* @author Vlastimil Elias (velias at redhat dot com)
*/
public class JIRAProjectIndexerTest {
/**
* Main method used to run integration tests with real JIRA call.
*
* @param args not used
* @throws Exception
*/
public static void main(String[] args) throws Exception {
IESIntegration esIntegrationMock = mockEsIntegrationComponent();
IJIRAClient jiraClient = new JIRA5RestClient(esIntegrationMock, "https://issues.jboss.org", null, null, 7000, null);
IJIRAIssueIndexStructureBuilder jiraIssueIndexStructureBuilderMock = mock(IJIRAIssueIndexStructureBuilder.class);
JIRAProjectIndexer tested = new JIRAProjectIndexer("ORG", false, jiraClient, esIntegrationMock,
jiraIssueIndexStructureBuilderMock);
tested.run();
}
@Test
public void constructor() {
IESIntegration esMock = mockEsIntegrationComponent();
IJIRAClient jiraClient = new JIRA5RestClient(esMock, "https://issues.jboss.org", null, null, 7000, null);
IJIRAIssueIndexStructureBuilder jiraIssueIndexStructureBuilderMock = mock(IJIRAIssueIndexStructureBuilder.class);
JIRAProjectIndexer tested = new JIRAProjectIndexer("ORG", true, jiraClient, esMock,
jiraIssueIndexStructureBuilderMock);
Assert.assertEquals("ORG", tested.projectKey);
Assert.assertTrue(tested.indexingInfo.fullUpdate);
Assert.assertEquals(jiraClient, tested.jiraClient);
Assert.assertEquals(jiraIssueIndexStructureBuilderMock, tested.jiraIssueIndexStructureBuilder);
Mockito.verify(esMock).createLogger(JIRAProjectIndexer.class);
}
@SuppressWarnings("unchecked")
@Test
public void processUpdate_Basic() throws Exception {
IJIRAClient jiraClientMock = mock(IJIRAClient.class);
IESIntegration esIntegrationMock = mockEsIntegrationComponent();
IJIRAIssueIndexStructureBuilder jiraIssueIndexStructureBuilderMock = mock(IJIRAIssueIndexStructureBuilder.class);
JIRAProjectIndexer tested = new JIRAProjectIndexer("ORG", false, jiraClientMock, esIntegrationMock,
jiraIssueIndexStructureBuilderMock);
List<Map<String, Object>> issues = new ArrayList<Map<String, Object>>();
Client client = Mockito.mock(Client.class);
// test case with empty result list from JIRA search method
// test case of 'last update date' reading from store and passing to the JIRA search method
{
Date mockDateAfter = new Date();
when(
esIntegrationMock.readDatetimeValue("ORG",
JIRAProjectIndexer.STORE_PROPERTYNAME_LAST_INDEXED_ISSUE_UPDATE_DATE)).thenReturn(mockDateAfter);
when(
jiraClientMock.getJIRAChangedIssues("ORG", 0, DateTimeUtils.roundDateTimeToMinutePrecise(mockDateAfter), null))
.thenReturn(new ChangedIssuesResults(issues, 0, 50, 0));
tested.processUpdate();
Assert.assertEquals(0, tested.getIndexingInfo().issuesUpdated);
Assert.assertFalse(tested.getIndexingInfo().fullUpdate);
verify(jiraClientMock, times(1)).getJIRAChangedIssues("ORG", 0,
DateTimeUtils.roundDateTimeToMinutePrecise(mockDateAfter), null);
verify(esIntegrationMock, times(1)).readDatetimeValue(Mockito.any(String.class), Mockito.any(String.class));
verify(esIntegrationMock, times(0)).prepareESBulkRequestBuilder();
verify(esIntegrationMock, times(0)).storeDatetimeValue(Mockito.any(String.class), Mockito.any(String.class),
Mockito.any(Date.class), Mockito.any(BulkRequestBuilder.class));
verify(esIntegrationMock, times(0)).executeESBulkRequest(Mockito.any(BulkRequestBuilder.class));
verify(esIntegrationMock, Mockito.atLeastOnce()).isClosed();
Mockito.verifyNoMoreInteractions(jiraClientMock);
Mockito.verifyNoMoreInteractions(esIntegrationMock);
}
// test case with one "page" of results from JIRA search method
// test case with 'last update date' storing
{
reset(esIntegrationMock);
reset(jiraClientMock);
reset(jiraIssueIndexStructureBuilderMock);
when(
esIntegrationMock.readDatetimeValue("ORG",
JIRAProjectIndexer.STORE_PROPERTYNAME_LAST_INDEXED_ISSUE_UPDATE_DATE)).thenReturn(null);
addIssueMock(issues, "ORG-45", "2012-08-14T08:00:00.000-0400");
addIssueMock(issues, "ORG-46", "2012-08-14T08:01:00.000-0400");
addIssueMock(issues, "ORG-47", "2012-08-14T08:02:10.000-0400");
configureStructureBuilderMockDefaults(jiraIssueIndexStructureBuilderMock);
when(jiraClientMock.getJIRAChangedIssues("ORG", 0, null, null)).thenReturn(
new ChangedIssuesResults(issues, 0, 50, 3));
BulkRequestBuilder brb = new BulkRequestBuilder(client);
when(esIntegrationMock.prepareESBulkRequestBuilder()).thenReturn(brb);
tested.processUpdate();
Assert.assertEquals(3, tested.indexingInfo.issuesUpdated);
Assert.assertTrue(tested.indexingInfo.fullUpdate);
verify(jiraClientMock, times(1)).getJIRAChangedIssues("ORG", 0, null, null);
verify(esIntegrationMock, times(1)).readDatetimeValue(Mockito.any(String.class), Mockito.any(String.class));
verify(esIntegrationMock, times(1)).prepareESBulkRequestBuilder();
verify(jiraIssueIndexStructureBuilderMock, times(3)).indexIssue(Mockito.eq(brb), Mockito.eq("ORG"),
Mockito.any(Map.class));
verify(esIntegrationMock, times(1)).storeDatetimeValue(Mockito.eq("ORG"),
Mockito.eq(JIRAProjectIndexer.STORE_PROPERTYNAME_LAST_INDEXED_ISSUE_UPDATE_DATE),
Mockito.eq(DateTimeUtils.parseISODateTime("2012-08-14T08:02:00.000-0400")), eq(brb));
verify(esIntegrationMock, times(1)).executeESBulkRequest(eq(brb));
verify(esIntegrationMock, Mockito.atLeastOnce()).isClosed();
Mockito.verifyNoMoreInteractions(jiraClientMock);
Mockito.verifyNoMoreInteractions(esIntegrationMock);
}
}
@SuppressWarnings("unchecked")
@Test
public void processUpdate_NoLastIsuueIndexedAgain() throws Exception {
IJIRAClient jiraClientMock = mock(IJIRAClient.class);
IESIntegration esIntegrationMock = mockEsIntegrationComponent();
IJIRAIssueIndexStructureBuilder jiraIssueIndexStructureBuilderMock = mock(IJIRAIssueIndexStructureBuilder.class);
JIRAProjectIndexer tested = new JIRAProjectIndexer("ORG", false, jiraClientMock, esIntegrationMock,
jiraIssueIndexStructureBuilderMock);
List<Map<String, Object>> issues = new ArrayList<Map<String, Object>>();
Client client = Mockito.mock(Client.class);
// test case with list from JIRA search method containing only one issue with same update time as 'last update date'
Date mockDateAfter = DateTimeUtils.parseISODateTime("2012-08-14T08:00:10.000-0400");
when(
esIntegrationMock
.readDatetimeValue("ORG", JIRAProjectIndexer.STORE_PROPERTYNAME_LAST_INDEXED_ISSUE_UPDATE_DATE))
.thenReturn(mockDateAfter);
addIssueMock(issues, "ORG-45", "2012-08-14T08:00:20.000-0400");
configureStructureBuilderMockDefaults(jiraIssueIndexStructureBuilderMock);
when(jiraClientMock.getJIRAChangedIssues("ORG", 0, DateTimeUtils.roundDateTimeToMinutePrecise(mockDateAfter), null))
.thenReturn(new ChangedIssuesResults(issues, 0, 50, 1));
BulkRequestBuilder brb = new BulkRequestBuilder(client);
when(esIntegrationMock.prepareESBulkRequestBuilder()).thenReturn(brb);
tested.processUpdate();
Assert.assertEquals(1, tested.indexingInfo.issuesUpdated);
Assert.assertFalse(tested.indexingInfo.fullUpdate);
verify(jiraClientMock, times(1)).getJIRAChangedIssues("ORG", 0,
DateTimeUtils.roundDateTimeToMinutePrecise(mockDateAfter), null);
verify(esIntegrationMock, times(1)).readDatetimeValue(Mockito.any(String.class), Mockito.any(String.class));
verify(esIntegrationMock, times(1)).prepareESBulkRequestBuilder();
verify(jiraIssueIndexStructureBuilderMock, times(1)).indexIssue(Mockito.eq(brb), Mockito.eq("ORG"),
Mockito.any(Map.class));
verify(esIntegrationMock, times(1)).storeDatetimeValue(Mockito.eq("ORG"),
Mockito.eq(JIRAProjectIndexer.STORE_PROPERTYNAME_LAST_INDEXED_ISSUE_UPDATE_DATE),
Mockito.eq(DateTimeUtils.parseISODateTime("2012-08-14T08:00:00.000-0400")), eq(brb));
verify(esIntegrationMock, times(1)).executeESBulkRequest(eq(brb));
// one more timestamp store with time incremented by one minute not to index last updated issue next time again!
verify(esIntegrationMock, times(1)).storeDatetimeValue(Mockito.eq("ORG"),
Mockito.eq(JIRAProjectIndexer.STORE_PROPERTYNAME_LAST_INDEXED_ISSUE_UPDATE_DATE),
Mockito.eq(DateTimeUtils.parseISODateTime("2012-08-14T08:01:00.000-0400")),
((BulkRequestBuilder) Mockito.isNull()));
verify(esIntegrationMock, Mockito.atLeastOnce()).isClosed();
Mockito.verifyNoMoreInteractions(jiraClientMock);
Mockito.verifyNoMoreInteractions(esIntegrationMock);
}
@SuppressWarnings("unchecked")
@Test
public void processUpdate_PagedByDate() throws Exception {
// test case with more than one "page" of results from JIRA search method with different updated dates
IJIRAClient jiraClientMock = mock(IJIRAClient.class);
IESIntegration esIntegrationMock = mockEsIntegrationComponent();
IJIRAIssueIndexStructureBuilder jiraIssueIndexStructureBuilderMock = mock(IJIRAIssueIndexStructureBuilder.class);
JIRAProjectIndexer tested = new JIRAProjectIndexer("ORG", false, jiraClientMock, esIntegrationMock,
jiraIssueIndexStructureBuilderMock);
Client client = Mockito.mock(Client.class);
BulkRequestBuilder brb = new BulkRequestBuilder(client);
List<Map<String, Object>> issues = new ArrayList<Map<String, Object>>();
addIssueMock(issues, "ORG-45", "2012-08-14T08:00:10.000-0400");
addIssueMock(issues, "ORG-46", "2012-08-14T08:01:10.000-0400");
addIssueMock(issues, "ORG-47", "2012-08-14T08:02:20.000-0400");
Date after2 = DateTimeUtils.parseISODateTime("2012-08-14T08:02:00.000-0400");
List<Map<String, Object>> issues2 = new ArrayList<Map<String, Object>>();
addIssueMock(issues2, "ORG-481", "2012-08-14T08:03:10.000-0400");
addIssueMock(issues2, "ORG-49", "2012-08-14T08:04:10.000-0400");
addIssueMock(issues2, "ORG-154", "2012-08-14T08:05:20.000-0400");
Date after3 = ISODateTimeFormat.dateTimeParser().parseDateTime("2012-08-14T08:05:00.000-0400").toDate();
List<Map<String, Object>> issues3 = new ArrayList<Map<String, Object>>();
addIssueMock(issues3, "ORG-4", "2012-08-14T08:06:10.000-0400");
addIssueMock(issues3, "ORG-91", "2012-08-14T08:07:20.000-0400");
when(
esIntegrationMock
.readDatetimeValue("ORG", JIRAProjectIndexer.STORE_PROPERTYNAME_LAST_INDEXED_ISSUE_UPDATE_DATE))
.thenReturn(null);
when(jiraClientMock.getJIRAChangedIssues("ORG", 0, null, null)).thenReturn(
new ChangedIssuesResults(issues, 0, 3, 8));
when(jiraClientMock.getJIRAChangedIssues("ORG", 0, after2, null)).thenReturn(
new ChangedIssuesResults(issues2, 0, 3, 5));
when(jiraClientMock.getJIRAChangedIssues("ORG", 0, after3, null)).thenReturn(
new ChangedIssuesResults(issues3, 0, 3, 2));
when(esIntegrationMock.prepareESBulkRequestBuilder()).thenReturn(brb);
configureStructureBuilderMockDefaults(jiraIssueIndexStructureBuilderMock);
tested.processUpdate();
Assert.assertEquals(8, tested.indexingInfo.issuesUpdated);
Assert.assertTrue(tested.indexingInfo.fullUpdate);
verify(esIntegrationMock, times(1)).readDatetimeValue(Mockito.any(String.class), Mockito.any(String.class));
verify(esIntegrationMock, times(3)).prepareESBulkRequestBuilder();
verify(jiraClientMock, times(1)).getJIRAChangedIssues("ORG", 0, null, null);
verify(jiraClientMock, times(1)).getJIRAChangedIssues("ORG", 0, after2, null);
verify(jiraClientMock, times(1)).getJIRAChangedIssues("ORG", 0, after3, null);
verify(jiraIssueIndexStructureBuilderMock, times(8)).indexIssue(Mockito.any(BulkRequestBuilder.class),
Mockito.eq("ORG"), Mockito.any(Map.class));
verify(esIntegrationMock, times(3)).storeDatetimeValue(Mockito.any(String.class), Mockito.any(String.class),
Mockito.any(Date.class), Mockito.any(BulkRequestBuilder.class));
verify(esIntegrationMock, times(1)).storeDatetimeValue(Mockito.eq("ORG"),
Mockito.eq(JIRAProjectIndexer.STORE_PROPERTYNAME_LAST_INDEXED_ISSUE_UPDATE_DATE),
Mockito.eq(ISODateTimeFormat.dateTimeParser().parseDateTime("2012-08-14T08:02:00.000-0400").toDate()),
Mockito.any(BulkRequestBuilder.class));
verify(esIntegrationMock, times(1)).storeDatetimeValue(Mockito.eq("ORG"),
Mockito.eq(JIRAProjectIndexer.STORE_PROPERTYNAME_LAST_INDEXED_ISSUE_UPDATE_DATE),
Mockito.eq(ISODateTimeFormat.dateTimeParser().parseDateTime("2012-08-14T08:05:00.000-0400").toDate()),
Mockito.any(BulkRequestBuilder.class));
verify(esIntegrationMock, times(1)).storeDatetimeValue(Mockito.eq("ORG"),
Mockito.eq(JIRAProjectIndexer.STORE_PROPERTYNAME_LAST_INDEXED_ISSUE_UPDATE_DATE),
Mockito.eq(ISODateTimeFormat.dateTimeParser().parseDateTime("2012-08-14T08:07:00.000-0400").toDate()),
Mockito.any(BulkRequestBuilder.class));
verify(esIntegrationMock, times(3)).executeESBulkRequest(Mockito.any(BulkRequestBuilder.class));
verify(esIntegrationMock, Mockito.atLeastOnce()).isClosed();
Mockito.verifyNoMoreInteractions(jiraClientMock);
Mockito.verifyNoMoreInteractions(esIntegrationMock);
}
@SuppressWarnings("unchecked")
@Test
public void processUpdate_PagedByStartAt() throws Exception {
// test case with more than one "page" of results from JIRA search method with same updated dates so pagination in
// JIRA is used. "same updated dates" means on minute precise basis due JQL limitations!!!
IJIRAClient jiraClientMock = mock(IJIRAClient.class);
IESIntegration esIntegrationMock = mockEsIntegrationComponent();
IJIRAIssueIndexStructureBuilder jiraIssueIndexStructureBuilderMock = mock(IJIRAIssueIndexStructureBuilder.class);
JIRAProjectIndexer tested = new JIRAProjectIndexer("ORG", false, jiraClientMock, esIntegrationMock,
jiraIssueIndexStructureBuilderMock);
Client client = Mockito.mock(Client.class);
BulkRequestBuilder brb = new BulkRequestBuilder(client);
List<Map<String, Object>> issues = new ArrayList<Map<String, Object>>();
addIssueMock(issues, "ORG-45", "2012-08-14T08:00:00.000-0400");
addIssueMock(issues, "ORG-46", "2012-08-14T08:00:00.000-0400");
addIssueMock(issues, "ORG-47", "2012-08-14T08:00:00.000-0400");
List<Map<String, Object>> issues2 = new ArrayList<Map<String, Object>>();
addIssueMock(issues2, "ORG-481", "2012-08-14T08:00:00.000-0400");
addIssueMock(issues2, "ORG-49", "2012-08-14T08:00:10.000-0400");
addIssueMock(issues2, "ORG-154", "2012-08-14T08:00:10.000-0400");
List<Map<String, Object>> issues3 = new ArrayList<Map<String, Object>>();
addIssueMock(issues3, "ORG-4", "2012-08-14T08:00:10.000-0400");
addIssueMock(issues3, "ORG-91", "2012-08-14T08:00:20.000-0400");
when(
esIntegrationMock
.readDatetimeValue("ORG", JIRAProjectIndexer.STORE_PROPERTYNAME_LAST_INDEXED_ISSUE_UPDATE_DATE))
.thenReturn(null);
when(jiraClientMock.getJIRAChangedIssues("ORG", 0, null, null)).thenReturn(
new ChangedIssuesResults(issues, 0, 3, 8));
when(jiraClientMock.getJIRAChangedIssues("ORG", 3, null, null)).thenReturn(
new ChangedIssuesResults(issues2, 3, 3, 8));
when(jiraClientMock.getJIRAChangedIssues("ORG", 6, null, null)).thenReturn(
new ChangedIssuesResults(issues3, 6, 3, 8));
when(esIntegrationMock.prepareESBulkRequestBuilder()).thenReturn(brb);
configureStructureBuilderMockDefaults(jiraIssueIndexStructureBuilderMock);
tested.processUpdate();
Assert.assertEquals(8, tested.indexingInfo.issuesUpdated);
verify(esIntegrationMock, times(1)).readDatetimeValue(Mockito.any(String.class), Mockito.any(String.class));
verify(esIntegrationMock, times(3)).prepareESBulkRequestBuilder();
verify(jiraClientMock, times(1)).getJIRAChangedIssues("ORG", 0, null, null);
verify(jiraClientMock, times(1)).getJIRAChangedIssues("ORG", 3, null, null);
verify(jiraClientMock, times(1)).getJIRAChangedIssues("ORG", 6, null, null);
verify(jiraIssueIndexStructureBuilderMock, times(8)).indexIssue(Mockito.any(BulkRequestBuilder.class),
Mockito.eq("ORG"), Mockito.any(Map.class));
verify(esIntegrationMock, times(3)).storeDatetimeValue(Mockito.any(String.class), Mockito.any(String.class),
Mockito.any(Date.class), Mockito.any(BulkRequestBuilder.class));
verify(esIntegrationMock, times(3)).storeDatetimeValue(Mockito.eq("ORG"),
Mockito.eq(JIRAProjectIndexer.STORE_PROPERTYNAME_LAST_INDEXED_ISSUE_UPDATE_DATE),
Mockito.eq(DateTimeUtils.parseISODateTime("2012-08-14T08:00:00.000-0400")),
Mockito.any(BulkRequestBuilder.class));
verify(esIntegrationMock, times(3)).executeESBulkRequest(Mockito.any(BulkRequestBuilder.class));
verify(esIntegrationMock, Mockito.atLeastOnce()).isClosed();
Mockito.verifyNoMoreInteractions(jiraClientMock);
Mockito.verifyNoMoreInteractions(esIntegrationMock);
}
@Test
public void run() throws Exception {
IJIRAClient jiraClientMock = mock(IJIRAClient.class);
IESIntegration esIntegrationMock = mockEsIntegrationComponent();
IJIRAIssueIndexStructureBuilder jiraIssueIndexStructureBuilderMock = mock(IJIRAIssueIndexStructureBuilder.class);
JIRAProjectIndexer tested = new JIRAProjectIndexer("ORG", false, jiraClientMock, esIntegrationMock,
jiraIssueIndexStructureBuilderMock);
List<Map<String, Object>> issues = new ArrayList<Map<String, Object>>();
Date lastUpdatedDate = DateTimeUtils.parseISODateTime("2012-08-14T07:00:00.000-0400");
addIssueMock(issues, "ORG-45", "2012-08-14T08:00:00.000-0400");
addIssueMock(issues, "ORG-46", "2012-08-14T08:00:10.000-0400");
addIssueMock(issues, "ORG-47", "2012-08-14T08:00:20.000-0400");
Client client = Mockito.mock(Client.class);
BulkRequestBuilder brb = new BulkRequestBuilder(client);
SearchRequestBuilder srb = new SearchRequestBuilder(client);
// test case with indexing finished OK
{
when(
esIntegrationMock.readDatetimeValue("ORG",
JIRAProjectIndexer.STORE_PROPERTYNAME_LAST_INDEXED_ISSUE_UPDATE_DATE)).thenReturn(lastUpdatedDate);
when(jiraClientMock.getJIRAChangedIssues("ORG", 0, lastUpdatedDate, null)).thenReturn(
new ChangedIssuesResults(issues, 0, 50, 3));
when(esIntegrationMock.prepareESBulkRequestBuilder()).thenReturn(brb);
configureStructureBuilderMockDefaults(jiraIssueIndexStructureBuilderMock);
tested.run();
verify(esIntegrationMock, times(1)).reportIndexingFinished(
Mockito.argThat(new ProjectInfoMatcher("ORG", false, true, 3, 0, null)));
}
// test case with indexing finished with error, but some issues was indexed from first page
{
reset(esIntegrationMock);
reset(jiraClientMock);
when(
esIntegrationMock.readDatetimeValue("ORG",
JIRAProjectIndexer.STORE_PROPERTYNAME_LAST_INDEXED_ISSUE_UPDATE_DATE)).thenReturn(null);
when(jiraClientMock.getJIRAChangedIssues("ORG", 0, null, null)).thenReturn(
new ChangedIssuesResults(issues, 0, 50, 4));
when(jiraClientMock.getJIRAChangedIssues("ORG", 3, null, null)).thenThrow(new Exception("JIRA call error"));
when(esIntegrationMock.prepareESBulkRequestBuilder()).thenReturn(brb);
tested.run();
verify(esIntegrationMock, times(1)).reportIndexingFinished(
Mockito.argThat(new ProjectInfoMatcher("ORG", true, false, 3, 0, "JIRA call error")));
}
// case - run issues delete on full update!!!
{
esIntegrationMock = mockEsIntegrationComponent();
reset(jiraClientMock);
tested = new JIRAProjectIndexer("ORG", true, jiraClientMock, esIntegrationMock,
jiraIssueIndexStructureBuilderMock);
// prepare update part
Date mockDate = new Date();
when(
esIntegrationMock.readDatetimeValue("ORG",
JIRAProjectIndexer.STORE_PROPERTYNAME_LAST_INDEXED_ISSUE_UPDATE_DATE)).thenReturn(mockDate);
// updatedAfter is null here (even some is returned from previous when) because we run full update!
when(jiraClientMock.getJIRAChangedIssues("ORG", 0, null, null)).thenReturn(
new ChangedIssuesResults(issues, 0, 50, 3));
when(esIntegrationMock.prepareESBulkRequestBuilder()).thenReturn(brb);
// prepare delete part
when(esIntegrationMock.prepareESScrollSearchRequestBuilder(Mockito.anyString())).thenReturn(srb);
SearchResponse sr1 = prepareSearchResponse("scrlid1",
new InternalSearchHit(1, "ORG-12", new StringText(""), null));
when(esIntegrationMock.executeESSearchRequest(Mockito.any(SearchRequestBuilder.class))).thenReturn(sr1);
SearchResponse sr2 = prepareSearchResponse("scrlid1",
new InternalSearchHit(1, "ORG-12", new StringText(""), null));
when(esIntegrationMock.executeESScrollSearchNextRequest(sr1)).thenReturn(sr2);
when(esIntegrationMock.executeESScrollSearchNextRequest(sr2)).thenReturn(prepareSearchResponse("scrlid3"));
when(
jiraIssueIndexStructureBuilderMock.deleteIssueDocument(Mockito.any(BulkRequestBuilder.class),
Mockito.any(SearchHit.class))).thenReturn(true);
tested.run();
// verify updatedAfter is null in this call, not value read from store, because we run full update here!
verify(jiraClientMock, times(1)).getJIRAChangedIssues("ORG", 0, null, null);
verify(jiraClientMock, times(0)).getJIRAChangedIssues("ORG", 0, mockDate, null);
verify(esIntegrationMock, times(1)).reportIndexingFinished(
Mockito.argThat(new ProjectInfoMatcher("ORG", true, true, 3, 1, null)));
}
}
/**
* @param jiraIssueIndexStructureBuilderMock
*/
@SuppressWarnings("unchecked")
private void configureStructureBuilderMockDefaults(IJIRAIssueIndexStructureBuilder jiraIssueIndexStructureBuilderMock) {
when(jiraIssueIndexStructureBuilderMock.extractIssueKey(Mockito.anyMap())).thenAnswer(new Answer<String>() {
public String answer(InvocationOnMock invocation) throws Throwable {
return (String) ((Map<String, Object>) invocation.getArguments()[0]).get("key");
}
});
when(jiraIssueIndexStructureBuilderMock.extractIssueUpdated(Mockito.anyMap())).thenAnswer(new Answer<Date>() {
public Date answer(InvocationOnMock invocation) throws Throwable {
return DateTimeUtils.parseISODateTime((String) ((Map<String, Object>) invocation.getArguments()[0])
.get("updated"));
}
});
}
@Test
public void processDelete() throws Exception {
IJIRAClient jiraClientMock = mock(IJIRAClient.class);
IESIntegration esIntegrationMock = mockEsIntegrationComponent();
IJIRAIssueIndexStructureBuilder jiraIssueIndexStructureBuilderMock = mock(IJIRAIssueIndexStructureBuilder.class);
JIRAProjectIndexer tested = new JIRAProjectIndexer("ORG", true, jiraClientMock, esIntegrationMock,
jiraIssueIndexStructureBuilderMock);
Client client = Mockito.mock(Client.class);
Mockito.verify(esIntegrationMock).createLogger(JIRAProjectIndexer.class);
try {
tested.processDelete(null);
Assert.fail("IllegalArgumentException must be thrown");
} catch (IllegalArgumentException e) {
// OK
}
// case - nothing performed if no full update mode
{
tested.indexingInfo.fullUpdate = false;
tested.processDelete(new Date());
Assert.assertEquals(0, tested.indexingInfo.issuesDeleted);
Mockito.verifyZeroInteractions(jiraClientMock);
Mockito.verifyNoMoreInteractions(esIntegrationMock);
Mockito.verifyZeroInteractions(jiraIssueIndexStructureBuilderMock);
}
// case - no issues for delete found
{
reset(jiraClientMock);
reset(esIntegrationMock);
reset(jiraIssueIndexStructureBuilderMock);
tested.indexingInfo.fullUpdate = true;
String jiraIndexName = "jira_index";
Date boundDate = DateTimeUtils.parseISODateTime("2012-08-14T07:00:00.000-0400");
when(jiraIssueIndexStructureBuilderMock.getIssuesSearchIndexName("ORG")).thenReturn(jiraIndexName);
SearchRequestBuilder srbmock = new SearchRequestBuilder(client);
when(esIntegrationMock.prepareESScrollSearchRequestBuilder(jiraIndexName)).thenReturn(srbmock);
when(esIntegrationMock.executeESSearchRequest(srbmock)).thenReturn(prepareSearchResponse("scrlid3"));
tested.processDelete(boundDate);
Assert.assertEquals(0, tested.indexingInfo.issuesDeleted);
verify(jiraIssueIndexStructureBuilderMock).getIssuesSearchIndexName("ORG");
verify(esIntegrationMock).refreshSearchIndex(jiraIndexName);
verify(jiraIssueIndexStructureBuilderMock).buildSearchForIndexedDocumentsNotUpdatedAfter(srbmock, "ORG",
boundDate);
verify(esIntegrationMock).prepareESScrollSearchRequestBuilder(jiraIndexName);
verify(esIntegrationMock).executeESSearchRequest(srbmock);
Mockito.verifyNoMoreInteractions(jiraClientMock);
Mockito.verifyNoMoreInteractions(esIntegrationMock);
Mockito.verifyNoMoreInteractions(jiraIssueIndexStructureBuilderMock);
}
// case - perform delete for some issues
{
reset(jiraClientMock);
reset(esIntegrationMock);
reset(jiraIssueIndexStructureBuilderMock);
tested.indexingInfo.fullUpdate = true;
String jiraIndexName = "jira_index";
Date boundDate = DateTimeUtils.parseISODateTime("2012-08-14T07:00:00.000-0400");
when(jiraIssueIndexStructureBuilderMock.getIssuesSearchIndexName("ORG")).thenReturn(jiraIndexName);
SearchRequestBuilder srbmock = new SearchRequestBuilder(client);
when(esIntegrationMock.prepareESScrollSearchRequestBuilder(jiraIndexName)).thenReturn(srbmock);
SearchResponse sr = prepareSearchResponse("scrlid0", new InternalSearchHit(1, "ORG-12", new StringText(""), null));
when(esIntegrationMock.executeESSearchRequest(srbmock)).thenReturn(sr);
BulkRequestBuilder brbmock = new BulkRequestBuilder(client);
when(esIntegrationMock.prepareESBulkRequestBuilder()).thenReturn(brbmock);
InternalSearchHit hit1_1 = new InternalSearchHit(1, "ORG-12", new StringText(""), null);
InternalSearchHit hit1_2 = new InternalSearchHit(2, "ORG-124", new StringText(""), null);
SearchResponse sr1 = prepareSearchResponse("scrlid1", hit1_1, hit1_2);
when(esIntegrationMock.executeESScrollSearchNextRequest(sr)).thenReturn(sr1);
InternalSearchHit hit2_1 = new InternalSearchHit(1, "ORG-22", new StringText(""), null);
InternalSearchHit hit2_2 = new InternalSearchHit(2, "ORG-224", new StringText(""), null);
InternalSearchHit hit2_3 = new InternalSearchHit(3, "ORG-2243", new StringText(""), null);
SearchResponse sr2 = prepareSearchResponse("scrlid2", hit2_1, hit2_2, hit2_3);
when(esIntegrationMock.executeESScrollSearchNextRequest(sr1)).thenReturn(sr2);
when(esIntegrationMock.executeESScrollSearchNextRequest(sr2)).thenReturn(prepareSearchResponse("scrlid3"));
when(jiraIssueIndexStructureBuilderMock.deleteIssueDocument(Mockito.eq(brbmock), Mockito.any(SearchHit.class)))
.thenReturn(true);
tested.processDelete(boundDate);
Assert.assertEquals(5, tested.indexingInfo.issuesDeleted);
verify(jiraIssueIndexStructureBuilderMock).getIssuesSearchIndexName("ORG");
verify(esIntegrationMock).refreshSearchIndex(jiraIndexName);
verify(jiraIssueIndexStructureBuilderMock).buildSearchForIndexedDocumentsNotUpdatedAfter(srbmock, "ORG",
boundDate);
verify(esIntegrationMock).prepareESScrollSearchRequestBuilder(jiraIndexName);
verify(esIntegrationMock).executeESSearchRequest(srbmock);
verify(esIntegrationMock).prepareESBulkRequestBuilder();
verify(esIntegrationMock, times(3)).isClosed();
verify(esIntegrationMock, times(3)).executeESScrollSearchNextRequest(Mockito.any(SearchResponse.class));
verify(jiraIssueIndexStructureBuilderMock).deleteIssueDocument(brbmock, hit1_1);
verify(jiraIssueIndexStructureBuilderMock).deleteIssueDocument(brbmock, hit1_2);
verify(jiraIssueIndexStructureBuilderMock).deleteIssueDocument(brbmock, hit2_1);
verify(jiraIssueIndexStructureBuilderMock).deleteIssueDocument(brbmock, hit2_2);
verify(jiraIssueIndexStructureBuilderMock).deleteIssueDocument(brbmock, hit2_3);
verify(esIntegrationMock).executeESBulkRequest(brbmock);
Mockito.verifyNoMoreInteractions(jiraClientMock);
Mockito.verifyNoMoreInteractions(esIntegrationMock);
Mockito.verifyNoMoreInteractions(jiraIssueIndexStructureBuilderMock);
}
}
private SearchResponse prepareSearchResponse(String scrollId, InternalSearchHit... hits) {
InternalSearchHits hitsi = new InternalSearchHits(hits, hits.length, 10f);
InternalSearchResponse sr1i = new InternalSearchResponse(hitsi, null, null, null, false, null);
SearchResponse sr1 = new SearchResponse(sr1i, scrollId, 1, 1, 100, null);
return sr1;
}
/**
* Add issue info structure into list of issues. Used to build mock {@link ChangedIssuesResults} instances.
*
* @param issues list of issues to add issue into
* @param key of issue
* @param updated field of JIRA issue with format: 2009-03-23T08:38:52.000-0400
*/
protected void addIssueMock(List<Map<String, Object>> issues, String key, String updated) {
Map<String, Object> issue = new HashMap<String, Object>();
issues.add(issue);
issue.put("key", key);
issue.put("updated", updated);
}
protected static IESIntegration mockEsIntegrationComponent() {
IESIntegration esIntegrationMock = mock(IESIntegration.class);
Mockito.when(esIntegrationMock.createLogger(Mockito.any(Class.class))).thenReturn(
ESLoggerFactory.getLogger(JIRAProjectIndexerCoordinator.class.getName()));
return esIntegrationMock;
}
}