/*
* Copyright 2015 herd contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.finra.herd.service;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Future;
import org.elasticsearch.action.ListenableActionFuture;
import org.elasticsearch.action.admin.indices.get.GetIndexRequestBuilder;
import org.elasticsearch.action.admin.indices.get.GetIndexResponse;
import org.elasticsearch.action.admin.indices.stats.CommonStats;
import org.elasticsearch.action.admin.indices.stats.IndexStats;
import org.elasticsearch.action.admin.indices.stats.IndicesStatsRequestBuilder;
import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse;
import org.elasticsearch.client.AdminClient;
import org.elasticsearch.client.IndicesAdminClient;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.collect.ImmutableOpenMap;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.shard.DocsStats;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.finra.herd.core.helper.ConfigurationHelper;
import org.finra.herd.dao.BusinessObjectDefinitionDao;
import org.finra.herd.dao.SearchIndexDao;
import org.finra.herd.model.AlreadyExistsException;
import org.finra.herd.model.api.xml.SearchIndex;
import org.finra.herd.model.api.xml.SearchIndexCreateRequest;
import org.finra.herd.model.api.xml.SearchIndexKey;
import org.finra.herd.model.api.xml.SearchIndexKeys;
import org.finra.herd.model.api.xml.SearchIndexStatistics;
import org.finra.herd.model.dto.ConfigurationValue;
import org.finra.herd.model.jpa.SearchIndexEntity;
import org.finra.herd.model.jpa.SearchIndexStatusEntity;
import org.finra.herd.model.jpa.SearchIndexTypeEntity;
import org.finra.herd.service.functional.SearchFunctions;
import org.finra.herd.service.helper.AlternateKeyHelper;
import org.finra.herd.service.helper.BusinessObjectDefinitionHelper;
import org.finra.herd.service.helper.ConfigurationDaoHelper;
import org.finra.herd.service.helper.SearchIndexDaoHelper;
import org.finra.herd.service.helper.SearchIndexStatusDaoHelper;
import org.finra.herd.service.helper.SearchIndexTypeDaoHelper;
import org.finra.herd.service.impl.SearchIndexServiceImpl;
/**
* This class tests search index functionality within the search index service.
*/
public class SearchIndexServiceTest extends AbstractServiceTest
{
@Mock
private AlternateKeyHelper alternateKeyHelper;
@Mock
private BusinessObjectDefinitionDao businessObjectDefinitionDao;
@Mock
private BusinessObjectDefinitionHelper businessObjectDefinitionHelper;
@Mock
private ConfigurationDaoHelper configurationDaoHelper;
@Mock
private ConfigurationHelper configurationHelper;
@Mock
private SearchFunctions searchFunctions;
@Mock
private SearchIndexDao searchIndexDao;
@Mock
private SearchIndexDaoHelper searchIndexDaoHelper;
@Mock
private SearchIndexHelperService searchIndexHelperService;
@InjectMocks
private SearchIndexServiceImpl searchIndexService;
@Mock
private SearchIndexStatusDaoHelper searchIndexStatusDaoHelper;
@Mock
private SearchIndexTypeDaoHelper searchIndexTypeDaoHelper;
@Before
public void before()
{
MockitoAnnotations.initMocks(this);
}
@Test
public void testCreateSearchIndex()
{
// Create a search index key.
SearchIndexKey searchIndexKey = new SearchIndexKey(SEARCH_INDEX_NAME);
// Get the search index type value.
String searchIndexType = SearchIndexTypeEntity.SearchIndexTypes.BUS_OBJCT_DFNTN.name();
// Get the search index status value.
String searchIndexStatus = SearchIndexStatusEntity.SearchIndexStatuses.BUILDING.name();
// Create a search index create request.
SearchIndexCreateRequest searchIndexCreateRequest = new SearchIndexCreateRequest(searchIndexKey, searchIndexType);
// Creates a test search index type entity.
SearchIndexTypeEntity searchIndexTypeEntity = new SearchIndexTypeEntity();
searchIndexTypeEntity.setCode(searchIndexType);
// Creates a test search index status entity.
SearchIndexStatusEntity searchIndexStatusEntity = new SearchIndexStatusEntity();
searchIndexStatusEntity.setCode(searchIndexStatus);
// Creates a test search index entity.
SearchIndexEntity searchIndexEntity = new SearchIndexEntity();
searchIndexEntity.setName(SEARCH_INDEX_NAME);
searchIndexEntity.setType(searchIndexTypeEntity);
searchIndexEntity.setStatus(searchIndexStatusEntity);
searchIndexEntity.setCreatedBy(USER_ID);
searchIndexEntity.setCreatedOn(new Timestamp(CREATED_ON.toGregorianCalendar().getTimeInMillis()));
searchIndexEntity.setUpdatedOn(new Timestamp(UPDATED_ON.toGregorianCalendar().getTimeInMillis()));
// Mock some of the external call responses.
@SuppressWarnings("unchecked")
Future<Void> mockedFuture = mock(Future.class);
// Mock the external calls.
when(alternateKeyHelper.validateStringParameter("Search index name", SEARCH_INDEX_NAME)).thenReturn(SEARCH_INDEX_NAME);
when(alternateKeyHelper.validateStringParameter("Search index type", searchIndexType)).thenReturn(searchIndexType);
when(searchIndexDao.getSearchIndexByKey(searchIndexKey)).thenReturn(null);
when(searchIndexTypeDaoHelper.getSearchIndexTypeEntity(searchIndexType)).thenReturn(searchIndexTypeEntity);
when(searchIndexStatusDaoHelper.getSearchIndexStatusEntity(searchIndexStatus)).thenReturn(searchIndexStatusEntity);
when(searchIndexDao.saveAndRefresh(any(SearchIndexEntity.class))).thenReturn(searchIndexEntity);
when(configurationHelper.getProperty(ConfigurationValue.ELASTICSEARCH_BDEF_DOCUMENT_TYPE, String.class)).thenReturn(SEARCH_INDEX_DOCUMENT_TYPE);
when(configurationDaoHelper.getClobProperty(ConfigurationValue.ELASTICSEARCH_BDEF_MAPPINGS_JSON.getKey())).thenReturn(SEARCH_INDEX_MAPPING);
when(configurationDaoHelper.getClobProperty(ConfigurationValue.ELASTICSEARCH_BDEF_SETTINGS_JSON.getKey())).thenReturn(SEARCH_INDEX_SETTINGS);
when(searchFunctions.getIndexExistsFunction()).thenReturn(indexName -> true);
when(searchFunctions.getDeleteIndexFunction()).thenReturn(indexName -> {
});
when(searchFunctions.getCreateIndexFunction()).thenReturn((indexName, documentType, mapping, settings) -> {
});
when(searchIndexHelperService.indexAllBusinessObjectDefinitions(searchIndexKey, SEARCH_INDEX_DOCUMENT_TYPE)).thenReturn(mockedFuture);
// Create a search index.
SearchIndex response = searchIndexService.createSearchIndex(searchIndexCreateRequest);
// Verify the external calls.
verify(alternateKeyHelper).validateStringParameter("Search index name", SEARCH_INDEX_NAME);
verify(alternateKeyHelper).validateStringParameter("Search index type", searchIndexType);
verify(searchIndexDao).getSearchIndexByKey(searchIndexKey);
verify(searchIndexTypeDaoHelper).getSearchIndexTypeEntity(searchIndexType);
verify(searchIndexStatusDaoHelper).getSearchIndexStatusEntity(searchIndexStatus);
verify(searchIndexDao).saveAndRefresh(any(SearchIndexEntity.class));
verify(configurationHelper).getProperty(ConfigurationValue.ELASTICSEARCH_BDEF_DOCUMENT_TYPE, String.class);
verify(configurationDaoHelper).getClobProperty(ConfigurationValue.ELASTICSEARCH_BDEF_MAPPINGS_JSON.getKey());
verify(configurationDaoHelper).getClobProperty(ConfigurationValue.ELASTICSEARCH_BDEF_SETTINGS_JSON.getKey());
verify(searchFunctions).getIndexExistsFunction();
verify(searchFunctions).getDeleteIndexFunction();
verify(searchFunctions).getCreateIndexFunction();
verify(searchIndexHelperService).indexAllBusinessObjectDefinitions(searchIndexKey, SEARCH_INDEX_DOCUMENT_TYPE);
verifyNoMoreInteractions(alternateKeyHelper, businessObjectDefinitionDao, businessObjectDefinitionHelper, configurationDaoHelper, configurationHelper,
searchFunctions, searchIndexDao, searchIndexDaoHelper, searchIndexHelperService, searchIndexStatusDaoHelper, searchIndexTypeDaoHelper);
// Validate the returned object.
assertEquals(new SearchIndex(searchIndexKey, searchIndexType, searchIndexStatus, NO_SEARCH_INDEX_STATISTICS, USER_ID, CREATED_ON, UPDATED_ON),
response);
}
@Test
public void testCreateSearchIndexSearchIndexAlreadyExists()
{
// Create a search index key.
SearchIndexKey searchIndexKey = new SearchIndexKey(SEARCH_INDEX_NAME);
// Mock the external calls.
when(alternateKeyHelper.validateStringParameter("Search index name", SEARCH_INDEX_NAME)).thenReturn(SEARCH_INDEX_NAME);
when(alternateKeyHelper.validateStringParameter("Search index type", SEARCH_INDEX_TYPE)).thenReturn(SEARCH_INDEX_TYPE);
when(searchIndexDao.getSearchIndexByKey(searchIndexKey)).thenReturn(new SearchIndexEntity());
// Try to create a search index when search index entity already exists.
try
{
searchIndexService.createSearchIndex(new SearchIndexCreateRequest(searchIndexKey, SEARCH_INDEX_TYPE));
fail();
}
catch (AlreadyExistsException e)
{
assertEquals(String.format("Unable to create search index with name \"%s\" because it already exists.", SEARCH_INDEX_NAME), e.getMessage());
}
// Verify the external calls.
verify(alternateKeyHelper).validateStringParameter("Search index name", SEARCH_INDEX_NAME);
verify(alternateKeyHelper).validateStringParameter("Search index type", SEARCH_INDEX_TYPE);
verify(searchIndexDao).getSearchIndexByKey(searchIndexKey);
verifyNoMoreInteractions(alternateKeyHelper, businessObjectDefinitionDao, businessObjectDefinitionHelper, configurationDaoHelper, configurationHelper,
searchFunctions, searchIndexDao, searchIndexDaoHelper, searchIndexHelperService, searchIndexStatusDaoHelper, searchIndexTypeDaoHelper);
}
@Test
public void testDeleteSearchIndex()
{
// Create a search index key.
SearchIndexKey searchIndexKey = new SearchIndexKey(SEARCH_INDEX_NAME);
// Create the search index entity.
SearchIndexEntity searchIndexEntity = createTestSearchIndexEntity();
// Mock the external calls.
when(alternateKeyHelper.validateStringParameter("Search index name", SEARCH_INDEX_NAME)).thenReturn(SEARCH_INDEX_NAME);
when(searchIndexDaoHelper.getSearchIndexEntity(searchIndexKey)).thenReturn(searchIndexEntity);
when(searchFunctions.getIndexExistsFunction()).thenReturn(SEARCH_INDEX_NAME -> true);
when(searchFunctions.getDeleteIndexFunction()).thenReturn(SEARCH_INDEX_NAME -> {
});
// Delete a search index.
SearchIndex response = searchIndexService.deleteSearchIndex(searchIndexKey);
// Verify the external calls.
verify(alternateKeyHelper).validateStringParameter("Search index name", SEARCH_INDEX_NAME);
verify(searchIndexDaoHelper).getSearchIndexEntity(searchIndexKey);
verify(searchFunctions).getIndexExistsFunction();
verify(searchFunctions).getDeleteIndexFunction();
verify(searchIndexDao).delete(searchIndexEntity);
verifyNoMoreInteractions(alternateKeyHelper, businessObjectDefinitionDao, businessObjectDefinitionHelper, configurationDaoHelper, configurationHelper,
searchFunctions, searchIndexDao, searchIndexDaoHelper, searchIndexHelperService, searchIndexStatusDaoHelper, searchIndexTypeDaoHelper);
// Validate the returned object.
assertEquals(new SearchIndex(searchIndexKey, SEARCH_INDEX_TYPE, SEARCH_INDEX_STATUS, NO_SEARCH_INDEX_STATISTICS, USER_ID, CREATED_ON, UPDATED_ON),
response);
}
@Test
public void testGetSearchIndex()
{
// Create a search index key.
SearchIndexKey searchIndexKey = new SearchIndexKey(SEARCH_INDEX_NAME);
// Create the search index entity.
SearchIndexEntity searchIndexEntity = createTestSearchIndexEntity();
// Mock some of the external call responses.
AdminClient mockedAdminClient = mock(AdminClient.class);
IndicesAdminClient mockedIndiciesAdminClient = mock(IndicesAdminClient.class);
GetIndexRequestBuilder mockedGetIndexRequestBuilder = mock(GetIndexRequestBuilder.class);
@SuppressWarnings("unchecked")
ListenableActionFuture<GetIndexResponse> mockedListenableActionFutureGetIndexResponse = mock(ListenableActionFuture.class);
GetIndexResponse mockedGetIndexResponse = mock(GetIndexResponse.class);
IndicesStatsRequestBuilder mockedIndicesStatsRequestBuilder = mock(IndicesStatsRequestBuilder.class);
@SuppressWarnings("unchecked")
ListenableActionFuture<IndicesStatsResponse> mockedListenableActionFutureIndicesStatsResponse = mock(ListenableActionFuture.class);
IndicesStatsResponse mockedIndicesStatsResponse = mock(IndicesStatsResponse.class);
IndexStats mockedIndexStats = mock(IndexStats.class);
CommonStats mockedCommonStats = mock(CommonStats.class);
DocsStats mockedDocsStats = mock(DocsStats.class);
// Create a search index get settings response.
ImmutableOpenMap<String, Settings> getIndexResponseSettings = ImmutableOpenMap.<String, Settings>builder().fPut(SEARCH_INDEX_NAME,
Settings.builder().put(IndexMetaData.SETTING_CREATION_DATE, SEARCH_INDEX_STATISTICS_CREATION_DATE.toGregorianCalendar().getTimeInMillis())
.put(IndexMetaData.SETTING_INDEX_UUID, SEARCH_INDEX_STATISTICS_INDEX_UUID).build()).build();
// Mock the external calls.
when(alternateKeyHelper.validateStringParameter("Search index name", SEARCH_INDEX_NAME)).thenReturn(SEARCH_INDEX_NAME);
when(searchIndexDaoHelper.getSearchIndexEntity(searchIndexKey)).thenReturn(searchIndexEntity);
when(searchIndexHelperService.getAdminClient()).thenReturn(mockedAdminClient);
when(mockedAdminClient.indices()).thenReturn(mockedIndiciesAdminClient);
when(mockedIndiciesAdminClient.prepareGetIndex()).thenReturn(mockedGetIndexRequestBuilder);
when(mockedGetIndexRequestBuilder.setIndices(SEARCH_INDEX_NAME)).thenReturn(mockedGetIndexRequestBuilder);
when(mockedGetIndexRequestBuilder.execute()).thenReturn(mockedListenableActionFutureGetIndexResponse);
when(mockedListenableActionFutureGetIndexResponse.actionGet()).thenReturn(mockedGetIndexResponse);
when(mockedGetIndexResponse.getSettings()).thenReturn(getIndexResponseSettings);
when(mockedIndiciesAdminClient.prepareStats(SEARCH_INDEX_NAME)).thenReturn(mockedIndicesStatsRequestBuilder);
when(mockedIndicesStatsRequestBuilder.clear()).thenReturn(mockedIndicesStatsRequestBuilder);
when(mockedIndicesStatsRequestBuilder.setDocs(true)).thenReturn(mockedIndicesStatsRequestBuilder);
when(mockedIndicesStatsRequestBuilder.execute()).thenReturn(mockedListenableActionFutureIndicesStatsResponse);
when(mockedListenableActionFutureIndicesStatsResponse.actionGet()).thenReturn(mockedIndicesStatsResponse);
when(mockedIndicesStatsResponse.getIndex(SEARCH_INDEX_NAME)).thenReturn(mockedIndexStats);
when(mockedIndexStats.getPrimaries()).thenReturn(mockedCommonStats);
when(mockedCommonStats.getDocs()).thenReturn(mockedDocsStats);
when(mockedDocsStats.getCount()).thenReturn(SEARCH_INDEX_STATISTICS_NUMBER_OF_ACTIVE_DOCUMENTS);
when(mockedDocsStats.getDeleted()).thenReturn(SEARCH_INDEX_STATISTICS_NUMBER_OF_DELETED_DOCUMENTS);
// Get a search index.
SearchIndex response = searchIndexService.getSearchIndex(searchIndexKey);
// Verify the external calls.
verify(alternateKeyHelper).validateStringParameter("Search index name", SEARCH_INDEX_NAME);
verify(searchIndexDaoHelper).getSearchIndexEntity(searchIndexKey);
verify(searchIndexHelperService, times(2)).getAdminClient();
verifyNoMoreInteractions(alternateKeyHelper, businessObjectDefinitionDao, businessObjectDefinitionHelper, configurationDaoHelper, configurationHelper,
searchFunctions, searchIndexDao, searchIndexDaoHelper, searchIndexHelperService, searchIndexStatusDaoHelper, searchIndexTypeDaoHelper);
// Validate the returned object.
assertEquals(new SearchIndex(searchIndexKey, SEARCH_INDEX_TYPE, SEARCH_INDEX_STATUS,
new SearchIndexStatistics(SEARCH_INDEX_STATISTICS_CREATION_DATE, SEARCH_INDEX_STATISTICS_NUMBER_OF_ACTIVE_DOCUMENTS,
SEARCH_INDEX_STATISTICS_NUMBER_OF_DELETED_DOCUMENTS, SEARCH_INDEX_STATISTICS_INDEX_UUID), USER_ID, CREATED_ON, UPDATED_ON), response);
}
@Test
public void testGetSearchIndexes()
{
// Create a list of search index keys.
List<SearchIndexKey> searchIndexKeys = Arrays.asList(new SearchIndexKey(SEARCH_INDEX_NAME), new SearchIndexKey(SEARCH_INDEX_NAME_2));
// Mock the external calls.
when(searchIndexDao.getSearchIndexes()).thenReturn(searchIndexKeys);
// Get search indexes.
SearchIndexKeys response = searchIndexService.getSearchIndexes();
// Verify the external calls.
verify(searchIndexDao).getSearchIndexes();
verifyNoMoreInteractions(alternateKeyHelper, businessObjectDefinitionDao, businessObjectDefinitionHelper, configurationDaoHelper, configurationHelper,
searchFunctions, searchIndexDao, searchIndexDaoHelper, searchIndexHelperService, searchIndexStatusDaoHelper, searchIndexTypeDaoHelper);
// Validate the returned object.
assertEquals(new SearchIndexKeys(searchIndexKeys), response);
}
/**
* Creates a test search index entity along with the relative database entities.
*
* @return the search index entity
*/
private SearchIndexEntity createTestSearchIndexEntity()
{
// Creates a test search index type entity.
SearchIndexTypeEntity searchIndexTypeEntity = new SearchIndexTypeEntity();
searchIndexTypeEntity.setCode(SEARCH_INDEX_TYPE);
// Creates a test search index status entity.
SearchIndexStatusEntity searchIndexStatusEntity = new SearchIndexStatusEntity();
searchIndexStatusEntity.setCode(SEARCH_INDEX_STATUS);
// Create a test search index entity.
SearchIndexEntity searchIndexEntity = new SearchIndexEntity();
searchIndexEntity.setName(SEARCH_INDEX_NAME);
searchIndexEntity.setType(searchIndexTypeEntity);
searchIndexEntity.setStatus(searchIndexStatusEntity);
searchIndexEntity.setCreatedBy(USER_ID);
searchIndexEntity.setCreatedOn(new Timestamp(CREATED_ON.toGregorianCalendar().getTimeInMillis()));
searchIndexEntity.setUpdatedOn(new Timestamp(UPDATED_ON.toGregorianCalendar().getTimeInMillis()));
return searchIndexEntity;
}
}