/*
* 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.index.reindex;
import org.elasticsearch.Version;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.Streamable;
import org.elasticsearch.common.lucene.uid.Versions;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.tasks.TaskId;
import org.elasticsearch.test.ESTestCase;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static org.apache.lucene.util.TestUtil.randomSimpleString;
import static org.elasticsearch.common.unit.TimeValue.parseTimeValue;
/**
* Round trip tests for all Streamable things declared in this plugin.
*/
public class RoundTripTests extends ESTestCase {
public void testReindexRequest() throws IOException {
ReindexRequest reindex = new ReindexRequest(new SearchRequest(), new IndexRequest());
randomRequest(reindex);
reindex.getDestination().version(randomFrom(Versions.MATCH_ANY, Versions.MATCH_DELETED, 12L, 1L, 123124L, 12L));
reindex.getDestination().index("test");
if (randomBoolean()) {
int port = between(1, Integer.MAX_VALUE);
BytesReference query = new BytesArray(randomAlphaOfLength(5));
String username = randomBoolean() ? randomAlphaOfLength(5) : null;
String password = username != null && randomBoolean() ? randomAlphaOfLength(5) : null;
int headersCount = randomBoolean() ? 0 : between(1, 10);
Map<String, String> headers = new HashMap<>(headersCount);
while (headers.size() < headersCount) {
headers.put(randomAlphaOfLength(5), randomAlphaOfLength(5));
}
TimeValue socketTimeout = parseTimeValue(randomPositiveTimeValue(), "socketTimeout");
TimeValue connectTimeout = parseTimeValue(randomPositiveTimeValue(), "connectTimeout");
reindex.setRemoteInfo(new RemoteInfo(randomAlphaOfLength(5), randomAlphaOfLength(5), port, query, username, password, headers,
socketTimeout, connectTimeout));
}
ReindexRequest tripped = new ReindexRequest();
roundTrip(reindex, tripped);
assertRequestEquals(reindex, tripped);
// Try slices with a version that doesn't support slices. That should fail.
reindex.setSlices(between(2, 1000));
Exception e = expectThrows(IllegalArgumentException.class, () -> roundTrip(Version.V_5_0_0_rc1, reindex, null));
assertEquals("Attempting to send sliced reindex-style request to a node that doesn't support it. "
+ "Version is [5.0.0-rc1] but must be [5.1.1]", e.getMessage());
// Try without slices with a version that doesn't support slices. That should work.
tripped = new ReindexRequest();
reindex.setSlices(1);
roundTrip(Version.V_5_0_0_rc1, reindex, tripped);
assertRequestEquals(Version.V_5_0_0_rc1, reindex, tripped);
}
public void testUpdateByQueryRequest() throws IOException {
UpdateByQueryRequest update = new UpdateByQueryRequest(new SearchRequest());
randomRequest(update);
if (randomBoolean()) {
update.setPipeline(randomAlphaOfLength(5));
}
UpdateByQueryRequest tripped = new UpdateByQueryRequest();
roundTrip(update, tripped);
assertRequestEquals(update, tripped);
assertEquals(update.getPipeline(), tripped.getPipeline());
// Try slices with a version that doesn't support slices. That should fail.
update.setSlices(between(2, 1000));
Exception e = expectThrows(IllegalArgumentException.class, () -> roundTrip(Version.V_5_0_0_rc1, update, null));
assertEquals("Attempting to send sliced reindex-style request to a node that doesn't support it. "
+ "Version is [5.0.0-rc1] but must be [5.1.1]", e.getMessage());
// Try without slices with a version that doesn't support slices. That should work.
tripped = new UpdateByQueryRequest();
update.setSlices(1);
roundTrip(Version.V_5_0_0_rc1, update, tripped);
assertRequestEquals(update, tripped);
assertEquals(update.getPipeline(), tripped.getPipeline());
}
public void testDeleteByQueryRequest() throws IOException {
DeleteByQueryRequest delete = new DeleteByQueryRequest(new SearchRequest());
randomRequest(delete);
DeleteByQueryRequest tripped = new DeleteByQueryRequest();
roundTrip(delete, tripped);
assertRequestEquals(delete, tripped);
// Try slices with a version that doesn't support slices. That should fail.
delete.setSlices(between(2, 1000));
Exception e = expectThrows(IllegalArgumentException.class, () -> roundTrip(Version.V_5_0_0_rc1, delete, null));
assertEquals("Attempting to send sliced reindex-style request to a node that doesn't support it. "
+ "Version is [5.0.0-rc1] but must be [5.1.1]", e.getMessage());
// Try without slices with a version that doesn't support slices. That should work.
tripped = new DeleteByQueryRequest();
delete.setSlices(1);
roundTrip(Version.V_5_0_0_rc1, delete, tripped);
assertRequestEquals(delete, tripped);
}
private void randomRequest(AbstractBulkByScrollRequest<?> request) {
request.getSearchRequest().indices("test");
request.getSearchRequest().source().size(between(1, 1000));
request.setSize(random().nextBoolean() ? between(1, Integer.MAX_VALUE) : -1);
request.setAbortOnVersionConflict(random().nextBoolean());
request.setRefresh(rarely());
request.setTimeout(TimeValue.parseTimeValue(randomTimeValue(), null, "test"));
request.setWaitForActiveShards(randomIntBetween(0, 10));
request.setRequestsPerSecond(between(0, Integer.MAX_VALUE));
request.setSlices(between(1, Integer.MAX_VALUE));
}
private void randomRequest(AbstractBulkIndexByScrollRequest<?> request) {
randomRequest((AbstractBulkByScrollRequest<?>) request);
request.setScript(random().nextBoolean() ? null : randomScript());
}
private void assertRequestEquals(Version version, ReindexRequest request, ReindexRequest tripped) {
assertRequestEquals((AbstractBulkIndexByScrollRequest<?>) request, (AbstractBulkIndexByScrollRequest<?>) tripped);
assertEquals(request.getDestination().version(), tripped.getDestination().version());
assertEquals(request.getDestination().index(), tripped.getDestination().index());
if (request.getRemoteInfo() == null) {
assertNull(tripped.getRemoteInfo());
} else {
assertNotNull(tripped.getRemoteInfo());
assertEquals(request.getRemoteInfo().getScheme(), tripped.getRemoteInfo().getScheme());
assertEquals(request.getRemoteInfo().getHost(), tripped.getRemoteInfo().getHost());
assertEquals(request.getRemoteInfo().getQuery(), tripped.getRemoteInfo().getQuery());
assertEquals(request.getRemoteInfo().getUsername(), tripped.getRemoteInfo().getUsername());
assertEquals(request.getRemoteInfo().getPassword(), tripped.getRemoteInfo().getPassword());
assertEquals(request.getRemoteInfo().getHeaders(), tripped.getRemoteInfo().getHeaders());
if (version.onOrAfter(Version.V_5_2_0_UNRELEASED)) {
assertEquals(request.getRemoteInfo().getSocketTimeout(), tripped.getRemoteInfo().getSocketTimeout());
assertEquals(request.getRemoteInfo().getConnectTimeout(), tripped.getRemoteInfo().getConnectTimeout());
} else {
assertEquals(RemoteInfo.DEFAULT_SOCKET_TIMEOUT, tripped.getRemoteInfo().getSocketTimeout());
assertEquals(RemoteInfo.DEFAULT_CONNECT_TIMEOUT, tripped.getRemoteInfo().getConnectTimeout());
}
}
}
private void assertRequestEquals(AbstractBulkIndexByScrollRequest<?> request,
AbstractBulkIndexByScrollRequest<?> tripped) {
assertRequestEquals((AbstractBulkByScrollRequest<?>) request, (AbstractBulkByScrollRequest<?>) tripped);
assertEquals(request.getScript(), tripped.getScript());
}
private void assertRequestEquals(AbstractBulkByScrollRequest<?> request, AbstractBulkByScrollRequest<?> tripped) {
assertArrayEquals(request.getSearchRequest().indices(), tripped.getSearchRequest().indices());
assertEquals(request.getSearchRequest().source().size(), tripped.getSearchRequest().source().size());
assertEquals(request.isAbortOnVersionConflict(), tripped.isAbortOnVersionConflict());
assertEquals(request.isRefresh(), tripped.isRefresh());
assertEquals(request.getTimeout(), tripped.getTimeout());
assertEquals(request.getWaitForActiveShards(), tripped.getWaitForActiveShards());
assertEquals(request.getRetryBackoffInitialTime(), tripped.getRetryBackoffInitialTime());
assertEquals(request.getMaxRetries(), tripped.getMaxRetries());
assertEquals(request.getRequestsPerSecond(), tripped.getRequestsPerSecond(), 0d);
}
public void testRethrottleRequest() throws IOException {
RethrottleRequest request = new RethrottleRequest();
request.setRequestsPerSecond((float) randomDoubleBetween(0, Float.POSITIVE_INFINITY, false));
if (randomBoolean()) {
request.setActions(randomFrom(UpdateByQueryAction.NAME, ReindexAction.NAME));
} else {
request.setTaskId(new TaskId(randomAlphaOfLength(5), randomLong()));
}
RethrottleRequest tripped = new RethrottleRequest();
roundTrip(request, tripped);
assertEquals(request.getRequestsPerSecond(), tripped.getRequestsPerSecond(), 0.00001);
assertArrayEquals(request.getActions(), tripped.getActions());
assertEquals(request.getTaskId(), tripped.getTaskId());
}
private void roundTrip(Streamable example, Streamable empty) throws IOException {
roundTrip(Version.CURRENT, example, empty);
}
private void roundTrip(Version version, Streamable example, Streamable empty) throws IOException {
BytesStreamOutput out = new BytesStreamOutput();
out.setVersion(version);
example.writeTo(out);
StreamInput in = out.bytes().streamInput();
in.setVersion(version);
empty.readFrom(in);
}
private Script randomScript() {
ScriptType type = randomFrom(ScriptType.values());
String lang = random().nextBoolean() ? Script.DEFAULT_SCRIPT_LANG : randomSimpleString(random());
String idOrCode = randomSimpleString(random());
Map<String, Object> params = Collections.emptyMap();
return new Script(type, lang, idOrCode, params);
}
}