From 7a8d735a7f5007a7e8819cb4ad7e3a1b4ad440e7 Mon Sep 17 00:00:00 2001 From: Tine Kondo Date: Sun, 14 Apr 2019 08:00:23 +0200 Subject: [PATCH] feat(elasticsearch6): add support for Elasticsearch 6.x.x Closes #191 --- .travis.yml | 16 ++ docker-compose.yml | 51 ++++ nosqlunit-demo/pom.xml | 1 + nosqlunit-elasticsearch6/pom.xml | 38 +++ ...efaultElasticsearchComparisonStrategy.java | 25 ++ ...DefaultElasticsearchInsertionStrategy.java | 13 + .../ElasticsearchAssertion.java | 142 ++++++++++ .../ElasticsearchComparisonStrategy.java | 6 + .../ElasticsearchConfiguration.java | 48 ++++ .../ElasticsearchConnectionCallback.java | 7 + .../ElasticsearchInsertionStrategy.java | 6 + .../ElasticsearchOperation.java | 106 +++++++ .../elasticsearch6/ElasticsearchRule.java | 81 ++++++ .../elasticsearch6/EmbeddedElasticsearch.java | 87 ++++++ ...ddedElasticsearchConfigurationBuilder.java | 30 ++ ...EmbeddedElasticsearchInstancesFactory.java | 20 ++ ...EmbeddedElasticsearchLifecycleManager.java | 129 +++++++++ .../LowLevelElasticSearchOperations.java | 32 +++ .../elasticsearch6/ManagedElasticsearch.java | 78 ++++++ ...agedElasticsearchConfigurationBuilder.java | 45 +++ .../ManagedElasticsearchLifecycleManager.java | 258 ++++++++++++++++++ ...moteElasticsearchConfigurationBuilder.java | 52 ++++ .../elasticsearch6/parser/DataReader.java | 121 ++++++++ ...anagedElasticsearchLifecycleIsManaged.java | 178 ++++++++++++ ...dedElasticsearchOperationsAreRequired.java | 109 ++++++++ .../WhenExpectedDataShouldBeCompared.java | 192 +++++++++++++ ...gedElasticsearchOperationsAreRequired.java | 104 +++++++ .../WhenElasticsearchDataIsImported.java | 71 +++++ pom.xml | 98 ++++--- 29 files changed, 2099 insertions(+), 45 deletions(-) create mode 100644 .travis.yml create mode 100644 docker-compose.yml create mode 100644 nosqlunit-elasticsearch6/pom.xml create mode 100644 nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/DefaultElasticsearchComparisonStrategy.java create mode 100644 nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/DefaultElasticsearchInsertionStrategy.java create mode 100644 nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchAssertion.java create mode 100644 nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchComparisonStrategy.java create mode 100644 nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchConfiguration.java create mode 100644 nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchConnectionCallback.java create mode 100644 nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchInsertionStrategy.java create mode 100644 nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchOperation.java create mode 100644 nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchRule.java create mode 100644 nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/EmbeddedElasticsearch.java create mode 100644 nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/EmbeddedElasticsearchConfigurationBuilder.java create mode 100644 nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/EmbeddedElasticsearchInstancesFactory.java create mode 100644 nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/EmbeddedElasticsearchLifecycleManager.java create mode 100644 nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/LowLevelElasticSearchOperations.java create mode 100644 nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ManagedElasticsearch.java create mode 100644 nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ManagedElasticsearchConfigurationBuilder.java create mode 100644 nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ManagedElasticsearchLifecycleManager.java create mode 100644 nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/RemoteElasticsearchConfigurationBuilder.java create mode 100644 nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/parser/DataReader.java create mode 100644 nosqlunit-elasticsearch6/src/test/java/com/lordofthejars/nosqlunit/elasticsearch6/WhenManagedElasticsearchLifecycleIsManaged.java create mode 100644 nosqlunit-elasticsearch6/src/test/java/com/lordofthejars/nosqlunit/elasticsearch6/integration/WhenEmbeddedElasticsearchOperationsAreRequired.java create mode 100644 nosqlunit-elasticsearch6/src/test/java/com/lordofthejars/nosqlunit/elasticsearch6/integration/WhenExpectedDataShouldBeCompared.java create mode 100644 nosqlunit-elasticsearch6/src/test/java/com/lordofthejars/nosqlunit/elasticsearch6/integration/WhenManagedElasticsearchOperationsAreRequired.java create mode 100644 nosqlunit-elasticsearch6/src/test/java/com/lordofthejars/nosqlunit/elasticsearch6/integration/parser/WhenElasticsearchDataIsImported.java diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..3c75446 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,16 @@ +language: java + +services: + - docker + +before_install: + - docker --version + - docker-compose --version + - docker-compose up -d + - docker-compose run wait + - docker-compose run mvn -B -Pintregration-tests clean install + +script: + - mvn -B -Pintegration-tests clean install + + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..fca0cde --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,51 @@ +version: '2.2' +services: + nosqlunit-elasticsearch6.elasticsearch: + image: docker.elastic.co/elasticsearch/elasticsearch:6.7.1 + environment: + - discovery.type=single-node + #- cluster.name=docker-cluster + - bootstrap.memory_lock=true + - "ES_JAVA_OPTS=-Xms512m -Xmx512m" + ulimits: + memlock: + soft: -1 + hard: -1 + #volumes: + # - esdata1:/usr/share/elasticsearch/data + ports: + - 9200:9200 + - 9300:9300 + networks: + nosqlunit-net: + aliases: + - elasticsearch6 + nosqlunit.maven: + image: maven:3.6.0-jdk-8-alpine + stop_signal: SIGKILL + stdin_open: true + tty: true + working_dir: $PWD + volumes: + - $PWD:/usr/src/nosqlunit + - /var/run/docker.sock:/var/run/docker.sock + # Maven cache (optional) + - ~/.m2:/root/.m2 + networks: + nosqlunit-net: + aliases: + - maven + #command: mvn -B -Pintegration-tests clean install + nosqlunit.wait: + image: waisbrot/wait + depends_on: + - nosqlunit.maven + - nosqlunit-elasticsearch6.elasticsearch + environment: + - TARGETS=elasticsearch6:9200 + networks: + nosqlunit-net: + aliases: + - wait +networks: + nosqlunit-net: \ No newline at end of file diff --git a/nosqlunit-demo/pom.xml b/nosqlunit-demo/pom.xml index 46f8f4f..beb3094 100644 --- a/nosqlunit-demo/pom.xml +++ b/nosqlunit-demo/pom.xml @@ -14,6 +14,7 @@ org.apache.maven.plugins maven-deploy-plugin + 2.8.1 true diff --git a/nosqlunit-elasticsearch6/pom.xml b/nosqlunit-elasticsearch6/pom.xml new file mode 100644 index 0000000..5743c4c --- /dev/null +++ b/nosqlunit-elasticsearch6/pom.xml @@ -0,0 +1,38 @@ + + 4.0.0 + + com.lordofthejars + nosqlunit + 1.0.1-SNAPSHOT + + nosqlunit-elasticsearch6 + + + + nosqlunit-core + com.lordofthejars + ${project.version} + + + + org.elasticsearch.client + transport + ${elasticsearch6.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.4 + + 1.8 + 1.8 + + + + + + diff --git a/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/DefaultElasticsearchComparisonStrategy.java b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/DefaultElasticsearchComparisonStrategy.java new file mode 100644 index 0000000..c12c8e8 --- /dev/null +++ b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/DefaultElasticsearchComparisonStrategy.java @@ -0,0 +1,25 @@ +package com.lordofthejars.nosqlunit.elasticsearch6; + +import com.lordofthejars.nosqlunit.core.NoSqlAssertionError; +import com.lordofthejars.nosqlunit.elasticsearch6.parser.DataReader; + +import org.elasticsearch.client.Client; + +import java.io.InputStream; +import java.util.List; +import java.util.Map; + +public class DefaultElasticsearchComparisonStrategy implements ElasticsearchComparisonStrategy { + @Override + public boolean compare(ElasticsearchConnectionCallback connection, InputStream dataset) throws NoSqlAssertionError, + Throwable { + final Client nodeClient = connection.nodeClient(); + final List> documents = DataReader.getDocuments(dataset); + ElasticsearchAssertion.strictAssertEquals(documents, nodeClient); + return true; + } + + @Override + public void setIgnoreProperties(String[] ignoreProperties) { + } +} diff --git a/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/DefaultElasticsearchInsertionStrategy.java b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/DefaultElasticsearchInsertionStrategy.java new file mode 100644 index 0000000..a6df12f --- /dev/null +++ b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/DefaultElasticsearchInsertionStrategy.java @@ -0,0 +1,13 @@ +package com.lordofthejars.nosqlunit.elasticsearch6; + +import java.io.InputStream; + +import com.lordofthejars.nosqlunit.elasticsearch6.parser.DataReader; + +public class DefaultElasticsearchInsertionStrategy implements ElasticsearchInsertionStrategy { + @Override + public void insert(ElasticsearchConnectionCallback connection, InputStream dataset) throws Throwable { + DataReader dataReader = new DataReader(connection.nodeClient()); + dataReader.read(dataset); + } +} diff --git a/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchAssertion.java b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchAssertion.java new file mode 100644 index 0000000..1b69035 --- /dev/null +++ b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchAssertion.java @@ -0,0 +1,142 @@ +package com.lordofthejars.nosqlunit.elasticsearch6; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.codehaus.jackson.map.ObjectMapper; +import org.elasticsearch.action.get.GetRequestBuilder; +import org.elasticsearch.action.get.GetResponse; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.client.Client; +import org.elasticsearch.search.builder.SearchSourceBuilder; + +import com.lordofthejars.nosqlunit.core.FailureHandler; +import com.lordofthejars.nosqlunit.elasticsearch6.parser.DataReader; +import com.lordofthejars.nosqlunit.util.DeepEquals; + +public class ElasticsearchAssertion { + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + private ElasticsearchAssertion() { + super(); + } + + public static void strictAssertEquals(final List> expectedDocuments, final Client client) { + + checkNumberOfDocuments(expectedDocuments, client); + + for (Map document : expectedDocuments) { + final Object object = document.get(DataReader.DOCUMENT_ELEMENT); + + if (object instanceof List) { + @SuppressWarnings("unchecked") + final List> properties = (List>) object; + + final List indexes = new ArrayList<>(); + Map expectedDataOfDocument = new HashMap<>(); + + for (Map property : properties) { + + if (property.containsKey(DataReader.INDEX_ELEMENT)) { + indexes.add(prepareGetIndex(property.get(DataReader.INDEX_ELEMENT), client)); + } else { + if (property.containsKey(DataReader.DATA_ELEMENT)) { + expectedDataOfDocument = dataOfDocument(property.get(DataReader.DATA_ELEMENT)); + } + } + + } + + checkIndicesWithDocument(indexes, expectedDataOfDocument); + + } else { + throw new IllegalArgumentException("Array of Indexes and Data are required."); + } + } + } + + private static void checkIndicesWithDocument(final List indexes, + final Map expectedDataOfDocument) { + for (GetRequestBuilder getRequestBuilder : indexes) { + + GetResponse dataOfDocumentResponse = getRequestBuilder.execute().actionGet(); + + checkExistenceOfDocument(getRequestBuilder, dataOfDocumentResponse); + checkDocumentEquality(expectedDataOfDocument, getRequestBuilder, dataOfDocumentResponse); + + } + } + + private static void checkDocumentEquality(final Map expectedDataOfDocument, + final GetRequestBuilder getRequestBuilder, final GetResponse dataOfDocumentResponse) { + final Map dataOfDocument = new LinkedHashMap<>(dataOfDocumentResponse.getSource()); + + if (!DeepEquals.deepEquals(dataOfDocument, expectedDataOfDocument)) { + try { + throw FailureHandler.createFailure( + "Expected document for index: %s - type: %s - id: %s is %s, but %s was found.", + getRequestBuilder.request().index(), getRequestBuilder.request().type(), + getRequestBuilder.request().id(), OBJECT_MAPPER.writeValueAsString(expectedDataOfDocument), + OBJECT_MAPPER.writeValueAsString(dataOfDocument)); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + } + } + + private static void checkExistenceOfDocument(final GetRequestBuilder getRequestBuilder, + final GetResponse dataOfDocumentResponse) { + if (!dataOfDocumentResponse.isExists()) { + throw FailureHandler.createFailure( + "Document with index: %s - type: %s - id: %s has not returned any document.", + getRequestBuilder.request().index(), getRequestBuilder.request().type(), + getRequestBuilder.request().id()); + } + } + + private static void checkNumberOfDocuments(final List> expectedDocuments, final Client client) { + int expectedNumberOfElements = expectedDocuments.size(); + + long numberOfInsertedDocuments = numberOfInsertedDocuments(client); + + if (expectedNumberOfElements != numberOfInsertedDocuments) { + throw FailureHandler.createFailure("Expected number of documents are %s but %s has been found.", + expectedNumberOfElements, numberOfInsertedDocuments); + } + } + + private static GetRequestBuilder prepareGetIndex(final Object object, final Client client) { + @SuppressWarnings("unchecked") + Map indexInformation = (Map) object; + + GetRequestBuilder prepareGet = client.prepareGet(); + + if (indexInformation.containsKey(DataReader.INDEX_NAME_ELEMENT)) { + prepareGet.setIndex(indexInformation.get(DataReader.INDEX_NAME_ELEMENT)); + } + + if (indexInformation.containsKey(DataReader.INDEX_TYPE_ELEMENT)) { + prepareGet.setType(indexInformation.get(DataReader.INDEX_TYPE_ELEMENT)); + } + + if (indexInformation.containsKey(DataReader.INDEX_ID_ELEMENT)) { + prepareGet.setId(indexInformation.get(DataReader.INDEX_ID_ELEMENT)); + } + + return prepareGet; + } + + @SuppressWarnings("unchecked") + private static Map dataOfDocument(final Object object) { + return (Map) object; + } + + private static long numberOfInsertedDocuments(final Client client) { + SearchResponse response = client.prepareSearch().setSource(new SearchSourceBuilder().size(0)).get(); + return response.getHits().totalHits; + } +} diff --git a/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchComparisonStrategy.java b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchComparisonStrategy.java new file mode 100644 index 0000000..3e44e3f --- /dev/null +++ b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchComparisonStrategy.java @@ -0,0 +1,6 @@ +package com.lordofthejars.nosqlunit.elasticsearch6; + +import com.lordofthejars.nosqlunit.core.ComparisonStrategy; + +public interface ElasticsearchComparisonStrategy extends ComparisonStrategy { +} diff --git a/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchConfiguration.java b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchConfiguration.java new file mode 100644 index 0000000..6bfe691 --- /dev/null +++ b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchConfiguration.java @@ -0,0 +1,48 @@ +package com.lordofthejars.nosqlunit.elasticsearch6; + +import com.lordofthejars.nosqlunit.core.AbstractJsr330Configuration; +import org.elasticsearch.client.Client; +import org.elasticsearch.common.settings.Settings; + +public class ElasticsearchConfiguration extends AbstractJsr330Configuration { + private static final String LOCALHOST = "localhost"; + private static final int DEFAULT_PORT = 9300; + + private String host = LOCALHOST; + private int port = DEFAULT_PORT; + private Settings settings = null; + + private Client client; + + public void setClient(Client client) { + this.client = client; + } + + public Client getClient() { + return client; + } + + public void setPort(int port) { + this.port = port; + } + + public int getPort() { + return port; + } + + public void setSettings(Settings settings) { + this.settings = settings; + } + + public Settings getSettings() { + return settings; + } + + public void setHost(String host) { + this.host = host; + } + + public String getHost() { + return host; + } +} diff --git a/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchConnectionCallback.java b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchConnectionCallback.java new file mode 100644 index 0000000..b698040 --- /dev/null +++ b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchConnectionCallback.java @@ -0,0 +1,7 @@ +package com.lordofthejars.nosqlunit.elasticsearch6; + +import org.elasticsearch.client.Client; + +public interface ElasticsearchConnectionCallback { + Client nodeClient(); +} diff --git a/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchInsertionStrategy.java b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchInsertionStrategy.java new file mode 100644 index 0000000..55167e1 --- /dev/null +++ b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchInsertionStrategy.java @@ -0,0 +1,6 @@ +package com.lordofthejars.nosqlunit.elasticsearch6; + +import com.lordofthejars.nosqlunit.core.InsertionStrategy; + +public interface ElasticsearchInsertionStrategy extends InsertionStrategy { +} diff --git a/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchOperation.java b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchOperation.java new file mode 100644 index 0000000..7369f3f --- /dev/null +++ b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchOperation.java @@ -0,0 +1,106 @@ +package com.lordofthejars.nosqlunit.elasticsearch6; + +import java.io.InputStream; +import java.util.concurrent.TimeUnit; + +import org.elasticsearch.action.bulk.BulkRequestBuilder; +import org.elasticsearch.action.bulk.BulkResponse; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.action.search.SearchType; +import org.elasticsearch.client.Client; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.search.SearchHit; +import org.elasticsearch.search.builder.SearchSourceBuilder; + +import com.lordofthejars.nosqlunit.core.AbstractCustomizableDatabaseOperation; +import com.lordofthejars.nosqlunit.core.NoSqlAssertionError; + +public class ElasticsearchOperation + extends AbstractCustomizableDatabaseOperation { + + private Client client; + + public ElasticsearchOperation(final Client client) { + this.client = client; + setInsertionStrategy(new DefaultElasticsearchInsertionStrategy()); + setComparisonStrategy(new DefaultElasticsearchComparisonStrategy()); + } + + @Override + public void insert(final InputStream dataScript) { + insertData(dataScript); + } + + private void insertData(final InputStream dataScript) { + try { + executeInsertion(() -> client, dataScript); + } catch (Throwable e) { + throw new IllegalArgumentException(e); + } + } + + @Override + public void deleteAll() { + clearDocuments(); + } + + private void clearDocuments() { + if (isAnyIndexPresent()) { + final SearchResponse countResponse = client.prepareSearch().setSearchType(SearchType.QUERY_THEN_FETCH) + .setQuery(QueryBuilders.matchAllQuery()).setSize(0).execute().actionGet(); + + Long docCount = countResponse.getHits().totalHits; + final SearchResponse scrollResponse = client.prepareSearch().setSearchType(SearchType.DEFAULT) + .setScroll(new TimeValue(1L, TimeUnit.MINUTES)).setQuery(QueryBuilders.matchAllQuery()) + .setSize(docCount.intValue()).execute().actionGet(); + + final BulkRequestBuilder bulkRequestBuilder = client.prepareBulk(); + while (true) { + final SearchResponse searchResponse = client.prepareSearchScroll(scrollResponse.getScrollId()) + .setScroll(new TimeValue(1L, TimeUnit.MINUTES)).execute().actionGet(); + + for (SearchHit hit : searchResponse.getHits().getHits()) { + bulkRequestBuilder.add(client.prepareDelete(hit.getIndex(), hit.getType(), hit.getId())); + } + + // Break condition: No hits are returned + if (searchResponse.getHits().getHits().length == 0) { + break; + } + } + + if (bulkRequestBuilder.numberOfActions() > 0) { + final BulkResponse bulkResponse = bulkRequestBuilder.execute().actionGet(); + } + + refreshNode(); + } + + } + + private boolean isAnyIndexPresent() { + SearchResponse response = client.prepareSearch().setSource(new SearchSourceBuilder().size(0)).get(); + return response.getHits().totalHits > 0; + } + + private void refreshNode() { + client.admin().indices().prepareRefresh().execute().actionGet(); + } + + @Override + public boolean databaseIs(final InputStream expectedData) { + try { + return executeComparison(() -> client, expectedData); + } catch (NoSqlAssertionError e) { + throw e; + } catch (Throwable e) { + throw new IllegalStateException(e); + } + } + + @Override + public Client connectionManager() { + return client; + } +} diff --git a/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchRule.java b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchRule.java new file mode 100644 index 0000000..73d4ccf --- /dev/null +++ b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ElasticsearchRule.java @@ -0,0 +1,81 @@ +package com.lordofthejars.nosqlunit.elasticsearch6; + + +import com.lordofthejars.nosqlunit.core.AbstractNoSqlTestRule; +import com.lordofthejars.nosqlunit.core.DatabaseOperation; +import org.elasticsearch.client.Client; + +public class ElasticsearchRule extends AbstractNoSqlTestRule { + + private static final String EXTENSION = "json"; + + private DatabaseOperation databaseOperation; + + public static class ElasticsearchRuleBuilder { + + private ElasticsearchConfiguration elasticsearchConfiguration; + private Object target; + + private ElasticsearchRuleBuilder() { + } + + public static ElasticsearchRuleBuilder newElasticsearchRule() { + return new ElasticsearchRuleBuilder(); + } + + public ElasticsearchRuleBuilder configure(ElasticsearchConfiguration elasticsearchConfiguration) { + this.elasticsearchConfiguration = elasticsearchConfiguration; + return this; + } + + public ElasticsearchRuleBuilder unitInstance(Object target) { + this.target = target; + return this; + } + + public ElasticsearchRule defaultEmbeddedElasticsearch() { + return new ElasticsearchRule(EmbeddedElasticsearchConfigurationBuilder.embeddedElasticsearch().build()); + } + + public ElasticsearchRule defaultManagedElasticsearch() { + return new ElasticsearchRule(ManagedElasticsearchConfigurationBuilder.managedElasticsearch().build()); + } + + public ElasticsearchRule build() { + + if (this.elasticsearchConfiguration == null) { + throw new IllegalArgumentException("Configuration object should be provided."); + } + + return new ElasticsearchRule(elasticsearchConfiguration, target); + } + + } + + public ElasticsearchRule(ElasticsearchConfiguration elasticsearchConfiguration) { + super(elasticsearchConfiguration.getConnectionIdentifier()); + this.databaseOperation = new ElasticsearchOperation(elasticsearchConfiguration.getClient()); + } + + /*With JUnit 10 is impossible to get target from a Rule, it seems that future versions will support it. For now constructor is apporach is the only way.*/ + public ElasticsearchRule(ElasticsearchConfiguration elasticsearchConfiguration, Object target) { + this(elasticsearchConfiguration); + setTarget(target); + } + + @Override + public DatabaseOperation getDatabaseOperation() { + return this.databaseOperation; + } + + @Override + public String getWorkingExtension() { + return EXTENSION; + } + + @Override + public void close() { + this.databaseOperation.connectionManager().close(); + } + +} diff --git a/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/EmbeddedElasticsearch.java b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/EmbeddedElasticsearch.java new file mode 100644 index 0000000..d32ec52 --- /dev/null +++ b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/EmbeddedElasticsearch.java @@ -0,0 +1,87 @@ +package com.lordofthejars.nosqlunit.elasticsearch6; + +import org.elasticsearch.common.settings.Settings; +import org.junit.rules.ExternalResource; + +import java.io.File; + +public class EmbeddedElasticsearch extends ExternalResource { + + private EmbeddedElasticsearch() { + super(); + } + + protected EmbeddedElasticsearchLifecycleManager elasticsearchLifecycleManager; + + public static class EmbeddedElasticsearchRuleBuilder { + + private EmbeddedElasticsearchLifecycleManager elasticsearchLifecycleManager; + + private EmbeddedElasticsearchRuleBuilder() { + this.elasticsearchLifecycleManager = new EmbeddedElasticsearchLifecycleManager(); + } + + public static EmbeddedElasticsearchRuleBuilder newEmbeddedElasticsearchRule() { + return new EmbeddedElasticsearchRuleBuilder(); + } + + public EmbeddedElasticsearchRuleBuilder homePath(File homePath) { + this.elasticsearchLifecycleManager.setHomePath(homePath); + return this; + } + + public EmbeddedElasticsearchRuleBuilder targetPath(File targetPath) { + this.elasticsearchLifecycleManager.setDataPath(targetPath); + return this; + } + + public EmbeddedElasticsearchRuleBuilder clusterName(String clusterName) { + this.elasticsearchLifecycleManager.setClusterName(clusterName); + return this; + } + + public EmbeddedElasticsearchRuleBuilder client(boolean client) { + this.elasticsearchLifecycleManager.setClient(client); + return this; + } + + public EmbeddedElasticsearchRuleBuilder settings(Settings settings) { + this.elasticsearchLifecycleManager.setSettings(settings); + return this; + } + + public EmbeddedElasticsearchRuleBuilder local(boolean local) { + this.elasticsearchLifecycleManager.setLocal(local); + return this; + } + + public EmbeddedElasticsearchRuleBuilder data(boolean data) { + this.elasticsearchLifecycleManager.setData(data); + return this; + } + + public EmbeddedElasticsearch build() { + + if (this.elasticsearchLifecycleManager.getDataPath() == null) { + throw new IllegalArgumentException("No Path to Embedded Elasticsearch is provided."); + } + + EmbeddedElasticsearch embeddedElasticsearch = new EmbeddedElasticsearch(); + embeddedElasticsearch.elasticsearchLifecycleManager = this.elasticsearchLifecycleManager; + + return embeddedElasticsearch; + + } + + } + + @Override + protected void before() throws Throwable { + this.elasticsearchLifecycleManager.startEngine(); + } + + @Override + protected void after() { + this.elasticsearchLifecycleManager.stopEngine(); + } +} diff --git a/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/EmbeddedElasticsearchConfigurationBuilder.java b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/EmbeddedElasticsearchConfigurationBuilder.java new file mode 100644 index 0000000..8e2abf5 --- /dev/null +++ b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/EmbeddedElasticsearchConfigurationBuilder.java @@ -0,0 +1,30 @@ +package com.lordofthejars.nosqlunit.elasticsearch6; + +import com.lordofthejars.nosqlunit.core.FailureHandler; +import org.elasticsearch.node.Node; + +public class EmbeddedElasticsearchConfigurationBuilder { + + private ElasticsearchConfiguration elasticsearchConfiguration = new ElasticsearchConfiguration(); + + public static EmbeddedElasticsearchConfigurationBuilder embeddedElasticsearch() { + return new EmbeddedElasticsearchConfigurationBuilder(); + } + + public EmbeddedElasticsearchConfigurationBuilder connectionIdentifier(String connectionIdentifier) { + elasticsearchConfiguration.setConnectionIdentifier(connectionIdentifier); + return this; + } + + public ElasticsearchConfiguration build() { + + Node defaultEmbeddedInstance = EmbeddedElasticsearchInstancesFactory.getInstance().getDefaultEmbeddedInstance(); + + if (defaultEmbeddedInstance == null) { + throw FailureHandler.createIllegalStateFailure("There is no EmbeddedElasticsearch rule with default target defined during test execution. Please create one using @Rule or @ClassRule before executing these tests."); + } + + this.elasticsearchConfiguration.setClient(defaultEmbeddedInstance.client()); + return this.elasticsearchConfiguration; + } +} diff --git a/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/EmbeddedElasticsearchInstancesFactory.java b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/EmbeddedElasticsearchInstancesFactory.java new file mode 100644 index 0000000..bea6a71 --- /dev/null +++ b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/EmbeddedElasticsearchInstancesFactory.java @@ -0,0 +1,20 @@ +package com.lordofthejars.nosqlunit.elasticsearch6; + +import com.lordofthejars.nosqlunit.util.EmbeddedInstances; +import org.elasticsearch.node.Node; + +public class EmbeddedElasticsearchInstancesFactory { + private static EmbeddedInstances embeddedInstances; + + private EmbeddedElasticsearchInstancesFactory() { + } + + public synchronized static EmbeddedInstances getInstance() { + if (embeddedInstances == null) { + embeddedInstances = new EmbeddedInstances<>(); + } + + return embeddedInstances; + } + +} diff --git a/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/EmbeddedElasticsearchLifecycleManager.java b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/EmbeddedElasticsearchLifecycleManager.java new file mode 100644 index 0000000..9b4aa4a --- /dev/null +++ b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/EmbeddedElasticsearchLifecycleManager.java @@ -0,0 +1,129 @@ +package com.lordofthejars.nosqlunit.elasticsearch6; + +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; + +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.node.Node; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.lordofthejars.nosqlunit.core.AbstractLifecycleManager; + +public class EmbeddedElasticsearchLifecycleManager extends AbstractLifecycleManager { + private static final Logger LOGGER = LoggerFactory.getLogger(EmbeddedElasticsearchLifecycleManager.class); + private static final String LOCALHOST = "127.0.0.1"; + private static final int DEFAULT_PORT = 9300; + private static final String HOME_PATH_PROPERTY = "path.home"; + private static final String DATA_PATH_PROPERTY = "path.data"; + + public static final File EMBEDDED_ELASTICSEARCH_HOME_PATH = createTempEsFolder(); + public static final File EMBEDDED_ELASTICSEARCH_DATA_PATH = new File(EMBEDDED_ELASTICSEARCH_HOME_PATH, "data"); + + private File homePath = EMBEDDED_ELASTICSEARCH_HOME_PATH; + private File dataPath = EMBEDDED_ELASTICSEARCH_DATA_PATH; + + private Settings.Builder settingsBuilder; + + public EmbeddedElasticsearchLifecycleManager() { + settingsBuilder = Settings.builder().put("node.local", true); + } + + @Override + public String getHost() { + return LOCALHOST + dataPath; + } + + @Override + public int getPort() { + return DEFAULT_PORT; + } + + @Override + public void doStart() throws Throwable { + LOGGER.info("Starting Embedded Elasticsearch instance."); + + settingsBuilder.put(HOME_PATH_PROPERTY, homePath.getAbsolutePath()).put(DATA_PATH_PROPERTY, + dataPath.getAbsolutePath()); + Node node = elasticsearchNode(); + EmbeddedElasticsearchInstancesFactory.getInstance().addEmbeddedInstance(node, dataPath.getAbsolutePath()); + + LOGGER.info("Started Embedded Elasticsearch instance."); + } + + private Node elasticsearchNode() { + return new Node(settingsBuilder.build()) { + + @Override + protected void registerDerivedNodeNameWithLogger(final String nodeName) { + + } + }; + } + + @Override + public void doStop() { + LOGGER.info("Stopping Embedded Elasticsearch instance."); + + Node node = EmbeddedElasticsearchInstancesFactory.getInstance() + .getEmbeddedByTargetPath(dataPath.getAbsolutePath()); + + if (node != null) { + try { + node.close(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + EmbeddedElasticsearchInstancesFactory.getInstance().removeEmbeddedInstance(dataPath.getAbsolutePath()); + LOGGER.info("Stopped Embedded Elasticsearch instance."); + + } + + public void setSettings(final Settings settings) { + settingsBuilder.put(settings); + } + + public void setClient(final boolean client) { + settingsBuilder.put("node.client", client); + } + + public void setClusterName(final String clusterName) { + settingsBuilder.put("cluster.name", clusterName); + } + + public void setData(final boolean data) { + settingsBuilder.put("node.data", data); + } + + public void setLocal(final boolean local) { + settingsBuilder.put("node.local", local); + } + + public File getDataPath() { + return dataPath; + } + + public void setDataPath(final File dataPath) { + this.dataPath = dataPath; + } + + public File getHomePath() { + return homePath; + } + + public void setHomePath(final File homePath) { + this.homePath = homePath; + } + + private static File createTempEsFolder() { + try { + return Files.createTempDirectory("es").toFile(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } +} diff --git a/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/LowLevelElasticSearchOperations.java b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/LowLevelElasticSearchOperations.java new file mode 100644 index 0000000..59b3667 --- /dev/null +++ b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/LowLevelElasticSearchOperations.java @@ -0,0 +1,32 @@ +package com.lordofthejars.nosqlunit.elasticsearch6; + +import java.net.InetSocketAddress; +import java.util.concurrent.TimeUnit; + +import org.elasticsearch.client.transport.TransportClient; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.transport.TransportAddress; +import org.elasticsearch.transport.client.PreBuiltTransportClient; + +public class LowLevelElasticSearchOperations { + private static final int NUM_RETRIES_TO_CHECK_SERVER_UP = 3; + + public boolean assertThatConnectionToElasticsearchIsPossible(final Settings settings, final String host, + final int port) throws InterruptedException { + final InetSocketAddress address = new InetSocketAddress(host, port); + + try (TransportClient transportClient = new PreBuiltTransportClient(settings)) { + transportClient.addTransportAddress(new TransportAddress(address)); + for (int i = 0; i < NUM_RETRIES_TO_CHECK_SERVER_UP; i++) { + try { + transportClient.admin().cluster().prepareState().execute().actionGet(); + return true; + } catch (Exception e) { + TimeUnit.SECONDS.sleep(7); + } + } + } + + return false; + } +} diff --git a/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ManagedElasticsearch.java b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ManagedElasticsearch.java new file mode 100644 index 0000000..3ead331 --- /dev/null +++ b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ManagedElasticsearch.java @@ -0,0 +1,78 @@ +package com.lordofthejars.nosqlunit.elasticsearch6; + +import org.junit.rules.ExternalResource; + +public class ManagedElasticsearch extends ExternalResource { + + private ManagedElasticsearch() { + super(); + } + + protected ManagedElasticsearchLifecycleManager managedElasticsearchLifecycleManager; + + public static class ManagedElasticsearchRuleBuilder { + + private ManagedElasticsearchLifecycleManager managedElasticsearchLifecycleManager; + + private ManagedElasticsearchRuleBuilder() { + this.managedElasticsearchLifecycleManager = new ManagedElasticsearchLifecycleManager(); + } + + public static ManagedElasticsearchRuleBuilder newManagedElasticsearchRule() { + return new ManagedElasticsearchRuleBuilder(); + } + + public ManagedElasticsearchRuleBuilder elasticsearchPath(String elasticsearchPath) { + this.managedElasticsearchLifecycleManager.setElasticsearchPath(elasticsearchPath); + return this; + } + + public ManagedElasticsearchRuleBuilder port(int port) { + this.managedElasticsearchLifecycleManager.setPort(port); + return this; + } + + + public ManagedElasticsearchRuleBuilder targetPath(String targetPath) { + this.managedElasticsearchLifecycleManager.setTargetPath(targetPath); + return this; + } + + + public ManagedElasticsearchRuleBuilder appendCommandLineArguments( + String argumentName, String argumentValue) { + this.managedElasticsearchLifecycleManager.addExtraCommandLineArgument(argumentName, + argumentValue); + return this; + } + + public ManagedElasticsearchRuleBuilder appendSingleCommandLineArguments( + String argument) { + this.managedElasticsearchLifecycleManager.addSingleCommandLineArgument(argument); + return this; + } + + + public ManagedElasticsearch build() { + if (this.managedElasticsearchLifecycleManager.getElasticsearchPath() == null) { + throw new IllegalArgumentException( + "No Path to Elasticsearch is provided."); + } + + ManagedElasticsearch managedElasticsearch = new ManagedElasticsearch(); + managedElasticsearch.managedElasticsearchLifecycleManager = this.managedElasticsearchLifecycleManager; + + return managedElasticsearch; + } + } + + @Override + protected void before() throws Throwable { + this.managedElasticsearchLifecycleManager.startEngine(); + } + + @Override + protected void after() { + this.managedElasticsearchLifecycleManager.stopEngine(); + } +} diff --git a/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ManagedElasticsearchConfigurationBuilder.java b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ManagedElasticsearchConfigurationBuilder.java new file mode 100644 index 0000000..4f3c4fd --- /dev/null +++ b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ManagedElasticsearchConfigurationBuilder.java @@ -0,0 +1,45 @@ +package com.lordofthejars.nosqlunit.elasticsearch6; + +import java.net.InetSocketAddress; + +import org.elasticsearch.client.transport.TransportClient; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.transport.TransportAddress; +import org.elasticsearch.transport.client.PreBuiltTransportClient; + +public class ManagedElasticsearchConfigurationBuilder { + private ElasticsearchConfiguration elasticsearchConfiguration = new ElasticsearchConfiguration(); + + private ManagedElasticsearchConfigurationBuilder() { + super(); + } + + public static ManagedElasticsearchConfigurationBuilder managedElasticsearch() { + return new ManagedElasticsearchConfigurationBuilder(); + } + + public ManagedElasticsearchConfigurationBuilder port(final int port) { + this.elasticsearchConfiguration.setPort(port); + return this; + } + + public ManagedElasticsearchConfigurationBuilder settings(final Settings settings) { + this.elasticsearchConfiguration.setSettings(settings); + return this; + } + + public ManagedElasticsearchConfigurationBuilder connectionIdentifier(final String connectionIdentifier) { + this.elasticsearchConfiguration.setConnectionIdentifier(connectionIdentifier); + return this; + } + + public ElasticsearchConfiguration build() { + final InetSocketAddress address = new InetSocketAddress(this.elasticsearchConfiguration.getHost(), + this.elasticsearchConfiguration.getPort()); + final TransportClient client = new PreBuiltTransportClient(this.elasticsearchConfiguration.getSettings()) + .addTransportAddress(new TransportAddress(address)); + this.elasticsearchConfiguration.setClient(client); + + return this.elasticsearchConfiguration; + } +} diff --git a/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ManagedElasticsearchLifecycleManager.java b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ManagedElasticsearchLifecycleManager.java new file mode 100644 index 0000000..044d52d --- /dev/null +++ b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/ManagedElasticsearchLifecycleManager.java @@ -0,0 +1,258 @@ +package com.lordofthejars.nosqlunit.elasticsearch6; + +import static com.lordofthejars.nosqlunit.core.IOUtils.deleteDir; + +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CountDownLatch; + +import org.elasticsearch.common.settings.Settings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.lordofthejars.nosqlunit.core.AbstractLifecycleManager; +import com.lordofthejars.nosqlunit.core.CommandLineExecutor; +import com.lordofthejars.nosqlunit.core.OperatingSystem; +import com.lordofthejars.nosqlunit.core.OperatingSystemFamily; +import com.lordofthejars.nosqlunit.core.OperatingSystemResolver; +import com.lordofthejars.nosqlunit.core.OsNameSystemPropertyOperatingSystemResolver; +import com.lordofthejars.nosqlunit.env.SystemEnvironmentVariables; + +public class ManagedElasticsearchLifecycleManager extends AbstractLifecycleManager { + private static final Logger LOGGER = LoggerFactory.getLogger(ManagedElasticsearchLifecycleManager.class); + + private static final Settings DEFAULT_SETTINGS = Settings.EMPTY; + private static final String DEFAULT_HOST = "localhost"; + protected static final int DEFAULT_PORT = 9300; + protected static final String DEFAULT_ELASTICSEARCH_TARGET_PATH = createTempEsFolder(); + protected static final String FOREGROUND_OPTION = "-f"; + private static final String ELASTICSEARCH_BINARY_DIRECTORY = "bin"; + + private static final String ELASTICSEARCH_EXECUTABLE_X = "elasticsearch"; + private static final String ELASTICSEARCH_EXECUTABLE_W = "elasticsearch.bat"; + + private Map extraCommandArguments = new HashMap(); + private List singleCommandArguments = new ArrayList(); + + private CommandLineExecutor commandLineExecutor = new CommandLineExecutor(); + private OperatingSystemResolver operatingSystemResolver = new OsNameSystemPropertyOperatingSystemResolver(); + private LowLevelElasticSearchOperations lowLevelElasticSearchOperations = new LowLevelElasticSearchOperations(); + + private String elasticsearchPath = SystemEnvironmentVariables.getEnvironmentOrPropertyVariable("ES_HOME"); + private int port = DEFAULT_PORT; + + private String targetPath = DEFAULT_ELASTICSEARCH_TARGET_PATH; + + private ProcessRunnable processRunnable; + + public ManagedElasticsearchLifecycleManager() { + super(); + } + + @Override + public String getHost() { + return DEFAULT_HOST; + } + + @Override + public int getPort() { + return port; + } + + @Override + public void doStart() throws Throwable { + + LOGGER.info("Starting {} Elasticsearch instance.", elasticsearchPath); + + File dbPath = ensureDbPathDoesNotExitsAndReturnCompositePath(); + + if (dbPath.mkdirs()) { + startElasticsearchAsADaemon(); + boolean isServerUp = this.lowLevelElasticSearchOperations + .assertThatConnectionToElasticsearchIsPossible(DEFAULT_SETTINGS, DEFAULT_HOST, DEFAULT_PORT); + + if (!isServerUp) { + throw new IllegalStateException("Couldn't establish a connection with " + this.elasticsearchPath + + " server at /127.0.0.1:" + port); + } + + } else { + throw new IllegalStateException("Db Path " + dbPath + " could not be created."); + } + + LOGGER.info("Started {} Elasticsearch instance.", elasticsearchPath); + } + + private void startElasticsearchAsADaemon() throws InterruptedException { + CountDownLatch processIsReady = new CountDownLatch(1); + processRunnable = new ProcessRunnable(processIsReady); + Thread thread = new Thread(processRunnable); + thread.start(); + processIsReady.await(); + } + + @Override + public void doStop() { + LOGGER.info("Stopping {} Elasticsearch instance.", elasticsearchPath); + + try { + if (this.processRunnable != null) { + this.processRunnable.destroyProcess(); + } + } finally { + ensureDbPathDoesNotExitsAndReturnCompositePath(); + } + + LOGGER.info("Stopped {} Elasticsearch instance.", elasticsearchPath); + } + + private List buildOperationSystemProgramAndArguments() { + + List programAndArguments = new ArrayList(); + + programAndArguments.add(getExecutablePath()); + + if (isXBased()) { + programAndArguments.add(FOREGROUND_OPTION); + } + + for (String argument : this.singleCommandArguments) { + programAndArguments.add(argument); + } + + for (String argumentName : this.extraCommandArguments.keySet()) { + programAndArguments.add(argumentName); + programAndArguments.add(this.extraCommandArguments.get(argumentName)); + } + + return programAndArguments; + + } + + private boolean isXBased() { + OperatingSystemFamily family = this.operatingSystemResolver.currentOperatingSystem().getFamily(); + return family != OperatingSystemFamily.WINDOWS; + } + + private String getExecutablePath() { + return this.elasticsearchPath + File.separatorChar + ELASTICSEARCH_BINARY_DIRECTORY + File.separatorChar + + elasticsearchExecutable(); + } + + private File ensureDbPathDoesNotExitsAndReturnCompositePath() { + File dbPath = new File(targetPath); + if (dbPath.exists()) { + deleteDir(dbPath); + } + return dbPath; + } + + private String elasticsearchExecutable() { + OperatingSystem operatingSystem = this.operatingSystemResolver.currentOperatingSystem(); + + switch (operatingSystem.getFamily()) { + case WINDOWS: + return ELASTICSEARCH_EXECUTABLE_W; + default: + return ELASTICSEARCH_EXECUTABLE_X; + } + + } + + public void setPort(final int port) { + this.port = port; + } + + public void setElasticsearchPath(final String elasticsearchPath) { + this.elasticsearchPath = elasticsearchPath; + } + + public void setTargetPath(final String targetPath) { + this.targetPath = targetPath; + } + + public void addExtraCommandLineArgument(final String argumentName, final String argumentValue) { + this.extraCommandArguments.put(argumentName, argumentValue); + } + + public void addSingleCommandLineArgument(final String argument) { + this.singleCommandArguments.add(argument); + } + + public String getElasticsearchPath() { + return elasticsearchPath; + } + + protected void setCommandLineExecutor(final CommandLineExecutor commandLineExecutor) { + this.commandLineExecutor = commandLineExecutor; + } + + protected void setOperatingSystemResolver(final OperatingSystemResolver operatingSystemResolver) { + this.operatingSystemResolver = operatingSystemResolver; + } + + protected void setLowLevelElasticSearchOperations( + final LowLevelElasticSearchOperations lowLevelElasticSearchOperations) { + this.lowLevelElasticSearchOperations = lowLevelElasticSearchOperations; + } + + public class ProcessRunnable implements Runnable { + + private CountDownLatch processIsReady; + + private Process process; + + public ProcessRunnable(final CountDownLatch processIsReady) { + this.processIsReady = processIsReady; + } + + @Override + public void run() { + try { + process = startProcess(); + } catch (IOException e) { + throw prepareException(e); + } finally { + processIsReady.countDown(); + } + + try { + process.waitFor(); + + } catch (InterruptedException ie) { + throw prepareException(ie); + } + + } + + public void destroyProcess() { + if (this.process != null) { + this.process.destroy(); + } + } + + private IllegalStateException prepareException(final Exception e) { + return new IllegalStateException("Elasticsearch [" + elasticsearchPath + + "] could not be started. Next console message was thrown: " + e.getMessage()); + } + + private Process startProcess() throws IOException { + return commandLineExecutor.startProcessInDirectoryAndArguments(targetPath, + buildOperationSystemProgramAndArguments()); + } + } + + private static String createTempEsFolder() { + try { + return Files.createTempDirectory("es").toFile().getAbsolutePath(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } +} diff --git a/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/RemoteElasticsearchConfigurationBuilder.java b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/RemoteElasticsearchConfigurationBuilder.java new file mode 100644 index 0000000..20f433b --- /dev/null +++ b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/RemoteElasticsearchConfigurationBuilder.java @@ -0,0 +1,52 @@ +package com.lordofthejars.nosqlunit.elasticsearch6; + +import java.net.InetSocketAddress; + +import org.elasticsearch.client.transport.TransportClient; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.transport.TransportAddress; +import org.elasticsearch.transport.client.PreBuiltTransportClient; + +public class RemoteElasticsearchConfigurationBuilder { + + private ElasticsearchConfiguration elasticsearchConfiguration = new ElasticsearchConfiguration(); + + private RemoteElasticsearchConfigurationBuilder() { + super(); + } + + public static RemoteElasticsearchConfigurationBuilder remoteElasticsearch() { + return new RemoteElasticsearchConfigurationBuilder(); + } + + public RemoteElasticsearchConfigurationBuilder port(final int port) { + this.elasticsearchConfiguration.setPort(port); + return this; + } + + public RemoteElasticsearchConfigurationBuilder host(final String host) { + this.elasticsearchConfiguration.setHost(host); + return this; + } + + public RemoteElasticsearchConfigurationBuilder settings(final Settings settings) { + this.elasticsearchConfiguration.setSettings(settings); + return this; + } + + public RemoteElasticsearchConfigurationBuilder connectionIdentifier(final String connectionIdentifier) { + this.elasticsearchConfiguration.setConnectionIdentifier(connectionIdentifier); + return this; + } + + public ElasticsearchConfiguration build() { + final InetSocketAddress address = new InetSocketAddress(this.elasticsearchConfiguration.getHost(), + this.elasticsearchConfiguration.getPort()); + final TransportClient client = new PreBuiltTransportClient(this.elasticsearchConfiguration.getSettings()) + .addTransportAddress(new TransportAddress(address)); + this.elasticsearchConfiguration.setClient(client); + + return this.elasticsearchConfiguration; + } + +} diff --git a/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/parser/DataReader.java b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/parser/DataReader.java new file mode 100644 index 0000000..b5fc248 --- /dev/null +++ b/nosqlunit-elasticsearch6/src/main/java/com/lordofthejars/nosqlunit/elasticsearch6/parser/DataReader.java @@ -0,0 +1,121 @@ +package com.lordofthejars.nosqlunit.elasticsearch6.parser; + +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.type.TypeReference; +import org.elasticsearch.action.index.IndexRequestBuilder; +import org.elasticsearch.client.Client; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class DataReader { + private static final ObjectMapper MAPPER = new ObjectMapper(); + + public static final String DOCUMENTS_ELEMENT = "documents"; + public static final String DOCUMENT_ELEMENT = "document"; + public static final String DATA_ELEMENT = "data"; + public static final String INDEX_ELEMENT = "index"; + public static final String INDEX_NAME_ELEMENT = "indexName"; + public static final String INDEX_TYPE_ELEMENT = "indexType"; + public static final String INDEX_ID_ELEMENT = "indexId"; + + private Client client; + + public DataReader(Client client) { + this.client = client; + } + + public void read(InputStream data) { + try { + final List> documents = getDocuments(data); + insertDocuments(documents); + refreshNode(); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + } + + private void refreshNode() { + client.admin().indices().prepareRefresh().execute().actionGet(); + } + + private void insertDocuments(List> documents) { + for (Map document : documents) { + final Object object = document.get(DOCUMENT_ELEMENT); + + if (object instanceof List) { + @SuppressWarnings("unchecked") + final List> properties = (List>) object; + insertDocument(properties); + } else { + throw new IllegalArgumentException("Array of Indexes and Data are required."); + } + } + } + + private void insertDocument(List> properties) { + final List indexes = new ArrayList<>(); + Map dataOfDocument = new HashMap<>(); + + for (Map property : properties) { + if (property.containsKey(INDEX_ELEMENT)) { + indexes.add(createIndex(property.get(INDEX_ELEMENT))); + } else { + if (property.containsKey(DATA_ELEMENT)) { + dataOfDocument = dataOfDocument(property.get(DATA_ELEMENT)); + } + } + } + + insertIndexes(indexes, dataOfDocument); + } + + private void insertIndexes(List indexes, Map dataOfDocument) { + for (IndexRequestBuilder indexRequestBuilder : indexes) { + indexRequestBuilder.setSource(dataOfDocument).execute().actionGet(); + } + } + + @SuppressWarnings("unchecked") + private Map dataOfDocument(Object object) { + return (Map) object; + } + + private IndexRequestBuilder createIndex(Object object) { + @SuppressWarnings("unchecked") + final Map indexInformation = (Map) object; + + final IndexRequestBuilder prepareIndex = client.prepareIndex(); + + if (indexInformation.containsKey(INDEX_NAME_ELEMENT)) { + prepareIndex.setIndex(indexInformation.get(INDEX_NAME_ELEMENT)); + } + + if (indexInformation.containsKey(INDEX_TYPE_ELEMENT)) { + prepareIndex.setType(indexInformation.get(INDEX_TYPE_ELEMENT)); + } + + if (indexInformation.containsKey(INDEX_ID_ELEMENT)) { + prepareIndex.setId(indexInformation.get(INDEX_ID_ELEMENT)); + } + + return prepareIndex; + } + + @SuppressWarnings("unchecked") + public static List> getDocuments(InputStream data) throws IOException { + final Map rootNode = MAPPER.readValue(data, new TypeReference>() { + }); + final Object dataElements = rootNode.get(DOCUMENTS_ELEMENT); + + if (dataElements instanceof List) { + return (List>) dataElements; + } else { + throw new IllegalArgumentException("Array of documents are required."); + } + } +} diff --git a/nosqlunit-elasticsearch6/src/test/java/com/lordofthejars/nosqlunit/elasticsearch6/WhenManagedElasticsearchLifecycleIsManaged.java b/nosqlunit-elasticsearch6/src/test/java/com/lordofthejars/nosqlunit/elasticsearch6/WhenManagedElasticsearchLifecycleIsManaged.java new file mode 100644 index 0000000..2b31560 --- /dev/null +++ b/nosqlunit-elasticsearch6/src/test/java/com/lordofthejars/nosqlunit/elasticsearch6/WhenManagedElasticsearchLifecycleIsManaged.java @@ -0,0 +1,178 @@ +package com.lordofthejars.nosqlunit.elasticsearch6; + +import static com.lordofthejars.nosqlunit.elasticsearch6.ManagedElasticsearch.ManagedElasticsearchRuleBuilder.newManagedElasticsearchRule; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyListOf; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +import org.elasticsearch.common.settings.Settings; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import com.lordofthejars.nosqlunit.core.CommandLineExecutor; +import com.lordofthejars.nosqlunit.core.ConnectionManagement; +import com.lordofthejars.nosqlunit.core.OperatingSystem; +import com.lordofthejars.nosqlunit.core.OperatingSystemResolver; + +@RunWith(MockitoJUnitRunner.class) +public class WhenManagedElasticsearchLifecycleIsManaged { + private static final String DEFAULT_ELASTICSEARCH_HOME = "/opt/elasticsearch-6.7.1/"; + private static final String ES_HOME = System.getProperty("ES_HOME", DEFAULT_ELASTICSEARCH_HOME); + private static final Path ES_HOME_PATH = Paths.get(ES_HOME); + + @Mock + private OperatingSystemResolver operatingSystemResolver; + + @Mock + private LowLevelElasticSearchOperations lowLevelElasticSearchOperations; + + @Test + public void managed_elasticsearch_should_be_started_from_elasticsearch_home() throws Throwable { + final String oldElasticsearchHome = System.getProperty("ES_HOME"); + if (oldElasticsearchHome == null) { + System.setProperty("ES_HOME", ES_HOME); + } + + when(lowLevelElasticSearchOperations.assertThatConnectionToElasticsearchIsPossible(any(Settings.class), + anyString(), anyInt())).thenReturn(true); + when(operatingSystemResolver.currentOperatingSystem()).thenReturn(OperatingSystem.LINUX_OS); + + CommandLineExecutor commandLineExecutor = mock(CommandLineExecutor.class); + + Process mockProcess = mock(Process.class); + when(mockProcess.exitValue()).thenReturn(0); + + when(commandLineExecutor.startProcessInDirectoryAndArguments(anyString(), anyListOf(String.class))) + .thenReturn(mockProcess); + + try { + ManagedElasticsearch managedElasticsearch = newManagedElasticsearchRule().build(); + managedElasticsearch.managedElasticsearchLifecycleManager.setCommandLineExecutor(commandLineExecutor); + managedElasticsearch.managedElasticsearchLifecycleManager + .setOperatingSystemResolver(operatingSystemResolver); + managedElasticsearch.managedElasticsearchLifecycleManager + .setLowLevelElasticSearchOperations(lowLevelElasticSearchOperations); + + managedElasticsearch.before(); + managedElasticsearch.after(); + + verify(commandLineExecutor).startProcessInDirectoryAndArguments( + ManagedElasticsearchLifecycleManager.DEFAULT_ELASTICSEARCH_TARGET_PATH, getExpectedXCommand()); + } finally { + if (oldElasticsearchHome == null) { + System.clearProperty("ES_HOME"); + } + } + } + + @Test + public void managed_elasticsearch_should_be_started_from_elasticsearch_custom_location() throws Throwable { + when(lowLevelElasticSearchOperations.assertThatConnectionToElasticsearchIsPossible(any(Settings.class), + anyString(), anyInt())).thenReturn(true); + when(operatingSystemResolver.currentOperatingSystem()).thenReturn(OperatingSystem.LINUX_OS); + + CommandLineExecutor commandLineExecutor = mock(CommandLineExecutor.class); + + Process mockProcess = mock(Process.class); + when(mockProcess.exitValue()).thenReturn(0); + + when(commandLineExecutor.startProcessInDirectoryAndArguments(anyString(), anyListOf(String.class))) + .thenReturn(mockProcess); + + ManagedElasticsearch managedElasticsearch = newManagedElasticsearchRule().elasticsearchPath(ES_HOME).build(); + managedElasticsearch.managedElasticsearchLifecycleManager.setCommandLineExecutor(commandLineExecutor); + managedElasticsearch.managedElasticsearchLifecycleManager.setOperatingSystemResolver(operatingSystemResolver); + managedElasticsearch.managedElasticsearchLifecycleManager + .setLowLevelElasticSearchOperations(lowLevelElasticSearchOperations); + + managedElasticsearch.before(); + managedElasticsearch.after(); + + verify(commandLineExecutor).startProcessInDirectoryAndArguments( + ManagedElasticsearchLifecycleManager.DEFAULT_ELASTICSEARCH_TARGET_PATH, getExpectedXCommand()); + + } + + @Test + public void managed_elasticsearch_should_be_started_from_windows_custom_location() throws Throwable { + when(lowLevelElasticSearchOperations.assertThatConnectionToElasticsearchIsPossible(any(Settings.class), + anyString(), anyInt())).thenReturn(true); + when(operatingSystemResolver.currentOperatingSystem()).thenReturn(OperatingSystem.WINDOWS_7); + + CommandLineExecutor commandLineExecutor = mock(CommandLineExecutor.class); + + Process mockProcess = mock(Process.class); + when(mockProcess.exitValue()).thenReturn(0); + + when(commandLineExecutor.startProcessInDirectoryAndArguments(anyString(), anyListOf(String.class))) + .thenReturn(mockProcess); + + ManagedElasticsearch managedElasticsearch = newManagedElasticsearchRule().elasticsearchPath(ES_HOME).build(); + managedElasticsearch.managedElasticsearchLifecycleManager.setCommandLineExecutor(commandLineExecutor); + managedElasticsearch.managedElasticsearchLifecycleManager.setOperatingSystemResolver(operatingSystemResolver); + managedElasticsearch.managedElasticsearchLifecycleManager + .setLowLevelElasticSearchOperations(lowLevelElasticSearchOperations); + + managedElasticsearch.before(); + managedElasticsearch.after(); + + verify(commandLineExecutor).startProcessInDirectoryAndArguments( + ManagedElasticsearchLifecycleManager.DEFAULT_ELASTICSEARCH_TARGET_PATH, getExpectedWindowsCommand()); + + } + + @Test + public void managed_elasticsearch_should_be_stopped() throws Throwable { + when(lowLevelElasticSearchOperations.assertThatConnectionToElasticsearchIsPossible(any(Settings.class), + anyString(), anyInt())).thenReturn(true); + when(operatingSystemResolver.currentOperatingSystem()).thenReturn(OperatingSystem.LINUX_OS); + + CommandLineExecutor commandLineExecutor = mock(CommandLineExecutor.class); + + Process mockProcess = mock(Process.class); + when(mockProcess.exitValue()).thenReturn(0); + + when(commandLineExecutor.startProcessInDirectoryAndArguments(anyString(), anyListOf(String.class))) + .thenReturn(mockProcess); + + ManagedElasticsearch managedElasticsearch = newManagedElasticsearchRule().elasticsearchPath(ES_HOME).build(); + managedElasticsearch.managedElasticsearchLifecycleManager.setCommandLineExecutor(commandLineExecutor); + managedElasticsearch.managedElasticsearchLifecycleManager.setOperatingSystemResolver(operatingSystemResolver); + managedElasticsearch.managedElasticsearchLifecycleManager + .setLowLevelElasticSearchOperations(lowLevelElasticSearchOperations); + + managedElasticsearch.before(); + managedElasticsearch.after(); + + assertThat(ConnectionManagement.getInstance().isConnectionRegistered("127.0.0.1", + ManagedElasticsearchLifecycleManager.DEFAULT_PORT), is(false)); + } + + private List getExpectedWindowsCommand() { + final List expectedCommand = new ArrayList<>(); + expectedCommand.add(ES_HOME_PATH.resolve(Paths.get("bin", "elasticsearch.bat")).toString()); + + return expectedCommand; + } + + private List getExpectedXCommand() { + final List expectedCommand = new ArrayList<>(); + expectedCommand.add(ES_HOME_PATH.resolve(Paths.get("bin", "elasticsearch")).toString()); + expectedCommand.add(ManagedElasticsearchLifecycleManager.FOREGROUND_OPTION); + + return expectedCommand; + } +} diff --git a/nosqlunit-elasticsearch6/src/test/java/com/lordofthejars/nosqlunit/elasticsearch6/integration/WhenEmbeddedElasticsearchOperationsAreRequired.java b/nosqlunit-elasticsearch6/src/test/java/com/lordofthejars/nosqlunit/elasticsearch6/integration/WhenEmbeddedElasticsearchOperationsAreRequired.java new file mode 100644 index 0000000..c70375e --- /dev/null +++ b/nosqlunit-elasticsearch6/src/test/java/com/lordofthejars/nosqlunit/elasticsearch6/integration/WhenEmbeddedElasticsearchOperationsAreRequired.java @@ -0,0 +1,109 @@ +package com.lordofthejars.nosqlunit.elasticsearch6.integration; + +import org.elasticsearch.action.get.GetResponse; +import org.elasticsearch.client.Client; +import org.elasticsearch.node.Node; +import org.junit.After; +import org.junit.ClassRule; +import org.junit.Test; + +import com.lordofthejars.nosqlunit.elasticsearch6.ElasticsearchOperation; +import com.lordofthejars.nosqlunit.elasticsearch6.EmbeddedElasticsearch; +import com.lordofthejars.nosqlunit.elasticsearch6.EmbeddedElasticsearchInstancesFactory; + +import java.io.ByteArrayInputStream; +import java.util.Map; + +import static com.lordofthejars.nosqlunit.elasticsearch6.EmbeddedElasticsearch.EmbeddedElasticsearchRuleBuilder.newEmbeddedElasticsearchRule; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.collection.IsMapContaining.hasEntry; +import static org.junit.Assert.assertThat; + +public class WhenEmbeddedElasticsearchOperationsAreRequired { + private static final String ELASTICSEARCH_DATA = "{\n" + + " \"documents\":[\n" + + " {\n" + + " \"document\":[\n" + + " {\n" + + " \"index\":{\n" + + " \"indexName\":\"tweeter\",\n" + + " \"indexType\":\"tweet\",\n" + + " \"indexId\":\"1\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"data\":{\n" + + " \"name\":\"a\",\n" + + " \"msg\":\"b\"\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + "}"; + + @ClassRule + public static final EmbeddedElasticsearch EMBEDDED_ELASTICSEARCH = newEmbeddedElasticsearchRule().build(); + + @After + public void removeIndexes() { + Node defaultEmbeddedInstance = EmbeddedElasticsearchInstancesFactory.getInstance().getDefaultEmbeddedInstance(); + + try (final Client client = defaultEmbeddedInstance.client()) { + client.admin().indices().prepareDelete("*").execute().actionGet(); + client.admin().indices().prepareRefresh().execute().actionGet(); + } + } + + @Test + public void insert_operation_should_index_all_dataset() { + + Node defaultEmbeddedInstance = EmbeddedElasticsearchInstancesFactory.getInstance().getDefaultEmbeddedInstance(); + Client client = defaultEmbeddedInstance.client(); + + ElasticsearchOperation elasticsearchOperation = new ElasticsearchOperation(client); + elasticsearchOperation.insert(new ByteArrayInputStream(ELASTICSEARCH_DATA.getBytes())); + + GetResponse document = client.prepareGet("tweeter", "tweet", "1").execute().actionGet(); + Map documentSource = document.getSource(); + + //Strange a cast to Object + assertThat(documentSource, hasEntry("name", (Object) "a")); + assertThat(documentSource, hasEntry("msg", (Object) "b")); + + client.close(); + } + + @Test + public void delete_operation_should_remove_all_Indexes() { + + Node defaultEmbeddedInstance = EmbeddedElasticsearchInstancesFactory.getInstance().getDefaultEmbeddedInstance(); + Client client = defaultEmbeddedInstance.client(); + + ElasticsearchOperation elasticsearchOperation = new ElasticsearchOperation(client); + elasticsearchOperation.insert(new ByteArrayInputStream(ELASTICSEARCH_DATA.getBytes())); + + elasticsearchOperation.deleteAll(); + + GetResponse document = client.prepareGet("tweeter", "tweet", "1").execute().actionGet(); + assertThat(document.isSourceEmpty(), is(true)); + + client.close(); + } + + @Test + public void databaseIs_operation_should_compare_all_Indexes() { + + Node defaultEmbeddedInstance = EmbeddedElasticsearchInstancesFactory.getInstance().getDefaultEmbeddedInstance(); + Client client = defaultEmbeddedInstance.client(); + + ElasticsearchOperation elasticsearchOperation = new ElasticsearchOperation(client); + elasticsearchOperation.insert(new ByteArrayInputStream(ELASTICSEARCH_DATA.getBytes())); + + boolean isEqual = elasticsearchOperation.databaseIs(new ByteArrayInputStream(ELASTICSEARCH_DATA.getBytes())); + + assertThat(isEqual, is(true)); + + client.close(); + } +} diff --git a/nosqlunit-elasticsearch6/src/test/java/com/lordofthejars/nosqlunit/elasticsearch6/integration/WhenExpectedDataShouldBeCompared.java b/nosqlunit-elasticsearch6/src/test/java/com/lordofthejars/nosqlunit/elasticsearch6/integration/WhenExpectedDataShouldBeCompared.java new file mode 100644 index 0000000..c0d1030 --- /dev/null +++ b/nosqlunit-elasticsearch6/src/test/java/com/lordofthejars/nosqlunit/elasticsearch6/integration/WhenExpectedDataShouldBeCompared.java @@ -0,0 +1,192 @@ +package com.lordofthejars.nosqlunit.elasticsearch6.integration; + +import com.lordofthejars.nosqlunit.core.NoSqlAssertionError; +import com.lordofthejars.nosqlunit.elasticsearch6.ElasticsearchOperation; +import com.lordofthejars.nosqlunit.elasticsearch6.EmbeddedElasticsearch; +import com.lordofthejars.nosqlunit.elasticsearch6.EmbeddedElasticsearchInstancesFactory; + +import org.elasticsearch.client.Client; +import org.elasticsearch.node.Node; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; + +import java.io.ByteArrayInputStream; + +import static com.lordofthejars.nosqlunit.elasticsearch6.EmbeddedElasticsearch.EmbeddedElasticsearchRuleBuilder.newEmbeddedElasticsearchRule; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +public class WhenExpectedDataShouldBeCompared { + + private static final String ELASTICSEARCH_DATA = "{\n" + + " \"documents\":[\n" + + " {\n" + + " \"document\":[\n" + + " {\n" + + " \"index\":{\n" + + " \"indexName\":\"tweeter\",\n" + + " \"indexType\":\"tweet\",\n" + + " \"indexId\":\"1\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"data\":{\n" + + " \"name\":\"a\",\n" + + " \"msg\":\"b\"\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + "}"; + + private static final String ELASTICSEARCH_TWO_DATA = "{\n" + + " \"documents\":[\n" + + " {\n" + + " \"document\":[\n" + + " {\n" + + " \"index\":{\n" + + " \"indexName\":\"tweeter\",\n" + + " \"indexType\":\"tweet\",\n" + + " \"indexId\":\"1\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"data\":{\n" + + " \"name\":\"a\",\n" + + " \"msg\":\"b\"\n" + + " }\n" + + " }\n" + + " ]\n" + + " },\n" + + " {\n" + + " \"document\":[\n" + + " {\n" + + " \"index\":{\n" + + " \"indexName\":\"tweeter\",\n" + + " \"indexType\":\"tweet\",\n" + + " \"indexId\":\"2\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"data\":{\n" + + " \"name\":\"c\",\n" + + " \"msg\":\"d\"\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + "}"; + + private static final String ELASTICSEARCH_DATA_INDEX_NOT_FOUND = "{\n" + + " \"documents\":[\n" + + " {\n" + + " \"document\":[\n" + + " {\n" + + " \"index\":{\n" + + " \"indexName\":\"tweeter\",\n" + + " \"indexType\":\"tweet\",\n" + + " \"indexId\":\"2\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"data\":{\n" + + " \"name\":\"a\",\n" + + " \"msg\":\"b\"\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + "}"; + + private static final String ELASTICSEARCH_DATA_NOT_FOUND = "{\n" + + " \"documents\":[\n" + + " {\n" + + " \"document\":[\n" + + " {\n" + + " \"index\":{\n" + + " \"indexName\":\"tweeter\",\n" + + " \"indexType\":\"tweet\",\n" + + " \"indexId\":\"1\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"data\":{\n" + + " \"name\":\"a\",\n" + + " \"msg\":\"c\"\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + "}"; + + @ClassRule + public static EmbeddedElasticsearch embeddedElasticsearch = newEmbeddedElasticsearchRule().build(); + + private ElasticsearchOperation elasticsearchOperation; + + @Before + public void setUp() { + Node defaultEmbeddedInstance = EmbeddedElasticsearchInstancesFactory.getInstance().getDefaultEmbeddedInstance(); + Client client = defaultEmbeddedInstance.client(); + + elasticsearchOperation = new ElasticsearchOperation(client); + elasticsearchOperation.deleteAll(); + } + + @Test + public void no_exception_should_be_thrown_if_data_is_expected() { + + elasticsearchOperation.insert(new ByteArrayInputStream(ELASTICSEARCH_DATA.getBytes())); + + boolean result = elasticsearchOperation.databaseIs(new ByteArrayInputStream(ELASTICSEARCH_DATA.getBytes())); + + assertThat(result, is(true)); + + } + + @Test + public void exception_should_be_thrown_if_different_number_of_documents() { + + elasticsearchOperation.insert(new ByteArrayInputStream(ELASTICSEARCH_DATA.getBytes())); + + try { + elasticsearchOperation.databaseIs(new ByteArrayInputStream(ELASTICSEARCH_TWO_DATA.getBytes())); + fail(); + } catch (NoSqlAssertionError e) { + assertThat(e.getMessage(), is("Expected number of documents are 2 but 1 has been found.")); + } + } + + @Test + public void exception_should_be_thrown_if_index_not_found() { + + elasticsearchOperation.insert(new ByteArrayInputStream(ELASTICSEARCH_DATA.getBytes())); + + try { + elasticsearchOperation.databaseIs(new ByteArrayInputStream(ELASTICSEARCH_DATA_INDEX_NOT_FOUND.getBytes())); + fail(); + } catch (NoSqlAssertionError e) { + assertThat(e.getMessage(), is("Document with index: tweeter - type: tweet - id: 2 has not returned any document.")); + } + } + + @Test + public void exception_should_be_thrown_if_different_() { + + elasticsearchOperation.insert(new ByteArrayInputStream(ELASTICSEARCH_DATA.getBytes())); + + try { + elasticsearchOperation.databaseIs(new ByteArrayInputStream(ELASTICSEARCH_DATA_NOT_FOUND.getBytes())); + fail(); + } catch (NoSqlAssertionError e) { + assertThat(e.getMessage(), is("Expected document for index: tweeter - type: tweet - id: 1 is {\"name\":\"a\",\"msg\":\"c\"}, but {\"name\":\"a\",\"msg\":\"b\"} was found.")); + } + } + +} diff --git a/nosqlunit-elasticsearch6/src/test/java/com/lordofthejars/nosqlunit/elasticsearch6/integration/WhenManagedElasticsearchOperationsAreRequired.java b/nosqlunit-elasticsearch6/src/test/java/com/lordofthejars/nosqlunit/elasticsearch6/integration/WhenManagedElasticsearchOperationsAreRequired.java new file mode 100644 index 0000000..0ed65e2 --- /dev/null +++ b/nosqlunit-elasticsearch6/src/test/java/com/lordofthejars/nosqlunit/elasticsearch6/integration/WhenManagedElasticsearchOperationsAreRequired.java @@ -0,0 +1,104 @@ +package com.lordofthejars.nosqlunit.elasticsearch6.integration; + +import static com.lordofthejars.nosqlunit.elasticsearch6.ManagedElasticsearch.ManagedElasticsearchRuleBuilder.newManagedElasticsearchRule; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.collection.IsMapContaining.hasEntry; +import static org.junit.Assert.assertThat; + +import java.io.ByteArrayInputStream; +import java.net.InetSocketAddress; +import java.util.Map; + +import org.elasticsearch.action.get.GetResponse; +import org.elasticsearch.client.Client; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.transport.TransportAddress; +import org.elasticsearch.transport.client.PreBuiltTransportClient; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; + +import com.lordofthejars.nosqlunit.elasticsearch6.ElasticsearchOperation; +import com.lordofthejars.nosqlunit.elasticsearch6.ManagedElasticsearch; + +public class WhenManagedElasticsearchOperationsAreRequired { + private static final String ELASTICSEARCH_DATA = "{\n" + + " \"documents\":[\n" + + " {\n" + + " \"document\":[\n" + + " {\n" + + " \"index\":{\n" + + " \"indexName\":\"tweeter\",\n" + + " \"indexType\":\"tweet\",\n" + + " \"indexId\":\"1\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"data\":{\n" + + " \"name\":\"a\",\n" + + " \"msg\":\"b\"\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + "}"; + + + @ClassRule + public static ManagedElasticsearch managedElasticsearch = newManagedElasticsearchRule().elasticsearchPath("/usr/local/Cellar/elasticsearch/6.7.1/").build(); + + private static final InetSocketAddress INET_SOCKET_ADDRESS = new InetSocketAddress("localhost", 9300); + private static final TransportAddress TRANSPORT_ADDRESS = new TransportAddress(INET_SOCKET_ADDRESS); + + private Client client; + + @Before + public void setupClient() { + client = new PreBuiltTransportClient(Settings.EMPTY).addTransportAddress(TRANSPORT_ADDRESS); + } + + + @After + public void removeIndexes() { + client.admin().indices().prepareDelete("*").execute().actionGet(); + client.admin().indices().prepareRefresh().execute().actionGet(); + + client.close(); + } + + @Test + public void insert_operation_should_index_all_dataset() { + ElasticsearchOperation elasticsearchOperation = new ElasticsearchOperation(client); + elasticsearchOperation.insert(new ByteArrayInputStream(ELASTICSEARCH_DATA.getBytes())); + + GetResponse document = client.prepareGet("tweeter", "tweet", "1").execute().actionGet(); + Map documentSource = document.getSource(); + + //Strange a cast to Object + assertThat(documentSource, hasEntry("name", (Object) "a")); + assertThat(documentSource, hasEntry("msg", (Object) "b")); + } + + @Test + public void delete_operation_should_remove_all_Indexes() { + ElasticsearchOperation elasticsearchOperation = new ElasticsearchOperation(client); + elasticsearchOperation.insert(new ByteArrayInputStream(ELASTICSEARCH_DATA.getBytes())); + + elasticsearchOperation.deleteAll(); + + GetResponse document = client.prepareGet("tweeter", "tweet", "1").execute().actionGet(); + assertThat(document.isSourceEmpty(), is(true)); + } + + @Test + public void databaseIs_operation_should_compare_all_Indexes() { + ElasticsearchOperation elasticsearchOperation = new ElasticsearchOperation(client); + elasticsearchOperation.insert(new ByteArrayInputStream(ELASTICSEARCH_DATA.getBytes())); + + boolean isEqual = elasticsearchOperation.databaseIs(new ByteArrayInputStream(ELASTICSEARCH_DATA.getBytes())); + + assertThat(isEqual, is(true)); + } +} diff --git a/nosqlunit-elasticsearch6/src/test/java/com/lordofthejars/nosqlunit/elasticsearch6/integration/parser/WhenElasticsearchDataIsImported.java b/nosqlunit-elasticsearch6/src/test/java/com/lordofthejars/nosqlunit/elasticsearch6/integration/parser/WhenElasticsearchDataIsImported.java new file mode 100644 index 0000000..c7f1530 --- /dev/null +++ b/nosqlunit-elasticsearch6/src/test/java/com/lordofthejars/nosqlunit/elasticsearch6/integration/parser/WhenElasticsearchDataIsImported.java @@ -0,0 +1,71 @@ +package com.lordofthejars.nosqlunit.elasticsearch6.integration.parser; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.Map; + +import org.elasticsearch.action.get.GetResponse; +import org.elasticsearch.client.Client; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.node.Node; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import com.lordofthejars.nosqlunit.elasticsearch6.parser.DataReader; + +public class WhenElasticsearchDataIsImported { + private static final String ELASTICSEARCH_DATA = "{\n" + // + " \"documents\":[\n" + // + " {\n" + // + " \"document\":[\n" + // + " {\n" + // + " \"index\":{\n" + // + " \"indexName\":\"tweeter\",\n" + // + " \"indexType\":\"tweet\",\n" + // + " \"indexId\":\"1\"\n" + // + " }\n" + " },\n" + // + " {\n" + // + " \"data\":{\n" + // + " \"name\":\"a\",\n" + // + " \"msg\":\"b\"\n" + // + " }\n" + // + " }\n" + // + " ]\n" + // + " }\n" + // + " ]\n" + // + "}"; + + @Rule + public final TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Test + public void data_should_be_indexed() throws IOException { + final String pathHome = temporaryFolder.newFolder().getAbsolutePath(); + final Settings settings = Settings.builder()// + .put("path.home", pathHome)// + .put("transport.type", "local")// + .put("http.enabled", false)// + .build(); + + try (final Node node = new Node(settings) { + + @Override + protected void registerDerivedNodeNameWithLogger(String nodeName) { + } + + }; final Client client = node.client()) { + final DataReader dataReader = new DataReader(client); + dataReader.read(new ByteArrayInputStream(ELASTICSEARCH_DATA.getBytes())); + + final GetResponse response = client.prepareGet("tweeter", "tweet", "1").execute().actionGet(); + final Map document = response.getSourceAsMap(); + + assertThat((String) document.get("name"), is("a")); + assertThat((String) document.get("msg"), is("b")); + } + } +} diff --git a/pom.xml b/pom.xml index 1f50620..c471828 100644 --- a/pom.xml +++ b/pom.xml @@ -38,6 +38,8 @@ 3.2.2 1.1.1 2.0.2 + 6.7.0 + 4.12 4.12 1.3 1.9.0 @@ -371,6 +373,7 @@ nosqlunit-infinispan nosqlunit-elasticsearch nosqlunit-elasticsearch2 + nosqlunit-elasticsearch6 nosqlunit-couchbase nosqlunit-vault nosqlunit-dynamodb @@ -378,7 +381,6 @@ - org.apache.maven.plugins @@ -389,50 +391,6 @@ 1.8 - - org.apache.maven.plugins - maven-source-plugin - 2.1.2 - - - attach-sources - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.1 - - - sign-artifacts - verify - - sign - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.7 - - - attach-javadocs - - jar - - - -Xdoclint:none - - - - - @@ -484,6 +442,56 @@ + + release + + + + org.apache.maven.plugins + maven-source-plugin + 2.1.2 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.1 + + + sign-artifacts + verify + + sign + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.7 + + + attach-javadocs + + jar + + + -Xdoclint:none + + + + + + + integration-tests