From adba4fb9a136ec27d6fc3e295c43a6f0f04ae865 Mon Sep 17 00:00:00 2001 From: winsvega Date: Fri, 27 Mar 2015 01:05:45 +0300 Subject: [PATCH] Check State Incomplete State Support --- TestHelper.cpp | 124 +++++++++++++++++++++++++++++++++++++------------ TestHelper.h | 14 ++++++ 2 files changed, 108 insertions(+), 30 deletions(-) diff --git a/TestHelper.cpp b/TestHelper.cpp index ca7caf3d4..a830636de 100644 --- a/TestHelper.cpp +++ b/TestHelper.cpp @@ -25,7 +25,6 @@ #include #include -#include #include #include @@ -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 (bigint(o["balance"].get_str()) >= c_max256plus1) - BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("State 'balance' is equal or greater than 2**256") ); - if (bigint(o["nonce"].get_str()) >= c_max256plus1) - BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("State 'nonce' is equal or greater than 2**256") ); + 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); - for (auto const& j: o["storage"].get_obj()) - _state.setStorage(address, toInt(j.first), toInt(j.second)); + 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 stateStorage = _statePost.storage(a.first); - for (auto const& s: _stateExpect.storage(a.first)) + ImportStateOptions addressOptions(true); + if(_expectedStateOptions.size()) { - CHECK(stateStorage[s.first] == s.second, - "Check State: " << a.first << ": incorrect storage [" << s.first << "] = " << toHex(stateStorage[s.first]) << ", expected [" << s.first << "] = " << toHex(s.second)); + try + { + addressOptions = _expectedStateOptions.at(a.first); + } + catch(std::out_of_range) + { + BOOST_ERROR("expectedStateOptions map does not match expectedState in checkExpectedState!"); + break; + } } - 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)) << "'"); + 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 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)) << "'"); + } } } } @@ -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) { - State expectState(Address(), OverlayDB(), eth::BaseState::Empty); - importState(m_TestObject["expect"].get_obj(), expectState); - checkExpectedState(expectState, _statePost, Options::get().checkState ? WhenError::Throw : WhenError::DontThrow); + stateOptionsMap stateMap; + State expectState(Address(), OverlayDB(), eth::BaseState::Empty); + 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")); } diff --git a/TestHelper.h b/TestHelper.h index b4002aebe..81251649a 100644 --- a/TestHelper.h +++ b/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 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;