aboutsummaryrefslogtreecommitdiffstats
path: root/TestHelper.cpp
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-04-15 23:43:23 +0800
committerchriseth <c@ethdev.com>2015-04-15 23:43:23 +0800
commit6753e0a8e6796e99ee826c28c7bcbde55348b07d (patch)
treefdcb51c9c0b26aab635680ff2f2cb330cf4f4bd2 /TestHelper.cpp
parentc19d10321a116bec4ed08aabf3b3c8d74bf61608 (diff)
parentc5f08fe6dff58f973da8b888d25afa3ef967936e (diff)
downloaddexon-solidity-6753e0a8e6796e99ee826c28c7bcbde55348b07d.tar
dexon-solidity-6753e0a8e6796e99ee826c28c7bcbde55348b07d.tar.gz
dexon-solidity-6753e0a8e6796e99ee826c28c7bcbde55348b07d.tar.bz2
dexon-solidity-6753e0a8e6796e99ee826c28c7bcbde55348b07d.tar.lz
dexon-solidity-6753e0a8e6796e99ee826c28c7bcbde55348b07d.tar.xz
dexon-solidity-6753e0a8e6796e99ee826c28c7bcbde55348b07d.tar.zst
dexon-solidity-6753e0a8e6796e99ee826c28c7bcbde55348b07d.zip
Merge remote-tracking branch 'ethereum/develop' into sol_overloadingFunctions
Conflicts: libsolidity/Types.cpp
Diffstat (limited to 'TestHelper.cpp')
-rw-r--r--TestHelper.cpp170
1 files changed, 153 insertions, 17 deletions
diff --git a/TestHelper.cpp b/TestHelper.cpp
index dd7c09ea..93c564e6 100644
--- a/TestHelper.cpp
+++ b/TestHelper.cpp
@@ -62,12 +62,45 @@ void connectClients(Client& c1, Client& c2)
c2.connect("127.0.0.1", c1Port);
#endif
}
+
+void mine(State& s, BlockChain const& _bc)
+{
+ s.commitToMine(_bc);
+ GenericFarm<ProofOfWork> f;
+ bool completed = false;
+ f.onSolutionFound([&](ProofOfWork::Solution sol)
+ {
+ return completed = s.completeMine<ProofOfWork>(sol);
+ });
+ f.setWork(s.info());
+ f.startCPU();
+ while (!completed)
+ this_thread::sleep_for(chrono::milliseconds(20));
+}
+
+void mine(BlockInfo& _bi)
+{
+ GenericFarm<ProofOfWork> f;
+ bool completed = false;
+ f.onSolutionFound([&](ProofOfWork::Solution sol)
+ {
+ ProofOfWork::assignResult(sol, _bi);
+ return completed = true;
+ });
+ f.setWork(_bi);
+ f.startCPU();
+ while (!completed)
+ this_thread::sleep_for(chrono::milliseconds(20));
+}
+
}
namespace test
{
struct ValueTooLarge: virtual Exception {};
+struct MissingFields : virtual Exception {};
+
bigint const c_max256plus1 = bigint(1) << 256;
ImportTest::ImportTest(json_spirit::mObject& _o, bool isFiller):
@@ -106,41 +139,75 @@ 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 balance = 0;
+ u256 nonce = 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") );
+ balance = toInt(o["balance"]);
+ }
- 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("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") );
+ nonce = 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(balance, Account::ContractConception);
_state.m_cache[address].setCode(code);
}
else
- _state.m_cache[address] = Account(toInt(o["balance"]), Account::NormalCreation);
+ _state.m_cache[address] = Account(balance, 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 < nonce; ++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)
+ {
+ //check that every parameter was declared in state object
+ if (!stateOptionMap.second.isAllSet())
+ BOOST_THROW_EXCEPTION(MissingFields() << errinfo_comment("Import State: Missing state fields!"));
}
}
@@ -172,7 +239,65 @@ void ImportTest::importTransaction(json_spirit::mObject& _o)
{
RLPStream transactionRLPStream = createRLPStreamFromTransactionFields(_o);
RLP transactionRLP(transactionRLPStream.out());
- m_transaction = Transaction(transactionRLP.data(), CheckSignature::Sender);
+ m_transaction = Transaction(transactionRLP.data(), CheckTransaction::Everything);
+ }
+}
+
+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); \
+ else \
+ BOOST_WARN_MESSAGE(a,b); \
+ }
+
+ for (auto const& a: _stateExpect.addresses())
+ {
+ 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));
+
+ //Check for unexpected storage values
+ stateStorage = _stateExpect.storage(a.first);
+ for (auto const& s: _statePost.storage(a.first))
+ CHECK(stateStorage[s.first] == s.second,
+ "Check State: " << a.first << ": incorrect storage [" << s.first << "] = " << toHex(s.second) << ", expected [" << s.first << "] = " << toHex(stateStorage[s.first]));
+ }
+
+ 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)) << "'");
+ }
}
}
@@ -184,8 +309,17 @@ void ImportTest::exportTest(bytes const& _output, State const& _statePost)
// export logs
m_TestObject["logs"] = exportLog(_statePost.pending().size() ? _statePost.log(0) : LogEntries());
- // export post state
+ // compare expected state with post state
+ if (m_TestObject.count("expect") > 0)
+ {
+ stateOptionsMap stateMap;
+ State expectState(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"));
+ }
+ // export post state
m_TestObject["post"] = fillJsonWithState(_statePost);
m_TestObject["postStateRoot"] = toHex(_statePost.rootHash().asBytes());
@@ -559,6 +693,8 @@ Options::Options()
inputLimits = true;
else if (arg == "--bigdata")
bigData = true;
+ else if (arg == "--checkstate")
+ checkState = true;
else if (arg == "--all")
{
performance = true;