/*
* 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 java.util.TimeZone;
import junit.framework.Assert;
import org.elasticsearch.Version;
import org.elasticsearch.action.ListenableActionFuture;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsException;
import org.elasticsearch.common.transport.DummyTransportAddress;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.river.RiverName;
import org.elasticsearch.river.RiverSettings;
import org.jboss.elasticsearch.river.jira.testtools.ESRealClientTestBase;
import org.jboss.elasticsearch.river.jira.testtools.IssueDataPreprocessorMock;
import org.jboss.elasticsearch.river.jira.testtools.MockThread;
import org.jboss.elasticsearch.river.jira.testtools.TestUtils;
import org.jboss.elasticsearch.tools.content.StructuredContentPreprocessor;
import org.junit.Test;
import org.mockito.Mockito;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
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 JiraRiver}.
*
* @author Vlastimil Elias (velias at redhat dot com)
*/
public class JiraRiverTest extends ESRealClientTestBase {
private static final String RIVER_NAME = "my_jira_river";
private static final String KEY_1 = "AAA";
private static final String KEY_2 = "AAB";
@Test
public void constructor_config() throws Exception {
// case - exception if no jira URL base is defined
try {
prepareJiraRiverInstanceForTest(null, null, null, false);
Assert.fail("No SettingsException thrown");
} catch (SettingsException e) {
// OK
}
try {
prepareJiraRiverInstanceForTest(" ", null, null, false);
Assert.fail("No SettingsException thrown");
} catch (SettingsException e) {
// OK
}
Map<String, Object> jiraSettings = new HashMap<String, Object>();
Map<String, Object> toplevelSettingsAdd = new HashMap<String, Object>();
// case - test default settings
JiraRiver tested = prepareJiraRiverInstanceForTest("https://issues.jboss.org", jiraSettings, toplevelSettingsAdd,
false);
Assert.assertEquals(1, tested.maxIndexingThreads);
Assert.assertEquals(5 * 60 * 1000, tested.indexUpdatePeriod);
Assert.assertEquals(12 * 60 * 60 * 1000, tested.indexFullUpdatePeriod);
Assert.assertNull(tested.indexFullUpdateCronExpression);
Assert.assertEquals("my_jira_river", tested.indexName);
Assert.assertEquals(JiraRiver.INDEX_ISSUE_TYPE_NAME_DEFAULT, tested.typeName);
Assert.assertEquals(50, tested.jiraClient.getListJIRAIssuesMax());
Assert.assertEquals("https://issues.jboss.org/rest/api/2/", tested.jiraClient.getJiraAPIUrlBase());
Map<String, Object> indexSettings = new HashMap<String, Object>();
toplevelSettingsAdd.put("index", indexSettings);
tested = prepareJiraRiverInstanceForTest("https://issues.jboss.org", jiraSettings, toplevelSettingsAdd, false);
Assert.assertEquals("my_jira_river", tested.indexName);
Assert.assertEquals(JiraRiver.INDEX_ISSUE_TYPE_NAME_DEFAULT, tested.typeName);
Assert.assertEquals(tested.jiraIssueIndexStructureBuilder, tested.jiraClient.getIndexStructureBuilder());
// case - test river configuration reading
jiraSettings.put("maxIndexingThreads", "5");
jiraSettings.put("indexUpdatePeriod", "20m");
jiraSettings.put("indexFullUpdatePeriod", "5h");
jiraSettings.put("indexFullUpdateCronExpression", "* * 1 * * ?");
jiraSettings.put("maxIssuesPerRequest", 20);
jiraSettings.put("timeout", "5s");
jiraSettings.put("jqlTimeZone", "Europe/Prague");
jiraSettings.put("restApiVersion", "latest");
indexSettings.put("index", "my_index_name");
indexSettings.put("type", "type_test");
tested = prepareJiraRiverInstanceForTest("https://issues.jboss.org", jiraSettings, toplevelSettingsAdd, false);
Assert.assertEquals("https://issues.jboss.org/rest/api/latest/", tested.jiraClient.getJiraAPIUrlBase());
Assert.assertEquals(5, tested.maxIndexingThreads);
Assert.assertEquals(20 * 60 * 1000, tested.indexUpdatePeriod);
Assert.assertEquals(5 * 60 * 60 * 1000, tested.indexFullUpdatePeriod);
Assert.assertEquals("* * 1 * * ?", tested.indexFullUpdateCronExpression.toString());
Assert.assertEquals("my_index_name", tested.indexName);
Assert.assertEquals("type_test", tested.typeName);
Assert.assertEquals(20, tested.jiraClient.getListJIRAIssuesMax());
Assert.assertEquals(TimeZone.getTimeZone("Europe/Prague"),
((JIRA5RestClient) tested.jiraClient).jqlDateFormat.getTimeZone());
// assert index structure builder initialization
Assert.assertEquals(tested.jiraIssueIndexStructureBuilder, tested.jiraClient.getIndexStructureBuilder());
Assert.assertEquals(tested.indexName,
((JIRA5RestIssueIndexStructureBuilder) tested.jiraIssueIndexStructureBuilder).indexName);
Assert.assertEquals(tested.typeName,
((JIRA5RestIssueIndexStructureBuilder) tested.jiraIssueIndexStructureBuilder).issueTypeName);
Assert.assertEquals(tested.riverName().getName(),
((JIRA5RestIssueIndexStructureBuilder) tested.jiraIssueIndexStructureBuilder).riverName);
// case - invalid cron expression
try {
jiraSettings.put("indexFullUpdateCronExpression", "* * * * ? ?");
tested = prepareJiraRiverInstanceForTest("https://issues.jboss.org", jiraSettings, toplevelSettingsAdd, false);
Assert.fail("SettingsException expected");
} catch (SettingsException e) {
Assert
.assertEquals(
"Cron expression in indexFullUpdateCronExpression is invalid: '?' can only be specfied for Day-of-Month or Day-of-Week.",
e.getMessage());
}
}
@Test
public void constructor_postprocessors() throws Exception {
JiraRiver tested = prepareJiraRiverInstanceForTest("https://issues.jboss.org", null,
Utils.loadJSONFromJarPackagedFile("/river_configuration_test_preprocessors.json"), false);
List<StructuredContentPreprocessor> preprocs = ((JIRA5RestIssueIndexStructureBuilder) tested.jiraIssueIndexStructureBuilder).issueDataPreprocessors;
Assert.assertEquals(2, preprocs.size());
Assert.assertEquals("Status Normalizer", preprocs.get(0).getName());
Assert.assertEquals("value1", ((IssueDataPreprocessorMock) preprocs.get(0)).settings.get("some_setting_1_1"));
Assert.assertEquals("value2", ((IssueDataPreprocessorMock) preprocs.get(0)).settings.get("some_setting_1_2"));
Assert.assertEquals("Issue type Normalizer", preprocs.get(1).getName());
Assert.assertEquals("value1", ((IssueDataPreprocessorMock) preprocs.get(1)).settings.get("some_setting_2_1"));
Assert.assertEquals("value2", ((IssueDataPreprocessorMock) preprocs.get(1)).settings.get("some_setting_2_2"));
}
@Test
public void configure() throws Exception {
JiraRiver tested = prepareJiraRiverInstanceForTest(null);
try {
tested.closed = false;
tested.configure(null);
Assert.fail("IllegalStateException must be thrown");
} catch (IllegalStateException e) {
// OK
}
// do not test configuration read here, it's tested in constructor tests
}
@Test
public void start() throws Exception {
JiraRiver tested = prepareJiraRiverInstanceForTest(null);
try {
tested.closed = false;
tested.start();
Assert.fail("IllegalStateException must be thrown");
} catch (IllegalStateException e) {
// OK
}
// do not test real start here because it's hardly testable
}
@Test
public void close() throws Exception {
// case - close all correctly
JiraRiver tested = prepareJiraRiverInstanceForTest(null);
MockThread mockThread = new MockThread();
tested.coordinatorThread = mockThread;
tested.coordinatorInstance = mock(IJIRAProjectIndexerCoordinator.class);
tested.closed = false;
Assert.assertNotNull(tested.coordinatorThread);
Assert.assertNotNull(tested.coordinatorInstance);
JiraRiver.riverInstances.put(tested.riverName().getName(), tested);
Assert.assertTrue(JiraRiver.riverInstances.containsKey(tested.riverName().getName()));
tested.close();
Assert.assertTrue(tested.isClosed());
Assert.assertTrue(mockThread.interruptWasCalled);
Assert.assertNull(tested.coordinatorThread);
Assert.assertNull(tested.coordinatorInstance);
Assert.assertFalse(JiraRiver.riverInstances.containsKey(tested.riverName().getName()));
// case - no exception when coordinatorThread and coordinatorInstance is null
tested = prepareJiraRiverInstanceForTest(null);
JiraRiver.riverInstances.put(tested.riverName().getName(), tested);
tested.coordinatorThread = null;
tested.coordinatorInstance = null;
tested.closed = false;
Assert.assertNull(tested.coordinatorThread);
Assert.assertNull(tested.coordinatorInstance);
tested.close();
Assert.assertTrue(tested.isClosed());
Assert.assertNull(tested.coordinatorThread);
Assert.assertNull(tested.coordinatorInstance);
Assert.assertFalse(JiraRiver.riverInstances.containsKey(tested.riverName().getName()));
}
@Test
public void stop() throws Exception {
// case - close all correctly
JiraRiver tested = prepareJiraRiverInstanceForTest(null);
MockThread mockThread = new MockThread();
tested.coordinatorThread = mockThread;
tested.coordinatorInstance = mock(IJIRAProjectIndexerCoordinator.class);
tested.closed = false;
Assert.assertNotNull(tested.coordinatorThread);
Assert.assertNotNull(tested.coordinatorInstance);
JiraRiver.riverInstances.put(tested.riverName().getName(), tested);
Assert.assertTrue(JiraRiver.riverInstances.containsKey(tested.riverName().getName()));
tested.stop(false);
Assert.assertTrue(tested.isClosed());
Assert.assertTrue(mockThread.interruptWasCalled);
Assert.assertNull(tested.coordinatorThread);
Assert.assertNull(tested.coordinatorInstance);
Assert.assertTrue(JiraRiver.riverInstances.containsKey(tested.riverName().getName()));
// case - no exception when coordinatorThread and coordinatorInstance is null
tested = prepareJiraRiverInstanceForTest(null);
JiraRiver.riverInstances.put(tested.riverName().getName(), tested);
tested.coordinatorThread = null;
tested.coordinatorInstance = null;
tested.closed = false;
Assert.assertNull(tested.coordinatorThread);
Assert.assertNull(tested.coordinatorInstance);
tested.stop(false);
Assert.assertTrue(tested.isClosed());
Assert.assertNull(tested.coordinatorThread);
Assert.assertNull(tested.coordinatorInstance);
Assert.assertTrue(JiraRiver.riverInstances.containsKey(tested.riverName().getName()));
}
@Test
public void stop_permanent() throws Exception {
JiraRiver tested = prepareJiraRiverInstanceForTest(null);
try {
tested.client = prepareESClientForUnitTest();
indexCreate(tested.getRiverIndexName());
// case - not permanent stop
tested.closed = false;
tested.stop(false);
Assert.assertNull(tested.readDatetimeValue(null, JiraRiver.PERMSTOREPROP_RIVER_STOPPED_PERMANENTLY));
Assert.assertTrue(tested.isClosed());
// case - permanent stop
tested.closed = false;
tested.stop(true);
Assert.assertNotNull(tested.readDatetimeValue(null, JiraRiver.PERMSTOREPROP_RIVER_STOPPED_PERMANENTLY));
Assert.assertTrue(tested.isClosed());
} finally {
finalizeESClientForUnitTest();
}
}
@Test
public void reconfigure() throws Exception {
// case - exception when not stopped
{
JiraRiver tested = prepareJiraRiverInstanceForTest(null);
try {
tested.closed = false;
tested.reconfigure();
Assert.fail("IllegalStateException must be thrown");
} catch (IllegalStateException e) {
// OK
}
}
// case - config reload error because no document
{
JiraRiver tested = prepareJiraRiverInstanceForTest(null);
try {
tested.client = prepareESClientForUnitTest();
tested.closed = true;
indexCreate(tested.getRiverIndexName());
tested.reconfigure();
Assert.fail("IllegalStateException must be thrown");
} catch (IllegalStateException e) {
// OK
} finally {
finalizeESClientForUnitTest();
}
}
// case - config reload performed
{
JiraRiver tested = prepareJiraRiverInstanceForTest(null);
try {
tested.client = prepareESClientForUnitTest();
tested.closed = true;
tested.client.prepareIndex(tested.getRiverIndexName(), tested.riverName().getName(), "_meta")
.setSource(TestUtils.readStringFromClasspathFile("/river_reconfiguration_test.json")).execute().actionGet();
tested.reconfigure();
Assert.assertEquals("https://issues.jboss.org/rest/api/2/",
((JIRA5RestClient) tested.jiraClient).jiraRestAPIUrlBase);
Assert.assertEquals("my_jira_index_test", tested.indexName);
Assert.assertEquals("jira_issue_test", tested.typeName);
Assert.assertEquals("jira_river_activity_test", tested.activityLogIndexName);
Assert.assertEquals("jira_river_indexupdate_test", tested.activityLogTypeName);
} finally {
finalizeESClientForUnitTest();
}
}
}
@Test
public void restart() {
// TODO unit test for river restart method
}
@Test
public void getAllIndexedProjectsKeys_FromStaticConfig() throws Exception {
Map<String, Object> jiraSettings = new HashMap<String, Object>();
jiraSettings.put("projectKeysIndexed", "ORG, UUUU, PEM, SU07");
JiraRiver tested = prepareJiraRiverInstanceForTest(jiraSettings);
IJIRAClient jiraClientMock = tested.jiraClient;
List<String> r = tested.getAllIndexedProjectsKeys();
Assert.assertEquals(4, r.size());
Assert.assertEquals("ORG", r.get(0));
Assert.assertEquals("UUUU", r.get(1));
Assert.assertEquals("PEM", r.get(2));
Assert.assertEquals("SU07", r.get(3));
Assert.assertEquals(Long.MAX_VALUE, tested.allIndexedProjectsKeysNextRefresh);
verify(jiraClientMock, times(0)).getAllJIRAProjects();
}
@Test
public void getAllIndexedProjectsKeys_FromJIRANoExcludes() throws Exception {
Map<String, Object> jiraSettings = new HashMap<String, Object>();
jiraSettings.put("projectKeysExcluded", "");
JiraRiver tested = prepareJiraRiverInstanceForTest(jiraSettings);
IJIRAClient jiraClientMock = tested.jiraClient;
List<String> pl = Utils.parseCsvString("ORG,UUUU,PEM,SU07");
when(jiraClientMock.getAllJIRAProjects()).thenReturn(pl);
List<String> r = tested.getAllIndexedProjectsKeys();
verify(jiraClientMock, times(1)).getAllJIRAProjects();
Assert.assertEquals(4, r.size());
Assert.assertEquals("ORG", r.get(0));
Assert.assertEquals("UUUU", r.get(1));
Assert.assertEquals("PEM", r.get(2));
Assert.assertEquals("SU07", r.get(3));
Assert
.assertTrue(tested.allIndexedProjectsKeysNextRefresh <= (System.currentTimeMillis() + JiraRiver.JIRA_PROJECTS_REFRESH_TIME));
}
@Test
public void getAllIndexedProjectsKeys_FromJIRAWithExcludes() throws Exception {
Map<String, Object> jiraSettings = new HashMap<String, Object>();
jiraSettings.put("projectKeysExcluded", "PEM,UUUU");
JiraRiver tested = prepareJiraRiverInstanceForTest(jiraSettings);
IJIRAClient jiraClientMock = tested.jiraClient;
List<String> pl = Utils.parseCsvString("ORG,UUUU,PEM,SU07");
when(jiraClientMock.getAllJIRAProjects()).thenReturn(pl);
List<String> r = tested.getAllIndexedProjectsKeys();
verify(jiraClientMock, times(1)).getAllJIRAProjects();
Assert.assertEquals(2, r.size());
Assert.assertEquals("ORG", r.get(0));
Assert.assertEquals("SU07", r.get(1));
Assert
.assertTrue(tested.allIndexedProjectsKeysNextRefresh <= (System.currentTimeMillis() + JiraRiver.JIRA_PROJECTS_REFRESH_TIME));
}
@Test
public void storeDatetimeValueBuildDocument() throws Exception {
JiraRiver tested = prepareJiraRiverInstanceForTest(null);
String dt = "2012-09-30T12:22:44.156Z";
Date d = DateTimeUtils.parseISODateTime(dt);
{
Map<String, Object> out = TestUtils.getJSONMapFromString(tested.storeDatetimeValueBuildDocument(null,
"my_property", d).string());
Assert.assertEquals(2, out.size());
Assert.assertEquals("my_property", out.get("propertyName"));
Assert.assertEquals(d.getTime(), DateTimeUtils.parseISODateTime((String) out.get("value")).getTime());
}
{
Map<String, Object> out = TestUtils.getJSONMapFromString(tested.storeDatetimeValueBuildDocument("AAA",
"my_property", d).string());
Assert.assertEquals(3, out.size());
Assert.assertEquals("AAA", out.get("projectKey"));
Assert.assertEquals("my_property", out.get("propertyName"));
Assert.assertEquals(d.getTime(), DateTimeUtils.parseISODateTime((String) out.get("value")).getTime());
}
}
@Test
public void readAndStoreAndDeleteDatetimeValue() throws Exception {
try {
Client client = prepareESClientForUnitTest();
JiraRiver tested = prepareJiraRiverInstanceForTest(null);
tested.client = client;
indexCreate("_river");
Assert.assertFalse(tested.deleteDatetimeValue("ORG1", "testProperty_1_1"));
tested
.storeDatetimeValue("ORG1", "testProperty_1_1", DateTimeUtils.parseISODateTime("2012-09-03T18:12:45"), null);
tested
.storeDatetimeValue("ORG1", "testProperty_1_2", DateTimeUtils.parseISODateTime("2012-09-03T05:12:40"), null);
tested
.storeDatetimeValue("ORG2", "testProperty_1_1", DateTimeUtils.parseISODateTime("2012-09-02T08:12:30"), null);
tested
.storeDatetimeValue("ORG2", "testProperty_1_2", DateTimeUtils.parseISODateTime("2012-09-02T05:02:20"), null);
Assert.assertEquals(DateTimeUtils.parseISODateTime("2012-09-03T18:12:45"),
tested.readDatetimeValue("ORG1", "testProperty_1_1"));
Assert.assertEquals(DateTimeUtils.parseISODateTime("2012-09-03T05:12:40"),
tested.readDatetimeValue("ORG1", "testProperty_1_2"));
Assert.assertEquals(DateTimeUtils.parseISODateTime("2012-09-02T08:12:30"),
tested.readDatetimeValue("ORG2", "testProperty_1_1"));
Assert.assertEquals(DateTimeUtils.parseISODateTime("2012-09-02T05:02:20"),
tested.readDatetimeValue("ORG2", "testProperty_1_2"));
Assert.assertTrue(tested.deleteDatetimeValue("ORG1", "testProperty_1_1"));
Assert.assertNull(tested.readDatetimeValue("ORG1", "testProperty_1_1"));
Assert.assertEquals(DateTimeUtils.parseISODateTime("2012-09-03T05:12:40"),
tested.readDatetimeValue("ORG1", "testProperty_1_2"));
Assert.assertEquals(DateTimeUtils.parseISODateTime("2012-09-02T08:12:30"),
tested.readDatetimeValue("ORG2", "testProperty_1_1"));
Assert.assertEquals(DateTimeUtils.parseISODateTime("2012-09-02T05:02:20"),
tested.readDatetimeValue("ORG2", "testProperty_1_2"));
Assert.assertTrue(tested.deleteDatetimeValue("ORG1", "testProperty_1_2"));
Assert.assertNull(tested.readDatetimeValue("ORG1", "testProperty_1_2"));
Assert.assertEquals(DateTimeUtils.parseISODateTime("2012-09-02T08:12:30"),
tested.readDatetimeValue("ORG2", "testProperty_1_1"));
Assert.assertEquals(DateTimeUtils.parseISODateTime("2012-09-02T05:02:20"),
tested.readDatetimeValue("ORG2", "testProperty_1_2"));
} finally {
finalizeESClientForUnitTest();
}
}
@Test
public void storeDatetimeValue_Bulk() throws Exception {
JiraRiver tested = prepareJiraRiverInstanceForTest(null);
BulkRequestBuilder esBulk = new BulkRequestBuilder(tested.client);
tested.storeDatetimeValue("ORG", "prop", new Date(), esBulk);
tested.storeDatetimeValue("ORG", "prop2", new Date(), esBulk);
tested.storeDatetimeValue("ORG", "prop3", new Date(), esBulk);
Assert.assertEquals(3, esBulk.numberOfActions());
}
@Test
public void prepareValueStoreDocumentName() {
Assert.assertEquals("_lastupdatedissue_ORG", JiraRiver.prepareValueStoreDocumentName("ORG", "lastupdatedissue"));
Assert.assertEquals("_lastupdatedissue", JiraRiver.prepareValueStoreDocumentName(null, "lastupdatedissue"));
}
@Test
public void prepareESBulkRequestBuilder() throws Exception {
JiraRiver tested = prepareJiraRiverInstanceForTest(null);
Client clientMock = tested.client;
BulkRequestBuilder brb = new BulkRequestBuilder(clientMock);
when(clientMock.prepareBulk()).thenReturn(brb);
Assert.assertNotNull(tested.prepareESBulkRequestBuilder());
verify(clientMock, times(1)).prepareBulk();
}
@Test
public void reportIndexingFinished() throws Exception {
IJIRAProjectIndexerCoordinator coordMock = mock(IJIRAProjectIndexerCoordinator.class);
JiraRiver tested = prepareJiraRiverInstanceForTest(null);
Client clientMock = tested.client;
tested.coordinatorInstance = coordMock;
// case - report correctly - no activity log
{
tested.reportIndexingFinished(new ProjectIndexingInfo("ORG", false, 10, 0, 0, null, true, 10, null));
verify(coordMock, times(1)).reportIndexingFinished("ORG", true, false);
Mockito.verifyZeroInteractions(clientMock);
}
{
reset(coordMock);
tested.reportIndexingFinished(new ProjectIndexingInfo("AAA", true, 10, 0, 0, null, false, 10, null));
verify(coordMock, times(1)).reportIndexingFinished("AAA", false, true);
Mockito.verifyZeroInteractions(clientMock);
}
// report correctly with activity log
tested.activityLogIndexName = "alindex";
tested.activityLogTypeName = "altype";
{
IndexRequestBuilder irb = Mockito.mock(IndexRequestBuilder.class);
Mockito.when(irb.setSource(Mockito.any(XContentBuilder.class))).thenReturn(irb);
@SuppressWarnings("unchecked")
ListenableActionFuture<IndexResponse> laf = Mockito.mock(ListenableActionFuture.class);
Mockito.when(irb.execute()).thenReturn(laf);
when(clientMock.prepareIndex("alindex", "altype")).thenReturn(irb);
tested.reportIndexingFinished(new ProjectIndexingInfo("ORG", false, 10, 0, 0, null, true, 10, null));
Mockito.verify(irb).setSource(Mockito.any(XContentBuilder.class));
Mockito.verify(irb).execute();
Mockito.verify(laf).actionGet();
}
// case - no exception if coordinatorInstance is null
tested = prepareJiraRiverInstanceForTest(null);
tested.reportIndexingFinished(new ProjectIndexingInfo("ORG", false, 10, 0, 0, null, true, 10, null));
}
@Test
public void prepareESScrollSearchRequestBuilder() throws Exception {
JiraRiver tested = prepareJiraRiverInstanceForTest(null);
Client clientMock = tested.client;
SearchRequestBuilder srb = new SearchRequestBuilder(clientMock);
when(clientMock.prepareSearch("myIndex")).thenReturn(srb);
tested.prepareESScrollSearchRequestBuilder("myIndex");
Assert.assertNotNull(srb.request().scroll());
Assert.assertEquals(SearchType.SCAN, srb.request().searchType());
verify(clientMock).prepareSearch("myIndex");
}
@Test
public void getRiverOperationInfo_activityLogDisabled() throws Exception {
JiraRiver tested = prepareJiraRiverInstanceForTest(null);
IJIRAProjectIndexerCoordinator coordMock = mock(IJIRAProjectIndexerCoordinator.class);
tested.coordinatorInstance = coordMock;
List<ProjectIndexingInfo> currentIndexings = new ArrayList<ProjectIndexingInfo>();
currentIndexings.add(new ProjectIndexingInfo("ORG", true, 256, 10, 0, DateTimeUtils
.parseISODateTime("2012-09-27T09:21:25.422Z"), false, 0, null));
currentIndexings.add(new ProjectIndexingInfo("AAA", false, 15, 0, 0, DateTimeUtils
.parseISODateTime("2012-09-27T09:21:24.422Z"), false, 0, null));
when(coordMock.getCurrentProjectIndexingInfo()).thenReturn(currentIndexings);
tested.allIndexedProjectsKeysNextRefresh = Long.MAX_VALUE;
tested.allIndexedProjectsKeys = new ArrayList<String>();
tested.allIndexedProjectsKeys.add("ORG");
tested.allIndexedProjectsKeys.add("AAA");
tested.allIndexedProjectsKeys.add("JJJ");
tested.allIndexedProjectsKeys.add("FFF");
tested.lastProjectIndexingInfo.put("ORG",
new ProjectIndexingInfo("ORG", true, 125, 10, 0, DateTimeUtils.parseISODateTime("2012-09-27T09:15:25.422Z"),
true, 1500, null));
tested.lastProjectIndexingInfo.put("JJJ",
new ProjectIndexingInfo("JJJ", false, 12, 0, 0, DateTimeUtils.parseISODateTime("2012-09-27T09:12:25.422Z"),
false, 1800, "JIRA timeout"));
// case - nothing stored in audit log index - no exception!
String info = tested.getRiverOperationInfo(new DiscoveryNode("My Node", "fsdfsdfxzd",
DummyTransportAddress.INSTANCE, new HashMap<String, String>(), Version.CURRENT), DateTimeUtils
.parseISODateTime("2012-09-27T09:21:26.422Z"));
TestUtils.assertStringFromClasspathFile("/asserts/JiraRiver_getRiverOperationInfo_1.json", info);
}
@Test
public void getRiverOperationInfo_activityLogEnabled() throws Exception {
try {
Client client = prepareESClientForUnitTest();
JiraRiver tested = prepareJiraRiverInstanceForTest(null);
tested.client = client;
tested.activityLogIndexName = "activity_log_index";
tested.activityLogTypeName = "jira_river_indexupdate";
IJIRAProjectIndexerCoordinator coordMock = mock(IJIRAProjectIndexerCoordinator.class);
tested.coordinatorInstance = coordMock;
List<ProjectIndexingInfo> currentIndexings = new ArrayList<ProjectIndexingInfo>();
currentIndexings.add(new ProjectIndexingInfo("ORG", true, 256, 10, 0, DateTimeUtils
.parseISODateTime("2012-09-27T09:21:25.422Z"), false, 0, null));
currentIndexings.add(new ProjectIndexingInfo("AAA", false, 15, 0, 0, DateTimeUtils
.parseISODateTime("2012-09-27T09:21:24.422Z"), false, 0, null));
when(coordMock.getCurrentProjectIndexingInfo()).thenReturn(currentIndexings);
tested.allIndexedProjectsKeysNextRefresh = Long.MAX_VALUE;
tested.allIndexedProjectsKeys = new ArrayList<String>();
tested.allIndexedProjectsKeys.add("ORG");
tested.allIndexedProjectsKeys.add("AAA");
tested.allIndexedProjectsKeys.add("JJJ");
tested.allIndexedProjectsKeys.add("FFF");
tested.lastProjectIndexingInfo.put("ORG",
new ProjectIndexingInfo("ORG", true, 125, 10, 0, DateTimeUtils.parseISODateTime("2012-09-27T09:15:25.422Z"),
true, 1500, null));
tested.lastProjectIndexingInfo.put("JJJ",
new ProjectIndexingInfo("JJJ", false, 12, 0, 0, DateTimeUtils.parseISODateTime("2012-09-27T09:12:25.422Z"),
false, 1800, "JIRA timeout"));
// case - nothing stored in audit log index - no exception!
String info = tested.getRiverOperationInfo(new DiscoveryNode("My Node", "fsdfsdfxzd",
DummyTransportAddress.INSTANCE, new HashMap<String, String>(), Version.CURRENT), DateTimeUtils
.parseISODateTime("2012-09-27T09:21:26.422Z"));
TestUtils.assertStringFromClasspathFile("/asserts/JiraRiver_getRiverOperationInfo_1.json", info);
// case - last indexed record into ES index for FFF project found
indexCreate(tested.activityLogIndexName);
client.admin().indices().preparePutMapping(tested.activityLogIndexName).setType(tested.activityLogTypeName)
.setSource(TestUtils.readStringFromClasspathFile("/examples/jira_river_indexupdate.json")).execute()
.actionGet();
tested.writeActivityLogRecord(new ProjectIndexingInfo("FFF", false, 12, 0, 0, DateTimeUtils
.parseISODateTime("2012-09-27T08:10:25.422Z"), true, 181, null));
tested.writeActivityLogRecord(new ProjectIndexingInfo("FFF", false, 125, 0, 0, DateTimeUtils
.parseISODateTime("2012-09-27T08:11:25.422Z"), true, 1810, null));
tested.refreshSearchIndex(tested.activityLogIndexName);
info = tested.getRiverOperationInfo(new DiscoveryNode("My Node", "fsdfsdfxzd", DummyTransportAddress.INSTANCE,
new HashMap<String, String>(), Version.CURRENT), DateTimeUtils.parseISODateTime("2012-09-27T09:21:26.422Z"));
TestUtils.assertStringFromClasspathFile("/asserts/JiraRiver_getRiverOperationInfo_2.json", info);
} finally {
finalizeESClientForUnitTest();
}
}
@Test
public void forceFullReindex() throws Exception {
JiraRiver tested = prepareJiraRiverInstanceForTest(null);
IJIRAProjectIndexerCoordinator coordinatorMock = mock(IJIRAProjectIndexerCoordinator.class);
tested.coordinatorInstance = coordinatorMock;
// case - all projects but no any exists
{
tested.allIndexedProjectsKeys = null;
Assert.assertEquals("", tested.forceFullReindex(null));
Mockito.verifyNoMoreInteractions(coordinatorMock);
}
// case - all projects and some exists
{
reset(coordinatorMock);
tested.allIndexedProjectsKeys = new ArrayList<String>();
tested.allIndexedProjectsKeys.add("ORG");
tested.allIndexedProjectsKeys.add("AAA");
Assert.assertEquals("ORG,AAA", tested.forceFullReindex(null));
verify(coordinatorMock).forceFullReindex("ORG");
verify(coordinatorMock).forceFullReindex("AAA");
Mockito.verifyNoMoreInteractions(coordinatorMock);
}
// case - one project not exists
{
reset(coordinatorMock);
Assert.assertNull(tested.forceFullReindex("BBB"));
Mockito.verifyNoMoreInteractions(coordinatorMock);
}
// case - one project which exists
{
reset(coordinatorMock);
Assert.assertEquals("ORG", tested.forceFullReindex("ORG"));
verify(coordinatorMock).forceFullReindex("ORG");
Mockito.verifyNoMoreInteractions(coordinatorMock);
reset(coordinatorMock);
Assert.assertEquals("AAA", tested.forceFullReindex("AAA"));
verify(coordinatorMock).forceFullReindex("AAA");
Mockito.verifyNoMoreInteractions(coordinatorMock);
}
}
@Test
public void forceIncrementalReindex() throws Exception {
JiraRiver tested = prepareJiraRiverInstanceForTest(null);
IJIRAProjectIndexerCoordinator coordinatorMock = mock(IJIRAProjectIndexerCoordinator.class);
tested.coordinatorInstance = coordinatorMock;
// case - all projects but no any exists
{
tested.allIndexedProjectsKeys = null;
Assert.assertEquals("", tested.forceIncrementalReindex(null));
Mockito.verifyNoMoreInteractions(coordinatorMock);
}
// case - all projects and some exists
{
reset(coordinatorMock);
tested.allIndexedProjectsKeys = new ArrayList<String>();
tested.allIndexedProjectsKeys.add("ORG");
tested.allIndexedProjectsKeys.add("AAA");
Assert.assertEquals("ORG,AAA", tested.forceIncrementalReindex(null));
verify(coordinatorMock).forceIncrementalReindex("ORG");
verify(coordinatorMock).forceIncrementalReindex("AAA");
Mockito.verifyNoMoreInteractions(coordinatorMock);
}
// case - one project not exists
{
reset(coordinatorMock);
Assert.assertNull(tested.forceIncrementalReindex("BBB"));
Mockito.verifyNoMoreInteractions(coordinatorMock);
}
// case - one project which exists
{
reset(coordinatorMock);
Assert.assertEquals("ORG", tested.forceIncrementalReindex("ORG"));
verify(coordinatorMock).forceIncrementalReindex("ORG");
Mockito.verifyNoMoreInteractions(coordinatorMock);
reset(coordinatorMock);
Assert.assertEquals("AAA", tested.forceIncrementalReindex("AAA"));
verify(coordinatorMock).forceIncrementalReindex("AAA");
Mockito.verifyNoMoreInteractions(coordinatorMock);
}
}
@Test
public void createLogger() throws Exception {
JiraRiver tested = prepareJiraRiverInstanceForTest(null);
ESLogger logger = tested.createLogger(JIRAProjectIndexerCoordinator.class);
Assert.assertNotNull(logger);
Assert.assertEquals("org.elasticsearch.org.jboss.elasticsearch.river.jira.JIRAProjectIndexerCoordinator",
logger.getName());
Assert.assertEquals(" [jira][" + RIVER_NAME + "] ", logger.getPrefix());
}
@Test
public void riverName() throws Exception {
JiraRiver tested = prepareJiraRiverInstanceForTest(null);
RiverName rn = tested.riverName();
Assert.assertEquals(RIVER_NAME, rn.getName());
Assert.assertEquals("jira", rn.getType());
}
@Test
public void writeActivityLogRecord_getLastSpaceIndexingInfo() throws Exception {
JiraRiver tested = prepareJiraRiverInstanceForTest(null);
tested.activityLogIndexName = "alindex";
tested.activityLogTypeName = "altype";
try {
tested.client = prepareESClientForUnitTest();
indexCreate(tested.activityLogIndexName);
indexCreateMapping(tested.activityLogIndexName, tested.activityLogTypeName, "{\n" + " \""
+ tested.activityLogTypeName + "\" : {\n" + " \"properties\" : {\n"
+ " \"river_name\" : {\"type\" : \"string\", \"analyzer\" : \"keyword\"},\n"
+ " \"project_key\" : {\"type\" : \"string\", \"analyzer\" : \"keyword\"},\n"
+ " \"update_type\" : {\"type\" : \"string\", \"analyzer\" : \"keyword\"},\n"
+ " \"result\" : {\"type\" : \"string\", \"analyzer\" : \"keyword\"}\n" + " }\n"
+ " }\n" + " }");
// older record to be sure latest one is readed
ProjectIndexingInfo indexingInfo1Older = new ProjectIndexingInfo(KEY_1, false, 5, 2, 1,
DateTimeUtils.parseISODateTimeWithMinutePrecise("2014-12-22T12:53"), true, 60000, null);
indexingInfo1Older.finishedOK = true;
tested.writeActivityLogRecord(indexingInfo1Older);
ProjectIndexingInfo indexingInfo1 = new ProjectIndexingInfo(KEY_1, false, 5, 2, 1,
DateTimeUtils.parseISODateTimeWithMinutePrecise("2014-12-22T12:55"), true, 60000, null);
indexingInfo1.finishedOK = true;
tested.writeActivityLogRecord(indexingInfo1);
// #56 - newer record from another river name to be sure correct one is readed
ProjectIndexingInfo indexingInfo1OtherRiver = new ProjectIndexingInfo(KEY_1, false, 5, 2, 1,
DateTimeUtils.parseISODateTimeWithMinutePrecise("2014-12-22T12:56"), true, 60000, null);
indexingInfo1OtherRiver.finishedOK = true;
tested.client.prepareIndex(tested.activityLogIndexName, tested.activityLogTypeName)
.setSource(indexingInfo1OtherRiver.buildDocument(jsonBuilder(), "other_river", true, true)).execute()
.actionGet();
ProjectIndexingInfo indexingInfo2 = new ProjectIndexingInfo(KEY_2, false, 8, 1, 0,
DateTimeUtils.parseISODateTimeWithMinutePrecise("2014-12-22T12:56"), false, 60000, "error");
indexingInfo2.finishedOK = true;
tested.writeActivityLogRecord(indexingInfo2);
assertLastInfo(tested, indexingInfo1);
assertLastInfo(tested, indexingInfo2);
} finally {
finalizeESClientForUnitTest();
}
}
private void assertLastInfo(JiraRiver tested, ProjectIndexingInfo indexingInfoExpected) {
ProjectIndexingInfo indexingInfoReal = tested.getLastProjectIndexingInfo(indexingInfoExpected.projectKey);
Assert.assertNotNull(indexingInfoReal);
Assert.assertEquals(indexingInfoExpected.startDate, indexingInfoReal.startDate);
Assert.assertEquals(indexingInfoExpected.issuesDeleted, indexingInfoReal.issuesDeleted);
Assert.assertEquals(indexingInfoExpected.issuesUpdated, indexingInfoReal.issuesUpdated);
Assert.assertEquals(indexingInfoExpected.finishedOK, indexingInfoReal.finishedOK);
Assert.assertEquals(indexingInfoExpected.fullUpdate, indexingInfoReal.fullUpdate);
Assert.assertEquals(indexingInfoExpected.timeElapsed, indexingInfoReal.timeElapsed);
}
/**
* Prepare {@link JiraRiver} instance for unit test, with Mockito moceked jiraClient and elasticSearchClient.
*
* @param jiraSettingsAdd additional/optional config properties to be added into <code>jira</code> configuration node
* @return instance for tests
* @throws Exception from constructor
*/
protected JiraRiver prepareJiraRiverInstanceForTest(Map<String, Object> jiraSettingsAdd) throws Exception {
return prepareJiraRiverInstanceForTest("https://issues.jboss.org", jiraSettingsAdd, null, true);
}
/**
* Prepare {@link JiraRiver} instance for unit test, with Mockito moceked jiraClient and elasticSearchClient.
*
* @param urlBase parameter for jira settings
* @param jiraSettingsAdd additional/optional config properties to be added into <code>jira</code> configuration node
* @param toplevelSettingsAdd additional/optional config properties to be added into toplevel node. Do not add
* <code>jira</code> here, will be ignored.
* @param jiraClientMock if set to true then Mockito mock instance is createdand set into {@link JiraRiver#jiraClient}
* @return instance for tests
* @throws Exception from constructor
*/
public static JiraRiver prepareJiraRiverInstanceForTest(String urlBase, Map<String, Object> jiraSettingsAdd,
Map<String, Object> toplevelSettingsAdd, boolean jiraClientMock) throws Exception {
Map<String, Object> settings = new HashMap<String, Object>();
if (toplevelSettingsAdd != null)
settings.putAll(toplevelSettingsAdd);
if (urlBase != null || jiraSettingsAdd != null) {
Map<String, Object> jiraSettings = new HashMap<String, Object>();
settings.put("jira", jiraSettings);
if (jiraSettingsAdd != null)
jiraSettings.putAll(jiraSettingsAdd);
jiraSettings.put("urlBase", urlBase);
}
Settings gs = mock(Settings.class);
RiverSettings rs = new RiverSettings(gs, settings);
Client clientMock = mock(Client.class);
JiraRiver tested = new JiraRiver(new RiverName("jira", RIVER_NAME), rs, clientMock);
if (jiraClientMock) {
IJIRAClient jClientMock = mock(IJIRAClient.class);
tested.jiraClient = jClientMock;
}
return tested;
}
}