blob: 7a3357964ee59d88939adbcb62638fef4f279282 [file] [log] [blame]
// Licensed 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
#include <stdint.h>
#include <sys/stat.h>
#include <string>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <stout/gtest.hpp>
#include <stout/json.hpp>
#include <stout/stringify.hpp>
#include <stout/strings.hpp>
using std::string;
using boost::get;
TEST(JsonTest, DefaultValueIsNull)
{
JSON::Value v;
EXPECT_EQ("null", stringify(v));
}
TEST(JsonTest, UTF8)
{
// We don't use the optional \uXXXX escaping for UTF-8,
// unless required (" U+0022, \ U+005C, and the control
// characters U+0000 to U+001F).
JSON::String s("Hello! \x01\x1F\x22\x5C \xF0\x9F\x98\x80");
EXPECT_EQ("\"Hello! \\u0001\\u001F\\\"\\\\ \xF0\x9F\x98\x80\"",
stringify(s));
}
TEST(JsonTest, InvalidUTF8)
{
// There currently is no validation either when constructing
// invalid UTF-8 string, or during serialization. Here, we
// use a 4 byte sequence but only provide the first byte.
// For now, this just gets passed through.
JSON::String s("\xF0");
EXPECT_EQ("\"\xF0\"", stringify(s));
}
TEST(JsonTest, NumberFormat)
{
// Test whole numbers (as doubles).
EXPECT_EQ("0.0", stringify(JSON::Number(0.0)));
EXPECT_EQ("1.0", stringify(JSON::Number(1.0)));
// Negative.
EXPECT_EQ("-1.0", stringify(JSON::Number(-1.0)));
// Test integers.
EXPECT_EQ("0", stringify(JSON::Number(0)));
EXPECT_EQ("2", stringify(JSON::Number(2)));
EXPECT_EQ("-2", stringify(JSON::Number(-2)));
// Expect at least 15 digits of precision.
EXPECT_EQ("1234567890.12345", stringify(JSON::Number(1234567890.12345)));
}
TEST(JsonTest, NumberComparisons)
{
// Unsigned and signed comparisons.
EXPECT_EQ(JSON::Number(1U), JSON::Number((int64_t) 1));
EXPECT_EQ(JSON::Number(0U), JSON::Number((int64_t) 0));
EXPECT_NE(JSON::Number(1U), JSON::Number(-1));
EXPECT_NE(JSON::Number((uint64_t) -1), JSON::Number(-1));
// Signed and unsigned comparisons (opposite order of above).
EXPECT_EQ(JSON::Number((int64_t) 1), JSON::Number(1U));
EXPECT_EQ(JSON::Number((int64_t) 0), JSON::Number(0U));
EXPECT_NE(JSON::Number(-1), JSON::Number(1U));
EXPECT_NE(JSON::Number(-1), JSON::Number((uint64_t) -1));
// Make sure we aren't doing an implicit cast from int64_t to uint64_t.
// These have the same bit representation (64h'8000_0000_0000_0001).
EXPECT_NE(
JSON::Number(9223372036854775809U),
JSON::Number(-9223372036854775807));
EXPECT_NE(
JSON::Number(-9223372036854775807),
JSON::Number(9223372036854775809U));
}
TEST(JsonTest, BooleanFormat)
{
EXPECT_EQ("false", stringify(JSON::False()));
EXPECT_EQ("true", stringify(JSON::True()));
EXPECT_EQ("true", stringify(JSON::Boolean(true)));
EXPECT_EQ("false", stringify(JSON::Boolean(false)));
EXPECT_EQ("true", stringify(JSON::Value(true)));
EXPECT_EQ("false", stringify(JSON::Value(false)));
}
TEST(JsonTest, BooleanAssignement)
{
JSON::Value v = true;
EXPECT_TRUE(get<JSON::Boolean>(v).value);
v = false;
EXPECT_FALSE(get<JSON::Boolean>(v).value);
JSON::Boolean b = true;
EXPECT_TRUE(b.value);
b = false;
EXPECT_FALSE(b.value);
}
TEST(JsonTest, CStringAssignment)
{
JSON::Value v = "test";
JSON::String s = "test";
EXPECT_EQ(get<JSON::String>(v).value, "test");
EXPECT_EQ(s.value, "test");
v = "123";
s = "123";
EXPECT_EQ(get<JSON::String>(v).value, "123");
EXPECT_EQ(s.value, "123");
char buf[1000];
v = strcpy(buf, "bar");
s = strcpy(buf, "bar");
EXPECT_EQ(get<JSON::String>(v).value, "bar");
EXPECT_EQ(s.value, "bar");
}
TEST(JsonTest, NumericAssignment)
{
// Just using this to get various numeric datatypes that
// are used by clients of stout.
struct stat s;
s.st_nlink = 1;
JSON::Value v = s.st_nlink;
JSON::Number d = s.st_nlink;
EXPECT_NE(get<JSON::Number>(v).type, JSON::Number::FLOATING);
EXPECT_EQ(get<JSON::Number>(v).as<int64_t>(), 1);
EXPECT_EQ(d.as<int64_t>(), 1);
s.st_size = 2;
v = s.st_size;
d = s.st_size;
EXPECT_NE(get<JSON::Number>(v).type, JSON::Number::FLOATING);
EXPECT_EQ(get<JSON::Number>(v).as<int64_t>(), 2);
EXPECT_EQ(d.as<int64_t>(), 2);
s.st_mtime = 3;
v = s.st_mtime;
d = s.st_mtime;
EXPECT_EQ(get<JSON::Number>(v).as<int64_t>(), 3);
EXPECT_EQ(d.as<int64_t>(), 3);
size_t st = 4;
v = st;
d = st;
EXPECT_EQ(get<JSON::Number>(v).type, JSON::Number::UNSIGNED_INTEGER);
EXPECT_EQ(get<JSON::Number>(v).as<uint64_t>(), 4u);
EXPECT_EQ(d.as<uint64_t>(), 4u);
uint64_t ui64 = 5;
v = ui64;
d = ui64;
EXPECT_EQ(get<JSON::Number>(v).type, JSON::Number::UNSIGNED_INTEGER);
EXPECT_EQ(get<JSON::Number>(v).as<uint64_t>(), 5u);
EXPECT_EQ(d.as<uint64_t>(), 5u);
const unsigned int ui = 6;
v = ui;
d = ui;
EXPECT_EQ(get<JSON::Number>(v).type, JSON::Number::UNSIGNED_INTEGER);
EXPECT_EQ(get<JSON::Number>(v).as<uint64_t>(), 6u);
EXPECT_EQ(d.as<uint64_t>(), 6u);
int i = 7;
v = i;
d = i;
EXPECT_EQ(get<JSON::Number>(v).type, JSON::Number::SIGNED_INTEGER);
EXPECT_EQ(get<JSON::Number>(v).as<int64_t>(), 7);
EXPECT_EQ(d.as<int64_t>(), 7);
}
TEST(JsonTest, Parse)
{
JSON::Object object;
object.values["strings"] = "string";
object.values["integer1"] = 1;
object.values["integer2"] = -1;
object.values["double1"] = 1;
object.values["double2"] = -1;
object.values["double3"] = -1.42;
JSON::Object nested;
nested.values["string"] = "string";
EXPECT_SOME_EQ(nested, JSON::parse<JSON::Object>(stringify(nested)));
object.values["nested"] = nested;
JSON::Array array;
array.values.push_back(nested);
EXPECT_SOME_EQ(array, JSON::parse<JSON::Array>(stringify(array)));
object.values["array"] = array;
EXPECT_SOME_EQ(object, JSON::parse(stringify(object)));
// Test parsing with whitespace before and after a JSON object.
object = JSON::Object();
object.values["some"] = "stuff";
object.values["oh"] = "no";
string jsonString =
" "
"{\n"
" \"some\": \"stuff\","
" \"oh\": \"no\""
"}\t ";
EXPECT_SOME_EQ(object, JSON::parse<JSON::Object>(jsonString));
}
TEST(JsonTest, ParseError)
{
string jsonString =
"{"
" \"key1\": \"value1\","
" \"key2\": \"value2\""
"}trailingcharacters";
EXPECT_ERROR(JSON::parse<JSON::Object>(jsonString));
jsonString =
"{"
" \"key1\": \"value1\","
" \"key2\": \"value2\""
"},"
"{"
" \"key3\": \"value3\","
" \"key4\": \"value4\""
"}";
EXPECT_ERROR(JSON::parse<JSON::Object>(jsonString));
jsonString =
"{"
" \"key1\": \"value1\","
" \"key2\": \"value2\""
" ";
EXPECT_ERROR(JSON::parse<JSON::Object>(jsonString));
jsonString = R"~(
{
"double1": 123123123121231231231231321312312312123123122E112312387129381723\x0d\x0a\x0d\x0a\x0d\x0a\x0d
})~";
EXPECT_ERROR(JSON::parse<JSON::Object>(jsonString));
jsonString = R"~(
{
"double2": -332861120361594135E400
})~";
EXPECT_ERROR(JSON::parse<JSON::Object>(jsonString));
}
TEST(JsonTest, Find)
{
Try<JSON::Value> value = JSON::parse(
R"~(
{
"nested1": {
"nested2": {
"string": "string",
"integer": -1,
"double": -1.42,
"null": null,
"array": ["hello"]
}
}
})~");
ASSERT_SOME(value);
ASSERT_TRUE(value->is<JSON::Object>());
JSON::Object object = value->as<JSON::Object>();
EXPECT_NONE(object.find<JSON::String>("nested.nested.string"));
EXPECT_NONE(object.find<JSON::String>("nested1.nested2.none"));
EXPECT_ERROR(object.find<JSON::String>("nested1.nested2.array"));
EXPECT_ERROR(object.find<JSON::String>("nested1.nested2.array.foo"));
EXPECT_SOME_EQ(
JSON::String("string"),
object.find<JSON::String>("nested1.nested2.string"));
EXPECT_SOME_EQ(
JSON::Number(-1),
object.find<JSON::Number>("nested1.nested2.integer"));
EXPECT_SOME_EQ(
JSON::Number(-1.42),
object.find<JSON::Number>("nested1.nested2.double"));
EXPECT_SOME_EQ(
JSON::String("hello"),
object.find<JSON::String>("nested1.nested2.array[0]"));
EXPECT_ERROR(object.find<JSON::String>("nested1.nested2.array[1"));
EXPECT_ERROR(object.find<JSON::String>("nested1.nested2.array[[1]"));
EXPECT_ERROR(object.find<JSON::String>("nested1.nested2.array[1]]"));
EXPECT_ERROR(object.find<JSON::String>("nested1.nested2.array.[1]"));
EXPECT_ERROR(object.find<JSON::String>("nested1.nested2.array[.1]"));
EXPECT_ERROR(object.find<JSON::String>("nested1.nested2.array[1.]"));
EXPECT_ERROR(object.find<JSON::String>("nested1.nested2.array[]"));
EXPECT_ERROR(object.find<JSON::String>("nested1.nested2.array[[]"));
EXPECT_ERROR(object.find<JSON::String>("nested1.nested2.array[]]"));
EXPECT_ERROR(object.find<JSON::String>("nested1.nested2.array[[]]"));
EXPECT_ERROR(object.find<JSON::String>("nested1.nested2.array[[1]]"));
EXPECT_ERROR(object.find<JSON::String>("nested1.nested2.array[[1]"));
EXPECT_ERROR(object.find<JSON::String>("nested1.nested2.array[1]]"));
// Out of bounds is none.
EXPECT_NONE(object.find<JSON::String>("nested1.nested2.array[1]"));
// Indexing into a non-array is an error.
EXPECT_ERROR(object.find<JSON::String>("nested1[1].nested2.string"));
EXPECT_ERROR(object.find<JSON::String>("nested1.nested2[1].string"));
EXPECT_ERROR(object.find<JSON::String>("nested1.nested2.string[1]"));
// Indexing into a null is the same as a non-existent field.
EXPECT_NONE(object.find<JSON::String>("nested1.nested2.null[1]"));
EXPECT_NONE(object.find<JSON::String>("nested1.nested2.missing[1]"));
// Null entries are found when looking for a matching type (Null or Value).
EXPECT_SOME_EQ(
JSON::Null(),
object.find<JSON::Null>("nested1.nested2.null"));
EXPECT_SOME_EQ(
JSON::Null(),
object.find<JSON::Value>("nested1.nested2.null"));
// Null entries are not found when looking for non-null finds.
EXPECT_NONE(object.find<JSON::String>("nested1.nested2.null"));
EXPECT_NONE(object.find<JSON::Number>("nested1.nested2.null"));
EXPECT_NONE(object.find<JSON::Object>("nested1.nested2.null"));
EXPECT_NONE(object.find<JSON::Array>("nested1.nested2.null"));
EXPECT_NONE(object.find<JSON::Boolean>("nested1.nested2.null"));
// Also test getting JSON::Value when you don't know the type.
EXPECT_SOME(object.find<JSON::Value>("nested1.nested2.null"));
}
TEST(JsonTest, At)
{
JSON::Object object;
object.values["this.string"] = "string";
object.values["this.integer"] = -1;
object.values["this.double"] = -1.42;
object.values["this.null"] = JSON::Null();
ASSERT_NONE(object.find<JSON::String>("this.string"));
ASSERT_ERROR(object.at<JSON::Number>("this.string"));
ASSERT_ERROR(object.at<JSON::Null>("this.string"));
ASSERT_SOME_EQ(
JSON::String("string"),
object.at<JSON::String>("this.string"));
ASSERT_NONE(object.find<JSON::Number>("this.integer"));
ASSERT_ERROR(object.at<JSON::String>("this.integer"));
ASSERT_ERROR(object.at<JSON::Null>("this.integer"));
ASSERT_SOME_EQ(
JSON::Number(-1),
object.at<JSON::Number>("this.integer"));
ASSERT_NONE(object.find<JSON::Number>("this.double"));
ASSERT_ERROR(object.at<JSON::String>("this.double"));
ASSERT_ERROR(object.at<JSON::Null>("this.double"));
ASSERT_SOME_EQ(
JSON::Number(-1.42),
object.at<JSON::Number>("this.double"));
ASSERT_NONE(object.find<JSON::Null>("this.null"));
ASSERT_ERROR(object.at<JSON::Number>("this.null"));
ASSERT_ERROR(object.at<JSON::String>("this.null"));
ASSERT_SOME_EQ(
JSON::Null(),
object.at<JSON::Null>("this.null"));
ASSERT_NONE(object.at<JSON::String>("something.else"));
ASSERT_NONE(object.at<JSON::String>("none"));
ASSERT_NONE(object.at<JSON::String>(string()));
}
// Test the equality operator between two objects.
TEST(JsonTest, Equals)
{
// Array checks.
Try<JSON::Value> _array = JSON::parse("{\"array\" : [1, 2, 3]}");
ASSERT_SOME(_array);
const JSON::Value array = _array.get();
EXPECT_SOME_EQ(array, JSON::parse("{\"array\" : [1, 2, 3]}"));
EXPECT_SOME_NE(array, JSON::parse("{\"array\" : [3, 2, 1, 0]}"));
EXPECT_SOME_NE(array, JSON::parse("{\"array\" : [1, 2, 3, 4]}"));
EXPECT_SOME_NE(array, JSON::parse("{\"array\" : [3, 2, 1]}"));
EXPECT_SOME_NE(array, JSON::parse("{\"array\" : [1, 2, 4]}"));
EXPECT_SOME_NE(array, JSON::parse("{\"array\" : [1, 2]}"));
EXPECT_SOME_NE(array, JSON::parse("{\"array\" : []}"));
EXPECT_SOME_NE(array, JSON::parse("{\"array\" : null}"));
EXPECT_SOME_NE(array, JSON::parse("{\"array\" : 42}"));
// Boolean checks.
Try<JSON::Value> _boolean = JSON::parse("{\"boolean\" : true}");
ASSERT_SOME(_boolean);
const JSON::Value boolean = _boolean.get();
EXPECT_SOME_EQ(boolean, JSON::parse("{\"boolean\" : true}"));
EXPECT_SOME_NE(boolean, JSON::parse("{\"boolean\" : false}"));
EXPECT_SOME_NE(boolean, JSON::parse("{\"boolean\" : null}"));
EXPECT_SOME_NE(boolean, JSON::parse("{\"boolean\" : 42}"));
// Null checks.
Try<JSON::Value> _nullEntry = JSON::parse("{\"null_entry\" : null}");
ASSERT_SOME(_nullEntry);
const JSON::Value nullEntry = _nullEntry.get();
EXPECT_SOME_EQ(nullEntry, JSON::parse("{\"null_entry\" : null}"));
EXPECT_SOME_NE(nullEntry, JSON::parse("{\"null_entry\" : 42}"));
// String checks.
Try<JSON::Value> _str = JSON::parse("{\"string\" : \"Hello World!\"}");
ASSERT_SOME(_str);
const JSON::Value str = _str.get();
EXPECT_SOME_EQ(str, JSON::parse("{\"string\" : \"Hello World!\"}"));
EXPECT_SOME_NE(str, JSON::parse("{\"string\" : \"Goodbye World!\"}"));
EXPECT_SOME_NE(str, JSON::parse("{\"string\" : \"\"}"));
EXPECT_SOME_NE(str, JSON::parse("{\"string\" : null}"));
EXPECT_SOME_NE(str, JSON::parse("{\"string\" : 42}"));
// Object's checks.
Try<JSON::Value> _object = JSON::parse("{\"a\" : 1, \"b\" : 2}");
ASSERT_SOME(_object);
const JSON::Value object = _object.get();
EXPECT_SOME_EQ(object, JSON::parse("{\"a\" : 1, \"b\" : 2}"));
EXPECT_SOME_NE(object, JSON::parse("{\"a\" : 1, \"b\" : []}"));
EXPECT_SOME_NE(object, JSON::parse("{\"a\" : 1}"));
EXPECT_SOME_NE(object, JSON::parse("{}"));
}
// Test the containment of JSON objects where one is a JSON array.
TEST(JsonTest, ContainsArray)
{
Try<JSON::Value> _array = JSON::parse("{\"array\" : [1, 2, 3]}");
ASSERT_SOME(_array);
const JSON::Value array = _array.get();
Try<JSON::Value> arrayTest = JSON::parse("{\"array\" : [1, 2, 3]}");
EXPECT_TRUE(array.contains(arrayTest.get()));
arrayTest = JSON::parse("{}");
EXPECT_TRUE(array.contains(arrayTest.get()));
arrayTest = JSON::parse("{\"array\" : [3, 2, 1, 0]}");
EXPECT_FALSE(array.contains(arrayTest.get()));
arrayTest = JSON::parse("{\"array\" : [1, 2, 3, 4]}");
EXPECT_FALSE(array.contains(arrayTest.get()));
arrayTest = JSON::parse("{\"array\" : [3, 2, 1]}");
EXPECT_FALSE(array.contains(arrayTest.get()));
arrayTest = JSON::parse("{\"array\" : [1, 2, 4]}");
EXPECT_FALSE(array.contains(arrayTest.get()));
arrayTest = JSON::parse("{\"array\" : [1, 2]}");
EXPECT_FALSE(array.contains(arrayTest.get()));
arrayTest = JSON::parse("{\"array\" : []}");
EXPECT_FALSE(array.contains(arrayTest.get()));
arrayTest = JSON::parse("{\"array\" : null}");
EXPECT_FALSE(array.contains(arrayTest.get()));
arrayTest = JSON::parse("{\"array\" : 42}");
EXPECT_FALSE(array.contains(arrayTest.get()));
arrayTest = JSON::parse("{\"array\" : \"A string\"}");
EXPECT_FALSE(array.contains(arrayTest.get()));
// Test arrays of doubles.
Try<JSON::Value> _doubleArray =
JSON::parse("{\"array_of_doubles\" : [1.0, -22.33, 99.987, 100]}");
ASSERT_SOME(_doubleArray);
const JSON::Value doubleArray = _doubleArray.get();
Try<JSON::Value> doubleArrayTest =
JSON::parse("{\"array_of_doubles\" : [1.0, -22.33, 99.987, 100]}");
EXPECT_TRUE(doubleArray.contains(doubleArrayTest.get()));
doubleArrayTest =
JSON::parse("{\"array_of_doubles\" : [1.0, -22.33, 99.999, 100]}");
EXPECT_FALSE(doubleArray.contains(doubleArrayTest.get()));
doubleArrayTest = JSON::parse("{\"array_of_doubles\" : [1.0, -22.33, 100]}");
EXPECT_FALSE(doubleArray.contains(doubleArrayTest.get()));
// Test array of arrays.
Try<JSON::Value> _arrayArray =
JSON::parse("{\"array_of_arrays\" : [[1.0, -22.33], [1, 2]]}");
ASSERT_SOME(_arrayArray);
const JSON::Value arrayArray = _arrayArray.get();
Try<JSON::Value> arrayArrayTest =
JSON::parse("{\"array_of_arrays\" : [[1.0, -22.33], [1, 2]]}");
EXPECT_TRUE(arrayArray.contains(arrayArrayTest.get()));
arrayArrayTest =
JSON::parse("{\"array_of_arrays\" : [[1.0, -22.33], [1, 3]]}");
EXPECT_FALSE(arrayArray.contains(arrayArrayTest.get()));
arrayArrayTest =
JSON::parse("{\"array_of_arrays\" : [[1.0, -33.44], [1, 3]]}");
EXPECT_FALSE(arrayArray.contains(arrayArrayTest.get()));
arrayArrayTest =
JSON::parse("{\"array_of_arrays\" : [[1.0, -22.33], [1]]}");
EXPECT_FALSE(arrayArray.contains(arrayArrayTest.get()));
}
// Test the containment of JSON objects where one is a JSON boolean.
TEST(JsonTest, ContainsBoolean)
{
Try<JSON::Value> _boolean = JSON::parse("{\"boolean\" : true}");
ASSERT_SOME(_boolean);
const JSON::Value boolean = _boolean.get();
Try<JSON::Value> booleanTest = JSON::parse("{\"boolean\" : true}");
EXPECT_TRUE(boolean.contains(booleanTest.get()));
booleanTest = JSON::parse("{}");
EXPECT_TRUE(boolean.contains(booleanTest.get()));
booleanTest = JSON::parse("{\"boolean\" : false}");
EXPECT_FALSE(boolean.contains(booleanTest.get()));
booleanTest = JSON::parse("{\"boolean\" : null}");
EXPECT_FALSE(boolean.contains(booleanTest.get()));
booleanTest = JSON::parse("{\"boolean\" : 42}");
EXPECT_FALSE(boolean.contains(booleanTest.get()));
booleanTest = JSON::parse("{\"boolean\" : \"A string\"}");
EXPECT_FALSE(boolean.contains(booleanTest.get()));
}
// Test the containment of JSON objects where one is a JSON null.
TEST(JsonTest, ContainsNull)
{
Try<JSON::Value> _nullEntry = JSON::parse("{\"null_entry\" : null}");
ASSERT_SOME(_nullEntry);
const JSON::Value nullEntry = _nullEntry.get();
Try<JSON::Value> nullEntryTest = JSON::parse("{\"null_entry\" : null}");
EXPECT_TRUE(nullEntry.contains(nullEntryTest.get()));
nullEntryTest = JSON::parse("{}");
EXPECT_TRUE(nullEntry.contains(nullEntryTest.get()));
nullEntryTest = JSON::parse("{\"null_entry\" : 42}");
EXPECT_FALSE(nullEntry.contains(nullEntryTest.get()));
nullEntryTest = JSON::parse("{\"null_entry\" : \"A string\"}");
EXPECT_FALSE(nullEntry.contains(nullEntryTest.get()));
}
// Test the containment of JSON objects where one is a JSON string.
TEST(JsonTest, ContainsString)
{
Try<JSON::Value> _str = JSON::parse("{\"string\" : \"Hello World!\"}");
ASSERT_SOME(_str);
const JSON::Value str = _str.get();
Try<JSON::Value> strTest = JSON::parse("{\"string\" : \"Hello World!\"}");
EXPECT_TRUE(str.contains(strTest.get()));
strTest = JSON::parse("{}");
EXPECT_TRUE(str.contains(strTest.get()));
strTest = JSON::parse("{\"string\" : \"Goodbye World!\"}");
EXPECT_FALSE(str.contains(strTest.get()));
strTest = JSON::parse("{\"string\" : \"\"}");
EXPECT_FALSE(str.contains(strTest.get()));
strTest = JSON::parse("{\"string\" : null}");
EXPECT_FALSE(str.contains(strTest.get()));
strTest = JSON::parse("{\"string\" : 42}");
EXPECT_FALSE(str.contains(strTest.get()));
strTest = JSON::parse("{\"string\" : [42]}");
EXPECT_FALSE(str.contains(strTest.get()));
}
// Test the containment of JSON objects to JSON objects.
TEST(JsonTest, ContainsObject)
{
Try<JSON::Value> _object = JSON::parse("{\"a\" : 1, \"b\" : 2}");
ASSERT_SOME(_object);
const JSON::Value object = _object.get();
Try<JSON::Value> objectTest = JSON::parse("{\"a\" : 1, \"b\" : 2}");
EXPECT_TRUE(object.contains(objectTest.get()));
objectTest = JSON::parse("{\"a\" : 1}");
EXPECT_TRUE(object.contains(objectTest.get()));
objectTest = JSON::parse("{\"b\" : 2}");
EXPECT_TRUE(object.contains(objectTest.get()));
objectTest = JSON::parse("{}");
EXPECT_TRUE(object.contains(objectTest.get()));
objectTest = JSON::parse("{\"a\" : 2}");
EXPECT_FALSE(object.contains(objectTest.get()));
objectTest = JSON::parse("{\"a\" : 1, \"b\" : []}");
EXPECT_FALSE(object.contains(objectTest.get()));
// Array of objects checks.
Try<JSON::Value> _objectArray = JSON::parse(
"{"
" \"objectarray\" : ["
" {\"a\" : 1, \"b\" : 2},"
" {\"c\" : 3, \"d\" : 4}"
" ]"
"}").get();
ASSERT_SOME(_objectArray);
const JSON::Value objectArray = _objectArray.get();
Try<JSON::Value> objectArrayTest = objectArray;
EXPECT_TRUE(objectArray.contains(objectArrayTest.get()));
objectArrayTest = JSON::parse("{}");
EXPECT_TRUE(objectArray.contains(objectArrayTest.get()));
objectArrayTest = JSON::parse(
"{"
" \"objectarray\" : ["
" {\"a\" : 1, \"b\" : 2},"
" {\"c\" : 3}"
" ]"
"}");
EXPECT_TRUE(objectArray.contains(objectArrayTest.get()));
objectArrayTest = JSON::parse(
"{"
" \"objectarray\" : ["
" {\"a\" : 1},"
" {}"
" ]"
"}");
EXPECT_TRUE(objectArray.contains(objectArrayTest.get()));
objectArrayTest = JSON::parse(
"{"
" \"objectarray\" : ["
" {},"
" {}"
" ]"
"}");
EXPECT_TRUE(objectArray.contains(objectArrayTest.get()));
objectArrayTest = JSON::parse(
"{"
" \"objectarray\" : ["
" {\"c\" : 3, \"d\" : 4},"
" {\"a\" : 1, \"b\" : 2}"
" ]"
"}");
EXPECT_FALSE(objectArray.contains(objectArrayTest.get()));
objectArrayTest = JSON::parse(
"{"
" \"objectarray\" : ["
" {\"e\" : 5},"
" {}"
" ]"
"}");
EXPECT_FALSE(objectArray.contains(objectArrayTest.get()));
objectArrayTest = JSON::parse(
"{"
" \"objectarray\" : []"
"}");
EXPECT_FALSE(objectArray.contains(objectArrayTest.get()));
objectArrayTest = JSON::parse(
"{"
" \"objectarray\" : ["
" {},"
" {},"
" {}"
" ]"
"}");
EXPECT_FALSE(objectArray.contains(objectArrayTest.get()));
// Tests on nested objects.
Try<JSON::Value> _nested = JSON::parse(
"{"
" \"object\" : {"
" \"a\" : 1,"
" \"b\" : 2"
" }"
"}");
ASSERT_SOME(_nested);
const JSON::Value nested = _nested.get();
Try<JSON::Value> nestedTest = nested;
EXPECT_TRUE(nested.contains(nestedTest.get()));
nestedTest = JSON::parse("{}");
EXPECT_TRUE(nested.contains(nestedTest.get()));
nestedTest = JSON::parse("{\"object\" : {}}");
EXPECT_TRUE(nested.contains(nestedTest.get()));
nestedTest = JSON::parse("{\"object\" : {\"a\" : 1}}");
EXPECT_TRUE(nested.contains(nestedTest.get()));
nestedTest = JSON::parse("{\"object\" : {\"c\" : 1}}");
EXPECT_FALSE(nested.contains(nestedTest.get()));
nestedTest = JSON::parse(
"{"
" \"object\" : {"
" \"a\" : 1,"
" \"b\" : 2,"
" \"c\" : 3"
" }"
"}");
EXPECT_FALSE(nested.contains(nestedTest.get()));
}
TEST(JsonTest, NestingDepth)
{
const size_t depth = 500000;
string deeplyNested;
for (size_t i = 0; i < depth; ++i) {
deeplyNested += "[";
}
deeplyNested += "42";
for (size_t i = 0; i < depth; ++i) {
deeplyNested += "]";
}
Try<JSON::Value> parsed = JSON::parse(deeplyNested);
ASSERT_ERROR(parsed); // Maximum depth exceeded.
}