/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.search.elasticsearch.internal.index;
import com.liferay.portal.kernel.test.util.RandomTestUtil;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.search.elasticsearch.index.IndexNameBuilder;
import com.liferay.portal.search.elasticsearch.internal.connection.ElasticsearchFixture;
import com.liferay.portal.search.elasticsearch.internal.connection.IndexName;
import com.liferay.portal.search.elasticsearch.internal.document.SingleFieldFixture;
import com.liferay.portal.search.elasticsearch.internal.util.ResourceUtil;
import com.liferay.portal.search.elasticsearch.settings.BaseIndexSettingsContributor;
import com.liferay.portal.search.elasticsearch.settings.IndexSettingsHelper;
import com.liferay.portal.search.elasticsearch.settings.TypeMappingsHelper;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.elasticsearch.action.admin.indices.get.GetIndexResponse;
import org.elasticsearch.client.AdminClient;
import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.common.collect.ImmutableOpenMap;
import org.elasticsearch.common.settings.Settings;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
/**
* @author André de Oliveira
*/
public class CompanyIndexFactoryTest {
@Before
public void setUp() throws Exception {
_companyIndexFactory = createCompanyIndexFactory();
_elasticsearchFixture = new ElasticsearchFixture(
CompanyIndexFactoryTest.class.getSimpleName());
_elasticsearchFixture.setUp();
_singleFieldFixture = new SingleFieldFixture(
_elasticsearchFixture.getClient(),
new IndexName(getTestIndexName()),
LiferayTypeMappingsConstants.LIFERAY_DOCUMENT_TYPE);
}
@After
public void tearDown() throws Exception {
_elasticsearchFixture.tearDown();
}
@Test
public void testAdditionalIndexConfigurations() throws Exception {
_companyIndexFactory.setAdditionalIndexConfigurations(
"index.number_of_replicas: 1\nindex.number_of_shards: 2");
createIndices();
Settings settings = getIndexSettings();
Assert.assertEquals("1", settings.get("index.number_of_replicas"));
Assert.assertEquals("2", settings.get("index.number_of_shards"));
}
@Test
public void testAdditionalTypeMappings() throws Exception {
_companyIndexFactory.setAdditionalIndexConfigurations(
loadAdditionalAnalyzers());
_companyIndexFactory.setAdditionalTypeMappings(
loadAdditionalTypeMappings());
createIndices();
String field = RandomTestUtil.randomString() + "_ja";
indexOneDocument(field);
assertAnalyzer(field, "kuromoji_liferay_custom");
}
@Test
public void testCreateIndicesWithBlankStrings() throws Exception {
Map<String, Object> properties = new HashMap<>();
properties.put("additionalIndexConfigurations", StringPool.BLANK);
properties.put("additionalTypeMappings", StringPool.SPACE);
_companyIndexFactory.activate(properties);
createIndices();
}
@Test
public void testCreateIndicesWithEmptyConfiguration() throws Exception {
_companyIndexFactory.activate(new HashMap<String, Object>());
createIndices();
}
@Test
public void testDefaultIndexSettings() throws Exception {
createIndices();
Settings settings = getIndexSettings();
Assert.assertEquals("0", settings.get("index.number_of_replicas"));
Assert.assertEquals("1", settings.get("index.number_of_shards"));
}
@Test
public void testDefaultIndices() throws Exception {
_companyIndexFactory.activate(
new HashMap<String, Object>() {
{
put(
"typeMappings.KeywordQueryDocumentType",
"/META-INF/mappings/keyword-query-type-mappings.json");
put(
"typeMappings.SpellCheckDocumentType",
"/META-INF/mappings/spellcheck-type-mappings.json");
}
});
createIndices();
assertIndicesExist(
LiferayTypeMappingsConstants.LIFERAY_DOCUMENT_TYPE,
"KeywordQueryDocumentType", "SpellCheckDocumentType");
}
@Test
public void testIndexSettingsContributor() throws Exception {
_companyIndexFactory.addIndexSettingsContributor(
new BaseIndexSettingsContributor(1) {
@Override
public void populate(IndexSettingsHelper indexSettingsHelper) {
indexSettingsHelper.put("index.number_of_replicas", "2");
indexSettingsHelper.put("index.number_of_shards", "3");
}
});
_companyIndexFactory.setAdditionalIndexConfigurations(
"index.number_of_replicas: 0\nindex.number_of_shards: 0");
createIndices();
Settings settings = getIndexSettings();
Assert.assertEquals("2", settings.get("index.number_of_replicas"));
Assert.assertEquals("3", settings.get("index.number_of_shards"));
}
@Test
public void testIndexSettingsContributorTypeMappings() throws Exception {
final String mappings = loadAdditionalTypeMappings();
_companyIndexFactory.addIndexSettingsContributor(
new BaseIndexSettingsContributor(1) {
@Override
public void contribute(TypeMappingsHelper typeMappingsHelper) {
typeMappingsHelper.addTypeMappings(
getTestIndexName(),
replaceAnalyzer(mappings, "brazilian"));
}
});
_companyIndexFactory.setAdditionalTypeMappings(
replaceAnalyzer(mappings, "portuguese"));
createIndices();
String field = RandomTestUtil.randomString() + "_ja";
indexOneDocument(field);
assertAnalyzer(field, "brazilian");
}
@Test
public void testOverrideTypeMappings() throws Exception {
_companyIndexFactory.setAdditionalIndexConfigurations(
loadAdditionalAnalyzers());
_companyIndexFactory.setOverrideTypeMappings(
loadOverrideTypeMappings());
createIndices();
String field = "title";
indexOneDocument(field);
assertAnalyzer(field, "kuromoji_liferay_custom");
String field2 = "description";
indexOneDocument(field2);
assertNoAnalyzer(field2);
}
@Test
public void testOverrideTypeMappingsHonorDefaultIndices() throws Exception {
_companyIndexFactory.activate(
Collections.<String, Object>singletonMap(
"typeMappings.SpellCheckDocumentType",
"/META-INF/mappings/spellcheck-type-mappings.json"));
_companyIndexFactory.setAdditionalIndexConfigurations(
loadAdditionalAnalyzers());
_companyIndexFactory.setOverrideTypeMappings(
loadOverrideTypeMappings());
createIndices();
assertIndicesExist(
LiferayTypeMappingsConstants.LIFERAY_DOCUMENT_TYPE,
"SpellCheckDocumentType");
}
@Test
public void testOverrideTypeMappingsIgnoreOtherContributions()
throws Exception {
final String mappings = replaceAnalyzer(
loadAdditionalTypeMappings(), RandomTestUtil.randomString());
_companyIndexFactory.addIndexSettingsContributor(
new BaseIndexSettingsContributor(1) {
@Override
public void contribute(TypeMappingsHelper typeMappingsHelper) {
typeMappingsHelper.addTypeMappings(
getTestIndexName(), mappings);
}
});
_companyIndexFactory.setAdditionalIndexConfigurations(
loadAdditionalAnalyzers());
_companyIndexFactory.setAdditionalTypeMappings(mappings);
_companyIndexFactory.setOverrideTypeMappings(
loadOverrideTypeMappings());
createIndices();
String field = RandomTestUtil.randomString() + "_ja";
indexOneDocument(field);
assertNoAnalyzer(field);
}
@Rule
public TestName testName = new TestName();
protected void assertAnalyzer(String field, String analyzer)
throws Exception {
FieldMappingAssert.assertAnalyzer(
analyzer, field, LiferayTypeMappingsConstants.LIFERAY_DOCUMENT_TYPE,
getTestIndexName(), _elasticsearchFixture.getIndicesAdminClient());
}
protected void assertIndicesExist(String... indexNames) {
GetIndexResponse getIndexResponse = _elasticsearchFixture.getIndex(
getTestIndexName());
ImmutableOpenMap<String, ImmutableOpenMap<String, MappingMetaData>>
mappings = getIndexResponse.mappings();
Iterator<ImmutableOpenMap<String, MappingMetaData>> iterator =
mappings.valuesIt();
ImmutableOpenMap<String, MappingMetaData> map = iterator.next();
for (String indexName : indexNames) {
Assert.assertTrue(indexName, map.containsKey(indexName));
}
}
protected void assertNoAnalyzer(String field) throws Exception {
assertAnalyzer(field, null);
}
protected CompanyIndexFactory createCompanyIndexFactory() {
CompanyIndexFactory companyIndexFactory = new CompanyIndexFactory();
companyIndexFactory.indexNameBuilder = new TestIndexNameBuilder();
return companyIndexFactory;
}
protected void createIndices() throws Exception {
AdminClient adminClient = _elasticsearchFixture.getAdminClient();
_companyIndexFactory.createIndices(
adminClient, RandomTestUtil.randomLong());
}
protected Settings getIndexSettings() {
String name = getTestIndexName();
GetIndexResponse getIndexResponse = _elasticsearchFixture.getIndex(
name);
ImmutableOpenMap<String, Settings> immutableOpenMap =
getIndexResponse.getSettings();
return immutableOpenMap.get(name);
}
protected String getTestIndexName() {
IndexName indexName = new IndexName(testName.getMethodName());
return indexName.getName();
}
protected void indexOneDocument(String field) {
_singleFieldFixture.setField(field);
_singleFieldFixture.indexDocument(RandomTestUtil.randomString());
}
protected String loadAdditionalAnalyzers() throws Exception {
return ResourceUtil.getResourceAsString(
getClass(), "CompanyIndexFactoryTest-additionalAnalyzers.json");
}
protected String loadAdditionalTypeMappings() throws Exception {
return ResourceUtil.getResourceAsString(
getClass(), "CompanyIndexFactoryTest-additionalTypeMappings.json");
}
protected String loadOverrideTypeMappings() throws Exception {
return ResourceUtil.getResourceAsString(
getClass(), "CompanyIndexFactoryTest-overrideTypeMappings.json");
}
protected String replaceAnalyzer(String mappings, String analyzer) {
return StringUtil.replace(
mappings, "kuromoji_liferay_custom", analyzer);
}
protected class TestIndexNameBuilder implements IndexNameBuilder {
@Override
public String getIndexName(long companyId) {
return getTestIndexName();
}
}
private CompanyIndexFactory _companyIndexFactory;
private ElasticsearchFixture _elasticsearchFixture;
private SingleFieldFixture _singleFieldFixture;
}