diff --git a/.travis.yml b/.travis.yml index 7ac33241a97..b45d7198005 100644 --- a/.travis.yml +++ b/.travis.yml @@ -228,6 +228,7 @@ matrix: - bash - ninja - cmake + - wget - openssl@1.1 update: true install: diff --git a/src/ripple/json/impl/json_value.cpp b/src/ripple/json/impl/json_value.cpp index 10ff20e30c4..677ee8e3433 100644 --- a/src/ripple/json/impl/json_value.cpp +++ b/src/ripple/json/impl/json_value.cpp @@ -122,21 +122,6 @@ Value::CZString::~CZString () valueAllocator ()->releaseMemberName ( const_cast ( cstr_ ) ); } -void -Value::CZString::swap ( CZString& other ) noexcept -{ - std::swap ( cstr_, other.cstr_ ); - std::swap ( index_, other.index_ ); -} - -Value::CZString& -Value::CZString::operator = ( const CZString& other ) -{ - CZString temp ( other ); - swap ( temp ); - return *this; -} - bool Value::CZString::operator< ( const CZString& other ) const { @@ -250,24 +235,12 @@ Value::Value ( const char* value ) value_.string_ = valueAllocator ()->duplicateStringValue ( value ); } - -Value::Value ( const char* beginValue, - const char* endValue ) - : type_ ( stringValue ) - , allocated_ ( true ) -{ - value_.string_ = valueAllocator ()->duplicateStringValue ( beginValue, - UInt (endValue - beginValue) ); -} - - Value::Value ( std::string const& value ) : type_ ( stringValue ) , allocated_ ( true ) { value_.string_ = valueAllocator ()->duplicateStringValue ( value.c_str (), (unsigned int)value.length () ); - } Value::Value ( const StaticString& value ) @@ -562,7 +535,10 @@ Value::asInt () const return value_.bool_ ? 1 : 0; case stringValue: - return beast::lexicalCastThrow (value_.string_); + { + char const* const str {value_.string_ ? value_.string_ : ""}; + return beast::lexicalCastThrow (str); + } case arrayValue: case objectValue: @@ -598,7 +574,10 @@ Value::asUInt () const return value_.bool_ ? 1 : 0; case stringValue: - return beast::lexicalCastThrow (value_.string_); + { + char const* const str {value_.string_ ? value_.string_ : ""}; + return beast::lexicalCastThrow (str); + } case arrayValue: case objectValue: @@ -802,30 +781,6 @@ Value::clear () } } -void -Value::resize ( UInt newSize ) -{ - JSON_ASSERT ( type_ == nullValue || type_ == arrayValue ); - - if ( type_ == nullValue ) - *this = Value ( arrayValue ); - - UInt oldSize = size (); - - if ( newSize == 0 ) - clear (); - else if ( newSize > oldSize ) - (*this)[ newSize - 1 ]; - else - { - for ( UInt index = newSize; index < oldSize; ++index ) - value_.map_->erase ( index ); - - assert ( size () == newSize ); - } -} - - Value& Value::operator[] ( UInt index ) { @@ -954,6 +909,12 @@ Value::append ( const Value& value ) return (*this)[size ()] = value; } +Value& +Value::append ( Value&& value ) +{ + return (*this)[size ()] = std::move(value); +} + Value Value::get ( const char* key, diff --git a/src/ripple/json/json_value.h b/src/ripple/json/json_value.h index ee1fae0e5cc..6550fa03eec 100644 --- a/src/ripple/json/json_value.h +++ b/src/ripple/json/json_value.h @@ -46,17 +46,9 @@ enum ValueType objectValue ///< object value (collection of name/value pairs). }; -enum CommentPlacement -{ - commentBefore = 0, ///< a comment placed on the line before a value - commentAfterOnSameLine, ///< a comment just after a value on the same line - commentAfter, ///< a comment on the line after a value (only make sense for root value) - numberOfCommentPlacement -}; - /** \brief Lightweight wrapper to tag static string. * - * Value constructor and objectValue member assignement takes advantage of the + * Value constructor and objectValue member assignment takes advantage of the * StaticString and avoid the cost of string duplication when storing the * string or the member name. * @@ -92,8 +84,6 @@ class StaticString inline bool operator== (StaticString x, StaticString y) { - // TODO(tom): could I use x != y here because StaticStrings are supposed to - // be unique? return strcmp (x.c_str(), y.c_str()) == 0; } @@ -180,14 +170,13 @@ class Value CZString ( const char* cstr, DuplicationPolicy allocate ); CZString ( const CZString& other ); ~CZString (); - CZString& operator = ( const CZString& other ); + CZString& operator = ( const CZString& other ) = delete; bool operator< ( const CZString& other ) const; bool operator== ( const CZString& other ) const; int index () const; const char* c_str () const; bool isStaticString () const; private: - void swap ( CZString& other ) noexcept; const char* cstr_; int index_; }; @@ -216,7 +205,6 @@ class Value Value ( UInt value ); Value ( double value ); Value ( const char* value ); - Value ( const char* beginValue, const char* endValue ); /** \brief Constructs a value from a static string. * Like other value string constructor but do not duplicate the string for @@ -239,8 +227,6 @@ class Value Value ( Value&& other ) noexcept; /// Swap values. - /// \note Currently, comments are intentionally not swapped, for - /// both logic and efficiency. void swap ( Value& other ) noexcept; ValueType type () const; @@ -284,13 +270,6 @@ class Value /// \post type() is unchanged void clear (); - /// Resize the array to size elements. - /// New elements are initialized to null. - /// May only be called on nullValue or arrayValue. - /// \pre type() is arrayValue or nullValue - /// \post type() is arrayValue - void resize ( UInt size ); - /// Access an array element (zero based index ). /// If the array contains less than index element, then null value are inserted /// in the array so that its size is index+1. @@ -311,6 +290,7 @@ class Value /// /// Equivalent to jsonvalue[jsonvalue.size()] = value; Value& append ( const Value& value ); + Value& append ( Value&& value ); /// Access an object value by name, create a null member if it does not exist. Value& operator[] ( const char* key ); @@ -362,10 +342,6 @@ class Value /// \post if type() was nullValue, it remains nullValue Members getMemberNames () const; - bool hasComment ( CommentPlacement placement ) const; - /// Include delimiters and embedded newlines. - std::string getComment ( CommentPlacement placement ) const; - std::string toStyledString () const; const_iterator begin () const; @@ -468,11 +444,6 @@ class ValueIteratorBase return !isEqual ( other ); } - difference_type operator - ( const SelfType& other ) const - { - return computeDistance ( other ); - } - /// Return either the index or the member name of the referenced value as a Value. Value key () const; diff --git a/src/ripple/json/json_writer.h b/src/ripple/json/json_writer.h index c2009830de3..c32a0fcb423 100644 --- a/src/ripple/json/json_writer.h +++ b/src/ripple/json/json_writer.h @@ -75,9 +75,7 @@ class FastWriter : public WriterBase * - otherwise, it the values do not fit on one line, or the array contains * object or non empty array, then print one value per line. * - * If the Value have comments then they are outputed according to their #CommentPlacement. - * - * \sa Reader, Value, Value::setComment() + * \sa Reader, Value */ class StyledWriter: public WriterBase { @@ -127,10 +125,8 @@ class StyledWriter: public WriterBase * - otherwise, it the values do not fit on one line, or the array contains * object or non empty array, then print one value per line. * - * If the Value have comments then they are outputed according to their #CommentPlacement. - * * \param indentation Each level will be indented by this amount extra. - * \sa Reader, Value, Value::setComment() + * \sa Reader, Value */ class StyledStreamWriter { diff --git a/src/test/json/json_value_test.cpp b/src/test/json/json_value_test.cpp index 1917e4cfb3a..b09be9de386 100644 --- a/src/test/json/json_value_test.cpp +++ b/src/test/json/json_value_test.cpp @@ -17,11 +17,12 @@ */ //============================================================================== -#include #include +#include #include -#include +#include #include +#include #include #include @@ -30,6 +31,548 @@ namespace ripple { struct json_value_test : beast::unit_test::suite { + void test_StaticString() + { + static constexpr char sample[] {"Contents of a Json::StaticString"}; + + static constexpr Json::StaticString test1 (sample); + char const* addrTest1 {test1}; + + BEAST_EXPECT (addrTest1 == &sample[0]); + BEAST_EXPECT (test1.c_str() == &sample[0]); + + static constexpr Json::StaticString test2 { + "Contents of a Json::StaticString"}; + static constexpr Json::StaticString test3 {"Another StaticString"}; + + BEAST_EXPECT (test1 == test2); + BEAST_EXPECT (test1 != test3); + + std::string str {sample}; + BEAST_EXPECT (str == test2); + BEAST_EXPECT (str != test3); + BEAST_EXPECT (test2 == str); + BEAST_EXPECT (test3 != str); + } + + void test_types() + { + // Exercise ValueType constructor + static constexpr Json::StaticString staticStr {"staticStr"}; + + auto testCopy = [this] (Json::ValueType typ) + { + Json::Value val {typ}; + Json::Value cpy {val}; + BEAST_EXPECT (val.type() == typ); + BEAST_EXPECT (cpy.type() == typ); + return val; + }; + { + Json::Value const nullV {testCopy (Json::nullValue)}; + BEAST_EXPECT ( nullV.isNull()); + BEAST_EXPECT (! nullV.isBool()); + BEAST_EXPECT (! nullV.isInt()); + BEAST_EXPECT (! nullV.isUInt()); + BEAST_EXPECT (! nullV.isIntegral()); + BEAST_EXPECT (! nullV.isDouble()); + BEAST_EXPECT (! nullV.isNumeric()); + BEAST_EXPECT (! nullV.isString()); + BEAST_EXPECT (! nullV.isArray()); + BEAST_EXPECT ( nullV.isArrayOrNull()); + BEAST_EXPECT (! nullV.isObject()); + BEAST_EXPECT ( nullV.isObjectOrNull()); + } + { + Json::Value const intV {testCopy (Json::intValue)}; + BEAST_EXPECT (! intV.isNull()); + BEAST_EXPECT (! intV.isBool()); + BEAST_EXPECT ( intV.isInt()); + BEAST_EXPECT (! intV.isUInt()); + BEAST_EXPECT ( intV.isIntegral()); + BEAST_EXPECT (! intV.isDouble()); + BEAST_EXPECT ( intV.isNumeric()); + BEAST_EXPECT (! intV.isString()); + BEAST_EXPECT (! intV.isArray()); + BEAST_EXPECT (! intV.isArrayOrNull()); + BEAST_EXPECT (! intV.isObject()); + BEAST_EXPECT (! intV.isObjectOrNull()); + } + { + Json::Value const uintV {testCopy (Json::uintValue)}; + BEAST_EXPECT (! uintV.isNull()); + BEAST_EXPECT (! uintV.isBool()); + BEAST_EXPECT (! uintV.isInt()); + BEAST_EXPECT ( uintV.isUInt()); + BEAST_EXPECT ( uintV.isIntegral()); + BEAST_EXPECT (! uintV.isDouble()); + BEAST_EXPECT ( uintV.isNumeric()); + BEAST_EXPECT (! uintV.isString()); + BEAST_EXPECT (! uintV.isArray()); + BEAST_EXPECT (! uintV.isArrayOrNull()); + BEAST_EXPECT (! uintV.isObject()); + BEAST_EXPECT (! uintV.isObjectOrNull()); + } + { + Json::Value const realV {testCopy (Json::realValue)}; + BEAST_EXPECT (! realV.isNull()); + BEAST_EXPECT (! realV.isBool()); + BEAST_EXPECT (! realV.isInt()); + BEAST_EXPECT (! realV.isUInt()); + BEAST_EXPECT (! realV.isIntegral()); + BEAST_EXPECT ( realV.isDouble()); + BEAST_EXPECT ( realV.isNumeric()); + BEAST_EXPECT (! realV.isString()); + BEAST_EXPECT (! realV.isArray()); + BEAST_EXPECT (! realV.isArrayOrNull()); + BEAST_EXPECT (! realV.isObject()); + BEAST_EXPECT (! realV.isObjectOrNull()); + } + { + Json::Value const stringV {testCopy (Json::stringValue)}; + BEAST_EXPECT (! stringV.isNull()); + BEAST_EXPECT (! stringV.isBool()); + BEAST_EXPECT (! stringV.isInt()); + BEAST_EXPECT (! stringV.isUInt()); + BEAST_EXPECT (! stringV.isIntegral()); + BEAST_EXPECT (! stringV.isDouble()); + BEAST_EXPECT (! stringV.isNumeric()); + BEAST_EXPECT ( stringV.isString()); + BEAST_EXPECT (! stringV.isArray()); + BEAST_EXPECT (! stringV.isArrayOrNull()); + BEAST_EXPECT (! stringV.isObject()); + BEAST_EXPECT (! stringV.isObjectOrNull()); + } + { + Json::Value const staticStrV {staticStr}; + { + Json::Value cpy {staticStrV}; + BEAST_EXPECT (staticStrV.type() == Json::stringValue); + BEAST_EXPECT (cpy.type() == Json::stringValue); + } + BEAST_EXPECT (! staticStrV.isNull()); + BEAST_EXPECT (! staticStrV.isBool()); + BEAST_EXPECT (! staticStrV.isInt()); + BEAST_EXPECT (! staticStrV.isUInt()); + BEAST_EXPECT (! staticStrV.isIntegral()); + BEAST_EXPECT (! staticStrV.isDouble()); + BEAST_EXPECT (! staticStrV.isNumeric()); + BEAST_EXPECT ( staticStrV.isString()); + BEAST_EXPECT (! staticStrV.isArray()); + BEAST_EXPECT (! staticStrV.isArrayOrNull()); + BEAST_EXPECT (! staticStrV.isObject()); + BEAST_EXPECT (! staticStrV.isObjectOrNull()); + } + { + Json::Value const boolV {testCopy (Json::booleanValue)}; + BEAST_EXPECT (! boolV.isNull()); + BEAST_EXPECT ( boolV.isBool()); + BEAST_EXPECT (! boolV.isInt()); + BEAST_EXPECT (! boolV.isUInt()); + BEAST_EXPECT ( boolV.isIntegral()); + BEAST_EXPECT (! boolV.isDouble()); + BEAST_EXPECT ( boolV.isNumeric()); + BEAST_EXPECT (! boolV.isString()); + BEAST_EXPECT (! boolV.isArray()); + BEAST_EXPECT (! boolV.isArrayOrNull()); + BEAST_EXPECT (! boolV.isObject()); + BEAST_EXPECT (! boolV.isObjectOrNull()); + } + { + Json::Value const arrayV {testCopy (Json::arrayValue)}; + BEAST_EXPECT (! arrayV.isNull()); + BEAST_EXPECT (! arrayV.isBool()); + BEAST_EXPECT (! arrayV.isInt()); + BEAST_EXPECT (! arrayV.isUInt()); + BEAST_EXPECT (! arrayV.isIntegral()); + BEAST_EXPECT (! arrayV.isDouble()); + BEAST_EXPECT (! arrayV.isNumeric()); + BEAST_EXPECT (! arrayV.isString()); + BEAST_EXPECT ( arrayV.isArray()); + BEAST_EXPECT ( arrayV.isArrayOrNull()); + BEAST_EXPECT (! arrayV.isObject()); + BEAST_EXPECT (! arrayV.isObjectOrNull()); + } + { + Json::Value const objectV {testCopy (Json::objectValue)}; + BEAST_EXPECT (! objectV.isNull()); + BEAST_EXPECT (! objectV.isBool()); + BEAST_EXPECT (! objectV.isInt()); + BEAST_EXPECT (! objectV.isUInt()); + BEAST_EXPECT (! objectV.isIntegral()); + BEAST_EXPECT (! objectV.isDouble()); + BEAST_EXPECT (! objectV.isNumeric()); + BEAST_EXPECT (! objectV.isString()); + BEAST_EXPECT (! objectV.isArray()); + BEAST_EXPECT (! objectV.isArrayOrNull()); + BEAST_EXPECT ( objectV.isObject()); + BEAST_EXPECT ( objectV.isObjectOrNull()); + } + } + + void test_compare() + { + auto doCompare = [this] ( + Json::Value const& lhs, + Json::Value const& rhs, + bool lhsEqRhs, + bool lhsLtRhs, + int line) + { + auto fmt = [this] (bool cond, char const* text, int line) + { + if (cond) + this->pass(); + else + this->fail (text, __FILE__, line); + }; + fmt ((lhs == rhs) == lhsEqRhs, "Value ==", line); + fmt ((lhs != rhs) != lhsEqRhs, "Value !=", line); + fmt ((lhs < rhs) == (! (lhsEqRhs | !lhsLtRhs)), "Value <", line); + fmt ((lhs <= rhs) == ( lhsEqRhs | lhsLtRhs ), "Value <=", line); + fmt ((lhs >= rhs) == ( lhsEqRhs | !lhsLtRhs ), "Value >=", line); + fmt ((lhs > rhs) == (! (lhsEqRhs | lhsLtRhs)), "Value >", line); + }; + + Json::Value const null0; + Json::Value const intNeg1 {-1}; + Json::Value const int0 {Json::intValue}; + Json::Value const intPos1 {1}; + Json::Value const uint0 {Json::uintValue}; + Json::Value const uint1 {1u}; + Json::Value const realNeg1 {-1.0}; + Json::Value const real0 {Json::realValue}; + Json::Value const realPos1 {1.0}; + Json::Value const str0 {Json::stringValue}; + Json::Value const str1 {"1"}; + Json::Value const boolF {false}; + Json::Value const boolT {true}; + Json::Value const array0 {Json::arrayValue}; + Json::Value const array1 { + []() + { + Json::Value array1; + array1[0u] = 1; + return array1; + }() + }; + Json::Value const obj0 {Json::objectValue}; + Json::Value const obj1 { + []() + { + Json::Value obj1; + obj1["one"] = 1; + return obj1; + }() + }; + // lhs == rhs lhs < rhs + doCompare (null0, Json::Value{}, true, false, __LINE__); + doCompare (null0, intNeg1, false, true, __LINE__); + doCompare (null0, int0, false, true, __LINE__); + doCompare (null0, intPos1, false, true, __LINE__); + doCompare (null0, uint0, false, true, __LINE__); + doCompare (null0, uint1, false, true, __LINE__); + doCompare (null0, realNeg1, false, true, __LINE__); + doCompare (null0, real0, false, true, __LINE__); + doCompare (null0, realPos1, false, true, __LINE__); + doCompare (null0, str0, false, true, __LINE__); + doCompare (null0, str1, false, true, __LINE__); + doCompare (null0, boolF, false, true, __LINE__); + doCompare (null0, boolT, false, true, __LINE__); + doCompare (null0, array0, false, true, __LINE__); + doCompare (null0, array1, false, true, __LINE__); + doCompare (null0, obj0, false, true, __LINE__); + doCompare (null0, obj1, false, true, __LINE__); + // lhs == rhs lhs < rhs + doCompare (intNeg1, null0, false, false, __LINE__); + doCompare (intNeg1, intNeg1, true, false, __LINE__); + doCompare (intNeg1, int0, false, true, __LINE__); + doCompare (intNeg1, intPos1, false, true, __LINE__); + doCompare (intNeg1, uint0, false, true, __LINE__); + doCompare (intNeg1, uint1, false, true, __LINE__); + doCompare (intNeg1, realNeg1, false, true, __LINE__); + doCompare (intNeg1, real0, false, true, __LINE__); + doCompare (intNeg1, realPos1, false, true, __LINE__); + doCompare (intNeg1, str0, false, true, __LINE__); + doCompare (intNeg1, str1, false, true, __LINE__); + doCompare (intNeg1, boolF, false, true, __LINE__); + doCompare (intNeg1, boolT, false, true, __LINE__); + doCompare (intNeg1, array0, false, true, __LINE__); + doCompare (intNeg1, array1, false, true, __LINE__); + doCompare (intNeg1, obj0, false, true, __LINE__); + doCompare (intNeg1, obj1, false, true, __LINE__); + // lhs == rhs lhs < rhs + doCompare (int0, null0, false, false, __LINE__); + doCompare (int0, intNeg1, false, false, __LINE__); + doCompare (int0, int0, true, false, __LINE__); + doCompare (int0, intPos1, false, true, __LINE__); + doCompare (int0, uint0, true, false, __LINE__); + doCompare (int0, uint1, false, true, __LINE__); + doCompare (int0, realNeg1, false, true, __LINE__); + doCompare (int0, real0, false, true, __LINE__); + doCompare (int0, realPos1, false, true, __LINE__); + doCompare (int0, str0, false, true, __LINE__); + doCompare (int0, str1, false, true, __LINE__); + doCompare (int0, boolF, false, true, __LINE__); + doCompare (int0, boolT, false, true, __LINE__); + doCompare (int0, array0, false, true, __LINE__); + doCompare (int0, array1, false, true, __LINE__); + doCompare (int0, obj0, false, true, __LINE__); + doCompare (int0, obj1, false, true, __LINE__); + // lhs == rhs lhs < rhs + doCompare (intPos1, null0, false, false, __LINE__); + doCompare (intPos1, intNeg1, false, false, __LINE__); + doCompare (intPos1, int0, false, false, __LINE__); + doCompare (intPos1, intPos1, true, false, __LINE__); + doCompare (intPos1, uint0, false, false, __LINE__); + doCompare (intPos1, uint1, true, false, __LINE__); + doCompare (intPos1, realNeg1, false, true, __LINE__); + doCompare (intPos1, real0, false, true, __LINE__); + doCompare (intPos1, realPos1, false, true, __LINE__); + doCompare (intPos1, str0, false, true, __LINE__); + doCompare (intPos1, str1, false, true, __LINE__); + doCompare (intPos1, boolF, false, true, __LINE__); + doCompare (intPos1, boolT, false, true, __LINE__); + doCompare (intPos1, array0, false, true, __LINE__); + doCompare (intPos1, array1, false, true, __LINE__); + doCompare (intPos1, obj0, false, true, __LINE__); + doCompare (intPos1, obj1, false, true, __LINE__); + // lhs == rhs lhs < rhs + doCompare (uint0, null0, false, false, __LINE__); + doCompare (uint0, intNeg1, false, false, __LINE__); + doCompare (uint0, int0, true, false, __LINE__); + doCompare (uint0, intPos1, false, true, __LINE__); + doCompare (uint0, uint0, true, false, __LINE__); + doCompare (uint0, uint1, false, true, __LINE__); + doCompare (uint0, realNeg1, false, true, __LINE__); + doCompare (uint0, real0, false, true, __LINE__); + doCompare (uint0, realPos1, false, true, __LINE__); + doCompare (uint0, str0, false, true, __LINE__); + doCompare (uint0, str1, false, true, __LINE__); + doCompare (uint0, boolF, false, true, __LINE__); + doCompare (uint0, boolT, false, true, __LINE__); + doCompare (uint0, array0, false, true, __LINE__); + doCompare (uint0, array1, false, true, __LINE__); + doCompare (uint0, obj0, false, true, __LINE__); + doCompare (uint0, obj1, false, true, __LINE__); + // lhs == rhs lhs < rhs + doCompare (uint1, null0, false, false, __LINE__); + doCompare (uint1, intNeg1, false, false, __LINE__); + doCompare (uint1, int0, false, false, __LINE__); + doCompare (uint1, intPos1, true, false, __LINE__); + doCompare (uint1, uint0, false, false, __LINE__); + doCompare (uint1, uint1, true, false, __LINE__); + doCompare (uint1, realNeg1, false, true, __LINE__); + doCompare (uint1, real0, false, true, __LINE__); + doCompare (uint1, realPos1, false, true, __LINE__); + doCompare (uint1, str0, false, true, __LINE__); + doCompare (uint1, str1, false, true, __LINE__); + doCompare (uint1, boolF, false, true, __LINE__); + doCompare (uint1, boolT, false, true, __LINE__); + doCompare (uint1, array0, false, true, __LINE__); + doCompare (uint1, array1, false, true, __LINE__); + doCompare (uint1, obj0, false, true, __LINE__); + doCompare (uint1, obj1, false, true, __LINE__); + // lhs == rhs lhs < rhs + doCompare (realNeg1, null0, false, false, __LINE__); + doCompare (realNeg1, intNeg1, false, false, __LINE__); + doCompare (realNeg1, int0, false, false, __LINE__); + doCompare (realNeg1, intPos1, false, false, __LINE__); + doCompare (realNeg1, uint0, false, false, __LINE__); + doCompare (realNeg1, uint1, false, false, __LINE__); + doCompare (realNeg1, realNeg1, true, false, __LINE__); + doCompare (realNeg1, real0, false, true, __LINE__); + doCompare (realNeg1, realPos1, false, true, __LINE__); + doCompare (realNeg1, str0, false, true, __LINE__); + doCompare (realNeg1, str1, false, true, __LINE__); + doCompare (realNeg1, boolF, false, true, __LINE__); + doCompare (realNeg1, boolT, false, true, __LINE__); + doCompare (realNeg1, array0, false, true, __LINE__); + doCompare (realNeg1, array1, false, true, __LINE__); + doCompare (realNeg1, obj0, false, true, __LINE__); + doCompare (realNeg1, obj1, false, true, __LINE__); + // lhs == rhs lhs < rhs + doCompare (real0, null0, false, false, __LINE__); + doCompare (real0, intNeg1, false, false, __LINE__); + doCompare (real0, int0, false, false, __LINE__); + doCompare (real0, intPos1, false, false, __LINE__); + doCompare (real0, uint0, false, false, __LINE__); + doCompare (real0, uint1, false, false, __LINE__); + doCompare (real0, realNeg1, false, false, __LINE__); + doCompare (real0, real0, true, false, __LINE__); + doCompare (real0, realPos1, false, true, __LINE__); + doCompare (real0, str0, false, true, __LINE__); + doCompare (real0, str1, false, true, __LINE__); + doCompare (real0, boolF, false, true, __LINE__); + doCompare (real0, boolT, false, true, __LINE__); + doCompare (real0, array0, false, true, __LINE__); + doCompare (real0, array1, false, true, __LINE__); + doCompare (real0, obj0, false, true, __LINE__); + doCompare (real0, obj1, false, true, __LINE__); + // lhs == rhs lhs < rhs + doCompare (realPos1, null0, false, false, __LINE__); + doCompare (realPos1, intNeg1, false, false, __LINE__); + doCompare (realPos1, int0, false, false, __LINE__); + doCompare (realPos1, intPos1, false, false, __LINE__); + doCompare (realPos1, uint0, false, false, __LINE__); + doCompare (realPos1, uint1, false, false, __LINE__); + doCompare (realPos1, realNeg1, false, false, __LINE__); + doCompare (realPos1, real0, false, false, __LINE__); + doCompare (realPos1, realPos1, true, false, __LINE__); + doCompare (realPos1, str0, false, true, __LINE__); + doCompare (realPos1, str1, false, true, __LINE__); + doCompare (realPos1, boolF, false, true, __LINE__); + doCompare (realPos1, boolT, false, true, __LINE__); + doCompare (realPos1, array0, false, true, __LINE__); + doCompare (realPos1, array1, false, true, __LINE__); + doCompare (realPos1, obj0, false, true, __LINE__); + doCompare (realPos1, obj1, false, true, __LINE__); + // lhs == rhs lhs < rhs + doCompare (str0, null0, false, false, __LINE__); + doCompare (str0, intNeg1, false, false, __LINE__); + doCompare (str0, int0, false, false, __LINE__); + doCompare (str0, intPos1, false, false, __LINE__); + doCompare (str0, uint0, false, false, __LINE__); + doCompare (str0, uint1, false, false, __LINE__); + doCompare (str0, realNeg1, false, false, __LINE__); + doCompare (str0, real0, false, false, __LINE__); + doCompare (str0, realPos1, false, false, __LINE__); + doCompare (str0, str0, true, false, __LINE__); + doCompare (str0, str1, false, true, __LINE__); + doCompare (str0, boolF, false, true, __LINE__); + doCompare (str0, boolT, false, true, __LINE__); + doCompare (str0, array0, false, true, __LINE__); + doCompare (str0, array1, false, true, __LINE__); + doCompare (str0, obj0, false, true, __LINE__); + doCompare (str0, obj1, false, true, __LINE__); + // lhs == rhs lhs < rhs + doCompare (str1, null0, false, false, __LINE__); + doCompare (str1, intNeg1, false, false, __LINE__); + doCompare (str1, int0, false, false, __LINE__); + doCompare (str1, intPos1, false, false, __LINE__); + doCompare (str1, uint0, false, false, __LINE__); + doCompare (str1, uint1, false, false, __LINE__); + doCompare (str1, realNeg1, false, false, __LINE__); + doCompare (str1, real0, false, false, __LINE__); + doCompare (str1, realPos1, false, false, __LINE__); + doCompare (str1, str0, false, false, __LINE__); + doCompare (str1, str1, true, false, __LINE__); + doCompare (str1, boolF, false, true, __LINE__); + doCompare (str1, boolT, false, true, __LINE__); + doCompare (str1, array0, false, true, __LINE__); + doCompare (str1, array1, false, true, __LINE__); + doCompare (str1, obj0, false, true, __LINE__); + doCompare (str1, obj1, false, true, __LINE__); + // lhs == rhs lhs < rhs + doCompare (boolF, null0, false, false, __LINE__); + doCompare (boolF, intNeg1, false, false, __LINE__); + doCompare (boolF, int0, false, false, __LINE__); + doCompare (boolF, intPos1, false, false, __LINE__); + doCompare (boolF, uint0, false, false, __LINE__); + doCompare (boolF, uint1, false, false, __LINE__); + doCompare (boolF, realNeg1, false, false, __LINE__); + doCompare (boolF, real0, false, false, __LINE__); + doCompare (boolF, realPos1, false, false, __LINE__); + doCompare (boolF, str0, false, false, __LINE__); + doCompare (boolF, str1, false, false, __LINE__); + doCompare (boolF, boolF, true, false, __LINE__); + doCompare (boolF, boolT, false, true, __LINE__); + doCompare (boolF, array0, false, true, __LINE__); + doCompare (boolF, array1, false, true, __LINE__); + doCompare (boolF, obj0, false, true, __LINE__); + doCompare (boolF, obj1, false, true, __LINE__); + // lhs == rhs lhs < rhs + doCompare (boolT, null0, false, false, __LINE__); + doCompare (boolT, intNeg1, false, false, __LINE__); + doCompare (boolT, int0, false, false, __LINE__); + doCompare (boolT, intPos1, false, false, __LINE__); + doCompare (boolT, uint0, false, false, __LINE__); + doCompare (boolT, uint1, false, false, __LINE__); + doCompare (boolT, realNeg1, false, false, __LINE__); + doCompare (boolT, real0, false, false, __LINE__); + doCompare (boolT, realPos1, false, false, __LINE__); + doCompare (boolT, str0, false, false, __LINE__); + doCompare (boolT, str1, false, false, __LINE__); + doCompare (boolT, boolF, false, false, __LINE__); + doCompare (boolT, boolT, true, false, __LINE__); + doCompare (boolT, array0, false, true, __LINE__); + doCompare (boolT, array1, false, true, __LINE__); + doCompare (boolT, obj0, false, true, __LINE__); + doCompare (boolT, obj1, false, true, __LINE__); + // lhs == rhs lhs < rhs + doCompare (array0, null0, false, false, __LINE__); + doCompare (array0, intNeg1, false, false, __LINE__); + doCompare (array0, int0, false, false, __LINE__); + doCompare (array0, intPos1, false, false, __LINE__); + doCompare (array0, uint0, false, false, __LINE__); + doCompare (array0, uint1, false, false, __LINE__); + doCompare (array0, realNeg1, false, false, __LINE__); + doCompare (array0, real0, false, false, __LINE__); + doCompare (array0, realPos1, false, false, __LINE__); + doCompare (array0, str0, false, false, __LINE__); + doCompare (array0, str1, false, false, __LINE__); + doCompare (array0, boolF, false, false, __LINE__); + doCompare (array0, boolT, false, false, __LINE__); + doCompare (array0, array0, true, false, __LINE__); + doCompare (array0, array1, false, true, __LINE__); + doCompare (array0, obj0, false, true, __LINE__); + doCompare (array0, obj1, false, true, __LINE__); + // lhs == rhs lhs < rhs + doCompare (array1, null0, false, false, __LINE__); + doCompare (array1, intNeg1, false, false, __LINE__); + doCompare (array1, int0, false, false, __LINE__); + doCompare (array1, intPos1, false, false, __LINE__); + doCompare (array1, uint0, false, false, __LINE__); + doCompare (array1, uint1, false, false, __LINE__); + doCompare (array1, realNeg1, false, false, __LINE__); + doCompare (array1, real0, false, false, __LINE__); + doCompare (array1, realPos1, false, false, __LINE__); + doCompare (array1, str0, false, false, __LINE__); + doCompare (array1, str1, false, false, __LINE__); + doCompare (array1, boolF, false, false, __LINE__); + doCompare (array1, boolT, false, false, __LINE__); + doCompare (array1, array0, false, false, __LINE__); + doCompare (array1, array1, true, false, __LINE__); + doCompare (array1, obj0, false, true, __LINE__); + doCompare (array1, obj1, false, true, __LINE__); + // lhs == rhs lhs < rhs + doCompare (obj0, null0, false, false, __LINE__); + doCompare (obj0, intNeg1, false, false, __LINE__); + doCompare (obj0, int0, false, false, __LINE__); + doCompare (obj0, intPos1, false, false, __LINE__); + doCompare (obj0, uint0, false, false, __LINE__); + doCompare (obj0, uint1, false, false, __LINE__); + doCompare (obj0, realNeg1, false, false, __LINE__); + doCompare (obj0, real0, false, false, __LINE__); + doCompare (obj0, realPos1, false, false, __LINE__); + doCompare (obj0, str0, false, false, __LINE__); + doCompare (obj0, str1, false, false, __LINE__); + doCompare (obj0, boolF, false, false, __LINE__); + doCompare (obj0, boolT, false, false, __LINE__); + doCompare (obj0, array0, false, false, __LINE__); + doCompare (obj0, array1, false, false, __LINE__); + doCompare (obj0, obj0, true, false, __LINE__); + doCompare (obj0, obj1, false, true, __LINE__); + // lhs == rhs lhs < rhs + doCompare (obj1, null0, false, false, __LINE__); + doCompare (obj1, intNeg1, false, false, __LINE__); + doCompare (obj1, int0, false, false, __LINE__); + doCompare (obj1, intPos1, false, false, __LINE__); + doCompare (obj1, uint0, false, false, __LINE__); + doCompare (obj1, uint1, false, false, __LINE__); + doCompare (obj1, realNeg1, false, false, __LINE__); + doCompare (obj1, real0, false, false, __LINE__); + doCompare (obj1, realPos1, false, false, __LINE__); + doCompare (obj1, str0, false, false, __LINE__); + doCompare (obj1, str1, false, false, __LINE__); + doCompare (obj1, boolF, false, false, __LINE__); + doCompare (obj1, boolT, false, false, __LINE__); + doCompare (obj1, array0, false, false, __LINE__); + doCompare (obj1, array1, false, false, __LINE__); + doCompare (obj1, obj0, false, false, __LINE__); + doCompare (obj1, obj1, true, false, __LINE__); + } + void test_bool() { BEAST_EXPECT(! Json::Value()); @@ -120,7 +663,57 @@ struct json_value_test : beast::unit_test::suite BEAST_EXPECT(!r3.parse (json, j3)); - pass (); + Json::Value intString {"4294967296"}; + try + { + [[maybe_unused]] std::uint32_t const uTooBig {intString.asUInt()}; + fail("4294967296", __FILE__, __LINE__); + } catch (beast::BadLexicalCast const&) + { + pass(); + } + + intString = "4294967295"; + BEAST_EXPECT (intString.asUInt() == 4294967295u); + + intString = "0"; + BEAST_EXPECT (intString.asUInt() == 0); + + intString = "-1"; + try + { + [[maybe_unused]] std::uint32_t const uTooSmall {intString.asUInt()}; + fail("-1", __FILE__, __LINE__); + } catch (beast::BadLexicalCast const&) + { + pass(); + } + + intString = "2147483648"; + try + { + [[maybe_unused]] std::int32_t tooPos {intString.asInt()}; + fail("2147483648", __FILE__, __LINE__); + } catch (beast::BadLexicalCast const&) + { + pass(); + } + + intString = "2147483647"; + BEAST_EXPECT (intString.asInt() == 2147483647); + + intString = "-2147483648"; + BEAST_EXPECT (intString.asInt() == -2147483648LL); // MSVC wants the LL + + intString = "-2147483649"; + try + { + [[maybe_unused]] std::int32_t tooNeg {intString.asInt()}; + fail("-2147483649", __FILE__, __LINE__); + } catch (beast::BadLexicalCast const&) + { + pass(); + } } void @@ -253,37 +846,435 @@ struct json_value_test : beast::unit_test::suite void test_conversions () { - // We have Json::Int, but not Json::Double or Json::Real. - // We have Json::Int, Json::Value::Int, and Json::ValueType::intValue. - // We have Json::ValueType::realValue but Json::Value::asDouble. - // TODO: What's the thinking here? - { - // null + // We have Json::Int, but not Json::Double or Json::Real. + // We have Json::Int, Json::Value::Int, and Json::ValueType::intValue. + // We have Json::ValueType::realValue but Json::Value::asDouble. + // TODO: What's the thinking here? + { + // null + Json::Value val; + BEAST_EXPECT(val.isNull()); +// BEAST_EXPECT(strcmp (val.asCString(), ?) == 0); // asserts + BEAST_EXPECT(val.asString() == ""); + BEAST_EXPECT(val.asInt() == 0); + BEAST_EXPECT(val.asUInt() == 0); + BEAST_EXPECT(val.asDouble() == 0.0); + BEAST_EXPECT(val.asBool() == false); + + BEAST_EXPECT( val.isConvertibleTo (Json::nullValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::intValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::uintValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::realValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::stringValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::booleanValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::arrayValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::objectValue)); + } + { + // int + Json::Value val = -1234; + BEAST_EXPECT(val.isInt()); +// BEAST_EXPECT(strcmp (val.asCString(), ?) == 0); // asserts + BEAST_EXPECT(val.asString() == "-1234"); + BEAST_EXPECT(val.asInt() == -1234); +// BEAST_EXPECT(val.asUInt() == ?); // asserts or throws + BEAST_EXPECT(val.asDouble() == -1234.0); + BEAST_EXPECT(val.asBool() == true); + + BEAST_EXPECT(! val.isConvertibleTo (Json::nullValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::intValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::uintValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::realValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::stringValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::booleanValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::arrayValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::objectValue)); + } + { + // uint + Json::Value val = 1234U; + BEAST_EXPECT(val.isUInt()); +// BEAST_EXPECT(strcmp (val.asCString(), ?) == 0); // asserts + BEAST_EXPECT(val.asString() == "1234"); + BEAST_EXPECT(val.asInt() == 1234); + BEAST_EXPECT(val.asUInt() == 1234u); + BEAST_EXPECT(val.asDouble() == 1234.0); + BEAST_EXPECT(val.asBool() == true); + + BEAST_EXPECT(! val.isConvertibleTo (Json::nullValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::intValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::uintValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::realValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::stringValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::booleanValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::arrayValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::objectValue)); + } + { + // real + Json::Value val = 2.0; + BEAST_EXPECT(val.isDouble()); +// BEAST_EXPECT(strcmp (val.asCString(), ?) == 0); // asserts + BEAST_EXPECT(std::regex_match( + val.asString(), std::regex("^2\\.0*$"))); + BEAST_EXPECT(val.asInt() == 2); + BEAST_EXPECT(val.asUInt() == 2u); + BEAST_EXPECT(val.asDouble() == 2.0); + BEAST_EXPECT(val.asBool() == true); + + BEAST_EXPECT(! val.isConvertibleTo (Json::nullValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::intValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::uintValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::realValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::stringValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::booleanValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::arrayValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::objectValue)); + } + { + // numeric string + Json::Value val = "54321"; + BEAST_EXPECT(val.isString()); + BEAST_EXPECT(strcmp (val.asCString(), "54321") == 0); + BEAST_EXPECT(val.asString() == "54321"); + BEAST_EXPECT(val.asInt() == 54321); + BEAST_EXPECT(val.asUInt() == 54321u); +// BEAST_EXPECT(val.asDouble() == 54321.0); // asserts or throws + BEAST_EXPECT(val.asBool() == true); + + BEAST_EXPECT(! val.isConvertibleTo (Json::nullValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::intValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::uintValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::realValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::stringValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::booleanValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::arrayValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::objectValue)); + } + { + // non-numeric string + Json::Value val (Json::stringValue); + BEAST_EXPECT(val.isString()); + BEAST_EXPECT(val.asCString() == nullptr); + BEAST_EXPECT(val.asString() == ""); + try { + BEAST_EXPECT(val.asInt() == 0); + fail("expected exception", __FILE__, __LINE__); + } catch (std::exception const&) { + pass(); + } + try { + BEAST_EXPECT(val.asUInt() == 0); + fail("expected exception", __FILE__, __LINE__); + } catch (std::exception const&) { + pass(); + } +// BEAST_EXPECT(val.asDouble() == ?); // asserts or throws + BEAST_EXPECT(val.asBool() == false); + + BEAST_EXPECT( val.isConvertibleTo (Json::nullValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::intValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::uintValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::realValue)); + BEAST_EXPECT(val.isConvertibleTo (Json::stringValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::booleanValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::arrayValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::objectValue)); + } + { + // bool false + Json::Value val = false; + BEAST_EXPECT(val.isBool()); +// BEAST_EXPECT(strcmp (val.asCString(), ?) == 0); // asserts + BEAST_EXPECT(val.asString() == "false"); + BEAST_EXPECT(val.asInt() == 0); + BEAST_EXPECT(val.asUInt() == 0); + BEAST_EXPECT(val.asDouble() == 0.0); + BEAST_EXPECT(val.asBool() == false); + + BEAST_EXPECT( val.isConvertibleTo (Json::nullValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::intValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::uintValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::realValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::stringValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::booleanValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::arrayValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::objectValue)); + } + { + // bool true + Json::Value val = true; + BEAST_EXPECT(val.isBool()); +// BEAST_EXPECT(strcmp (val.asCString(), ?) == 0); // asserts + BEAST_EXPECT(val.asString() == "true"); + BEAST_EXPECT(val.asInt() == 1); + BEAST_EXPECT(val.asUInt() == 1); + BEAST_EXPECT(val.asDouble() == 1.0); + BEAST_EXPECT(val.asBool() == true); + + BEAST_EXPECT(! val.isConvertibleTo (Json::nullValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::intValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::uintValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::realValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::stringValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::booleanValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::arrayValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::objectValue)); + } + { + // array type + Json::Value val (Json::arrayValue); + BEAST_EXPECT (val.isArray()); +// BEAST_EXPECT(strcmp (val.asCString(), ?) == 0); // asserts +// BEAST_EXPECT(val.asString() == ?); // asserts or throws +// BEAST_EXPECT(val.asInt() == ?); // asserts or throws +// BEAST_EXPECT(val.asUInt() == ?); // asserts or throws +// BEAST_EXPECT(val.asDouble() == ?); // asserts or throws + BEAST_EXPECT(val.asBool() == false); // empty or not + + BEAST_EXPECT( val.isConvertibleTo (Json::nullValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::intValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::uintValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::realValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::stringValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::booleanValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::arrayValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::objectValue)); + } + { + // object type + Json::Value val (Json::objectValue); + BEAST_EXPECT (val.isObject()); +// BEAST_EXPECT(strcmp (val.asCString(), ?) == 0); // asserts +// BEAST_EXPECT(strcmp (val.asCString(), ?) == 0); // asserts +// BEAST_EXPECT(val.asString() == ?); // asserts or throws +// BEAST_EXPECT(val.asInt() == ?); // asserts or throws +// BEAST_EXPECT(val.asUInt() == ?); // asserts or throws + BEAST_EXPECT(val.asBool() == false); // empty or not + + BEAST_EXPECT( val.isConvertibleTo (Json::nullValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::intValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::uintValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::realValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::stringValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::booleanValue)); + BEAST_EXPECT(! val.isConvertibleTo (Json::arrayValue)); + BEAST_EXPECT( val.isConvertibleTo (Json::objectValue)); + } + } + + void + test_access() + { Json::Value val; - BEAST_EXPECT(val.isNull()); - BEAST_EXPECT(val.asString() == ""); - } - { - // bool - Json::Value val = true; - BEAST_EXPECT(val.asString() == "true"); - } - { - // int - Json::Value val = -1234; - BEAST_EXPECT(val.asString() == "-1234"); - } - { - // uint - Json::Value val = 1234U; - BEAST_EXPECT(val.asString() == "1234"); - } - { - // real - Json::Value val = 2.0; - BEAST_EXPECT(std::regex_match( - val.asString(), std::regex("^2\\.0*$"))); - } + BEAST_EXPECT (val.type() == Json::nullValue); + BEAST_EXPECT (val.size() == 0); + BEAST_EXPECT (! val.isValidIndex(0)); + BEAST_EXPECT (! val.isMember("key")); + { + Json::Value const constVal = val; + BEAST_EXPECT (constVal[7u].type() == Json::nullValue); + BEAST_EXPECT (! constVal.isMember("key")); + BEAST_EXPECT (constVal["key"].type() == Json::nullValue); + BEAST_EXPECT (constVal.getMemberNames().empty()); + BEAST_EXPECT (constVal.get (1u, "default0") == "default0"); + BEAST_EXPECT (constVal.get (std::string ("not"), "oh") == "oh"); + BEAST_EXPECT (constVal.get ("missing", "default2") == "default2"); + } + + val = -7; + BEAST_EXPECT (val.type() == Json::intValue); + BEAST_EXPECT (val.size() == 0); + BEAST_EXPECT (! val.isValidIndex(0)); + BEAST_EXPECT (! val.isMember("key")); + + val = 42u; + BEAST_EXPECT (val.type() == Json::uintValue); + BEAST_EXPECT (val.size() == 0); + BEAST_EXPECT (! val.isValidIndex(0)); + BEAST_EXPECT (! val.isMember("key")); + + val = 3.14159; + BEAST_EXPECT (val.type() == Json::realValue); + BEAST_EXPECT (val.size() == 0); + BEAST_EXPECT (! val.isValidIndex(0)); + BEAST_EXPECT (! val.isMember("key")); + + val = true; + BEAST_EXPECT (val.type() == Json::booleanValue); + BEAST_EXPECT (val.size() == 0); + BEAST_EXPECT (! val.isValidIndex(0)); + BEAST_EXPECT (! val.isMember("key")); + + val = "string"; + BEAST_EXPECT (val.type() == Json::stringValue); + BEAST_EXPECT (val.size() == 0); + BEAST_EXPECT (! val.isValidIndex(0)); + BEAST_EXPECT (! val.isMember("key")); + + val = Json::Value (Json::objectValue); + BEAST_EXPECT (val.type() == Json::objectValue); + BEAST_EXPECT (val.size() == 0); + static Json::StaticString const staticThree ("three"); + val[staticThree] = 3; + val["two"] = 2; + BEAST_EXPECT (val.size() == 2); + BEAST_EXPECT (val.isValidIndex(1)); + BEAST_EXPECT (! val.isValidIndex(2)); + BEAST_EXPECT (val[staticThree] == 3); + BEAST_EXPECT (val.isMember("two")); + BEAST_EXPECT (val.isMember(staticThree)); + BEAST_EXPECT (! val.isMember("key")); + { + Json::Value const constVal = val; + BEAST_EXPECT (constVal["two"] == 2); + BEAST_EXPECT (constVal["four"].type() == Json::nullValue); + BEAST_EXPECT (constVal[staticThree] == 3); + BEAST_EXPECT (constVal.isMember("two")); + BEAST_EXPECT (constVal.isMember(staticThree)); + BEAST_EXPECT (! constVal.isMember("key")); + BEAST_EXPECT (val.get (std::string("two"), "backup") == 2); + BEAST_EXPECT (val.get ("missing", "default2") == "default2"); + } + + val = Json::Value (Json::arrayValue); + BEAST_EXPECT (val.type() == Json::arrayValue); + BEAST_EXPECT (val.size() == 0); + val[0u] = "zero"; + val[1u] = "one"; + BEAST_EXPECT (val.size() == 2); + BEAST_EXPECT (val.isValidIndex(1)); + BEAST_EXPECT (! val.isValidIndex(2)); + BEAST_EXPECT (val[20u].type() == Json::nullValue); + BEAST_EXPECT (! val.isMember("key")); + { + Json::Value const constVal = val; + BEAST_EXPECT (constVal[0u] == "zero"); + BEAST_EXPECT (constVal[2u].type() == Json::nullValue); + BEAST_EXPECT (! constVal.isMember("key")); + BEAST_EXPECT (val.get (1u, "default0") == "one"); + BEAST_EXPECT (val.get (3u, "default1") == "default1"); + } + } + + void + test_removeMember() + { + Json::Value val; + BEAST_EXPECT ( + val.removeMember (std::string("member")).type() == Json::nullValue); + + val = Json::Value (Json::objectValue); + static Json::StaticString const staticThree ("three"); + val[staticThree] = 3; + val["two"] = 2; + BEAST_EXPECT (val.size() == 2); + + BEAST_EXPECT ( + val.removeMember (std::string("six")).type() == Json::nullValue); + BEAST_EXPECT (val.size() == 2); + + BEAST_EXPECT (val.removeMember (staticThree) == 3); + BEAST_EXPECT (val.size() == 1); + + BEAST_EXPECT (val.removeMember (staticThree).type() == Json::nullValue); + BEAST_EXPECT (val.size() == 1); + + BEAST_EXPECT (val.removeMember (std::string ("two")) == 2); + BEAST_EXPECT (val.size() == 0); + + BEAST_EXPECT ( + val.removeMember (std::string ("two")).type() == Json::nullValue); + BEAST_EXPECT (val.size() == 0); + } + + void + test_iterator() + { + { + // Iterating an array. + Json::Value arr {Json::arrayValue}; + arr[0u] = "zero"; + arr[1u] = "one"; + arr[2u] = "two"; + arr[3u] = "three"; + + Json::ValueIterator const b {arr.begin()}; + Json::ValueIterator const e {arr.end()}; + + Json::ValueIterator i1 = b; + Json::ValueIterator i2 = e; + --i2; + + // key(), index(), and memberName() on an object iterator. + BEAST_EXPECT (b != e); + BEAST_EXPECT (! (b == e)); + BEAST_EXPECT (i1.key() == 0); + BEAST_EXPECT (i2.key() == 3); + BEAST_EXPECT (i1.index() == 0); + BEAST_EXPECT (i2.index() == 3); + BEAST_EXPECT (std::strcmp (i1.memberName(), "") == 0); + BEAST_EXPECT (std::strcmp (i2.memberName(), "") == 0); + + // Pre and post increment and decrement. + *i1++ = "0"; + BEAST_EXPECT (*i1 == "one"); + *i1 = "1"; + ++i1; + + *i2-- = "3"; + BEAST_EXPECT (*i2 == "two"); + BEAST_EXPECT (i1 == i2); + *i2 = "2"; + BEAST_EXPECT (*i1 == "2"); + } + { + // Iterating a const object. + Json::Value const obj {[] () + { + Json::Value obj {Json::objectValue}; + obj["0"] = 0; + obj["1"] = 1; + obj["2"] = 2; + obj["3"] = 3; + return obj; + }() + }; + + Json::ValueConstIterator i1 {obj.begin()}; + Json::ValueConstIterator i2 {obj.end()}; + --i2; + + // key(), index(), and memberName() on an object iterator. + BEAST_EXPECT (i1 != i2); + BEAST_EXPECT (! (i1 == i2)); + BEAST_EXPECT (i1.key() == "0"); + BEAST_EXPECT (i2.key() == "3"); + BEAST_EXPECT (i1.index() == -1); + BEAST_EXPECT (i2.index() == -1); + BEAST_EXPECT (std::strcmp (i1.memberName(), "0") == 0); + BEAST_EXPECT (std::strcmp (i2.memberName(), "3") == 0); + + // Pre and post increment and decrement. + BEAST_EXPECT (*i1++ == 0); + BEAST_EXPECT (*i1 == 1); + ++i1; + + BEAST_EXPECT (*i2-- == 3); + BEAST_EXPECT (*i2 == 2); + BEAST_EXPECT (i1 == i2); + BEAST_EXPECT (*i1 == 2); + } + { + // Iterating a non-const null object. + Json::Value nul {}; + BEAST_EXPECT (nul.begin() == nul.end()); + } + { + // Iterating a const Int. + Json::Value const i {-3}; + BEAST_EXPECT (i.begin() == i.end()); + } } void test_nest_limits () @@ -332,19 +1323,43 @@ struct json_value_test : beast::unit_test::suite } } - void + void test_leak() { - // When run with the address sanitizer, this test confirms there is no - // memory leak with the scenario below. - Json::Value a; - a[0u] = 1; - a = std::move(a[0u]); - pass(); + // When run with the address sanitizer, this test confirms there is no + // memory leak with the scenarios below. + { + Json::Value a; + a[0u] = 1; + BEAST_EXPECT (a.type() == Json::arrayValue); + BEAST_EXPECT (a[0u].type() == Json::intValue); + a = std::move(a[0u]); + BEAST_EXPECT (a.type() == Json::intValue); + } + { + Json::Value b; + Json::Value temp; + temp["a"] = "Probably avoids the small string optimization"; + temp["b"] = "Also probably avoids the small string optimization"; + BEAST_EXPECT (temp.type() == Json::objectValue); + b.append (temp); + BEAST_EXPECT (temp.type() == Json::objectValue); + BEAST_EXPECT (b.size() == 1); + + b.append (std::move (temp)); + BEAST_EXPECT (b.size() == 2); + + // Note that the type() == nullValue check is implementation + // specific and not guaranteed to be valid in the future. + BEAST_EXPECT (temp.type() == Json::nullValue); + } } void run () override { + test_StaticString (); + test_types (); + test_compare (); test_bool (); test_bad_json (); test_edge_cases (); @@ -352,9 +1367,12 @@ struct json_value_test : beast::unit_test::suite test_move (); test_comparisons (); test_compact (); - test_conversions(); + test_conversions (); + test_access (); + test_removeMember (); + test_iterator (); test_nest_limits (); - test_leak(); + test_leak (); } }; diff --git a/src/test/jtx/impl/multisign.cpp b/src/test/jtx/impl/multisign.cpp index 1a441003eba..c04df2ff03e 100644 --- a/src/test/jtx/impl/multisign.cpp +++ b/src/test/jtx/impl/multisign.cpp @@ -39,7 +39,6 @@ signers (Account const& account, jv[jss::TransactionType] = jss::SignerListSet; jv[sfSignerQuorum.getJsonName()] = quorum; auto& ja = jv[sfSignerEntries.getJsonName()]; - ja.resize(v.size()); for(std::size_t i = 0; i < v.size(); ++i) { auto const& e = v[i]; @@ -91,7 +90,6 @@ msig::operator()(Env& env, JTx& jt) const Rethrow(); } auto& js = jtx[sfSigners.getJsonName()]; - js.resize(mySigners.size()); for(std::size_t i = 0; i < mySigners.size(); ++i) { auto const& e = mySigners[i];