/* * 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.JsonParseException; import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.test.ESTestCase; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.Map; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.isIn; import static org.hamcrest.Matchers.nullValue; public class XContentParserTests extends ESTestCase { public void testReadList() throws IOException { assertThat(readList("{\"foo\": [\"bar\"]}"), contains("bar")); assertThat(readList("{\"foo\": [\"bar\",\"baz\"]}"), contains("bar", "baz")); assertThat(readList("{\"foo\": [1, 2, 3], \"bar\": 4}"), contains(1, 2, 3)); assertThat(readList("{\"foo\": [{\"bar\":1},{\"baz\":2},{\"qux\":3}]}"), hasSize(3)); assertThat(readList("{\"foo\": [null]}"), contains(nullValue())); assertThat(readList("{\"foo\": []}"), hasSize(0)); assertThat(readList("{\"foo\": [1]}"), contains(1)); assertThat(readList("{\"foo\": [1,2]}"), contains(1, 2)); assertThat(readList("{\"foo\": [{},{},{},{}]}"), hasSize(4)); } public void testReadListThrowsException() throws IOException { // Calling XContentParser.list() or listOrderedMap() to read a simple // value or object should throw an exception assertReadListThrowsException("{\"foo\": \"bar\"}"); assertReadListThrowsException("{\"foo\": 1, \"bar\": 2}"); assertReadListThrowsException("{\"foo\": {\"bar\":\"baz\"}}"); } @SuppressWarnings("unchecked") private <T> List<T> readList(String source) throws IOException { try (XContentParser parser = createParser(JsonXContent.jsonXContent, source)) { XContentParser.Token token = parser.nextToken(); assertThat(token, equalTo(XContentParser.Token.START_OBJECT)); token = parser.nextToken(); assertThat(token, equalTo(XContentParser.Token.FIELD_NAME)); assertThat(parser.currentName(), equalTo("foo")); return (List<T>) (randomBoolean() ? parser.listOrderedMap() : parser.list()); } } private void assertReadListThrowsException(String source) { try { readList(source); fail("should have thrown a parse exception"); } catch (Exception e) { assertThat(e, instanceOf(ElasticsearchParseException.class)); assertThat(e.getMessage(), containsString("Failed to parse list")); } } public void testReadMapStrings() throws IOException { Map<String, String> map = readMapStrings("{\"foo\": {\"kbar\":\"vbar\"}}"); assertThat(map.get("kbar"), equalTo("vbar")); assertThat(map.size(), equalTo(1)); map = readMapStrings("{\"foo\": {\"kbar\":\"vbar\", \"kbaz\":\"vbaz\"}}"); assertThat(map.get("kbar"), equalTo("vbar")); assertThat(map.get("kbaz"), equalTo("vbaz")); assertThat(map.size(), equalTo(2)); map = readMapStrings("{\"foo\": {}}"); assertThat(map.size(), equalTo(0)); } private Map<String, String> readMapStrings(String source) throws IOException { try (XContentParser parser = createParser(JsonXContent.jsonXContent, source)) { XContentParser.Token token = parser.nextToken(); assertThat(token, equalTo(XContentParser.Token.START_OBJECT)); token = parser.nextToken(); assertThat(token, equalTo(XContentParser.Token.FIELD_NAME)); assertThat(parser.currentName(), equalTo("foo")); token = parser.nextToken(); assertThat(token, equalTo(XContentParser.Token.START_OBJECT)); return randomBoolean() ? parser.mapStringsOrdered() : parser.mapStrings(); } } @SuppressWarnings("deprecation") // #isBooleanValueLenient() and #booleanValueLenient() are the test subjects public void testReadLenientBooleans() throws IOException { // allow String, boolean and int representations of lenient booleans String falsy = randomFrom("\"off\"", "\"no\"", "\"0\"", "0", "\"false\"", "false"); String truthy = randomFrom("\"on\"", "\"yes\"", "\"1\"", "1", "\"true\"", "true"); try (XContentParser parser = createParser(JsonXContent.jsonXContent, "{\"foo\": " + falsy + ", \"bar\": " + truthy + "}")) { XContentParser.Token token = parser.nextToken(); assertThat(token, equalTo(XContentParser.Token.START_OBJECT)); token = parser.nextToken(); assertThat(token, equalTo(XContentParser.Token.FIELD_NAME)); assertThat(parser.currentName(), equalTo("foo")); token = parser.nextToken(); assertThat(token, isIn( Arrays.asList(XContentParser.Token.VALUE_STRING, XContentParser.Token.VALUE_NUMBER, XContentParser.Token.VALUE_BOOLEAN))); assertTrue(parser.isBooleanValueLenient()); assertFalse(parser.booleanValueLenient()); token = parser.nextToken(); assertThat(token, equalTo(XContentParser.Token.FIELD_NAME)); assertThat(parser.currentName(), equalTo("bar")); token = parser.nextToken(); assertThat(token, isIn( Arrays.asList(XContentParser.Token.VALUE_STRING, XContentParser.Token.VALUE_NUMBER, XContentParser.Token.VALUE_BOOLEAN))); assertTrue(parser.isBooleanValueLenient()); assertTrue(parser.booleanValueLenient()); } } public void testReadBooleansFailsForLenientBooleans() throws IOException { String falsy = randomFrom("\"off\"", "\"no\"", "\"0\"", "0"); String truthy = randomFrom("\"on\"", "\"yes\"", "\"1\"", "1"); try (XContentParser parser = createParser(JsonXContent.jsonXContent, "{\"foo\": " + falsy + ", \"bar\": " + truthy + "}")) { XContentParser.Token token = parser.nextToken(); assertThat(token, equalTo(XContentParser.Token.START_OBJECT)); token = parser.nextToken(); assertThat(token, equalTo(XContentParser.Token.FIELD_NAME)); assertThat(parser.currentName(), equalTo("foo")); token = parser.nextToken(); assertThat(token, isIn(Arrays.asList(XContentParser.Token.VALUE_STRING, XContentParser.Token.VALUE_NUMBER))); assertFalse(parser.isBooleanValue()); if (token.equals(XContentParser.Token.VALUE_STRING)) { expectThrows(IllegalArgumentException.class, parser::booleanValue); } else { expectThrows(JsonParseException.class, parser::booleanValue); } token = parser.nextToken(); assertThat(token, equalTo(XContentParser.Token.FIELD_NAME)); assertThat(parser.currentName(), equalTo("bar")); token = parser.nextToken(); assertThat(token, isIn(Arrays.asList(XContentParser.Token.VALUE_STRING, XContentParser.Token.VALUE_NUMBER))); assertFalse(parser.isBooleanValue()); if (token.equals(XContentParser.Token.VALUE_STRING)) { expectThrows(IllegalArgumentException.class, parser::booleanValue); } else { expectThrows(JsonParseException.class, parser::booleanValue); } } } public void testReadBooleans() throws IOException { String falsy = randomFrom("\"false\"", "false"); String truthy = randomFrom("\"true\"", "true"); try (XContentParser parser = createParser(JsonXContent.jsonXContent, "{\"foo\": " + falsy + ", \"bar\": " + truthy + "}")) { XContentParser.Token token = parser.nextToken(); assertThat(token, equalTo(XContentParser.Token.START_OBJECT)); token = parser.nextToken(); assertThat(token, equalTo(XContentParser.Token.FIELD_NAME)); assertThat(parser.currentName(), equalTo("foo")); token = parser.nextToken(); assertThat(token, isIn(Arrays.asList(XContentParser.Token.VALUE_STRING, XContentParser.Token.VALUE_BOOLEAN))); assertTrue(parser.isBooleanValue()); assertFalse(parser.booleanValue()); token = parser.nextToken(); assertThat(token, equalTo(XContentParser.Token.FIELD_NAME)); assertThat(parser.currentName(), equalTo("bar")); token = parser.nextToken(); assertThat(token, isIn(Arrays.asList(XContentParser.Token.VALUE_STRING, XContentParser.Token.VALUE_BOOLEAN))); assertTrue(parser.isBooleanValue()); assertTrue(parser.booleanValue()); } } }