提交 d3e53912 编写于 作者: B Brian Johnson

Added RAM limit tests. GH #3039

上级 8919c359
......@@ -26,6 +26,7 @@ add_subdirectory(test_api)
add_subdirectory(test_api_mem)
add_subdirectory(test_api_db)
add_subdirectory(test_api_multi_index)
add_subdirectory(test_ram_limit)
#add_subdirectory(social)
add_subdirectory(eosio.bios)
add_subdirectory(noop)
......
file(GLOB ABI_FILES "*.abi")
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_wast_executable(TARGET test_ram_limit
INCLUDE_FOLDERS ${STANDARD_INCLUDE_FOLDERS}
LIBRARIES libc++ libc eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
{
"____comment": "This file was generated by eosio-abigen. DO NOT EDIT - 2018-03-29T02:09:11",
"types": [],
"structs": [{
"name": "setentry",
"base": "",
"fields": [{
"name": "payer",
"type": "account_name"
},{
"name": "from",
"type": "uint64"
},{
"name": "to",
"type": "uint64"
},{
"name": "size",
"type": "uint64"
}
]
},{
"name": "rmentry",
"base": "",
"fields": [{
"name": "from",
"type": "uint64"
},{
"name": "to",
"type": "uint64"
}
]
},{
"name": "printentry",
"base": "",
"fields": [{
"name": "from",
"type": "uint64"
},{
"name": "to",
"type": "uint64"
}
]
},{
"name": "test",
"base": "",
"fields": [{
"name": "key",
"type": "uint64"
},{
"name": "data",
"type": "int8[]"
}
]
}
],
"actions": [{
"name": "setentry",
"type": "setentry",
"ricardian_contract": ""
},{
"name": "rmentry",
"type": "rmentry",
"ricardian_contract": ""
},{
"name": "printentry",
"type": "printentry",
"ricardian_contract": ""
}
],
"tables": [{
"name": "test.table",
"index_type": "i64",
"key_names": [
"key"
],
"key_types": [
"uint64"
],
"type": "test"
}
],
"ricardian_clauses": []
}
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#include <utility>
#include <vector>
#include <string>
#include <eosiolib/eosio.hpp>
#include <eosiolib/contract.hpp>
class test_ram_limit : public eosio::contract {
public:
const uint32_t FIVE_MINUTES = 5*60;
test_ram_limit(account_name self)
:eosio::contract(self)
{}
//@abi action
void setentry(account_name payer, uint64_t from, uint64_t to, uint64_t size) {
const auto self = get_self();
eosio::print("test_ram_limit::setentry ", eosio::name{self}, "\n");
test_table table(self, self);
for (int key = from; key <=to; ++key) {
auto itr = table.find(key);
if (itr != table.end()) {
table.modify(itr, payer, [size](test& t) {
t.data.assign(size, (int8_t)size);
});
} else {
table.emplace(payer, [key,size](test& t) {
t.key = key;
t.data.assign(size, (int8_t)size);
});
}
}
}
//@abi action
void rmentry(uint64_t from, uint64_t to) {
const auto self = get_self();
eosio::print("test_ram_limit::rmentry ", eosio::name{self}, "\n");
test_table table(self, self);
for (int key = from; key <=to; ++key) {
auto itr = table.find(key);
eosio_assert (itr != table.end(), "could not find test_table entry");
table.erase(itr);
}
}
//@abi action
void printentry(uint64_t from, uint64_t to) {
const auto self = get_self();
eosio::print("test_ram_limit::printout ", eosio::name{self}, ":");
test_table table(self, self);
for (int key = from; key <=to; ++key) {
auto itr = table.find(key);
eosio::print("\nkey=", key);
eosio_assert (itr != table.end(), "could not find test_table entry");
eosio::print(" size=", itr->data.size());
}
}
private:
struct test {
uint64_t key;
std::vector<int8_t> data;
uint64_t primary_key()const { return key; }
EOSLIB_SERIALIZE( test, (key)(data) )
};
typedef eosio::multi_index< N(test.table), test> test_table;
};
EOSIO_ABI( test_ram_limit, (setentry)(rmentry)(printentry) )
......@@ -2,6 +2,8 @@
* @file
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include <eosio/testing/tester.hpp>
#include <eosio/chain/abi_serializer.hpp>
......@@ -35,7 +37,13 @@ namespace eosio_system {
class eosio_system_tester : public TESTER {
public:
eosio_system_tester() {
eosio_system_tester()
: eosio_system_tester([](TESTER& ) {}){}
template<typename Lambda>
eosio_system_tester(Lambda setup) {
setup(*this);
produce_blocks( 2 );
create_accounts( { N(eosio.token) } );
......@@ -83,7 +91,7 @@ public:
}
}
transaction_trace_ptr create_account_with_resources( account_name a, account_name creator ) {
transaction_trace_ptr create_account_with_resources( account_name a, account_name creator, uint32_t ram_bytes = 8000 ) {
signed_transaction trx;
set_transaction_headers(trx);
......@@ -102,7 +110,7 @@ public:
mvo()
("payer", creator)
("receiver", a)
("bytes", 8000) )
("bytes", ram_bytes) )
);
trx.actions.emplace_back( get_action( N(eosio), N(delegatebw), vector<permission_level>{{creator,config::active_name}},
mvo()
......@@ -386,7 +394,7 @@ public:
abi_serializer token_abi_ser;
};
fc::mutable_variant_object voter( account_name acct ) {
inline fc::mutable_variant_object voter( account_name acct ) {
return mutable_variant_object()
("owner", acct)
("proxy", name(0).to_string())
......@@ -401,15 +409,15 @@ fc::mutable_variant_object voter( account_name acct ) {
;
}
fc::mutable_variant_object voter( account_name acct, const asset& vote_stake ) {
inline fc::mutable_variant_object voter( account_name acct, const asset& vote_stake ) {
return voter( acct )( "staked", vote_stake.amount );
}
fc::mutable_variant_object voter( account_name acct, int64_t vote_stake ) {
inline fc::mutable_variant_object voter( account_name acct, int64_t vote_stake ) {
return voter( acct )( "staked", vote_stake );
}
fc::mutable_variant_object proxy( account_name acct ) {
inline fc::mutable_variant_object proxy( account_name acct ) {
return voter( acct )( "is_proxy", 1 );
}
......
/**
* @file api_tests.cpp
* @copyright defined in eos/LICENSE.txt
*/
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare"
#include <boost/test/unit_test.hpp>
#pragma GCC diagnostic pop
#include <eosio/testing/tester.hpp>
#include <eosio/chain/exceptions.hpp>
#include <eosio/chain/resource_limits.hpp>
#include <fc/exception/exception.hpp>
#include <fc/variant_object.hpp>
#include "eosio_system_tester.hpp"
#include <test_ram_limit/test_ram_limit.abi.hpp>
#include <test_ram_limit/test_ram_limit.wast.hpp>
#define DISABLE_EOSLIB_SERIALIZE
#include <test_api/test_api_common.hpp>
/*
* register test suite `ram_tests`
*/
BOOST_AUTO_TEST_SUITE(ram_tests)
/*************************************************************************************
* ram_tests test case
*************************************************************************************/
BOOST_FIXTURE_TEST_CASE(ram_tests, eosio_system::eosio_system_tester) { try {
auto init_request_bytes = 80000;
const auto increment_contract_bytes = 10000;
const auto table_allocation_bytes = 12000;
BOOST_REQUIRE_MESSAGE(table_allocation_bytes > increment_contract_bytes, "increment_contract_bytes must be less than table_allocation_bytes for this test setup to work");
buyrambytes(N(eosio), N(eosio), 70000);
produce_blocks(10);
create_account_with_resources(N(testram11111),N(eosio), init_request_bytes);
create_account_with_resources(N(testram22222),N(eosio), init_request_bytes);
produce_blocks(10);
BOOST_REQUIRE_EQUAL( success(), stake( "eosio", "testram11111", "10.0000 EOS", "5.0000 EOS" ) );
produce_blocks(10);
for (auto i = 0; i < 10; ++i) {
try {
set_code( N(testram11111), test_ram_limit_wast );
break;
} catch (const ram_usage_exceeded&) {
init_request_bytes += increment_contract_bytes;
buyrambytes(N(eosio), N(testram11111), increment_contract_bytes);
buyrambytes(N(eosio), N(testram22222), increment_contract_bytes);
}
}
produce_blocks(10);
for (auto i = 0; i < 10; ++i) {
try {
set_abi( N(testram11111), test_ram_limit_abi );
break;
} catch (const ram_usage_exceeded&) {
init_request_bytes += increment_contract_bytes;
buyrambytes(N(eosio), N(testram11111), increment_contract_bytes);
buyrambytes(N(eosio), N(testram22222), increment_contract_bytes);
}
}
produce_blocks(10);
set_code( N(testram22222), test_ram_limit_wast );
set_abi( N(testram22222), test_ram_limit_abi );
produce_blocks(10);
auto total = get_total_stake( N(testram11111) );
const auto init_bytes = total["ram_bytes"].as_uint64();
auto rlm = control->get_resource_limits_manager();
auto initial_ram_usage = rlm.get_account_ram_usage(N(testram11111));
// calculate how many more bytes we need to have table_allocation_bytes for database stores
auto more_ram = table_allocation_bytes + init_bytes - init_request_bytes;
BOOST_REQUIRE_MESSAGE(more_ram >= 0, "Underlying understanding changed, need to reduce size of init_request_bytes");
wdump((init_bytes)(initial_ram_usage)(init_request_bytes)(more_ram) );
buyrambytes(N(eosio), N(testram11111), more_ram);
buyrambytes(N(eosio), N(testram22222), more_ram);
TESTER* tester = this;
// allocate just under the allocated bytes
tester->push_action( N(testram11111), N(setentry), N(testram11111), mvo()
("payer", "testram11111")
("from", 1)
("to", 10)
("size", 1910));
produce_blocks(1);
auto ram_usage = rlm.get_account_ram_usage(N(testram11111));
total = get_total_stake( N(testram11111) );
const auto ram_bytes = total["ram_bytes"].as_uint64();
wdump((ram_bytes)(ram_usage)(initial_ram_usage)(init_bytes)(ram_usage - initial_ram_usage)(init_bytes - ram_usage) );
wlog("ram_tests 1 %%%%%%");
// allocate just beyond the allocated bytes
BOOST_REQUIRE_EXCEPTION(
tester->push_action( N(testram11111), N(setentry), N(testram11111), mvo()
("payer", "testram11111")
("from", 1)
("to", 10)
("size", 1920)),
ram_usage_exceeded,
fc_exception_message_starts_with("account testram11111 has insufficient ram bytes"));
wlog("ram_tests 2 %%%%%%");
produce_blocks(1);
BOOST_REQUIRE_EQUAL(ram_usage, rlm.get_account_ram_usage(N(testram11111)));
// update the entries with smaller allocations so that we can verify space is freed and new allocations can be made
tester->push_action( N(testram11111), N(setentry), N(testram11111), mvo()
("payer", "testram11111")
("from", 1)
("to", 10)
("size", 1810));
produce_blocks(1);
BOOST_REQUIRE_EQUAL(ram_usage - 1000, rlm.get_account_ram_usage(N(testram11111)));
// verify the added entry is beyond the allocation bytes limit
BOOST_REQUIRE_EXCEPTION(
tester->push_action( N(testram11111), N(setentry), N(testram11111), mvo()
("payer", "testram11111")
("from", 1)
("to", 11)
("size", 1810)),
ram_usage_exceeded,
fc_exception_message_starts_with("account testram11111 has insufficient ram bytes"));
produce_blocks(1);
BOOST_REQUIRE_EQUAL(ram_usage - 1000, rlm.get_account_ram_usage(N(testram11111)));
// verify the new entry's bytes minus the freed up bytes for existing entries still exceeds the allocation bytes limit
BOOST_REQUIRE_EXCEPTION(
tester->push_action( N(testram11111), N(setentry), N(testram11111), mvo()
("payer", "testram11111")
("from", 1)
("to", 11)
("size", 1760)),
ram_usage_exceeded,
fc_exception_message_starts_with("account testram11111 has insufficient ram bytes"));
produce_blocks(1);
BOOST_REQUIRE_EQUAL(ram_usage - 1000, rlm.get_account_ram_usage(N(testram11111)));
// verify the new entry's bytes minus the freed up bytes for existing entries are under the allocation bytes limit
tester->push_action( N(testram11111), N(setentry), N(testram11111), mvo()
("payer", "testram11111")
("from", 1)
("to", 11)
("size", 1720));
produce_blocks(1);
tester->push_action( N(testram11111), N(rmentry), N(testram11111), mvo()
("from", 3)
("to", 3));
produce_blocks(1);
// verify that the new entry will exceed the allocation bytes limit
BOOST_REQUIRE_EXCEPTION(
tester->push_action( N(testram11111), N(setentry), N(testram11111), mvo()
("payer", "testram11111")
("from", 12)
("to", 12)
("size", 1900)),
ram_usage_exceeded,
fc_exception_message_starts_with("account testram11111 has insufficient ram bytes"));
produce_blocks(1);
// verify that the new entry is under the allocation bytes limit
tester->push_action( N(testram11111), N(setentry), N(testram11111), mvo()
("payer", "testram11111")
("from", 12)
("to", 12)
("size", 1720));
produce_blocks(1);
// verify that anoth new entry will exceed the allocation bytes limit, to setup testing of new payer
BOOST_REQUIRE_EXCEPTION(
tester->push_action( N(testram11111), N(setentry), N(testram11111), mvo()
("payer", "testram11111")
("from", 13)
("to", 13)
("size", 1720)),
ram_usage_exceeded,
fc_exception_message_starts_with("account testram11111 has insufficient ram bytes"));
produce_blocks(1);
// verify that the new entry is under the allocation bytes limit
tester->push_action( N(testram11111), N(setentry), {N(testram11111),N(testram22222)}, mvo()
("payer", "testram22222")
("from", 12)
("to", 12)
("size", 1720));
produce_blocks(1);
// verify that another new entry that is too big will exceed the allocation bytes limit, to setup testing of new payer
BOOST_REQUIRE_EXCEPTION(
tester->push_action( N(testram11111), N(setentry), N(testram11111), mvo()
("payer", "testram11111")
("from", 13)
("to", 13)
("size", 1900)),
ram_usage_exceeded,
fc_exception_message_starts_with("account testram11111 has insufficient ram bytes"));
produce_blocks(1);
wlog("ram_tests 18 %%%%%%");
// verify that the new entry is under the allocation bytes limit, because entry 12 is now charged to testram22222
tester->push_action( N(testram11111), N(setentry), N(testram11111), mvo()
("payer", "testram11111")
("from", 13)
("to", 13)
("size", 1720));
produce_blocks(1);
// verify that new entries for testram22222 exceed the allocation bytes limit
BOOST_REQUIRE_EXCEPTION(
tester->push_action( N(testram11111), N(setentry), {N(testram11111),N(testram22222)}, mvo()
("payer", "testram22222")
("from", 12)
("to", 21)
("size", 1930)),
ram_usage_exceeded,
fc_exception_message_starts_with("account testram22222 has insufficient ram bytes"));
produce_blocks(1);
// verify that new entries for testram22222 are under the allocation bytes limit
tester->push_action( N(testram11111), N(setentry), {N(testram11111),N(testram22222)}, mvo()
("payer", "testram22222")
("from", 12)
("to", 21)
("size", 1910));
produce_blocks(1);
// verify that new entry for testram22222 exceed the allocation bytes limit
BOOST_REQUIRE_EXCEPTION(
tester->push_action( N(testram11111), N(setentry), {N(testram11111),N(testram22222)}, mvo()
("payer", "testram22222")
("from", 22)
("to", 22)
("size", 1910)),
ram_usage_exceeded,
fc_exception_message_starts_with("account testram22222 has insufficient ram bytes"));
produce_blocks(1);
tester->push_action( N(testram11111), N(rmentry), N(testram11111), mvo()
("from", 20)
("to", 20));
produce_blocks(1);
// verify that new entry for testram22222 are under the allocation bytes limit
tester->push_action( N(testram11111), N(setentry), {N(testram11111),N(testram22222)}, mvo()
("payer", "testram22222")
("from", 22)
("to", 22)
("size", 1910));
produce_blocks(1);
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_SUITE_END()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册