mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
update test to new Block/State refactoring - credit to winsvega and chriseth
This commit is contained in:
parent
e0863fbd27
commit
4626890913
@ -25,6 +25,7 @@
|
||||
#include <chrono>
|
||||
#include <libethcore/EthashAux.h>
|
||||
#include <libethereum/Client.h>
|
||||
#include <libevm/ExtVMFace.h>
|
||||
#include <liblll/Compiler.h>
|
||||
#include <libevm/VMFactory.h>
|
||||
#include "Stats.h"
|
||||
@ -61,7 +62,7 @@ void connectClients(Client& c1, Client& c2)
|
||||
#endif
|
||||
}
|
||||
|
||||
void mine(State& s, BlockChain const& _bc)
|
||||
void mine(Block& s, BlockChain const& _bc)
|
||||
{
|
||||
std::unique_ptr<SealEngineFace> sealer(Ethash::createSealEngine());
|
||||
s.commitToSeal(_bc);
|
||||
@ -94,23 +95,43 @@ struct MissingFields : virtual Exception {};
|
||||
|
||||
bigint const c_max256plus1 = bigint(1) << 256;
|
||||
|
||||
ImportTest::ImportTest(json_spirit::mObject& _o, bool isFiller):
|
||||
m_statePre(OverlayDB(), eth::BaseState::Empty, Address(_o["env"].get_obj()["currentCoinbase"].get_str())),
|
||||
m_statePost(OverlayDB(), eth::BaseState::Empty, Address(_o["env"].get_obj()["currentCoinbase"].get_str())),
|
||||
m_environment(m_envInfo),
|
||||
ImportTest::ImportTest(json_spirit::mObject& _o, bool isFiller, testType testTemplate):
|
||||
m_statePre(OverlayDB(), eth::BaseState::Empty),
|
||||
m_statePost(OverlayDB(), eth::BaseState::Empty),
|
||||
m_testObject(_o)
|
||||
{
|
||||
importEnv(_o["env"].get_obj());
|
||||
importState(_o["pre"].get_obj(), m_statePre);
|
||||
importTransaction(_o["transaction"].get_obj());
|
||||
|
||||
if (!isFiller)
|
||||
if (testTemplate == testType::StateTests)
|
||||
{
|
||||
importState(_o["post"].get_obj(), m_statePost);
|
||||
m_environment.sub.logs = importLog(_o["logs"].get_array());
|
||||
importEnv(_o["env"].get_obj());
|
||||
importTransaction(_o["transaction"].get_obj());
|
||||
importState(_o["pre"].get_obj(), m_statePre);
|
||||
if (!isFiller)
|
||||
{
|
||||
if (_o.count("post"))
|
||||
importState(_o["post"].get_obj(), m_statePost);
|
||||
else
|
||||
importState(_o["postState"].get_obj(), m_statePost);
|
||||
m_logsExpected = importLog(_o["logs"].get_array());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//executes an imported transacton on preState
|
||||
bytes ImportTest::executeTest()
|
||||
{
|
||||
ExecutionResult res;
|
||||
eth::State tmpState = m_statePre;
|
||||
|
||||
std::pair<ExecutionResult, TransactionReceipt> execOut = m_statePre.execute(m_envInfo, m_transaction);
|
||||
res = execOut.first;
|
||||
m_logs = execOut.second.log();
|
||||
m_statePre.commit();
|
||||
m_statePost = m_statePre;
|
||||
m_statePre = tmpState;
|
||||
|
||||
return res.output;
|
||||
}
|
||||
|
||||
json_spirit::mObject& ImportTest::makeAllFieldsHex(json_spirit::mObject& _o)
|
||||
{
|
||||
static const set<string> hashes {"bloom" , "coinbase", "hash", "mixHash", "parentHash", "receiptTrie",
|
||||
@ -139,24 +160,25 @@ json_spirit::mObject& ImportTest::makeAllFieldsHex(json_spirit::mObject& _o)
|
||||
|
||||
void ImportTest::importEnv(json_spirit::mObject& _o)
|
||||
{
|
||||
assert(_o.count("previousHash") > 0);
|
||||
assert(_o.count("currentGasLimit") > 0);
|
||||
assert(_o.count("currentDifficulty") > 0);
|
||||
assert(_o.count("currentDifficulty") > 0);
|
||||
assert(_o.count("currentNumber") > 0);
|
||||
assert(_o.count("currentTimestamp") > 0);
|
||||
assert(_o.count("currentCoinbase") > 0);
|
||||
assert(_o.count("currentNumber") > 0);
|
||||
m_envInfo.setBeneficiary(Address(_o["currentCoinbase"].get_str()));
|
||||
m_envInfo.setGasLimit(toInt(_o["currentGasLimit"]));
|
||||
m_envInfo.setDifficulty(toInt(_o["currentDifficulty"]));
|
||||
m_envInfo.setNumber(toInt(_o["currentNumber"]));
|
||||
m_envInfo.setGasLimit(toInt(_o["currentGasLimit"]));
|
||||
m_envInfo.setTimestamp(toInt(_o["currentTimestamp"]));
|
||||
m_envInfo.setBeneficiary(Address(_o["currentCoinbase"].get_str()));
|
||||
m_envInfo.setLastHashes( lastHashes( m_envInfo.number() ) );
|
||||
}
|
||||
|
||||
// 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, AccountMaskMap& o_mask)
|
||||
{
|
||||
_state.populateFrom(jsonToAccountMap(json_spirit::write_string(_o, false), &o_mask));
|
||||
{
|
||||
std::string jsondata = json_spirit::write_string((json_spirit::mValue)_o, false);
|
||||
_state.populateFrom(jsonToAccountMap(jsondata, &o_mask));
|
||||
}
|
||||
|
||||
void ImportTest::importState(json_spirit::mObject& _o, State& _state)
|
||||
@ -215,7 +237,7 @@ void ImportTest::importTransaction(json_spirit::mObject& _o)
|
||||
}
|
||||
}
|
||||
|
||||
void ImportTest::checkExpectedState(State const& _stateExpect, State const& _statePost, stateOptionsMap const _expectedStateOptions, WhenError _throw)
|
||||
void ImportTest::compareStates(State const& _stateExpect, State const& _statePost, AccountMaskMap const _expectedStateOptions, WhenError _throw)
|
||||
{
|
||||
#define CHECK(a,b) \
|
||||
{ \
|
||||
@ -230,7 +252,7 @@ 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);
|
||||
AccountMask addressOptions(true);
|
||||
if(_expectedStateOptions.size())
|
||||
{
|
||||
try
|
||||
@ -244,15 +266,15 @@ void ImportTest::checkExpectedState(State const& _stateExpect, State const& _sta
|
||||
}
|
||||
}
|
||||
|
||||
if (addressOptions.m_bHasBalance)
|
||||
if (addressOptions.hasBalance())
|
||||
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)
|
||||
if (addressOptions.hasNonce())
|
||||
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)
|
||||
if (addressOptions.hasStorage())
|
||||
{
|
||||
unordered_map<u256, u256> stateStorage = _statePost.storage(a.first);
|
||||
for (auto const& s: _stateExpect.storage(a.first))
|
||||
@ -266,14 +288,14 @@ void ImportTest::checkExpectedState(State const& _stateExpect, State const& _sta
|
||||
"Check State: " << a.first << ": incorrect storage [" << s.first << "] = " << toHex(s.second) << ", expected [" << s.first << "] = " << toHex(stateStorage[s.first]));
|
||||
}
|
||||
|
||||
if (addressOptions.m_bHasCode)
|
||||
if (addressOptions.hasCode())
|
||||
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)
|
||||
void ImportTest::exportTest(bytes const& _output)
|
||||
{
|
||||
// export output
|
||||
|
||||
@ -291,22 +313,22 @@ void ImportTest::exportTest(bytes const& _output, State const& _statePost)
|
||||
m_testObject.erase(m_testObject.find("expectOut"));
|
||||
}
|
||||
|
||||
// export logs
|
||||
m_testObject["logs"] = exportLog(_statePost.pending().size() ? _statePost.log(0) : LogEntries());
|
||||
// export logs
|
||||
m_testObject["logs"] = exportLog(m_logs);
|
||||
|
||||
// compare expected state with post state
|
||||
if (m_testObject.count("expect") > 0)
|
||||
{
|
||||
stateOptionsMap stateMap;
|
||||
eth::AccountMaskMap 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);
|
||||
compareStates(expectState, m_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());
|
||||
m_testObject["post"] = fillJsonWithState(m_statePost);
|
||||
m_testObject["postStateRoot"] = toHex(m_statePost.rootHash().asBytes());
|
||||
|
||||
// export pre state
|
||||
m_testObject["pre"] = fillJsonWithState(m_statePre);
|
||||
|
27
TestHelper.h
27
TestHelper.h
@ -32,6 +32,7 @@
|
||||
#include <libevm/ExtVMFace.h>
|
||||
#include <libtestutils/Common.h>
|
||||
|
||||
|
||||
#ifdef NOBOOST
|
||||
#define TBOOST_REQUIRE(arg) if(arg == false) throw dev::Exception();
|
||||
#define TBOOST_REQUIRE_EQUAL(arg1, arg2) if(arg1 != arg2) throw dev::Exception();
|
||||
@ -62,7 +63,7 @@ class State;
|
||||
|
||||
void mine(Client& c, int numBlocks);
|
||||
void connectClients(Client& c1, Client& c2);
|
||||
void mine(State& _s, BlockChain const& _bc);
|
||||
void mine(Block& _s, BlockChain const& _bc);
|
||||
void mine(Ethash::BlockHeader& _bi);
|
||||
|
||||
}
|
||||
@ -122,11 +123,17 @@ namespace test
|
||||
} \
|
||||
while (0)
|
||||
|
||||
enum class testType
|
||||
{
|
||||
StateTests,
|
||||
BlockChainTests,
|
||||
Other
|
||||
};
|
||||
|
||||
class ImportTest
|
||||
{
|
||||
public:
|
||||
ImportTest(json_spirit::mObject& _o): m_environment(m_envInfo), m_testObject(_o) {}
|
||||
ImportTest(json_spirit::mObject& _o, bool isFiller);
|
||||
ImportTest(json_spirit::mObject& _o, bool isFiller, testType testTemplate = testType::StateTests);
|
||||
|
||||
// imports
|
||||
void importEnv(json_spirit::mObject& _o);
|
||||
@ -135,14 +142,16 @@ public:
|
||||
void importTransaction(json_spirit::mObject& _o);
|
||||
static json_spirit::mObject& makeAllFieldsHex(json_spirit::mObject& _o);
|
||||
|
||||
void exportTest(bytes const& _output, eth::State const& _statePost);
|
||||
static void checkExpectedState(eth::State const& _stateExpect, eth::State const& _statePost, stateOptionsMap const _expectedStateOptions = stateOptionsMap(), WhenError _throw = WhenError::Throw);
|
||||
bytes executeTest();
|
||||
void exportTest(bytes const& _output);
|
||||
static void compareStates(eth::State const& _stateExpect, eth::State const& _statePost, eth::AccountMaskMap const _expectedStateOptions = eth::AccountMaskMap(), WhenError _throw = WhenError::Throw);
|
||||
|
||||
eth::State m_statePre;
|
||||
eth::State m_statePost;
|
||||
eth::EnvInfo m_envInfo;
|
||||
eth::ExtVMFace m_environment;
|
||||
eth::Transaction m_transaction;
|
||||
eth::Transaction m_transaction;
|
||||
eth::LogEntries m_logs;
|
||||
eth::LogEntries m_logsExpected;
|
||||
|
||||
private:
|
||||
json_spirit::mObject& m_testObject;
|
||||
@ -196,7 +205,7 @@ void doVMTests(json_spirit::mValue& v, bool _fillin);
|
||||
void doBlockchainTests(json_spirit::mValue& _v, bool _fillin);
|
||||
void doRlpTests(json_spirit::mValue& v, bool _fillin);
|
||||
|
||||
template<typename mapType>
|
||||
/*template<typename mapType>
|
||||
void checkAddresses(mapType& _expectedAddrs, mapType& _resultAddrs)
|
||||
{
|
||||
for (auto& resultPair : _resultAddrs)
|
||||
@ -207,7 +216,7 @@ void checkAddresses(mapType& _expectedAddrs, mapType& _resultAddrs)
|
||||
TBOOST_ERROR("Missing result address " << resultAddr);
|
||||
}
|
||||
TBOOST_CHECK((_expectedAddrs == _resultAddrs));
|
||||
}
|
||||
}*/
|
||||
|
||||
class Options
|
||||
{
|
||||
|
@ -101,7 +101,9 @@ void ClientBaseFixture::enumerateClients(std::function<void(Json::Value const&,
|
||||
{
|
||||
enumerateBlockchains([&callback](Json::Value const& _json, BlockChain const& _bc, State _state) -> void
|
||||
{
|
||||
FixedClient client(_bc, _state);
|
||||
cerr << "void ClientBaseFixture::enumerateClients. FixedClient now accepts block not sate!" << endl;
|
||||
_state.commit(); //unused variable. remove this line
|
||||
FixedClient client(_bc, eth::Block {});
|
||||
callback(_json, client);
|
||||
});
|
||||
}
|
||||
|
@ -545,7 +545,7 @@ BOOST_AUTO_TEST_CASE(multisig_value_transfer)
|
||||
// 4 owners, set required to 3
|
||||
BOOST_REQUIRE(callContractFunction("changeRequirement(uint256)", u256(3)) == encodeArgs());
|
||||
// check that balance is and stays zero at destination address
|
||||
h256 opHash("8f27f478ebcfaf28b0c354f4809ace8087000d668b89c8bc3b1b608bfdbe6654");
|
||||
h256 opHash("6244b4fa93f73e09db0ae52750095ca0364a76b72bc01723c97011fcb876cc9e");
|
||||
BOOST_CHECK_EQUAL(m_state.balance(Address(0x05)), 0);
|
||||
m_sender = Address(0x12);
|
||||
BOOST_REQUIRE(callContractFunction("execute(address,uint256,bytes)", h256(0x05), 100, 0x60, 0x00) == encodeArgs(opHash));
|
||||
@ -596,7 +596,7 @@ BOOST_AUTO_TEST_CASE(revoke_transaction)
|
||||
BOOST_REQUIRE(callContractFunction("changeRequirement(uint256)", u256(3)) == encodeArgs());
|
||||
// create a transaction
|
||||
Address deployer = m_sender;
|
||||
h256 opHash("8f27f478ebcfaf28b0c354f4809ace8087000d668b89c8bc3b1b608bfdbe6654");
|
||||
h256 opHash("6244b4fa93f73e09db0ae52750095ca0364a76b72bc01723c97011fcb876cc9e");
|
||||
BOOST_CHECK_EQUAL(m_state.balance(Address(0x05)), 0);
|
||||
m_sender = Address(0x12);
|
||||
BOOST_REQUIRE(callContractFunction("execute(address,uint256,bytes)", h256(0x05), 100, 0x60, 0x00) == encodeArgs(opHash));
|
||||
|
@ -1151,8 +1151,10 @@ BOOST_AUTO_TEST_CASE(blockchain)
|
||||
" blockNumber = block.number;\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
m_envInfo.setBeneficiary(Address(0x123));
|
||||
m_envInfo.setNumber(7);
|
||||
compileAndRun(sourceCode, 27);
|
||||
BOOST_CHECK(callContractFunctionWithValue("someInfo()", 28) == encodeArgs(28, 0, 1));
|
||||
BOOST_CHECK(callContractFunctionWithValue("someInfo()", 28) == encodeArgs(28, 0x123, 7));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(msg_sig)
|
||||
@ -1187,12 +1189,14 @@ BOOST_AUTO_TEST_CASE(msg_sig_after_internal_call_is_same)
|
||||
BOOST_AUTO_TEST_CASE(now)
|
||||
{
|
||||
char const* sourceCode = "contract test {\n"
|
||||
" function someInfo() returns (bool success) {\n"
|
||||
" return block.timestamp == now && now > 0;\n"
|
||||
" function someInfo() returns (bool equal, uint val) {\n"
|
||||
" equal = block.timestamp == now;\n"
|
||||
" val = now;\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
m_envInfo.setTimestamp(9);
|
||||
compileAndRun(sourceCode);
|
||||
BOOST_CHECK(callContractFunction("someInfo()") == encodeArgs(true));
|
||||
BOOST_CHECK(callContractFunction("someInfo()") == encodeArgs(true, 9));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(type_conversions_cleanup)
|
||||
@ -5099,31 +5103,6 @@ BOOST_AUTO_TEST_CASE(memory_structs_with_mappings)
|
||||
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(string_bytes_conversion)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract Test {
|
||||
string s;
|
||||
bytes b;
|
||||
function f(string _s, uint n) returns (byte) {
|
||||
b = bytes(_s);
|
||||
s = string(b);
|
||||
return bytes(s)[n];
|
||||
}
|
||||
function l() returns (uint) { return bytes(s).length; }
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "Test");
|
||||
BOOST_CHECK(callContractFunction(
|
||||
"f(string,uint256)",
|
||||
u256(0x40),
|
||||
u256(2),
|
||||
u256(6),
|
||||
string("abcdef")
|
||||
) == encodeArgs("c"));
|
||||
BOOST_CHECK(callContractFunction("l()") == encodeArgs(u256(6)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(string_as_mapping_key)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
|
@ -2149,23 +2149,6 @@ BOOST_AUTO_TEST_CASE(memory_structs_with_mappings)
|
||||
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(string_bytes_conversion)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract Test {
|
||||
string s;
|
||||
bytes b;
|
||||
function h(string _s) external { bytes(_s).length; }
|
||||
function i(string _s) internal { bytes(_s).length; }
|
||||
function j() internal { bytes(s).length; }
|
||||
function k(bytes _b) external { string(_b); }
|
||||
function l(bytes _b) internal { string(_b); }
|
||||
function m() internal { string(b); }
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
}
|
||||
|
@ -44,7 +44,6 @@ public:
|
||||
ExecutionFramework()
|
||||
{
|
||||
g_logVerbosity = 0;
|
||||
m_state.resetCurrent();
|
||||
}
|
||||
|
||||
bytes const& compileAndRunWithoutCheck(
|
||||
@ -185,7 +184,7 @@ protected:
|
||||
void sendMessage(bytes const& _data, bool _isCreation, u256 const& _value = 0)
|
||||
{
|
||||
m_state.addBalance(m_sender, _value); // just in case
|
||||
eth::Executive executive(m_state, eth::EnvInfo(), 0);
|
||||
eth::Executive executive(m_state, m_envInfo, 0);
|
||||
eth::ExecutionResult res;
|
||||
executive.setResultRecipient(res);
|
||||
eth::Transaction t =
|
||||
@ -226,6 +225,7 @@ protected:
|
||||
dev::solidity::CompilerStack m_compiler;
|
||||
Address m_sender;
|
||||
Address m_contractAddress;
|
||||
eth::EnvInfo m_envInfo;
|
||||
eth::State m_state;
|
||||
u256 const m_gasPrice = 100 * eth::szabo;
|
||||
u256 const m_gas = 100000000;
|
||||
|
Loading…
Reference in New Issue
Block a user