|
@@ -19,6 +19,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
|
import org.elasticsearch.common.xcontent.XContentElasticsearchExtension;
|
|
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
|
|
import org.elasticsearch.common.xcontent.XContentGenerator;
|
|
|
+import org.elasticsearch.common.xcontent.XContentHelper;
|
|
|
import org.elasticsearch.common.xcontent.XContentParser;
|
|
|
import org.elasticsearch.common.xcontent.XContentType;
|
|
|
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
|
@@ -26,9 +27,13 @@ import org.elasticsearch.test.ESTestCase;
|
|
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
|
import java.io.IOException;
|
|
|
+import java.io.InputStream;
|
|
|
+import java.io.OutputStream;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
import java.nio.file.Path;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Arrays;
|
|
|
+import java.util.Base64;
|
|
|
import java.util.Calendar;
|
|
|
import java.util.Collections;
|
|
|
import java.util.Date;
|
|
@@ -37,9 +42,13 @@ import java.util.HashMap;
|
|
|
import java.util.List;
|
|
|
import java.util.Locale;
|
|
|
import java.util.Map;
|
|
|
+import java.util.Objects;
|
|
|
import java.util.TimeZone;
|
|
|
|
|
|
+import static org.hamcrest.Matchers.aMapWithSize;
|
|
|
import static org.hamcrest.Matchers.equalTo;
|
|
|
+import static org.hamcrest.Matchers.hasEntry;
|
|
|
+import static org.hamcrest.Matchers.instanceOf;
|
|
|
|
|
|
public class XContentBuilderTests extends ESTestCase {
|
|
|
public void testPrettyWithLfAtEnd() throws Exception {
|
|
@@ -383,4 +392,84 @@ public class XContentBuilderTests extends ESTestCase {
|
|
|
assertThat(e.getMessage(), equalTo("Failed to close the XContentBuilder"));
|
|
|
assertThat(e.getCause().getMessage(), equalTo("Unclosed object or array found"));
|
|
|
}
|
|
|
+
|
|
|
+ private static class TestWritableValue {
|
|
|
+ final Map<String, Byte> values;
|
|
|
+
|
|
|
+ static TestWritableValue randomValue() {
|
|
|
+ int numKeys = randomIntBetween(0, 10);
|
|
|
+ Map<String, Byte> values = new HashMap<>();
|
|
|
+ for (int i = 0; i < numKeys; i++) {
|
|
|
+ values.put(randomAlphaOfLength(10), randomByte());
|
|
|
+ }
|
|
|
+ return new TestWritableValue(values);
|
|
|
+ }
|
|
|
+
|
|
|
+ TestWritableValue(Map<String, Byte> values) {
|
|
|
+ this.values = values;
|
|
|
+ }
|
|
|
+
|
|
|
+ TestWritableValue(InputStream in) throws IOException {
|
|
|
+ final int size = in.read();
|
|
|
+ this.values = new HashMap<>(size);
|
|
|
+ for (int i = 0; i < size; i++) {
|
|
|
+ final int keySize = in.read();
|
|
|
+ final String key = new String(in.readNBytes(keySize), StandardCharsets.ISO_8859_1);
|
|
|
+ final byte value = (byte) in.read();
|
|
|
+ values.put(key, value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void writeTo(OutputStream os) throws IOException {
|
|
|
+ os.write((byte) values.size());
|
|
|
+ for (Map.Entry<String, Byte> e : values.entrySet()) {
|
|
|
+ final String k = e.getKey();
|
|
|
+ os.write((byte) k.length());
|
|
|
+ os.write(k.getBytes(StandardCharsets.ISO_8859_1));
|
|
|
+ os.write(e.getValue());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void testWritableValue() throws Exception {
|
|
|
+ Map<String, Object> expectedValues = new HashMap<>();
|
|
|
+ final XContentBuilder builder = XContentFactory.jsonBuilder();
|
|
|
+ builder.startObject();
|
|
|
+ int fields = iterations(1, 10);
|
|
|
+ for (int i = 0; i < fields; i++) {
|
|
|
+ String field = "field-" + i;
|
|
|
+ if (randomBoolean()) {
|
|
|
+ final TestWritableValue value = TestWritableValue.randomValue();
|
|
|
+ builder.directFieldAsBase64(field, value::writeTo);
|
|
|
+ expectedValues.put(field, value);
|
|
|
+ } else {
|
|
|
+ Object value = randomFrom(randomInt(), randomAlphaOfLength(10));
|
|
|
+ builder.field(field, value);
|
|
|
+ expectedValues.put(field, value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ builder.endObject();
|
|
|
+ final BytesReference bytes = BytesReference.bytes(builder);
|
|
|
+ final Map<String, Object> actualValues = XContentHelper.convertToMap(bytes, true).v2();
|
|
|
+ assertThat(actualValues, aMapWithSize(fields));
|
|
|
+ for (Map.Entry<String, Object> e : expectedValues.entrySet()) {
|
|
|
+ if (e.getValue() instanceof TestWritableValue) {
|
|
|
+ final TestWritableValue expectedValue = (TestWritableValue) e.getValue();
|
|
|
+ assertThat(actualValues.get(e.getKey()), instanceOf(String.class));
|
|
|
+ final byte[] decoded = Base64.getDecoder().decode((String) actualValues.get(e.getKey()));
|
|
|
+ final TestWritableValue actualValue = new TestWritableValue(new InputStream() {
|
|
|
+ int pos = 0;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int read() {
|
|
|
+ Objects.checkIndex(pos, decoded.length);
|
|
|
+ return decoded[pos++];
|
|
|
+ }
|
|
|
+ });
|
|
|
+ assertThat(actualValue.values, equalTo(expectedValue.values));
|
|
|
+ } else {
|
|
|
+ assertThat(actualValues, hasEntry(e.getKey(), e.getValue()));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|