text: // 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 "jsontest.h"
  #include <cmath>
  #include <cstring>
  #include <iomanip>
  #include <json/config.h>
  #include <json/json.h>
  #include <limits>
  #include <sstream>
  #include <string>
  
  // 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)
  
  struct ValueTest : JsonTest::TestCase {
    Json::Value null_;
    Json::Value emptyArray_;
    Json::Value emptyObject_;
    Json::Value integer_;
    Json::Value unsignedInteger_;
    Json::Value smallUnsignedInteger_;
    Json::Value real_;
    Json::Value float_;
    Json::Value array1_;
    Json::Value object1_;
    Json::Value emptyString_;
    Json::Value string1_;
    Json::Value string_;
    Json::Value true_;
    Json::Value false_;
  
    ValueTest()
        : emptyArray_(Json::arrayValue), emptyObject_(Json::objectValue),
          integer_(123456789), unsignedInteger_(34567890u),
          smallUnsignedInteger_(Json::Value::UInt(Json::Value::maxInt)),
          real_(1234.56789), float_(0.00390625f), emptyString_(""), string1_("a"),
          string_("sometext with space"), true_(true), false_(false) {
      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) {
    Json::String::size_type index = s.find_last_of("eE");
    if (index != Json::String::npos) {
      Json::String::size_type hasSign =
          (s[index + 1] == '+' || s[index + 1] == '-') ? 1 : 0;
      Json::String::size_type exponentStartIndex = index + 1 + hasSign;
      Json::String normalized = s.substr(0, exponentStartIndex);
      Json::String::size_type indexDigit =
          s.find_first_not_of('0', exponentStartIndex);
      Json::String exponent = "0";
      if (indexDigit != Json::String::npos) // There is an exponent different
                                            // from 0
      {
        exponent = s.substr(indexDigit);
      }
      return normalized + exponent;
    }
    return s;
  }
  
  JSONTEST_FIXTURE(ValueTest, checkNormalizeFloatingPointStr) {
    JSONTEST_ASSERT_STRING_EQUAL("0.0", normalizeFloatingPointStr("0.0"));
    JSONTEST_ASSERT_STRING_EQUAL("0e0", normalizeFloatingPointStr("0e0"));
    JSONTEST_ASSERT_STRING_EQUAL("1234.0", normalizeFloatingPointStr("1234.0"));
    JSONTEST_ASSERT_STRING_EQUAL("1234.0e0",
                                 normalizeFloatingPointStr("1234.0e0"));
    JSONTEST_ASSERT_STRING_EQUAL("1234.0e+0",
                                 normalizeFloatingPointStr("1234.0e+0"));
    JSONTEST_ASSERT_STRING_EQUAL("1234e-1", normalizeFloatingPointStr("1234e-1"));
    JSONTEST_ASSERT_STRING_EQUAL("1234e10", normalizeFloatingPointStr("1234e10"));
    JSONTEST_ASSERT_STRING_EQUAL("1234e10",
                                 normalizeFloatingPointStr("1234e010"));
    JSONTEST_ASSERT_STRING_EQUAL("1234e+10",
                                 normalizeFloatingPointStr("1234e+010"));
    JSONTEST_ASSERT_STRING_EQUAL("1234e-10",
                                 normalizeFloatingPointStr("1234e-010"));
    JSONTEST_ASSERT_STRING_EQUAL("1234e+100",
                                 normalizeFloatingPointStr("1234e+100"));
    JSONTEST_ASSERT_STRING_EQUAL("1234e-100",
                                 normalizeFloatingPointStr("1234e-100"));
    JSONTEST_ASSERT_STRING_EQUAL("1234e+1",
                                 normalizeFloatingPointStr("1234e+001"));
  }
  
  JSONTEST_FIXTURE(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_FIXTURE(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 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);
  }
  
  JSONTEST_FIXTURE(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(ValueTest, arrayIssue252) {
    int count = 5;
    Json::Value root;
    Json::Value item;
    root["array"] = Json::Value::nullRef;
    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(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::null, 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(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(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(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(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(ValueTest, compareNull) {
    JSONTEST_ASSERT_PRED(checkIsEqual(Json::Value(), Json::Value()));
  }
  
  JSONTEST_FIXTURE(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(ValueTest, compareUInt) {
    JSONTEST_ASSERT_PRED(checkIsLess(0u, 10u));
    JSONTEST_ASSERT_PRED(checkIsLess(0u, Json::Value::maxUInt));
    JSONTEST_ASSERT_PRED(checkIsEqual(10u, 10u));
  }
  
  JSONTEST_FIXTURE(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(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(ValueTest, compareBoolean) {
    JSONTEST_ASSERT_PRED(checkIsLess(false, true));
    JSONTEST_ASSERT_PRED(checkIsEqual(false, false));
    JSONTEST_ASSERT_PRED(checkIsEqual(true, true));
  }
  
  JSONTEST_FIXTURE(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, 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(l2bArray, Json::Value(l2bArray)));
  }
  
  JSONTEST_FIXTURE(ValueTest, compareObject) {
    // object compare size then content
    Json::Value emptyObject(Json::objectValue);
    Json::Value l1aObject;
    l1aObject["key1"] = 0;
    Json::Value l1bObject;
    l1aObject["key1"] = 10;
    Json::Value l2aObject;
    l2aObject["key1"] = 0;
    l2aObject["key2"] = 0;
    JSONTEST_ASSERT_PRED(checkIsLess(emptyObject, l1aObject));
    JSONTEST_ASSERT_PRED(checkIsLess(emptyObject, l2aObject));
    JSONTEST_ASSERT_PRED(checkIsLess(l1aObject, l2aObject));
    JSONTEST_ASSERT_PRED(checkIsEqual(emptyObject, Json::Value(emptyObject)));
    JSONTEST_ASSERT_PRED(checkIsEqual(l1aObject, Json::Value(l1aObject)));
    JSONTEST_ASSERT_PRED(checkIsEqual(l2aObject, Json::Value(l2aObject)));
  }
  
  JSONTEST_FIXTURE(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(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);
  }
  
  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(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(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(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(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(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(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::nullRef).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::nullRef).asString());
    }
  }
  
  JSONTEST_FIXTURE(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(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"] = 10;
    b.settings_["precisionType"] = "decimal";
    v = 0.23300000;
    expected = "0.233";
    result = Json::writeString(b, v);
    JSONTEST_ASSERT_STRING_EQUAL(expected, result);
  }
  
  struct WriterTest : JsonTest::TestCase {};
  
  JSONTEST_FIXTURE(WriterTest, dropNullPlaceholders) {
    Json::FastWriter writer;
    Json::Value nullValue;
    JSONTEST_ASSERT(writer.write(nullValue) == "null\n");
  
    writer.dropNullPlaceholders();
    JSONTEST_ASSERT(writer.write(nullValue) == "\n");
  }
  
  struct StreamWriterTest : JsonTest::TestCase {};
  
  JSONTEST_FIXTURE(StreamWriterTest, dropNullPlaceholders) {
    Json::StreamWriterBuilder b;
    Json::Value nullValue;
    b.settings_["dropNullPlaceholders"] = false;
    JSONTEST_ASSERT(Json::writeString(b, nullValue) == "null");
    b.settings_["dropNullPlaceholders"] = true;
    JSONTEST_ASSERT(Json::writeString(b, nullValue).empty());
  }
  
  JSONTEST_FIXTURE(StreamWriterTest, writeZeroes) {
    Json::String binary("hi", 3); // include trailing 0
    JSONTEST_ASSERT_EQUAL(3, binary.length());
    Json::String expected("\"hi\\u0000\""); // unicoded zero
    Json::StreamWriterBuilder b;
    {
      Json::Value root;
      root = binary;
      JSONTEST_ASSERT_STRING_EQUAL(binary, root.asString());
      Json::String out = Json::writeString(b, root);
      JSONTEST_ASSERT_EQUAL(expected.size(), out.size());
      JSONTEST_ASSERT_STRING_EQUAL(expected, out);
    }
    {
      Json::Value root;
      root["top"] = binary;
      JSONTEST_ASSERT_STRING_EQUAL(binary, root["top"].asString());
      Json::String out = Json::writeString(b, root["top"]);
      JSONTEST_ASSERT_STRING_EQUAL(expected, out);
    }
  }
  
  struct ReaderTest : JsonTest::TestCase {};
  
  JSONTEST_FIXTURE(ReaderTest, parseWithNoErrors) {
    Json::Reader reader;
    Json::Value root;
    bool ok = reader.parse("{ \"property\" : \"value\" }", root);
    JSONTEST_ASSERT(ok);
    JSONTEST_ASSERT(reader.getFormattedErrorMessages().empty());
    JSONTEST_ASSERT(reader.getStructuredErrors().empty());
  }
  
  JSONTEST_FIXTURE(ReaderTest, parseWithNoErrorsTestingOffsets) {
    Json::Reader reader;
    Json::Value root;
    bool ok = reader.parse("{ \"property\" : [\"value\", \"value2\"], \"obj\" : "
                           "{ \"nested\" : 123, \"bool\" : true}, \"null\" : "
                           "null, \"false\" : false }",
                           root);
    JSONTEST_ASSERT(ok);
    JSONTEST_ASSERT(reader.getFormattedErrorMessages().empty());
    JSONTEST_ASSERT(reader.getStructuredErrors().empty());
    JSONTEST_ASSERT(root["property"].getOffsetStart() == 15);
    JSONTEST_ASSERT(root["property"].getOffsetLimit() == 34);
    JSONTEST_ASSERT(root["property"][0].getOffsetStart() == 16);
    JSONTEST_ASSERT(root["property"][0].getOffsetLimit() == 23);
    JSONTEST_ASSERT(root["property"][1].getOffsetStart() == 25);
    JSONTEST_ASSERT(root["property"][1].getOffsetLimit() == 33);
    JSONTEST_ASSERT(root["obj"].getOffsetStart() == 44);
    JSONTEST_ASSERT(root["obj"].getOffsetLimit() == 76);
    JSONTEST_ASSERT(root["obj"]["nested"].getOffsetStart() == 57);
    JSONTEST_ASSERT(root["obj"]["nested"].getOffsetLimit() == 60);
    JSONTEST_ASSERT(root["obj"]["bool"].getOffsetStart() == 71);
    JSONTEST_ASSERT(root["obj"]["bool"].getOffsetLimit() == 75);
    JSONTEST_ASSERT(root["null"].getOffsetStart() == 87);
    JSONTEST_ASSERT(root["null"].getOffsetLimit() == 91);
    JSONTEST_ASSERT(root["false"].getOffsetStart() == 103);
    JSONTEST_ASSERT(root["false"].getOffsetLimit() == 108);
    JSONTEST_ASSERT(root.getOffsetStart() == 0);
    JSONTEST_ASSERT(root.getOffsetLimit() == 110);
  }
  
  JSONTEST_FIXTURE(ReaderTest, parseWithOneError) {
    Json::Reader reader;
    Json::Value root;
    bool ok = reader.parse("{ \"property\" :: \"value\" }", root);
    JSONTEST_ASSERT(!ok);
    JSONTEST_ASSERT(reader.getFormattedErrorMessages() ==
                    "* Line 1, Column 15\n  Syntax error: value, object or array "
                    "expected.\n");
    std::vector<Json::Reader::StructuredError> errors =
        reader.getStructuredErrors();
    JSONTEST_ASSERT(errors.size() == 1);
    JSONTEST_ASSERT(errors.at(0).offset_start == 14);
    JSONTEST_ASSERT(errors.at(0).offset_limit == 15);
    JSONTEST_ASSERT(errors.at(0).message ==
                    "Syntax error: value, object or array expected.");
  }
  
  JSONTEST_FIXTURE(ReaderTest, parseChineseWithOneError) {
    Json::Reader reader;
    Json::Value root;
    bool ok = reader.parse("{ \"pr佐藤erty\" :: \"value\" }", root);
    JSONTEST_ASSERT(!ok);
    JSONTEST_ASSERT(reader.getFormattedErrorMessages() ==
                    "* Line 1, Column 19\n  Syntax error: value, object or array "
                    "expected.\n");
    std::vector<Json::Reader::StructuredError> errors =
        reader.getStructuredErrors();
    JSONTEST_ASSERT(errors.size() == 1);
    JSONTEST_ASSERT(errors.at(0).offset_start == 18);
    JSONTEST_ASSERT(errors.at(0).offset_limit == 19);
    JSONTEST_ASSERT(errors.at(0).message ==
                    "Syntax error: value, object or array expected.");
  }
  
  JSONTEST_FIXTURE(ReaderTest, parseWithDetailError) {
    Json::Reader reader;
    Json::Value root;
    bool ok = reader.parse("{ \"property\" : \"v\\alue\" }", root);
    JSONTEST_ASSERT(!ok);
    JSONTEST_ASSERT(reader.getFormattedErrorMessages() ==
                    "* Line 1, Column 16\n  Bad escape sequence in string\nSee "
                    "Line 1, Column 20 for detail.\n");
    std::vector<Json::Reader::StructuredError> errors =
        reader.getStructuredErrors();
    JSONTEST_ASSERT(errors.size() == 1);
    JSONTEST_ASSERT(errors.at(0).offset_start == 15);
    JSONTEST_ASSERT(errors.at(0).offset_limit == 23);
    JSONTEST_ASSERT(errors.at(0).message == "Bad escape sequence in string");
  }
  
  struct CharReaderTest : JsonTest::TestCase {};
  
  JSONTEST_FIXTURE(CharReaderTest, parseWithNoErrors) {
    Json::CharReaderBuilder b;
    Json::CharReader* reader(b.newCharReader());
    Json::String errs;
    Json::Value root;
    char const doc[] = "{ \"property\" : \"value\" }";
    bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
    JSONTEST_ASSERT(ok);
    JSONTEST_ASSERT(errs.empty());
    delete reader;
  }
  
  JSONTEST_FIXTURE(CharReaderTest, parseWithNoErrorsTestingOffsets) {
    Json::CharReaderBuilder b;
    Json::CharReader* reader(b.newCharReader());
    Json::String errs;
    Json::Value root;
    char const doc[] = "{ \"property\" : [\"value\", \"value2\"], \"obj\" : "
                       "{ \"nested\" : 123, \"bool\" : true}, \"null\" : "
                       "null, \"false\" : false }";
    bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
    JSONTEST_ASSERT(ok);
    JSONTEST_ASSERT(errs.empty());
    delete reader;
  }
  
  JSONTEST_FIXTURE(CharReaderTest, parseWithOneError) {
    Json::CharReaderBuilder b;
    Json::CharReader* reader(b.newCharReader());
    Json::String errs;
    Json::Value root;
    char const doc[] = "{ \"property\" :: \"value\" }";
    bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
    JSONTEST_ASSERT(!ok);
    JSONTEST_ASSERT(errs ==
                    "* Line 1, Column 15\n  Syntax error: value, object or array "
                    "expected.\n");
    delete reader;
  }
  
  JSONTEST_FIXTURE(CharReaderTest, parseChineseWithOneError) {
    Json::CharReaderBuilder b;
    Json::CharReader* reader(b.newCharReader());
    Json::String errs;
    Json::Value root;
    char const doc[] = "{ \"pr佐藤erty\" :: \"value\" }";
    bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
    JSONTEST_ASSERT(!ok);
    JSONTEST_ASSERT(errs ==
                    "* Line 1, Column 19\n  Syntax error: value, object or array "
                    "expected.\n");
    delete reader;
  }
  
  JSONTEST_FIXTURE(CharReaderTest, parseWithDetailError) {
    Json::CharReaderBuilder b;
    Json::CharReader* reader(b.newCharReader());
    Json::String errs;
    Json::Value root;
    char const doc[] = "{ \"property\" : \"v\\alue\" }";
    bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
    JSONTEST_ASSERT(!ok);
    JSONTEST_ASSERT(errs ==
                    "* Line 1, Column 16\n  Bad escape sequence in string\nSee "
                    "Line 1, Column 20 for detail.\n");
    delete reader;
  }
  
  JSONTEST_FIXTURE(CharReaderTest, parseWithStackLimit) {
    Json::CharReaderBuilder b;
    Json::Value root;
    char const doc[] = "{ \"property\" : \"value\" }";
    {
      b.settings_["stackLimit"] = 2;
      Json::CharReader* reader(b.newCharReader());
      Json::String errs;
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT(errs.empty());
      JSONTEST_ASSERT_EQUAL("value", root["property"]);
      delete reader;
    }
    {
      b.settings_["stackLimit"] = 1;
      Json::CharReader* reader(b.newCharReader());
      Json::String errs;
      JSONTEST_ASSERT_THROWS(
          reader->parse(doc, doc + std::strlen(doc), &root, &errs));
      delete reader;
    }
  }
  
  struct CharReaderStrictModeTest : JsonTest::TestCase {};
  
  JSONTEST_FIXTURE(CharReaderStrictModeTest, dupKeys) {
    Json::CharReaderBuilder b;
    Json::Value root;
    char const doc[] =
        "{ \"property\" : \"value\", \"key\" : \"val1\", \"key\" : \"val2\" }";
    {
      b.strictMode(&b.settings_);
      Json::CharReader* reader(b.newCharReader());
      Json::String errs;
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(!ok);
      JSONTEST_ASSERT_STRING_EQUAL("* Line 1, Column 41\n"
                                   "  Duplicate key: 'key'\n",
                                   errs);
      JSONTEST_ASSERT_EQUAL("val1", root["key"]); // so far
      delete reader;
    }
  }
  struct CharReaderFailIfExtraTest : JsonTest::TestCase {};
  
  JSONTEST_FIXTURE(CharReaderFailIfExtraTest, issue164) {
    // This is interpreted as a string value followed by a colon.
    Json::CharReaderBuilder b;
    Json::Value root;
    char const doc[] = " \"property\" : \"value\" }";
    {
      b.settings_["failIfExtra"] = false;
      Json::CharReader* reader(b.newCharReader());
      Json::String errs;
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT(errs.empty());
      JSONTEST_ASSERT_EQUAL("property", root);
      delete reader;
    }
    {
      b.settings_["failIfExtra"] = true;
      Json::CharReader* reader(b.newCharReader());
      Json::String errs;
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(!ok);
      JSONTEST_ASSERT_STRING_EQUAL(errs,
                                   "* Line 1, Column 13\n"
                                   "  Extra non-whitespace after JSON value.\n");
      JSONTEST_ASSERT_EQUAL("property", root);
      delete reader;
    }
    {
      b.settings_["failIfExtra"] = false;
      b.strictMode(&b.settings_);
      Json::CharReader* reader(b.newCharReader());
      Json::String errs;
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(!ok);
      JSONTEST_ASSERT_STRING_EQUAL(errs,
                                   "* Line 1, Column 13\n"
                                   "  Extra non-whitespace after JSON value.\n");
      JSONTEST_ASSERT_EQUAL("property", root);
      delete reader;
    }
  }
  JSONTEST_FIXTURE(CharReaderFailIfExtraTest, issue107) {
    // This is interpreted as an int value followed by a colon.
    Json::CharReaderBuilder b;
    Json::Value root;
    char const doc[] = "1:2:3";
    b.settings_["failIfExtra"] = true;
    Json::CharReader* reader(b.newCharReader());
    Json::String errs;
    bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
    JSONTEST_ASSERT(!ok);
    JSONTEST_ASSERT_STRING_EQUAL("* Line 1, Column 2\n"
                                 "  Extra non-whitespace after JSON value.\n",
                                 errs);
    JSONTEST_ASSERT_EQUAL(1, root.asInt());
    delete reader;
  }
  JSONTEST_FIXTURE(CharReaderFailIfExtraTest, commentAfterObject) {
    Json::CharReaderBuilder b;
    Json::Value root;
    {
      char const doc[] = "{ \"property\" : \"value\" } //trailing\n//comment\n";
      b.settings_["failIfExtra"] = true;
      Json::CharReader* reader(b.newCharReader());
      Json::String errs;
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT_STRING_EQUAL("", errs);
      JSONTEST_ASSERT_EQUAL("value", root["property"]);
      delete reader;
    }
  }
  JSONTEST_FIXTURE(CharReaderFailIfExtraTest, commentAfterArray) {
    Json::CharReaderBuilder b;
    Json::Value root;
    char const doc[] = "[ \"property\" , \"value\" ] //trailing\n//comment\n";
    b.settings_["failIfExtra"] = true;
    Json::CharReader* reader(b.newCharReader());
    Json::String errs;
    bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
    JSONTEST_ASSERT(ok);
    JSONTEST_ASSERT_STRING_EQUAL("", errs);
    JSONTEST_ASSERT_EQUAL("value", root[1u]);
    delete reader;
  }
  JSONTEST_FIXTURE(CharReaderFailIfExtraTest, commentAfterBool) {
    Json::CharReaderBuilder b;
    Json::Value root;
    char const doc[] = " true /*trailing\ncomment*/";
    b.settings_["failIfExtra"] = true;
    Json::CharReader* reader(b.newCharReader());
    Json::String errs;
    bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
    JSONTEST_ASSERT(ok);
    JSONTEST_ASSERT_STRING_EQUAL("", errs);
    JSONTEST_ASSERT_EQUAL(true, root.asBool());
    delete reader;
  }
  struct CharReaderAllowDropNullTest : JsonTest::TestCase {};
  
  JSONTEST_FIXTURE(CharReaderAllowDropNullTest, issue178) {
    Json::CharReaderBuilder b;
    b.settings_["allowDroppedNullPlaceholders"] = true;
    Json::Value root;
    Json::String errs;
    Json::CharReader* reader(b.newCharReader());
    {
      char const doc[] = "{\"a\":,\"b\":true}";
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT_STRING_EQUAL("", errs);
      JSONTEST_ASSERT_EQUAL(2u, root.size());
      JSONTEST_ASSERT_EQUAL(Json::nullValue, root.get("a", true));
    }
    {
      char const doc[] = "{\"a\":}";
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT_STRING_EQUAL("", errs);
      JSONTEST_ASSERT_EQUAL(1u, root.size());
      JSONTEST_ASSERT_EQUAL(Json::nullValue, root.get("a", true));
    }
    {
      char const doc[] = "[]";
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT(errs.empty());
      JSONTEST_ASSERT_EQUAL(0u, root.size());
      JSONTEST_ASSERT_EQUAL(Json::arrayValue, root);
    }
    {
      char const doc[] = "[null]";
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT(errs.empty());
      JSONTEST_ASSERT_EQUAL(1u, root.size());
    }
    {
      char const doc[] = "[,]";
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT_STRING_EQUAL("", errs);
      JSONTEST_ASSERT_EQUAL(2u, root.size());
    }
    {
      char const doc[] = "[,,,]";
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT_STRING_EQUAL("", errs);
      JSONTEST_ASSERT_EQUAL(4u, root.size());
    }
    {
      char const doc[] = "[null,]";
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT_STRING_EQUAL("", errs);
      JSONTEST_ASSERT_EQUAL(2u, root.size());
    }
    {
      char const doc[] = "[,null]";
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT(errs.empty());
      JSONTEST_ASSERT_EQUAL(2u, root.size());
    }
    {
      char const doc[] = "[,,]";
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT_STRING_EQUAL("", errs);
      JSONTEST_ASSERT_EQUAL(3u, root.size());
    }
    {
      char const doc[] = "[null,,]";
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT_STRING_EQUAL("", errs);
      JSONTEST_ASSERT_EQUAL(3u, root.size());
    }
    {
      char const doc[] = "[,null,]";
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT_STRING_EQUAL("", errs);
      JSONTEST_ASSERT_EQUAL(3u, root.size());
    }
    {
      char const doc[] = "[,,null]";
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT(errs.empty());
      JSONTEST_ASSERT_EQUAL(3u, root.size());
    }
    {
      char const doc[] = "[[],,,]";
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT_STRING_EQUAL("", errs);
      JSONTEST_ASSERT_EQUAL(4u, root.size());
      JSONTEST_ASSERT_EQUAL(Json::arrayValue, root[0u]);
    }
    {
      char const doc[] = "[,[],,]";
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT_STRING_EQUAL("", errs);
      JSONTEST_ASSERT_EQUAL(4u, root.size());
      JSONTEST_ASSERT_EQUAL(Json::arrayValue, root[1u]);
    }
    {
      char const doc[] = "[,,,[]]";
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT(errs.empty());
      JSONTEST_ASSERT_EQUAL(4u, root.size());
      JSONTEST_ASSERT_EQUAL(Json::arrayValue, root[3u]);
    }
    delete reader;
  }
  
  struct CharReaderAllowSingleQuotesTest : JsonTest::TestCase {};
  
  JSONTEST_FIXTURE(CharReaderAllowSingleQuotesTest, issue182) {
    Json::CharReaderBuilder b;
    b.settings_["allowSingleQuotes"] = true;
    Json::Value root;
    Json::String errs;
    Json::CharReader* reader(b.newCharReader());
    {
      char const doc[] = "{'a':true,\"b\":true}";
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT_STRING_EQUAL("", errs);
      JSONTEST_ASSERT_EQUAL(2u, root.size());
      JSONTEST_ASSERT_EQUAL(true, root.get("a", false));
      JSONTEST_ASSERT_EQUAL(true, root.get("b", false));
    }
    {
      char const doc[] = "{'a': 'x', \"b\":'y'}";
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT_STRING_EQUAL("", errs);
      JSONTEST_ASSERT_EQUAL(2u, root.size());
      JSONTEST_ASSERT_STRING_EQUAL("x", root["a"].asString());
      JSONTEST_ASSERT_STRING_EQUAL("y", root["b"].asString());
    }
    delete reader;
  }
  
  struct CharReaderAllowZeroesTest : JsonTest::TestCase {};
  
  JSONTEST_FIXTURE(CharReaderAllowZeroesTest, issue176) {
    Json::CharReaderBuilder b;
    b.settings_["allowSingleQuotes"] = true;
    Json::Value root;
    Json::String errs;
    Json::CharReader* reader(b.newCharReader());
    {
      char const doc[] = "{'a':true,\"b\":true}";
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT_STRING_EQUAL("", errs);
      JSONTEST_ASSERT_EQUAL(2u, root.size());
      JSONTEST_ASSERT_EQUAL(true, root.get("a", false));
      JSONTEST_ASSERT_EQUAL(true, root.get("b", false));
    }
    {
      char const doc[] = "{'a': 'x', \"b\":'y'}";
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT_STRING_EQUAL("", errs);
      JSONTEST_ASSERT_EQUAL(2u, root.size());
      JSONTEST_ASSERT_STRING_EQUAL("x", root["a"].asString());
      JSONTEST_ASSERT_STRING_EQUAL("y", root["b"].asString());
    }
    delete reader;
  }
  
  struct CharReaderAllowSpecialFloatsTest : JsonTest::TestCase {};
  
  JSONTEST_FIXTURE(CharReaderAllowSpecialFloatsTest, issue209) {
    Json::CharReaderBuilder b;
    b.settings_["allowSpecialFloats"] = true;
    Json::Value root;
    Json::String errs;
    Json::CharReader* reader(b.newCharReader());
    {
      char const doc[] = "{\"a\":NaN,\"b\":Infinity,\"c\":-Infinity}";
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT_STRING_EQUAL("", errs);
      JSONTEST_ASSERT_EQUAL(3u, root.size());
      double n = root["a"].asDouble();
      JSONTEST_ASSERT(std::isnan(n));
      JSONTEST_ASSERT_EQUAL(std::numeric_limits<double>::infinity(),
                            root.get("b", 0.0));
      JSONTEST_ASSERT_EQUAL(-std::numeric_limits<double>::infinity(),
                            root.get("c", 0.0));
    }
  
    struct TestData {
      int line;
      bool ok;
      Json::String in;
    };
    const TestData test_data[] = {
        {__LINE__, true, "{\"a\":9}"},          //
        {__LINE__, false, "{\"a\":0Infinity}"}, //
        {__LINE__, false, "{\"a\":1Infinity}"}, //
        {__LINE__, false, "{\"a\":9Infinity}"}, //
        {__LINE__, false, "{\"a\":0nfinity}"},  //
        {__LINE__, false, "{\"a\":1nfinity}"},  //
        {__LINE__, false, "{\"a\":9nfinity}"},  //
        {__LINE__, false, "{\"a\":nfinity}"},   //
        {__LINE__, false, "{\"a\":.nfinity}"},  //
        {__LINE__, false, "{\"a\":9nfinity}"},  //
        {__LINE__, false, "{\"a\":-nfinity}"},  //
        {__LINE__, true, "{\"a\":Infinity}"},   //
        {__LINE__, false, "{\"a\":.Infinity}"}, //
        {__LINE__, false, "{\"a\":_Infinity}"}, //
        {__LINE__, false, "{\"a\":_nfinity}"},  //
        {__LINE__, true, "{\"a\":-Infinity}"}   //
    };
    for (const auto& td : test_data) {
      bool ok = reader->parse(&*td.in.begin(), &*td.in.begin() + td.in.size(),
                              &root, &errs);
      JSONTEST_ASSERT(td.ok == ok) << "line:" << td.line << "\n"
                                   << "  expected: {"
                                   << "ok:" << td.ok << ", in:\'" << td.in << "\'"
                                   << "}\n"
                                   << "  actual: {"
                                   << "ok:" << ok << "}\n";
    }
  
    {
      char const doc[] = "{\"posInf\": Infinity, \"NegInf\": -Infinity}";
      bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
      JSONTEST_ASSERT(ok);
      JSONTEST_ASSERT_STRING_EQUAL("", errs);
      JSONTEST_ASSERT_EQUAL(2u, root.size());
      JSONTEST_ASSERT_EQUAL(std::numeric_limits<double>::infinity(),
                            root["posInf"].asDouble());
      JSONTEST_ASSERT_EQUAL(-std::numeric_limits<double>::infinity(),
                            root["NegInf"].asDouble());
    }
    delete reader;
  }
  
  struct BuilderTest : JsonTest::TestCase {};
  
  JSONTEST_FIXTURE(BuilderTest, settings) {
    {
      Json::Value errs;
      Json::CharReaderBuilder rb;
      JSONTEST_ASSERT_EQUAL(false, rb.settings_.isMember("foo"));
      JSONTEST_ASSERT_EQUAL(true, rb.validate(&errs));
      rb["foo"] = "bar";
      JSONTEST_ASSERT_EQUAL(true, rb.settings_.isMember("foo"));
      JSONTEST_ASSERT_EQUAL(false, rb.validate(&errs));
    }
    {
      Json::Value errs;
      Json::StreamWriterBuilder wb;
      JSONTEST_ASSERT_EQUAL(false, wb.settings_.isMember("foo"));
      JSONTEST_ASSERT_EQUAL(true, wb.validate(&errs));
      wb["foo"] = "bar";
      JSONTEST_ASSERT_EQUAL(true, wb.settings_.isMember("foo"));
      JSONTEST_ASSERT_EQUAL(false, wb.validate(&errs));
    }
  }
  
  struct IteratorTest : JsonTest::TestCase {};
  
  JSONTEST_FIXTURE(IteratorTest, distance) {
    Json::Value json;
    json["k1"] = "a";
    json["k2"] = "b";
    int dist = 0;
    Json::String str;
    for (Json::ValueIterator it = json.begin(); it != json.end(); ++it) {
      dist = it - json.begin();
      str = it->asString().c_str();
    }
    JSONTEST_ASSERT_EQUAL(1, dist);
    JSONTEST_ASSERT_STRING_EQUAL("b", str);
  }
  
  JSONTEST_FIXTURE(IteratorTest, names) {
    Json::Value json;
    json["k1"] = "a";
    json["k2"] = "b";
    Json::ValueIterator it = json.begin();
    JSONTEST_ASSERT(it != json.end());
    JSONTEST_ASSERT_EQUAL(Json::Value("k1"), it.key());
    JSONTEST_ASSERT_STRING_EQUAL("k1", it.name());
    JSONTEST_ASSERT_EQUAL(-1, it.index());
    ++it;
    JSONTEST_ASSERT(it != json.end());
    JSONTEST_ASSERT_EQUAL(Json::Value("k2"), it.key());
    JSONTEST_ASSERT_STRING_EQUAL("k2", it.name());
    JSONTEST_ASSERT_EQUAL(-1, it.index());
    ++it;
    JSONTEST_ASSERT(it == json.end());
  }
  
  JSONTEST_FIXTURE(IteratorTest, indexes) {
    Json::Value json;
    json[0] = "a";
    json[1] = "b";
    Json::ValueIterator it = json.begin();
    JSONTEST_ASSERT(it != json.end());
    JSONTEST_ASSERT_EQUAL(Json::Value(Json::ArrayIndex(0)), it.key());
    JSONTEST_ASSERT_STRING_EQUAL("", it.name());
    JSONTEST_ASSERT_EQUAL(0, it.index());
    ++it;
    JSONTEST_ASSERT(it != json.end());
    JSONTEST_ASSERT_EQUAL(Json::Value(Json::ArrayIndex(1)), it.key());
    JSONTEST_ASSERT_STRING_EQUAL("", it.name());
    JSONTEST_ASSERT_EQUAL(1, it.index());
    ++it;
    JSONTEST_ASSERT(it == json.end());
  }
  
  JSONTEST_FIXTURE(IteratorTest, const) {
    Json::Value const v;
    JSONTEST_ASSERT_THROWS(
        Json::Value::iterator it(v.begin()) // Compile, but throw.
    );
  
    Json::Value value;
  
    for (int i = 9; i < 12; ++i) {
      Json::OStringStream out;
      out << std::setw(2) << i;
      Json::String str = out.str();
      value[str] = str;
    }
  
    Json::OStringStream out;
    // in old code, this will get a compile error
    Json::Value::const_iterator iter = value.begin();
    for (; iter != value.end(); ++iter) {
      out << *iter << ',';
    }
    Json::String expected = "\" 9\",\"10\",\"11\",";
    JSONTEST_ASSERT_STRING_EQUAL(expected, out.str());
  }
  
  struct RValueTest : JsonTest::TestCase {};
  
  JSONTEST_FIXTURE(RValueTest, moveConstruction) {
    Json::Value json;
    json["key"] = "value";
    Json::Value moved = std::move(json);
    JSONTEST_ASSERT(moved != json); // Possibly not nullValue; definitely not
                                    // equal.
    JSONTEST_ASSERT_EQUAL(Json::objectValue, moved.type());
    JSONTEST_ASSERT_EQUAL(Json::stringValue, moved["key"].type());
  }
  
  int main(int argc, const char* argv[]) {
    JsonTest::Runner runner;
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, checkNormalizeFloatingPointStr);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, memberCount);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, objects);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, arrays);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, arrayIssue252);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, null);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, strings);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, bools);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, integers);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, nonIntegers);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareNull);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareInt);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareUInt);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareDouble);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareString);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareBoolean);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareArray);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareObject);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareType);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, CopyObject);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, offsetAccessors);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, typeChecksThrowExceptions);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, StaticString);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, CommentBefore);
    // JSONTEST_REGISTER_FIXTURE(runner, ValueTest, nulls);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, zeroes);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, zeroesInKeys);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, specialFloats);
    JSONTEST_REGISTER_FIXTURE(runner, ValueTest, precision);
  
    JSONTEST_REGISTER_FIXTURE(runner, WriterTest, dropNullPlaceholders);
    JSONTEST_REGISTER_FIXTURE(runner, StreamWriterTest, dropNullPlaceholders);
    JSONTEST_REGISTER_FIXTURE(runner, StreamWriterTest, writeZeroes);
  
    JSONTEST_REGISTER_FIXTURE(runner, ReaderTest, parseWithNoErrors);
    JSONTEST_REGISTER_FIXTURE(runner, ReaderTest,
                              parseWithNoErrorsTestingOffsets);
    JSONTEST_REGISTER_FIXTURE(runner, ReaderTest, parseWithOneError);
    JSONTEST_REGISTER_FIXTURE(runner, ReaderTest, parseChineseWithOneError);
    JSONTEST_REGISTER_FIXTURE(runner, ReaderTest, parseWithDetailError);
  
    JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithNoErrors);
    JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest,
                              parseWithNoErrorsTestingOffsets);
    JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithOneError);
    JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseChineseWithOneError);
    JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithDetailError);
    JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithStackLimit);
  
    JSONTEST_REGISTER_FIXTURE(runner, CharReaderStrictModeTest, dupKeys);
  
    JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, issue164);
    JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, issue107);
    JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest,
                              commentAfterObject);
    JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest,
                              commentAfterArray);
    JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest,
                              commentAfterBool);
  
    JSONTEST_REGISTER_FIXTURE(runner, CharReaderAllowDropNullTest, issue178);
  
    JSONTEST_REGISTER_FIXTURE(runner, CharReaderAllowSingleQuotesTest, issue182);
  
    JSONTEST_REGISTER_FIXTURE(runner, CharReaderAllowZeroesTest, issue176);
  
    JSONTEST_REGISTER_FIXTURE(runner, CharReaderAllowSpecialFloatsTest, issue209);
  
    JSONTEST_REGISTER_FIXTURE(runner, BuilderTest, settings);
  
    JSONTEST_REGISTER_FIXTURE(runner, IteratorTest, distance);
    JSONTEST_REGISTER_FIXTURE(runner, IteratorTest, names);
    JSONTEST_REGISTER_FIXTURE(runner, IteratorTest, indexes);
    JSONTEST_REGISTER_FIXTURE(runner, IteratorTest, const);
  
    JSONTEST_REGISTER_FIXTURE(runner, RValueTest, moveConstruction);
  
    return runner.runCommandLine(argc, argv);
  }
  
  #if defined(__GNUC__)
  #pragma GCC diagnostic pop
  #endif
  