/*
* 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.common.xcontent;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParseException;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.Constants;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.io.PathUtils;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.xcontent.XContentParser.Token;
import org.elasticsearch.test.ESTestCase;
import org.hamcrest.Matcher;
import org.hamcrest.Matchers;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.Instant;
import org.joda.time.ReadableInstant;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.startsWith;
public abstract class BaseXContentTestCase extends ESTestCase {
protected abstract XContentType xcontentType();
private XContentBuilder builder() throws IOException {
return XContentBuilder.builder(xcontentType().xContent());
}
public void testContentType() throws IOException {
assertThat(builder().contentType(), equalTo(xcontentType()));
}
public void testStartEndObject() throws IOException {
expectUnclosedException(() -> builder().startObject().bytes());
expectUnclosedException(() -> builder().startObject().close());
expectUnclosedException(() -> builder().startObject().string());
expectObjectException(() -> builder().endObject().bytes());
expectObjectException(() -> builder().endObject().close());
expectObjectException(() -> builder().endObject().string());
expectValueException(() -> builder().startObject("foo").endObject());
expectNonNullFieldException(() -> builder().startObject().startObject(null));
assertResult("{}", () -> builder().startObject().endObject());
assertResult("{'foo':{}}", () -> builder().startObject().startObject("foo").endObject().endObject());
assertResult("{'foo':{'bar':{}}}", () -> builder()
.startObject()
.startObject("foo")
.startObject("bar")
.endObject()
.endObject()
.endObject());
}
public void testStartEndArray() throws IOException {
expectUnclosedException(() -> builder().startArray().bytes());
expectUnclosedException(() -> builder().startArray().close());
expectUnclosedException(() -> builder().startArray().string());
expectArrayException(() -> builder().endArray().bytes());
expectArrayException(() -> builder().endArray().close());
expectArrayException(() -> builder().endArray().string());
expectValueException(() -> builder().startArray("foo").endObject());
expectFieldException(() -> builder().startObject().startArray().endArray().endObject());
expectNonNullFieldException(() -> builder().startObject().startArray(null).endArray().endObject());
assertResult("{'foo':[]}", () -> builder().startObject().startArray("foo").endArray().endObject());
assertResult("{'foo':[1,2,3]}", () -> builder()
.startObject()
.startArray("foo")
.value(1)
.value(2)
.value(3)
.endArray()
.endObject());
}
public void testField() throws IOException {
expectValueException(() -> builder().field("foo").bytes());
expectNonNullFieldException(() -> builder().field(null).bytes());
expectUnclosedException(() -> builder().startObject().field("foo").bytes());
assertResult("{'foo':'bar'}", () -> builder().startObject().field("foo").value("bar").endObject());
}
public void testNullField() throws IOException {
expectValueException(() -> builder().nullField("foo").bytes());
expectNonNullFieldException(() -> builder().nullField(null).bytes());
expectUnclosedException(() -> builder().startObject().nullField("foo").bytes());
assertResult("{'foo':null}", () -> builder().startObject().nullField("foo").endObject());
}
public void testNullValue() throws IOException {
assertResult("{'foo':null}", () -> builder().startObject().field("foo").nullValue().endObject());
}
public void testBooleans() throws IOException {
assertResult("{'boolean':null}", () -> builder().startObject().field("boolean", (Boolean) null).endObject());
assertResult("{'boolean':true}", () -> builder().startObject().field("boolean", Boolean.TRUE).endObject());
assertResult("{'boolean':false}", () -> builder().startObject().field("boolean", Boolean.FALSE).endObject());
assertResult("{'boolean':[true,false,true]}", () -> builder().startObject().array("boolean", true, false, true).endObject());
assertResult("{'boolean':[false,true]}", () -> builder().startObject().array("boolean", new boolean[]{false, true}).endObject());
assertResult("{'boolean':null}", () -> builder().startObject().array("boolean", (boolean[]) null).endObject());
assertResult("{'boolean':[]}", () -> builder().startObject().array("boolean", new boolean[]{}).endObject());
assertResult("{'boolean':null}", () -> builder().startObject().field("boolean").value((Boolean) null).endObject());
assertResult("{'boolean':true}", () -> builder().startObject().field("boolean").value(Boolean.TRUE).endObject());
assertResult("{'boolean':false}", () -> builder().startObject().field("boolean").value(Boolean.FALSE).endObject());
}
public void testBytes() throws IOException {
assertResult("{'byte':null}", () -> builder().startObject().field("byte", (Byte) null).endObject());
assertResult("{'byte':0}", () -> builder().startObject().field("byte", (byte) 0).endObject());
assertResult("{'byte':1}", () -> builder().startObject().field("byte", (byte) 1).endObject());
assertResult("{'byte':null}", () -> builder().startObject().field("byte").value((Byte) null).endObject());
assertResult("{'byte':0}", () -> builder().startObject().field("byte").value((byte) 0).endObject());
assertResult("{'byte':1}", () -> builder().startObject().field("byte").value((byte) 1).endObject());
}
public void testDoubles() throws IOException {
assertResult("{'double':null}", () -> builder().startObject().field("double", (Double) null).endObject());
assertResult("{'double':42.5}", () -> builder().startObject().field("double", Double.valueOf(42.5)).endObject());
assertResult("{'double':1.2}", () -> builder().startObject().field("double", 1.2).endObject());
assertResult("{'double':[42.0,43.0,45]}", () -> builder().startObject().array("double", 42.0, 43.0, 45).endObject());
assertResult("{'double':null}", () -> builder().startObject().array("double", (double[]) null).endObject());
assertResult("{'double':[]}", () -> builder().startObject().array("double", new double[]{}).endObject());
assertResult("{'double':null}", () -> builder().startObject().field("double").value((Double) null).endObject());
assertResult("{'double':0.001}", () -> builder().startObject().field("double").value(0.001).endObject());
assertResult("{'double':[1.7976931348623157E308,4.9E-324]}", () -> builder()
.startObject()
.array("double", new double[]{Double.MAX_VALUE, Double.MIN_VALUE})
.endObject());
}
public void testFloats() throws IOException {
assertResult("{'float':null}", () -> builder().startObject().field("float", (Float) null).endObject());
assertResult("{'float':42.5}", () -> builder().startObject().field("float", Float.valueOf(42.5f)).endObject());
assertResult("{'float':1.2}", () -> builder().startObject().field("float", 1.2f).endObject());
assertResult("{'float':null}", () -> builder().startObject().array("float", (float[]) null).endObject());
assertResult("{'float':[]}", () -> builder().startObject().array("float", new float[]{}).endObject());
assertResult("{'float':null}", () -> builder().startObject().field("float").value((Float) null).endObject());
assertResult("{'float':9.9E-7}", () -> builder().startObject().field("float").value(0.00000099f).endObject());
assertResult("{'float':[42.0,43.0,45.666668]}", () -> builder()
.startObject()
.array("float", 42.0f, 43.0f, 45.66666667f)
.endObject());
assertResult("{'float':[3.4028235E38,1.4E-45]}", () -> builder()
.startObject()
.array("float", new float[]{Float.MAX_VALUE, Float.MIN_VALUE})
.endObject());
}
public void testIntegers() throws IOException {
assertResult("{'integer':null}", () -> builder().startObject().field("integer", (Integer) null).endObject());
assertResult("{'integer':42}", () -> builder().startObject().field("integer", Integer.valueOf(42)).endObject());
assertResult("{'integer':3}", () -> builder().startObject().field("integer", 3).endObject());
assertResult("{'integer':[1,3,5,7,11]}", () -> builder().startObject().array("integer", 1, 3, 5, 7, 11).endObject());
assertResult("{'integer':null}", () -> builder().startObject().array("integer", (int[]) null).endObject());
assertResult("{'integer':[]}", () -> builder().startObject().array("integer", new int[]{}).endObject());
assertResult("{'integer':null}", () -> builder().startObject().field("integer").value((Integer) null).endObject());
assertResult("{'integer':42}", () -> builder().startObject().field("integer").value(42).endObject());
assertResult("{'integer':[2147483647,-2147483648]}", () -> builder()
.startObject()
.array("integer", new int[]{Integer.MAX_VALUE, Integer.MIN_VALUE})
.endObject());
}
public void testLongs() throws IOException {
assertResult("{'long':null}", () -> builder().startObject().field("long", (Long) null).endObject());
assertResult("{'long':42}", () -> builder().startObject().field("long", Long.valueOf(42L)).endObject());
assertResult("{'long':9223372036854775807}", () -> builder().startObject().field("long", 9_223_372_036_854_775_807L).endObject());
assertResult("{'long':[1,3,5,7,11]}", () -> builder().startObject().array("long", 1L, 3L, 5L, 7L, 11L).endObject());
assertResult("{'long':null}", () -> builder().startObject().array("long", (long[]) null).endObject());
assertResult("{'long':[]}", () -> builder().startObject().array("long", new long[]{}).endObject());
assertResult("{'long':null}", () -> builder().startObject().field("long").value((Long) null).endObject());
assertResult("{'long':42}", () -> builder().startObject().field("long").value(42).endObject());
assertResult("{'long':[2147483647,-2147483648]}", () -> builder()
.startObject()
.array("long", new long[]{Integer.MAX_VALUE, Integer.MIN_VALUE})
.endObject());
}
public void testShorts() throws IOException {
assertResult("{'short':null}", () -> builder().startObject().field("short", (Short) null).endObject());
assertResult("{'short':5000}", () -> builder().startObject().field("short", Short.valueOf((short) 5000)).endObject());
assertResult("{'short':null}", () -> builder().startObject().array("short", (short[]) null).endObject());
assertResult("{'short':[]}", () -> builder().startObject().array("short", new short[]{}).endObject());
assertResult("{'short':null}", () -> builder().startObject().field("short").value((Short) null).endObject());
assertResult("{'short':42}", () -> builder().startObject().field("short").value((short) 42).endObject());
assertResult("{'short':[1,3,5,7,11]}", () -> builder()
.startObject()
.array("short", (short) 1, (short) 3, (short) 5, (short) 7, (short) 11)
.endObject());
assertResult("{'short':[32767,-32768]}", () -> builder()
.startObject()
.array("short", new short[]{Short.MAX_VALUE, Short.MIN_VALUE})
.endObject());
}
public void testStrings() throws IOException {
assertResult("{'string':null}", () -> builder().startObject().field("string", (String) null).endObject());
assertResult("{'string':'value'}", () -> builder().startObject().field("string", "value").endObject());
assertResult("{'string':''}", () -> builder().startObject().field("string", "").endObject());
assertResult("{'string':null}", () -> builder().startObject().array("string", (String[]) null).endObject());
assertResult("{'string':[]}", () -> builder().startObject().array("string", Strings.EMPTY_ARRAY).endObject());
assertResult("{'string':null}", () -> builder().startObject().field("string").value((String) null).endObject());
assertResult("{'string':'42'}", () -> builder().startObject().field("string").value("42").endObject());
assertResult("{'string':['a','b','c','d']}", () -> builder()
.startObject()
.array("string", "a", "b", "c", "d")
.endObject());
}
public void testBinaryField() throws Exception {
assertResult("{'binary':null}", () -> builder().startObject().field("binary", (byte[]) null).endObject());
final byte[] randomBytes = randomBytes();
BytesReference bytes = builder().startObject().field("binary", randomBytes).endObject().bytes();
XContentParser parser = createParser(xcontentType().xContent(), bytes);
assertSame(parser.nextToken(), Token.START_OBJECT);
assertSame(parser.nextToken(), Token.FIELD_NAME);
assertEquals(parser.currentName(), "binary");
assertTrue(parser.nextToken().isValue());
assertArrayEquals(randomBytes, parser.binaryValue());
assertSame(parser.nextToken(), Token.END_OBJECT);
assertNull(parser.nextToken());
}
public void testBinaryValue() throws Exception {
assertResult("{'binary':null}", () -> builder().startObject().field("binary").value((byte[]) null).endObject());
final byte[] randomBytes = randomBytes();
BytesReference bytes = builder().startObject().field("binary").value(randomBytes).endObject().bytes();
XContentParser parser = createParser(xcontentType().xContent(), bytes);
assertSame(parser.nextToken(), Token.START_OBJECT);
assertSame(parser.nextToken(), Token.FIELD_NAME);
assertEquals(parser.currentName(), "binary");
assertTrue(parser.nextToken().isValue());
assertArrayEquals(randomBytes, parser.binaryValue());
assertSame(parser.nextToken(), Token.END_OBJECT);
assertNull(parser.nextToken());
}
public void testBinaryValueWithOffsetLength() throws Exception {
assertResult("{'binary':null}", () -> builder().startObject().field("binary").value(null, 0, 0).endObject());
final byte[] randomBytes = randomBytes();
final int offset = randomIntBetween(0, randomBytes.length - 1);
final int length = randomIntBetween(1, Math.max(1, randomBytes.length - offset - 1));
XContentBuilder builder = builder().startObject();
if (randomBoolean()) {
builder.field("bin", randomBytes, offset, length);
} else {
builder.field("bin").value(randomBytes, offset, length);
}
builder.endObject();
XContentParser parser = createParser(xcontentType().xContent(), builder.bytes());
assertSame(parser.nextToken(), Token.START_OBJECT);
assertSame(parser.nextToken(), Token.FIELD_NAME);
assertEquals(parser.currentName(), "bin");
assertTrue(parser.nextToken().isValue());
assertArrayEquals(Arrays.copyOfRange(randomBytes, offset, offset + length), parser.binaryValue());
assertSame(parser.nextToken(), Token.END_OBJECT);
assertNull(parser.nextToken());
}
public void testBinaryUTF8() throws Exception {
assertResult("{'utf8':null}", () -> builder().startObject().utf8Field("utf8", null).endObject());
final BytesRef randomBytesRef = new BytesRef(randomBytes());
XContentBuilder builder = builder().startObject();
if (randomBoolean()) {
builder.utf8Field("utf8", randomBytesRef);
} else {
builder.field("utf8").utf8Value(randomBytesRef);
}
builder.endObject();
XContentParser parser = createParser(xcontentType().xContent(), builder.bytes());
assertSame(parser.nextToken(), Token.START_OBJECT);
assertSame(parser.nextToken(), Token.FIELD_NAME);
assertEquals(parser.currentName(), "utf8");
assertTrue(parser.nextToken().isValue());
assertThat(parser.utf8Bytes().utf8ToString(), equalTo(randomBytesRef.utf8ToString()));
assertSame(parser.nextToken(), Token.END_OBJECT);
assertNull(parser.nextToken());
}
public void testText() throws Exception {
assertResult("{'text':null}", () -> builder().startObject().field("text", (Text) null).endObject());
assertResult("{'text':''}", () -> builder().startObject().field("text", new Text("")).endObject());
assertResult("{'text':'foo bar'}", () -> builder().startObject().field("text", new Text("foo bar")).endObject());
final BytesReference random = new BytesArray(randomBytes());
XContentBuilder builder = builder().startObject().field("text", new Text(random)).endObject();
XContentParser parser = createParser(xcontentType().xContent(), builder.bytes());
assertSame(parser.nextToken(), Token.START_OBJECT);
assertSame(parser.nextToken(), Token.FIELD_NAME);
assertEquals(parser.currentName(), "text");
assertTrue(parser.nextToken().isValue());
assertThat(parser.utf8Bytes().utf8ToString(), equalTo(random.utf8ToString()));
assertSame(parser.nextToken(), Token.END_OBJECT);
assertNull(parser.nextToken());
}
public void testReadableInstant() throws Exception {
assertResult("{'instant':null}", () -> builder().startObject().field("instant", (ReadableInstant) null).endObject());
assertResult("{'instant':null}", () -> builder().startObject().field("instant").value((ReadableInstant) null).endObject());
final DateTime t1 = new DateTime(2016, 1, 1, 0, 0, DateTimeZone.UTC);
String expected = "{'t1':'2016-01-01T00:00:00.000Z'}";
assertResult(expected, () -> builder().startObject().field("t1", t1).endObject());
assertResult(expected, () -> builder().startObject().field("t1").value(t1).endObject());
final DateTime t2 = new DateTime(2016, 12, 25, 7, 59, 42, 213, DateTimeZone.UTC);
expected = "{'t2':'2016-12-25T07:59:42.213Z'}";
assertResult(expected, () -> builder().startObject().field("t2", t2).endObject());
assertResult(expected, () -> builder().startObject().field("t2").value(t2).endObject());
final DateTimeFormatter formatter = randomFrom(ISODateTimeFormat.basicDate(), ISODateTimeFormat.dateTimeNoMillis());
final DateTime t3 = DateTime.now();
expected = "{'t3':'" + formatter.print(t3) + "'}";
assertResult(expected, () -> builder().startObject().field("t3", t3, formatter).endObject());
assertResult(expected, () -> builder().startObject().field("t3").value(t3, formatter).endObject());
final DateTime t4 = new DateTime(randomDateTimeZone());
expected = "{'t4':'" + formatter.print(t4) + "'}";
assertResult(expected, () -> builder().startObject().field("t4", t4, formatter).endObject());
assertResult(expected, () -> builder().startObject().field("t4").value(t4, formatter).endObject());
long date = Math.abs(randomLong() % (2 * (long) 10e11)); // 1970-01-01T00:00:00Z - 2033-05-18T05:33:20.000+02:00
final DateTime t5 = new DateTime(date, randomDateTimeZone());
expected = "{'t5':'" + XContentBuilder.DEFAULT_DATE_PRINTER.print(t5) + "'}";
assertResult(expected, () -> builder().startObject().field("t5", t5).endObject());
assertResult(expected, () -> builder().startObject().field("t5").value(t5).endObject());
expected = "{'t5':'" + formatter.print(t5) + "'}";
assertResult(expected, () -> builder().startObject().field("t5", t5, formatter).endObject());
assertResult(expected, () -> builder().startObject().field("t5").value(t5, formatter).endObject());
Instant i1 = new Instant(1451606400000L); // 2016-01-01T00:00:00.000Z
expected = "{'i1':'2016-01-01T00:00:00.000Z'}";
assertResult(expected, () -> builder().startObject().field("i1", i1).endObject());
assertResult(expected, () -> builder().startObject().field("i1").value(i1).endObject());
Instant i2 = new Instant(1482652782213L); // 2016-12-25T07:59:42.213Z
expected = "{'i2':'" + formatter.print(i2) + "'}";
assertResult(expected, () -> builder().startObject().field("i2", i2, formatter).endObject());
assertResult(expected, () -> builder().startObject().field("i2").value(i2, formatter).endObject());
expectNonNullFormatterException(() -> builder().startObject().field("t3", t3, null).endObject());
expectNonNullFormatterException(() -> builder().startObject().field("t3").value(t3, null).endObject());
}
public void testDate() throws Exception {
assertResult("{'date':null}", () -> builder().startObject().field("date", (Date) null).endObject());
assertResult("{'date':null}", () -> builder().startObject().field("date").value((Date) null).endObject());
final Date d1 = new DateTime(2016, 1, 1, 0, 0, DateTimeZone.UTC).toDate();
assertResult("{'d1':'2016-01-01T00:00:00.000Z'}", () -> builder().startObject().field("d1", d1).endObject());
assertResult("{'d1':'2016-01-01T00:00:00.000Z'}", () -> builder().startObject().field("d1").value(d1).endObject());
final Date d2 = new DateTime(2016, 12, 25, 7, 59, 42, 213, DateTimeZone.UTC).toDate();
assertResult("{'d2':'2016-12-25T07:59:42.213Z'}", () -> builder().startObject().field("d2", d2).endObject());
assertResult("{'d2':'2016-12-25T07:59:42.213Z'}", () -> builder().startObject().field("d2").value(d2).endObject());
final DateTimeFormatter formatter = randomFrom(ISODateTimeFormat.basicDate(), ISODateTimeFormat.dateTimeNoMillis());
final Date d3 = DateTime.now().toDate();
String expected = "{'d3':'" + formatter.print(d3.getTime()) + "'}";
assertResult(expected, () -> builder().startObject().field("d3", d3, formatter).endObject());
assertResult(expected, () -> builder().startObject().field("d3").value(d3, formatter).endObject());
expectNonNullFormatterException(() -> builder().startObject().field("d3", d3, null).endObject());
expectNonNullFormatterException(() -> builder().startObject().field("d3").value(d3, null).endObject());
expectNonNullFormatterException(() -> builder().value(null, 1L));
}
public void testDateField() throws Exception {
final Date d = new DateTime(2016, 1, 1, 0, 0, DateTimeZone.UTC).toDate();
assertResult("{'date_in_millis':1451606400000}", () -> builder()
.startObject()
.dateField("date_in_millis", "date", d.getTime())
.endObject());
assertResult("{'date':'2016-01-01T00:00:00.000Z','date_in_millis':1451606400000}", () -> builder()
.humanReadable(true)
.startObject
().dateField("date_in_millis", "date", d.getTime())
.endObject());
}
public void testCalendar() throws Exception {
Calendar calendar = new DateTime(2016, 1, 1, 0, 0, DateTimeZone.UTC).toCalendar(Locale.ROOT);
assertResult("{'calendar':'2016-01-01T00:00:00.000Z'}", () -> builder()
.startObject()
.field("calendar")
.value(calendar)
.endObject());
}
public void testGeoPoint() throws Exception {
assertResult("{'geo':null}", () -> builder().startObject().field("geo", (GeoPoint) null).endObject());
assertResult("{'geo':{'lat':52.4267578125,'lon':13.271484375}}", () -> builder()
.startObject()
. field("geo", GeoPoint.fromGeohash("u336q"))
.endObject());
assertResult("{'geo':{'lat':52.5201416015625,'lon':13.4033203125}}", () -> builder()
.startObject()
.field("geo")
.value(GeoPoint.fromGeohash("u33dc1"))
.endObject());
}
public void testLatLon() throws Exception {
final String expected = "{'latlon':{'lat':13.271484375,'lon':52.4267578125}}";
assertResult(expected, () -> builder().startObject().latlon("latlon", 13.271484375, 52.4267578125).endObject());
assertResult(expected, () -> builder().startObject().field("latlon").latlon(13.271484375, 52.4267578125).endObject());
}
public void testPath() throws Exception {
assertResult("{'path':null}", () -> builder().startObject().field("path", (Path) null).endObject());
final Path path = PathUtils.get("first", "second", "third");
final String expected = Constants.WINDOWS ? "{'path':'first\\\\second\\\\third'}" : "{'path':'first/second/third'}";
assertResult(expected, () -> builder().startObject().field("path", path).endObject());
}
public void testObjects() throws Exception {
Map<String, Object[]> objects = new HashMap<>();
objects.put("{'objects':[false,true,false]}", new Object[]{false, true, false});
objects.put("{'objects':[1,1,2,3,5,8,13]}", new Object[]{(byte) 1, (byte) 1, (byte) 2, (byte) 3, (byte) 5, (byte) 8, (byte) 13});
objects.put("{'objects':[1.0,1.0,2.0,3.0,5.0,8.0,13.0]}", new Object[]{1.0d, 1.0d, 2.0d, 3.0d, 5.0d, 8.0d, 13.0d});
objects.put("{'objects':[1.0,1.0,2.0,3.0,5.0,8.0,13.0]}", new Object[]{1.0f, 1.0f, 2.0f, 3.0f, 5.0f, 8.0f, 13.0f});
objects.put("{'objects':[{'lat':45.759429931640625,'lon':4.8394775390625}]}", new Object[]{GeoPoint.fromGeohash("u05kq4k")});
objects.put("{'objects':[1,1,2,3,5,8,13]}", new Object[]{1, 1, 2, 3, 5, 8, 13});
objects.put("{'objects':[1,1,2,3,5,8,13]}", new Object[]{1L, 1L, 2L, 3L, 5L, 8L, 13L});
objects.put("{'objects':[1,1,2,3,5,8]}", new Object[]{(short) 1, (short) 1, (short) 2, (short) 3, (short) 5, (short) 8});
objects.put("{'objects':['a','b','c']}", new Object[]{"a", "b", "c"});
objects.put("{'objects':['a','b','c']}", new Object[]{new Text("a"), new Text(new BytesArray("b")), new Text("c")});
objects.put("{'objects':null}", null);
objects.put("{'objects':[null,null,null]}", new Object[]{null, null, null});
objects.put("{'objects':['OPEN','CLOSE']}", IndexMetaData.State.values());
objects.put("{'objects':[{'f1':'v1'},{'f2':'v2'}]}", new Object[]{singletonMap("f1", "v1"), singletonMap("f2", "v2")});
objects.put("{'objects':[[1,2,3],[4,5]]}", new Object[]{Arrays.asList(1, 2, 3), Arrays.asList(4, 5)});
final String paths = Constants.WINDOWS ? "{'objects':['a\\\\b\\\\c','d\\\\e']}" : "{'objects':['a/b/c','d/e']}";
objects.put(paths, new Object[]{PathUtils.get("a", "b", "c"), PathUtils.get("d", "e")});
final DateTimeFormatter formatter = XContentBuilder.DEFAULT_DATE_PRINTER;
final Date d1 = new DateTime(2016, 1, 1, 0, 0, DateTimeZone.UTC).toDate();
final Date d2 = new DateTime(2015, 1, 1, 0, 0, DateTimeZone.UTC).toDate();
objects.put("{'objects':['" + formatter.print(d1.getTime()) + "','" + formatter.print(d2.getTime()) + "']}", new Object[]{d1, d2});
final DateTime dt1 = DateTime.now();
final DateTime dt2 = new DateTime(2016, 12, 25, 7, 59, 42, 213, DateTimeZone.UTC);
objects.put("{'objects':['" + formatter.print(dt1) + "','2016-12-25T07:59:42.213Z']}", new Object[]{dt1, dt2});
final Calendar c1 = new DateTime(2012, 7, 7, 10, 23, DateTimeZone.UTC).toCalendar(Locale.ROOT);
final Calendar c2 = new DateTime(2014, 11, 16, 19, 36, DateTimeZone.UTC).toCalendar(Locale.ROOT);
objects.put("{'objects':['2012-07-07T10:23:00.000Z','2014-11-16T19:36:00.000Z']}", new Object[]{c1, c2});
final ToXContent x1 = (builder, params) -> builder.startObject().field("f1", "v1").field("f2", 2).array("f3", 3, 4, 5).endObject();
final ToXContent x2 = (builder, params) -> builder.startObject().field("f1", "v1").field("f2", x1).endObject();
objects.put("{'objects':[{'f1':'v1','f2':2,'f3':[3,4,5]},{'f1':'v1','f2':{'f1':'v1','f2':2,'f3':[3,4,5]}}]}", new Object[]{x1, x2});
for (Map.Entry<String, Object[]> o : objects.entrySet()) {
final String expected = o.getKey();
assertResult(expected, () -> builder().startObject().field("objects", o.getValue()).endObject());
assertResult(expected, () -> builder().startObject().field("objects").value(o.getValue()).endObject());
assertResult(expected, () -> builder().startObject().field("objects").values(o.getValue()).endObject());
assertResult(expected, () -> builder().startObject().array("objects", o.getValue()).endObject());
}
}
public void testObject() throws Exception {
Map<String, Object> object = new HashMap<>();
object.put("{'object':false}", Boolean.FALSE);
object.put("{'object':13}", (byte) 13);
object.put("{'object':5.0}", 5.0d);
object.put("{'object':8.0}", 8.0f);
object.put("{'object':{'lat':45.759429931640625,'lon':4.8394775390625}}", GeoPoint.fromGeohash("u05kq4k"));
object.put("{'object':3}", 3);
object.put("{'object':2}", 2L);
object.put("{'object':1}", (short) 1);
object.put("{'object':'string'}", "string");
object.put("{'object':'a'}", new Text("a"));
object.put("{'object':'b'}", new Text(new BytesArray("b")));
object.put("{'object':null}", null);
object.put("{'object':'OPEN'}", IndexMetaData.State.OPEN);
object.put("{'object':'NM'}", DistanceUnit.NAUTICALMILES);
object.put("{'object':{'f1':'v1'}}", singletonMap("f1", "v1"));
object.put("{'object':{'f1':{'f2':'v2'}}}", singletonMap("f1", singletonMap("f2", "v2")));
object.put("{'object':[1,2,3]}", Arrays.asList(1, 2, 3));
final String path = Constants.WINDOWS ? "{'object':'a\\\\b\\\\c'}" : "{'object':'a/b/c'}";
object.put(path, PathUtils.get("a", "b", "c"));
final DateTimeFormatter formatter = XContentBuilder.DEFAULT_DATE_PRINTER;
final Date d1 = new DateTime(2016, 1, 1, 0, 0, DateTimeZone.UTC).toDate();
object.put("{'object':'" + formatter.print(d1.getTime()) + "'}", d1);
final DateTime d2 = DateTime.now();
object.put("{'object':'" + formatter.print(d2) + "'}", d2);
final Calendar c1 = new DateTime(2010, 1, 1, 0, 0, DateTimeZone.UTC).toCalendar(Locale.ROOT);
object.put("{'object':'2010-01-01T00:00:00.000Z'}", c1);
final ToXContent x1 = (builder, params) -> builder.startObject().field("f1", "v1").field("f2", 2).array("f3", 3, 4, 5).endObject();
final ToXContent x2 = (builder, params) -> builder.startObject().field("f1", "v1").field("f2", x1).endObject();
object.put("{'object':{'f1':'v1','f2':{'f1':'v1','f2':2,'f3':[3,4,5]}}}", x2);
for (Map.Entry<String, Object> o : object.entrySet()) {
final String expected = o.getKey();
assertResult(expected, () -> builder().humanReadable(true).startObject().field("object", o.getValue()).endObject());
assertResult(expected, () -> builder().humanReadable(true).startObject().field("object").value(o.getValue()).endObject());
}
assertResult("{'objects':[null,null,null]}", () -> builder().startObject().array("objects", null, null, null).endObject());
}
public void testToXContent() throws Exception {
assertResult("{'xcontent':null}", () -> builder().startObject().field("xcontent", (ToXContent) null).endObject());
assertResult("{'xcontent':null}", () -> builder().startObject().field("xcontent").value((ToXContent) null).endObject());
ToXContent xcontent0 = (builder, params) -> {
builder.startObject();
builder.field("field", "value");
builder.array("array", "1", "2", "3");
builder.startObject("foo");
builder.field("bar", "baz");
builder.endObject();
builder.endObject();
return builder;
};
assertResult("{'field':'value','array':['1','2','3'],'foo':{'bar':'baz'}}", () -> builder().value(xcontent0));
assertResult("{'xcontent':{'field':'value','array':['1','2','3'],'foo':{'bar':'baz'}}}", () -> builder()
.startObject()
.field("xcontent", xcontent0)
.endObject());
ToXContent xcontent1 = (builder, params) -> {
builder.startObject();
builder.field("field", "value");
builder.startObject("foo");
builder.field("bar", "baz");
builder.endObject();
builder.endObject();
return builder;
};
ToXContent xcontent2 = (builder, params) -> {
builder.startObject();
builder.field("root", xcontent0);
builder.array("childs", xcontent0, xcontent1);
builder.endObject();
return builder;
};
assertResult("{'root':{" +
"'field':'value'," +
"'array':['1','2','3']," +
"'foo':{'bar':'baz'}" +
"}," +
"'childs':[" +
"{'field':'value','array':['1','2','3'],'foo':{'bar':'baz'}}," +
"{'field':'value','foo':{'bar':'baz'}}" +
"]}", () -> builder().value(xcontent2));
}
public void testMap() throws Exception {
Map<String, Map<String, ?>> maps = new HashMap<>();
maps.put("{'map':null}", (Map) null);
maps.put("{'map':{}}", Collections.emptyMap());
maps.put("{'map':{'key':'value'}}", singletonMap("key", "value"));
Map<String, Object> innerMap = new HashMap<>();
innerMap.put("string", "value");
innerMap.put("int", 42);
innerMap.put("long", 42L);
innerMap.put("long[]", new long[]{1L, 3L});
innerMap.put("path", PathUtils.get("path", "to", "file"));
innerMap.put("object", singletonMap("key", "value"));
final String path = Constants.WINDOWS ? "path\\\\to\\\\file" : "path/to/file";
maps.put("{'map':{'path':'" + path + "','string':'value','long[]':[1,3],'int':42,'long':42,'object':{'key':'value'}}}", innerMap);
for (Map.Entry<String, Map<String, ?>> m : maps.entrySet()) {
final String expected = m.getKey();
assertResult(expected, () -> builder().startObject().field("map", m.getValue()).endObject());
assertResult(expected, () -> builder().startObject().field("map").value(m.getValue()).endObject());
assertResult(expected, () -> builder().startObject().field("map").map(m.getValue()).endObject());
}
}
public void testIterable() throws Exception {
Map<String, Iterable<?>> iterables = new HashMap<>();
iterables.put("{'iter':null}", (Iterable) null);
iterables.put("{'iter':[]}", Collections.emptyList());
iterables.put("{'iter':['a','b']}", Arrays.asList("a", "b"));
final String path = Constants.WINDOWS ? "{'iter':'path\\\\to\\\\file'}" : "{'iter':'path/to/file'}";
iterables.put(path, PathUtils.get("path", "to", "file"));
final String paths = Constants.WINDOWS ? "{'iter':['a\\\\b\\\\c','c\\\\d']}" : "{'iter':['a/b/c','c/d']}";
iterables.put(paths, Arrays.asList(PathUtils.get("a", "b", "c"), PathUtils.get("c", "d")));
for (Map.Entry<String, Iterable<?>> i : iterables.entrySet()) {
final String expected = i.getKey();
assertResult(expected, () -> builder().startObject().field("iter", i.getValue()).endObject());
assertResult(expected, () -> builder().startObject().field("iter").value(i.getValue()).endObject());
}
}
public void testUnknownObject() throws Exception {
Map<String, Object> objects = new HashMap<>();
objects.put("{'obj':50.63}", DistanceUnit.METERS.fromMeters(50.63));
objects.put("{'obj':'MINUTES'}", TimeUnit.MINUTES);
objects.put("{'obj':'class org.elasticsearch.common.xcontent.BaseXContentTestCase'}", BaseXContentTestCase.class);
for (Map.Entry<String, ?> o : objects.entrySet()) {
final String expected = o.getKey();
assertResult(expected, () -> builder().startObject().field("obj", o.getValue()).endObject());
assertResult(expected, () -> builder().startObject().field("obj").value(o.getValue()).endObject());
}
}
public void testBasics() throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
try (XContentGenerator generator = xcontentType().xContent().createGenerator(os)) {
generator.writeStartObject();
generator.writeEndObject();
}
byte[] data = os.toByteArray();
assertEquals(xcontentType(), XContentFactory.xContentType(data));
}
public void testMissingEndObject() throws IOException {
IOException e = expectThrows(IOException.class, () -> {
ByteArrayOutputStream os = new ByteArrayOutputStream();
try (XContentGenerator generator = xcontentType().xContent().createGenerator(os)) {
generator.writeStartObject();
generator.writeFieldName("foo");
generator.writeNumber(2L);
}
});
assertEquals(e.getMessage(), "Unclosed object or array found");
}
public void testMissingEndArray() throws IOException {
IOException e = expectThrows(IOException.class, () -> {
ByteArrayOutputStream os = new ByteArrayOutputStream();
try (XContentGenerator generator = xcontentType().xContent().createGenerator(os)) {
generator.writeStartArray();
generator.writeNumber(2L);
}
});
assertEquals(e.getMessage(), "Unclosed object or array found");
}
public void testRawField() throws Exception {
for (boolean useStream : new boolean[]{false, true}) {
for (XContentType xcontentType : XContentType.values()) {
doTestRawField(xcontentType.xContent(), useStream);
}
}
}
void doTestRawField(XContent source, boolean useStream) throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
try (XContentGenerator generator = source.createGenerator(os)) {
generator.writeStartObject();
generator.writeFieldName("foo");
generator.writeNull();
generator.writeEndObject();
}
final byte[] rawData = os.toByteArray();
os = new ByteArrayOutputStream();
try (XContentGenerator generator = xcontentType().xContent().createGenerator(os)) {
generator.writeStartObject();
if (useStream) {
generator.writeRawField("bar", new ByteArrayInputStream(rawData));
} else {
generator.writeRawField("bar", new BytesArray(rawData));
}
generator.writeEndObject();
}
XContentParser parser = xcontentType().xContent().createParser(NamedXContentRegistry.EMPTY, os.toByteArray());
assertEquals(Token.START_OBJECT, parser.nextToken());
assertEquals(Token.FIELD_NAME, parser.nextToken());
assertEquals("bar", parser.currentName());
assertEquals(Token.START_OBJECT, parser.nextToken());
assertEquals(Token.FIELD_NAME, parser.nextToken());
assertEquals("foo", parser.currentName());
assertEquals(Token.VALUE_NULL, parser.nextToken());
assertEquals(Token.END_OBJECT, parser.nextToken());
assertEquals(Token.END_OBJECT, parser.nextToken());
assertNull(parser.nextToken());
}
public void testRawValue() throws Exception {
for (XContentType xcontentType : XContentType.values()) {
doTestRawValue(xcontentType.xContent());
}
}
void doTestRawValue(XContent source) throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
try (XContentGenerator generator = source.createGenerator(os)) {
generator.writeStartObject();
generator.writeFieldName("foo");
generator.writeNull();
generator.writeEndObject();
}
final byte[] rawData = os.toByteArray();
os = new ByteArrayOutputStream();
try (XContentGenerator generator = xcontentType().xContent().createGenerator(os)) {
generator.writeRawValue(new BytesArray(rawData));
}
XContentParser parser = xcontentType().xContent().createParser(NamedXContentRegistry.EMPTY, os.toByteArray());
assertEquals(Token.START_OBJECT, parser.nextToken());
assertEquals(Token.FIELD_NAME, parser.nextToken());
assertEquals("foo", parser.currentName());
assertEquals(Token.VALUE_NULL, parser.nextToken());
assertEquals(Token.END_OBJECT, parser.nextToken());
assertNull(parser.nextToken());
os = new ByteArrayOutputStream();
try (XContentGenerator generator = xcontentType().xContent().createGenerator(os)) {
generator.writeStartObject();
generator.writeFieldName("test");
generator.writeRawValue(new BytesArray(rawData));
generator.writeEndObject();
}
parser = xcontentType().xContent().createParser(NamedXContentRegistry.EMPTY, os.toByteArray());
assertEquals(Token.START_OBJECT, parser.nextToken());
assertEquals(Token.FIELD_NAME, parser.nextToken());
assertEquals("test", parser.currentName());
assertEquals(Token.START_OBJECT, parser.nextToken());
assertEquals(Token.FIELD_NAME, parser.nextToken());
assertEquals("foo", parser.currentName());
assertEquals(Token.VALUE_NULL, parser.nextToken());
assertEquals(Token.END_OBJECT, parser.nextToken());
assertEquals(Token.END_OBJECT, parser.nextToken());
assertNull(parser.nextToken());
}
protected void doTestBigInteger(JsonGenerator generator, ByteArrayOutputStream os) throws Exception {
// Big integers cannot be handled explicitly, but if some values happen to be big ints,
// we can still call parser.map() and get the bigint value so that eg. source filtering
// keeps working
BigInteger bigInteger = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE);
generator.writeStartObject();
generator.writeFieldName("foo");
generator.writeString("bar");
generator.writeFieldName("bigint");
generator.writeNumber(bigInteger);
generator.writeEndObject();
generator.flush();
byte[] serialized = os.toByteArray();
XContentParser parser = xcontentType().xContent().createParser(NamedXContentRegistry.EMPTY, serialized);
Map<String, Object> map = parser.map();
assertEquals("bar", map.get("foo"));
assertEquals(bigInteger, map.get("bigint"));
}
public void testEnsureNameNotNull() {
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> XContentBuilder.ensureNameNotNull(null));
assertThat(e.getMessage(), containsString("Field name cannot be null"));
}
public void testFormatterNameNotNull() {
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> XContentBuilder.ensureFormatterNotNull(null));
assertThat(e.getMessage(), containsString("DateTimeFormatter cannot be null"));
}
public void testEnsureNotNull() {
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> XContentBuilder.ensureNotNull(null, "message"));
assertThat(e.getMessage(), containsString("message"));
XContentBuilder.ensureNotNull("foo", "No exception must be thrown");
}
public void testEnsureNoSelfReferences() throws IOException {
XContentBuilder.ensureNoSelfReferences(emptyMap());
XContentBuilder.ensureNoSelfReferences(null);
Map<String, Object> map = new HashMap<>();
map.put("field", map);
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> builder().map(map));
assertThat(e.getMessage(), containsString("Object has already been built and is self-referencing itself"));
}
/**
* Test that the same map written multiple times do not trigger the self-reference check in
* {@link XContentBuilder#ensureNoSelfReferences(Object)}
*/
public void testRepeatedMapsAndNoSelfReferences() throws Exception {
Map<String, Object> mapB = singletonMap("b", "B");
Map<String, Object> mapC = singletonMap("c", "C");
Map<String, Object> mapD = singletonMap("d", "D");
Map<String, Object> mapA = new HashMap<>();
mapA.put("a", 0);
mapA.put("b1", mapB);
mapA.put("b2", mapB);
mapA.put("c", Arrays.asList(mapC, mapC));
mapA.put("d1", mapD);
mapA.put("d2", singletonMap("d3", mapD));
final String expected =
"{'map':{'b2':{'b':'B'},'a':0,'c':[{'c':'C'},{'c':'C'}],'d1':{'d':'D'},'d2':{'d3':{'d':'D'}},'b1':{'b':'B'}}}";
assertResult(expected, () -> builder().startObject().field("map", mapA).endObject());
assertResult(expected, () -> builder().startObject().field("map").value(mapA).endObject());
assertResult(expected, () -> builder().startObject().field("map").map(mapA).endObject());
}
public void testSelfReferencingMapsOneLevel() throws IOException {
Map<String, Object> map0 = new HashMap<>();
Map<String, Object> map1 = new HashMap<>();
map0.put("foo", 0);
map0.put("map1", map1); // map 0 -> map 1
map1.put("bar", 1);
map1.put("map0", map0); // map 1 -> map 0 loop
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> builder().map(map0));
assertThat(e.getMessage(), containsString("Object has already been built and is self-referencing itself"));
}
public void testSelfReferencingMapsTwoLevels() throws IOException {
Map<String, Object> map0 = new HashMap<>();
Map<String, Object> map1 = new HashMap<>();
Map<String, Object> map2 = new HashMap<>();
map0.put("foo", 0);
map0.put("map1", map1); // map 0 -> map 1
map1.put("bar", 1);
map1.put("map2", map2); // map 1 -> map 2
map2.put("baz", 2);
map2.put("map0", map0); // map 2 -> map 0 loop
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> builder().map(map0));
assertThat(e.getMessage(), containsString("Object has already been built and is self-referencing itself"));
}
public void testSelfReferencingObjectsArray() throws IOException {
Object[] values = new Object[3];
values[0] = 0;
values[1] = 1;
values[2] = values;
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> builder()
.startObject()
.field("field", values)
.endObject());
assertThat(e.getMessage(), containsString("Object has already been built and is self-referencing itself"));
e = expectThrows(IllegalArgumentException.class, () -> builder()
.startObject()
.array("field", values)
.endObject());
assertThat(e.getMessage(), containsString("Object has already been built and is self-referencing itself"));
}
public void testSelfReferencingIterable() throws IOException {
List<Object> values = new ArrayList<>();
values.add("foo");
values.add("bar");
values.add(values);
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> builder()
.startObject()
.field("field", (Iterable) values)
.endObject());
assertThat(e.getMessage(), containsString("Object has already been built and is self-referencing itself"));
}
public void testSelfReferencingIterableOneLevel() throws IOException {
Map<String, Object> map = new HashMap<>();
map.put("foo", 0);
map.put("bar", 1);
Iterable<Object> values = Arrays.asList("one", "two", map);
map.put("baz", values);
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> builder()
.startObject()
.field("field", (Iterable) values)
.endObject());
assertThat(e.getMessage(), containsString("Object has already been built and is self-referencing itself"));
}
public void testSelfReferencingIterableTwoLevels() throws IOException {
Map<String, Object> map0 = new HashMap<>();
Map<String, Object> map1 = new HashMap<>();
Map<String, Object> map2 = new HashMap<>();
List<Object> it1 = new ArrayList<>();
map0.put("foo", 0);
map0.put("it1", (Iterable<?>) it1); // map 0 -> it1
it1.add(map1);
it1.add(map2); // it 1 -> map 1, map 2
map2.put("baz", 2);
map2.put("map0", map0); // map 2 -> map 0 loop
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> builder().map(map0));
assertThat(e.getMessage(), containsString("Object has already been built and is self-referencing itself"));
}
public void testChecksForDuplicates() throws Exception {
assumeTrue("Test only makes sense if XContent parser has strict duplicate checks enabled",
XContent.isStrictDuplicateDetectionEnabled());
XContentBuilder builder = builder()
.startObject()
.field("key", 1)
.field("key", 2)
.endObject();
JsonParseException pex = expectThrows(JsonParseException.class, () -> createParser(builder).map());
assertThat(pex.getMessage(), startsWith("Duplicate field 'key'"));
}
public void testNamedObject() throws IOException {
Object test1 = new Object();
Object test2 = new Object();
NamedXContentRegistry registry = new NamedXContentRegistry(Arrays.asList(
new NamedXContentRegistry.Entry(Object.class, new ParseField("test1"), p -> test1),
new NamedXContentRegistry.Entry(Object.class, new ParseField("test2", "deprecated"), p -> test2),
new NamedXContentRegistry.Entry(Object.class, new ParseField("str"), p -> p.text())));
XContentBuilder b = XContentBuilder.builder(xcontentType().xContent());
b.value("test");
XContentParser p = xcontentType().xContent().createParser(registry, b.bytes());
assertEquals(test1, p.namedObject(Object.class, "test1", null));
assertEquals(test2, p.namedObject(Object.class, "test2", null));
assertEquals(test2, p.namedObject(Object.class, "deprecated", null));
assertWarnings("Deprecated field [deprecated] used, expected [test2] instead");
{
p.nextToken();
assertEquals("test", p.namedObject(Object.class, "str", null));
NamedXContentRegistry.UnknownNamedObjectException e = expectThrows(NamedXContentRegistry.UnknownNamedObjectException.class,
() -> p.namedObject(Object.class, "unknown", null));
assertEquals("Unknown Object [unknown]", e.getMessage());
assertEquals("java.lang.Object", e.getCategoryClass());
assertEquals("unknown", e.getName());
}
{
Exception e = expectThrows(ElasticsearchException.class, () -> p.namedObject(String.class, "doesn't matter", null));
assertEquals("Unknown namedObject category [java.lang.String]", e.getMessage());
}
{
XContentParser emptyRegistryParser = xcontentType().xContent().createParser(NamedXContentRegistry.EMPTY, new byte[] {});
Exception e = expectThrows(ElasticsearchException.class,
() -> emptyRegistryParser.namedObject(String.class, "doesn't matter", null));
assertEquals("namedObject is not supported for this parser", e.getMessage());
}
}
private static void expectUnclosedException(ThrowingRunnable runnable) {
IllegalStateException e = expectThrows(IllegalStateException.class, runnable);
assertThat(e.getMessage(), containsString("Failed to close the XContentBuilder"));
assertThat(e.getCause(), allOf(notNullValue(), instanceOf(IOException.class)));
assertThat(e.getCause().getMessage(), containsString("Unclosed object or array found"));
}
private static void expectValueException(ThrowingRunnable runnable) {
JsonGenerationException e = expectThrows(JsonGenerationException.class, runnable);
assertThat(e.getMessage(), containsString("expecting a value"));
}
private static void expectFieldException(ThrowingRunnable runnable) {
JsonGenerationException e = expectThrows(JsonGenerationException.class, runnable);
assertThat(e.getMessage(), containsString("expecting field name"));
}
private static void expectNonNullFieldException(ThrowingRunnable runnable) {
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, runnable);
assertThat(e.getMessage(), containsString("Field name cannot be null"));
}
private static void expectNonNullFormatterException(ThrowingRunnable runnable) {
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, runnable);
assertThat(e.getMessage(), containsString("DateTimeFormatter cannot be null"));
}
private static void expectObjectException(ThrowingRunnable runnable) {
JsonGenerationException e = expectThrows(JsonGenerationException.class, runnable);
assertThat(e.getMessage(), containsString("Current context not Object"));
}
private static void expectArrayException(ThrowingRunnable runnable) {
JsonGenerationException e = expectThrows(JsonGenerationException.class, runnable);
assertThat(e.getMessage(), containsString("Current context not Array"));
}
public static Matcher<String> equalToJson(String json) {
return Matchers.equalTo(json.replace("'", "\""));
}
private static void assertResult(String expected, Builder builder) throws IOException {
// Build the XContentBuilder, convert its bytes to JSON and check it matches
assertThat(XContentHelper.convertToJson(builder.build().bytes(), randomBoolean()), equalToJson(expected));
}
private static byte[] randomBytes() throws Exception {
return randomUnicodeOfLength(scaledRandomIntBetween(10, 1000)).getBytes("UTF-8");
}
@FunctionalInterface
private interface Builder {
XContentBuilder build() throws IOException;
}
}