From c574f08384352e67c42a2b93aa9652c215ece956 Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Fri, 17 Nov 2023 19:12:58 -0500 Subject: [PATCH 1/5] wip to support arrays in abi_serializer. --- libraries/chain/abi_serializer.cpp | 12 ++++++---- unittests/abi_tests.cpp | 38 ++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/libraries/chain/abi_serializer.cpp b/libraries/chain/abi_serializer.cpp index 0e6232b8af..c654abc591 100644 --- a/libraries/chain/abi_serializer.cpp +++ b/libraries/chain/abi_serializer.cpp @@ -401,14 +401,15 @@ namespace eosio { namespace chain { auto rtype = resolve_type(type); auto ftype = fundamental_type(rtype); auto btype = built_in_types.find(ftype ); - if( btype != built_in_types.end() ) { + bool is_var_array = is_szarray(rtype); + if( !is_var_array && btype != built_in_types.end() ) { try { return btype->second.first(stream, is_array(rtype), is_optional(rtype), ctx.get_yield_function()); } EOS_RETHROW_EXCEPTIONS( unpack_exception, "Unable to unpack ${class} type '${type}' while processing '${p}'", ("class", is_array(rtype) ? "array of built-in" : is_optional(rtype) ? "optional of built-in" : "built-in") ("type", impl::limit_size(ftype))("p", ctx.get_path_string()) ) } - if ( is_array(rtype) ) { + if ( is_array(rtype) || is_var_array ) { ctx.hint_array_type_if_in_array(); fc::unsigned_int size; try { @@ -496,10 +497,11 @@ namespace eosio { namespace chain { auto v_itr = variants.end(); auto s_itr = structs.end(); - auto btype = built_in_types.find(fundamental_type(rtype)); - if( btype != built_in_types.end() ) { + bool var_is_array = var.get_type() == fc::variant::array_type; + + if( auto btype = built_in_types.find(fundamental_type(rtype)); !var_is_array && btype != built_in_types.end() ) { btype->second.second(var, ds, is_array(rtype), is_optional(rtype), ctx.get_yield_function()); - } else if ( is_array(rtype) ) { + } else if ( var_is_array || is_array(rtype) ) { ctx.hint_array_type_if_in_array(); vector vars = var.get_array(); fc::raw::pack(ds, (fc::unsigned_int)vars.size()); diff --git a/unittests/abi_tests.cpp b/unittests/abi_tests.cpp index d3a936fc46..5f5e9a90d4 100644 --- a/unittests/abi_tests.cpp +++ b/unittests/abi_tests.cpp @@ -530,6 +530,44 @@ fc::variant verify_type_round_trip_conversion( const abi_serializer& abis, const } )====="; +BOOST_AUTO_TEST_CASE(std_array_types) +{ try { + + const char* currency_abi = R"=====( + { + "version": "eosio::abi/1.0", + "types": [], + "structs": [{ + "name": "test", + "base": "", + "fields": [{ + "name": "a", + "type": "uint8[5]" + }] + }], + "actions": [], + "tables": [], + "ricardian_clauses": [] + } + )====="; + + auto abi = fc::json::from_string(currency_abi).as(); + + abi_serializer abis(eosio_contract_abi(abi), abi_serializer::create_yield_function( max_serialization_time )); + + const char* test_data = R"=====( + { + "a" : [1, 2, 3, 4, 5] + } + )====="; + + + auto var = fc::json::from_string(test_data); + verify_byte_round_trip_conversion(abi_serializer{std::move(abi), abi_serializer::create_yield_function( max_serialization_time )}, "test", var); + +} FC_LOG_AND_RETHROW() } + + BOOST_AUTO_TEST_CASE(uint_types) { try { From f2c478c94ee22b32d34fc4ba61869b8e1666f2c0 Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Fri, 17 Nov 2023 19:21:36 -0500 Subject: [PATCH 2/5] Fix issue - now `abi_tests.cpp` do pass. --- libraries/chain/abi_serializer.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libraries/chain/abi_serializer.cpp b/libraries/chain/abi_serializer.cpp index c654abc591..866be65adb 100644 --- a/libraries/chain/abi_serializer.cpp +++ b/libraries/chain/abi_serializer.cpp @@ -400,16 +400,15 @@ namespace eosio { namespace chain { auto h = ctx.enter_scope(); auto rtype = resolve_type(type); auto ftype = fundamental_type(rtype); - auto btype = built_in_types.find(ftype ); - bool is_var_array = is_szarray(rtype); - if( !is_var_array && btype != built_in_types.end() ) { + bool var_is_array = is_szarray(rtype); + if( auto btype = built_in_types.find(ftype ); !var_is_array && btype != built_in_types.end() ) { try { return btype->second.first(stream, is_array(rtype), is_optional(rtype), ctx.get_yield_function()); } EOS_RETHROW_EXCEPTIONS( unpack_exception, "Unable to unpack ${class} type '${type}' while processing '${p}'", ("class", is_array(rtype) ? "array of built-in" : is_optional(rtype) ? "optional of built-in" : "built-in") ("type", impl::limit_size(ftype))("p", ctx.get_path_string()) ) } - if ( is_array(rtype) || is_var_array ) { + if ( is_array(rtype) || var_is_array ) { ctx.hint_array_type_if_in_array(); fc::unsigned_int size; try { @@ -497,7 +496,7 @@ namespace eosio { namespace chain { auto v_itr = variants.end(); auto s_itr = structs.end(); - bool var_is_array = var.get_type() == fc::variant::array_type; + bool var_is_array = is_szarray(rtype); if( auto btype = built_in_types.find(fundamental_type(rtype)); !var_is_array && btype != built_in_types.end() ) { btype->second.second(var, ds, is_array(rtype), is_optional(rtype), ctx.get_yield_function()); From 401cf8a982a846171d4a7e3aeb2cacd55b75fe3c Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Sat, 18 Nov 2023 14:00:16 -0500 Subject: [PATCH 3/5] Better support for fixed-size arrays (don't serialize the size) --- libraries/chain/abi_serializer.cpp | 84 ++++++++++++------- .../include/eosio/chain/abi_serializer.hpp | 2 +- libraries/libfc/include/fc/io/varint.hpp | 21 ++--- 3 files changed, 64 insertions(+), 43 deletions(-) diff --git a/libraries/chain/abi_serializer.cpp b/libraries/chain/abi_serializer.cpp index 866be65adb..e4ccbc8e8e 100644 --- a/libraries/chain/abi_serializer.cpp +++ b/libraries/chain/abi_serializer.cpp @@ -218,17 +218,23 @@ namespace eosio { namespace chain { return ends_with(type, "[]"); } - bool abi_serializer::is_szarray(const string_view& type)const { + std::optional abi_serializer::is_szarray(const string_view& type)const { auto pos1 = type.find_last_of('['); auto pos2 = type.find_last_of(']'); - if(pos1 == string_view::npos || pos2 == string_view::npos) return false; + if(pos1 == string_view::npos || pos2 == string_view::npos) + return {}; auto pos = pos1 + 1; - if(pos == pos2) return false; + if(pos == pos2) + return {}; + + fc::unsigned_int sz = 0; while(pos < pos2) { - if( ! (type[pos] >= '0' && type[pos] <= '9') ) return false; + if( ! (type[pos] >= '0' && type[pos] <= '9') ) + return {}; + sz = 10 * sz + (type[pos] - '0'); ++pos; } - return true; + return sz; } bool abi_serializer::is_optional(const string_view& type)const { @@ -400,35 +406,39 @@ namespace eosio { namespace chain { auto h = ctx.enter_scope(); auto rtype = resolve_type(type); auto ftype = fundamental_type(rtype); - bool var_is_array = is_szarray(rtype); - if( auto btype = built_in_types.find(ftype ); !var_is_array && btype != built_in_types.end() ) { + auto fixed_array_sz = is_szarray(rtype); + + auto read_array = [&](fc::unsigned_int::base_uint sz) { + ctx.hint_array_type_if_in_array(); + vector vars; + vars.reserve(sz); + auto h1 = ctx.push_to_path( impl::array_index_path_item{} ); + for( fc::unsigned_int::base_uint i = 0; i < sz; ++i ) { + ctx.set_array_index_of_path_back(i); + auto v = _binary_to_variant(ftype, stream, ctx); + // The exception below is commented out to allow array of optional as input data + //EOS_ASSERT( !v.is_null(), unpack_exception, "Invalid packed array '${p}'", ("p", ctx.get_path_string()) ); + vars.emplace_back(std::move(v)); + } + return fc::variant( std::move(vars) ); + }; + + if (fixed_array_sz) { + return read_array(*fixed_array_sz); + } else if( auto btype = built_in_types.find(ftype ); btype != built_in_types.end() ) { try { return btype->second.first(stream, is_array(rtype), is_optional(rtype), ctx.get_yield_function()); } EOS_RETHROW_EXCEPTIONS( unpack_exception, "Unable to unpack ${class} type '${type}' while processing '${p}'", ("class", is_array(rtype) ? "array of built-in" : is_optional(rtype) ? "optional of built-in" : "built-in") ("type", impl::limit_size(ftype))("p", ctx.get_path_string()) ) } - if ( is_array(rtype) || var_is_array ) { + if ( is_array(rtype) ) { ctx.hint_array_type_if_in_array(); fc::unsigned_int size; try { fc::raw::unpack(stream, size); } EOS_RETHROW_EXCEPTIONS( unpack_exception, "Unable to unpack size of array '${p}'", ("p", ctx.get_path_string()) ) - vector vars; - auto h1 = ctx.push_to_path( impl::array_index_path_item{} ); - for( decltype(size.value) i = 0; i < size; ++i ) { - ctx.set_array_index_of_path_back(i); - auto v = _binary_to_variant(ftype, stream, ctx); - // The exception below is commented out to allow array of optional as input data - //EOS_ASSERT( !v.is_null(), unpack_exception, "Invalid packed array '${p}'", ("p", ctx.get_path_string()) ); - vars.emplace_back(std::move(v)); - } - // QUESTION: Why would the assert below ever fail? - EOS_ASSERT( vars.size() == size.value, - unpack_exception, - "packed size does not match unpacked array size, packed size ${p} actual size ${a}", - ("p", size)("a", vars.size()) ); - return fc::variant( std::move(vars) ); + return read_array(size.value); } else if ( is_optional(rtype) ) { char flag; try { @@ -496,15 +506,9 @@ namespace eosio { namespace chain { auto v_itr = variants.end(); auto s_itr = structs.end(); - bool var_is_array = is_szarray(rtype); - - if( auto btype = built_in_types.find(fundamental_type(rtype)); !var_is_array && btype != built_in_types.end() ) { - btype->second.second(var, ds, is_array(rtype), is_optional(rtype), ctx.get_yield_function()); - } else if ( var_is_array || is_array(rtype) ) { - ctx.hint_array_type_if_in_array(); - vector vars = var.get_array(); - fc::raw::pack(ds, (fc::unsigned_int)vars.size()); + auto fixed_array_sz = is_szarray(rtype); + auto pack_array = [&](const vector& vars) { auto h1 = ctx.push_to_path( impl::array_index_path_item{} ); auto h2 = ctx.disallow_extensions_unless(false); @@ -513,7 +517,23 @@ namespace eosio { namespace chain { ctx.set_array_index_of_path_back(i); _variant_to_binary(fundamental_type(rtype), var, ds, ctx); ++i; - } + } + }; + + if (fixed_array_sz) { + size_t sz = *fixed_array_sz; + ctx.hint_array_type_if_in_array(); + const vector& vars = var.get_array(); + EOS_ASSERT( vars.size() == sz, pack_exception, + "Incorrect number of values provided (${a}) for fixed-size (${b}) array type", ("a", sz)("b", vars.size())); + pack_array(vars); + } else if( auto btype = built_in_types.find(fundamental_type(rtype)); btype != built_in_types.end() ) { + btype->second.second(var, ds, is_array(rtype), is_optional(rtype), ctx.get_yield_function()); + } else if ( is_array(rtype) ) { + ctx.hint_array_type_if_in_array(); + const vector& vars = var.get_array(); + fc::raw::pack(ds, (fc::unsigned_int)vars.size()); + pack_array(vars); } else if( is_optional(rtype) ) { char flag = !var.is_null(); fc::raw::pack(ds, flag); diff --git a/libraries/chain/include/eosio/chain/abi_serializer.hpp b/libraries/chain/include/eosio/chain/abi_serializer.hpp index 3cad62bcf5..332005cc32 100644 --- a/libraries/chain/include/eosio/chain/abi_serializer.hpp +++ b/libraries/chain/include/eosio/chain/abi_serializer.hpp @@ -47,7 +47,7 @@ struct abi_serializer { /// @return string_view of `t` or internal string type std::string_view resolve_type(const std::string_view& t)const; bool is_array(const std::string_view& type)const; - bool is_szarray(const std::string_view& type)const; + std::optional is_szarray(const std::string_view& type)const; bool is_optional(const std::string_view& type)const; bool is_type( const std::string_view& type, const yield_function_t& yield )const; bool is_type(const std::string_view& type, const fc::microseconds& max_serialization_time)const; diff --git a/libraries/libfc/include/fc/io/varint.hpp b/libraries/libfc/include/fc/io/varint.hpp index c451847bcd..4dae35a667 100644 --- a/libraries/libfc/include/fc/io/varint.hpp +++ b/libraries/libfc/include/fc/io/varint.hpp @@ -4,7 +4,8 @@ namespace fc { struct unsigned_int { - unsigned_int( uint32_t v = 0 ):value(v){} + using base_uint = uint32_t; + unsigned_int( base_uint v = 0 ):value(v){} template unsigned_int( T v ):value(v){} @@ -14,22 +15,22 @@ struct unsigned_int { unsigned_int& operator=( int32_t v ) { value = v; return *this; } - uint32_t value; + base_uint value; - friend bool operator==( const unsigned_int& i, const uint32_t& v ) { return i.value == v; } - friend bool operator==( const uint32_t& i, const unsigned_int& v ) { return i == v.value; } + friend bool operator==( const unsigned_int& i, const base_uint& v ) { return i.value == v; } + friend bool operator==( const base_uint& i, const unsigned_int& v ) { return i == v.value; } friend bool operator==( const unsigned_int& i, const unsigned_int& v ) { return i.value == v.value; } - friend bool operator!=( const unsigned_int& i, const uint32_t& v ) { return i.value != v; } - friend bool operator!=( const uint32_t& i, const unsigned_int& v ) { return i != v.value; } + friend bool operator!=( const unsigned_int& i, const base_uint& v ) { return i.value != v; } + friend bool operator!=( const base_uint& i, const unsigned_int& v ) { return i != v.value; } friend bool operator!=( const unsigned_int& i, const unsigned_int& v ) { return i.value != v.value; } - friend bool operator<( const unsigned_int& i, const uint32_t& v ) { return i.value < v; } - friend bool operator<( const uint32_t& i, const unsigned_int& v ) { return i < v.value; } + friend bool operator<( const unsigned_int& i, const base_uint& v ) { return i.value < v; } + friend bool operator<( const base_uint& i, const unsigned_int& v ) { return i < v.value; } friend bool operator<( const unsigned_int& i, const unsigned_int& v ) { return i.value < v.value; } - friend bool operator>=( const unsigned_int& i, const uint32_t& v ) { return i.value >= v; } - friend bool operator>=( const uint32_t& i, const unsigned_int& v ) { return i >= v.value; } + friend bool operator>=( const unsigned_int& i, const base_uint& v ) { return i.value >= v; } + friend bool operator>=( const base_uint& i, const unsigned_int& v ) { return i >= v.value; } friend bool operator>=( const unsigned_int& i, const unsigned_int& v ) { return i.value >= v.value; } }; From e41b934c3b8770a7bec2d83a117ed4f290c3985f Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Sat, 18 Nov 2023 16:11:06 -0500 Subject: [PATCH 4/5] Update abi name in test: `currency_abi` -> `test_abi` --- unittests/abi_tests.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/unittests/abi_tests.cpp b/unittests/abi_tests.cpp index 5f5e9a90d4..20ac02d75e 100644 --- a/unittests/abi_tests.cpp +++ b/unittests/abi_tests.cpp @@ -533,7 +533,7 @@ fc::variant verify_type_round_trip_conversion( const abi_serializer& abis, const BOOST_AUTO_TEST_CASE(std_array_types) { try { - const char* currency_abi = R"=====( + const char* test_abi = R"=====( { "version": "eosio::abi/1.0", "types": [], @@ -551,7 +551,7 @@ BOOST_AUTO_TEST_CASE(std_array_types) } )====="; - auto abi = fc::json::from_string(currency_abi).as(); + auto abi = fc::json::from_string(test_abi).as(); abi_serializer abis(eosio_contract_abi(abi), abi_serializer::create_yield_function( max_serialization_time )); @@ -571,7 +571,7 @@ BOOST_AUTO_TEST_CASE(std_array_types) BOOST_AUTO_TEST_CASE(uint_types) { try { - const char* currency_abi = R"=====( + const char* test_abi = R"=====( { "version": "eosio::abi/1.0", "types": [], @@ -598,7 +598,7 @@ BOOST_AUTO_TEST_CASE(uint_types) } )====="; - auto abi = fc::json::from_string(currency_abi).as(); + auto abi = fc::json::from_string(test_abi).as(); abi_serializer abis(eosio_contract_abi(abi), abi_serializer::create_yield_function( max_serialization_time )); From 96ad7e436ca5af7842976d898c156dffe27715e6 Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Sat, 18 Nov 2023 16:24:59 -0500 Subject: [PATCH 5/5] Add test where fixed-size array is serialized with wrong number of values. Also replace the mouthful `abi_serializer::create_yield_function( max_serialization_time )` with `yield_fn()` --- unittests/abi_tests.cpp | 269 +++++++++++++++++++++++----------------- 1 file changed, 158 insertions(+), 111 deletions(-) diff --git a/unittests/abi_tests.cpp b/unittests/abi_tests.cpp index 20ac02d75e..210fcdcb19 100644 --- a/unittests/abi_tests.cpp +++ b/unittests/abi_tests.cpp @@ -51,21 +51,23 @@ static fc::time_point get_deadline() { return fc::time_point::now().safe_add(max_serialization_time); } +static auto yield_fn() { return abi_serializer::create_yield_function( max_serialization_time ); } + // verify that round trip conversion, via bytes, reproduces the exact same data fc::variant verify_byte_round_trip_conversion( const abi_serializer& abis, const type_name& type, const fc::variant& var ) { - auto bytes = abis.variant_to_binary(type, var, abi_serializer::create_yield_function( max_serialization_time )); + auto bytes = abis.variant_to_binary(type, var, yield_fn()); auto b = abis.variant_to_binary(type, var, max_serialization_time ); BOOST_TEST( b == bytes ); - auto var2 = abis.binary_to_variant(type, bytes, abi_serializer::create_yield_function( max_serialization_time )); + auto var2 = abis.binary_to_variant(type, bytes, yield_fn()); auto var3 = abis.binary_to_variant(type, b, max_serialization_time); std::string r2 = fc::json::to_string(var2, get_deadline()); std::string r3 = fc::json::to_string(var3, get_deadline()); BOOST_TEST( r2 == r3 ); - auto bytes2 = abis.variant_to_binary(type, var2, abi_serializer::create_yield_function( max_serialization_time )); + auto bytes2 = abis.variant_to_binary(type, var2, yield_fn()); auto bytes3 = abis.variant_to_binary(type, var3, max_serialization_time); BOOST_TEST( bytes2 == bytes3 ); @@ -77,15 +79,15 @@ fc::variant verify_byte_round_trip_conversion( const abi_serializer& abis, const void verify_round_trip_conversion( const abi_serializer& abis, const type_name& type, const std::string& json, const std::string& hex, const std::string& expected_json ) { auto var = fc::json::from_string(json); - auto bytes = abis.variant_to_binary(type, var, abi_serializer::create_yield_function( max_serialization_time )); + auto bytes = abis.variant_to_binary(type, var, yield_fn()); BOOST_REQUIRE_EQUAL(fc::to_hex(bytes), hex); auto b = abis.variant_to_binary(type, var, max_serialization_time); BOOST_REQUIRE_EQUAL(fc::to_hex(b), hex); - auto var2 = abis.binary_to_variant(type, bytes, abi_serializer::create_yield_function( max_serialization_time )); + auto var2 = abis.binary_to_variant(type, bytes, yield_fn()); BOOST_REQUIRE_EQUAL(fc::json::to_string(var2, get_deadline()), expected_json); auto var3 = abis.binary_to_variant(type, b, max_serialization_time ); BOOST_REQUIRE_EQUAL(fc::json::to_string(var3, get_deadline()), expected_json); - auto bytes2 = abis.variant_to_binary(type, var2, abi_serializer::create_yield_function( max_serialization_time )); + auto bytes2 = abis.variant_to_binary(type, var2, yield_fn()); BOOST_REQUIRE_EQUAL(fc::to_hex(bytes2), hex); auto b2 = abis.variant_to_binary(type, var3, max_serialization_time); BOOST_REQUIRE_EQUAL(fc::to_hex(b2), hex); @@ -99,7 +101,7 @@ void verify_round_trip_conversion( const abi_serializer& abis, const type_name& auto get_resolver(const abi_def& abi = abi_def()) { return [&abi](const account_name &name) -> std::optional { - return abi_serializer(eosio_contract_abi(abi), abi_serializer::create_yield_function( max_serialization_time )); + return abi_serializer(eosio_contract_abi(abi), yield_fn()); }; } @@ -108,17 +110,17 @@ template fc::variant verify_type_round_trip_conversion( const abi_serializer& abis, const type_name& type, const fc::variant& var ) { try { - auto bytes = abis.variant_to_binary(type, var, abi_serializer::create_yield_function( max_serialization_time )); + auto bytes = abis.variant_to_binary(type, var, yield_fn()); auto b = abis.variant_to_binary(type, var, max_serialization_time); T obj; - abi_serializer::from_variant(var, obj, get_resolver(), abi_serializer::create_yield_function( max_serialization_time )); + abi_serializer::from_variant(var, obj, get_resolver(), yield_fn()); T obj2; abi_serializer::from_variant(var, obj2, get_resolver(), max_serialization_time); fc::variant var2; - abi_serializer::to_variant(obj, var2, get_resolver(), abi_serializer::create_yield_function( max_serialization_time )); + abi_serializer::to_variant(obj, var2, get_resolver(), yield_fn()); fc::variant var3; abi_serializer::to_variant(obj2, var3, get_resolver(), max_serialization_time); @@ -127,7 +129,7 @@ fc::variant verify_type_round_trip_conversion( const abi_serializer& abis, const std::string r3 = fc::json::to_string(var3, get_deadline()); BOOST_TEST( r2 == r3 ); - auto bytes2 = abis.variant_to_binary(type, var2, abi_serializer::create_yield_function( max_serialization_time )); + auto bytes2 = abis.variant_to_binary(type, var2, yield_fn()); auto b3 = abis.variant_to_binary(type, var3, max_serialization_time); BOOST_TEST( bytes2 == b3 ); BOOST_TEST( b == b3 ); @@ -553,7 +555,7 @@ BOOST_AUTO_TEST_CASE(std_array_types) auto abi = fc::json::from_string(test_abi).as(); - abi_serializer abis(eosio_contract_abi(abi), abi_serializer::create_yield_function( max_serialization_time )); + abi_serializer abis(eosio_contract_abi(abi), yield_fn()); const char* test_data = R"=====( { @@ -563,10 +565,55 @@ BOOST_AUTO_TEST_CASE(std_array_types) auto var = fc::json::from_string(test_data); - verify_byte_round_trip_conversion(abi_serializer{std::move(abi), abi_serializer::create_yield_function( max_serialization_time )}, "test", var); + verify_byte_round_trip_conversion(abi_serializer{std::move(abi), yield_fn()}, "test", var); } FC_LOG_AND_RETHROW() } +BOOST_AUTO_TEST_CASE(std_array_types_short) +{ try { + + const char* test_abi = R"=====( + { + "version": "eosio::abi/1.0", + "types": [], + "structs": [{ + "name": "test", + "base": "", + "fields": [{ + "name": "a", + "type": "uint8[5]" + }] + }], + "actions": [], + "tables": [], + "ricardian_clauses": [] + } + )====="; + + auto abi = fc::json::from_string(test_abi).as(); + + abi_serializer abis(eosio_contract_abi(abi), yield_fn()); + + const char* test_data = R"=====( + { + "a" : [1, 2, 3, 4] + } + )====="; + + // Check that providing the wrong number of values for a fixed size array type triggers an exception + // ------------------------------------------------------------------------------------------------- + auto is_assert_exception = [](const auto& e) -> bool { + wlog(e.to_string()); return true; + }; + + auto var = fc::json::from_string(test_data); + + BOOST_CHECK_EXCEPTION( verify_byte_round_trip_conversion(abi_serializer{std::move(abi), yield_fn()}, "test", var), + pack_exception, is_assert_exception ); + +} FC_LOG_AND_RETHROW() } + + BOOST_AUTO_TEST_CASE(uint_types) { try { @@ -600,7 +647,7 @@ BOOST_AUTO_TEST_CASE(uint_types) auto abi = fc::json::from_string(test_abi).as(); - abi_serializer abis(eosio_contract_abi(abi), abi_serializer::create_yield_function( max_serialization_time )); + abi_serializer abis(eosio_contract_abi(abi), yield_fn()); const char* test_data = R"=====( { @@ -613,7 +660,7 @@ BOOST_AUTO_TEST_CASE(uint_types) auto var = fc::json::from_string(test_data); - verify_byte_round_trip_conversion(abi_serializer{std::move(abi), abi_serializer::create_yield_function( max_serialization_time )}, "transfer", var); + verify_byte_round_trip_conversion(abi_serializer{std::move(abi), yield_fn()}, "transfer", var); } FC_LOG_AND_RETHROW() } @@ -623,7 +670,7 @@ BOOST_AUTO_TEST_CASE(general) auto abi = eosio_contract_abi(fc::json::from_string(my_abi).as()); - abi_serializer abis(abi_def(abi), abi_serializer::create_yield_function( max_serialization_time )); + abi_serializer abis(abi_def(abi), yield_fn()); const char *my_other = R"=====( { @@ -822,7 +869,7 @@ BOOST_AUTO_TEST_CASE(general) )====="; auto var = fc::json::from_string(my_other); - verify_byte_round_trip_conversion(abi_serializer{std::move(abi), abi_serializer::create_yield_function( max_serialization_time )}, "A", var); + verify_byte_round_trip_conversion(abi_serializer{std::move(abi), yield_fn()}, "A", var); } FC_LOG_AND_RETHROW() } @@ -873,18 +920,18 @@ BOOST_AUTO_TEST_CASE(abi_cycle) auto is_assert_exception = [](const auto& e) -> bool { wlog(e.to_string()); return true; }; - BOOST_CHECK_EXCEPTION( abi_serializer abis(std::move(abi), abi_serializer::create_yield_function( max_serialization_time )), duplicate_abi_type_def_exception, is_assert_exception); + BOOST_CHECK_EXCEPTION( abi_serializer abis(std::move(abi), yield_fn()), duplicate_abi_type_def_exception, is_assert_exception); abi = fc::json::from_string(struct_cycle_abi).as(); abi_serializer abis; - BOOST_CHECK_EXCEPTION( abis.set_abi(std::move(abi), abi_serializer::create_yield_function( max_serialization_time )), abi_circular_def_exception, is_assert_exception ); + BOOST_CHECK_EXCEPTION( abis.set_abi(std::move(abi), yield_fn()), abi_circular_def_exception, is_assert_exception ); } FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE(linkauth_test) { try { - abi_serializer abis(eosio_contract_abi(abi_def()), abi_serializer::create_yield_function( max_serialization_time )); + abi_serializer abis(eosio_contract_abi(abi_def()), yield_fn()); BOOST_CHECK(true); const char* test_data = R"=====( @@ -918,7 +965,7 @@ BOOST_AUTO_TEST_CASE(linkauth_test) BOOST_AUTO_TEST_CASE(unlinkauth_test) { try { - abi_serializer abis(eosio_contract_abi(abi_def()), abi_serializer::create_yield_function( max_serialization_time )); + abi_serializer abis(eosio_contract_abi(abi_def()), yield_fn()); BOOST_CHECK(true); const char* test_data = R"=====( @@ -949,7 +996,7 @@ BOOST_AUTO_TEST_CASE(unlinkauth_test) BOOST_AUTO_TEST_CASE(updateauth_test) { try { - abi_serializer abis(eosio_contract_abi(abi_def()), abi_serializer::create_yield_function( max_serialization_time )); + abi_serializer abis(eosio_contract_abi(abi_def()), yield_fn()); BOOST_CHECK(true); const char* test_data = R"=====( @@ -1019,7 +1066,7 @@ BOOST_AUTO_TEST_CASE(updateauth_test) BOOST_AUTO_TEST_CASE(deleteauth_test) { try { - abi_serializer abis(eosio_contract_abi(abi_def()), abi_serializer::create_yield_function( max_serialization_time )); + abi_serializer abis(eosio_contract_abi(abi_def()), yield_fn()); BOOST_CHECK(true); const char* test_data = R"=====( @@ -1047,7 +1094,7 @@ BOOST_AUTO_TEST_CASE(deleteauth_test) BOOST_AUTO_TEST_CASE(newaccount_test) { try { - abi_serializer abis(eosio_contract_abi(abi_def()), abi_serializer::create_yield_function( max_serialization_time )); + abi_serializer abis(eosio_contract_abi(abi_def()), yield_fn()); BOOST_CHECK(true); const char* test_data = R"=====( @@ -1157,7 +1204,7 @@ BOOST_AUTO_TEST_CASE(newaccount_test) BOOST_AUTO_TEST_CASE(setcode_test) { try { - abi_serializer abis(eosio_contract_abi(abi_def()), abi_serializer::create_yield_function( max_serialization_time )); + abi_serializer abis(eosio_contract_abi(abi_def()), yield_fn()); const char* test_data = R"=====( { @@ -1320,7 +1367,7 @@ BOOST_AUTO_TEST_CASE(setabi_test) auto v = fc::json::from_string(abi_def_abi); - abi_serializer abis(eosio_contract_abi(v.as()), abi_serializer::create_yield_function( max_serialization_time )); + abi_serializer abis(eosio_contract_abi(v.as()), yield_fn()); const char* abi_string = R"=====( { @@ -1642,12 +1689,12 @@ BOOST_AUTO_TEST_CASE(packed_transaction) } )====="; fc::variant var; - abi_serializer::to_variant(packed_txn, var, get_resolver(fc::json::from_string(packed_transaction_abi).as()), abi_serializer::create_yield_function( max_serialization_time )); + abi_serializer::to_variant(packed_txn, var, get_resolver(fc::json::from_string(packed_transaction_abi).as()), yield_fn()); fc::variant var2; abi_serializer::to_variant(packed_txn, var2, get_resolver(fc::json::from_string(packed_transaction_abi).as()), max_serialization_time); chain::packed_transaction packed_txn2; - abi_serializer::from_variant(var, packed_txn2, get_resolver(fc::json::from_string(packed_transaction_abi).as()), abi_serializer::create_yield_function( max_serialization_time )); + abi_serializer::from_variant(var, packed_txn2, get_resolver(fc::json::from_string(packed_transaction_abi).as()), yield_fn()); chain::packed_transaction packed_txn3; abi_serializer::from_variant(var2, packed_txn3, get_resolver(fc::json::from_string(packed_transaction_abi).as()), max_serialization_time); @@ -1738,7 +1785,7 @@ BOOST_AUTO_TEST_CASE(abi_type_repeat) auto abi = eosio_contract_abi(fc::json::from_string(repeat_abi).as()); auto is_table_exception = [](fc::exception const & e) -> bool { return e.to_detail_string().find("type already exists") != std::string::npos; }; - BOOST_CHECK_EXCEPTION( abi_serializer abis(std::move(abi), abi_serializer::create_yield_function( max_serialization_time )), duplicate_abi_type_def_exception, is_table_exception ); + BOOST_CHECK_EXCEPTION( abi_serializer abis(std::move(abi), yield_fn()), duplicate_abi_type_def_exception, is_table_exception ); } FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE(abi_struct_repeat) @@ -1795,7 +1842,7 @@ BOOST_AUTO_TEST_CASE(abi_struct_repeat) )====="; auto abi = eosio_contract_abi(fc::json::from_string(repeat_abi).as()); - BOOST_CHECK_THROW( abi_serializer abis(std::move(abi), abi_serializer::create_yield_function( max_serialization_time )), duplicate_abi_struct_def_exception ); + BOOST_CHECK_THROW( abi_serializer abis(std::move(abi), yield_fn()), duplicate_abi_struct_def_exception ); } FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE(abi_action_repeat) @@ -1855,7 +1902,7 @@ BOOST_AUTO_TEST_CASE(abi_action_repeat) )====="; auto abi = eosio_contract_abi(fc::json::from_string(repeat_abi).as()); - BOOST_CHECK_THROW( abi_serializer abis(std::move(abi), abi_serializer::create_yield_function( max_serialization_time )), duplicate_abi_action_def_exception ); + BOOST_CHECK_THROW( abi_serializer abis(std::move(abi), yield_fn()), duplicate_abi_action_def_exception ); } FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE(abi_table_repeat) @@ -1918,7 +1965,7 @@ BOOST_AUTO_TEST_CASE(abi_table_repeat) )====="; auto abi = eosio_contract_abi(fc::json::from_string(repeat_abi).as()); - BOOST_CHECK_THROW( abi_serializer abis(std::move(abi), abi_serializer::create_yield_function( max_serialization_time )), duplicate_abi_table_def_exception ); + BOOST_CHECK_THROW( abi_serializer abis(std::move(abi), yield_fn()), duplicate_abi_table_def_exception ); } FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE(abi_type_def) @@ -1957,9 +2004,9 @@ BOOST_AUTO_TEST_CASE(abi_type_def) } )====="; - abi_serializer abis(fc::json::from_string(repeat_abi).as(), abi_serializer::create_yield_function( max_serialization_time )); - BOOST_CHECK(abis.is_type("name", abi_serializer::create_yield_function( max_serialization_time ))); - BOOST_CHECK(abis.is_type("account_name", abi_serializer::create_yield_function( max_serialization_time ))); + abi_serializer abis(fc::json::from_string(repeat_abi).as(), yield_fn()); + BOOST_CHECK(abis.is_type("name", yield_fn())); + BOOST_CHECK(abis.is_type("account_name", yield_fn())); const char* test_data = R"=====( { @@ -2014,7 +2061,7 @@ BOOST_AUTO_TEST_CASE(abi_type_loop) )====="; auto is_type_exception = [](fc::exception const & e) -> bool { return e.to_detail_string().find("type already exists") != std::string::npos; }; - BOOST_CHECK_EXCEPTION( abi_serializer abis(fc::json::from_string(repeat_abi).as(), abi_serializer::create_yield_function( max_serialization_time )), duplicate_abi_type_def_exception, is_type_exception ); + BOOST_CHECK_EXCEPTION( abi_serializer abis(fc::json::from_string(repeat_abi).as(), yield_fn()), duplicate_abi_type_def_exception, is_type_exception ); } FC_LOG_AND_RETHROW() } @@ -2058,7 +2105,7 @@ BOOST_AUTO_TEST_CASE(abi_std_optional) } )====="; - abi_serializer abis(fc::json::from_string(repeat_abi).as(), abi_serializer::create_yield_function( max_serialization_time )); + abi_serializer abis(fc::json::from_string(repeat_abi).as(), yield_fn()); { // check conversion when all optional members are provided std::string test_data = R"=====( @@ -2162,7 +2209,7 @@ BOOST_AUTO_TEST_CASE(abi_type_redefine) )====="; auto is_type_exception = [](fc::exception const & e) -> bool { return e.to_detail_string().find("Circular reference in type account_name") != std::string::npos; }; - BOOST_CHECK_EXCEPTION( abi_serializer abis(fc::json::from_string(repeat_abi).as(), abi_serializer::create_yield_function( max_serialization_time )), abi_circular_def_exception, is_type_exception ); + BOOST_CHECK_EXCEPTION( abi_serializer abis(fc::json::from_string(repeat_abi).as(), yield_fn()), abi_circular_def_exception, is_type_exception ); } FC_LOG_AND_RETHROW() } @@ -2184,7 +2231,7 @@ BOOST_AUTO_TEST_CASE(abi_type_redefine_to_name) )====="; auto is_type_exception = [](fc::exception const & e) -> bool { return e.to_detail_string().find("type already exists") != std::string::npos; }; - BOOST_CHECK_EXCEPTION( abi_serializer abis(fc::json::from_string(repeat_abi).as(), abi_serializer::create_yield_function( max_serialization_time )), duplicate_abi_type_def_exception, is_type_exception ); + BOOST_CHECK_EXCEPTION( abi_serializer abis(fc::json::from_string(repeat_abi).as(), yield_fn()), duplicate_abi_type_def_exception, is_type_exception ); } FC_LOG_AND_RETHROW() } @@ -2210,7 +2257,7 @@ BOOST_AUTO_TEST_CASE(abi_type_nested_in_vector) } )====="; - BOOST_CHECK_THROW( abi_serializer abis(fc::json::from_string(repeat_abi).as(), abi_serializer::create_yield_function( max_serialization_time )), parse_error_exception ); + BOOST_CHECK_THROW( abi_serializer abis(fc::json::from_string(repeat_abi).as(), yield_fn()), parse_error_exception ); } FC_LOG_AND_RETHROW() } @@ -2282,14 +2329,14 @@ BOOST_AUTO_TEST_CASE(abi_large_array) } )====="; - abi_serializer abis( fc::json::from_string( abi_str ).as(), abi_serializer::create_yield_function( max_serialization_time ) ); + abi_serializer abis( fc::json::from_string( abi_str ).as(), yield_fn() ); // indicate a very large array, but don't actually provide a large array bytes bin = {static_cast(0xff), static_cast(0xff), static_cast(0xff), static_cast(0xff), static_cast(0x08)}; - BOOST_CHECK_THROW( abis.binary_to_variant( "hi[]", bin, abi_serializer::create_yield_function( max_serialization_time ) );, fc::exception ); + BOOST_CHECK_THROW( abis.binary_to_variant( "hi[]", bin, yield_fn() );, fc::exception ); BOOST_CHECK_THROW( abis.binary_to_variant( "hi[]", bin, max_serialization_time );, fc::exception ); } FC_LOG_AND_RETHROW() @@ -2334,7 +2381,7 @@ BOOST_AUTO_TEST_CASE(abi_is_type_recursion) } )====="; - BOOST_CHECK_THROW( abi_serializer abis(fc::json::from_string(abi_str).as(), abi_serializer::create_yield_function( max_serialization_time )), fc::exception ); + BOOST_CHECK_THROW( abi_serializer abis(fc::json::from_string(abi_str).as(), yield_fn()), fc::exception ); } FC_LOG_AND_RETHROW() } @@ -2401,11 +2448,11 @@ BOOST_AUTO_TEST_CASE(abi_recursive_structs) } )====="; - abi_serializer abis(fc::json::from_string(abi_str).as(), abi_serializer::create_yield_function( max_serialization_time )); + abi_serializer abis(fc::json::from_string(abi_str).as(), yield_fn()); string hi_data = "{\"user\":\"eosio\"}"; - auto bin = abis.variant_to_binary("hi2", fc::json::from_string(hi_data), abi_serializer::create_yield_function( max_serialization_time )); + auto bin = abis.variant_to_binary("hi2", fc::json::from_string(hi_data), yield_fn()); auto bin2 = abis.variant_to_binary("hi2", fc::json::from_string(hi_data), max_serialization_time); - BOOST_CHECK_THROW( abis.binary_to_variant("hi", bin, abi_serializer::create_yield_function( max_serialization_time ));, fc::exception ); + BOOST_CHECK_THROW( abis.binary_to_variant("hi", bin, yield_fn());, fc::exception ); BOOST_CHECK_THROW( abis.binary_to_variant("hi", bin2, max_serialization_time);, fc::exception ); } FC_LOG_AND_RETHROW() @@ -2415,9 +2462,9 @@ BOOST_AUTO_TEST_CASE(abi_recursive_structs) BOOST_AUTO_TEST_CASE(abi_very_deep_structs) { try { - abi_serializer abis( fc::json::from_string( large_nested_abi ).as(), abi_serializer::create_yield_function( max_serialization_time ) ); + abi_serializer abis( fc::json::from_string( large_nested_abi ).as(), yield_fn() ); string hi_data = "{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":{\"f1\":0}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}"; - BOOST_CHECK_THROW( abis.variant_to_binary( "s98", fc::json::from_string( hi_data ), abi_serializer::create_yield_function( max_serialization_time ) ), fc::exception ); + BOOST_CHECK_THROW( abis.variant_to_binary( "s98", fc::json::from_string( hi_data ), yield_fn() ), fc::exception ); BOOST_CHECK_THROW( abis.variant_to_binary( "s98", fc::json::from_string( hi_data ), max_serialization_time ), fc::exception ); } FC_LOG_AND_RETHROW() } @@ -2436,7 +2483,7 @@ BOOST_AUTO_TEST_CASE(abi_deep_structs_validate) { try { BOOST_CHECK_THROW( - abi_serializer abis( fc::json::from_string( deep_nested_abi ).as(), abi_serializer::create_yield_function( max_serialization_time ) ), + abi_serializer abis( fc::json::from_string( deep_nested_abi ).as(), yield_fn() ), fc::exception ); } FC_LOG_AND_RETHROW() } @@ -2567,22 +2614,22 @@ BOOST_AUTO_TEST_CASE(variants) // json -> variant -> abi_def -> bin auto bin = fc::raw::pack(fc::json::from_string(variant_abi).as()); // bin -> abi_def -> variant -> abi_def - abi_serializer abis(fc::variant(fc::raw::unpack(bin)).as(), abi_serializer::create_yield_function( max_serialization_time ) ); + abi_serializer abis(fc::variant(fc::raw::unpack(bin)).as(), yield_fn() ); // duplicate variant definition detected - BOOST_CHECK_THROW( abi_serializer( fc::json::from_string(duplicate_variant_abi).as(), abi_serializer::create_yield_function( max_serialization_time ) ), duplicate_abi_variant_def_exception ); + BOOST_CHECK_THROW( abi_serializer( fc::json::from_string(duplicate_variant_abi).as(), yield_fn() ), duplicate_abi_variant_def_exception ); // invalid_type_inside_abi - BOOST_CHECK_THROW( abi_serializer( fc::json::from_string(variant_abi_invalid_type).as(), abi_serializer::create_yield_function( max_serialization_time ) ), invalid_type_inside_abi ); + BOOST_CHECK_THROW( abi_serializer( fc::json::from_string(variant_abi_invalid_type).as(), yield_fn() ), invalid_type_inside_abi ); // expected array containing variant - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("v1", fc::json::from_string(R"(9)"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("v1", fc::json::from_string(R"(9)"), yield_fn()), pack_exception, fc_exception_message_starts_with("Expected input to be an array of two items while processing variant 'v1'") ); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("v1", fc::json::from_string(R"([4])"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("v1", fc::json::from_string(R"([4])"), yield_fn()), pack_exception, fc_exception_message_starts_with("Expected input to be an array of two items while processing variant 'v1") ); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("v1", fc::json::from_string(R"([4, 5])"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("v1", fc::json::from_string(R"([4, 5])"), yield_fn()), pack_exception, fc_exception_message_starts_with("Encountered non-string as first item of input array while processing variant 'v1") ); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("v1", fc::json::from_string(R"(["4", 5, 6])"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("v1", fc::json::from_string(R"(["4", 5, 6])"), yield_fn()), pack_exception, fc_exception_message_starts_with("Expected input to be an array of two items while processing variant 'v1'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("v1", fc::json::from_string(R"(9)"), max_serialization_time), @@ -2595,7 +2642,7 @@ BOOST_AUTO_TEST_CASE(variants) pack_exception, fc_exception_message_starts_with("Expected input to be an array of two items while processing variant 'v1'") ); // type is not valid within this variant - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("v1", fc::json::from_string(R"(["int9", 21])"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("v1", fc::json::from_string(R"(["int9", 21])"), yield_fn()), pack_exception, fc_exception_message_starts_with("Specified type 'int9' in input array is not valid within the variant 'v1'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("v1", fc::json::from_string(R"(["int9", 21])"), max_serialization_time), pack_exception, fc_exception_message_starts_with("Specified type 'int9' in input array is not valid within the variant 'v1'") ); @@ -2628,7 +2675,7 @@ BOOST_AUTO_TEST_CASE(aliased_variants) // json -> variant -> abi_def -> bin auto bin = fc::raw::pack(fc::json::from_string(aliased_variant).as()); // bin -> abi_def -> variant -> abi_def - abi_serializer abis(fc::variant(fc::raw::unpack(bin)).as(), abi_serializer::create_yield_function( max_serialization_time ) ); + abi_serializer abis(fc::variant(fc::raw::unpack(bin)).as(), yield_fn() ); verify_round_trip_conversion(abis, "foo", R"(["int8",21])", "0015"); } FC_LOG_AND_RETHROW() @@ -2654,7 +2701,7 @@ BOOST_AUTO_TEST_CASE(variant_of_aliases) // json -> variant -> abi_def -> bin auto bin = fc::raw::pack(fc::json::from_string(aliased_variant).as()); // bin -> abi_def -> variant -> abi_def - abi_serializer abis(fc::variant(fc::raw::unpack(bin)).as(), abi_serializer::create_yield_function( max_serialization_time ) ); + abi_serializer abis(fc::variant(fc::raw::unpack(bin)).as(), yield_fn() ); verify_round_trip_conversion(abis, "foo", R"(["foo_0",21])", "0015"); } FC_LOG_AND_RETHROW() @@ -2685,16 +2732,16 @@ BOOST_AUTO_TEST_CASE(extend) // Such a check is not yet implemented during validation, but it can check during serialization. try { - abi_serializer abis(fc::json::from_string(abi).as(), abi_serializer::create_yield_function( max_serialization_time ) ); + abi_serializer abis(fc::json::from_string(abi).as(), yield_fn() ); // missing i1 - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s", fc::json::from_string(R"({"i0":5})"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s", fc::json::from_string(R"({"i0":5})"), yield_fn()), pack_exception, fc_exception_message_starts_with("Missing field 'i1' in input object while processing struct") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s", fc::json::from_string(R"({"i0":5})"), max_serialization_time), pack_exception, fc_exception_message_starts_with("Missing field 'i1' in input object while processing struct") ); // Unexpected 'a' - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s", fc::json::from_string(R"({"i0":5,"i1":6,"a":[8,9,10]})"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s", fc::json::from_string(R"({"i0":5,"i1":6,"a":[8,9,10]})"), yield_fn()), pack_exception, fc_exception_message_starts_with("Unexpected field 'a' found in input object while processing struct") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s", fc::json::from_string(R"({"i0":5,"i1":6,"a":[8,9,10]})"), max_serialization_time), pack_exception, fc_exception_message_starts_with("Unexpected field 'a' found in input object while processing struct") ); @@ -2711,7 +2758,7 @@ BOOST_AUTO_TEST_CASE(extend) verify_round_trip_conversion(abis, "s", R"([5,6,7,[8,9,10],null])", "0506070308090a00", R"({"i0":5,"i1":6,"i2":7,"a":[8,9,10],"o":null})"); verify_round_trip_conversion(abis, "s", R"([5,6,7,[8,9,10],31])", "0506070308090a011f", R"({"i0":5,"i1":6,"i2":7,"a":[8,9,10],"o":31})"); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s2", fc::json::from_string(R"({"i0":1})"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s2", fc::json::from_string(R"({"i0":1})"), yield_fn()), abi_exception, fc_exception_message_starts_with("Encountered field 'i2' without binary extension designation while processing struct") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s2", fc::json::from_string(R"({"i0":1})"), max_serialization_time), abi_exception, fc_exception_message_starts_with("Encountered field 'i2' without binary extension designation while processing struct") ); @@ -2723,11 +2770,11 @@ BOOST_AUTO_TEST_CASE(extend) BOOST_AUTO_TEST_CASE(version) { try { - BOOST_CHECK_THROW( abi_serializer(fc::json::from_string(R"({})").as(), abi_serializer::create_yield_function( max_serialization_time )), unsupported_abi_version_exception ); - BOOST_CHECK_THROW( abi_serializer(fc::json::from_string(R"({"version": ""})").as(), abi_serializer::create_yield_function( max_serialization_time )), unsupported_abi_version_exception ); - BOOST_CHECK_THROW( abi_serializer(fc::json::from_string(R"({"version": "eosio::abi/9.0"})").as(), abi_serializer::create_yield_function( max_serialization_time )), unsupported_abi_version_exception ); - abi_serializer(fc::json::from_string(R"({"version": "eosio::abi/1.0"})").as(), abi_serializer::create_yield_function( max_serialization_time )); - abi_serializer(fc::json::from_string(R"({"version": "eosio::abi/1.1"})").as(), abi_serializer::create_yield_function( max_serialization_time )); + BOOST_CHECK_THROW( abi_serializer(fc::json::from_string(R"({})").as(), yield_fn()), unsupported_abi_version_exception ); + BOOST_CHECK_THROW( abi_serializer(fc::json::from_string(R"({"version": ""})").as(), yield_fn()), unsupported_abi_version_exception ); + BOOST_CHECK_THROW( abi_serializer(fc::json::from_string(R"({"version": "eosio::abi/9.0"})").as(), yield_fn()), unsupported_abi_version_exception ); + abi_serializer(fc::json::from_string(R"({"version": "eosio::abi/1.0"})").as(), yield_fn()); + abi_serializer(fc::json::from_string(R"({"version": "eosio::abi/1.1"})").as(), yield_fn()); } FC_LOG_AND_RETHROW() } @@ -2747,14 +2794,14 @@ BOOST_AUTO_TEST_CASE(abi_serialize_incomplete_json_array) })"; try { - abi_serializer abis( fc::json::from_string(abi).as(), abi_serializer::create_yield_function( max_serialization_time ) ); + abi_serializer abis( fc::json::from_string(abi).as(), yield_fn() ); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s", fc::json::from_string(R"([])"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s", fc::json::from_string(R"([])"), yield_fn()), pack_exception, fc_exception_message_starts_with("Early end to input array specifying the fields of struct") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s", fc::json::from_string(R"([])"), max_serialization_time), pack_exception, fc_exception_message_starts_with("Early end to input array specifying the fields of struct") ); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s", fc::json::from_string(R"([1,2])"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s", fc::json::from_string(R"([1,2])"), yield_fn()), pack_exception, fc_exception_message_starts_with("Early end to input array specifying the fields of struct") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s", fc::json::from_string(R"([1,2])"), max_serialization_time), pack_exception, fc_exception_message_starts_with("Early end to input array specifying the fields of struct") ); @@ -2783,14 +2830,14 @@ BOOST_AUTO_TEST_CASE(abi_serialize_incomplete_json_object) })"; try { - abi_serializer abis( fc::json::from_string(abi).as(), abi_serializer::create_yield_function( max_serialization_time ) ); + abi_serializer abis( fc::json::from_string(abi).as(), yield_fn() ); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s2", fc::json::from_string(R"({})"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s2", fc::json::from_string(R"({})"), yield_fn()), pack_exception, fc_exception_message_starts_with("Missing field 'f0' in input object") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s2", fc::json::from_string(R"({})"), max_serialization_time), pack_exception, fc_exception_message_starts_with("Missing field 'f0' in input object") ); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s2", fc::json::from_string(R"({"f0":{"i0":1}})"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s2", fc::json::from_string(R"({"f0":{"i0":1}})"), yield_fn()), pack_exception, fc_exception_message_starts_with("Missing field 'i1' in input object") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s2", fc::json::from_string(R"({"f0":{"i0":1}})"), max_serialization_time), pack_exception, fc_exception_message_starts_with("Missing field 'i1' in input object") ); @@ -2818,9 +2865,9 @@ BOOST_AUTO_TEST_CASE(abi_serialize_json_mismatching_type) })"; try { - abi_serializer abis( fc::json::from_string(abi).as(), abi_serializer::create_yield_function( max_serialization_time ) ); + abi_serializer abis( fc::json::from_string(abi).as(), yield_fn() ); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s2", fc::json::from_string(R"({"f0":1,"i1":2})"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s2", fc::json::from_string(R"({"f0":1,"i1":2})"), yield_fn()), pack_exception, fc_exception_message_is("Unexpected input encountered while processing struct 's2.f0'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s2", fc::json::from_string(R"({"f0":1,"i1":2})"), max_serialization_time), pack_exception, fc_exception_message_is("Unexpected input encountered while processing struct 's2.f0'") ); @@ -2845,9 +2892,9 @@ BOOST_AUTO_TEST_CASE(abi_serialize_json_empty_name) })"; try { - abi_serializer abis( fc::json::from_string(abi).as(), abi_serializer::create_yield_function( max_serialization_time ) ); + abi_serializer abis( fc::json::from_string(abi).as(), yield_fn() ); - auto bin1 = abis.variant_to_binary("s1", fc::json::from_string(R"({"":1})"), abi_serializer::create_yield_function( max_serialization_time )); + auto bin1 = abis.variant_to_binary("s1", fc::json::from_string(R"({"":1})"), yield_fn()); auto bin2 = abis.variant_to_binary("s1", fc::json::from_string(R"({"":1})"), max_serialization_time); verify_round_trip_conversion(abis, "s1", R"({"":1})", "01"); @@ -2897,53 +2944,53 @@ BOOST_AUTO_TEST_CASE(abi_serialize_detailed_error_messages) })"; try { - abi_serializer abis( fc::json::from_string(abi).as(), abi_serializer::create_yield_function( max_serialization_time ) ); + abi_serializer abis( fc::json::from_string(abi).as(), yield_fn() ); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("bar", fc::json::from_string(R"({"f0":{"i0":1},"i2":3})"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("bar", fc::json::from_string(R"({"f0":{"i0":1},"i2":3})"), yield_fn()), pack_exception, fc_exception_message_is("Missing field 'i1' in input object while processing struct 's2.f0'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("bar", fc::json::from_string(R"({"f0":{"i0":1},"i2":3})"), max_serialization_time), pack_exception, fc_exception_message_is("Missing field 'i1' in input object while processing struct 's2.f0'") ); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s3", fc::json::from_string(R"({"i0":1,"i2":3})"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s3", fc::json::from_string(R"({"i0":1,"i2":3})"), yield_fn()), pack_exception, fc_exception_message_is("Missing field 'i1' in input object while processing struct 's3'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s3", fc::json::from_string(R"({"i0":1,"i2":3})"), max_serialization_time), pack_exception, fc_exception_message_is("Missing field 'i1' in input object while processing struct 's3'") ); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s3", fc::json::from_string(R"({"i0":1,"i1":2,"i2":3,"f3":["s2",{}]})"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s3", fc::json::from_string(R"({"i0":1,"i1":2,"i2":3,"f3":["s2",{}]})"), yield_fn()), pack_exception, fc_exception_message_is("Specified type 's2' in input array is not valid within the variant 's3.f3'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s3", fc::json::from_string(R"({"i0":1,"i1":2,"i2":3,"f3":["s2",{}]})"), max_serialization_time), pack_exception, fc_exception_message_is("Specified type 's2' in input array is not valid within the variant 's3.f3'") ); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s3", fc::json::from_string(R"({"i0":1,"i1":2,"i2":3,"f3":["bar",{"f0":{"i0":11},"i2":13}]})"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s3", fc::json::from_string(R"({"i0":1,"i1":2,"i2":3,"f3":["bar",{"f0":{"i0":11},"i2":13}]})"), yield_fn()), pack_exception, fc_exception_message_is("Missing field 'i1' in input object while processing struct 's3.f3..f0'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s3", fc::json::from_string(R"({"i0":1,"i1":2,"i2":3,"f3":["bar",{"f0":{"i0":11},"i2":13}]})"), max_serialization_time), pack_exception, fc_exception_message_is("Missing field 'i1' in input object while processing struct 's3.f3..f0'") ); verify_round_trip_conversion(abis, "s3", R"({"i0":1,"i1":2,"i2":3,"f3":["bar",{"f0":{"i0":11,"i1":12},"i2":13}]})", "010203010b0c0d"); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("v1", fc::json::from_string(R"(["s3",{"i0":1,"i1":2,"i2":3,"f3":["bar",{"f0":{"i0":11,"i1":12},"i2":13}],"f5":0}])"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("v1", fc::json::from_string(R"(["s3",{"i0":1,"i1":2,"i2":3,"f3":["bar",{"f0":{"i0":11,"i1":12},"i2":13}],"f5":0}])"), yield_fn()), pack_exception, fc_exception_message_is("Unexpected field 'f5' found in input object while processing struct 'v1.'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("v1", fc::json::from_string(R"(["s3",{"i0":1,"i1":2,"i2":3,"f3":["bar",{"f0":{"i0":11,"i1":12},"i2":13}],"f5":0}])"), max_serialization_time), pack_exception, fc_exception_message_is("Unexpected field 'f5' found in input object while processing struct 'v1.'") ); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("v1", fc::json::from_string(R"(["s4",{"f0":[0,1],"f1":[{"i0":2,"i1":3},{"i1":5}]}])"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("v1", fc::json::from_string(R"(["s4",{"f0":[0,1],"f1":[{"i0":2,"i1":3},{"i1":5}]}])"), yield_fn()), pack_exception, fc_exception_message_is("Missing field 'i0' in input object while processing struct 'v1..f1[1]'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("v1", fc::json::from_string(R"(["s4",{"f0":[0,1],"f1":[{"i0":2,"i1":3},{"i1":5}]}])"), max_serialization_time), pack_exception, fc_exception_message_is("Missing field 'i0' in input object while processing struct 'v1..f1[1]'") ); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s2[]", fc::json::from_string(R"([{"f0":{"i0":1,"i1":2},"i2":3},{"f0":{"i0":4},"i2":6}])"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s2[]", fc::json::from_string(R"([{"f0":{"i0":1,"i1":2},"i2":3},{"f0":{"i0":4},"i2":6}])"), yield_fn()), pack_exception, fc_exception_message_is("Missing field 'i1' in input object while processing struct 'ARRAY[1].f0'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s2[]", fc::json::from_string(R"([{"f0":{"i0":1,"i1":2},"i2":3},{"f0":{"i0":4},"i2":6}])"), max_serialization_time), pack_exception, fc_exception_message_is("Missing field 'i1' in input object while processing struct 'ARRAY[1].f0'") ); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s5", fc::json::from_string(R"({"f0":[["bar",{"f0":{"i0":1,"i1":2},"i2":3}],["foo",{"f0":{"i0":4},"i2":6}]]})"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s5", fc::json::from_string(R"({"f0":[["bar",{"f0":{"i0":1,"i1":2},"i2":3}],["foo",{"f0":{"i0":4},"i2":6}]]})"), yield_fn()), pack_exception, fc_exception_message_is("Missing field 'i1' in input object while processing struct 's5.f0[1]..f0'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s5", fc::json::from_string(R"({"f0":[["bar",{"f0":{"i0":1,"i1":2},"i2":3}],["foo",{"f0":{"i0":4},"i2":6}]]})"), max_serialization_time), pack_exception, fc_exception_message_is("Missing field 'i1' in input object while processing struct 's5.f0[1]..f0'") ); verify_round_trip_conversion( abis, "s1arrayarray", R"([[{"i0":1,"i1":2},{"i0":3,"i1":4}],[{"i0":5,"i1":6},{"i0":7,"i1":8},{"i0":9,"i1":10}]])", "0202010203040305060708090a"); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s1arrayarray", fc::json::from_string(R"([[{"i0":1,"i1":2},{"i0":3,"i1":4}],[{"i0":6,"i1":6},{"i0":7,"i1":8},{"i1":10}]])"), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s1arrayarray", fc::json::from_string(R"([[{"i0":1,"i1":2},{"i0":3,"i1":4}],[{"i0":6,"i1":6},{"i0":7,"i1":8},{"i1":10}]])"), yield_fn()), pack_exception, fc_exception_message_is("Missing field 'i0' in input object while processing struct 'ARRAY[1][2]'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s1arrayarray", fc::json::from_string(R"([[{"i0":1,"i1":2},{"i0":3,"i1":4}],[{"i0":6,"i1":6},{"i0":7,"i1":8},{"i1":10}]])"), max_serialization_time), pack_exception, fc_exception_message_is("Missing field 'i0' in input object while processing struct 'ARRAY[1][2]'") ); @@ -2992,15 +3039,15 @@ BOOST_AUTO_TEST_CASE(abi_serialize_short_error_messages) })"; try { - abi_serializer abis( fc::json::from_string(abi).as(), abi_serializer::create_yield_function( max_serialization_time ) ); + abi_serializer abis( fc::json::from_string(abi).as(), yield_fn() ); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("bar", fc::json::from_string(R"({"f0":{"i0":1},"i2":3})"), abi_serializer::create_yield_function( max_serialization_time ), true), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("bar", fc::json::from_string(R"({"f0":{"i0":1},"i2":3})"), yield_fn(), true), pack_exception, fc_exception_message_is("Missing field 'i1' in input object while processing struct 's1'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("bar", fc::json::from_string(R"({"f0":{"i0":1},"i2":3})"), max_serialization_time, true), pack_exception, fc_exception_message_is("Missing field 'i1' in input object while processing struct 's1'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary( "very_very_very_very_very_very_very_very_very_very_long_struct_name_s3", - fc::json::from_string(R"({"i0":1,"i2":3})"), abi_serializer::create_yield_function( max_serialization_time ), true ), + fc::json::from_string(R"({"i0":1,"i2":3})"), yield_fn(), true ), pack_exception, fc_exception_message_is("Missing field 'i1' in input object while processing struct 'very_very_very_very_very_very_very_very_very_very_long_...ame_s3'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary( "very_very_very_very_very_very_very_very_very_very_long_struct_name_s3", @@ -3009,14 +3056,14 @@ BOOST_AUTO_TEST_CASE(abi_serialize_short_error_messages) fc_exception_message_is("Missing field 'i1' in input object while processing struct 'very_very_very_very_very_very_very_very_very_very_long_...ame_s3'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary( "very_very_very_very_very_very_very_very_very_very_long_struct_name_s3", - fc::json::from_string(R"({"i0":1,"i1":2,"i2":3,"f3":["s2",{}]})"), abi_serializer::create_yield_function( max_serialization_time ), true ), + fc::json::from_string(R"({"i0":1,"i1":2,"i2":3,"f3":["s2",{}]})"), yield_fn(), true ), pack_exception, fc_exception_message_is("Specified type 's2' in input array is not valid within the variant 'v2'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary( "very_very_very_very_very_very_very_very_very_very_long_struct_name_s3", fc::json::from_string(R"({"i0":1,"i1":2,"i2":3,"f3":["s2",{}]})"), max_serialization_time, true ), pack_exception, fc_exception_message_is("Specified type 's2' in input array is not valid within the variant 'v2'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary( "very_very_very_very_very_very_very_very_very_very_long_struct_name_s3", - fc::json::from_string(R"({"i0":1,"i1":2,"i2":3,"f3":["bar",{"f0":{"i0":11},"i2":13}]})"), abi_serializer::create_yield_function( max_serialization_time ), true ), + fc::json::from_string(R"({"i0":1,"i1":2,"i2":3,"f3":["bar",{"f0":{"i0":11},"i2":13}]})"), yield_fn(), true ), pack_exception, fc_exception_message_is("Missing field 'i1' in input object while processing struct 's1'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary( "very_very_very_very_very_very_very_very_very_very_long_struct_name_s3", fc::json::from_string(R"({"i0":1,"i1":2,"i2":3,"f3":["bar",{"f0":{"i0":11},"i2":13}]})"), max_serialization_time, true ), @@ -3024,7 +3071,7 @@ BOOST_AUTO_TEST_CASE(abi_serialize_short_error_messages) BOOST_CHECK_EXCEPTION( abis.variant_to_binary( "v1", fc::json::from_string(R"(["very_very_very_very_very_very_very_very_very_very_long_struct_name_s3",{"i0":1,"i1":2,"i2":3,"f3":["bar",{"f0":{"i0":11,"i1":12},"i2":13}],"very_very_very_very_very_very_very_very_very_very_long_field_name_f5":0}])"), - abi_serializer::create_yield_function( max_serialization_time ), true ), + yield_fn(), true ), pack_exception, fc_exception_message_is("Unexpected field 'very_very_very_very_very_very_very_very_very_very_long_...ame_f5' found in input object while processing struct 'very_very_very_very_very_very_very_very_very_very_long_...ame_s3'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary( "v1", @@ -3033,22 +3080,22 @@ BOOST_AUTO_TEST_CASE(abi_serialize_short_error_messages) pack_exception, fc_exception_message_is("Unexpected field 'very_very_very_very_very_very_very_very_very_very_long_...ame_f5' found in input object while processing struct 'very_very_very_very_very_very_very_very_very_very_long_...ame_s3'") ); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("v1", fc::json::from_string(R"(["s4",{"f0":[0,1],"f1":[{"i0":2,"i1":3},{"i1":5}]}])"), abi_serializer::create_yield_function( max_serialization_time ), true), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("v1", fc::json::from_string(R"(["s4",{"f0":[0,1],"f1":[{"i0":2,"i1":3},{"i1":5}]}])"), yield_fn(), true), pack_exception, fc_exception_message_is("Missing field 'i0' in input object while processing struct 's1'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("v1", fc::json::from_string(R"(["s4",{"f0":[0,1],"f1":[{"i0":2,"i1":3},{"i1":5}]}])"), max_serialization_time, true), pack_exception, fc_exception_message_is("Missing field 'i0' in input object while processing struct 's1'") ); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s2[]", fc::json::from_string(R"([{"f0":{"i0":1,"i1":2},"i2":3},{"f0":{"i0":4},"i2":6}])"), abi_serializer::create_yield_function( max_serialization_time ), true), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s2[]", fc::json::from_string(R"([{"f0":{"i0":1,"i1":2},"i2":3},{"f0":{"i0":4},"i2":6}])"), yield_fn(), true), pack_exception, fc_exception_message_is("Missing field 'i1' in input object while processing struct 's1'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s2[]", fc::json::from_string(R"([{"f0":{"i0":1,"i1":2},"i2":3},{"f0":{"i0":4},"i2":6}])"), max_serialization_time, true), pack_exception, fc_exception_message_is("Missing field 'i1' in input object while processing struct 's1'") ); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s5", fc::json::from_string(R"({"f0":[["bar",{"f0":{"i0":1,"i1":2},"i2":3}],["foo",{"f0":{"i0":4},"i2":6}]]})"), abi_serializer::create_yield_function( max_serialization_time ), true), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s5", fc::json::from_string(R"({"f0":[["bar",{"f0":{"i0":1,"i1":2},"i2":3}],["foo",{"f0":{"i0":4},"i2":6}]]})"), yield_fn(), true), pack_exception, fc_exception_message_is("Missing field 'i1' in input object while processing struct 's1'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s5", fc::json::from_string(R"({"f0":[["bar",{"f0":{"i0":1,"i1":2},"i2":3}],["foo",{"f0":{"i0":4},"i2":6}]]})"), max_serialization_time, true), pack_exception, fc_exception_message_is("Missing field 'i1' in input object while processing struct 's1'") ); - BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s1arrayarray", fc::json::from_string(R"([[{"i0":1,"i1":2},{"i0":3,"i1":4}],[{"i0":6,"i1":6},{"i0":7,"i1":8},{"i1":10}]])"), abi_serializer::create_yield_function( max_serialization_time ), true), + BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s1arrayarray", fc::json::from_string(R"([[{"i0":1,"i1":2},{"i0":3,"i1":4}],[{"i0":6,"i1":6},{"i0":7,"i1":8},{"i1":10}]])"), yield_fn(), true), pack_exception, fc_exception_message_is("Missing field 'i0' in input object while processing struct 's1'") ); BOOST_CHECK_EXCEPTION( abis.variant_to_binary("s1arrayarray", fc::json::from_string(R"([[{"i0":1,"i1":2},{"i0":3,"i1":4}],[{"i0":6,"i1":6},{"i0":7,"i1":8},{"i1":10}]])"), max_serialization_time, true), pack_exception, fc_exception_message_is("Missing field 'i0' in input object while processing struct 's1'") ); @@ -3097,58 +3144,58 @@ BOOST_AUTO_TEST_CASE(abi_deserialize_detailed_error_messages) // Some details here: c::variant("030101000103") represents an array of std::optional {1,null,3}, and // fc::variant("0400000000") represents an array of 4 nulls. Also fc::variant("030001af013a") represents {null, 0xAF, 0x3A}. // Test to verify that array of optinal doesn't throw exception - abi_serializer abis( fc::json::from_string(abi).as(), abi_serializer::create_yield_function( max_serialization_time ) ); - BOOST_CHECK_NO_THROW( abis.binary_to_variant("s4", fc::variant("030101000103").as(), abi_serializer::create_yield_function( max_serialization_time )) ); + abi_serializer abis( fc::json::from_string(abi).as(), yield_fn() ); + BOOST_CHECK_NO_THROW( abis.binary_to_variant("s4", fc::variant("030101000103").as(), yield_fn()) ); BOOST_CHECK_NO_THROW( abis.binary_to_variant("s4", fc::variant("030101000103").as(), max_serialization_time) ); try { - BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s2", fc::variant("020102").as(), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s2", fc::variant("020102").as(), yield_fn()), unpack_exception, fc_exception_message_is("Stream unexpectedly ended; unable to unpack field 'f1' of struct 's2'") ); BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s2", fc::variant("020102").as(), max_serialization_time), unpack_exception, fc_exception_message_is("Stream unexpectedly ended; unable to unpack field 'f1' of struct 's2'") ); - BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s2", fc::variant("0201020103").as(), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s2", fc::variant("0201020103").as(), yield_fn()), unpack_exception, fc_exception_message_is("Stream unexpectedly ended; unable to unpack field 'i1' of struct 's2.f1[0]'") ); BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s2", fc::variant("0201020103").as(), max_serialization_time), unpack_exception, fc_exception_message_is("Stream unexpectedly ended; unable to unpack field 'i1' of struct 's2.f1[0]'") ); - BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s2", fc::variant("020102ff").as(), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s2", fc::variant("020102ff").as(), yield_fn()), unpack_exception, fc_exception_message_is("Unable to unpack size of array 's2.f1'") ); BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s2", fc::variant("020102ff").as(), max_serialization_time), unpack_exception, fc_exception_message_is("Unable to unpack size of array 's2.f1'") ); - BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s3", fc::variant("010203").as(), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s3", fc::variant("010203").as(), yield_fn()), abi_exception, fc_exception_message_is("Encountered field 'i5' without binary extension designation while processing struct 's3'") ); BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s3", fc::variant("010203").as(), max_serialization_time), abi_exception, fc_exception_message_is("Encountered field 'i5' without binary extension designation while processing struct 's3'") ); - BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s3", fc::variant("02010304").as(), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s3", fc::variant("02010304").as(), yield_fn()), abi_exception, fc_exception_message_is("Encountered field 'i5' without binary extension designation while processing struct 's3'") ); BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s3", fc::variant("02010304").as(), max_serialization_time), abi_exception, fc_exception_message_is("Encountered field 'i5' without binary extension designation while processing struct 's3'") ); - BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s4", fc::variant("020101").as(), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s4", fc::variant("020101").as(), yield_fn()), unpack_exception, fc_exception_message_is("Unable to unpack optional of built-in type 'int8' while processing 's4.f0[1]'") ); BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s4", fc::variant("020101").as(), max_serialization_time), unpack_exception, fc_exception_message_is("Unable to unpack optional of built-in type 'int8' while processing 's4.f0[1]'") ); - BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s5", fc::variant("02010102").as(), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s5", fc::variant("02010102").as(), yield_fn()), unpack_exception, fc_exception_message_is("Unable to unpack presence flag of optional 's5.f0[1]'") ); BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s5", fc::variant("02010102").as(), max_serialization_time), unpack_exception, fc_exception_message_is("Unable to unpack presence flag of optional 's5.f0[1]'") ); - BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s5", fc::variant("0001").as(), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s5", fc::variant("0001").as(), yield_fn()), unpack_exception, fc_exception_message_is("Unable to unpack tag of variant 's5.f1[0]'") ); BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s5", fc::variant("0001").as(), max_serialization_time), unpack_exception, fc_exception_message_is("Unable to unpack tag of variant 's5.f1[0]'") ); - BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s5", fc::variant("00010501").as(), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s5", fc::variant("00010501").as(), yield_fn()), unpack_exception, fc_exception_message_is("Unpacked invalid tag (5) for variant 's5.f1[0]'") ); BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s5", fc::variant("00010501").as(), max_serialization_time), unpack_exception, fc_exception_message_is("Unpacked invalid tag (5) for variant 's5.f1[0]'") ); - BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s5", fc::variant("00010101").as(), abi_serializer::create_yield_function( max_serialization_time )), + BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s5", fc::variant("00010101").as(), yield_fn()), unpack_exception, fc_exception_message_is("Stream unexpectedly ended; unable to unpack field 'i1' of struct 's5.f1[0].'") ); BOOST_CHECK_EXCEPTION( abis.binary_to_variant("s5", fc::variant("00010101").as(), max_serialization_time), unpack_exception, fc_exception_message_is("Stream unexpectedly ended; unable to unpack field 'i1' of struct 's5.f1[0].'") ); @@ -3168,7 +3215,7 @@ BOOST_AUTO_TEST_CASE(serialize_optional_struct_type) })"; try { - abi_serializer abis( fc::json::from_string(abi).as(), abi_serializer::create_yield_function( max_serialization_time ) ); + abi_serializer abis( fc::json::from_string(abi).as(), yield_fn() ); verify_round_trip_conversion(abis, "s?", R"({"i0":5})", "0105"); verify_round_trip_conversion(abis, "s?", R"(null)", "00");