/* * 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.searchisko.api.service; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.elasticsearch.action.search.SearchRequestBuilder; import org.elasticsearch.client.Client; import org.elasticsearch.common.joda.time.DateTime; import org.elasticsearch.common.joda.time.DateTimeZone; import org.elasticsearch.common.settings.SettingsException; import org.elasticsearch.index.query.FilterBuilder; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.sort.SortOrder; import org.json.JSONException; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.searchisko.api.model.PastIntervalValue; import org.searchisko.api.model.QuerySettings; import org.searchisko.api.model.QuerySettings.Filters; import org.searchisko.api.model.SortByValue; import org.searchisko.api.rest.exception.BadFieldException; import org.searchisko.api.rest.exception.NotAuthorizedException; import org.searchisko.api.security.Role; import org.searchisko.api.testtools.TestUtils; /** * Unit test for {@link SearchService} * * @author Vlastimil Elias (velias at redhat dot com) * @author Lukas Vlcek */ public class SearchServiceTest extends SearchServiceTestBase { /** * https://github.com/searchisko/searchisko/issues/79 */ @Test public void missingFilterFieldsConfigDoesNotThrowNPE() throws ReflectiveOperationException { ConfigService configService = Mockito.mock(ConfigService.class); Mockito.when(configService.get(ConfigService.CFGNAME_SEARCH_FULLTEXT_FILTER_FIELDS)).thenReturn(null); SearchService tested = getTested(configService); Filters filters = new Filters(); filters.acknowledgeUrlFilterCandidate("test", "value"); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); } @Test public void getSearchResponseAdditionalFields() throws ReflectiveOperationException { ConfigService configService = mockConfigurationService(); SearchService tested = getTested(configService); try { tested.getIntervalValuesForDateHistogramAggregations(null); Assert.fail("NullPointerException expected"); } catch (NullPointerException e) { // OK } QuerySettings qs = new QuerySettings(); Map<String, String> ret = tested.getIntervalValuesForDateHistogramAggregations(qs); Assert.assertTrue(ret.isEmpty()); qs.addAggregation("activity_dates_histogram"); qs.getFiltersInit().acknowledgeUrlFilterCandidate("activity_date_interval", PastIntervalValue.QUARTER.toString()); tested.parsedFilterConfigService.prepareFiltersForRequest(qs.getFilters()); ret = tested.getIntervalValuesForDateHistogramAggregations(qs); Assert.assertEquals(1, ret.size()); Assert.assertEquals("week", ret.get("activity_dates_histogram_interval")); } @Test public void prepareIndexNamesCacheKey() { Assert.assertEquals("_all||false", SearchService.prepareIndexNamesCacheKey(null, false)); Assert.assertEquals("_all||true", SearchService.prepareIndexNamesCacheKey(null, true)); Set<String> sysTypesRequested = new HashSet<>(); Assert.assertEquals("_all||false", SearchService.prepareIndexNamesCacheKey(sysTypesRequested, false)); Assert.assertEquals("_all||true", SearchService.prepareIndexNamesCacheKey(sysTypesRequested, true)); sysTypesRequested.add("aaaa"); Assert.assertEquals("aaaa||true", SearchService.prepareIndexNamesCacheKey(sysTypesRequested, true)); Assert.assertEquals("aaaa||false", SearchService.prepareIndexNamesCacheKey(sysTypesRequested, false)); sysTypesRequested.add("bb"); Assert.assertEquals("aaaa|bb||true", SearchService.prepareIndexNamesCacheKey(sysTypesRequested, true)); Assert.assertEquals("aaaa|bb||false", SearchService.prepareIndexNamesCacheKey(sysTypesRequested, false)); // check ordering sysTypesRequested = new HashSet<>(); sysTypesRequested.add("bb"); sysTypesRequested.add("zzzzz"); sysTypesRequested.add("aaaa"); Assert.assertEquals("aaaa|bb|zzzzz||true", SearchService.prepareIndexNamesCacheKey(sysTypesRequested, true)); Assert.assertEquals("aaaa|bb|zzzzz||false", SearchService.prepareIndexNamesCacheKey(sysTypesRequested, false)); } @Test public void handleCommonFiltersSettings_moreFilters() throws IOException, JSONException, ReflectiveOperationException { ConfigService configService = mockConfigurationService(); SearchService tested = getTested(configService); // case - no filters object exists { tested.parsedFilterConfigService.prepareFiltersForRequest(null); Assert.assertEquals(0, tested.parsedFilterConfigService.getSearchFiltersForRequest().size()); } QuerySettings querySettings = new QuerySettings(); tested.parsedFilterConfigService.prepareFiltersForRequest(querySettings.getFilters()); // case - empty filters object exists { QueryBuilder qb = QueryBuilders.matchAllQuery(); QueryBuilder qbRes = tested.applyCommonFilters(tested.parsedFilterConfigService.getSearchFiltersForRequest(), qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_match_all.json", qbRes.toString()); } Filters filters = new Filters(); querySettings.setFilters(filters); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); // case - empty filters object { QueryBuilder qb = QueryBuilders.matchAllQuery(); QueryBuilder qbRes = tested.applyCommonFilters(tested.parsedFilterConfigService.getSearchFiltersForRequest(), qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_match_all.json", qbRes.toString()); } // case - all filters used { filters.acknowledgeUrlFilterCandidate("sys_type", "mySysType", "mySysType2"); filters.acknowledgeUrlFilterCandidate("content_provider", "my_content_provider"); filters.acknowledgeUrlFilterCandidate("tag", "tag1", "tag2"); filters.acknowledgeUrlFilterCandidate("project", "pr1", "pr2"); filters.acknowledgeUrlFilterCandidate("contributor", "John Doe <john@doe.com>", "Dan Boo <boo@boo.net>"); // activityDateInterval not tested here because variable, see separate test filters.acknowledgeUrlFilterCandidate("activity_date_from", new DateTime(1359232356456L).toString(DATE_TIME_FORMATTER_UTC)); filters.acknowledgeUrlFilterCandidate("activity_date_to", new DateTime(1359232366456L).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); QueryBuilder qb = QueryBuilders.matchAllQuery(); QueryBuilder qbRes = tested.applyCommonFilters(tested.parsedFilterConfigService.getSearchFiltersForRequest(), qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_filters_moreFilters.json", qbRes.toString()); } } @Test public void handleCommonFiltersSettings_ActivityDateInterval() throws IOException, JSONException, ReflectiveOperationException { ConfigService configService = mockConfigurationService(); SearchService tested = getTested(configService); QuerySettings querySettings = new QuerySettings(); Filters filters = new Filters(); querySettings.setFilters(filters); filters.acknowledgeUrlFilterCandidate("activity_date_interval", PastIntervalValue.TEST.toString()); // set date_from and date_to to some values to test this is ignored if interval is used filters.acknowledgeUrlFilterCandidate("activity_date_to", new DateTime(1359232366456L).toString(DATE_TIME_FORMATTER_UTC)); filters.acknowledgeUrlFilterCandidate("activity_date_from", new DateTime(1359232356456L).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); { QueryBuilder qb = QueryBuilders.matchAllQuery(); QueryBuilder qbRes = tested.applyCommonFilters(tested.parsedFilterConfigService.getSearchFiltersForRequest(), qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_filters_activityDateInterval.json", qbRes.toString()); } } @Test public void handleCommonFiltersSettings_ActivityDateFromTo() throws IOException, JSONException, ReflectiveOperationException { ConfigService configService = mockConfigurationService(); SearchService tested = getTested(configService); QuerySettings querySettings = new QuerySettings(); Filters filters = new Filters(); querySettings.setFilters(filters); // case - only from filters.acknowledgeUrlFilterCandidate("activity_date_from", new DateTime(1359232356456L).toString(DATE_TIME_FORMATTER_UTC)); filters.acknowledgeUrlFilterCandidate("activity_date_to"); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); { QueryBuilder qb = QueryBuilders.matchAllQuery(); QueryBuilder qbRes = tested.applyCommonFilters(tested.parsedFilterConfigService.getSearchFiltersForRequest(), qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_filters_activityDateFrom.json", qbRes.toString()); } // case - only to filters.acknowledgeUrlFilterCandidate("activity_date_from"); filters.acknowledgeUrlFilterCandidate("activity_date_to", new DateTime(1359232366456L).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); { QueryBuilder qb = QueryBuilders.matchAllQuery(); QueryBuilder qbRes = tested.applyCommonFilters(tested.parsedFilterConfigService.getSearchFiltersForRequest(), qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_filters_activityDateTo.json", qbRes.toString()); } // case - both bounds filters.acknowledgeUrlFilterCandidate("activity_date_from", new DateTime(1359232356456L).toString(DATE_TIME_FORMATTER_UTC)); filters.acknowledgeUrlFilterCandidate("activity_date_to", new DateTime(1359232366456L).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); { QueryBuilder qb = QueryBuilders.matchAllQuery(); QueryBuilder qbRes = tested.applyCommonFilters(tested.parsedFilterConfigService.getSearchFiltersForRequest(), qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_filters_activityDateFromTo.json", qbRes.toString()); } } @Test public void handleCommonFiltersSettings_projects() throws IOException, JSONException, ReflectiveOperationException { ConfigService configService = mockConfigurationService(); SearchService tested = getTested(configService); QuerySettings querySettings = new QuerySettings(); Filters filters = new Filters(); querySettings.setFilters(filters); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); // case - list of projects is null { QueryBuilder qb = QueryBuilders.matchAllQuery(); QueryBuilder qbRes = tested.applyCommonFilters(tested.parsedFilterConfigService.getSearchFiltersForRequest(), qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_match_all.json", qbRes.toString()); } // case - list of projects is empty { filters.acknowledgeUrlFilterCandidate("project", Collections.<String> emptyList()); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); QueryBuilder qb = QueryBuilders.matchAllQuery(); QueryBuilder qbRes = tested.applyCommonFilters(tested.parsedFilterConfigService.getSearchFiltersForRequest(), qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_match_all.json", qbRes.toString()); } // case - one project { filters.acknowledgeUrlFilterCandidate("project", "pr1"); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); QueryBuilder qb = QueryBuilders.matchAllQuery(); QueryBuilder qbRes = tested.applyCommonFilters(tested.parsedFilterConfigService.getSearchFiltersForRequest(), qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_filters_projects_one.json", qbRes.toString()); } // case - more projects { filters.acknowledgeUrlFilterCandidate("project", "pr1", "pr2", "pr3", "pr4"); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); QueryBuilder qb = QueryBuilders.matchAllQuery(); QueryBuilder qbRes = tested.applyCommonFilters(tested.parsedFilterConfigService.getSearchFiltersForRequest(), qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_filters_projects_more.json", qbRes.toString()); } } @Test public void handleCommonFiltersSettings_tags() throws IOException, JSONException, ReflectiveOperationException { ConfigService configService = mockConfigurationService(); SearchService tested = getTested(configService); QuerySettings querySettings = new QuerySettings(); Filters filters = new Filters(); querySettings.setFilters(filters); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); // case - list of tags is null { QueryBuilder qb = QueryBuilders.matchAllQuery(); QueryBuilder qbRes = tested.applyCommonFilters(tested.parsedFilterConfigService.getSearchFiltersForRequest(), qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_match_all.json", qbRes.toString()); } // case - list of tags is empty { filters.acknowledgeUrlFilterCandidate("tag", Collections.<String> emptyList()); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); QueryBuilder qb = QueryBuilders.matchAllQuery(); QueryBuilder qbRes = tested.applyCommonFilters(tested.parsedFilterConfigService.getSearchFiltersForRequest(), qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_match_all.json", qbRes.toString()); } // case - one tag { filters.acknowledgeUrlFilterCandidate("tag", "tg1"); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); QueryBuilder qb = QueryBuilders.matchAllQuery(); QueryBuilder qbRes = tested.applyCommonFilters(tested.parsedFilterConfigService.getSearchFiltersForRequest(), qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_filters_tags_one.json", qbRes.toString()); } // case - more tags { filters.acknowledgeUrlFilterCandidate("tag", "tg1", "tg2", "tg3", "tg4"); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); QueryBuilder qb = QueryBuilders.matchAllQuery(); QueryBuilder qbRes = tested.applyCommonFilters(tested.parsedFilterConfigService.getSearchFiltersForRequest(), qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_filters_tags_more.json", qbRes.toString()); } // case - all UPPER CASED chars in tags values are converted to LOWER CASED { filters.acknowledgeUrlFilterCandidate("tag", "TG1", "Tg2", "tG3", "tg4"); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); QueryBuilder qb = QueryBuilders.matchAllQuery(); QueryBuilder qbRes = tested.applyCommonFilters(tested.parsedFilterConfigService.getSearchFiltersForRequest(), qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_filters_tags_more.json", qbRes.toString()); } } @Test public void handleCommonFiltersSettings_contributors() throws IOException, JSONException, ReflectiveOperationException { ConfigService configService = mockConfigurationService(); SearchService tested = getTested(configService); QuerySettings querySettings = new QuerySettings(); Filters filters = new Filters(); querySettings.setFilters(filters); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); // case - list of contributors is null { QueryBuilder qb = QueryBuilders.matchAllQuery(); QueryBuilder qbRes = tested.applyCommonFilters(tested.parsedFilterConfigService.getSearchFiltersForRequest(), qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_match_all.json", qbRes.toString()); } // case - list of contributors is empty { filters.acknowledgeUrlFilterCandidate("contributor", Collections.<String> emptyList()); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); QueryBuilder qb = QueryBuilders.matchAllQuery(); QueryBuilder qbRes = tested.applyCommonFilters(tested.parsedFilterConfigService.getSearchFiltersForRequest(), qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_match_all.json", qbRes.toString()); } // case - one contributor { filters.acknowledgeUrlFilterCandidate("contributor", "tg1"); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); QueryBuilder qb = QueryBuilders.matchAllQuery(); QueryBuilder qbRes = tested.applyCommonFilters(tested.parsedFilterConfigService.getSearchFiltersForRequest(), qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_filters_contributors_one.json", qbRes.toString()); } // case - more contributors { filters.acknowledgeUrlFilterCandidate("contributor", "tg1", "tg2", "tg3", "tg4"); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); QueryBuilder qb = QueryBuilders.matchAllQuery(); QueryBuilder qbRes = tested.applyCommonFilters(tested.parsedFilterConfigService.getSearchFiltersForRequest(), qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_filters_contributors_more.json", qbRes.toString()); } } @Test public void handleFulltextSearchSettings() throws IOException, JSONException { ConfigService configService = Mockito.mock(ConfigService.class); SearchService tested = getTested(configService); // case - NPE when no settings passed in try { tested.prepareQueryBuilder(null); Assert.fail("NullPointerException expected"); } catch (NullPointerException e) { // OK } QuerySettings querySettings = new QuerySettings(); // case - no fulltext parameter requested { querySettings.setQuery(null); QueryBuilder qbRes = tested.prepareQueryBuilder(querySettings); TestUtils.assertJsonContentFromClasspathFile("/search/query_match_all.json", qbRes.toString()); } // case - fulltext parameter requested, no fulltext fields configured { Mockito.reset(tested.configService); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_FULLTEXT_QUERY_FIELDS)).thenReturn(null); querySettings.setQuery("my query string"); QueryBuilder qbRes = tested.prepareQueryBuilder(querySettings); TestUtils.assertJsonContentFromClasspathFile("/search/query_fulltext.json", qbRes.toString()); Mockito.verify(tested.configService).get(ConfigService.CFGNAME_SEARCH_FULLTEXT_QUERY_FIELDS); Mockito.verifyNoMoreInteractions(tested.configService); } // case - fulltext parameter requested, some fulltext fields configured (one with invalid format) { Mockito.reset(tested.configService); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_FULLTEXT_QUERY_FIELDS)).thenReturn( TestUtils.loadJSONFromClasspathFile("/search/search_fulltext_query_fields.json")); querySettings.setQuery("my query string"); QueryBuilder qbRes = tested.prepareQueryBuilder(querySettings); TestUtils.assertJsonContentFromClasspathFile("/search/query_fulltext_fields.json", qbRes.toString()); Mockito.verify(tested.configService).get(ConfigService.CFGNAME_SEARCH_FULLTEXT_QUERY_FIELDS); Mockito.verifyNoMoreInteractions(tested.configService); } // case - no fulltext parameter requested, some fulltext fields configured which has no effect { querySettings.setQuery(null); Mockito.reset(tested.configService); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_FULLTEXT_QUERY_FIELDS)).thenReturn( TestUtils.loadJSONFromClasspathFile("/search/search_fulltext_query_fields.json")); QueryBuilder qbRes = tested.prepareQueryBuilder(querySettings); TestUtils.assertJsonContentFromClasspathFile("/search/query_match_all.json", qbRes.toString()); Mockito.verifyZeroInteractions(tested.configService); } } @SuppressWarnings("unchecked") @Test public void handleHighlightSettings() { ConfigService configService = Mockito.mock(ConfigService.class); SearchService tested = getTested(configService); SearchRequestBuilder srbMock = Mockito.mock(SearchRequestBuilder.class); // case - NPE when no settings passed in try { tested.setSearchRequestHighlight(null, srbMock); Assert.fail("NullPointerException expected"); } catch (NullPointerException e) { // OK } QuerySettings querySettings = new QuerySettings(); // case - highlight requested but no fulltext query requested so nothing done { Mockito.reset(srbMock, tested.configService); querySettings.setQuery(null); querySettings.setQueryHighlight(true); tested.setSearchRequestHighlight(querySettings, srbMock); Mockito.verifyZeroInteractions(srbMock); Mockito.verifyZeroInteractions(tested.configService); } // case - highlight requested not requested, fulltext query requested, nothing done { Mockito.reset(srbMock, tested.configService); querySettings.setQuery("query"); querySettings.setQueryHighlight(false); tested.setSearchRequestHighlight(querySettings, srbMock); Mockito.verifyZeroInteractions(srbMock); Mockito.verifyZeroInteractions(tested.configService); } // case - highlight and fulltext query requested, configuration OK { Mockito.reset(srbMock, tested.configService); querySettings.setQuery("query"); querySettings.setQueryHighlight(true); Map<String, Object> cfg = TestUtils.loadJSONFromClasspathFile("/search/search_fulltext_highlight_fields.json"); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_FULLTEXT_HIGHLIGHT_FIELDS)).thenReturn(cfg); tested.setSearchRequestHighlight(querySettings, srbMock); Mockito.verify(srbMock).setHighlighterPreTags("<span class='hlt'>"); Mockito.verify(srbMock).setHighlighterPostTags("</span>"); Mockito.verify(srbMock).setHighlighterEncoder("html"); Mockito.verify(srbMock).addHighlightedField("sys_title", -1, 0, 0); Mockito.verify(srbMock).addHighlightedField("sys_description", 2, 3, 20); Mockito.verify(srbMock).addHighlightedField("sys_contributors.fulltext", 5, 10, 30); Mockito.verifyNoMoreInteractions(srbMock); Mockito.verify(tested.configService).get(ConfigService.CFGNAME_SEARCH_FULLTEXT_HIGHLIGHT_FIELDS); Mockito.verifyNoMoreInteractions(tested.configService); } // cases - highlight and fulltext query requested, distinct configuration errors { Mockito.reset(srbMock, tested.configService); querySettings.setQuery("query"); querySettings.setQueryHighlight(true); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_FULLTEXT_HIGHLIGHT_FIELDS)).thenReturn(null); try { tested.setSearchRequestHighlight(querySettings, srbMock); Assert.fail("SettingsException expected"); } catch (SettingsException e) { // OK } } { Mockito.reset(srbMock, tested.configService); querySettings.setQuery("query"); querySettings.setQueryHighlight(true); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_FULLTEXT_HIGHLIGHT_FIELDS)).thenReturn( new HashMap<String, Object>()); try { tested.setSearchRequestHighlight(querySettings, srbMock); Assert.fail("SettingsException expected"); } catch (SettingsException e) { // OK } } { Mockito.reset(srbMock, tested.configService); querySettings.setQuery("query"); querySettings.setQueryHighlight(true); Map<String, Object> cfg = TestUtils.loadJSONFromClasspathFile("/search/search_fulltext_highlight_fields.json"); cfg.put("sys_title", "badclass"); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_FULLTEXT_HIGHLIGHT_FIELDS)).thenReturn(cfg); try { tested.setSearchRequestHighlight(querySettings, srbMock); Assert.fail("SettingsException expected"); } catch (SettingsException e) { // OK } } { Mockito.reset(srbMock, tested.configService); querySettings.setQuery("query"); querySettings.setQueryHighlight(true); Map<String, Object> cfg = TestUtils.loadJSONFromClasspathFile("/search/search_fulltext_highlight_fields.json"); Map<String, String> c = (Map<String, String>) cfg.get("sys_title"); // no integer parameter c.put("fragment_size", "no integer"); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_FULLTEXT_HIGHLIGHT_FIELDS)).thenReturn(cfg); try { tested.setSearchRequestHighlight(querySettings, srbMock); Assert.fail("SettingsException expected"); } catch (SettingsException e) { // OK } } { Mockito.reset(srbMock, tested.configService); querySettings.setQuery("query"); querySettings.setQueryHighlight(true); Map<String, Object> cfg = TestUtils.loadJSONFromClasspathFile("/search/search_fulltext_highlight_fields.json"); Map<String, String> c = (Map<String, String>) cfg.get("sys_title"); // empty parameter c.put("number_of_fragments", ""); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_FULLTEXT_HIGHLIGHT_FIELDS)).thenReturn(cfg); try { tested.setSearchRequestHighlight(querySettings, srbMock); Assert.fail("SettingsException expected"); } catch (SettingsException e) { // OK } } { Mockito.reset(srbMock, tested.configService); querySettings.setQuery("query"); querySettings.setQueryHighlight(true); Map<String, Object> cfg = TestUtils.loadJSONFromClasspathFile("/search/search_fulltext_highlight_fields.json"); Map<String, String> c = (Map<String, String>) cfg.get("sys_title"); // no integer parameter c.put("fragment_offset", "no integer"); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_FULLTEXT_HIGHLIGHT_FIELDS)).thenReturn(cfg); try { tested.setSearchRequestHighlight(querySettings, srbMock); Assert.fail("SettingsException expected"); } catch (SettingsException e) { // OK } } } @Test public void handleResponseContentSettings_pager() { ConfigService configService = Mockito.mock(ConfigService.class); SearchService tested = getTested(configService); SearchRequestBuilder srbMock = Mockito.mock(SearchRequestBuilder.class); // case - NPE when no settings passed in try { tested.setSearchRequestFromSize(null, srbMock); Assert.fail("NullPointerException expected"); } catch (NullPointerException e) { Mockito.verifyNoMoreInteractions(srbMock); // OK } // case - nothing requested { // no filters object Mockito.reset(srbMock); QuerySettings querySettings = new QuerySettings(); tested.setSearchRequestFromSize(querySettings, srbMock); Mockito.verifyNoMoreInteractions(srbMock); // empty filters object Mockito.reset(srbMock); querySettings.setFilters(new Filters()); tested.setSearchRequestFromSize(querySettings, srbMock); Mockito.verifyNoMoreInteractions(srbMock); } // case - size requested { Mockito.reset(srbMock); QuerySettings querySettings = new QuerySettings(); querySettings.setFilters(new Filters()); querySettings.setSize(124); tested.setSearchRequestFromSize(querySettings, srbMock); Mockito.verify(srbMock).setSize(124); Mockito.verifyNoMoreInteractions(srbMock); } // case - size requested but over maximum so stripped { Mockito.reset(srbMock); QuerySettings querySettings = new QuerySettings(); querySettings.setFilters(new Filters()); querySettings.setSize(SearchService.RESPONSE_MAX_SIZE + 10); tested.setSearchRequestFromSize(querySettings, srbMock); Mockito.verify(srbMock).setSize(SearchService.RESPONSE_MAX_SIZE); Mockito.verifyNoMoreInteractions(srbMock); } // case - size requested is 0 { Mockito.reset(srbMock); QuerySettings querySettings = new QuerySettings(); querySettings.setFilters(new Filters()); querySettings.setSize(0); tested.setSearchRequestFromSize(querySettings, srbMock); Mockito.verify(srbMock).setSize(0); Mockito.verifyNoMoreInteractions(srbMock); } // case - size requested is under 0 so not used { Mockito.reset(srbMock); QuerySettings querySettings = new QuerySettings(); querySettings.setFilters(new Filters()); querySettings.setSize(-1); tested.setSearchRequestFromSize(querySettings, srbMock); Mockito.verifyNoMoreInteractions(srbMock); } // case - from requested { Mockito.reset(srbMock); QuerySettings querySettings = new QuerySettings(); querySettings.setFilters(new Filters()); querySettings.setFrom(42); tested.setSearchRequestFromSize(querySettings, srbMock); Mockito.verify(srbMock).setFrom(42); Mockito.verifyNoMoreInteractions(srbMock); } // case - from requested is 0 { Mockito.reset(srbMock); QuerySettings querySettings = new QuerySettings(); querySettings.setFilters(new Filters()); querySettings.setFrom(0); tested.setSearchRequestFromSize(querySettings, srbMock); Mockito.verify(srbMock).setFrom(0); Mockito.verifyNoMoreInteractions(srbMock); } // case - from requested is under 0 so not used { Mockito.reset(srbMock); QuerySettings querySettings = new QuerySettings(); querySettings.setFilters(new Filters()); querySettings.setFrom(-1); tested.setSearchRequestFromSize(querySettings, srbMock); Mockito.verifyNoMoreInteractions(srbMock); } // case - size and from requested { Mockito.reset(srbMock); QuerySettings querySettings = new QuerySettings(); querySettings.setFilters(new Filters()); querySettings.setSize(124); querySettings.setFrom(42); tested.setSearchRequestFromSize(querySettings, srbMock); Mockito.verify(srbMock).setSize(124); Mockito.verify(srbMock).setFrom(42); Mockito.verifyNoMoreInteractions(srbMock); } } @Test public void handleResponseContentSettings_fields() { ConfigService configService = Mockito.mock(ConfigService.class); SearchService tested = getTested(configService); SearchRequestBuilder srbMock = Mockito.mock(SearchRequestBuilder.class); // case - NPE when no settings passed in try { tested.setSearchRequestFields(null, srbMock); Assert.fail("NullPointerException expected"); } catch (NullPointerException e) { Mockito.verifyNoMoreInteractions(srbMock); // OK } // case - no fields requested so defaults loaded from configuration but null { Mockito.reset(srbMock, tested.configService); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS)).thenReturn(null); QuerySettings querySettings = new QuerySettings(); tested.setSearchRequestFields(querySettings, srbMock); Mockito.verify(tested.configService).get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS); Mockito.verifyNoMoreInteractions(srbMock); Mockito.verifyNoMoreInteractions(tested.configService); } // case - no fields requested so defaults loaded from configuration but do not contains correct key { Mockito.reset(srbMock, tested.configService); Map<String, Object> mockConfig = new HashMap<>(); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS)).thenReturn(mockConfig); QuerySettings querySettings = new QuerySettings(); tested.setSearchRequestFields(querySettings, srbMock); Mockito.verify(tested.configService).get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS); Mockito.verifyNoMoreInteractions(srbMock); Mockito.verifyNoMoreInteractions(tested.configService); } // case - no fields requested so defaults loaded from configuration, contains correct key with String value { Mockito.reset(srbMock, tested.configService); Map<String, Object> mockConfig = new HashMap<>(); mockConfig.put(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS, "aa"); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS)).thenReturn(mockConfig); QuerySettings querySettings = new QuerySettings(); tested.setSearchRequestFields(querySettings, srbMock); Mockito.verify(tested.configService).get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS); Mockito.verify(srbMock).addFields(new String[] { "aa" }); Mockito.verifyNoMoreInteractions(srbMock); Mockito.verifyNoMoreInteractions(tested.configService); } // case - no fields requested so defaults loaded from configuration, contains correct key with List value { Mockito.reset(srbMock, tested.configService); Map<String, Object> mockConfig = new HashMap<>(); List<String> cfgList = new ArrayList<>(); cfgList.add("bb"); cfgList.add("cc"); mockConfig.put(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS, cfgList); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS)).thenReturn(mockConfig); QuerySettings querySettings = new QuerySettings(); tested.setSearchRequestFields(querySettings, srbMock); Mockito.verify(tested.configService).get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS); Mockito.verify(srbMock).addFields("bb", "cc"); Mockito.verifyNoMoreInteractions(srbMock); Mockito.verifyNoMoreInteractions(tested.configService); } // case - fields requested { Mockito.reset(srbMock, tested.configService); QuerySettings querySettings = new QuerySettings(); querySettings.addField("aa"); querySettings.addField("bb"); tested.setSearchRequestFields(querySettings, srbMock); Mockito.verify(srbMock).addFields("aa", "bb"); Mockito.verifyNoMoreInteractions(srbMock); Mockito.verify(tested.configService).get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS); Mockito.verifyZeroInteractions(tested.configService); } // case - fields requested but * used there which is invalid { Mockito.reset(srbMock, tested.configService); QuerySettings querySettings = new QuerySettings(); querySettings.addField("aa"); querySettings.addField("*"); try { tested.setSearchRequestFields(querySettings, srbMock); Assert.fail("BadFieldException expected"); } catch (BadFieldException e) { Assert.assertEquals(QuerySettings.FIELDS_KEY, e.getFieldName()); } } } @Test public void handleResponseContentSettings_fields_security() { ConfigService configService = Mockito.mock(ConfigService.class); SearchService tested = getTested(configService); SearchRequestBuilder srbMock = Mockito.mock(SearchRequestBuilder.class); Map<String, Object> mockConfig = new HashMap<>(); List<String> cfgList = new ArrayList<>(); cfgList.add("bb"); cfgList.add("cc"); mockConfig.put(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS, cfgList); Map<String, Object> rolesSettings = new HashMap<>(); rolesSettings.put("aa", "role1"); rolesSettings.put("bb", "role1"); rolesSettings.put("cc", "role1"); mockConfig.put(SearchService.CFGNAME_FIELD_VISIBLE_FOR_ROLES, rolesSettings); // we configure source filtering to check it is not used when _source field is not requested mockConfig.put(SearchService.CFGNAME_SOURCE_FILTERING_FOR_ROLES, rolesSettings); // case - no fields requested so defaults loaded from configuration, but no any available for current user { Mockito.reset(srbMock, tested.configService, tested.authenticationUtilService); mockAuthenticatedUserWithRole(tested, "role2"); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS)).thenReturn(mockConfig); QuerySettings querySettings = new QuerySettings(); try { tested.setSearchRequestFields(querySettings, srbMock); Assert.fail("NotAuthorizedException expected"); } catch (NotAuthorizedException e) { Mockito.verify(tested.configService).get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS); Mockito.verifyNoMoreInteractions(srbMock); Mockito.verifyNoMoreInteractions(tested.configService); } } // case - no fields requested so defaults loaded from configuration, some available for current user rolesSettings.put("bb", TestUtils.createListOfStrings("role1", "role2")); { Mockito.reset(srbMock, tested.configService, tested.authenticationUtilService); mockAuthenticatedUserWithRole(tested, "role2"); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS)).thenReturn(mockConfig); QuerySettings querySettings = new QuerySettings(); tested.setSearchRequestFields(querySettings, srbMock); Mockito.verify(tested.configService).get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS); Mockito.verify(srbMock).addFields("bb"); Mockito.verifyNoMoreInteractions(srbMock); Mockito.verifyNoMoreInteractions(tested.configService); } // case - no fields requested so defaults loaded from configuration, all available for admin role { Mockito.reset(srbMock, tested.configService, tested.authenticationUtilService); mockAuthenticatedUserWithRole(tested, Role.ADMIN); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS)).thenReturn(mockConfig); QuerySettings querySettings = new QuerySettings(); tested.setSearchRequestFields(querySettings, srbMock); Mockito.verify(tested.configService).get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS); Mockito.verify(srbMock).addFields("bb", "cc"); Mockito.verifyNoMoreInteractions(srbMock); Mockito.verifyNoMoreInteractions(tested.configService); } // case - fields requested, but no any available for current user { Mockito.reset(srbMock, tested.configService, tested.authenticationUtilService); mockAuthenticatedUserWithRole(tested, "role2"); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS)).thenReturn(mockConfig); QuerySettings querySettings = new QuerySettings(); querySettings.addField("aa"); querySettings.addField("cc"); try { tested.setSearchRequestFields(querySettings, srbMock); Assert.fail("NotAuthorizedException expected"); } catch (NotAuthorizedException e) { Mockito.verify(tested.configService).get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS); Mockito.verifyNoMoreInteractions(srbMock); Mockito.verifyNoMoreInteractions(tested.configService); } } // case - fields requested, some available for current user { Mockito.reset(srbMock, tested.configService, tested.authenticationUtilService); mockAuthenticatedUserWithRole(tested, "role1"); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS)).thenReturn(mockConfig); QuerySettings querySettings = new QuerySettings(); querySettings.addField("aa"); querySettings.addField("bb"); tested.setSearchRequestFields(querySettings, srbMock); Mockito.verify(tested.configService).get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS); Mockito.verify(srbMock).addFields("aa", "bb"); Mockito.verifyNoMoreInteractions(srbMock); Mockito.verifyNoMoreInteractions(tested.configService); } // case - fields requested, all available for admin role { Mockito.reset(srbMock, tested.configService, tested.authenticationUtilService); mockAuthenticatedUserWithRole(tested, Role.ADMIN); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS)).thenReturn(mockConfig); QuerySettings querySettings = new QuerySettings(); querySettings.addField("aa"); querySettings.addField("bb"); querySettings.addField("cc"); tested.setSearchRequestFields(querySettings, srbMock); Mockito.verify(tested.configService).get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS); Mockito.verify(srbMock).addFields("aa", "bb", "cc"); Mockito.verifyNoMoreInteractions(srbMock); Mockito.verifyNoMoreInteractions(tested.configService); } } @Test public void handleResponseContentSettings_fields_source_filtering() { // note that test which covers source filtering is not used when _source is not requested is in // handleResponseContentSettings_fields_security() ConfigService configService = Mockito.mock(ConfigService.class); SearchService tested = getTested(configService); SearchRequestBuilder srbMock = Mockito.mock(SearchRequestBuilder.class); Map<String, Object> mockConfig = new HashMap<>(); Map<String, Object> rolesSettings = new HashMap<>(); rolesSettings.put("*.aa", "role1"); rolesSettings.put("bb", "role1"); rolesSettings.put("cc.*", TestUtils.createListOfStrings("role1", "role2")); rolesSettings.put("dd", "role2"); mockConfig.put(SearchService.CFGNAME_SOURCE_FILTERING_FOR_ROLES, rolesSettings); QuerySettings querySettings = new QuerySettings(); // case - check source filtering is applied if not any field is requested, as elasticsearch returns source in // this case { Mockito.reset(srbMock, tested.configService, tested.authenticationUtilService); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS)).thenReturn(mockConfig); Mockito.when(srbMock.setFetchSource(Mockito.any(String[].class), Mockito.any(String[].class))).thenAnswer( new SourceExcludeMatcher(srbMock, TestUtils.createListOfStrings("*.aa", "bb", "cc.*", "dd"))); tested.setSearchRequestFields(querySettings, srbMock); Mockito.verify(tested.configService).get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS); Mockito.verify(srbMock).setFetchSource(Mockito.any(String[].class), Mockito.any(String[].class)); Mockito.verifyNoMoreInteractions(srbMock); Mockito.verifyNoMoreInteractions(tested.configService); } // set _source field as requested for other tests querySettings.addField("_source"); // case - source filtering not applied when not configured { Mockito.reset(srbMock, tested.configService, tested.authenticationUtilService); mockAuthenticatedUserWithRole(tested, "role1"); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS)).thenReturn( new HashMap<String, Object>()); tested.setSearchRequestFields(querySettings, srbMock); Mockito.verify(tested.configService).get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS); Mockito.verify(srbMock).addFields("_source"); Mockito.verifyNoMoreInteractions(srbMock); Mockito.verifyNoMoreInteractions(tested.configService); } // case - filtering configured, anonymous user has filtered source { Mockito.reset(srbMock, tested.configService, tested.authenticationUtilService); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS)).thenReturn(mockConfig); Mockito.when(srbMock.setFetchSource(Mockito.any(String[].class), Mockito.any(String[].class))).thenAnswer( new SourceExcludeMatcher(srbMock, TestUtils.createListOfStrings("*.aa", "bb", "cc.*", "dd"))); tested.setSearchRequestFields(querySettings, srbMock); Mockito.verify(tested.configService).get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS); Mockito.verify(srbMock).addFields("_source"); Mockito.verify(srbMock).setFetchSource(Mockito.any(String[].class), Mockito.any(String[].class)); Mockito.verifyNoMoreInteractions(srbMock); Mockito.verifyNoMoreInteractions(tested.configService); } // case - filtering configured, role1 and role2 users have filtered parts of source { Mockito.reset(srbMock, tested.configService, tested.authenticationUtilService); mockAuthenticatedUserWithRole(tested, "role1"); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS)).thenReturn(mockConfig); Mockito.when(srbMock.setFetchSource(Mockito.any(String[].class), Mockito.any(String[].class))).thenAnswer( new SourceExcludeMatcher(srbMock, TestUtils.createListOfStrings("dd"))); tested.setSearchRequestFields(querySettings, srbMock); Mockito.verify(tested.configService).get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS); Mockito.verify(srbMock).addFields("_source"); Mockito.verify(srbMock).setFetchSource(Mockito.any(String[].class), Mockito.any(String[].class)); Mockito.verifyNoMoreInteractions(srbMock); Mockito.verifyNoMoreInteractions(tested.configService); } { Mockito.reset(srbMock, tested.configService, tested.authenticationUtilService); mockAuthenticatedUserWithRole(tested, "role2"); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS)).thenReturn(mockConfig); Mockito.when(srbMock.setFetchSource(Mockito.any(String[].class), Mockito.any(String[].class))).thenAnswer( new SourceExcludeMatcher(srbMock, TestUtils.createListOfStrings("bb", "*.aa"))); tested.setSearchRequestFields(querySettings, srbMock); Mockito.verify(tested.configService).get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS); Mockito.verify(srbMock).addFields("_source"); Mockito.verify(srbMock).setFetchSource(Mockito.any(String[].class), Mockito.any(String[].class)); Mockito.verifyNoMoreInteractions(srbMock); Mockito.verifyNoMoreInteractions(tested.configService); } // case - filtering configured, admin can see all fields, no any source filtering applied { Mockito.reset(srbMock, tested.configService, tested.authenticationUtilService); mockAuthenticatedUserWithRole(tested, Role.ADMIN); Mockito.when(tested.configService.get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS)).thenReturn(mockConfig); tested.setSearchRequestFields(querySettings, srbMock); Mockito.verify(tested.configService).get(ConfigService.CFGNAME_SEARCH_RESPONSE_FIELDS); Mockito.verify(srbMock).addFields("_source"); Mockito.verifyNoMoreInteractions(srbMock); Mockito.verifyNoMoreInteractions(tested.configService); } } private static final class SourceExcludeMatcher implements Answer<SearchRequestBuilder> { private SearchRequestBuilder srbMock; private ArrayList<String> expectedExcludedFields; public SourceExcludeMatcher(SearchRequestBuilder srbMockToReturn, ArrayList<String> expectedExcludedFields) { this.srbMock = srbMockToReturn; this.expectedExcludedFields = expectedExcludedFields; } @Override public SearchRequestBuilder answer(InvocationOnMock invocation) throws Throwable { Assert.assertNull(invocation.getArguments()[0]); String[] actualStrings = (String[]) invocation.getArguments()[1]; Assert.assertEquals("size of expected and actual list of strings is not same", expectedExcludedFields.size(), actualStrings.length); for (String s : actualStrings) { Assert.assertTrue(s + " is not in expected strings", expectedExcludedFields.contains(s)); } return srbMock; } } @Test public void handleSortingSettings() { SearchService tested = getTested(Mockito.mock(ConfigService.class)); SearchRequestBuilder srbMock = Mockito.mock(SearchRequestBuilder.class); // case - NPE when no settings passed in try { tested.setSearchRequestSort(null, srbMock); Assert.fail("NullPointerException expected"); } catch (NullPointerException e) { Mockito.verifyNoMoreInteractions(srbMock); // OK } // case - sorting not requested { Mockito.reset(srbMock); QuerySettings querySettings = new QuerySettings(); tested.setSearchRequestSort(querySettings, srbMock); Mockito.verifyNoMoreInteractions(srbMock); } // case - sorting requests { Mockito.reset(srbMock); QuerySettings querySettings = new QuerySettings(); querySettings.setSortBy(SortByValue.SCORE); tested.setSearchRequestSort(querySettings, srbMock); Mockito.verifyNoMoreInteractions(srbMock); } { Mockito.reset(srbMock); QuerySettings querySettings = new QuerySettings(); querySettings.setSortBy(SortByValue.NEW); tested.setSearchRequestSort(querySettings, srbMock); Mockito.verify(srbMock).addSort("sys_last_activity_date", SortOrder.DESC); Mockito.verifyNoMoreInteractions(srbMock); } { Mockito.reset(srbMock); QuerySettings querySettings = new QuerySettings(); querySettings.setSortBy(SortByValue.OLD); tested.setSearchRequestSort(querySettings, srbMock); Mockito.verify(srbMock).addSort("sys_last_activity_date", SortOrder.ASC); Mockito.verifyNoMoreInteractions(srbMock); } { Mockito.reset(srbMock); QuerySettings querySettings = new QuerySettings(); querySettings.setSortBy(SortByValue.NEW_CREATION); tested.setSearchRequestSort(querySettings, srbMock); Mockito.verify(srbMock).addSort("sys_created", SortOrder.DESC); Mockito.verifyNoMoreInteractions(srbMock); } } @Test public void getFilters() { { FilterBuilder[] ret = SearchService.filtersMapToArrayExcluding(null, null); Assert.assertNotNull(ret); Assert.assertEquals(0, ret.length); } { FilterBuilder[] ret = SearchService.filtersMapToArrayExcluding(null, "aaa"); Assert.assertNotNull(ret); Assert.assertEquals(0, ret.length); } Map<String, FilterBuilder> filters = new LinkedHashMap<>(); FilterBuilder fb1 = Mockito.mock(FilterBuilder.class); filters.put("f1", fb1); FilterBuilder fb2 = Mockito.mock(FilterBuilder.class); filters.put("f2", fb2); FilterBuilder fb3 = Mockito.mock(FilterBuilder.class); filters.put("f3", fb3); { FilterBuilder[] ret = SearchService.filtersMapToArrayExcluding(filters, null); Assert.assertNotNull(ret); Assert.assertEquals(3, ret.length); Assert.assertEquals(fb1, ret[0]); Assert.assertEquals(fb2, ret[1]); Assert.assertEquals(fb3, ret[2]); } { FilterBuilder[] ret = SearchService.filtersMapToArrayExcluding(filters, "f2"); Assert.assertNotNull(ret); Assert.assertEquals(2, ret.length); Assert.assertEquals(fb1, ret[0]); Assert.assertEquals(fb3, ret[1]); } } @Test public void handleAggregationSettings_common() throws IOException, JSONException, ReflectiveOperationException { Client client = Mockito.mock(Client.class); ConfigService configService = mockConfigurationService(); SearchService tested = getTested(configService); // case - no aggregations requested { SearchRequestBuilder srbMock = new SearchRequestBuilder(client); QuerySettings querySettings = new QuerySettings(); tested.handleAggregationSettings(querySettings, null, srbMock); Assert.assertEquals("{ }", srbMock.toString()); } // case - one aggregation requested without filters { SearchRequestBuilder srbMock = new SearchRequestBuilder(client); QuerySettings querySettings = new QuerySettings(); querySettings.addAggregation("per_sys_type_counts"); tested.handleAggregationSettings(querySettings, null, srbMock); TestUtils.assertJsonContentFromClasspathFile("/search/query_aggregations_per_sys_type_counts.json", srbMock.toString()); } // case - more aggregations requested without filters { SearchRequestBuilder srbMock = new SearchRequestBuilder(client); QuerySettings querySettings = new QuerySettings(); querySettings.addAggregation("activity_dates_histogram"); querySettings.addAggregation("per_project_counts"); querySettings.addAggregation("tag_cloud"); querySettings.addAggregation("top_contributors"); tested.handleAggregationSettings(querySettings, null, srbMock); TestUtils.assertJsonContentFromClasspathFile("/search/query_aggregations_moreNoFilter.json", srbMock.toString()); } // case - more aggregations requested with more filters { SearchRequestBuilder srbMock = new SearchRequestBuilder(client); QuerySettings querySettings = new QuerySettings(); Filters filters = new Filters(); filters.acknowledgeUrlFilterCandidate("activity_date_from", new DateTime(100000l).toString(DATE_TIME_FORMATTER_UTC)); filters .acknowledgeUrlFilterCandidate("activity_date_to", new DateTime(100200l).toString(DATE_TIME_FORMATTER_UTC)); filters.acknowledgeUrlFilterCandidate("type", "my_content_type"); filters.acknowledgeUrlFilterCandidate("contributor", "my_contributor_1", "my_contributor_2"); filters.acknowledgeUrlFilterCandidate("content_provider", "my_sys_content_provider"); filters.acknowledgeUrlFilterCandidate("sys_type", "my_sys_type", "my_sys_type_2"); filters.acknowledgeUrlFilterCandidate("project", "my_project", "my_project_2"); filters.acknowledgeUrlFilterCandidate("tag", "tag1", "tag2"); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); querySettings.setFilters(filters); querySettings.addAggregation("per_sys_type_counts"); querySettings.addAggregation("activity_dates_histogram"); querySettings.addAggregation("per_project_counts"); querySettings.addAggregation("tag_cloud"); querySettings.addAggregation("top_contributors"); tested.handleAggregationSettings(querySettings, tested.parsedFilterConfigService.getSearchFiltersForRequest(), srbMock); TestUtils.assertJsonContentFromClasspathFile("/search/query_aggregations_moreWithFilter.json", srbMock.toString()); } } @Test public void handleAggregationSettings_top_contributors() throws IOException, JSONException, ReflectiveOperationException { Client client = Mockito.mock(Client.class); ConfigService configService = mockConfigurationService(); SearchService tested = getTested(configService); // case - no contributor filter used, so only one top_contributors aggregation { SearchRequestBuilder srbMock = new SearchRequestBuilder(client); QuerySettings querySettings = new QuerySettings(); querySettings.addAggregation("top_contributors"); Filters filters = new Filters(); filters.acknowledgeUrlFilterCandidate("tag", "tag1", "tag2"); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); querySettings.setFilters(filters); tested.handleAggregationSettings(querySettings, tested.parsedFilterConfigService.getSearchFiltersForRequest(), srbMock); TestUtils.assertJsonContentFromClasspathFile("/search/query_aggregations_top_contributors_1.json", srbMock.toString()); } // case - contributor filter used, so two top_contributors aggregations used { SearchRequestBuilder srbMock = new SearchRequestBuilder(client); QuerySettings querySettings = new QuerySettings(); querySettings.addAggregation("top_contributors"); Filters filters = new Filters(); filters.acknowledgeUrlFilterCandidate("tag", "tag1", "tag2"); filters.acknowledgeUrlFilterCandidate("contributor", "John Doe <john@doe.org>"); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); querySettings.setFilters(filters); tested.handleAggregationSettings(querySettings, tested.parsedFilterConfigService.getSearchFiltersForRequest(), srbMock); TestUtils.assertJsonContentFromClasspathFile("/search/query_aggregations_top_contributors_2.json", srbMock.toString()); } } @Test public void handleAggregationSettings_activity_dates_histogram() throws IOException, JSONException, ReflectiveOperationException { Client client = Mockito.mock(Client.class); ConfigService configService = mockConfigurationService(); SearchService tested = getTested(configService); // case - no activity dates filter used { SearchRequestBuilder srbMock = new SearchRequestBuilder(client); QuerySettings querySettings = new QuerySettings(); querySettings.addAggregation("activity_dates_histogram"); Filters filters = new Filters(); filters.acknowledgeUrlFilterCandidate("tag", "tag1", "tag2"); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); querySettings.setFilters(filters); tested.handleAggregationSettings(querySettings, tested.parsedFilterConfigService.getSearchFiltersForRequest(), srbMock); TestUtils.assertJsonContentFromClasspathFile("/search/query_aggregations_activity_dates_histogram_1.json", srbMock.toString()); } // case - activity dates interval filter used (so from/to is ignored) { SearchRequestBuilder srbMock = new SearchRequestBuilder(client); QuerySettings querySettings = new QuerySettings(); querySettings.addAggregation("activity_dates_histogram"); Filters filters = new Filters(); filters.acknowledgeUrlFilterCandidate("tag", "tag1", "tag2"); filters.acknowledgeUrlFilterCandidate("activity_date_interval", PastIntervalValue.TEST.toString()); filters.acknowledgeUrlFilterCandidate("activity_date_from", new DateTime(1256545l).toString(DATE_TIME_FORMATTER_UTC)); filters.acknowledgeUrlFilterCandidate("activity_date_to", new DateTime(2256545l).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); querySettings.setFilters(filters); tested.handleAggregationSettings(querySettings, tested.parsedFilterConfigService.getSearchFiltersForRequest(), srbMock); TestUtils.assertJsonContentFromClasspathFile("/search/query_aggregations_activity_dates_histogram_2.json", srbMock.toString()); } // case - activity dates from/to filter used { SearchRequestBuilder srbMock = new SearchRequestBuilder(client); QuerySettings querySettings = new QuerySettings(); querySettings.addAggregation("activity_dates_histogram"); Filters filters = new Filters(); filters.acknowledgeUrlFilterCandidate("tag", "tag1", "tag2"); filters.acknowledgeUrlFilterCandidate("activity_date_from", new DateTime(1256545l).toString(DATE_TIME_FORMATTER_UTC)); filters.acknowledgeUrlFilterCandidate("activity_date_to", new DateTime(22256545l).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); querySettings.setFilters(filters); tested.handleAggregationSettings(querySettings, tested.parsedFilterConfigService.getSearchFiltersForRequest(), srbMock); TestUtils.assertJsonContentFromClasspathFile("/search/query_aggregations_activity_dates_histogram_3.json", srbMock.toString()); } } /** * This test demonstrate how to test complete Elasticsearch query (and not only individual parts of it). * * @see <a href="https://github.com/searchisko/searchisko/issues/130">This test was inspired by #130.</a> * * @throws IOException * @throws JSONException * @throws ReflectiveOperationException */ @Test public void testCompleteElasticsearchQuery() throws IOException, JSONException, ReflectiveOperationException { Client client = Mockito.mock(Client.class); ConfigService configService = mockConfigurationService(); SearchService tested = getTested(configService); mockProviderConfiguration(tested, "/search/provider_1.json", "/search/provider_2.json"); // prepare search request params QuerySettings querySettings = new QuerySettings(); Filters filters = new Filters(); querySettings.setFilters(filters); querySettings.addAggregation("activity_dates_histogram"); querySettings.addAggregation("per_project_counts"); querySettings.addAggregation("per_sys_type_counts"); querySettings.setQuery("This is client query"); filters.acknowledgeUrlFilterCandidate("activity_date_interval", PastIntervalValue.TEST.toString()); filters.acknowledgeUrlFilterCandidate("project", "eap"); filters.acknowledgeUrlFilterCandidate("sys_type", "issue"); filters.acknowledgeUrlFilterCandidate("content_provider", "provider1"); filters.acknowledgeUrlFilterCandidate("type", "provider1_issue"); querySettings.setSize(0); querySettings.setFilters(filters); // case - user is not logged in { tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Mockito.when(tested.authenticationUtilService.isAuthenticatedUser()).thenReturn(false); SearchRequestBuilder srb = new SearchRequestBuilder(client); tested.performSearchInternal(querySettings, srb); TestUtils.assertJsonContentFromClasspathFile( "/search/complete_query_filters_and_activity_dates_histogram_userNotAuthenticated.json", srb.toString()); } // case - admin user { tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Mockito.reset(tested.authenticationUtilService); Mockito.when(tested.authenticationUtilService.isUserInRole(Role.ADMIN)).thenReturn(true); Mockito.when(tested.authenticationUtilService.isAuthenticatedUser()).thenReturn(true); SearchRequestBuilder srb = new SearchRequestBuilder(client); tested.performSearchInternal(querySettings, srb); TestUtils.assertJsonContentFromClasspathFile("/search/complete_query_filters_and_activity_dates_histogram_userIsAdmin.json", srb.toString()); } // case - authenticated user with roles { tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Mockito.reset(tested.authenticationUtilService); Mockito.when(tested.authenticationUtilService.isUserInRole(Role.ADMIN)).thenReturn(false); Mockito.when(tested.authenticationUtilService.getUserRoles()).thenReturn( TestUtils.createSetOfStrings("role1", "role2")); Mockito.when(tested.authenticationUtilService.isAuthenticatedUser()).thenReturn(true); SearchRequestBuilder srb = new SearchRequestBuilder(client); tested.performSearchInternal(querySettings, srb); TestUtils.assertJsonContentFromClasspathFile("/search/complete_query_filters_and_activity_dates_histogram_userWithRoles.json", srb.toString()); } } @Test public void applyContentLevelSecurityFilter() throws IOException, JSONException { ConfigService configService = mockConfigurationService(); SearchService tested = getTested(configService); // case - not logged in user QueryBuilder qb = QueryBuilders.matchAllQuery(); { Mockito.when(tested.authenticationUtilService.isAuthenticatedUser()).thenReturn(false); QueryBuilder retqb = tested.applyContentLevelSecurityFilter(qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_dlsecurity_filter_anonym.json", retqb.toString()); } // case - admin user { Mockito.reset(tested.authenticationUtilService); Mockito.when(tested.authenticationUtilService.isUserInRole(Role.ADMIN)).thenReturn(true); Mockito.when(tested.authenticationUtilService.isAuthenticatedUser()).thenReturn(true); QueryBuilder retqb = tested.applyContentLevelSecurityFilter(qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_dlsecurity_filter_admin.json", retqb.toString()); Mockito.verify(tested.authenticationUtilService).isUserInRole(Role.ADMIN); Mockito.verifyNoMoreInteractions(tested.authenticationUtilService); } // case - authenticated user with roles { Mockito.reset(tested.authenticationUtilService); Mockito.when(tested.authenticationUtilService.isUserInRole(Role.ADMIN)).thenReturn(false); Mockito.when(tested.authenticationUtilService.getUserRoles()).thenReturn( TestUtils.createSetOfStrings("role1", "role2")); Mockito.when(tested.authenticationUtilService.isAuthenticatedUser()).thenReturn(true); QueryBuilder retqb = tested.applyContentLevelSecurityFilter(qb); TestUtils.assertJsonContentFromClasspathFile("/search/query_dlsecurity_filter_userwithroles.json", retqb.toString()); Mockito.verify(tested.authenticationUtilService).isUserInRole(Role.ADMIN); Mockito.verify(tested.authenticationUtilService).isAuthenticatedUser(); Mockito.verify(tested.authenticationUtilService).getUserRoles(); Mockito.verifyNoMoreInteractions(tested.authenticationUtilService); } } @Test public void selectActivityDatesHistogramInterval_common() throws ReflectiveOperationException { ConfigService configService = mockConfigurationService(); SearchService tested = getTested(configService); tested.parsedFilterConfigService.prepareFiltersForRequest(null); String fieldName = "sys_activity_dates"; // case - no activity dates filter defined Assert.assertEquals("month", tested.getDateHistogramAggregationInterval(null)); Assert.assertEquals("month", tested.getDateHistogramAggregationInterval(fieldName)); Filters filters = new Filters(); // case - activity date interval precedence against from/to filters.acknowledgeUrlFilterCandidate("activity_date_interval", PastIntervalValue.YEAR.toString()); filters.acknowledgeUrlFilterCandidate("activity_date_from", new DateTime(DateTimeZone.UTC).minus(1000000).toString(DATE_TIME_FORMATTER_UTC)); filters.acknowledgeUrlFilterCandidate("activity_date_to", new DateTime(DateTimeZone.UTC).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("week", tested.getDateHistogramAggregationInterval(fieldName)); } @Test public void selectActivityDatesHistogramInterval_intervalFilter() throws ReflectiveOperationException { ConfigService configService = mockConfigurationService(); SearchService tested = getTested(configService); String fieldName = "sys_activity_dates"; Filters filters = new Filters(); filters.acknowledgeUrlFilterCandidate("activity_date_interval", PastIntervalValue.YEAR.toString()); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("week", tested.getDateHistogramAggregationInterval(fieldName)); filters.acknowledgeUrlFilterCandidate("activity_date_interval", PastIntervalValue.QUARTER.toString()); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("week", tested.getDateHistogramAggregationInterval(fieldName)); filters.acknowledgeUrlFilterCandidate("activity_date_interval", PastIntervalValue.MONTH.toString()); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("day", tested.getDateHistogramAggregationInterval(fieldName)); filters.acknowledgeUrlFilterCandidate("activity_date_interval", PastIntervalValue.WEEK.toString()); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("day", tested.getDateHistogramAggregationInterval(fieldName)); filters.acknowledgeUrlFilterCandidate("activity_date_interval", PastIntervalValue.DAY.toString()); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("hour", tested.getDateHistogramAggregationInterval(fieldName)); } @Test public void selectActivityDatesHistogramInterval_fromToFilter() throws ReflectiveOperationException { ConfigService configService = mockConfigurationService(); SearchService tested = getTested(configService); String fieldName = "sys_activity_dates"; Filters filters = new Filters(); // case - no from defined, so always month filters.forgetUrlFilterCandidate("activity_date_from", "activity_date_to"); filters.acknowledgeUrlFilterCandidate("activity_date_from"); filters.acknowledgeUrlFilterCandidate("activity_date_to", new DateTime(DateTimeZone.UTC).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("month", tested.getDateHistogramAggregationInterval(fieldName)); filters.forgetUrlFilterCandidate("activity_date_from", "activity_date_to"); filters.acknowledgeUrlFilterCandidate("activity_date_to", new DateTime(DateTimeZone.UTC).minusYears(10).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("month", tested.getDateHistogramAggregationInterval(fieldName)); // case - no to defined means current timestamp is used filters.forgetUrlFilterCandidate("activity_date_from", "activity_date_to"); filters.acknowledgeUrlFilterCandidate("activity_date_from", new DateTime(DateTimeZone.UTC).toString(DATE_TIME_FORMATTER_UTC)); filters.acknowledgeUrlFilterCandidate("activity_date_to"); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("minute", tested.getDateHistogramAggregationInterval(fieldName)); // clear cache filters.forgetUrlFilterCandidate("activity_date_from", "activity_date_to"); filters.acknowledgeUrlFilterCandidate("activity_date_from", new DateTime(DateTimeZone.UTC).minusHours(1).plusMillis(100).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("minute", tested.getDateHistogramAggregationInterval(fieldName)); filters.acknowledgeUrlFilterCandidate("activity_date_from", new DateTime(DateTimeZone.UTC).minusHours(1).minusMillis(100).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("hour", tested.getDateHistogramAggregationInterval(fieldName)); filters.forgetUrlFilterCandidate("activity_date_from", "activity_date_to"); filters.acknowledgeUrlFilterCandidate("activity_date_from", new DateTime(DateTimeZone.UTC).minusDays(2).plusMillis(100).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("hour", tested.getDateHistogramAggregationInterval(fieldName)); filters.acknowledgeUrlFilterCandidate("activity_date_from", new DateTime(DateTimeZone.UTC).minusDays(2).minusMillis(100).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("day", tested.getDateHistogramAggregationInterval(fieldName)); filters.forgetUrlFilterCandidate("activity_date_from", "activity_date_to"); filters.acknowledgeUrlFilterCandidate("activity_date_from", new DateTime(System.currentTimeMillis() - 1000L * 60L * 60L * 24l * 7l * 8l + 100l).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("day", tested.getDateHistogramAggregationInterval(fieldName)); filters.acknowledgeUrlFilterCandidate("activity_date_from", new DateTime(System.currentTimeMillis() - 1000L * 60L * 60L * 24l * 7l * 8l - 100l).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("week", tested.getDateHistogramAggregationInterval(fieldName)); filters.forgetUrlFilterCandidate("activity_date_from", "activity_date_to"); filters.acknowledgeUrlFilterCandidate("activity_date_from", new DateTime(DateTimeZone.UTC).minusDays(366).plusMillis(100).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("week", tested.getDateHistogramAggregationInterval(fieldName)); filters.acknowledgeUrlFilterCandidate("activity_date_from", new DateTime(DateTimeZone.UTC).minusDays(366).minusMillis(100) .toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("month", tested.getDateHistogramAggregationInterval(fieldName)); // case - both from and to defined filters.forgetUrlFilterCandidate("activity_date_from", "activity_date_to"); filters.acknowledgeUrlFilterCandidate("activity_date_from", new DateTime(1000L).toString(DATE_TIME_FORMATTER_UTC)); filters.acknowledgeUrlFilterCandidate("activity_date_to", new DateTime(1200L).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("minute", tested.getDateHistogramAggregationInterval(fieldName)); filters.acknowledgeUrlFilterCandidate("activity_date_to", new DateTime(1000L + 1000L * 60L * 60L - 100L).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("minute", tested.getDateHistogramAggregationInterval(fieldName)); filters.acknowledgeUrlFilterCandidate("activity_date_to", new DateTime(1000L + 1000L * 60L * 60L + 100L).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("hour", tested.getDateHistogramAggregationInterval(fieldName)); filters.acknowledgeUrlFilterCandidate("activity_date_from", new DateTime(1000000L).toString(DATE_TIME_FORMATTER_UTC)); filters.acknowledgeUrlFilterCandidate("activity_date_to", new DateTime(1000000L + 1000L * 60L * 60L * 24l * 2l - 100L).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("hour", tested.getDateHistogramAggregationInterval(fieldName)); filters.acknowledgeUrlFilterCandidate("activity_date_to", new DateTime(1000000L + 1000L * 60L * 60L * 24l * 2l + 100L).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("day", tested.getDateHistogramAggregationInterval(fieldName)); filters.acknowledgeUrlFilterCandidate("activity_date_from", new DateTime(100000000L).toString(DATE_TIME_FORMATTER_UTC)); filters.acknowledgeUrlFilterCandidate("activity_date_to", new DateTime(100000000L + 1000L * 60L * 60L * 24l * 7l * 8l - 100L).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("day", tested.getDateHistogramAggregationInterval(fieldName)); filters.acknowledgeUrlFilterCandidate("activity_date_to", new DateTime(100000000L + 1000L * 60L * 60L * 24l * 7l * 8l + 100L).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("week", tested.getDateHistogramAggregationInterval(fieldName)); filters.acknowledgeUrlFilterCandidate("activity_date_from", new DateTime(1000000000L).toString(DATE_TIME_FORMATTER_UTC)); filters.acknowledgeUrlFilterCandidate("activity_date_to", new DateTime(1000000000L + 1000L * 60L * 60L * 24L * 366L - 100L).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("week", tested.getDateHistogramAggregationInterval(fieldName)); filters.acknowledgeUrlFilterCandidate("activity_date_to", new DateTime(1000000000L + 1000L * 60L * 60L * 24L * 366L + 100L).toString(DATE_TIME_FORMATTER_UTC)); tested.parsedFilterConfigService.prepareFiltersForRequest(filters); Assert.assertEquals("month", tested.getDateHistogramAggregationInterval(fieldName)); } @SuppressWarnings({ "unchecked", "rawtypes" }) @Test public void writeSearchHitUsedStatisticsRecord() { SearchService tested = getTested(null); // case - record not accepted { Mockito.reset(tested.statsClientService); Mockito.when( tested.statsClientService.checkStatisticsRecordExists(Mockito.eq(StatsRecordType.SEARCH), Mockito.anyMap())) .thenAnswer(new Answer<Boolean>() { @Override public Boolean answer(InvocationOnMock invocation) throws Throwable { Map<String, String> conditions = (Map<String, String>) invocation.getArguments()[1]; Assert.assertEquals(2, conditions.size()); Assert.assertEquals("my-uuid", conditions.get(StatsClientService.FIELD_RESPONSE_UUID)); Assert.assertEquals("my_hit_id", conditions.get(StatsClientService.FIELD_HITS_ID)); return false; } }); Assert.assertFalse(tested.writeSearchHitUsedStatisticsRecord("my-uuid", "my_hit_id", null)); Mockito.verify(tested.statsClientService).checkStatisticsRecordExists(Mockito.eq(StatsRecordType.SEARCH), Mockito.anyMap()); Mockito.verifyNoMoreInteractions(tested.statsClientService); } // case - record accepted { Mockito.reset(tested.statsClientService); Mockito.when( tested.statsClientService.checkStatisticsRecordExists(Mockito.eq(StatsRecordType.SEARCH), Mockito.anyMap())) .thenAnswer(new Answer<Boolean>() { @Override public Boolean answer(InvocationOnMock invocation) throws Throwable { Map<String, String> conditions = (Map<String, String>) invocation.getArguments()[1]; Assert.assertEquals(2, conditions.size()); Assert.assertEquals("my-uuid", conditions.get(StatsClientService.FIELD_RESPONSE_UUID)); Assert.assertEquals("my_hit_id", conditions.get(StatsClientService.FIELD_HITS_ID)); return true; } }); Mockito.doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Map<String, String> conditions = (Map<String, String>) invocation.getArguments()[2]; Assert.assertEquals(3, conditions.size()); Assert.assertEquals("my-uuid", conditions.get(StatsClientService.FIELD_RESPONSE_UUID)); Assert.assertEquals("my_hit_id", conditions.get(StatsClientService.FIELD_HITS_ID)); Assert.assertEquals("my-session-id", conditions.get("session")); Long ts = (Long) invocation.getArguments()[1]; long cts = System.currentTimeMillis(); Assert.assertTrue("passed in timestamp is invalid, must be nearly current", (cts - 2000) <= ts && ts <= cts); return null; } }).when(tested.statsClientService) .writeStatisticsRecord(Mockito.eq(StatsRecordType.SEARCH_HIT_USED), Mockito.anyLong(), Mockito.anyMap()); Assert.assertTrue(tested.writeSearchHitUsedStatisticsRecord("my-uuid", "my_hit_id", "my-session-id")); Mockito.verify(tested.statsClientService).checkStatisticsRecordExists(Mockito.eq(StatsRecordType.SEARCH), Mockito.anyMap()); Mockito.verify(tested.statsClientService).writeStatisticsRecord(Mockito.eq(StatsRecordType.SEARCH_HIT_USED), Mockito.anyLong(), Mockito.anyMap()); Mockito.verifyNoMoreInteractions(tested.statsClientService); } } }