/* * 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.search; import org.elasticsearch.action.OriginalIndices; import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.cluster.routing.GroupShardsIterator; import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.index.Index; import org.elasticsearch.index.query.MatchAllQueryBuilder; import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.search.SearchPhaseResult; import org.elasticsearch.search.internal.AliasFilter; import org.elasticsearch.search.internal.ShardSearchTransportRequest; import org.elasticsearch.test.ESTestCase; import java.util.Collections; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThanOrEqualTo; public class AbstractSearchAsyncActionTests extends ESTestCase { private AbstractSearchAsyncAction<SearchPhaseResult> createAction( final boolean controlled, final AtomicLong expected) { final Runnable runnable; final TransportSearchAction.SearchTimeProvider timeProvider; if (controlled) { runnable = () -> expected.set(randomNonNegativeLong()); timeProvider = new TransportSearchAction.SearchTimeProvider(0, 0, expected::get); } else { runnable = () -> { long elapsed = spinForAtLeastNMilliseconds(randomIntBetween(1, 10)); expected.set(elapsed); }; timeProvider = new TransportSearchAction.SearchTimeProvider( 0, System.nanoTime(), System::nanoTime); } return new AbstractSearchAsyncAction<SearchPhaseResult>("test", null, null, null, Collections.singletonMap("foo", new AliasFilter(new MatchAllQueryBuilder())), Collections.singletonMap("foo", 2.0f), null, new SearchRequest(), null, new GroupShardsIterator<>(Collections.singletonList( new SearchShardIterator(null, null, Collections.emptyList(), null))), timeProvider, 0, null, new InitialSearchPhase.SearchPhaseResults<>(10)) { @Override protected SearchPhase getNextPhase(final SearchPhaseResults<SearchPhaseResult> results, final SearchPhaseContext context) { return null; } @Override protected void executePhaseOnShard(final SearchShardIterator shardIt, final ShardRouting shard, final SearchActionListener<SearchPhaseResult> listener) { } @Override long buildTookInMillis() { runnable.run(); return super.buildTookInMillis(); } }; } public void testTookWithControlledClock() { runTestTook(true); } public void testTookWithRealClock() { runTestTook(false); } private void runTestTook(final boolean controlled) { final AtomicLong expected = new AtomicLong(); AbstractSearchAsyncAction<SearchPhaseResult> action = createAction(controlled, expected); final long actual = action.buildTookInMillis(); if (controlled) { // with a controlled clock, we can assert the exact took time assertThat(actual, equalTo(TimeUnit.NANOSECONDS.toMillis(expected.get()))); } else { // with a real clock, the best we can say is that it took as long as we spun for assertThat(actual, greaterThanOrEqualTo(TimeUnit.NANOSECONDS.toMillis(expected.get()))); } } public void testBuildShardSearchTransportRequest() { final AtomicLong expected = new AtomicLong(); AbstractSearchAsyncAction<SearchPhaseResult> action = createAction(false, expected); SearchShardIterator iterator = new SearchShardIterator("test-cluster", new ShardId(new Index("name", "foo"), 1), Collections.emptyList(), new OriginalIndices(new String[] {"name", "name1"}, IndicesOptions.strictExpand())); ShardSearchTransportRequest shardSearchTransportRequest = action.buildShardSearchRequest(iterator); assertEquals(IndicesOptions.strictExpand(), shardSearchTransportRequest.indicesOptions()); assertArrayEquals(new String[] {"name", "name1"}, shardSearchTransportRequest.indices()); assertEquals(new MatchAllQueryBuilder(), shardSearchTransportRequest.filteringAliases()); assertEquals(2.0f, shardSearchTransportRequest.indexBoost(), 0.0f); } }