diff options
-rw-r--r-- | TestHelper.cpp | 122 | ||||
-rw-r--r-- | TestHelper.h | 14 |
2 files changed, 107 insertions, 29 deletions
diff --git a/TestHelper.cpp b/TestHelper.cpp index ca7caf3d..a830636d 100644 --- a/TestHelper.cpp +++ b/TestHelper.cpp @@ -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 (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<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 } } @@ -179,6 +209,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) \ BOOST_CHECK_MESSAGE(a,b); \ @@ -190,20 +226,47 @@ 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)) { - CHECK(_stateExpect.balance(a.first) == _statePost.balance(a.first), - "Check State: " << a.first << ": incorrect balance " << _statePost.balance(a.first) << ", expected " << _stateExpect.balance(a.first)); - CHECK(_stateExpect.transactionsFrom(a.first) == _statePost.transactionsFrom(a.first), - "Check State: " << a.first << ": incorrect nonce " << _statePost.transactionsFrom(a.first) << ", expected " << _stateExpect.transactionsFrom(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)); + } - map<u256, u256> stateStorage = _statePost.storage(a.first); - for (auto const& s: _stateExpect.storage(a.first)) + if (addressOptions.m_bHasNonce) { - CHECK(stateStorage[s.first] == s.second, - "Check State: " << a.first << ": incorrect storage [" << s.first << "] = " << toHex(stateStorage[s.first]) << ", expected [" << s.first << "] = " << toHex(s.second)); + CHECK(_stateExpect.transactionsFrom(a.first) == _statePost.transactionsFrom(a.first), + "Check State: " << a.first << ": incorrect nonce " << _statePost.transactionsFrom(a.first) << ", expected " << _stateExpect.transactionsFrom(a.first)); } - 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_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)) << "'"); + } } } } @@ -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 b4002aeb..81251649 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<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; |