mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Check State
Incomplete State Support
This commit is contained in:
parent
b0c8babf0e
commit
adba4fb9a1
@ -25,7 +25,6 @@
|
||||
#include <chrono>
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/assign.hpp>
|
||||
|
||||
#include <libethereum/Client.h>
|
||||
#include <liblll/Compiler.h>
|
||||
@ -107,41 +106,72 @@ void ImportTest::importEnv(json_spirit::mObject& _o)
|
||||
m_statePre.m_currentBlock = m_environment.currentBlock;
|
||||
}
|
||||
|
||||
void ImportTest::importState(json_spirit::mObject& _o, State& _state)
|
||||
// import state from not fully declared json_spirit::mObject, writing to _stateOptionsMap which fields were defined in json
|
||||
|
||||
void ImportTest::importState(json_spirit::mObject& _o, State& _state, stateOptionsMap& _stateOptionsMap)
|
||||
{
|
||||
for (auto& i: _o)
|
||||
{
|
||||
json_spirit::mObject o = i.second.get_obj();
|
||||
|
||||
assert(o.count("balance") > 0);
|
||||
assert(o.count("nonce") > 0);
|
||||
assert(o.count("storage") > 0);
|
||||
assert(o.count("code") > 0);
|
||||
ImportStateOptions stateOptions;
|
||||
u256 iBalance = 0, iNonce = 0;
|
||||
|
||||
if (o.count("balance") > 0)
|
||||
{
|
||||
stateOptions.m_bHasBalance = true;
|
||||
if (bigint(o["balance"].get_str()) >= c_max256plus1)
|
||||
BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("State 'balance' is equal or greater than 2**256") );
|
||||
iBalance = toInt(o["balance"]);
|
||||
}
|
||||
|
||||
if (o.count("nonce") > 0)
|
||||
{
|
||||
stateOptions.m_bHasNonce = true;
|
||||
if (bigint(o["nonce"].get_str()) >= c_max256plus1)
|
||||
BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("State 'nonce' is equal or greater than 2**256") );
|
||||
iNonce = toInt(o["nonce"]);
|
||||
}
|
||||
|
||||
Address address = Address(i.first);
|
||||
|
||||
bytes code = importCode(o);
|
||||
bytes code;
|
||||
if (o.count("code") > 0)
|
||||
{
|
||||
code = importCode(o);
|
||||
stateOptions.m_bHasCode = true;
|
||||
}
|
||||
|
||||
if (code.size())
|
||||
{
|
||||
_state.m_cache[address] = Account(toInt(o["balance"]), Account::ContractConception);
|
||||
_state.m_cache[address] = Account(iBalance, Account::ContractConception);
|
||||
_state.m_cache[address].setCode(code);
|
||||
}
|
||||
else
|
||||
_state.m_cache[address] = Account(toInt(o["balance"]), Account::NormalCreation);
|
||||
_state.m_cache[address] = Account(iBalance, Account::NormalCreation);
|
||||
|
||||
if (o.count("storage") > 0)
|
||||
{
|
||||
stateOptions.m_bHasStorage = true;
|
||||
for (auto const& j: o["storage"].get_obj())
|
||||
_state.setStorage(address, toInt(j.first), toInt(j.second));
|
||||
}
|
||||
|
||||
for(int i=0; i<toInt(o["nonce"]); ++i)
|
||||
for (int i=0; i<iNonce; ++i)
|
||||
_state.noteSending(address);
|
||||
|
||||
_state.ensureCached(address, false, false);
|
||||
_stateOptionsMap[address] = stateOptions;
|
||||
}
|
||||
}
|
||||
|
||||
void ImportTest::importState(json_spirit::mObject& _o, State& _state)
|
||||
{
|
||||
stateOptionsMap importedMap;
|
||||
importState(_o, _state, importedMap);
|
||||
for (auto& stateOptionMap: importedMap)
|
||||
{
|
||||
assert(stateOptionMap.second.isAllSet()); //check that every parameter was declared in state object
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,6 +208,12 @@ void ImportTest::importTransaction(json_spirit::mObject& _o)
|
||||
}
|
||||
|
||||
void ImportTest::checkExpectedState(State const& _stateExpect, State const& _statePost, WhenError _throw)
|
||||
{
|
||||
stateOptionsMap defaultMap;
|
||||
checkExpectedState(_stateExpect, _statePost, defaultMap, _throw);
|
||||
}
|
||||
|
||||
void ImportTest::checkExpectedState(State const& _stateExpect, State const& _statePost, stateOptionsMap const& _expectedStateOptions, WhenError _throw)
|
||||
{
|
||||
#define CHECK(a,b) \
|
||||
if (_throw == WhenError::Throw) \
|
||||
@ -189,24 +225,51 @@ void ImportTest::checkExpectedState(State const& _stateExpect, State const& _sta
|
||||
{
|
||||
CHECK(_statePost.addressInUse(a.first), "Filling Test: " << a.first << " missing expected address!");
|
||||
if (_statePost.addressInUse(a.first))
|
||||
{
|
||||
ImportStateOptions addressOptions(true);
|
||||
if(_expectedStateOptions.size())
|
||||
{
|
||||
try
|
||||
{
|
||||
addressOptions = _expectedStateOptions.at(a.first);
|
||||
}
|
||||
catch(std::out_of_range)
|
||||
{
|
||||
BOOST_ERROR("expectedStateOptions map does not match expectedState in checkExpectedState!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (addressOptions.m_bHasBalance)
|
||||
{
|
||||
CHECK(_stateExpect.balance(a.first) == _statePost.balance(a.first),
|
||||
"Check State: " << a.first << ": incorrect balance " << _statePost.balance(a.first) << ", expected " << _stateExpect.balance(a.first));
|
||||
}
|
||||
|
||||
if (addressOptions.m_bHasNonce)
|
||||
{
|
||||
CHECK(_stateExpect.transactionsFrom(a.first) == _statePost.transactionsFrom(a.first),
|
||||
"Check State: " << a.first << ": incorrect nonce " << _statePost.transactionsFrom(a.first) << ", expected " << _stateExpect.transactionsFrom(a.first));
|
||||
}
|
||||
|
||||
if (addressOptions.m_bHasStorage)
|
||||
{
|
||||
map<u256, u256> stateStorage = _statePost.storage(a.first);
|
||||
for (auto const& s: _stateExpect.storage(a.first))
|
||||
{
|
||||
CHECK(stateStorage[s.first] == s.second,
|
||||
"Check State: " << a.first << ": incorrect storage [" << s.first << "] = " << toHex(stateStorage[s.first]) << ", expected [" << s.first << "] = " << toHex(s.second));
|
||||
}
|
||||
}
|
||||
|
||||
if (addressOptions.m_bHasCode)
|
||||
{
|
||||
CHECK(_stateExpect.code(a.first) == _statePost.code(a.first),
|
||||
"Check State: " << a.first << ": incorrect code '" << toHex(_statePost.code(a.first)) << "', expected '" << toHex(_stateExpect.code(a.first)) << "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ImportTest::exportTest(bytes const& _output, State const& _statePost)
|
||||
{
|
||||
@ -219,9 +282,10 @@ void ImportTest::exportTest(bytes const& _output, State const& _statePost)
|
||||
// compare expected state with post state
|
||||
if (m_TestObject.count("expect") > 0)
|
||||
{
|
||||
stateOptionsMap stateMap;
|
||||
State expectState(Address(), OverlayDB(), eth::BaseState::Empty);
|
||||
importState(m_TestObject["expect"].get_obj(), expectState);
|
||||
checkExpectedState(expectState, _statePost, Options::get().checkState ? WhenError::Throw : WhenError::DontThrow);
|
||||
importState(m_TestObject["expect"].get_obj(), expectState, stateMap);
|
||||
checkExpectedState(expectState, _statePost, stateMap, Options::get().checkState ? WhenError::Throw : WhenError::DontThrow);
|
||||
m_TestObject.erase(m_TestObject.find("expect"));
|
||||
}
|
||||
|
||||
|
14
TestHelper.h
14
TestHelper.h
@ -97,6 +97,17 @@ namespace test
|
||||
} \
|
||||
while (0)
|
||||
|
||||
struct ImportStateOptions
|
||||
{
|
||||
ImportStateOptions():m_bHasBalance(false), m_bHasNonce(false), m_bHasCode(false), m_bHasStorage(false) {}
|
||||
ImportStateOptions(bool _bSetAll):m_bHasBalance(_bSetAll), m_bHasNonce(_bSetAll), m_bHasCode(_bSetAll), m_bHasStorage(_bSetAll) {}
|
||||
bool isAllSet() {return m_bHasBalance && m_bHasNonce && m_bHasCode && m_bHasStorage;}
|
||||
bool m_bHasBalance;
|
||||
bool m_bHasNonce;
|
||||
bool m_bHasCode;
|
||||
bool m_bHasStorage;
|
||||
};
|
||||
typedef std::map<Address, ImportStateOptions> stateOptionsMap;
|
||||
|
||||
class ImportTest
|
||||
{
|
||||
@ -106,9 +117,12 @@ public:
|
||||
// imports
|
||||
void importEnv(json_spirit::mObject& _o);
|
||||
static void importState(json_spirit::mObject& _o, eth::State& _state);
|
||||
static void importState(json_spirit::mObject& _o, eth::State& _state, stateOptionsMap& _stateOptionsMap);
|
||||
void importTransaction(json_spirit::mObject& _o);
|
||||
|
||||
void exportTest(bytes const& _output, eth::State const& _statePost);
|
||||
static void checkExpectedState(eth::State const& _stateExpect, eth::State const& _statePost, WhenError _throw = WhenError::Throw);
|
||||
static void checkExpectedState(eth::State const& _stateExpect, eth::State const& _statePost, stateOptionsMap const& _expectedStateOptions, WhenError _throw = WhenError::Throw);
|
||||
|
||||
eth::State m_statePre;
|
||||
eth::State m_statePost;
|
||||
|
Loading…
Reference in New Issue
Block a user