/*
* 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.index;
import org.elasticsearch.Version;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.support.ActiveShardCount;
import org.elasticsearch.action.support.replication.ReplicationResponse;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.index.VersionType;
import org.elasticsearch.index.seqno.SequenceNumbersService;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.test.ESTestCase;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashSet;
import java.util.Set;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
public class IndexRequestTests extends ESTestCase {
public void testIndexRequestOpTypeFromString() throws Exception {
String create = "create";
String index = "index";
String createUpper = "CREATE";
String indexUpper = "INDEX";
IndexRequest indexRequest = new IndexRequest("");
indexRequest.opType(create);
assertThat(indexRequest.opType() , equalTo(DocWriteRequest.OpType.CREATE));
indexRequest.opType(createUpper);
assertThat(indexRequest.opType() , equalTo(DocWriteRequest.OpType.CREATE));
indexRequest.opType(index);
assertThat(indexRequest.opType() , equalTo(DocWriteRequest.OpType.INDEX));
indexRequest.opType(indexUpper);
assertThat(indexRequest.opType() , equalTo(DocWriteRequest.OpType.INDEX));
}
public void testReadBogusString() {
try {
IndexRequest indexRequest = new IndexRequest("");
indexRequest.opType("foobar");
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
assertThat(e.getMessage(), equalTo("opType must be 'create' or 'index', found: [foobar]"));
}
}
public void testCreateOperationRejectsVersions() {
Set<VersionType> allButInternalSet = new HashSet<>(Arrays.asList(VersionType.values()));
allButInternalSet.remove(VersionType.INTERNAL);
VersionType[] allButInternal = allButInternalSet.toArray(new VersionType[]{});
IndexRequest request = new IndexRequest("index", "type", "1");
request.opType(IndexRequest.OpType.CREATE);
request.versionType(randomFrom(allButInternal));
assertThat(request.validate().validationErrors(), not(empty()));
request.versionType(VersionType.INTERNAL);
request.version(randomIntBetween(0, Integer.MAX_VALUE));
assertThat(request.validate().validationErrors(), not(empty()));
}
public void testIndexingRejectsLongIds() {
String id = randomAlphaOfLength(511);
IndexRequest request = new IndexRequest("index", "type", id);
request.source("{}", XContentType.JSON);
ActionRequestValidationException validate = request.validate();
assertNull(validate);
id = randomAlphaOfLength(512);
request = new IndexRequest("index", "type", id);
request.source("{}", XContentType.JSON);
validate = request.validate();
assertNull(validate);
id = randomAlphaOfLength(513);
request = new IndexRequest("index", "type", id);
request.source("{}", XContentType.JSON);
validate = request.validate();
assertThat(validate, notNullValue());
assertThat(validate.getMessage(),
containsString("id is too long, must be no longer than 512 bytes but was: 513"));
}
public void testWaitForActiveShards() {
IndexRequest request = new IndexRequest("index", "type");
final int count = randomIntBetween(0, 10);
request.waitForActiveShards(ActiveShardCount.from(count));
assertEquals(request.waitForActiveShards(), ActiveShardCount.from(count));
// test negative shard count value not allowed
expectThrows(IllegalArgumentException.class, () -> request.waitForActiveShards(ActiveShardCount.from(randomIntBetween(-10, -1))));
}
public void testAutoGenIdTimestampIsSet() {
IndexRequest request = new IndexRequest("index", "type");
request.process(null, "index");
assertTrue("expected > 0 but got: " + request.getAutoGeneratedTimestamp(), request.getAutoGeneratedTimestamp() > 0);
request = new IndexRequest("index", "type", "1");
request.process(null, "index");
assertEquals(IndexRequest.UNSET_AUTO_GENERATED_TIMESTAMP, request.getAutoGeneratedTimestamp());
}
public void testIndexResponse() {
ShardId shardId = new ShardId(randomAlphaOfLengthBetween(3, 10), randomAlphaOfLengthBetween(3, 10), randomIntBetween(0, 1000));
String type = randomAlphaOfLengthBetween(3, 10);
String id = randomAlphaOfLengthBetween(3, 10);
long version = randomLong();
boolean created = randomBoolean();
IndexResponse indexResponse = new IndexResponse(shardId, type, id, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, version, created);
int total = randomIntBetween(1, 10);
int successful = randomIntBetween(1, 10);
ReplicationResponse.ShardInfo shardInfo = new ReplicationResponse.ShardInfo(total, successful);
indexResponse.setShardInfo(shardInfo);
boolean forcedRefresh = false;
if (randomBoolean()) {
forcedRefresh = randomBoolean();
indexResponse.setForcedRefresh(forcedRefresh);
}
assertEquals(type, indexResponse.getType());
assertEquals(id, indexResponse.getId());
assertEquals(version, indexResponse.getVersion());
assertEquals(shardId, indexResponse.getShardId());
assertEquals(created ? RestStatus.CREATED : RestStatus.OK, indexResponse.status());
assertEquals(total, indexResponse.getShardInfo().getTotal());
assertEquals(successful, indexResponse.getShardInfo().getSuccessful());
assertEquals(forcedRefresh, indexResponse.forcedRefresh());
assertEquals("IndexResponse[index=" + shardId.getIndexName() + ",type=" + type + ",id="+ id +
",version=" + version + ",result=" + (created ? "created" : "updated") +
",seqNo=" + SequenceNumbersService.UNASSIGNED_SEQ_NO +
",primaryTerm=" + 0 +
",shards={\"total\":" + total + ",\"successful\":" + successful + ",\"failed\":0}]",
indexResponse.toString());
}
public void testIndexRequestXContentSerialization() throws IOException {
IndexRequest indexRequest = new IndexRequest("foo", "bar", "1");
indexRequest.source("{}", XContentType.JSON);
assertEquals(XContentType.JSON, indexRequest.getContentType());
BytesStreamOutput out = new BytesStreamOutput();
indexRequest.writeTo(out);
StreamInput in = StreamInput.wrap(out.bytes().toBytesRef().bytes);
IndexRequest serialized = new IndexRequest();
serialized.readFrom(in);
assertEquals(XContentType.JSON, serialized.getContentType());
assertEquals(new BytesArray("{}"), serialized.source());
}
public void testIndexRequestXContentSerializationBwc() throws IOException {
final byte[] data = Base64.getDecoder().decode("AAD////+AgQDZm9vAAAAAQNiYXIBATEAAAAAAnt9AP/////////9AAAA//////////8AAAAAAAA=");
final Version version = randomFrom(Version.V_5_0_0, Version.V_5_0_1, Version.V_5_0_2,
Version.V_5_0_3_UNRELEASED, Version.V_5_1_1_UNRELEASED, Version.V_5_1_2_UNRELEASED, Version.V_5_2_0_UNRELEASED);
try (StreamInput in = StreamInput.wrap(data)) {
in.setVersion(version);
IndexRequest serialized = new IndexRequest();
serialized.readFrom(in);
assertEquals(XContentType.JSON, serialized.getContentType());
assertEquals("{}", serialized.source().utf8ToString());
// don't test writing to earlier versions since output differs due to no timestamp
}
}
// reindex makes use of index requests without a source so this needs to be handled
public void testSerializationOfEmptyRequestWorks() throws IOException {
IndexRequest request = new IndexRequest("index", "type");
assertNull(request.getContentType());
try (BytesStreamOutput out = new BytesStreamOutput()) {
request.writeTo(out);
try (StreamInput in = out.bytes().streamInput()) {
IndexRequest serialized = new IndexRequest();
serialized.readFrom(in);
assertNull(request.getContentType());
assertEquals("index", request.index());
assertEquals("type", request.type());
}
}
}
public void testToStringSizeLimit() throws UnsupportedEncodingException {
IndexRequest request = new IndexRequest("index", "type");
String source = "{\"name\":\"value\"}";
request.source(source, XContentType.JSON);
assertEquals("index {[index][type][null], source[" + source + "]}", request.toString());
source = "{\"name\":\"" + randomUnicodeOfLength(IndexRequest.MAX_SOURCE_LENGTH_IN_TOSTRING) + "\"}";
request.source(source, XContentType.JSON);
int actualBytes = source.getBytes("UTF-8").length;
assertEquals("index {[index][type][null], source[n/a, actual length: [" + new ByteSizeValue(actualBytes).toString() +
"], max length: " + new ByteSizeValue(IndexRequest.MAX_SOURCE_LENGTH_IN_TOSTRING).toString() + "]}", request.toString());
}
}