/* * 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.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.map.DeserializationConfig; import org.codehaus.jackson.map.ObjectMapper; import org.elasticsearch.action.bulk.BulkRequestBuilder; import org.elasticsearch.action.search.SearchRequestBuilder; import org.elasticsearch.client.Client; import org.elasticsearch.common.logging.ESLoggerFactory; import org.elasticsearch.common.settings.SettingsException; import org.elasticsearch.common.xcontent.XContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentGenerator; import org.elasticsearch.river.RiverName; import org.jboss.elasticsearch.river.jira.testtools.TestUtils; import org.jboss.elasticsearch.tools.content.StructuredContentPreprocessor; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; 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 JIRA5RestIssueIndexStructureBuilder}. * * @author Vlastimil Elias (velias at redhat dot com) * @author Lukáš Vlček (lvlcek@redhat.com) */ public class JIRA5RestIssueIndexStructureBuilderTest { private static ObjectMapper mapper; private JsonNode toJsonNode(String source) { JsonNode node = null; try { node = mapper.readValue(source, JsonNode.class); } catch (IOException e) { fail("Exception while parsing!: " + e); } return node; } @BeforeClass public static void setUp() { mapper = new ObjectMapper(); mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); } @Test public void configuration_read_ok() { IESIntegration esMock = mockEsIntegrationComponent(); JIRA5RestIssueIndexStructureBuilder tested = new JIRA5RestIssueIndexStructureBuilder(esMock, "index_name", "type_name", "http://issues-stg.jboss.org", loadTestSettings("/index_structure_configuration_test_ok.json")); Mockito.verify(esMock).createLogger(JIRA5RestIssueIndexStructureBuilder.class); Assert.assertEquals("river_name", tested.riverName); Assert.assertEquals("index_name", tested.indexName); Assert.assertEquals("type_name", tested.issueTypeName); Assert.assertEquals("document_id", tested.jiraFieldForIssueDocumentId); Assert.assertEquals("river_name", tested.indexFieldForRiverName); Assert.assertEquals("link", tested.indexFieldForJiraURL); Assert.assertEquals("http://issues-stg.jboss.org/browse/", tested.jiraIssueShowUrlBase); Assert.assertEquals("jira_project_key", tested.indexFieldForProjectKey); Assert.assertEquals("jira_issue_key", tested.indexFieldForIssueKey); Assert.assertEquals(IssueCommentIndexingMode.CHILD, tested.commentIndexingMode); Assert.assertEquals("all_comments", tested.indexFieldForComments); Assert.assertEquals("jira_issue_comment_type", tested.commentTypeName); Assert.assertEquals(IssueCommentIndexingMode.CHILD, tested.changelogIndexingMode); Assert.assertEquals("all_changelogs", tested.indexFieldForChangelogs); Assert.assertEquals("jira_issue_change_type", tested.changelogTypeName); Assert.assertEquals(5, tested.fieldsConfig.size()); assertFieldConfiguration(tested.fieldsConfig, "created", "fields.created", null); assertFieldConfiguration(tested.fieldsConfig, "reporter", "fields.reporter", "user2"); assertFieldConfiguration(tested.fieldsConfig, "assignee", "fields.assignee", "user2"); assertFieldConfiguration(tested.fieldsConfig, "fix_versions", "fields.fixVersions", "name2"); assertFieldConfiguration(tested.fieldsConfig, "components", "fields.components", "name2"); Assert.assertEquals(2, tested.filtersConfig.size()); Assert.assertTrue(tested.filtersConfig.containsKey("user2")); Assert.assertTrue(tested.filtersConfig.containsKey("name2")); Map<String, String> userFilter = tested.filtersConfig.get("user2"); Assert.assertEquals(2, userFilter.size()); Assert.assertEquals("username2", userFilter.get("name")); Assert.assertEquals("display_name2", userFilter.get("displayName")); Assert.assertEquals(4, tested.commentFieldsConfig.size()); assertFieldConfiguration(tested.commentFieldsConfig, "comment_body", "body", null); assertFieldConfiguration(tested.commentFieldsConfig, "comment_author2", "author", "user2"); assertFieldConfiguration(tested.commentFieldsConfig, "comment_updater", "updateAuthor", "user2"); assertFieldConfiguration(tested.commentFieldsConfig, "comment_created", "created", null); Assert.assertEquals(3, tested.changelogFieldsConfig.size()); assertFieldConfiguration(tested.changelogFieldsConfig, "change_id", "id", null); assertFieldConfiguration(tested.changelogFieldsConfig, "change_author2", "author", "user2"); assertFieldConfiguration(tested.changelogFieldsConfig, "change_items", "items", null); } @SuppressWarnings("unchecked") private Map<String, Object> loadTestSettings(String file) { return (Map<String, Object>) Utils.loadJSONFromJarPackagedFile(file).get("index"); } @Test public void configuration_read_validation() { try { new JIRA5RestIssueIndexStructureBuilder(mockEsIntegrationComponent(), "index_name", "type_name", "http://issues-stg.jboss.org/", loadTestSettings("/index_structure_configuration_test_err_nojirafield.json")); Assert.fail("SettingsException must be thrown"); } catch (SettingsException e) { System.out.println(e.getMessage()); Assert.assertEquals("'jira_field' is not defined in 'index/fields/reporter'", e.getMessage()); } try { new JIRA5RestIssueIndexStructureBuilder(mockEsIntegrationComponent(), "index_name", "type_name", "http://issues-stg.jboss.org", loadTestSettings("/index_structure_configuration_test_err_emptyjirafield.json")); Assert.fail("SettingsException must be thrown"); } catch (SettingsException e) { System.out.println(e.getMessage()); Assert.assertEquals("'jira_field' is not defined in 'index/fields/link'", e.getMessage()); } try { new JIRA5RestIssueIndexStructureBuilder(mockEsIntegrationComponent(), "index_name", "type_name", "http://issues-stg.jboss.org/", loadTestSettings("/index_structure_configuration_test_err_unknownvaluefilter.json")); Assert.fail("SettingsException must be thrown"); } catch (SettingsException e) { System.out.println(e.getMessage()); Assert.assertEquals( "Filter definition not found for filter name 'name3' defined in 'index/fields/fix_versions/value_filter'", e.getMessage()); } try { new JIRA5RestIssueIndexStructureBuilder(mockEsIntegrationComponent(), "index_name", "type_name", "http://issues-stg.jboss.org/", loadTestSettings("/index_structure_configuration_test_err_nojirafieldcomment.json")); Assert.fail("SettingsException must be thrown"); } catch (SettingsException e) { System.out.println(e.getMessage()); Assert.assertEquals("'jira_field' is not defined in 'index/comment_fields/comment_author'", e.getMessage()); } } @SuppressWarnings("rawtypes") @Test public void configuration_defaultLoading() { assertDefaultConfigurationLoaded(new JIRA5RestIssueIndexStructureBuilder(mockEsIntegrationComponent(), "index_name", "type_name", "http://issues-stg.jboss.org", null)); Map<String, Object> settings = new HashMap<String, Object>(); assertDefaultConfigurationLoaded(new JIRA5RestIssueIndexStructureBuilder(mockEsIntegrationComponent(), "index_name", "type_name", "http://issues-stg.jboss.org", settings)); settings.put(JIRA5RestIssueIndexStructureBuilder.CONFIG_FIELDS, new HashMap()); settings.put(JIRA5RestIssueIndexStructureBuilder.CONFIG_FILTERS, new HashMap()); settings.put(JIRA5RestIssueIndexStructureBuilder.CONFIG_FIELDRIVERNAME, " "); assertDefaultConfigurationLoaded(new JIRA5RestIssueIndexStructureBuilder(mockEsIntegrationComponent(), "index_name", "type_name", "http://issues-stg.jboss.org/", settings)); } private void assertDefaultConfigurationLoaded(JIRA5RestIssueIndexStructureBuilder tested) { Assert.assertEquals("river_name", tested.riverName); Assert.assertEquals("index_name", tested.indexName); Assert.assertEquals("type_name", tested.issueTypeName); Assert.assertEquals("source", tested.indexFieldForRiverName); Assert.assertEquals("project_key", tested.indexFieldForProjectKey); Assert.assertEquals("issue_key", tested.indexFieldForIssueKey); Assert.assertEquals("document_url", tested.indexFieldForJiraURL); Assert.assertEquals("http://issues-stg.jboss.org/browse/", tested.jiraIssueShowUrlBase); Assert.assertEquals(IssueCommentIndexingMode.EMBEDDED, tested.commentIndexingMode); Assert.assertEquals("comments", tested.indexFieldForComments); Assert.assertEquals("jira_issue_comment", tested.commentTypeName); Assert.assertEquals(IssueCommentIndexingMode.NONE, tested.changelogIndexingMode); Assert.assertEquals("changelogs", tested.indexFieldForChangelogs); Assert.assertEquals("jira_issue_change", tested.changelogTypeName); Assert.assertEquals(13, tested.fieldsConfig.size()); assertFieldConfiguration(tested.fieldsConfig, "project_name", "fields.project.name", null); assertFieldConfiguration(tested.fieldsConfig, "assignee", "fields.assignee", "user"); assertFieldConfiguration(tested.fieldsConfig, "fix_versions", "fields.fixVersions", "name"); Assert.assertEquals(2, tested.filtersConfig.size()); Assert.assertTrue(tested.filtersConfig.containsKey("user")); Assert.assertTrue(tested.filtersConfig.containsKey("name")); Map<String, String> userFilter = tested.filtersConfig.get("user"); Assert.assertEquals(3, userFilter.size()); Assert.assertEquals("username", userFilter.get("name")); Assert.assertEquals("email_address", userFilter.get("emailAddress")); Assert.assertEquals("display_name", userFilter.get("displayName")); Assert.assertEquals(6, tested.commentFieldsConfig.size()); assertFieldConfiguration(tested.commentFieldsConfig, "comment_id", "id", null); assertFieldConfiguration(tested.commentFieldsConfig, "comment_body", "body", null); assertFieldConfiguration(tested.commentFieldsConfig, "comment_author", "author", "user"); assertFieldConfiguration(tested.commentFieldsConfig, "comment_updater", "updateAuthor", "user"); assertFieldConfiguration(tested.commentFieldsConfig, "comment_updated", "updated", null); assertFieldConfiguration(tested.commentFieldsConfig, "comment_created", "created", null); Assert.assertEquals(4, tested.changelogFieldsConfig.size()); assertFieldConfiguration(tested.changelogFieldsConfig, "change_id", "id", null); assertFieldConfiguration(tested.changelogFieldsConfig, "change_items", "items", null); assertFieldConfiguration(tested.changelogFieldsConfig, "change_author", "author", "user"); assertFieldConfiguration(tested.changelogFieldsConfig, "change_created", "created", null); } private void assertFieldConfiguration(Map<String, Map<String, String>> fieldsConfig, String indexFieldName, String jiraFieldName, String filter) { Assert.assertTrue(fieldsConfig.containsKey(indexFieldName)); Map<String, String> field = fieldsConfig.get(indexFieldName); Assert.assertEquals(jiraFieldName, field.get(JIRA5RestIssueIndexStructureBuilder.CONFIG_FIELDS_JIRAFIELD)); Assert.assertEquals(filter, field.get(JIRA5RestIssueIndexStructureBuilder.CONFIG_FIELDS_VALUEFILTER)); } @Test public void addIssueDataPreprocessor() { JIRA5RestIssueIndexStructureBuilder tested = new JIRA5RestIssueIndexStructureBuilder(mockEsIntegrationComponent(), null, null, "http://issues-stg.jboss.org/", null); // case - not NPE tested.addIssueDataPreprocessor(null); // case - preprocessors adding tested.addIssueDataPreprocessor(mock(StructuredContentPreprocessor.class)); Assert.assertEquals(1, tested.issueDataPreprocessors.size()); tested.addIssueDataPreprocessor(mock(StructuredContentPreprocessor.class)); tested.addIssueDataPreprocessor(mock(StructuredContentPreprocessor.class)); tested.addIssueDataPreprocessor(mock(StructuredContentPreprocessor.class)); Assert.assertEquals(4, tested.issueDataPreprocessors.size()); } @Test public void preprocessIssueData() { JIRA5RestIssueIndexStructureBuilder tested = new JIRA5RestIssueIndexStructureBuilder(mockEsIntegrationComponent(), null, null, "http://issues-stg.jboss.org/", null); Map<String, Object> issue = null; // case - no NPE and change when no preprocessors defined and issue data are null Assert.assertNull(tested.preprocessIssueData("ORG", issue)); // case - no NPE and change when no preprocessors defined and issue data are notnull { issue = new HashMap<String, Object>(); issue.put(JIRA5RestIssueIndexStructureBuilder.JF_KEY, "ORG-1545"); Map<String, Object> ret = tested.preprocessIssueData("ORG", issue); Assert.assertEquals(issue, ret); Assert.assertEquals(1, ret.size()); Assert.assertEquals("ORG-1545", ret.get(JIRA5RestIssueIndexStructureBuilder.JF_KEY)); } // case - all preprocessors called { StructuredContentPreprocessor idp1 = mock(StructuredContentPreprocessor.class); StructuredContentPreprocessor idp2 = mock(StructuredContentPreprocessor.class); when(idp1.preprocessData(issue)).thenAnswer(new Answer<Map<String, Object>>() { @SuppressWarnings("unchecked") @Override public Map<String, Object> answer(InvocationOnMock invocation) throws Throwable { Map<String, Object> ret = (Map<String, Object>) invocation.getArguments()[0]; ret.put("idp1", "called"); return ret; } }); when(idp2.preprocessData(issue)).thenAnswer(new Answer<Map<String, Object>>() { @SuppressWarnings("unchecked") @Override public Map<String, Object> answer(InvocationOnMock invocation) throws Throwable { Map<String, Object> ret = (Map<String, Object>) invocation.getArguments()[0]; ret.put("idp2", "called"); return ret; } }); tested.addIssueDataPreprocessor(idp1); tested.addIssueDataPreprocessor(idp2); Map<String, Object> ret = tested.preprocessIssueData("ORG", issue); Assert.assertEquals(issue, ret); Assert.assertEquals(3, ret.size()); Assert.assertEquals("ORG-1545", ret.get(JIRA5RestIssueIndexStructureBuilder.JF_KEY)); Assert.assertEquals("called", ret.get("idp1")); Assert.assertEquals("called", ret.get("idp2")); } } @Test public void getRequiredJIRACallIssueFields() { JIRA5RestIssueIndexStructureBuilder tested = new JIRA5RestIssueIndexStructureBuilder(mockEsIntegrationComponent(), null, null, "http://issues-stg.jboss.org/", null); tested.commentIndexingMode = IssueCommentIndexingMode.NONE; tested.changelogIndexingMode = IssueCommentIndexingMode.NONE; tested.prepareJiraCallFieldSet(); // case - mandatory fields in set String s = tested.getRequiredJIRACallIssueFields(); List<String> fp = Utils.parseCsvString(s); Assert.assertEquals(13, fp.size()); Assert.assertTrue(fp.contains("updated")); Assert.assertTrue(fp.contains("project")); // assert other fields from default configuration Assert.assertTrue(fp.contains("issuetype")); Assert.assertTrue(fp.contains("summary")); Assert.assertTrue(fp.contains("status")); Assert.assertTrue(fp.contains("created")); Assert.assertTrue(fp.contains("resolutiondate")); Assert.assertTrue(fp.contains("description")); Assert.assertTrue(fp.contains("labels")); Assert.assertTrue(fp.contains("assignee")); Assert.assertTrue(fp.contains("reporter")); Assert.assertTrue(fp.contains("components")); Assert.assertTrue(fp.contains("fixVersions")); Assert.assertFalse(fp.contains("comment")); // assert expands Assert.assertEquals("", tested.getRequiredJIRACallIssueExpands()); // case - comments enabled tested.commentIndexingMode = IssueCommentIndexingMode.EMBEDDED; tested.prepareJiraCallFieldSet(); fp = Utils.parseCsvString(tested.getRequiredJIRACallIssueFields()); Assert.assertEquals(14, fp.size()); Assert.assertTrue(fp.contains("comment")); tested.commentIndexingMode = IssueCommentIndexingMode.CHILD; tested.prepareJiraCallFieldSet(); fp = Utils.parseCsvString(tested.getRequiredJIRACallIssueFields()); Assert.assertEquals(14, fp.size()); Assert.assertTrue(fp.contains("comment")); tested.commentIndexingMode = IssueCommentIndexingMode.STANDALONE; tested.prepareJiraCallFieldSet(); fp = Utils.parseCsvString(tested.getRequiredJIRACallIssueFields()); Assert.assertEquals(14, fp.size()); Assert.assertTrue(fp.contains("comment")); // case - changelog enabled tested.changelogIndexingMode = IssueCommentIndexingMode.EMBEDDED; tested.prepareJiraCallFieldSet(); Assert.assertEquals("changelog", tested.getRequiredJIRACallIssueExpands()); tested.changelogIndexingMode = IssueCommentIndexingMode.CHILD; tested.prepareJiraCallFieldSet(); Assert.assertEquals("changelog", tested.getRequiredJIRACallIssueExpands()); tested.changelogIndexingMode = IssueCommentIndexingMode.STANDALONE; tested.prepareJiraCallFieldSet(); Assert.assertEquals("changelog", tested.getRequiredJIRACallIssueExpands()); } @Test public void constructJIRAIssueShowUrlBase() { JIRA5RestIssueIndexStructureBuilder tested = new JIRA5RestIssueIndexStructureBuilder(); tested.constructJIRAIssueShowUrlBase("http://issues.jboss.org"); Assert.assertEquals("http://issues.jboss.org/browse/", tested.jiraIssueShowUrlBase); tested.constructJIRAIssueShowUrlBase("http://jira.jboss.org/"); Assert.assertEquals("http://jira.jboss.org/browse/", tested.jiraIssueShowUrlBase); } @Test public void prepareJIRAGUIUrl() { JIRA5RestIssueIndexStructureBuilder tested = new JIRA5RestIssueIndexStructureBuilder(); tested.constructJIRAIssueShowUrlBase("http://issues.jboss.org"); Assert.assertEquals("http://issues.jboss.org/browse/ORG-1250", tested.prepareJIRAGUIUrl("ORG-1250", null)); Assert .assertEquals( "http://issues.jboss.org/browse/ORG-1250?focusedCommentId=1234&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-1234", tested.prepareJIRAGUIUrl("ORG-1250", "1234")); } @Test public void buildSearchForIndexedDocumentsNotUpdatedAfter() throws IOException { JIRA5RestIssueIndexStructureBuilder tested = new JIRA5RestIssueIndexStructureBuilder(mockEsIntegrationComponent(), "search_index", "issue_type", "http://issues-stg.jboss.org/", null); tested.commentTypeName = "comment_type"; tested.changelogTypeName = "changelog_type"; tested.changelogIndexingMode = IssueCommentIndexingMode.NONE; // case - comments NONE { tested.commentIndexingMode = IssueCommentIndexingMode.NONE; SearchRequestBuilder srb = new SearchRequestBuilder(Mockito.mock(Client.class)); tested.buildSearchForIndexedDocumentsNotUpdatedAfter(srb, "ORG", DateTimeUtils.parseISODateTime("2012-09-06T12:22:19Z")); Assert.assertArrayEquals(new String[] { "issue_type" }, srb.request().types()); assertTrue( "Should equals: " + srb.toString(), toJsonNode(srb.toString()).equals( toJsonNode(TestUtils .readStringFromClasspathFile("/asserts/buildSearchForIndexedDocumentsNotUpdatedAfter.json")))); } // case - comments EMBEDDED { tested.commentIndexingMode = IssueCommentIndexingMode.EMBEDDED; SearchRequestBuilder srb = new SearchRequestBuilder(Mockito.mock(Client.class)); tested.buildSearchForIndexedDocumentsNotUpdatedAfter(srb, "ORG", DateTimeUtils.parseISODateTime("2012-09-06T12:22:19Z")); Assert.assertArrayEquals(new String[] { "issue_type" }, srb.request().types()); assertTrue( "Should equals", toJsonNode(srb.toString()).equals( toJsonNode(TestUtils .readStringFromClasspathFile("/asserts/buildSearchForIndexedDocumentsNotUpdatedAfter.json")))); } // case - comments CHILD, changelog EMBEDDED { tested.commentIndexingMode = IssueCommentIndexingMode.CHILD; tested.changelogIndexingMode = IssueCommentIndexingMode.EMBEDDED; SearchRequestBuilder srb = new SearchRequestBuilder(Mockito.mock(Client.class)); tested.buildSearchForIndexedDocumentsNotUpdatedAfter(srb, "ORG", DateTimeUtils.parseISODateTime("2012-09-06T12:22:19Z")); Assert.assertArrayEquals(new String[] { "issue_type", "comment_type" }, srb.request().types()); assertTrue( "Should equals", toJsonNode(srb.toString()).equals( toJsonNode(TestUtils .readStringFromClasspathFile("/asserts/buildSearchForIndexedDocumentsNotUpdatedAfter.json")))); } // case - comments STANDALONE, changelog CHILD { tested.commentIndexingMode = IssueCommentIndexingMode.STANDALONE; tested.changelogIndexingMode = IssueCommentIndexingMode.CHILD; SearchRequestBuilder srb = new SearchRequestBuilder(Mockito.mock(Client.class)); tested.buildSearchForIndexedDocumentsNotUpdatedAfter(srb, "ORG", DateTimeUtils.parseISODateTime("2012-09-06T12:22:19Z")); Assert.assertArrayEquals(new String[] { "issue_type", "comment_type", "changelog_type" }, srb.request().types()); assertTrue( "Should equals", toJsonNode(srb.toString()).equals( toJsonNode(TestUtils .readStringFromClasspathFile("/asserts/buildSearchForIndexedDocumentsNotUpdatedAfter.json")))); } // case - comments NONE, changelog STANDALONE { tested.commentIndexingMode = IssueCommentIndexingMode.NONE; tested.changelogIndexingMode = IssueCommentIndexingMode.STANDALONE; SearchRequestBuilder srb = new SearchRequestBuilder(Mockito.mock(Client.class)); tested.buildSearchForIndexedDocumentsNotUpdatedAfter(srb, "ORG", DateTimeUtils.parseISODateTime("2012-09-06T12:22:19Z")); Assert.assertArrayEquals(new String[] { "issue_type", "changelog_type" }, srb.request().types()); assertTrue( "Should equals", toJsonNode(srb.toString()).equals( toJsonNode(TestUtils .readStringFromClasspathFile("/asserts/buildSearchForIndexedDocumentsNotUpdatedAfter.json")))); } } @Test public void prepareIssueIndexedDocument() throws Exception { JIRA5RestIssueIndexStructureBuilder tested = new JIRA5RestIssueIndexStructureBuilder(mockEsIntegrationComponent(), "search_index", "issue_type", "http://issues-stg.jboss.org/", null); // case - no comments nor changelogs { tested.commentIndexingMode = IssueCommentIndexingMode.NONE; tested.changelogIndexingMode = IssueCommentIndexingMode.NONE; String res = tested.prepareIssueIndexedDocument("ORG", TestUtils.readJiraJsonIssueDataFromClasspathFile("ORG-1501")).string(); assertTrue( "Should equals", toJsonNode(res).equals( toJsonNode(TestUtils .readStringFromClasspathFile("/asserts/prepareIssueIndexedDocument_ORG-1501_NOCOMMENT.json")))); } // case - comments and changelogs as CHILD so not in this document { tested.commentIndexingMode = IssueCommentIndexingMode.CHILD; tested.changelogIndexingMode = IssueCommentIndexingMode.CHILD; String res = tested.prepareIssueIndexedDocument("ORG", TestUtils.readJiraJsonIssueDataFromClasspathFile("ORG-1501")).string(); assertTrue( "Should equals", toJsonNode(res).equals( toJsonNode(TestUtils .readStringFromClasspathFile("/asserts/prepareIssueIndexedDocument_ORG-1501_NOCOMMENT.json")))); } // case - comments and changelog as STANDALONE so not in this document { tested.commentIndexingMode = IssueCommentIndexingMode.STANDALONE; tested.changelogIndexingMode = IssueCommentIndexingMode.STANDALONE; String res = tested.prepareIssueIndexedDocument("ORG", TestUtils.readJiraJsonIssueDataFromClasspathFile("ORG-1501")).string(); assertTrue( "Should equals", toJsonNode(res).equals( toJsonNode(TestUtils .readStringFromClasspathFile("/asserts/prepareIssueIndexedDocument_ORG-1501_NOCOMMENT.json")))); } // case - comments as EMBEDDED so present in this document { tested.commentIndexingMode = IssueCommentIndexingMode.EMBEDDED; tested.changelogIndexingMode = IssueCommentIndexingMode.NONE; String res = tested.prepareIssueIndexedDocument("ORG", TestUtils.readJiraJsonIssueDataFromClasspathFile("ORG-1501")).string(); assertTrue( "Should equals", toJsonNode(res).equals( toJsonNode(TestUtils .readStringFromClasspathFile("/asserts/prepareIssueIndexedDocument_ORG-1501_COMMENTS.json")))); } // case - changelog as EMBEDDED so present in this document { tested.commentIndexingMode = IssueCommentIndexingMode.NONE; tested.changelogIndexingMode = IssueCommentIndexingMode.EMBEDDED; String res = tested.prepareIssueIndexedDocument("ORG", TestUtils.readJiraJsonIssueDataFromClasspathFile("ORG-1501")).string(); assertTrue( "Should equals", toJsonNode(res).equals( toJsonNode(TestUtils .readStringFromClasspathFile("/asserts/prepareIssueIndexedDocument_ORG-1501_CHANGELOGS.json")))); } // case - comments and changelog as EMBEDDED but not in source so no present in this document { tested.commentIndexingMode = IssueCommentIndexingMode.EMBEDDED; tested.changelogIndexingMode = IssueCommentIndexingMode.EMBEDDED; String res = tested.prepareIssueIndexedDocument("ORG", TestUtils.readJiraJsonIssueDataFromClasspathFile("ORG-1513")).string(); assertTrue( "Should equals", toJsonNode(res).equals( toJsonNode(TestUtils .readStringFromClasspathFile("/asserts/prepareIssueIndexedDocument_ORG-1513_NOCOMMENTS.json")))); } } @Test public void prepareCommentIndexedDocument() throws Exception { JIRA5RestIssueIndexStructureBuilder tested = new JIRA5RestIssueIndexStructureBuilder(mockEsIntegrationComponent(), "search_index", "issue_type", "http://issues-stg.jboss.org/", null); Map<String, Object> issue = TestUtils.readJiraJsonIssueDataFromClasspathFile("ORG-1501"); List<Map<String, Object>> comments = tested.extractIssueComments(issue); String res = tested.prepareCommentIndexedDocument("ORG", "ORG-1501", comments.get(0)).string(); assertTrue( "Should equals", toJsonNode(res) .equals( toJsonNode(TestUtils .readStringFromClasspathFile("/asserts/prepareCommentIndexedDocument_ORG-1501_1.json")))); } @Test public void prepareChangelogIndexedDocument() throws Exception { JIRA5RestIssueIndexStructureBuilder tested = new JIRA5RestIssueIndexStructureBuilder(mockEsIntegrationComponent(), "search_index", "issue_type", "http://issues-stg.jboss.org/", null); Map<String, Object> issue = TestUtils.readJiraJsonIssueDataFromClasspathFile("ORG-1501"); List<Map<String, Object>> changelogs = tested.extractIssueChangelogs(issue); String res = tested.prepareChangelogIndexedDocument("ORG", "ORG-1501", changelogs.get(0)).string(); System.out.print(res); assertTrue( "Should equals", toJsonNode(res) .equals( toJsonNode(TestUtils .readStringFromClasspathFile("/asserts/prepareChagelogIndexedDocument_ORG-1501_1.json")))); } @Test public void prepareIssueDocumentId() { JIRA5RestIssueIndexStructureBuilder tested = new JIRA5RestIssueIndexStructureBuilder(mockEsIntegrationComponent(), "search_index", "issue_type", "http://issues-stg.jboss.org/", null); tested.jiraFieldForIssueDocumentId = null; Map<String, Object> issue = new HashMap<String, Object>(); issue.put("key", "ORG-15"); issue.put("key2", "ORG-16"); Utils.putValueIntoMapOfMaps(issue, "key3.value", "ORG-17"); // case - default key used if jiraFieldForIssueDocumentId is not configured Assert.assertEquals("ORG-15", tested.prepareIssueDocumentId(issue)); // case - default key used if jiraFieldForIssueDocumentId is configured but value is not provided tested.jiraFieldForIssueDocumentId = "key_unknown"; Assert.assertEquals("ORG-15", tested.prepareIssueDocumentId(issue)); // case - simple notation on jiraFieldForIssueDocumentId tested.jiraFieldForIssueDocumentId = "key2"; Assert.assertEquals("ORG-16", tested.prepareIssueDocumentId(issue)); // case - dot notation on jiraFieldForIssueDocumentId tested.jiraFieldForIssueDocumentId = "key3.value"; Assert.assertEquals("ORG-17", tested.prepareIssueDocumentId(issue)); } @SuppressWarnings("unchecked") @Test public void indexIssue() throws Exception { JIRA5RestIssueIndexStructureBuilder tested = new JIRA5RestIssueIndexStructureBuilder(mockEsIntegrationComponent(), "search_index", "issue_type", "http://issues-stg.jboss.org/", null); Client client = Mockito.mock(Client.class); // case - comments NONE { BulkRequestBuilder esBulk = new BulkRequestBuilder(client); tested.commentIndexingMode = IssueCommentIndexingMode.NONE; tested.changelogIndexingMode = IssueCommentIndexingMode.NONE; tested.indexIssue(esBulk, "ORG-1501", TestUtils.readJiraJsonIssueDataFromClasspathFile("ORG-1501")); Assert.assertEquals(1, esBulk.request().numberOfActions()); } // case - comments and changelog EMBEDDED { BulkRequestBuilder esBulk = new BulkRequestBuilder(client); tested.commentIndexingMode = IssueCommentIndexingMode.EMBEDDED; tested.changelogIndexingMode = IssueCommentIndexingMode.EMBEDDED; tested.indexIssue(esBulk, "ORG-1501", TestUtils.readJiraJsonIssueDataFromClasspathFile("ORG-1501")); Assert.assertEquals(1, esBulk.request().numberOfActions()); } // case - comments CHILD { BulkRequestBuilder esBulk = new BulkRequestBuilder(client); tested.commentIndexingMode = IssueCommentIndexingMode.CHILD; tested.changelogIndexingMode = IssueCommentIndexingMode.NONE; tested.indexIssue(esBulk, "ORG-1501", TestUtils.readJiraJsonIssueDataFromClasspathFile("ORG-1501")); Assert.assertEquals(3, esBulk.request().numberOfActions()); } // case - changelog CHILD { BulkRequestBuilder esBulk = new BulkRequestBuilder(client); tested.commentIndexingMode = IssueCommentIndexingMode.NONE; tested.changelogIndexingMode = IssueCommentIndexingMode.CHILD; tested.indexIssue(esBulk, "ORG-1501", TestUtils.readJiraJsonIssueDataFromClasspathFile("ORG-1501")); Assert.assertEquals(3, esBulk.request().numberOfActions()); } // case - both comments and changelog STANDALONE with comments in issue { BulkRequestBuilder esBulk = new BulkRequestBuilder(client); tested.commentIndexingMode = IssueCommentIndexingMode.STANDALONE; tested.changelogIndexingMode = IssueCommentIndexingMode.STANDALONE; tested.indexIssue(esBulk, "ORG-1501", TestUtils.readJiraJsonIssueDataFromClasspathFile("ORG-1501")); Assert.assertEquals(5, esBulk.request().numberOfActions()); } // case - comments and changelogs STANDALONE without comments in issue { BulkRequestBuilder esBulk = new BulkRequestBuilder(client); tested.commentIndexingMode = IssueCommentIndexingMode.STANDALONE; tested.changelogIndexingMode = IssueCommentIndexingMode.STANDALONE; tested.indexIssue(esBulk, "ORG-15013", TestUtils.readJiraJsonIssueDataFromClasspathFile("ORG-15013")); Assert.assertEquals(1, esBulk.request().numberOfActions()); } // case - preprocessor called { BulkRequestBuilder esBulk = new BulkRequestBuilder(client); tested.commentIndexingMode = IssueCommentIndexingMode.STANDALONE; StructuredContentPreprocessor idp1 = mock(StructuredContentPreprocessor.class); when(idp1.preprocessData(Mockito.anyMap())).thenAnswer(new Answer<Map<String, Object>>() { @Override public Map<String, Object> answer(InvocationOnMock invocation) throws Throwable { return (Map<String, Object>) invocation.getArguments()[0]; } }); tested.addIssueDataPreprocessor(idp1); tested.indexIssue(esBulk, "ORG-15013", TestUtils.readJiraJsonIssueDataFromClasspathFile("ORG-15013")); Assert.assertEquals(1, esBulk.request().numberOfActions()); verify(idp1, times(1)).preprocessData(Mockito.anyMap()); } } @Test public void addValueToTheIndex() throws Exception { JIRA5RestIssueIndexStructureBuilder tested = new JIRA5RestIssueIndexStructureBuilder(mockEsIntegrationComponent(), null, null, "http://issues-stg.jboss.org/", null); XContentGenerator xContentGeneratorMock = mock(XContentGenerator.class); XContentBuilder out = XContentBuilder.builder(preparexContentMock(xContentGeneratorMock)); // case - no exception if values parameter is null tested.addValueToTheIndex(out, "testfield", "testpath", null, (Map<String, String>) null); verify(xContentGeneratorMock, times(0)).writeFieldName(Mockito.anyString()); // case - no exception if value is not found reset(xContentGeneratorMock); Map<String, Object> values = new HashMap<String, Object>(); tested.addValueToTheIndex(out, "testfield", "testpath", values, (Map<String, String>) null); verify(xContentGeneratorMock, times(0)).writeFieldName(Mockito.anyString()); // case - get correctly value from first level of nesting, no filtering on null filter reset(xContentGeneratorMock); values.put("myKey", "myValue"); values.put("myKey2", "myValue2"); tested.addValueToTheIndex(out, "testfield", "myKey2", values, (Map<String, String>) null); verify(xContentGeneratorMock, times(1)).writeFieldName(Mockito.anyString()); verify(xContentGeneratorMock).writeFieldName("testfield"); verify(xContentGeneratorMock).writeString("myValue2"); Mockito.verifyNoMoreInteractions(xContentGeneratorMock); // case - get correctly value from deeper level of nesting, no filtering with empty filter reset(xContentGeneratorMock); values.put("myKey", "myValue"); values.put("myKey2", "myValue2"); Map<String, Object> parent3 = new HashMap<String, Object>(); values.put("parent3", parent3); parent3.put("myKey3", "myValue3"); Map<String, String> filter = new HashMap<String, String>(); tested.addValueToTheIndex(out, "testfield3", "parent3.myKey3", values, filter); verify(xContentGeneratorMock, times(1)).writeFieldName(Mockito.anyString()); verify(xContentGeneratorMock).writeFieldName("testfield3"); verify(xContentGeneratorMock).writeString("myValue3"); Mockito.verifyNoMoreInteractions(xContentGeneratorMock); // case - no error when filter on filtering unsupported value reset(xContentGeneratorMock); values.clear(); values.put("myKey", "myValue"); values.put("myKey2", "myValue2"); filter.put("myKeyFilter", "myKeyFilter"); tested.addValueToTheIndex(out, "testfield", "myKey2", values, filter); verify(xContentGeneratorMock).writeFieldName("testfield"); verify(xContentGeneratorMock).writeString("myValue2"); Mockito.verifyNoMoreInteractions(xContentGeneratorMock); // case - get correctly value from first level of nesting, filtering on Map reset(xContentGeneratorMock); values.clear(); values.put("myKey", "myValue"); values.put("myKey2", "myValue2"); parent3 = new HashMap<String, Object>(); values.put("parent3", parent3); parent3.put("myKey3", "myValue3"); parent3.put("myKey4", "myValue4"); filter.clear(); filter.put("myKey3", "myKey1"); tested.addValueToTheIndex(out, "testfield", "parent3", values, filter); verify(xContentGeneratorMock).writeFieldName("testfield"); verify(xContentGeneratorMock).writeStartObject(); verify(xContentGeneratorMock).writeFieldName("myKey1"); verify(xContentGeneratorMock).writeString("myValue3"); verify(xContentGeneratorMock).writeEndObject(); Mockito.verifyNoMoreInteractions(xContentGeneratorMock); // case - filtering on List of Maps reset(xContentGeneratorMock); values.clear(); values.put("myKey", "myValue"); values.put("myKey2", "myValue2"); List<Object> parent3list = new ArrayList<Object>(); values.put("parent3", parent3list); Map<String, Object> obj31 = new HashMap<String, Object>(); parent3list.add(obj31); obj31.put("myKey3", "myValue31"); obj31.put("myKey4", "myValue41"); Map<String, Object> obj32 = new HashMap<String, Object>(); parent3list.add(obj32); obj32.put("myKey3", "myValue32"); obj32.put("myKey4", "myValue42"); filter.clear(); filter.put("myKey3", "myKey3"); tested.addValueToTheIndex(out, "testfield", "parent3", values, filter); verify(xContentGeneratorMock).writeFieldName("testfield"); verify(xContentGeneratorMock, times(1)).writeStartArray(); verify(xContentGeneratorMock, times(2)).writeStartObject(); verify(xContentGeneratorMock, times(2)).writeFieldName("myKey3"); verify(xContentGeneratorMock).writeString("myValue31"); verify(xContentGeneratorMock).writeString("myValue32"); verify(xContentGeneratorMock, times(2)).writeEndObject(); verify(xContentGeneratorMock, times(1)).writeEndArray(); Mockito.verifyNoMoreInteractions(xContentGeneratorMock); } @Test public void addValueToTheIndexField() throws Exception { JIRA5RestIssueIndexStructureBuilder tested = new JIRA5RestIssueIndexStructureBuilder(mockEsIntegrationComponent(), null, null, "http://issues-stg.jboss.org/", null); XContentGenerator xContentGeneratorMock = mock(XContentGenerator.class); XContentBuilder out = XContentBuilder.builder(preparexContentMock(xContentGeneratorMock)); // case - string field tested.addValueToTheIndexField(out, "test", "testvalue"); verify(xContentGeneratorMock).writeFieldName("test"); verify(xContentGeneratorMock).writeString("testvalue"); // case - integer field reset(xContentGeneratorMock); tested.addValueToTheIndexField(out, "testint", new Integer(10)); verify(xContentGeneratorMock).writeFieldName("testint"); verify(xContentGeneratorMock).writeNumber(10); // case - nothing added if value is null reset(xContentGeneratorMock); tested.addValueToTheIndexField(out, "testnull", null); Mockito.verifyZeroInteractions(xContentGeneratorMock); } @Test public void getJiraCallFieldName() { JIRA5RestIssueIndexStructureBuilder tested = new JIRA5RestIssueIndexStructureBuilder(mockEsIntegrationComponent(), null, null, "http://issues-stg.jboss.org/", null); Assert.assertNull(tested.getJiraCallFieldName(null)); Assert.assertNull(tested.getJiraCallFieldName(" ")); Assert.assertNull(tested.getJiraCallFieldName("self")); Assert.assertNull(tested.getJiraCallFieldName("key")); Assert.assertNull(tested.getJiraCallFieldName("fields")); Assert.assertNull(tested.getJiraCallFieldName("fields.")); Assert.assertNull(tested.getJiraCallFieldName("fields. ")); Assert.assertNull(tested.getJiraCallFieldName("fields..")); Assert.assertNull(tested.getJiraCallFieldName("fields...")); Assert.assertNull(tested.getJiraCallFieldName("fields..something")); Assert.assertEquals("summary", tested.getJiraCallFieldName("fields.summary")); Assert.assertEquals("summary", tested.getJiraCallFieldName("fields.summary.")); Assert.assertEquals("summary", tested.getJiraCallFieldName("fields.summary.name")); Assert.assertEquals("summary", tested.getJiraCallFieldName(" fields.summary ")); Assert.assertEquals("summary", tested.getJiraCallFieldName(" fields.summary. ")); Assert.assertEquals("summary", tested.getJiraCallFieldName(" fields.summary.name ")); } /** * Prepare {@link XContent} mock to be used for {@link XContentBuilder} test instance creation. * * @param xContentGeneratorMock to be returned from XContent mock * @return XContent mock instance * @throws IOException */ protected XContent preparexContentMock(XContentGenerator xContentGeneratorMock) throws IOException { XContent xContentMock = mock(XContent.class); when(xContentMock.createGenerator(Mockito.any(OutputStream.class))).thenReturn(xContentGeneratorMock); return xContentMock; } protected IESIntegration mockEsIntegrationComponent() { IESIntegration esIntegrationMock = mock(IESIntegration.class); Mockito.when(esIntegrationMock.createLogger(Mockito.any(Class.class))).thenReturn( ESLoggerFactory.getLogger(JIRAProjectIndexerCoordinator.class.getName())); RiverName riverName = new RiverName("jira", "river_name"); Mockito.when(esIntegrationMock.riverName()).thenReturn(riverName); return esIntegrationMock; } }