blob: d0f5364acbde8dc01dfadaae016eae9ba1410ff3 [file] [log] [blame]
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#elif defined(_MSC_VER)
#pragma warning(disable : 4996)
#endif
#include "fuzz.h"
#include "jsontest.h"
#include <algorithm>
#include <cmath>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <json/config.h>
#include <json/json.h>
#include <limits>
#include <memory>
#include <sstream>
#include <string>
#include <vector>
using CharReaderPtr = std::unique_ptr<Json::CharReader>;
// Make numeric limits more convenient to talk about.
// Assumes int type in 32 bits.
#define kint32max Json::Value::maxInt
#define kint32min Json::Value::minInt
#define kuint32max Json::Value::maxUInt
#define kint64max Json::Value::maxInt64
#define kint64min Json::Value::minInt64
#define kuint64max Json::Value::maxUInt64
// static const double kdint64max = double(kint64max);
// static const float kfint64max = float(kint64max);
static const float kfint32max = float(kint32max);
static const float kfuint32max = float(kuint32max);
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// Json Library test cases
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
static inline double uint64ToDouble(Json::UInt64 value) {
return static_cast<double>(value);
}
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
static inline double uint64ToDouble(Json::UInt64 value) {
return static_cast<double>(Json::Int64(value / 2)) * 2.0 +
static_cast<double>(Json::Int64(value & 1));
}
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
// local_ is the collection for the testcases in this code file.
static std::deque<JsonTest::TestCaseFactory> local_;
#define JSONTEST_FIXTURE_LOCAL(FixtureType, name) \
JSONTEST_FIXTURE_V2(FixtureType, name, local_)
struct ValueTest : JsonTest::TestCase {
Json::Value null_;
Json::Value emptyArray_{Json::arrayValue};
Json::Value emptyObject_{Json::objectValue};
Json::Value integer_{123456789};
Json::Value unsignedInteger_{34567890};
Json::Value smallUnsignedInteger_{Json::Value::UInt(Json::Value::maxInt)};
Json::Value real_{1234.56789};
Json::Value float_{0.00390625f};
Json::Value array1_;
Json::Value object1_;
Json::Value emptyString_{""};
Json::Value string1_{"a"};
Json::Value string_{"sometext with space"};
Json::Value true_{true};
Json::Value false_{false};
ValueTest() {
array1_.append(1234);
object1_["id"] = 1234;
}
struct IsCheck {
/// Initialize all checks to \c false by default.
IsCheck();
bool isObject_{false};
bool isArray_{false};
bool isBool_{false};
bool isString_{false};
bool isNull_{false};
bool isInt_{false};
bool isInt64_{false};
bool isUInt_{false};
bool isUInt64_{false};
bool isIntegral_{false};
bool isDouble_{false};
bool isNumeric_{false};
};
void checkConstMemberCount(const Json::Value& value,
unsigned int expectedCount);
void checkMemberCount(Json::Value& value, unsigned int expectedCount);
void checkIs(const Json::Value& value, const IsCheck& check);
void checkIsLess(const Json::Value& x, const Json::Value& y);
void checkIsEqual(const Json::Value& x, const Json::Value& y);
/// Normalize the representation of floating-point number by stripped leading
/// 0 in exponent.
static Json::String normalizeFloatingPointStr(const Json::String& s);
};
Json::String ValueTest::normalizeFloatingPointStr(const Json::String& s) {
auto index = s.find_last_of("eE");
if (index == s.npos)
return s;
std::size_t signWidth = (s[index + 1] == '+' || s[index + 1] == '-') ? 1 : 0;
auto exponentStartIndex = index + 1 + signWidth;
Json::String normalized = s.substr(0, exponentStartIndex);
auto indexDigit = s.find_first_not_of('0', exponentStartIndex);
Json::String exponent = "0";
if (indexDigit != s.npos) { // nonzero exponent
exponent = s.substr(indexDigit);
}
return normalized + exponent;
}
JSONTEST_FIXTURE_LOCAL(ValueTest, checkNormalizeFloatingPointStr) {
struct TestData {
std::string in;
std::string out;
} const testData[] = {
{"0.0", "0.0"},
{"0e0", "0e0"},
{"1234.0", "1234.0"},
{"1234.0e0", "1234.0e0"},
{"1234.0e-1", "1234.0e-1"},
{"1234.0e+0", "1234.0e+0"},
{"1234.0e+001", "1234.0e+1"},
{"1234e-1", "1234e-1"},
{"1234e+000", "1234e+0"},
{"1234e+001", "1234e+1"},
{"1234e10", "1234e10"},
{"1234e010", "1234e10"},
{"1234e+010", "1234e+10"},
{"1234e-010", "1234e-10"},
{"1234e+100", "1234e+100"},
{"1234e-100", "1234e-100"},
};
for (const auto& td : testData) {
JSONTEST_ASSERT_STRING_EQUAL(normalizeFloatingPointStr(td.in), td.out);
}
}
JSONTEST_FIXTURE_LOCAL(ValueTest, memberCount) {
JSONTEST_ASSERT_PRED(checkMemberCount(emptyArray_, 0));
JSONTEST_ASSERT_PRED(checkMemberCount(emptyObject_, 0));
JSONTEST_ASSERT_PRED(checkMemberCount(array1_, 1));
JSONTEST_ASSERT_PRED(checkMemberCount(object1_, 1));
JSONTEST_ASSERT_PRED(checkMemberCount(null_, 0));
JSONTEST_ASSERT_PRED(checkMemberCount(integer_, 0));
JSONTEST_ASSERT_PRED(checkMemberCount(unsignedInteger_, 0));
JSONTEST_ASSERT_PRED(checkMemberCount(smallUnsignedInteger_, 0));
JSONTEST_ASSERT_PRED(checkMemberCount(real_, 0));
JSONTEST_ASSERT_PRED(checkMemberCount(emptyString_, 0));
JSONTEST_ASSERT_PRED(checkMemberCount(string_, 0));
JSONTEST_ASSERT_PRED(checkMemberCount(true_, 0));
JSONTEST_ASSERT_PRED(checkMemberCount(false_, 0));
JSONTEST_ASSERT_PRED(checkMemberCount(string1_, 0));
JSONTEST_ASSERT_PRED(checkMemberCount(float_, 0));
}
JSONTEST_FIXTURE_LOCAL(ValueTest, objects) {
// Types
IsCheck checks;
checks.isObject_ = true;
JSONTEST_ASSERT_PRED(checkIs(emptyObject_, checks));
JSONTEST_ASSERT_PRED(checkIs(object1_, checks));
JSONTEST_ASSERT_EQUAL(Json::objectValue, emptyObject_.type());
// Empty object okay
JSONTEST_ASSERT(emptyObject_.isConvertibleTo(Json::nullValue));
// Non-empty object not okay
JSONTEST_ASSERT(!object1_.isConvertibleTo(Json::nullValue));
// Always okay
JSONTEST_ASSERT(emptyObject_.isConvertibleTo(Json::objectValue));
// Never okay
JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::stringValue));
// Access through const reference
const Json::Value& constObject = object1_;
JSONTEST_ASSERT_EQUAL(Json::Value(1234), constObject["id"]);
JSONTEST_ASSERT_EQUAL(Json::Value(), constObject["unknown id"]);
// Access through find()
const char idKey[] = "id";
const Json::Value* foundId = object1_.find(idKey, idKey + strlen(idKey));
JSONTEST_ASSERT(foundId != nullptr);
JSONTEST_ASSERT_EQUAL(Json::Value(1234), *foundId);
const char unknownIdKey[] = "unknown id";
const Json::Value* foundUnknownId =
object1_.find(unknownIdKey, unknownIdKey + strlen(unknownIdKey));
JSONTEST_ASSERT_EQUAL(nullptr, foundUnknownId);
// Access through demand()
const char yetAnotherIdKey[] = "yet another id";
const Json::Value* foundYetAnotherId =
object1_.find(yetAnotherIdKey, yetAnotherIdKey + strlen(yetAnotherIdKey));
JSONTEST_ASSERT_EQUAL(nullptr, foundYetAnotherId);
Json::Value* demandedYetAnotherId = object1_.demand(
yetAnotherIdKey, yetAnotherIdKey + strlen(yetAnotherIdKey));
JSONTEST_ASSERT(demandedYetAnotherId != nullptr);
*demandedYetAnotherId = "baz";
JSONTEST_ASSERT_EQUAL(Json::Value("baz"), object1_["yet another id"]);
// Access through non-const reference
JSONTEST_ASSERT_EQUAL(Json::Value(1234), object1_["id"]);
JSONTEST_ASSERT_EQUAL(Json::Value(), object1_["unknown id"]);
object1_["some other id"] = "foo";
JSONTEST_ASSERT_EQUAL(Json::Value("foo"), object1_["some other id"]);
JSONTEST_ASSERT_EQUAL(Json::Value("foo"), object1_["some other id"]);
// Remove.
Json::Value got;
bool did;
did = object1_.removeMember("some other id", &got);
JSONTEST_ASSERT_EQUAL(Json::Value("foo"), got);
JSONTEST_ASSERT_EQUAL(true, did);
got = Json::Value("bar");
did = object1_.removeMember("some other id", &got);
JSONTEST_ASSERT_EQUAL(Json::Value("bar"), got);
JSONTEST_ASSERT_EQUAL(false, did);
object1_["some other id"] = "foo";
Json::Value* gotPtr = nullptr;
did = object1_.removeMember("some other id", gotPtr);
JSONTEST_ASSERT_EQUAL(nullptr, gotPtr);
JSONTEST_ASSERT_EQUAL(true, did);
// Using other removeMember interfaces, the test idea is the same as above.
object1_["some other id"] = "foo";
const Json::String key("some other id");
did = object1_.removeMember(key, &got);
JSONTEST_ASSERT_EQUAL(Json::Value("foo"), got);
JSONTEST_ASSERT_EQUAL(true, did);
got = Json::Value("bar");
did = object1_.removeMember(key, &got);
JSONTEST_ASSERT_EQUAL(Json::Value("bar"), got);
JSONTEST_ASSERT_EQUAL(false, did);
object1_["some other id"] = "foo";
object1_.removeMember(key);
JSONTEST_ASSERT_EQUAL(Json::nullValue, object1_[key]);
}
JSONTEST_FIXTURE_LOCAL(ValueTest, arrays) {
const unsigned int index0 = 0;
// Types
IsCheck checks;
checks.isArray_ = true;
JSONTEST_ASSERT_PRED(checkIs(emptyArray_, checks));
JSONTEST_ASSERT_PRED(checkIs(array1_, checks));
JSONTEST_ASSERT_EQUAL(Json::arrayValue, array1_.type());
// Empty array okay
JSONTEST_ASSERT(emptyArray_.isConvertibleTo(Json::nullValue));
// Non-empty array not okay
JSONTEST_ASSERT(!array1_.isConvertibleTo(Json::nullValue));
// Always okay
JSONTEST_ASSERT(emptyArray_.isConvertibleTo(Json::arrayValue));
// Never okay
JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::objectValue));
JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::stringValue));
// Access through const reference
const Json::Value& constArray = array1_;
JSONTEST_ASSERT_EQUAL(Json::Value(1234), constArray[index0]);
JSONTEST_ASSERT_EQUAL(Json::Value(1234), constArray[0]);
// Access through non-const reference
JSONTEST_ASSERT_EQUAL(Json::Value(1234), array1_[index0]);
JSONTEST_ASSERT_EQUAL(Json::Value(1234), array1_[0]);
array1_[2] = Json::Value(17);
JSONTEST_ASSERT_EQUAL(Json::Value(), array1_[1]);
JSONTEST_ASSERT_EQUAL(Json::Value(17), array1_[2]);
Json::Value got;
JSONTEST_ASSERT_EQUAL(true, array1_.removeIndex(2, &got));
JSONTEST_ASSERT_EQUAL(Json::Value(17), got);
JSONTEST_ASSERT_EQUAL(false, array1_.removeIndex(2, &got)); // gone now
}
JSONTEST_FIXTURE_LOCAL(ValueTest, resizeArray) {
Json::Value array;
{
for (Json::ArrayIndex i = 0; i < 10; i++)
array[i] = i;
JSONTEST_ASSERT_EQUAL(array.size(), 10);
// The length set is greater than the length of the array.
array.resize(15);
JSONTEST_ASSERT_EQUAL(array.size(), 15);
// The length set is less than the length of the array.
array.resize(5);
JSONTEST_ASSERT_EQUAL(array.size(), 5);
// The length of the array is set to 0.
array.resize(0);
JSONTEST_ASSERT_EQUAL(array.size(), 0);
}
{
for (Json::ArrayIndex i = 0; i < 10; i++)
array[i] = i;
JSONTEST_ASSERT_EQUAL(array.size(), 10);
array.clear();
JSONTEST_ASSERT_EQUAL(array.size(), 0);
}
}
JSONTEST_FIXTURE_LOCAL(ValueTest, resizePopulatesAllMissingElements) {
Json::ArrayIndex n = 10;
Json::Value v;
v.resize(n);
JSONTEST_ASSERT_EQUAL(n, v.size());
JSONTEST_ASSERT_EQUAL(n, std::distance(v.begin(), v.end()));
for (const Json::Value& e : v)
JSONTEST_ASSERT_EQUAL(e, Json::Value{});
}
JSONTEST_FIXTURE_LOCAL(ValueTest, getArrayValue) {
Json::Value array;
for (Json::ArrayIndex i = 0; i < 5; i++)
array[i] = i;
JSONTEST_ASSERT_EQUAL(array.size(), 5);
const Json::Value defaultValue(10);
Json::ArrayIndex index = 0;
for (; index <= 4; index++)
JSONTEST_ASSERT_EQUAL(index, array.get(index, defaultValue).asInt());
index = 4;
JSONTEST_ASSERT_EQUAL(array.isValidIndex(index), true);
index = 5;
JSONTEST_ASSERT_EQUAL(array.isValidIndex(index), false);
JSONTEST_ASSERT_EQUAL(defaultValue, array.get(index, defaultValue));
JSONTEST_ASSERT_EQUAL(array.isValidIndex(index), false);
}
JSONTEST_FIXTURE_LOCAL(ValueTest, arrayIssue252) {
int count = 5;
Json::Value root;
Json::Value item;
root["array"] = Json::Value::nullSingleton();
for (int i = 0; i < count; i++) {
item["a"] = i;
item["b"] = i;
root["array"][i] = item;
}
// JSONTEST_ASSERT_EQUAL(5, root["array"].size());
}
JSONTEST_FIXTURE_LOCAL(ValueTest, arrayInsertAtRandomIndex) {
Json::Value array;
const Json::Value str0("index2");
const Json::Value str1("index3");
array.append("index0"); // append rvalue
array.append("index1");
array.append(str0); // append lvalue
std::vector<Json::Value*> vec; // storage value address for checking
for (Json::ArrayIndex i = 0; i < 3; i++) {
vec.push_back(&array[i]);
}
JSONTEST_ASSERT_EQUAL(Json::Value("index0"), array[0]); // check append
JSONTEST_ASSERT_EQUAL(Json::Value("index1"), array[1]);
JSONTEST_ASSERT_EQUAL(Json::Value("index2"), array[2]);
// insert lvalue at the head
JSONTEST_ASSERT(array.insert(0, str1));
JSONTEST_ASSERT_EQUAL(Json::Value("index3"), array[0]);
JSONTEST_ASSERT_EQUAL(Json::Value("index0"), array[1]);
JSONTEST_ASSERT_EQUAL(Json::Value("index1"), array[2]);
JSONTEST_ASSERT_EQUAL(Json::Value("index2"), array[3]);
// checking address
for (Json::ArrayIndex i = 0; i < 3; i++) {
JSONTEST_ASSERT_EQUAL(vec[i], &array[i]);
}
vec.push_back(&array[3]);
// insert rvalue at middle
JSONTEST_ASSERT(array.insert(2, "index4"));
JSONTEST_ASSERT_EQUAL(Json::Value("index3"), array[0]);
JSONTEST_ASSERT_EQUAL(Json::Value("index0"), array[1]);
JSONTEST_ASSERT_EQUAL(Json::Value("index4"), array[2]);
JSONTEST_ASSERT_EQUAL(Json::Value("index1"), array[3]);
JSONTEST_ASSERT_EQUAL(Json::Value("index2"), array[4]);
// checking address
for (Json::ArrayIndex i = 0; i < 4; i++) {
JSONTEST_ASSERT_EQUAL(vec[i], &array[i]);
}
vec.push_back(&array[4]);
// insert rvalue at the tail
JSONTEST_ASSERT(array.insert(5, "index5"));
JSONTEST_ASSERT_EQUAL(Json::Value("index3"), array[0]);
JSONTEST_ASSERT_EQUAL(Json::Value("index0"), array[1]);
JSONTEST_ASSERT_EQUAL(Json::Value("index4"), array[2]);
JSONTEST_ASSERT_EQUAL(Json::Value("index1"), array[3]);
JSONTEST_ASSERT_EQUAL(Json::Value("index2"), array[4]);
JSONTEST_ASSERT_EQUAL(Json::Value("index5"), array[5]);
// checking address
for (Json::ArrayIndex i = 0; i < 5; i++) {
JSONTEST_ASSERT_EQUAL(vec[i], &array[i]);
}
vec.push_back(&array[5]);
// beyond max array size, it should not be allowed to insert into its tail
JSONTEST_ASSERT(!array.insert(10, "index10"));
}
JSONTEST_FIXTURE_LOCAL(ValueTest, null) {
JSONTEST_ASSERT_EQUAL(Json::nullValue, null_.type());
IsCheck checks;
checks.isNull_ = true;
JSONTEST_ASSERT_PRED(checkIs(null_, checks));
JSONTEST_ASSERT(null_.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(null_.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(null_.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT(null_.isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(null_.isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(null_.isConvertibleTo(Json::stringValue));
JSONTEST_ASSERT(null_.isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(null_.isConvertibleTo(Json::objectValue));
JSONTEST_ASSERT_EQUAL(Json::Int(0), null_.asInt());
JSONTEST_ASSERT_EQUAL(Json::LargestInt(0), null_.asLargestInt());
JSONTEST_ASSERT_EQUAL(Json::UInt(0), null_.asUInt());
JSONTEST_ASSERT_EQUAL(Json::LargestUInt(0), null_.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, null_.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, null_.asFloat());
JSONTEST_ASSERT_STRING_EQUAL("", null_.asString());
JSONTEST_ASSERT_EQUAL(Json::Value::nullSingleton(), null_);
// Test using a Value in a boolean context (false iff null)
JSONTEST_ASSERT_EQUAL(null_, false);
JSONTEST_ASSERT_EQUAL(object1_, true);
JSONTEST_ASSERT_EQUAL(!null_, true);
JSONTEST_ASSERT_EQUAL(!object1_, false);
}
JSONTEST_FIXTURE_LOCAL(ValueTest, strings) {
JSONTEST_ASSERT_EQUAL(Json::stringValue, string1_.type());
IsCheck checks;
checks.isString_ = true;
JSONTEST_ASSERT_PRED(checkIs(emptyString_, checks));
JSONTEST_ASSERT_PRED(checkIs(string_, checks));
JSONTEST_ASSERT_PRED(checkIs(string1_, checks));
// Empty string okay
JSONTEST_ASSERT(emptyString_.isConvertibleTo(Json::nullValue));
// Non-empty string not okay
JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::nullValue));
// Always okay
JSONTEST_ASSERT(string1_.isConvertibleTo(Json::stringValue));
// Never okay
JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::objectValue));
JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::realValue));
JSONTEST_ASSERT_STRING_EQUAL("a", string1_.asString());
JSONTEST_ASSERT_STRING_EQUAL("a", string1_.asCString());
}
JSONTEST_FIXTURE_LOCAL(ValueTest, bools) {
JSONTEST_ASSERT_EQUAL(Json::booleanValue, false_.type());
IsCheck checks;
checks.isBool_ = true;
JSONTEST_ASSERT_PRED(checkIs(false_, checks));
JSONTEST_ASSERT_PRED(checkIs(true_, checks));
// False okay
JSONTEST_ASSERT(false_.isConvertibleTo(Json::nullValue));
// True not okay
JSONTEST_ASSERT(!true_.isConvertibleTo(Json::nullValue));
// Always okay
JSONTEST_ASSERT(true_.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(true_.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT(true_.isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(true_.isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(true_.isConvertibleTo(Json::stringValue));
// Never okay
JSONTEST_ASSERT(!true_.isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!true_.isConvertibleTo(Json::objectValue));
JSONTEST_ASSERT_EQUAL(true, true_.asBool());
JSONTEST_ASSERT_EQUAL(1, true_.asInt());
JSONTEST_ASSERT_EQUAL(1, true_.asLargestInt());
JSONTEST_ASSERT_EQUAL(1, true_.asUInt());
JSONTEST_ASSERT_EQUAL(1, true_.asLargestUInt());
JSONTEST_ASSERT_EQUAL(1.0, true_.asDouble());
JSONTEST_ASSERT_EQUAL(1.0, true_.asFloat());
JSONTEST_ASSERT_EQUAL(false, false_.asBool());
JSONTEST_ASSERT_EQUAL(0, false_.asInt());
JSONTEST_ASSERT_EQUAL(0, false_.asLargestInt());
JSONTEST_ASSERT_EQUAL(0, false_.asUInt());
JSONTEST_ASSERT_EQUAL(0, false_.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, false_.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, false_.asFloat());
}
JSONTEST_FIXTURE_LOCAL(ValueTest, integers) {
IsCheck checks;
Json::Value val;
// Conversions that don't depend on the value.
JSONTEST_ASSERT(Json::Value(17).isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(Json::Value(17).isConvertibleTo(Json::stringValue));
JSONTEST_ASSERT(Json::Value(17).isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(!Json::Value(17).isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!Json::Value(17).isConvertibleTo(Json::objectValue));
JSONTEST_ASSERT(Json::Value(17U).isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(Json::Value(17U).isConvertibleTo(Json::stringValue));
JSONTEST_ASSERT(Json::Value(17U).isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(!Json::Value(17U).isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!Json::Value(17U).isConvertibleTo(Json::objectValue));
JSONTEST_ASSERT(Json::Value(17.0).isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(Json::Value(17.0).isConvertibleTo(Json::stringValue));
JSONTEST_ASSERT(Json::Value(17.0).isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(!Json::Value(17.0).isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!Json::Value(17.0).isConvertibleTo(Json::objectValue));
// Default int
val = Json::Value(Json::intValue);
JSONTEST_ASSERT_EQUAL(Json::intValue, val.type());
checks = IsCheck();
checks.isInt_ = true;
checks.isInt64_ = true;
checks.isUInt_ = true;
checks.isUInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(0, val.asInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(0, val.asUInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(false, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("0", val.asString());
// Default uint
val = Json::Value(Json::uintValue);
JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type());
checks = IsCheck();
checks.isInt_ = true;
checks.isInt64_ = true;
checks.isUInt_ = true;
checks.isUInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(0, val.asInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(0, val.asUInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(false, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("0", val.asString());
// Default real
val = Json::Value(Json::realValue);
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
checks = IsCheck();
checks.isInt_ = true;
checks.isInt64_ = true;
checks.isUInt_ = true;
checks.isUInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT_EQUAL(0, val.asInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(0, val.asUInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(false, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("0.0", val.asString());
// Zero (signed constructor arg)
val = Json::Value(0);
JSONTEST_ASSERT_EQUAL(Json::intValue, val.type());
checks = IsCheck();
checks.isInt_ = true;
checks.isInt64_ = true;
checks.isUInt_ = true;
checks.isUInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(0, val.asInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(0, val.asUInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(false, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("0", val.asString());
// Zero (unsigned constructor arg)
val = Json::Value(0u);
JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type());
checks = IsCheck();
checks.isInt_ = true;
checks.isInt64_ = true;
checks.isUInt_ = true;
checks.isUInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(0, val.asInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(0, val.asUInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(false, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("0", val.asString());
// Zero (floating-point constructor arg)
val = Json::Value(0.0);
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
checks = IsCheck();
checks.isInt_ = true;
checks.isInt64_ = true;
checks.isUInt_ = true;
checks.isUInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(0, val.asInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(0, val.asUInt());
JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(false, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("0.0", val.asString());
// 2^20 (signed constructor arg)
val = Json::Value(1 << 20);
JSONTEST_ASSERT_EQUAL(Json::intValue, val.type());
checks = IsCheck();
checks.isInt_ = true;
checks.isInt64_ = true;
checks.isUInt_ = true;
checks.isUInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL((1 << 20), val.asInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asUInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestUInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("1048576", val.asString());
// 2^20 (unsigned constructor arg)
val = Json::Value(Json::UInt(1 << 20));
JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type());
checks = IsCheck();
checks.isInt_ = true;
checks.isInt64_ = true;
checks.isUInt_ = true;
checks.isUInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL((1 << 20), val.asInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asUInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestUInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("1048576", val.asString());
// 2^20 (floating-point constructor arg)
val = Json::Value((1 << 20) / 1.0);
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
checks = IsCheck();
checks.isInt_ = true;
checks.isInt64_ = true;
checks.isUInt_ = true;
checks.isUInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL((1 << 20), val.asInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asUInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestUInt());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble());
JSONTEST_ASSERT_EQUAL((1 << 20), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL(
"1048576.0",
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
// -2^20
val = Json::Value(-(1 << 20));
JSONTEST_ASSERT_EQUAL(Json::intValue, val.type());
checks = IsCheck();
checks.isInt_ = true;
checks.isInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asInt());
JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asLargestInt());
JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asDouble());
JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("-1048576", val.asString());
// int32 max
val = Json::Value(kint32max);
JSONTEST_ASSERT_EQUAL(Json::intValue, val.type());
checks = IsCheck();
checks.isInt_ = true;
checks.isInt64_ = true;
checks.isUInt_ = true;
checks.isUInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(kint32max, val.asInt());
JSONTEST_ASSERT_EQUAL(kint32max, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(kint32max, val.asUInt());
JSONTEST_ASSERT_EQUAL(kint32max, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(kint32max, val.asDouble());
JSONTEST_ASSERT_EQUAL(kfint32max, val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("2147483647", val.asString());
// int32 min
val = Json::Value(kint32min);
JSONTEST_ASSERT_EQUAL(Json::intValue, val.type());
checks = IsCheck();
checks.isInt_ = true;
checks.isInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(kint32min, val.asInt());
JSONTEST_ASSERT_EQUAL(kint32min, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(kint32min, val.asDouble());
JSONTEST_ASSERT_EQUAL(kint32min, val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("-2147483648", val.asString());
// uint32 max
val = Json::Value(kuint32max);
JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type());
checks = IsCheck();
checks.isInt64_ = true;
checks.isUInt_ = true;
checks.isUInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
#ifndef JSON_NO_INT64
JSONTEST_ASSERT_EQUAL(kuint32max, val.asLargestInt());
#endif
JSONTEST_ASSERT_EQUAL(kuint32max, val.asUInt());
JSONTEST_ASSERT_EQUAL(kuint32max, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(kuint32max, val.asDouble());
JSONTEST_ASSERT_EQUAL(kfuint32max, val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("4294967295", val.asString());
#ifdef JSON_NO_INT64
// int64 max
val = Json::Value(double(kint64max));
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
checks = IsCheck();
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(double(kint64max), val.asDouble());
JSONTEST_ASSERT_EQUAL(float(kint64max), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("9.22337e+18", val.asString());
// int64 min
val = Json::Value(double(kint64min));
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
checks = IsCheck();
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(double(kint64min), val.asDouble());
JSONTEST_ASSERT_EQUAL(float(kint64min), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("-9.22337e+18", val.asString());
// uint64 max
val = Json::Value(double(kuint64max));
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
checks = IsCheck();
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(double(kuint64max), val.asDouble());
JSONTEST_ASSERT_EQUAL(float(kuint64max), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("1.84467e+19", val.asString());
#else // ifdef JSON_NO_INT64
// 2^40 (signed constructor arg)
val = Json::Value(Json::Int64(1) << 40);
JSONTEST_ASSERT_EQUAL(Json::intValue, val.type());
checks = IsCheck();
checks.isInt64_ = true;
checks.isUInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asInt64());
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestInt());
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asUInt64());
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestUInt());
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asDouble());
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("1099511627776", val.asString());
// 2^40 (unsigned constructor arg)
val = Json::Value(Json::UInt64(1) << 40);
JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type());
checks = IsCheck();
checks.isInt64_ = true;
checks.isUInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asInt64());
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestInt());
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asUInt64());
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestUInt());
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asDouble());
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("1099511627776", val.asString());
// 2^40 (floating-point constructor arg)
val = Json::Value((Json::Int64(1) << 40) / 1.0);
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
checks = IsCheck();
checks.isInt64_ = true;
checks.isUInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asInt64());
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestInt());
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asUInt64());
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestUInt());
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asDouble());
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL(
"1099511627776.0",
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
// -2^40
val = Json::Value(-(Json::Int64(1) << 40));
JSONTEST_ASSERT_EQUAL(Json::intValue, val.type());
checks = IsCheck();
checks.isInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(-(Json::Int64(1) << 40), val.asInt64());
JSONTEST_ASSERT_EQUAL(-(Json::Int64(1) << 40), val.asLargestInt());
JSONTEST_ASSERT_EQUAL(-(Json::Int64(1) << 40), val.asDouble());
JSONTEST_ASSERT_EQUAL(-(Json::Int64(1) << 40), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("-1099511627776", val.asString());
// int64 max
val = Json::Value(Json::Int64(kint64max));
JSONTEST_ASSERT_EQUAL(Json::intValue, val.type());
checks = IsCheck();
checks.isInt64_ = true;
checks.isUInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(kint64max, val.asInt64());
JSONTEST_ASSERT_EQUAL(kint64max, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(kint64max, val.asUInt64());
JSONTEST_ASSERT_EQUAL(kint64max, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(double(kint64max), val.asDouble());
JSONTEST_ASSERT_EQUAL(float(kint64max), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("9223372036854775807", val.asString());
// int64 max (floating point constructor). Note that kint64max is not exactly
// representable as a double, and will be rounded up to be higher.
val = Json::Value(double(kint64max));
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
checks = IsCheck();
checks.isUInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(Json::UInt64(1) << 63, val.asUInt64());
JSONTEST_ASSERT_EQUAL(Json::UInt64(1) << 63, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(uint64ToDouble(Json::UInt64(1) << 63), val.asDouble());
JSONTEST_ASSERT_EQUAL(float(Json::UInt64(1) << 63), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL(
"9.2233720368547758e+18",
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
// int64 min
val = Json::Value(Json::Int64(kint64min));
JSONTEST_ASSERT_EQUAL(Json::intValue, val.type());
checks = IsCheck();
checks.isInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(kint64min, val.asInt64());
JSONTEST_ASSERT_EQUAL(kint64min, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(double(kint64min), val.asDouble());
JSONTEST_ASSERT_EQUAL(float(kint64min), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("-9223372036854775808", val.asString());
// int64 min (floating point constructor). Note that kint64min *is* exactly
// representable as a double.
val = Json::Value(double(kint64min));
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
checks = IsCheck();
checks.isInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(kint64min, val.asInt64());
JSONTEST_ASSERT_EQUAL(kint64min, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL(
"-9.2233720368547758e+18",
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
// 10^19
const auto ten_to_19 = static_cast<Json::UInt64>(1e19);
val = Json::Value(Json::UInt64(ten_to_19));
JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type());
checks = IsCheck();
checks.isUInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(ten_to_19, val.asUInt64());
JSONTEST_ASSERT_EQUAL(ten_to_19, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(uint64ToDouble(ten_to_19), val.asDouble());
JSONTEST_ASSERT_EQUAL(float(uint64ToDouble(ten_to_19)), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("10000000000000000000", val.asString());
// 10^19 (double constructor). Note that 10^19 is not exactly representable
// as a double.
val = Json::Value(uint64ToDouble(ten_to_19));
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
checks = IsCheck();
checks.isUInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(1e19, val.asDouble());
JSONTEST_ASSERT_EQUAL(1e19, val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL(
"1e+19",
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
// uint64 max
val = Json::Value(Json::UInt64(kuint64max));
JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type());
checks = IsCheck();
checks.isUInt64_ = true;
checks.isIntegral_ = true;
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(kuint64max, val.asUInt64());
JSONTEST_ASSERT_EQUAL(kuint64max, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(uint64ToDouble(kuint64max), val.asDouble());
JSONTEST_ASSERT_EQUAL(float(uint64ToDouble(kuint64max)), val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("18446744073709551615", val.asString());
// uint64 max (floating point constructor). Note that kuint64max is not
// exactly representable as a double, and will be rounded up to be higher.
val = Json::Value(uint64ToDouble(kuint64max));
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
checks = IsCheck();
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT_EQUAL(18446744073709551616.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(18446744073709551616.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL(
"1.8446744073709552e+19",
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
#endif
}
JSONTEST_FIXTURE_LOCAL(ValueTest, nonIntegers) {
IsCheck checks;
Json::Value val;
// Small positive number
val = Json::Value(1.5);
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
checks = IsCheck();
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue));
JSONTEST_ASSERT_EQUAL(1.5, val.asDouble());
JSONTEST_ASSERT_EQUAL(1.5, val.asFloat());
JSONTEST_ASSERT_EQUAL(1, val.asInt());
JSONTEST_ASSERT_EQUAL(1, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(1, val.asUInt());
JSONTEST_ASSERT_EQUAL(1, val.asLargestUInt());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_EQUAL("1.5", val.asString());
// Small negative number
val = Json::Value(-1.5);
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
checks = IsCheck();
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue));
JSONTEST_ASSERT_EQUAL(-1.5, val.asDouble());
JSONTEST_ASSERT_EQUAL(-1.5, val.asFloat());
JSONTEST_ASSERT_EQUAL(-1, val.asInt());
JSONTEST_ASSERT_EQUAL(-1, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_EQUAL("-1.5", val.asString());
// A bit over int32 max
val = Json::Value(kint32max + 0.5);
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
checks = IsCheck();
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue));
JSONTEST_ASSERT_EQUAL(2147483647.5, val.asDouble());
JSONTEST_ASSERT_EQUAL(float(2147483647.5), val.asFloat());
JSONTEST_ASSERT_EQUAL(2147483647U, val.asUInt());
#ifdef JSON_HAS_INT64
JSONTEST_ASSERT_EQUAL(2147483647L, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(2147483647U, val.asLargestUInt());
#endif
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_EQUAL(
"2147483647.5",
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
// A bit under int32 min
val = Json::Value(kint32min - 0.5);
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
checks = IsCheck();
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue));
JSONTEST_ASSERT_EQUAL(-2147483648.5, val.asDouble());
JSONTEST_ASSERT_EQUAL(float(-2147483648.5), val.asFloat());
#ifdef JSON_HAS_INT64
JSONTEST_ASSERT_EQUAL(-(Json::Int64(1) << 31), val.asLargestInt());
#endif
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_EQUAL(
"-2147483648.5",
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
// A bit over uint32 max
val = Json::Value(kuint32max + 0.5);
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
checks = IsCheck();
checks.isDouble_ = true;
checks.isNumeric_ = true;
JSONTEST_ASSERT_PRED(checkIs(val, checks));
JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue));
JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue));
JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue));
JSONTEST_ASSERT_EQUAL(4294967295.5, val.asDouble());
JSONTEST_ASSERT_EQUAL(float(4294967295.5), val.asFloat());
#ifdef JSON_HAS_INT64
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 32) - 1, val.asLargestInt());
JSONTEST_ASSERT_EQUAL((Json::UInt64(1) << 32) - Json::UInt64(1),
val.asLargestUInt());
#endif
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_EQUAL(
"4294967295.5",
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
val = Json::Value(1.2345678901234);
JSONTEST_ASSERT_STRING_EQUAL(
"1.2345678901234001",
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
// A 16-digit floating point number.
val = Json::Value(2199023255552000.0f);
JSONTEST_ASSERT_EQUAL(float(2199023255552000.0f), val.asFloat());
JSONTEST_ASSERT_STRING_EQUAL(
"2199023255552000.0",
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
// A very large floating point number.
val = Json::Value(3.402823466385289e38);
JSONTEST_ASSERT_EQUAL(float(3.402823466385289e38), val.asFloat());
JSONTEST_ASSERT_STRING_EQUAL(
"3.402823466385289e+38",
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
// An even larger floating point number.
val = Json::Value(1.2345678e300);
JSONTEST_ASSERT_EQUAL(double(1.2345678e300), val.asDouble());
JSONTEST_ASSERT_STRING_EQUAL(
"1.2345678e+300",
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
}
void ValueTest::checkConstMemberCount(const Json::Value& value,
unsigned int expectedCount) {
unsigned int count = 0;
Json::Value::const_iterator itEnd = value.end();
for (Json::Value::const_iterator it = value.begin(); it != itEnd; ++it) {
++count;
}
JSONTEST_ASSERT_EQUAL(expectedCount, count) << "Json::Value::const_iterator";
}
void ValueTest::checkMemberCount(Json::Value& value,
unsigned int expectedCount) {
JSONTEST_ASSERT_EQUAL(expectedCount, value.size());
unsigned int count = 0;
Json::Value::iterator itEnd = value.end();
for (Json::Value::iterator it = value.begin(); it != itEnd; ++it) {
++count;
}
JSONTEST_ASSERT_EQUAL(expectedCount, count) << "Json::Value::iterator";
JSONTEST_ASSERT_PRED(checkConstMemberCount(value, expectedCount));
}
ValueTest::IsCheck::IsCheck() = default;
void ValueTest::checkIs(const Json::Value& value, const IsCheck& check) {
JSONTEST_ASSERT_EQUAL(check.isObject_, value.isObject());
JSONTEST_ASSERT_EQUAL(check.isArray_, value.isArray());
JSONTEST_ASSERT_EQUAL(check.isBool_, value.isBool());
JSONTEST_ASSERT_EQUAL(check.isDouble_, value.isDouble());
JSONTEST_ASSERT_EQUAL(check.isInt_, value.isInt());
JSONTEST_ASSERT_EQUAL(check.isUInt_, value.isUInt());
JSONTEST_ASSERT_EQUAL(check.isIntegral_, value.isIntegral());
JSONTEST_ASSERT_EQUAL(check.isNumeric_, value.isNumeric());
JSONTEST_ASSERT_EQUAL(check.isString_, value.isString());
JSONTEST_ASSERT_EQUAL(check.isNull_, value.isNull());
#ifdef JSON_HAS_INT64
JSONTEST_ASSERT_EQUAL(check.isInt64_, value.isInt64());
JSONTEST_ASSERT_EQUAL(check.isUInt64_, value.isUInt64());
#else
JSONTEST_ASSERT_EQUAL(false, value.isInt64());
JSONTEST_ASSERT_EQUAL(false, value.isUInt64());
#endif
}
JSONTEST_FIXTURE_LOCAL(ValueTest, compareNull) {
JSONTEST_ASSERT_PRED(checkIsEqual(Json::Value(), Json::Value()));
JSONTEST_ASSERT_PRED(
checkIsEqual(Json::Value::nullSingleton(), Json::Value()));
JSONTEST_ASSERT_PRED(
checkIsEqual(Json::Value::nullSingleton(), Json::Value::nullSingleton()));
}
JSONTEST_FIXTURE_LOCAL(ValueTest, compareInt) {
JSONTEST_ASSERT_PRED(checkIsLess(0, 10));
JSONTEST_ASSERT_PRED(checkIsEqual(10, 10));
JSONTEST_ASSERT_PRED(checkIsEqual(-10, -10));
JSONTEST_ASSERT_PRED(checkIsLess(-10, 0));
}
JSONTEST_FIXTURE_LOCAL(ValueTest, compareUInt) {
JSONTEST_ASSERT_PRED(checkIsLess(0u, 10u));
JSONTEST_ASSERT_PRED(checkIsLess(0u, Json::Value::maxUInt));
JSONTEST_ASSERT_PRED(checkIsEqual(10u, 10u));
}
JSONTEST_FIXTURE_LOCAL(ValueTest, compareDouble) {
JSONTEST_ASSERT_PRED(checkIsLess(0.0, 10.0));
JSONTEST_ASSERT_PRED(checkIsEqual(10.0, 10.0));
JSONTEST_ASSERT_PRED(checkIsEqual(-10.0, -10.0));
JSONTEST_ASSERT_PRED(checkIsLess(-10.0, 0.0));
}
JSONTEST_FIXTURE_LOCAL(ValueTest, compareString) {
JSONTEST_ASSERT_PRED(checkIsLess("", " "));
JSONTEST_ASSERT_PRED(checkIsLess("", "a"));
JSONTEST_ASSERT_PRED(checkIsLess("abcd", "zyui"));
JSONTEST_ASSERT_PRED(checkIsLess("abc", "abcd"));
JSONTEST_ASSERT_PRED(checkIsEqual("abcd", "abcd"));
JSONTEST_ASSERT_PRED(checkIsEqual(" ", " "));
JSONTEST_ASSERT_PRED(checkIsLess("ABCD", "abcd"));
JSONTEST_ASSERT_PRED(checkIsEqual("ABCD", "ABCD"));
}
JSONTEST_FIXTURE_LOCAL(ValueTest, compareBoolean) {
JSONTEST_ASSERT_PRED(checkIsLess(false, true));
JSONTEST_ASSERT_PRED(checkIsEqual(false, false));
JSONTEST_ASSERT_PRED(checkIsEqual(true, true));
}
JSONTEST_FIXTURE_LOCAL(ValueTest, compareArray) {
// array compare size then content
Json::Value emptyArray(Json::arrayValue);
Json::Value l1aArray;
l1aArray.append(0);
Json::Value l1bArray;
l1bArray.append(10);
Json::Value l2aArray;
l2aArray.append(0);
l2aArray.append(0);
Json::Value l2bArray;
l2bArray.append(0);
l2bArray.append(10);
JSONTEST_ASSERT_PRED(checkIsLess(emptyArray, l1aArray));
JSONTEST_ASSERT_PRED(checkIsLess(emptyArray, l2aArray));
JSONTEST_ASSERT_PRED(checkIsLess(l1aArray, l1bArray));
JSONTEST_ASSERT_PRED(checkIsLess(l1bArray, l2aArray));
JSONTEST_ASSERT_PRED(checkIsLess(l2aArray, l2bArray));
JSONTEST_ASSERT_PRED(checkIsEqual(emptyArray, Json::Value(emptyArray)));
JSONTEST_ASSERT_PRED(checkIsEqual(l1aArray, Json::Value(l1aArray)));
JSONTEST_ASSERT_PRED(checkIsEqual(l1bArray, Json::Value(l1bArray)));
JSONTEST_ASSERT_PRED(checkIsEqual(l2aArray, Json::Value(l2aArray)));
JSONTEST_ASSERT_PRED(checkIsEqual(l2bArray, Json::Value(l2bArray)));
}
JSONTEST_FIXTURE_LOCAL(ValueTest, compareObject) {
// object compare size then content
Json::Value emptyObject(Json::objectValue);
Json::Value l1aObject;
l1aObject["key1"] = 0;
Json::Value l1bObject;
l1bObject["key1"] = 10;
Json::Value l2aObject;
l2aObject["key1"] = 0;
l2aObject["key2"] = 0;
Json::Value l2bObject;
l2bObject["key1"] = 10;
l2bObject["key2"] = 0;
JSONTEST_ASSERT_PRED(checkIsLess(emptyObject, l1aObject));
JSONTEST_ASSERT_PRED(checkIsLess(l1aObject, l1bObject));
JSONTEST_ASSERT_PRED(checkIsLess(l1bObject, l2aObject));
JSONTEST_ASSERT_PRED(checkIsLess(l2aObject, l2bObject));
JSONTEST_ASSERT_PRED(checkIsEqual(emptyObject, Json::Value(emptyObject)));
JSONTEST_ASSERT_PRED(checkIsEqual(l1aObject, Json::Value(l1aObject)));
JSONTEST_ASSERT_PRED(checkIsEqual(l1bObject, Json::Value(l1bObject)));
JSONTEST_ASSERT_PRED(checkIsEqual(l2aObject, Json::Value(l2aObject)));
JSONTEST_ASSERT_PRED(checkIsEqual(l2bObject, Json::Value(l2bObject)));
{
Json::Value aObject;
aObject["a"] = 10;
Json::Value bObject;
bObject["b"] = 0;
Json::Value cObject;
cObject["c"] = 20;
cObject["f"] = 15;
Json::Value dObject;
dObject["d"] = -2;
dObject["e"] = 10;
JSONTEST_ASSERT_PRED(checkIsLess(aObject, bObject));
JSONTEST_ASSERT_PRED(checkIsLess(bObject, cObject));
JSONTEST_ASSERT_PRED(checkIsLess(cObject, dObject));
JSONTEST_ASSERT_PRED(checkIsEqual(aObject, Json::Value(aObject)));
JSONTEST_ASSERT_PRED(checkIsEqual(bObject, Json::Value(bObject)));
JSONTEST_ASSERT_PRED(checkIsEqual(cObject, Json::Value(cObject)));
JSONTEST_ASSERT_PRED(checkIsEqual(dObject, Json::Value(dObject)));
}
}
JSONTEST_FIXTURE_LOCAL(ValueTest, compareType) {
// object of different type are ordered according to their type
JSONTEST_ASSERT_PRED(checkIsLess(Json::Value(), Json::Value(1)));
JSONTEST_ASSERT_PRED(checkIsLess(Json::Value(1), Json::Value(1u)));
JSONTEST_ASSERT_PRED(checkIsLess(Json::Value(1u), Json::Value(1.0)));
JSONTEST_ASSERT_PRED(checkIsLess(Json::Value(1.0), Json::Value("a")));
JSONTEST_ASSERT_PRED(checkIsLess(Json::Value("a"), Json::Value(true)));
JSONTEST_ASSERT_PRED(
checkIsLess(Json::Value(true), Json::Value(Json::arrayValue)));
JSONTEST_ASSERT_PRED(checkIsLess(Json::Value(Json::arrayValue),
Json::Value(Json::objectValue)));
}
JSONTEST_FIXTURE_LOCAL(ValueTest, CopyObject) {
Json::Value arrayVal;
arrayVal.append("val1");
arrayVal.append("val2");
arrayVal.append("val3");
Json::Value stringVal("string value");
Json::Value copy1, copy2;
{
Json::Value arrayCopy, stringCopy;
arrayCopy.copy(arrayVal);
stringCopy.copy(stringVal);
JSONTEST_ASSERT_PRED(checkIsEqual(arrayCopy, arrayVal));
JSONTEST_ASSERT_PRED(checkIsEqual(stringCopy, stringVal));
arrayCopy.append("val4");
JSONTEST_ASSERT(arrayCopy.size() == 4);
arrayVal.append("new4");
arrayVal.append("new5");
JSONTEST_ASSERT(arrayVal.size() == 5);
JSONTEST_ASSERT(!(arrayCopy == arrayVal));
stringCopy = "another string";
JSONTEST_ASSERT(!(stringCopy == stringVal));
copy1.copy(arrayCopy);
copy2.copy(stringCopy);
}
JSONTEST_ASSERT(arrayVal.size() == 5);
JSONTEST_ASSERT(stringVal == "string value");
JSONTEST_ASSERT(copy1.size() == 4);
JSONTEST_ASSERT(copy2 == "another string");
copy1.copy(stringVal);
JSONTEST_ASSERT(copy1 == "string value");
copy2.copy(arrayVal);
JSONTEST_ASSERT(copy2.size() == 5);
{
Json::Value srcObject, objectCopy, otherObject;
srcObject["key0"] = 10;
objectCopy.copy(srcObject);
JSONTEST_ASSERT(srcObject["key0"] == 10);
JSONTEST_ASSERT(objectCopy["key0"] == 10);
JSONTEST_ASSERT(srcObject.getMemberNames().size() == 1);
JSONTEST_ASSERT(objectCopy.getMemberNames().size() == 1);
otherObject["key1"] = 15;
otherObject["key2"] = 16;
JSONTEST_ASSERT(otherObject.getMemberNames().size() == 2);
objectCopy.copy(otherObject);
JSONTEST_ASSERT(objectCopy["key1"] == 15);
JSONTEST_ASSERT(objectCopy["key2"] == 16);
JSONTEST_ASSERT(objectCopy.getMemberNames().size() == 2);
otherObject["key1"] = 20;
JSONTEST_ASSERT(objectCopy["key1"] == 15);
}
}
void ValueTest::checkIsLess(const Json::Value& x, const Json::Value& y) {
JSONTEST_ASSERT(x < y);
JSONTEST_ASSERT(y > x);
JSONTEST_ASSERT(x <= y);
JSONTEST_ASSERT(y >= x);
JSONTEST_ASSERT(!(x == y));
JSONTEST_ASSERT(!(y == x));
JSONTEST_ASSERT(!(x >= y));
JSONTEST_ASSERT(!(y <= x));
JSONTEST_ASSERT(!(x > y));
JSONTEST_ASSERT(!(y < x));
JSONTEST_ASSERT(x.compare(y) < 0);
JSONTEST_ASSERT(y.compare(x) >= 0);
}
void ValueTest::checkIsEqual(const Json::Value& x, const Json::Value& y) {
JSONTEST_ASSERT(x == y);
JSONTEST_ASSERT(y == x);
JSONTEST_ASSERT(x <= y);
JSONTEST_ASSERT(y <= x);
JSONTEST_ASSERT(x >= y);
JSONTEST_ASSERT(y >= x);
JSONTEST_ASSERT(!(x < y));
JSONTEST_ASSERT(!(y < x));
JSONTEST_ASSERT(!(x > y));
JSONTEST_ASSERT(!(y > x));
JSONTEST_ASSERT(x.compare(y) == 0);
JSONTEST_ASSERT(y.compare(x) == 0);
}
JSONTEST_FIXTURE_LOCAL(ValueTest, typeChecksThrowExceptions) {
#if JSON_USE_EXCEPTION
Json::Value intVal(1);
Json::Value strVal("Test");
Json::Value objVal(Json::objectValue);
Json::Value arrVal(Json::arrayValue);
JSONTEST_ASSERT_THROWS(intVal["test"]);
JSONTEST_ASSERT_THROWS(strVal["test"]);
JSONTEST_ASSERT_THROWS(arrVal["test"]);
JSONTEST_ASSERT_THROWS(intVal.removeMember("test"));
JSONTEST_ASSERT_THROWS(strVal.removeMember("test"));
JSONTEST_ASSERT_THROWS(arrVal.removeMember("test"));
JSONTEST_ASSERT_THROWS(intVal.getMemberNames());
JSONTEST_ASSERT_THROWS(strVal.getMemberNames());
JSONTEST_ASSERT_THROWS(arrVal.getMemberNames());
JSONTEST_ASSERT_THROWS(intVal[0]);
JSONTEST_ASSERT_THROWS(objVal[0]);
JSONTEST_ASSERT_THROWS(strVal[0]);
JSONTEST_ASSERT_THROWS(intVal.clear());
JSONTEST_ASSERT_THROWS(intVal.resize(1));
JSONTEST_ASSERT_THROWS(strVal.resize(1));
JSONTEST_ASSERT_THROWS(objVal.resize(1));
JSONTEST_ASSERT_THROWS(intVal.asCString());
JSONTEST_ASSERT_THROWS(objVal.asString());
JSONTEST_ASSERT_THROWS(arrVal.asString());
JSONTEST_ASSERT_THROWS(strVal.asInt());
JSONTEST_ASSERT_THROWS(objVal.asInt());
JSONTEST_ASSERT_THROWS(arrVal.asInt());
JSONTEST_ASSERT_THROWS(strVal.asUInt());
JSONTEST_ASSERT_THROWS(objVal.asUInt());
JSONTEST_ASSERT_THROWS(arrVal.asUInt());
JSONTEST_ASSERT_THROWS(strVal.asInt64());
JSONTEST_ASSERT_THROWS(objVal.asInt64());
JSONTEST_ASSERT_THROWS(arrVal.asInt64());
JSONTEST_ASSERT_THROWS(strVal.asUInt64());
JSONTEST_ASSERT_THROWS(objVal.asUInt64());
JSONTEST_ASSERT_THROWS(arrVal.asUInt64());
JSONTEST_ASSERT_THROWS(strVal.asDouble());
JSONTEST_ASSERT_THROWS(objVal.asDouble());
JSONTEST_ASSERT_THROWS(arrVal.asDouble());
JSONTEST_ASSERT_THROWS(strVal.asFloat());
JSONTEST_ASSERT_THROWS(objVal.asFloat());
JSONTEST_ASSERT_THROWS(arrVal.asFloat());
JSONTEST_ASSERT_THROWS(strVal.asBool());
JSONTEST_ASSERT_THROWS(objVal.asBool());
JSONTEST_ASSERT_THROWS(arrVal.asBool());
#endif
}
JSONTEST_FIXTURE_LOCAL(ValueTest, offsetAccessors) {
Json::Value x;
JSONTEST_ASSERT(x.getOffsetStart() == 0);
JSONTEST_ASSERT(x.getOffsetLimit() == 0);
x.setOffsetStart(10);
x.setOffsetLimit(20);
JSONTEST_ASSERT(x.getOffsetStart() == 10);
JSONTEST_ASSERT(x.getOffsetLimit() == 20);
Json::Value y(x);
JSONTEST_ASSERT(y.getOffsetStart() == 10);
JSONTEST_ASSERT(y.getOffsetLimit() == 20);
Json::Value z;
z.swap(y);
JSONTEST_ASSERT(z.getOffsetStart() == 10);
JSONTEST_ASSERT(z.getOffsetLimit() == 20);
JSONTEST_ASSERT(y.getOffsetStart() == 0);
JSONTEST_ASSERT(y.getOffsetLimit() == 0);
}
JSONTEST_FIXTURE_LOCAL(ValueTest, StaticString) {
char mutant[] = "hello";
Json::StaticString ss(mutant);
Json::String regular(mutant);
mutant[1] = 'a';
JSONTEST_ASSERT_STRING_EQUAL("hallo", ss.c_str());
JSONTEST_ASSERT_STRING_EQUAL("hello", regular.c_str());
{
Json::Value root;
root["top"] = ss;
JSONTEST_ASSERT_STRING_EQUAL("hallo", root["top"].asString());
mutant[1] = 'u';
JSONTEST_ASSERT_STRING_EQUAL("hullo", root["top"].asString());
}
{
Json::Value root;
root["top"] = regular;
JSONTEST_ASSERT_STRING_EQUAL("hello", root["top"].asString());
mutant[1] = 'u';
JSONTEST_ASSERT_STRING_EQUAL("hello", root["top"].asString());
}
}
JSONTEST_FIXTURE_LOCAL(ValueTest, WideString) {
// https://github.com/open-source-parsers/jsoncpp/issues/756
const std::string uni = u8"\u5f0f\uff0c\u8fdb"; // "式,进"
std::string styled;
{
Json::Value v;
v["abc"] = uni;
styled = v.toStyledString();
}
Json::Value root;
{
JSONCPP_STRING errs;
std::istringstream iss(styled);
bool ok = parseFromStream(Json::CharReaderBuilder(), iss, &root, &errs);
JSONTEST_ASSERT(ok);
if (!ok) {
std::cerr << "errs: " << errs << std::endl;
}
}
JSONTEST_ASSERT_STRING_EQUAL(root["abc"].asString(), uni);
}
JSONTEST_FIXTURE_LOCAL(ValueTest, CommentBefore) {
Json::Value val; // fill val
val.setComment(Json::String("// this comment should appear before"),
Json::commentBefore);
Json::StreamWriterBuilder wbuilder;
wbuilder.settings_["commentStyle"] = "All";
{
char const expected[] = "// this comment should appear before\nnull";
Json::String result = Json::writeString(wbuilder, val);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
Json::String res2 = val.toStyledString();
Json::String exp2 = "\n";
exp2 += expected;
exp2 += "\n";
JSONTEST_ASSERT_STRING_EQUAL(exp2, res2);
}
Json::Value other = "hello";
val.swapPayload(other);
{
char const expected[] = "// this comment should appear before\n\"hello\"";
Json::String result = Json::writeString(wbuilder, val);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
Json::String res2 = val.toStyledString();
Json::String exp2 = "\n";
exp2 += expected;
exp2 += "\n";
JSONTEST_ASSERT_STRING_EQUAL(exp2, res2);
JSONTEST_ASSERT_STRING_EQUAL("null\n", other.toStyledString());
}
val = "hello";
// val.setComment("// this comment should appear before",
// Json::CommentPlacement::commentBefore); Assignment over-writes comments.
{
char const expected[] = "\"hello\"";
Json::String result = Json::writeString(wbuilder, val);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
Json::String res2 = val.toStyledString();
Json::String exp2;
exp2 += expected;
exp2 += "\n";
JSONTEST_ASSERT_STRING_EQUAL(exp2, res2);
}
}
JSONTEST_FIXTURE_LOCAL(ValueTest, zeroes) {
char const cstr[] = "h\0i";
Json::String binary(cstr, sizeof(cstr)); // include trailing 0
JSONTEST_ASSERT_EQUAL(4U, binary.length());
Json::StreamWriterBuilder b;
{
Json::Value root;
root = binary;
JSONTEST_ASSERT_STRING_EQUAL(binary, root.asString());
}
{
char const top[] = "top";
Json::Value root;
root[top] = binary;
JSONTEST_ASSERT_STRING_EQUAL(binary, root[top].asString());
Json::Value removed;
bool did;
did = root.removeMember(top, top + sizeof(top) - 1U, &removed);
JSONTEST_ASSERT(did);
JSONTEST_ASSERT_STRING_EQUAL(binary, removed.asString());
did = root.removeMember(top, top + sizeof(top) - 1U, &removed);
JSONTEST_ASSERT(!did);
JSONTEST_ASSERT_STRING_EQUAL(binary, removed.asString()); // still
}
}
JSONTEST_FIXTURE_LOCAL(ValueTest, zeroesInKeys) {
char const cstr[] = "h\0i";
Json::String binary(cstr, sizeof(cstr)); // include trailing 0
JSONTEST_ASSERT_EQUAL(4U, binary.length());
{
Json::Value root;
root[binary] = "there";
JSONTEST_ASSERT_STRING_EQUAL("there", root[binary].asString());
JSONTEST_ASSERT(!root.isMember("h"));
JSONTEST_ASSERT(root.isMember(binary));
JSONTEST_ASSERT_STRING_EQUAL(
"there", root.get(binary, Json::Value::nullSingleton()).asString());
Json::Value removed;
bool did;
did = root.removeMember(binary.data(), binary.data() + binary.length(),
&removed);
JSONTEST_ASSERT(did);
JSONTEST_ASSERT_STRING_EQUAL("there", removed.asString());
did = root.removeMember(binary.data(), binary.data() + binary.length(),
&removed);
JSONTEST_ASSERT(!did);
JSONTEST_ASSERT_STRING_EQUAL("there", removed.asString()); // still
JSONTEST_ASSERT(!root.isMember(binary));
JSONTEST_ASSERT_STRING_EQUAL(
"", root.get(binary, Json::Value::nullSingleton()).asString());
}
}
JSONTEST_FIXTURE_LOCAL(ValueTest, specialFloats) {
Json::StreamWriterBuilder b;
b.settings_["useSpecialFloats"] = true;
Json::Value v = std::numeric_limits<double>::quiet_NaN();
Json::String expected = "NaN";
Json::String result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
v = std::numeric_limits<double>::infinity();
expected = "Infinity";
result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
v = -std::numeric_limits<double>::infinity();
expected = "-Infinity";
result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
}
JSONTEST_FIXTURE_LOCAL(ValueTest, precision) {
Json::StreamWriterBuilder b;
b.settings_["precision"] = 5;
Json::Value v = 100.0 / 3;
Json::String expected = "33.333";
Json::String result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
v = 0.25000000;
expected = "0.25";
result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
v = 0.2563456;
expected = "0.25635";
result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
b.settings_["precision"] = 1;
expected = "0.3";
result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
b.settings_["precision"] = 17;
v = 1234857476305.256345694873740545068;
expected = "1234857476305.2563";
result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
b.settings_["precision"] = 24;
v = 0.256345694873740545068;
expected = "0.25634569487374054";
result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
b.settings_["precision"] = 5;
b.settings_["precisionType"] = "decimal";
v = 0.256345694873740545068;
expected = "0.25635";
result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
b.settings_["precision"] = 1;
b.settings_["precisionType"] = "decimal";
v = 0.256345694873740545068;
expected = "0.3";
result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
b.settings_["precision"] = 0;
b.settings_["precisionType"] = "decimal";
v = 123.56345694873740545068;
expected = "124";
result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
b.settings_["precision"] = 1;
b.settings_["precisionType"] = "decimal";
v = 1230.001;
expected = "1230.0";
result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
b.settings_["precision"] = 0;
b.settings_["precisionType"] = "decimal";
v = 1230.001;
expected = "1230";
result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
b.settings_["precision"] = 0;
b.settings_["precisionType"] = "decimal";
v = 1231.5;
expected = "1232";
result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
b.settings_["precision"] = 10;
b.settings_["precisionType"] = "decimal";
v = 0.23300000;
expected = "0.233";
result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
}
JSONTEST_FIXTURE_LOCAL(ValueTest, searchValueByPath) {
Json::Value root, subroot;
root["property1"][0] = 0;
root["property1"][1] = 1;
subroot["object"] = "object";
root["property2"] = subroot;
const Json::Value defaultValue("error");
Json::FastWriter writer;
{
const Json::String expected("{"
"\"property1\":[0,1],"
"\"property2\":{\"object\":\"object\"}"
"}\n");
Json::String outcome = writer.write(root);
JSONTEST_ASSERT_STRING_EQUAL(expected, outcome);
// Array member exists.
const Json::Path path1(".property1.[%]", 1);
Json::Value result = path1.resolve(root);
JSONTEST_ASSERT_EQUAL(Json::Value(1), result);
result = path1.resolve(root, defaultValue);
JSONTEST_ASSERT_EQUAL(Json::Value(1), result);
// Array member does not exist.
const Json::Path path2(".property1.[2]");
result = path2.resolve(root);
JSONTEST_ASSERT_EQUAL(Json::nullValue, result);
result = path2.resolve(root, defaultValue);
JSONTEST_ASSERT_EQUAL(defaultValue, result);
// Access array path form error
const Json::Path path3(".property1.0");
result = path3.resolve(root);
JSONTEST_ASSERT_EQUAL(Json::nullValue, result);
result = path3.resolve(root, defaultValue);
JSONTEST_ASSERT_EQUAL(defaultValue, result);
// Object member exists.
const Json::Path path4(".property2.%", "object");
result = path4.resolve(root);
JSONTEST_ASSERT_EQUAL(Json::Value("object"), result);
result = path4.resolve(root, defaultValue);
JSONTEST_ASSERT_EQUAL(Json::Value("object"), result);
// Object member does not exist.
const Json::Path path5(".property2.hello");
result = path5.resolve(root);
JSONTEST_ASSERT_EQUAL(Json::nullValue, result);
result = path5.resolve(root, defaultValue);
JSONTEST_ASSERT_EQUAL(defaultValue, result);
// Access object path form error
const Json::Path path6(".property2.[0]");
result = path5.resolve(root);
JSONTEST_ASSERT_EQUAL(Json::nullValue, result);
result = path6.resolve(root, defaultValue);
JSONTEST_ASSERT_EQUAL(defaultValue, result);
// resolve will not change the value
outcome = writer.write(root);
JSONTEST_ASSERT_STRING_EQUAL(expected, outcome);
}
{
const Json::String expected("{"
"\"property1\":[0,1,null],"
"\"property2\":{"
"\"hello\":null,"
"\"object\":\"object\"}}\n");
Json::Path path1(".property1.[%]", 2);
Json::Value& value1 = path1.make(root);
JSONTEST_ASSERT_EQUAL(Json::nullValue, value1);
Json::Path path2(".property2.%", "hello");
Json::Value& value2 = path2.make(root);
JSONTEST_ASSERT_EQUAL(Json::nullValue, value2);
// make will change the value
const Json::String outcome = writer.write(root);
JSONTEST_ASSERT_STRING_EQUAL(expected, outcome);
}
}
struct FastWriterTest : JsonTest::TestCase {};
JSONTEST_FIXTURE_LOCAL(FastWriterTest, dropNullPlaceholders) {
Json::FastWriter writer;
Json::Value nullValue;
JSONTEST_ASSERT(writer.write(nullValue) == "null\n");
writer.dropNullPlaceholders();
JSONTEST_ASSERT(writer.write(nullValue) == "\n");
}
JSONTEST_FIXTURE_LOCAL(FastWriterTest, enableYAMLCompatibility) {
Json::FastWriter writer;
Json::Value root;
root["hello"] = "world";
JSONTEST_ASSERT(writer.write(root) == "{\"hello\":\"world\"}\n");
writer.enableYAMLCompatibility();
JSONTEST_ASSERT(writer.write(root) == "{\"hello\": \"world\"}\n");
}
JSONTEST_FIXTURE_LOCAL(FastWriterTest, omitEndingLineFeed) {
Json::FastWriter writer;
Json::Value nullValue;
JSONTEST_ASSERT(writer.write(nullValue) == "null\n");
writer.omitEndingLineFeed();
JSONTEST_ASSERT(writer.write(nullValue) == "null");
}
JSONTEST_FIXTURE_LOCAL(FastWriterTest, writeNumericValue) {
Json::FastWriter writer;
const Json::String expected("{"
"\"emptyValue\":null,"
"\"false\":false,"
"\"null\":\"null\","
"\"number\":-6200000000000000.0,"
"\"real\":1.256,"
"\"uintValue\":17"
"}\n");
Json::Value root;
root["emptyValue"] = Json::nullValue;
root["false"] = false;
root["null"] = "null";
root["number"] = -6.2e+15;
root["real"] = 1.256;
root["uintValue"] = Json::Value(17U);
const Json::String result = writer.write(root);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
}
JSONTEST_FIXTURE_LOCAL(FastWriterTest, writeArrays) {
Json::FastWriter writer;
const Json::String expected("{"
"\"property1\":[\"value1\",\"value2\"],"
"\"property2\":[]"
"}\n");
Json::Value root;
root["property1"][0] = "value1";
root["property1"][1] = "value2";
root["property2"] = Json::arrayValue;
const Json::String result = writer.write(root);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
}
JSONTEST_FIXTURE_LOCAL(FastWriterTest, writeNestedObjects) {
Json::FastWriter writer;
const Json::String expected("{"
"\"object1\":{"
"\"bool\":true,"
"\"nested\":123"
"},"
"\"object2\":{}"
"}\n");
Json::Value root, child;
child["nested"] = 123;
child["bool"] = true;
root["object1"] = child;
root["object2"] = Json::objectValue;
const Json::String result = writer.write(root);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
}
struct StyledWriterTest : JsonTest::TestCase {};
JSONTEST_FIXTURE_LOCAL(StyledWriterTest, writeNumericValue) {
Json::StyledWriter writer;
const Json::String expected("{\n"
" \"emptyValue\" : null,\n"
" \"false\" : false,\n"
" \"null\" : \"null\",\n"
" \"number\" : -6200000000000000.0,\n"
" \"real\" : 1.256,\n"
" \"uintValue\" : 17\n"
"}\n");
Json::Value root;
root["emptyValue"] = Json::nullValue;
root["false"] = false;
root["null"] = "null";
root["number"] = -6.2e+15;
root["real"] = 1.256;
root["uintValue"] = Json::Value(17U);
const Json::String result = writer.write(root);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
}
JSONTEST_FIXTURE_LOCAL(StyledWriterTest, writeArrays) {
Json::StyledWriter writer;
const Json::String expected("{\n"
" \"property1\" : [ \"value1\", \"value2\" ],\n"
" \"property2\" : []\n"
"}\n");
Json::Value root;
root["property1"][0] = "value1";
root["property1"][1] = "value2";
root["property2"] = Json::arrayValue;
const Json::String result = writer.write(root);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
}
JSONTEST_FIXTURE_LOCAL(StyledWriterTest, writeNestedObjects) {
Json::StyledWriter writer;
const Json::String expected("{\n"
" \"object1\" : {\n"
" \"bool\" : true,\n"
" \"nested\" : 123\n"
" },\n"
" \"object2\" : {}\n"
"}\n");
Json::Value root, child;
child["nested"] = 123;
child["bool"] = true;
root["object1"] = child;
root["object2"] = Json::objectValue;
const Json::String result = writer.write(root);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
}
JSONTEST_FIXTURE_LOCAL(StyledWriterTest, multiLineArray) {
Json::StyledWriter writer;
{
// Array member has more than 20 print effect rendering lines
const Json::String expected("[\n "
"0,\n 1,\n 2,\n "
"3,\n 4,\n 5,\n "
"6,\n 7,\n 8,\n "
"9,\n 10,\n 11,\n "
"12,\n 13,\n 14,\n "
"15,\n 16,\n 17,\n "
"18,\n 19,\n 20\n]\n");
Json::Value root;
for (Json::ArrayIndex i = 0; i < 21; i++)
root[i] = i;
const Json::String result = writer.write(root);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
}
{
// Array members do not exceed 21 print effects to render a single line
const Json::String expected("[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]\n");
Json::Value root;
for (Json::ArrayIndex i = 0; i < 10; i++)
root[i] = i;
const Json::String result = writer.write(root);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
}
}
JSONTEST_FIXTURE_LOCAL(StyledWriterTest, writeValueWithComment) {
Json::StyledWriter writer;
{
const Json::String expected("\n//commentBeforeValue\n\"hello\"\n");
Json::Value root = "hello";
root.setComment(Json::String("//commentBeforeValue"), Json::commentBefore);
const Json::String result = writer.write(root);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
}
{
const Json::String expected("\"hello\" //commentAfterValueOnSameLine\n");
Json::Value root = "hello";
root.setComment(Json::String("//commentAfterValueOnSameLine"),
Json::commentAfterOnSameLine);
const Json::String result = writer.write(root);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
}
{
const Json::String expected("\"hello\"\n//commentAfter\n\n");
Json::Value root = "hello";
root.setComment(Json::String("//commentAfter"), Json::commentAfter);
const Json::String result = writer.write(root);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
}
}
struct StyledStreamWriterTest : JsonTest::TestCase {};
JSONTEST_FIXTURE_LOCAL(StyledStreamWriterTest, writeNumericValue) {
Json::StyledStreamWriter writer;
const Json::String expected("{\n"
"\t\"emptyValue\" : null,\n"
"\t\"false\" : false,\n"
"\t\"null\" : \"null\",\n"
"\t\"number\" : -6200000000000000.0,\n"
"\t\"real\" : 1.256,\n"
"\t\"uintValue\" : 17\n"
"}\n");
Json::Value root;
root["emptyValue"] = Json::nullValue;
root["false"] = false;
root["null"] = "null";
root["number"] = -6.2e+15; // big float number
root["real"] = 1.256; // float number
root["uintValue"] = Json::Value(17U);
Json::OStringStream sout;
writer.write(sout, root);
const Json::String result = sout.str();
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
}
JSONTEST_FIXTURE_LOCAL(StyledStreamWriterTest, writeArrays) {
Json::StyledStreamWriter writer;
const Json::String expected("{\n"
"\t\"property1\" : [ \"value1\", \"value2\" ],\n"
"\t\"property2\" : []\n"
"}\n");
Json::Value root;
root["property1"][0] = "value1";
root["property1"][1] = "value2";
root["property2"] = Json::arrayValue;
Json::OStringStream sout;
writer.write(sout, root);
const Json::String result = sout.str();
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
}
JSONTEST_FIXTURE_LOCAL(StyledStreamWriterTest, writeNestedObjects) {
Json::StyledStreamWriter writer;
const Json::String expected("{\n"
"\t\"object1\" : \n"
"\t"
"{\n"
"\t\t\"bool\" : true,\n"
"\t\t\"nested\" : 123\n"
"\t},\n"
"\t\"object2\" : {}\n"
"}\n");
Json::Value root, child;
child["nested"] = 123;
child["bool"] = true;
root["object1"] = child;
root["object2"] = Json::objectValue;
Json::OStringStream sout;
writer.write(sout, root);
const Json::String result = sout.str();
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
}
JSONTEST_FIXTURE_LOCAL(StyledStreamWriterTest, multiLineArray) {
{
// Array member has more than 20 print effect rendering lines
const Json::String expected("[\n\t0,"
"\n\t1,"
"\n\t2,"
"\n\t3,"
"\n\t4,"
"\n\t5,"
"\n\t6,"
"\n\t7,"
"\n\t8,"
"\n\t9,"
"\n\t10,"
"\n\t11,"
"\n\t12,"
"\n\t13,"
"\n\t14,"
"\n\t15,"
"\n\t16,"
"\n\t17,"
"\n\t18,"
"\n\t19,"
"\n\t20\n]\n");
Json::StyledStreamWriter writer;
Json::Value root;
for (Json::ArrayIndex i = 0; i < 21; i++)
root[i] = i;
Json::OStringStream sout;
writer.write(sout,