aboutsummaryrefslogtreecommitdiffstats
path: root/test/TestHelper.cpp
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-08-20 06:55:41 +0800
committerchriseth <c@ethdev.com>2015-08-20 06:55:41 +0800
commit8d9eb6830781cc107d09a92a59f71914a341ad3c (patch)
tree39fd4a279c6aa7fefa314e10b615bc37137905d4 /test/TestHelper.cpp
parent4c8b2202575b8c169b6dda9f81a0c6f171361df9 (diff)
downloaddexon-solidity-8d9eb6830781cc107d09a92a59f71914a341ad3c.tar.gz
dexon-solidity-8d9eb6830781cc107d09a92a59f71914a341ad3c.tar.zst
dexon-solidity-8d9eb6830781cc107d09a92a59f71914a341ad3c.zip
Modularise CMakeLists files and integrate tests.
Diffstat (limited to 'test/TestHelper.cpp')
-rw-r--r--test/TestHelper.cpp833
1 files changed, 0 insertions, 833 deletions
diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp
index e7633c5e..79242f83 100644
--- a/test/TestHelper.cpp
+++ b/test/TestHelper.cpp
@@ -21,846 +21,13 @@
#include "TestHelper.h"
-#include <thread>
-#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"
-
using namespace std;
-using namespace dev::eth;
namespace dev
{
-namespace eth
-{
-
-void mine(Client& c, int numBlocks)
-{
- auto startBlock = c.blockChain().details().number;
-
- c.startMining();
- while(c.blockChain().details().number < startBlock + numBlocks)
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
- c.stopMining();
-}
-
-void connectClients(Client& c1, Client& c2)
-{
- (void)c1;
- (void)c2;
- // TODO: Move to WebThree. eth::Client no longer handles networking.
-#if 0
- short c1Port = 20000;
- short c2Port = 21000;
- c1.startNetwork(c1Port);
- c2.startNetwork(c2Port);
- c2.connect("127.0.0.1", c1Port);
-#endif
-}
-
-void mine(Block& s, BlockChain const& _bc)
-{
- std::unique_ptr<SealEngineFace> sealer(Ethash::createSealEngine());
- s.commitToSeal(_bc);
- Notified<bytes> sealed;
- sealer->onSealGenerated([&](bytes const& sealedHeader){ sealed = sealedHeader; });
- sealer->generateSeal(s.info());
- sealed.waitNot({});
- sealer.reset();
- s.sealBlock(sealed);
-}
-
-void mine(Ethash::BlockHeader& _bi)
-{
- std::unique_ptr<SealEngineFace> sealer(Ethash::createSealEngine());
- Notified<bytes> sealed;
- sealer->onSealGenerated([&](bytes const& sealedHeader){ sealed = sealedHeader; });
- sealer->generateSeal(_bi);
- sealed.waitNot({});
- sealer.reset();
- _bi = Ethash::BlockHeader(sealed, CheckNothing, h256{}, HeaderData);
-}
-
-}
-
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, testType testTemplate):
- m_statePre(OverlayDB(), eth::BaseState::Empty),
- m_statePost(OverlayDB(), eth::BaseState::Empty),
- m_testObject(_o)
-{
- if (testTemplate == testType::StateTests)
- {
- 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;
- try
- {
- std::pair<ExecutionResult, TransactionReceipt> execOut = m_statePre.execute(m_envInfo, m_transaction);
- res = execOut.first;
- m_logs = execOut.second.log();
- }
- catch (Exception const& _e)
- {
- cnote << "Exception: " << diagnostic_information(_e);
- }
- catch (std::exception const& _e)
- {
- cnote << "state execution exception: " << _e.what();
- }
-
- 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",
- "stateRoot", "transactionsTrie", "uncleHash", "currentCoinbase",
- "previousHash", "to", "address", "caller", "origin", "secretKey", "data"};
-
- for (auto& i: _o)
- {
- std::string key = i.first;
- if (hashes.count(key))
- continue;
-
- std::string str;
- json_spirit::mValue value = i.second;
-
- if (value.type() == json_spirit::int_type)
- str = toString(value.get_int());
- else if (value.type() == json_spirit::str_type)
- str = value.get_str();
- else continue;
-
- _o[key] = (str.substr(0, 2) == "0x") ? str : toCompactHex(toInt(str), HexPrefix::Add, 1);
- }
- return _o;
-}
-
-void ImportTest::importEnv(json_spirit::mObject& _o)
-{
- assert(_o.count("currentGasLimit") > 0);
- assert(_o.count("currentDifficulty") > 0);
- assert(_o.count("currentNumber") > 0);
- assert(_o.count("currentTimestamp") > 0);
- assert(_o.count("currentCoinbase") > 0);
- m_envInfo.setGasLimit(toInt(_o["currentGasLimit"]));
- m_envInfo.setDifficulty(toInt(_o["currentDifficulty"]));
- m_envInfo.setNumber(toInt(_o["currentNumber"]));
- 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)
-{
- 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)
-{
- AccountMaskMap mask;
- importState(_o, _state, mask);
- for (auto const& i: mask)
- //check that every parameter was declared in state object
- if (!i.second.allSet())
- BOOST_THROW_EXCEPTION(MissingFields() << errinfo_comment("Import State: Missing state fields!"));
-}
-
-void ImportTest::importTransaction (json_spirit::mObject const& _o, eth::Transaction& o_tr)
-{
- if (_o.count("secretKey") > 0)
- {
- assert(_o.count("nonce") > 0);
- assert(_o.count("gasPrice") > 0);
- assert(_o.count("gasLimit") > 0);
- assert(_o.count("to") > 0);
- assert(_o.count("value") > 0);
- assert(_o.count("data") > 0);
-
- if (bigint(_o.at("nonce").get_str()) >= c_max256plus1)
- BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'nonce' is equal or greater than 2**256") );
- if (bigint(_o.at("gasPrice").get_str()) >= c_max256plus1)
- BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'gasPrice' is equal or greater than 2**256") );
- if (bigint(_o.at("gasLimit").get_str()) >= c_max256plus1)
- BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'gasLimit' is equal or greater than 2**256") );
- if (bigint(_o.at("value").get_str()) >= c_max256plus1)
- BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'value' is equal or greater than 2**256") );
-
- o_tr = _o.at("to").get_str().empty() ?
- Transaction(toInt(_o.at("value")), toInt(_o.at("gasPrice")), toInt(_o.at("gasLimit")), importData(_o), toInt(_o.at("nonce")), Secret(_o.at("secretKey").get_str())) :
- Transaction(toInt(_o.at("value")), toInt(_o.at("gasPrice")), toInt(_o.at("gasLimit")), Address(_o.at("to").get_str()), importData(_o), toInt(_o.at("nonce")), Secret(_o.at("secretKey").get_str()));
- }
- else
- {
- RLPStream transactionRLPStream = createRLPStreamFromTransactionFields(_o);
- RLP transactionRLP(transactionRLPStream.out());
- try
- {
- o_tr = Transaction(transactionRLP.data(), CheckTransaction::Everything);
- }
- catch (InvalidSignature)
- {
- // create unsigned transaction
- o_tr = _o.at("to").get_str().empty() ?
- Transaction(toInt(_o.at("value")), toInt(_o.at("gasPrice")), toInt(_o.at("gasLimit")), importData(_o), toInt(_o.at("nonce"))) :
- Transaction(toInt(_o.at("value")), toInt(_o.at("gasPrice")), toInt(_o.at("gasLimit")), Address(_o.at("to").get_str()), importData(_o), toInt(_o.at("nonce")));
- }
- catch (Exception& _e)
- {
- cnote << "invalid transaction" << boost::diagnostic_information(_e);
- }
- }
-}
-
-void ImportTest::importTransaction(json_spirit::mObject const& o_tr)
-{
- importTransaction(o_tr, m_transaction);
-}
-
-int ImportTest::compareStates(State const& _stateExpect, State const& _statePost, AccountMaskMap const _expectedStateOptions, WhenError _throw)
-{
- #define CHECK(a,b) \
- { \
- if (_throw == WhenError::Throw) \
- { \
- TBOOST_CHECK_MESSAGE(a, b); \
- if (!a) \
- return 1; \
- } \
- else \
- {TBOOST_WARN_MESSAGE(a,b);} \
- }
-
- for (auto const& a: _stateExpect.addresses())
- {
- CHECK(_statePost.addressInUse(a.first), "Check State: " << a.first << " missing expected address!");
- if (_statePost.addressInUse(a.first))
- {
- AccountMask addressOptions(true);
- if(_expectedStateOptions.size())
- {
- try
- {
- addressOptions = _expectedStateOptions.at(a.first);
- }
- catch(std::out_of_range const&)
- {
- TBOOST_ERROR("expectedStateOptions map does not match expectedState in checkExpectedState!");
- break;
- }
- }
-
- 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.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.hasStorage())
- {
- unordered_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.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)) << "'");
- }
- }
- return 0;
-}
-
-int ImportTest::exportTest(bytes const& _output)
-{
- int err = 0;
- // export output
- m_testObject["out"] = (_output.size() > 4096 && !Options::get().fulloutput) ? "#" + toString(_output.size()) : toHex(_output, 2, HexPrefix::Add);
-
- // compare expected output with post output
- if (m_testObject.count("expectOut") > 0)
- {
- std::string warning = "Check State: Error! Unexpected output: " + m_testObject["out"].get_str() + " Expected: " + m_testObject["expectOut"].get_str();
- if (Options::get().checkState)
- {
- bool statement = (m_testObject["out"].get_str() == m_testObject["expectOut"].get_str());
- TBOOST_CHECK_MESSAGE(statement, warning);
- if (!statement)
- err = 1;
- }
- else
- TBOOST_WARN_MESSAGE((m_testObject["out"].get_str() == m_testObject["expectOut"].get_str()), warning);
-
- m_testObject.erase(m_testObject.find("expectOut"));
- }
-
- // export logs
- m_testObject["logs"] = exportLog(m_logs);
-
- // compare expected state with post state
- if (m_testObject.count("expect") > 0)
- {
- eth::AccountMaskMap stateMap;
- State expectState(OverlayDB(), eth::BaseState::Empty);
- importState(m_testObject["expect"].get_obj(), expectState, stateMap);
- 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(m_statePost);
- m_testObject["postStateRoot"] = toHex(m_statePost.rootHash().asBytes());
-
- // export pre state
- m_testObject["pre"] = fillJsonWithState(m_statePre);
- m_testObject["env"] = makeAllFieldsHex(m_testObject["env"].get_obj());
- m_testObject["transaction"] = makeAllFieldsHex(m_testObject["transaction"].get_obj());
- return err;
-}
-
-json_spirit::mObject fillJsonWithTransaction(Transaction _txn)
-{
- json_spirit::mObject txObject;
- txObject["nonce"] = toCompactHex(_txn.nonce(), HexPrefix::Add, 1);
- txObject["data"] = toHex(_txn.data(), 2, HexPrefix::Add);
- txObject["gasLimit"] = toCompactHex(_txn.gas(), HexPrefix::Add, 1);
- txObject["gasPrice"] = toCompactHex(_txn.gasPrice(), HexPrefix::Add, 1);
- txObject["r"] = toCompactHex(_txn.signature().r, HexPrefix::Add, 1);
- txObject["s"] = toCompactHex(_txn.signature().s, HexPrefix::Add, 1);
- txObject["v"] = toCompactHex(_txn.signature().v + 27, HexPrefix::Add, 1);
- txObject["to"] = _txn.isCreation() ? "" : toString(_txn.receiveAddress());
- txObject["value"] = toCompactHex(_txn.value(), HexPrefix::Add, 1);
- return txObject;
-}
-
-json_spirit::mObject fillJsonWithState(State _state)
-{
- json_spirit::mObject oState;
- for (auto const& a: _state.addresses())
- {
- json_spirit::mObject o;
- o["balance"] = toCompactHex(_state.balance(a.first), HexPrefix::Add, 1);
- o["nonce"] = toCompactHex(_state.transactionsFrom(a.first), HexPrefix::Add, 1);
- {
- json_spirit::mObject store;
- for (auto const& s: _state.storage(a.first))
- store[toCompactHex(s.first, HexPrefix::Add, 1)] = toCompactHex(s.second, HexPrefix::Add, 1);
- o["storage"] = store;
- }
- o["code"] = toHex(_state.code(a.first), 2, HexPrefix::Add);
- oState[toString(a.first)] = o;
- }
- return oState;
-}
-
-json_spirit::mArray exportLog(eth::LogEntries _logs)
-{
- json_spirit::mArray ret;
- if (_logs.size() == 0) return ret;
- for (LogEntry const& l: _logs)
- {
- json_spirit::mObject o;
- o["address"] = toString(l.address);
- json_spirit::mArray topics;
- for (auto const& t: l.topics)
- topics.push_back(toString(t));
- o["topics"] = topics;
- o["data"] = toHex(l.data, 2, HexPrefix::Add);
- o["bloom"] = toString(l.bloom());
- ret.push_back(o);
- }
- return ret;
-}
-
-u256 toInt(json_spirit::mValue const& _v)
-{
- switch (_v.type())
- {
- case json_spirit::str_type: return u256(_v.get_str());
- case json_spirit::int_type: return (u256)_v.get_uint64();
- case json_spirit::bool_type: return (u256)(uint64_t)_v.get_bool();
- case json_spirit::real_type: return (u256)(uint64_t)_v.get_real();
- default: cwarn << "Bad type for scalar: " << _v.type();
- }
- return 0;
-}
-
-byte toByte(json_spirit::mValue const& _v)
-{
- switch (_v.type())
- {
- case json_spirit::str_type: return (byte)stoi(_v.get_str());
- case json_spirit::int_type: return (byte)_v.get_uint64();
- case json_spirit::bool_type: return (byte)_v.get_bool();
- case json_spirit::real_type: return (byte)_v.get_real();
- default: cwarn << "Bad type for scalar: " << _v.type();
- }
- return 0;
-}
-
-bytes importByteArray(std::string const& _str)
-{
- return fromHex(_str.substr(0, 2) == "0x" ? _str.substr(2) : _str, WhenError::Throw);
-}
-
-bytes importData(json_spirit::mObject const& _o)
-{
- bytes data;
- if (_o.at("data").type() == json_spirit::str_type)
- data = importByteArray(_o.at("data").get_str());
- else
- for (auto const& j: _o.at("data").get_array())
- data.push_back(toByte(j));
- return data;
-}
-
-bytes importCode(json_spirit::mObject& _o)
-{
- bytes code;
- if (_o["code"].type() == json_spirit::str_type)
- if (_o["code"].get_str().find("0x") != 0)
- code = compileLLL(_o["code"].get_str(), false);
- else
- code = fromHex(_o["code"].get_str().substr(2));
- else if (_o["code"].type() == json_spirit::array_type)
- {
- code.clear();
- for (auto const& j: _o["code"].get_array())
- code.push_back(toByte(j));
- }
- return code;
-}
-
-LogEntries importLog(json_spirit::mArray& _a)
-{
- LogEntries logEntries;
- for (auto const& l: _a)
- {
- json_spirit::mObject o = l.get_obj();
- // cant use BOOST_REQUIRE, because this function is used outside boost test (createRandomTest)
- assert(o.count("address") > 0);
- assert(o.count("topics") > 0);
- assert(o.count("data") > 0);
- assert(o.count("bloom") > 0);
- LogEntry log;
- log.address = Address(o["address"].get_str());
- for (auto const& t: o["topics"].get_array())
- log.topics.push_back(h256(t.get_str()));
- log.data = importData(o);
- logEntries.push_back(log);
- }
- return logEntries;
-}
-
-void checkOutput(bytes const& _output, json_spirit::mObject& _o)
-{
- int j = 0;
-
- if (_o["out"].get_str().find("#") == 0)
- {TBOOST_CHECK(((u256)_output.size() == toInt(_o["out"].get_str().substr(1))));}
- else if (_o["out"].type() == json_spirit::array_type)
- for (auto const& d: _o["out"].get_array())
- {
- TBOOST_CHECK_MESSAGE((_output[j] == toInt(d)), "Output byte [" << j << "] different!");
- ++j;
- }
- else if (_o["out"].get_str().find("0x") == 0)
- {TBOOST_CHECK((_output == fromHex(_o["out"].get_str().substr(2))));}
- else
- TBOOST_CHECK((_output == fromHex(_o["out"].get_str())));
-}
-
-void checkStorage(map<u256, u256> _expectedStore, map<u256, u256> _resultStore, Address _expectedAddr)
-{
- _expectedAddr = _expectedAddr; //unsed parametr when macro
- for (auto&& expectedStorePair : _expectedStore)
- {
- auto& expectedStoreKey = expectedStorePair.first;
- auto resultStoreIt = _resultStore.find(expectedStoreKey);
- if (resultStoreIt == _resultStore.end())
- {TBOOST_ERROR(_expectedAddr << ": missing store key " << expectedStoreKey);}
- else
- {
- auto& expectedStoreValue = expectedStorePair.second;
- auto& resultStoreValue = resultStoreIt->second;
- TBOOST_CHECK_MESSAGE((expectedStoreValue == resultStoreValue), _expectedAddr << ": store[" << expectedStoreKey << "] = " << resultStoreValue << ", expected " << expectedStoreValue);
- }
- }
- TBOOST_CHECK_EQUAL(_resultStore.size(), _expectedStore.size());
- for (auto&& resultStorePair: _resultStore)
- {
- if (!_expectedStore.count(resultStorePair.first))
- TBOOST_ERROR(_expectedAddr << ": unexpected store key " << resultStorePair.first);
- }
-}
-
-void checkLog(LogEntries _resultLogs, LogEntries _expectedLogs)
-{
- TBOOST_REQUIRE_EQUAL(_resultLogs.size(), _expectedLogs.size());
-
- for (size_t i = 0; i < _resultLogs.size(); ++i)
- {
- TBOOST_CHECK_EQUAL(_resultLogs[i].address, _expectedLogs[i].address);
- TBOOST_CHECK_EQUAL(_resultLogs[i].topics, _expectedLogs[i].topics);
- TBOOST_CHECK((_resultLogs[i].data == _expectedLogs[i].data));
- }
-}
-
-void checkCallCreates(eth::Transactions _resultCallCreates, eth::Transactions _expectedCallCreates)
-{
- TBOOST_REQUIRE_EQUAL(_resultCallCreates.size(), _expectedCallCreates.size());
-
- for (size_t i = 0; i < _resultCallCreates.size(); ++i)
- {
- TBOOST_CHECK((_resultCallCreates[i].data() == _expectedCallCreates[i].data()));
- TBOOST_CHECK((_resultCallCreates[i].receiveAddress() == _expectedCallCreates[i].receiveAddress()));
- TBOOST_CHECK((_resultCallCreates[i].gas() == _expectedCallCreates[i].gas()));
- TBOOST_CHECK((_resultCallCreates[i].value() == _expectedCallCreates[i].value()));
- }
-}
-
-void userDefinedTest(std::function<void(json_spirit::mValue&, bool)> doTests)
-{
- if (!Options::get().singleTest)
- return;
-
- if (Options::get().singleTestFile.empty() || Options::get().singleTestName.empty())
- {
- cnote << "Missing user test specification\nUsage: testeth --singletest <filename> <testname>\n";
- return;
- }
-
- auto& filename = Options::get().singleTestFile;
- auto& testname = Options::get().singleTestName;
-
- if (g_logVerbosity != -1)
- VerbosityHolder sentinel(12);
-
- try
- {
- cnote << "Testing user defined test: " << filename;
- json_spirit::mValue v;
- string s = contentsString(filename);
- TBOOST_REQUIRE_MESSAGE((s.length() > 0), "Contents of " + filename + " is empty. ");
- json_spirit::read_string(s, v);
- json_spirit::mObject oSingleTest;
-
- json_spirit::mObject::const_iterator pos = v.get_obj().find(testname);
- if (pos == v.get_obj().end())
- {
- cnote << "Could not find test: " << testname << " in " << filename << "\n";
- return;
- }
- else
- oSingleTest[pos->first] = pos->second;
-
- json_spirit::mValue v_singleTest(oSingleTest);
- doTests(v_singleTest, test::Options::get().fillTests);
- }
- catch (Exception const& _e)
- {
- TBOOST_ERROR("Failed Test with Exception: " << diagnostic_information(_e));
- }
- catch (std::exception const& _e)
- {
- TBOOST_ERROR("Failed Test with Exception: " << _e.what());
- }
-}
-
-void executeTests(const string& _name, const string& _testPathAppendix, const boost::filesystem::path _pathToFiller, std::function<void(json_spirit::mValue&, bool)> doTests)
-{
- string testPath = getTestPath();
- testPath += _testPathAppendix;
-
- if (Options::get().stats)
- Listener::registerListener(Stats::get());
-
- if (Options::get().fillTests)
- {
- try
- {
- cnote << "Populating tests...";
- json_spirit::mValue v;
- boost::filesystem::path p(__FILE__);
- string s = asString(dev::contents(_pathToFiller.string() + "/" + _name + "Filler.json"));
- TBOOST_REQUIRE_MESSAGE((s.length() > 0), "Contents of " + _pathToFiller.string() + "/" + _name + "Filler.json is empty.");
- json_spirit::read_string(s, v);
- doTests(v, true);
- writeFile(testPath + "/" + _name + ".json", asBytes(json_spirit::write_string(v, true)));
- }
- catch (Exception const& _e)
- {
- TBOOST_ERROR("Failed filling test with Exception: " << diagnostic_information(_e));
- }
- catch (std::exception const& _e)
- {
- TBOOST_ERROR("Failed filling test with Exception: " << _e.what());
- }
- }
-
- try
- {
- cnote << "TEST " << _name << ":";
- json_spirit::mValue v;
- string s = asString(dev::contents(testPath + "/" + _name + ".json"));
- TBOOST_REQUIRE_MESSAGE((s.length() > 0), "Contents of " + testPath + "/" + _name + ".json is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?");
- json_spirit::read_string(s, v);
- Listener::notifySuiteStarted(_name);
- doTests(v, false);
- }
- catch (Exception const& _e)
- {
- TBOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e));
- }
- catch (std::exception const& _e)
- {
- TBOOST_ERROR("Failed test with Exception: " << _e.what());
- }
-}
-
-RLPStream createRLPStreamFromTransactionFields(json_spirit::mObject const& _tObj)
-{
- //Construct Rlp of the given transaction
- RLPStream rlpStream;
- rlpStream.appendList(_tObj.size());
-
- if (_tObj.count("nonce"))
- rlpStream << bigint(_tObj.at("nonce").get_str());
-
- if (_tObj.count("gasPrice"))
- rlpStream << bigint(_tObj.at("gasPrice").get_str());
-
- if (_tObj.count("gasLimit"))
- rlpStream << bigint(_tObj.at("gasLimit").get_str());
-
- if (_tObj.count("to"))
- {
- if (_tObj.at("to").get_str().empty())
- rlpStream << "";
- else
- rlpStream << importByteArray(_tObj.at("to").get_str());
- }
-
- if (_tObj.count("value"))
- rlpStream << bigint(_tObj.at("value").get_str());
-
- if (_tObj.count("data"))
- rlpStream << importData(_tObj);
-
- if (_tObj.count("v"))
- rlpStream << bigint(_tObj.at("v").get_str());
-
- if (_tObj.count("r"))
- rlpStream << bigint(_tObj.at("r").get_str());
-
- if (_tObj.count("s"))
- rlpStream << bigint(_tObj.at("s").get_str());
-
- if (_tObj.count("extrafield"))
- rlpStream << bigint(_tObj.at("extrafield").get_str());
-
- return rlpStream;
-}
-
-Options::Options()
-{
- auto argc = boost::unit_test::framework::master_test_suite().argc;
- auto argv = boost::unit_test::framework::master_test_suite().argv;
-
- for (auto i = 0; i < argc; ++i)
- {
- auto arg = std::string{argv[i]};
- if (arg == "--vm" && i + 1 < argc)
- {
- string vmKind = argv[++i];
- if (vmKind == "interpreter")
- VMFactory::setKind(VMKind::Interpreter);
- else if (vmKind == "jit")
- VMFactory::setKind(VMKind::JIT);
- else if (vmKind == "smart")
- VMFactory::setKind(VMKind::Smart);
- else
- cerr << "Unknown VM kind: " << vmKind << endl;
- }
- else if (arg == "--jit") // TODO: Remove deprecated option "--jit"
- VMFactory::setKind(VMKind::JIT);
- else if (arg == "--vmtrace")
- vmtrace = true;
- else if (arg == "--filltests")
- fillTests = true;
- else if (arg == "--stats" && i + 1 < argc)
- {
- stats = true;
- statsOutFile = argv[i + 1];
- }
- else if (arg == "--performance")
- performance = true;
- else if (arg == "--quadratic")
- quadratic = true;
- else if (arg == "--memory")
- memory = true;
- else if (arg == "--inputlimits")
- inputLimits = true;
- else if (arg == "--bigdata")
- bigData = true;
- else if (arg == "--checkstate")
- checkState = true;
- else if (arg == "--wallet")
- wallet = true;
- else if (arg == "--nonetwork")
- nonetwork = true;
- else if (arg == "--network")
- nonetwork = false;
- else if (arg == "--nodag")
- nodag = true;
- else if (arg == "--all")
- {
- performance = true;
- quadratic = true;
- memory = true;
- inputLimits = true;
- bigData = true;
- wallet = true;
- }
- else if (arg == "--singletest" && i + 1 < argc)
- {
- singleTest = true;
- auto name1 = std::string{argv[i + 1]};
- if (i + 1 < argc) // two params
- {
- auto name2 = std::string{argv[i + 2]};
- if (name2[0] == '-') // not param, another option
- singleTestName = std::move(name1);
- else
- {
- singleTestFile = std::move(name1);
- singleTestName = std::move(name2);
- }
- }
- else
- singleTestName = std::move(name1);
- }
- else if (arg == "--fulloutput")
- fulloutput = true;
- else if (arg == "--verbosity" && i + 1 < argc)
- {
- static std::ostringstream strCout; //static string to redirect logs to
- std::string indentLevel = std::string{argv[i + 1]};
- if (indentLevel == "0")
- {
- logVerbosity = Verbosity::None;
- std::cout.rdbuf(strCout.rdbuf());
- std::cerr.rdbuf(strCout.rdbuf());
- }
- else if (indentLevel == "1")
- logVerbosity = Verbosity::NiceReport;
- else
- logVerbosity = Verbosity::Full;
- }
- }
-
- //Default option
- if (logVerbosity == Verbosity::NiceReport)
- g_logVerbosity = -1; //disable cnote but leave cerr and cout
-}
-
-Options const& Options::get()
-{
- static Options instance;
- return instance;
-}
-
-LastHashes lastHashes(u256 _currentBlockNumber)
-{
- LastHashes ret;
- for (u256 i = 1; i <= 256 && i <= _currentBlockNumber; ++i)
- ret.push_back(sha3(toString(_currentBlockNumber - i)));
- return ret;
-}
-
-dev::eth::Ethash::BlockHeader constructHeader(
- h256 const& _parentHash,
- h256 const& _sha3Uncles,
- Address const& _coinbaseAddress,
- h256 const& _stateRoot,
- h256 const& _transactionsRoot,
- h256 const& _receiptsRoot,
- dev::eth::LogBloom const& _logBloom,
- u256 const& _difficulty,
- u256 const& _number,
- u256 const& _gasLimit,
- u256 const& _gasUsed,
- u256 const& _timestamp,
- bytes const& _extraData)
-{
- RLPStream rlpStream;
- rlpStream.appendList(Ethash::BlockHeader::Fields);
-
- rlpStream << _parentHash << _sha3Uncles << _coinbaseAddress << _stateRoot << _transactionsRoot << _receiptsRoot << _logBloom
- << _difficulty << _number << _gasLimit << _gasUsed << _timestamp << _extraData << h256{} << Nonce{};
-
- return Ethash::BlockHeader(rlpStream.out(), CheckNothing, h256{}, HeaderData);
-}
-
-void updateEthashSeal(dev::eth::Ethash::BlockHeader& _header, h256 const& _mixHash, dev::eth::Nonce const& _nonce)
-{
- RLPStream source;
- _header.streamRLP(source);
- RLP sourceRlp(source.out());
- RLPStream header;
- header.appendList(Ethash::BlockHeader::Fields);
- for (size_t i = 0; i < BlockInfo::BasicFields; i++)
- header << sourceRlp[i];
-
- header << _mixHash << _nonce;
- _header = Ethash::BlockHeader(header.out(), CheckNothing, h256{}, HeaderData);
-}
-
namespace
{
Listener* g_listener;