diff --git a/libraries/testing/contracts.hpp.in b/libraries/testing/contracts.hpp.in index f67c6066a3..3c0fc87cce 100644 --- a/libraries/testing/contracts.hpp.in +++ b/libraries/testing/contracts.hpp.in @@ -51,6 +51,7 @@ namespace eosio { MAKE_READ_WASM_ABI(deferred_test, deferred_test, test-contracts) MAKE_READ_WASM_ABI(get_sender_test, get_sender_test, test-contracts) MAKE_READ_WASM_ABI(get_table_test, get_table_test, test-contracts) + MAKE_READ_WASM_ABI(get_table_seckey_test, get_table_seckey_test, test-contracts) MAKE_READ_WASM_ABI(noop, noop, test-contracts) MAKE_READ_WASM_ABI(payloadless, payloadless, test-contracts) MAKE_READ_WASM_ABI(proxy, proxy, test-contracts) diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index 2758cd90e1..cfdc63fcc3 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -1583,6 +1583,10 @@ uint64_t read_only::get_table_index_name(const read_only::get_table_rows_params& return index; } +uint64_t convert_to_type(const eosio::name &n, const string &desc) { + return n.to_uint64_t(); +} + template<> uint64_t convert_to_type(const string& str, const string& desc) { diff --git a/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp b/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp index f327190eee..ba5719ccc5 100644 --- a/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp +++ b/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp @@ -69,6 +69,8 @@ Type convert_to_type(const string& str, const string& desc) { } FC_RETHROW_EXCEPTIONS(warn, "Could not convert ${desc} string '${str}' to key type.", ("desc", desc)("str",str) ) } +uint64_t convert_to_type(const eosio::name &n, const string &desc); + template<> uint64_t convert_to_type(const string& str, const string& desc); @@ -518,9 +520,12 @@ class read_only { if( p.lower_bound.size() ) { if( p.key_type == "name" ) { - name s(p.lower_bound); - SecKeyType lv = convert_to_type( s.to_string(), "lower_bound name" ); // avoids compiler error - std::get<1>(lower_bound_lookup_tuple) = conv( lv ); + if constexpr (std::is_same_v) { + SecKeyType lv = convert_to_type(name{p.lower_bound}, "lower_bound name"); + std::get<1>(lower_bound_lookup_tuple) = conv(lv); + } else { + EOS_ASSERT(false, chain::contract_table_query_exception, "Invalid key type of eosio::name ${nm} for lower bound", ("nm", p.lower_bound)); + } } else { SecKeyType lv = convert_to_type( p.lower_bound, "lower_bound" ); std::get<1>(lower_bound_lookup_tuple) = conv( lv ); @@ -529,9 +534,12 @@ class read_only { if( p.upper_bound.size() ) { if( p.key_type == "name" ) { - name s(p.upper_bound); - SecKeyType uv = convert_to_type( s.to_string(), "upper_bound name" ); - std::get<1>(upper_bound_lookup_tuple) = conv( uv ); + if constexpr (std::is_same_v) { + SecKeyType uv = convert_to_type(name{p.upper_bound}, "upper_bound name"); + std::get<1>(upper_bound_lookup_tuple) = conv(uv); + } else { + EOS_ASSERT(false, chain::contract_table_query_exception, "Invalid key type of eosio::name ${nm} for upper bound", ("nm", p.upper_bound)); + } } else { SecKeyType uv = convert_to_type( p.upper_bound, "upper_bound" ); std::get<1>(upper_bound_lookup_tuple) = conv( uv ); diff --git a/tests/get_table_seckey_tests.cpp b/tests/get_table_seckey_tests.cpp new file mode 100644 index 0000000000..fa97dbc266 --- /dev/null +++ b/tests/get_table_seckey_tests.cpp @@ -0,0 +1,98 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include + +#include +#include + +#ifdef NON_VALIDATING_TEST +#define TESTER tester +#else +#define TESTER validating_tester +#endif + +using namespace eosio; +using namespace eosio::chain; +using namespace eosio::testing; +using namespace fc; + +BOOST_AUTO_TEST_SUITE(get_table_seckey_tests) + +BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { + create_account("test"_n); + + // setup contract and abi + set_code( "test"_n, contracts::get_table_seckey_test_wasm() ); + set_abi( "test"_n, contracts::get_table_seckey_test_abi().data() ); + produce_block(); + + chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), {}, {}); + chain_apis::read_only::get_table_rows_params params = []{ + chain_apis::read_only::get_table_rows_params params{}; + params.json=true; + params.code="test"_n; + params.scope="test"; + params.limit=1; + return params; + }(); + + params.table = "numobjs"_n; + + + // name secondary key type + push_action("test"_n, "addnumobj"_n, "test"_n, mutable_variant_object()("input", 2)("nm", "a")); + push_action("test"_n, "addnumobj"_n, "test"_n, mutable_variant_object()("input", 5)("nm", "b")); + push_action("test"_n, "addnumobj"_n, "test"_n, mutable_variant_object()("input", 7)("nm", "c")); + + params.table = "numobjs"_n; + params.key_type = "name"; + params.limit = 10; + params.index_position = "6"; + params.lower_bound = "a"; + params.upper_bound = "a"; + auto res_nm = plugin.get_table_rows(params); + BOOST_REQUIRE(res_nm.rows.size() == 1); + + params.lower_bound = "a"; + params.upper_bound = "b"; + res_nm = plugin.get_table_rows(params); + BOOST_REQUIRE(res_nm.rows.size() == 2); + + params.lower_bound = "a"; + params.upper_bound = "c"; + res_nm = plugin.get_table_rows(params); + BOOST_REQUIRE(res_nm.rows.size() == 3); + + push_action("test"_n, "addnumobj"_n, "test"_n, mutable_variant_object()("input", 8)("nm", "1111")); + push_action("test"_n, "addnumobj"_n, "test"_n, mutable_variant_object()("input", 9)("nm", "2222")); + push_action("test"_n, "addnumobj"_n, "test"_n, mutable_variant_object()("input", 10)("nm", "3333")); + + params.lower_bound = "1111"; + params.upper_bound = "3333"; + res_nm = plugin.get_table_rows(params); + BOOST_REQUIRE(res_nm.rows.size() == 3); + + params.lower_bound = "2222"; + params.upper_bound = "3333"; + res_nm = plugin.get_table_rows(params); + BOOST_REQUIRE(res_nm.rows.size() == 2); + +} FC_LOG_AND_RETHROW() /// get_table_next_key_test + +BOOST_AUTO_TEST_SUITE_END() diff --git a/unittests/test-contracts/CMakeLists.txt b/unittests/test-contracts/CMakeLists.txt index aad0a93219..8c45188fbc 100644 --- a/unittests/test-contracts/CMakeLists.txt +++ b/unittests/test-contracts/CMakeLists.txt @@ -11,6 +11,7 @@ add_subdirectory( asserter ) add_subdirectory( deferred_test ) add_subdirectory( get_sender_test ) add_subdirectory( get_table_test ) +add_subdirectory( get_table_seckey_test ) add_subdirectory( integration_test ) add_subdirectory( noop ) add_subdirectory( payloadless ) diff --git a/unittests/test-contracts/get_table_seckey_test/CMakeLists.txt b/unittests/test-contracts/get_table_seckey_test/CMakeLists.txt new file mode 100644 index 0000000000..5fb8e25366 --- /dev/null +++ b/unittests/test-contracts/get_table_seckey_test/CMakeLists.txt @@ -0,0 +1,6 @@ +if( EOSIO_COMPILE_TEST_CONTRACTS ) + add_contract( get_table_seckey_test get_table_seckey_test get_table_seckey_test.cpp ) +else() + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/get_table_seckey_test.wasm ${CMAKE_CURRENT_BINARY_DIR}/get_table_seckey_test.wasm COPYONLY ) + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/get_table_seckey_test.abi ${CMAKE_CURRENT_BINARY_DIR}/get_table_seckey_test.abi COPYONLY ) +endif() diff --git a/unittests/test-contracts/get_table_seckey_test/get_table_seckey_test.abi b/unittests/test-contracts/get_table_seckey_test/get_table_seckey_test.abi new file mode 100644 index 0000000000..94ee4f2021 --- /dev/null +++ b/unittests/test-contracts/get_table_seckey_test/get_table_seckey_test.abi @@ -0,0 +1,71 @@ +{ + "____comment": "This file was generated with eosio-abigen. DO NOT EDIT ", + "version": "eosio::abi/1.2", + "types": [], + "structs": [ + { + "name": "addnumobj", + "base": "", + "fields": [ + { + "name": "input", + "type": "uint64" + }, + { + "name": "nm", + "type": "string" + } + ] + }, + { + "name": "numobj", + "base": "", + "fields": [ + { + "name": "key", + "type": "uint64" + }, + { + "name": "sec64", + "type": "uint64" + }, + { + "name": "sec128", + "type": "uint128" + }, + { + "name": "secdouble", + "type": "float64" + }, + { + "name": "secldouble", + "type": "float128" + }, + { + "name": "nm", + "type": "name" + } + ] + } + ], + "actions": [ + { + "name": "addnumobj", + "type": "addnumobj", + "ricardian_contract": "" + } + ], + "tables": [ + { + "name": "numobjs", + "type": "numobj", + "index_type": "i64", + "key_names": [], + "key_types": [] + } + ], + "kv_tables": {}, + "ricardian_clauses": [], + "variants": [], + "action_results": [] +} \ No newline at end of file diff --git a/unittests/test-contracts/get_table_seckey_test/get_table_seckey_test.cpp b/unittests/test-contracts/get_table_seckey_test/get_table_seckey_test.cpp new file mode 100644 index 0000000000..d3527e2530 --- /dev/null +++ b/unittests/test-contracts/get_table_seckey_test/get_table_seckey_test.cpp @@ -0,0 +1,18 @@ +/** + * @file + * @copyright defined in eos/LICENSE + */ +#include "get_table_seckey_test.hpp" + + +void get_table_seckey_test::addnumobj(uint64_t input, std::string nm) { + numobjs numobjs_table( _self, _self.value ); + numobjs_table.emplace(_self, [&](auto &obj) { + obj.key = numobjs_table.available_primary_key(); + obj.sec64 = input; + obj.sec128 = input; + obj.secdouble = input; + obj.secldouble = input; + obj.nm = name(nm); + }); +} diff --git a/unittests/test-contracts/get_table_seckey_test/get_table_seckey_test.hpp b/unittests/test-contracts/get_table_seckey_test/get_table_seckey_test.hpp new file mode 100644 index 0000000000..ed06fb7262 --- /dev/null +++ b/unittests/test-contracts/get_table_seckey_test/get_table_seckey_test.hpp @@ -0,0 +1,43 @@ +/** + * @file + * @copyright defined in eos/LICENSE + */ +#pragma once + +#include +#include + +using namespace eosio; + +class [[eosio::contract]] get_table_seckey_test : public eosio::contract { + public: + using eosio::contract::contract; + + // Number object + struct [[eosio::table]] numobj { + uint64_t key; + uint64_t sec64; + uint128_t sec128; + double secdouble; + long double secldouble; + name nm; + + uint64_t primary_key() const { return key; } + uint64_t sec64_key() const { return sec64; } + uint128_t sec128_key() const { return sec128; } + double secdouble_key() const { return secdouble; } + long double secldouble_key() const { return secldouble; } + uint64_t name_key() const { return nm.value; } + }; + + typedef eosio::multi_index< "numobjs"_n, numobj, + indexed_by<"bysec1"_n, const_mem_fun>, + indexed_by<"bysec2"_n, const_mem_fun>, + indexed_by<"bysec3"_n, const_mem_fun>, + indexed_by<"bysec4"_n, const_mem_fun>, + indexed_by<"byname"_n, const_mem_fun> + > numobjs; + + [[eosio::action]] + void addnumobj(uint64_t input, std::string nm); +}; diff --git a/unittests/test-contracts/get_table_seckey_test/get_table_seckey_test.wasm b/unittests/test-contracts/get_table_seckey_test/get_table_seckey_test.wasm new file mode 100755 index 0000000000..7cfdcef92c Binary files /dev/null and b/unittests/test-contracts/get_table_seckey_test/get_table_seckey_test.wasm differ