/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.action;
import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeAction;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequest;
import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheAction;
import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest;
import org.elasticsearch.action.admin.indices.close.CloseIndexAction;
import org.elasticsearch.action.admin.indices.close.CloseIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexAction;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.flush.FlushRequest;
import org.elasticsearch.action.admin.indices.flush.TransportShardFlushAction;
import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeAction;
import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeRequest;
import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsAction;
import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsRequest;
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsAction;
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingAction;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexAction;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.admin.indices.recovery.RecoveryAction;
import org.elasticsearch.action.admin.indices.recovery.RecoveryRequest;
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
import org.elasticsearch.action.admin.indices.refresh.TransportShardRefreshAction;
import org.elasticsearch.action.admin.indices.segments.IndicesSegmentsAction;
import org.elasticsearch.action.admin.indices.segments.IndicesSegmentsRequest;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsAction;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsAction;
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
import org.elasticsearch.action.admin.indices.stats.IndicesStatsAction;
import org.elasticsearch.action.admin.indices.stats.IndicesStatsRequest;
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryAction;
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequest;
import org.elasticsearch.action.bulk.BulkAction;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.explain.ExplainAction;
import org.elasticsearch.action.explain.ExplainRequest;
import org.elasticsearch.action.get.GetAction;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.MultiGetAction;
import org.elasticsearch.action.get.MultiGetRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.support.replication.TransportReplicationActionTests;
import org.elasticsearch.action.termvectors.MultiTermVectorsAction;
import org.elasticsearch.action.termvectors.MultiTermVectorsRequest;
import org.elasticsearch.action.termvectors.TermVectorsAction;
import org.elasticsearch.action.termvectors.TermVectorsRequest;
import org.elasticsearch.action.update.UpdateAction;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.Requests;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.plugins.NetworkPlugin;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.plugins.PluginsService;
import org.elasticsearch.script.MockScriptPlugin;
import org.elasticsearch.script.Script;
import org.elasticsearch.action.search.SearchTransportService;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.tasks.Task;
import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
import org.elasticsearch.test.ESIntegTestCase.Scope;
import org.elasticsearch.transport.TransportChannel;
import org.elasticsearch.transport.TransportInterceptor;
import org.elasticsearch.transport.TransportRequest;
import org.elasticsearch.transport.TransportRequestHandler;
import org.junit.After;
import org.junit.Before;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
import static org.hamcrest.Matchers.emptyIterable;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.hasItem;
@ClusterScope(scope = Scope.SUITE, numClientNodes = 1, minNumDataNodes = 2)
public class IndicesRequestIT extends ESIntegTestCase {
private final List<String> indices = new ArrayList<>();
@Override
protected int minimumNumberOfShards() {
//makes sure that a reduce is always needed when searching
return 2;
}
@Override
protected int minimumNumberOfReplicas() {
//makes sure that write operations get sent to the replica as well
//so we are able to intercept those messages and check them
return 1;
}
@Override
protected Settings nodeSettings(int ordinal) {
// must set this independently of the plugin so it overrides MockTransportService
return Settings.builder().put(super.nodeSettings(ordinal))
// InternalClusterInfoService sends IndicesStatsRequest periodically which messes with this test
// this setting disables it...
.put("cluster.routing.allocation.disk.threshold_enabled", false).build();
}
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
return Arrays.asList(InterceptingTransportService.TestPlugin.class, CustomScriptPlugin.class);
}
public static class CustomScriptPlugin extends MockScriptPlugin {
@Override
@SuppressWarnings("unchecked")
protected Map<String, Function<Map<String, Object>, Object>> pluginScripts() {
return Collections.singletonMap("ctx.op='delete'", vars -> ((Map<String, Object>) vars.get("ctx")).put("op", "delete"));
}
}
@Before
public void setup() {
int numIndices = iterations(1, 5);
for (int i = 0; i < numIndices; i++) {
indices.add("test" + i);
}
for (String index : indices) {
assertAcked(prepareCreate(index).addAlias(new Alias(index + "-alias")));
}
ensureGreen();
}
@After
public void cleanUp() {
assertAllRequestsHaveBeenConsumed();
indices.clear();
}
public void testGetFieldMappings() {
String getFieldMappingsShardAction = GetFieldMappingsAction.NAME + "[index][s]";
interceptTransportActions(getFieldMappingsShardAction);
GetFieldMappingsRequest getFieldMappingsRequest = new GetFieldMappingsRequest();
getFieldMappingsRequest.indices(randomIndicesOrAliases());
internalCluster().coordOnlyNodeClient().admin().indices().getFieldMappings(getFieldMappingsRequest).actionGet();
clearInterceptedActions();
assertSameIndices(getFieldMappingsRequest, getFieldMappingsShardAction);
}
public void testAnalyze() {
String analyzeShardAction = AnalyzeAction.NAME + "[s]";
interceptTransportActions(analyzeShardAction);
AnalyzeRequest analyzeRequest = new AnalyzeRequest(randomIndexOrAlias());
analyzeRequest.text("text");
internalCluster().coordOnlyNodeClient().admin().indices().analyze(analyzeRequest).actionGet();
clearInterceptedActions();
assertSameIndices(analyzeRequest, analyzeShardAction);
}
public void testIndex() {
String[] indexShardActions = new String[]{BulkAction.NAME + "[s][p]", BulkAction.NAME + "[s][r]"};
interceptTransportActions(indexShardActions);
IndexRequest indexRequest = new IndexRequest(randomIndexOrAlias(), "type", "id")
.source(Requests.INDEX_CONTENT_TYPE, "field", "value");
internalCluster().coordOnlyNodeClient().index(indexRequest).actionGet();
clearInterceptedActions();
assertSameIndices(indexRequest, indexShardActions);
}
public void testDelete() {
String[] deleteShardActions = new String[]{BulkAction.NAME + "[s][p]", BulkAction.NAME + "[s][r]"};
interceptTransportActions(deleteShardActions);
DeleteRequest deleteRequest = new DeleteRequest(randomIndexOrAlias(), "type", "id");
internalCluster().coordOnlyNodeClient().delete(deleteRequest).actionGet();
clearInterceptedActions();
assertSameIndices(deleteRequest, deleteShardActions);
}
public void testUpdate() {
//update action goes to the primary, index op gets executed locally, then replicated
String[] updateShardActions = new String[]{UpdateAction.NAME + "[s]", BulkAction.NAME + "[s][p]", BulkAction.NAME + "[s][r]"};
interceptTransportActions(updateShardActions);
String indexOrAlias = randomIndexOrAlias();
client().prepareIndex(indexOrAlias, "type", "id").setSource("field", "value").get();
UpdateRequest updateRequest = new UpdateRequest(indexOrAlias, "type", "id").doc(Requests.INDEX_CONTENT_TYPE, "field1", "value1");
UpdateResponse updateResponse = internalCluster().coordOnlyNodeClient().update(updateRequest).actionGet();
assertEquals(DocWriteResponse.Result.UPDATED, updateResponse.getResult());
clearInterceptedActions();
assertSameIndices(updateRequest, updateShardActions);
}
public void testUpdateUpsert() {
//update action goes to the primary, index op gets executed locally, then replicated
String[] updateShardActions = new String[]{UpdateAction.NAME + "[s]", BulkAction.NAME + "[s][p]", BulkAction.NAME + "[s][r]"};
interceptTransportActions(updateShardActions);
String indexOrAlias = randomIndexOrAlias();
UpdateRequest updateRequest = new UpdateRequest(indexOrAlias, "type", "id").upsert(Requests.INDEX_CONTENT_TYPE, "field", "value")
.doc(Requests.INDEX_CONTENT_TYPE, "field1", "value1");
UpdateResponse updateResponse = internalCluster().coordOnlyNodeClient().update(updateRequest).actionGet();
assertEquals(DocWriteResponse.Result.CREATED, updateResponse.getResult());
clearInterceptedActions();
assertSameIndices(updateRequest, updateShardActions);
}
public void testUpdateDelete() {
//update action goes to the primary, delete op gets executed locally, then replicated
String[] updateShardActions = new String[]{UpdateAction.NAME + "[s]", BulkAction.NAME + "[s][p]", BulkAction.NAME + "[s][r]"};
interceptTransportActions(updateShardActions);
String indexOrAlias = randomIndexOrAlias();
client().prepareIndex(indexOrAlias, "type", "id").setSource("field", "value").get();
UpdateRequest updateRequest = new UpdateRequest(indexOrAlias, "type", "id")
.script(new Script(ScriptType.INLINE, CustomScriptPlugin.NAME, "ctx.op='delete'", Collections.emptyMap()));
UpdateResponse updateResponse = internalCluster().coordOnlyNodeClient().update(updateRequest).actionGet();
assertEquals(DocWriteResponse.Result.DELETED, updateResponse.getResult());
clearInterceptedActions();
assertSameIndices(updateRequest, updateShardActions);
}
public void testBulk() {
String[] bulkShardActions = new String[]{BulkAction.NAME + "[s][p]", BulkAction.NAME + "[s][r]"};
interceptTransportActions(bulkShardActions);
List<String> indices = new ArrayList<>();
BulkRequest bulkRequest = new BulkRequest();
int numIndexRequests = iterations(1, 10);
for (int i = 0; i < numIndexRequests; i++) {
String indexOrAlias = randomIndexOrAlias();
bulkRequest.add(new IndexRequest(indexOrAlias, "type", "id").source(Requests.INDEX_CONTENT_TYPE, "field", "value"));
indices.add(indexOrAlias);
}
int numDeleteRequests = iterations(1, 10);
for (int i = 0; i < numDeleteRequests; i++) {
String indexOrAlias = randomIndexOrAlias();
bulkRequest.add(new DeleteRequest(indexOrAlias, "type", "id"));
indices.add(indexOrAlias);
}
int numUpdateRequests = iterations(1, 10);
for (int i = 0; i < numUpdateRequests; i++) {
String indexOrAlias = randomIndexOrAlias();
bulkRequest.add(new UpdateRequest(indexOrAlias, "type", "id").doc(Requests.INDEX_CONTENT_TYPE, "field1", "value1"));
indices.add(indexOrAlias);
}
internalCluster().coordOnlyNodeClient().bulk(bulkRequest).actionGet();
clearInterceptedActions();
assertIndicesSubset(indices, bulkShardActions);
}
public void testGet() {
String getShardAction = GetAction.NAME + "[s]";
interceptTransportActions(getShardAction);
GetRequest getRequest = new GetRequest(randomIndexOrAlias(), "type", "id");
internalCluster().coordOnlyNodeClient().get(getRequest).actionGet();
clearInterceptedActions();
assertSameIndices(getRequest, getShardAction);
}
public void testExplain() {
String explainShardAction = ExplainAction.NAME + "[s]";
interceptTransportActions(explainShardAction);
ExplainRequest explainRequest = new ExplainRequest(randomIndexOrAlias(), "type", "id").query(QueryBuilders.matchAllQuery());
internalCluster().coordOnlyNodeClient().explain(explainRequest).actionGet();
clearInterceptedActions();
assertSameIndices(explainRequest, explainShardAction);
}
public void testTermVector() {
String termVectorShardAction = TermVectorsAction.NAME + "[s]";
interceptTransportActions(termVectorShardAction);
TermVectorsRequest termVectorsRequest = new TermVectorsRequest(randomIndexOrAlias(), "type", "id");
internalCluster().coordOnlyNodeClient().termVectors(termVectorsRequest).actionGet();
clearInterceptedActions();
assertSameIndices(termVectorsRequest, termVectorShardAction);
}
public void testMultiTermVector() {
String multiTermVectorsShardAction = MultiTermVectorsAction.NAME + "[shard][s]";
interceptTransportActions(multiTermVectorsShardAction);
List<String> indices = new ArrayList<>();
MultiTermVectorsRequest multiTermVectorsRequest = new MultiTermVectorsRequest();
int numDocs = iterations(1, 30);
for (int i = 0; i < numDocs; i++) {
String indexOrAlias = randomIndexOrAlias();
multiTermVectorsRequest.add(indexOrAlias, "type", Integer.toString(i));
indices.add(indexOrAlias);
}
internalCluster().coordOnlyNodeClient().multiTermVectors(multiTermVectorsRequest).actionGet();
clearInterceptedActions();
assertIndicesSubset(indices, multiTermVectorsShardAction);
}
public void testMultiGet() {
String multiGetShardAction = MultiGetAction.NAME + "[shard][s]";
interceptTransportActions(multiGetShardAction);
List<String> indices = new ArrayList<>();
MultiGetRequest multiGetRequest = new MultiGetRequest();
int numDocs = iterations(1, 30);
for (int i = 0; i < numDocs; i++) {
String indexOrAlias = randomIndexOrAlias();
multiGetRequest.add(indexOrAlias, "type", Integer.toString(i));
indices.add(indexOrAlias);
}
internalCluster().coordOnlyNodeClient().multiGet(multiGetRequest).actionGet();
clearInterceptedActions();
assertIndicesSubset(indices, multiGetShardAction);
}
public void testFlush() {
String[] indexShardActions = new String[]{TransportShardFlushAction.NAME, TransportShardFlushAction.NAME + "[r]",
TransportShardFlushAction.NAME + "[p]"};
interceptTransportActions(indexShardActions);
FlushRequest flushRequest = new FlushRequest(randomIndicesOrAliases());
internalCluster().coordOnlyNodeClient().admin().indices().flush(flushRequest).actionGet();
clearInterceptedActions();
String[] indices = new IndexNameExpressionResolver(Settings.EMPTY)
.concreteIndexNames(client().admin().cluster().prepareState().get().getState(), flushRequest);
assertIndicesSubset(Arrays.asList(indices), indexShardActions);
}
public void testForceMerge() {
String mergeShardAction = ForceMergeAction.NAME + "[n]";
interceptTransportActions(mergeShardAction);
ForceMergeRequest mergeRequest = new ForceMergeRequest(randomIndicesOrAliases());
internalCluster().coordOnlyNodeClient().admin().indices().forceMerge(mergeRequest).actionGet();
clearInterceptedActions();
assertSameIndices(mergeRequest, mergeShardAction);
}
public void testRefresh() {
String[] indexShardActions = new String[]{TransportShardRefreshAction.NAME, TransportShardRefreshAction.NAME + "[r]",
TransportShardRefreshAction.NAME + "[p]"};
interceptTransportActions(indexShardActions);
RefreshRequest refreshRequest = new RefreshRequest(randomIndicesOrAliases());
internalCluster().coordOnlyNodeClient().admin().indices().refresh(refreshRequest).actionGet();
clearInterceptedActions();
String[] indices = new IndexNameExpressionResolver(Settings.EMPTY)
.concreteIndexNames(client().admin().cluster().prepareState().get().getState(), refreshRequest);
assertIndicesSubset(Arrays.asList(indices), indexShardActions);
}
public void testClearCache() {
String clearCacheAction = ClearIndicesCacheAction.NAME + "[n]";
interceptTransportActions(clearCacheAction);
ClearIndicesCacheRequest clearIndicesCacheRequest = new ClearIndicesCacheRequest(randomIndicesOrAliases());
internalCluster().coordOnlyNodeClient().admin().indices().clearCache(clearIndicesCacheRequest).actionGet();
clearInterceptedActions();
assertSameIndices(clearIndicesCacheRequest, clearCacheAction);
}
public void testRecovery() {
String recoveryAction = RecoveryAction.NAME + "[n]";
interceptTransportActions(recoveryAction);
RecoveryRequest recoveryRequest = new RecoveryRequest(randomIndicesOrAliases());
internalCluster().coordOnlyNodeClient().admin().indices().recoveries(recoveryRequest).actionGet();
clearInterceptedActions();
assertSameIndices(recoveryRequest, recoveryAction);
}
public void testSegments() {
String segmentsAction = IndicesSegmentsAction.NAME + "[n]";
interceptTransportActions(segmentsAction);
IndicesSegmentsRequest segmentsRequest = new IndicesSegmentsRequest(randomIndicesOrAliases());
internalCluster().coordOnlyNodeClient().admin().indices().segments(segmentsRequest).actionGet();
clearInterceptedActions();
assertSameIndices(segmentsRequest, segmentsAction);
}
public void testIndicesStats() {
String indicesStats = IndicesStatsAction.NAME + "[n]";
interceptTransportActions(indicesStats);
IndicesStatsRequest indicesStatsRequest = new IndicesStatsRequest().indices(randomIndicesOrAliases());
internalCluster().coordOnlyNodeClient().admin().indices().stats(indicesStatsRequest).actionGet();
clearInterceptedActions();
assertSameIndices(indicesStatsRequest, indicesStats);
}
public void testValidateQuery() {
String validateQueryShardAction = ValidateQueryAction.NAME + "[s]";
interceptTransportActions(validateQueryShardAction);
ValidateQueryRequest validateQueryRequest = new ValidateQueryRequest(randomIndicesOrAliases());
internalCluster().coordOnlyNodeClient().admin().indices().validateQuery(validateQueryRequest).actionGet();
clearInterceptedActions();
assertSameIndices(validateQueryRequest, validateQueryShardAction);
}
public void testOpenIndex() {
interceptTransportActions(OpenIndexAction.NAME);
OpenIndexRequest openIndexRequest = new OpenIndexRequest(randomUniqueIndicesOrAliases());
internalCluster().coordOnlyNodeClient().admin().indices().open(openIndexRequest).actionGet();
clearInterceptedActions();
assertSameIndices(openIndexRequest, OpenIndexAction.NAME);
}
public void testCloseIndex() {
interceptTransportActions(CloseIndexAction.NAME);
CloseIndexRequest closeIndexRequest = new CloseIndexRequest(randomUniqueIndicesOrAliases());
internalCluster().coordOnlyNodeClient().admin().indices().close(closeIndexRequest).actionGet();
clearInterceptedActions();
assertSameIndices(closeIndexRequest, CloseIndexAction.NAME);
}
public void testDeleteIndex() {
interceptTransportActions(DeleteIndexAction.NAME);
String[] randomIndicesOrAliases = randomUniqueIndicesOrAliases();
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(randomIndicesOrAliases);
assertAcked(internalCluster().coordOnlyNodeClient().admin().indices().delete(deleteIndexRequest).actionGet());
clearInterceptedActions();
assertSameIndices(deleteIndexRequest, DeleteIndexAction.NAME);
}
public void testGetMappings() {
interceptTransportActions(GetMappingsAction.NAME);
GetMappingsRequest getMappingsRequest = new GetMappingsRequest().indices(randomIndicesOrAliases());
internalCluster().coordOnlyNodeClient().admin().indices().getMappings(getMappingsRequest).actionGet();
clearInterceptedActions();
assertSameIndices(getMappingsRequest, GetMappingsAction.NAME);
}
public void testPutMapping() {
interceptTransportActions(PutMappingAction.NAME);
PutMappingRequest putMappingRequest = new PutMappingRequest(randomUniqueIndicesOrAliases())
.type("type")
.source("field", "type=text");
internalCluster().coordOnlyNodeClient().admin().indices().putMapping(putMappingRequest).actionGet();
clearInterceptedActions();
assertSameIndices(putMappingRequest, PutMappingAction.NAME);
}
public void testGetSettings() {
interceptTransportActions(GetSettingsAction.NAME);
GetSettingsRequest getSettingsRequest = new GetSettingsRequest().indices(randomIndicesOrAliases());
internalCluster().coordOnlyNodeClient().admin().indices().getSettings(getSettingsRequest).actionGet();
clearInterceptedActions();
assertSameIndices(getSettingsRequest, GetSettingsAction.NAME);
}
public void testUpdateSettings() {
interceptTransportActions(UpdateSettingsAction.NAME);
UpdateSettingsRequest updateSettingsRequest = new UpdateSettingsRequest(randomIndicesOrAliases())
.settings(Settings.builder().put("refresh_interval", -1));
internalCluster().coordOnlyNodeClient().admin().indices().updateSettings(updateSettingsRequest).actionGet();
clearInterceptedActions();
assertSameIndices(updateSettingsRequest, UpdateSettingsAction.NAME);
}
public void testSearchQueryThenFetch() throws Exception {
interceptTransportActions(SearchTransportService.QUERY_ACTION_NAME,
SearchTransportService.FETCH_ID_ACTION_NAME, SearchTransportService.FREE_CONTEXT_ACTION_NAME);
String[] randomIndicesOrAliases = randomIndicesOrAliases();
for (int i = 0; i < randomIndicesOrAliases.length; i++) {
client().prepareIndex(randomIndicesOrAliases[i], "type", "id-" + i).setSource("field", "value").get();
}
refresh();
SearchRequest searchRequest = new SearchRequest(randomIndicesOrAliases).searchType(SearchType.QUERY_THEN_FETCH);
SearchResponse searchResponse = internalCluster().coordOnlyNodeClient().search(searchRequest).actionGet();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().getTotalHits(), greaterThan(0L));
clearInterceptedActions();
assertSameIndices(searchRequest, SearchTransportService.QUERY_ACTION_NAME, SearchTransportService.FETCH_ID_ACTION_NAME);
//free context messages are not necessarily sent, but if they are, check their indices
assertSameIndicesOptionalRequests(searchRequest, SearchTransportService.FREE_CONTEXT_ACTION_NAME);
}
public void testSearchDfsQueryThenFetch() throws Exception {
interceptTransportActions(SearchTransportService.DFS_ACTION_NAME, SearchTransportService.QUERY_ID_ACTION_NAME,
SearchTransportService.FETCH_ID_ACTION_NAME, SearchTransportService.FREE_CONTEXT_ACTION_NAME);
String[] randomIndicesOrAliases = randomIndicesOrAliases();
for (int i = 0; i < randomIndicesOrAliases.length; i++) {
client().prepareIndex(randomIndicesOrAliases[i], "type", "id-" + i).setSource("field", "value").get();
}
refresh();
SearchRequest searchRequest = new SearchRequest(randomIndicesOrAliases).searchType(SearchType.DFS_QUERY_THEN_FETCH);
SearchResponse searchResponse = internalCluster().coordOnlyNodeClient().search(searchRequest).actionGet();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().getTotalHits(), greaterThan(0L));
clearInterceptedActions();
assertSameIndices(searchRequest, SearchTransportService.DFS_ACTION_NAME, SearchTransportService.QUERY_ID_ACTION_NAME,
SearchTransportService.FETCH_ID_ACTION_NAME);
//free context messages are not necessarily sent, but if they are, check their indices
assertSameIndicesOptionalRequests(searchRequest, SearchTransportService.FREE_CONTEXT_ACTION_NAME);
}
private static void assertSameIndices(IndicesRequest originalRequest, String... actions) {
assertSameIndices(originalRequest, false, actions);
}
private static void assertSameIndicesOptionalRequests(IndicesRequest originalRequest, String... actions) {
assertSameIndices(originalRequest, true, actions);
}
private static void assertSameIndices(IndicesRequest originalRequest, boolean optional, String... actions) {
for (String action : actions) {
List<TransportRequest> requests = consumeTransportRequests(action);
if (!optional) {
assertThat("no internal requests intercepted for action [" + action + "]", requests.size(), greaterThan(0));
}
for (TransportRequest internalRequest : requests) {
IndicesRequest indicesRequest = convertRequest(internalRequest);
assertThat(internalRequest.getClass().getName(), indicesRequest.indices(), equalTo(originalRequest.indices()));
assertThat(indicesRequest.indicesOptions(), equalTo(originalRequest.indicesOptions()));
}
}
}
private static void assertIndicesSubset(List<String> indices, String... actions) {
//indices returned by each bulk shard request need to be a subset of the original indices
for (String action : actions) {
List<TransportRequest> requests = consumeTransportRequests(action);
assertThat("no internal requests intercepted for action [" + action + "]", requests.size(), greaterThan(0));
for (TransportRequest internalRequest : requests) {
IndicesRequest indicesRequest = convertRequest(internalRequest);
for (String index : indicesRequest.indices()) {
assertThat(indices, hasItem(index));
}
}
}
}
static IndicesRequest convertRequest(TransportRequest request) {
final IndicesRequest indicesRequest;
if (request instanceof IndicesRequest) {
indicesRequest = (IndicesRequest) request;
} else {
indicesRequest = TransportReplicationActionTests.resolveRequest(request);
}
return indicesRequest;
}
private String randomIndexOrAlias() {
String index = randomFrom(indices);
if (randomBoolean()) {
return index + "-alias";
} else {
return index;
}
}
private String[] randomIndicesOrAliases() {
int count = randomIntBetween(1, indices.size() * 2); //every index has an alias
String[] indices = new String[count];
for (int i = 0; i < count; i++) {
indices[i] = randomIndexOrAlias();
}
return indices;
}
private String[] randomUniqueIndicesOrAliases() {
Set<String> uniqueIndices = new HashSet<>();
int count = randomIntBetween(1, this.indices.size());
while (uniqueIndices.size() < count) {
uniqueIndices.add(randomFrom(this.indices));
}
String[] indices = new String[count];
int i = 0;
for (String index : uniqueIndices) {
indices[i++] = randomBoolean() ? index + "-alias" : index;
}
return indices;
}
private static void assertAllRequestsHaveBeenConsumed() {
Iterable<PluginsService> pluginsServices = internalCluster().getInstances(PluginsService.class);
for (PluginsService pluginsService : pluginsServices) {
Set<Map.Entry<String, List<TransportRequest>>> entries =
pluginsService.filterPlugins(InterceptingTransportService.TestPlugin.class).stream().findFirst().get()
.instance.requests.entrySet();
assertThat(entries, emptyIterable());
}
}
private static void clearInterceptedActions() {
Iterable<PluginsService> pluginsServices = internalCluster().getInstances(PluginsService.class);
for (PluginsService pluginsService : pluginsServices) {
pluginsService.filterPlugins(InterceptingTransportService.TestPlugin.class).stream().findFirst().get()
.instance.clearInterceptedActions();
}
}
private static void interceptTransportActions(String... actions) {
Iterable<PluginsService> pluginsServices = internalCluster().getInstances(PluginsService.class);
for (PluginsService pluginsService : pluginsServices) {
pluginsService.filterPlugins(InterceptingTransportService.TestPlugin.class).stream().findFirst().get()
.instance.interceptTransportActions(actions);
}
}
private static List<TransportRequest> consumeTransportRequests(String action) {
List<TransportRequest> requests = new ArrayList<>();
Iterable<PluginsService> pluginsServices = internalCluster().getInstances(PluginsService.class);
for (PluginsService pluginsService : pluginsServices) {
List<TransportRequest> transportRequests = pluginsService.filterPlugins(InterceptingTransportService.TestPlugin.class)
.stream().findFirst().get().instance.consumeRequests(action);
if (transportRequests != null) {
requests.addAll(transportRequests);
}
}
return requests;
}
public static class InterceptingTransportService implements TransportInterceptor {
public static class TestPlugin extends Plugin implements NetworkPlugin {
public final InterceptingTransportService instance = new InterceptingTransportService();
@Override
public List<TransportInterceptor> getTransportInterceptors(NamedWriteableRegistry namedWriteableRegistry,
ThreadContext threadContext) {
return Collections.singletonList(instance);
}
}
private final Set<String> actions = new HashSet<>();
private final Map<String, List<TransportRequest>> requests = new HashMap<>();
@Override
public <T extends TransportRequest> TransportRequestHandler<T> interceptHandler(String action, String executor,
boolean forceExecution,
TransportRequestHandler<T> actualHandler) {
return new InterceptingRequestHandler<>(action, actualHandler);
}
synchronized List<TransportRequest> consumeRequests(String action) {
return requests.remove(action);
}
synchronized void interceptTransportActions(String... actions) {
Collections.addAll(this.actions, actions);
}
synchronized void clearInterceptedActions() {
actions.clear();
}
private class InterceptingRequestHandler<T extends TransportRequest> implements TransportRequestHandler<T> {
private final TransportRequestHandler<T> requestHandler;
private final String action;
InterceptingRequestHandler(String action, TransportRequestHandler<T> requestHandler) {
this.requestHandler = requestHandler;
this.action = action;
}
@Override
public void messageReceived(T request, TransportChannel channel, Task task) throws Exception {
synchronized (InterceptingTransportService.this) {
if (actions.contains(action)) {
List<TransportRequest> requestList = requests.get(action);
if (requestList == null) {
requestList = new ArrayList<>();
requestList.add(request);
requests.put(action, requestList);
} else {
requestList.add(request);
}
}
}
requestHandler.messageReceived(request, channel, task);
}
@Override
public void messageReceived(T request, TransportChannel channel) throws Exception {
messageReceived(request, channel, null);
}
}
}
}