diff options
author | Gav Wood <i@gavwood.com> | 2015-02-21 04:59:21 +0800 |
---|---|---|
committer | Gav Wood <i@gavwood.com> | 2015-02-21 04:59:21 +0800 |
commit | 4959e0e35c6f6049270cb64405c3c4e29b684742 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /TestHelper.cpp | |
parent | 9281eb507d7dc05133fe87490a1299a0f8d74229 (diff) | |
download | dexon-solidity-4959e0e35c6f6049270cb64405c3c4e29b684742.tar dexon-solidity-4959e0e35c6f6049270cb64405c3c4e29b684742.tar.gz dexon-solidity-4959e0e35c6f6049270cb64405c3c4e29b684742.tar.bz2 dexon-solidity-4959e0e35c6f6049270cb64405c3c4e29b684742.tar.lz dexon-solidity-4959e0e35c6f6049270cb64405c3c4e29b684742.tar.xz dexon-solidity-4959e0e35c6f6049270cb64405c3c4e29b684742.tar.zst dexon-solidity-4959e0e35c6f6049270cb64405c3c4e29b684742.zip |
Add EVMJIT.
Diffstat (limited to 'TestHelper.cpp')
-rw-r--r-- | TestHelper.cpp | 574 |
1 files changed, 0 insertions, 574 deletions
diff --git a/TestHelper.cpp b/TestHelper.cpp deleted file mode 100644 index ff6939a5..00000000 --- a/TestHelper.cpp +++ /dev/null @@ -1,574 +0,0 @@ -/* - This file is part of cpp-ethereum. - - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. -*/ -/** @file TestHelper.cpp - * @author Marko Simovic <markobarko@gmail.com> - * @date 2014 - */ - -#include "TestHelper.h" - -#include <thread> -#include <chrono> -#include <boost/filesystem/path.hpp> -#include <libethereum/Client.h> -#include <liblll/Compiler.h> -#include <libevm/VMFactory.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 -} -} - -namespace test -{ - -struct ValueTooLarge: virtual Exception {}; -bigint const c_max256plus1 = bigint(1) << 256; - -ImportTest::ImportTest(json_spirit::mObject& _o, bool isFiller): m_TestObject(_o) -{ - importEnv(_o["env"].get_obj()); - importState(_o["pre"].get_obj(), m_statePre); - importTransaction(_o["transaction"].get_obj()); - - if (!isFiller) - { - importState(_o["post"].get_obj(), m_statePost); - m_environment.sub.logs = importLog(_o["logs"].get_array()); - } -} - -void ImportTest::importEnv(json_spirit::mObject& _o) -{ - BOOST_REQUIRE(_o.count("previousHash") > 0); - BOOST_REQUIRE(_o.count("currentGasLimit") > 0); - BOOST_REQUIRE(_o.count("currentDifficulty") > 0); - BOOST_REQUIRE(_o.count("currentTimestamp") > 0); - BOOST_REQUIRE(_o.count("currentCoinbase") > 0); - BOOST_REQUIRE(_o.count("currentNumber") > 0); - - m_environment.previousBlock.hash = h256(_o["previousHash"].get_str()); - m_environment.currentBlock.number = toInt(_o["currentNumber"]); - m_environment.currentBlock.gasLimit = toInt(_o["currentGasLimit"]); - m_environment.currentBlock.difficulty = toInt(_o["currentDifficulty"]); - m_environment.currentBlock.timestamp = toInt(_o["currentTimestamp"]); - m_environment.currentBlock.coinbaseAddress = Address(_o["currentCoinbase"].get_str()); - - m_statePre.m_previousBlock = m_environment.previousBlock; - m_statePre.m_currentBlock = m_environment.currentBlock; -} - -void ImportTest::importState(json_spirit::mObject& _o, State& _state) -{ - for (auto& i: _o) - { - json_spirit::mObject o = i.second.get_obj(); - - BOOST_REQUIRE(o.count("balance") > 0); - BOOST_REQUIRE(o.count("nonce") > 0); - BOOST_REQUIRE(o.count("storage") > 0); - BOOST_REQUIRE(o.count("code") > 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") ); - - Address address = Address(i.first); - - bytes code = importCode(o); - - if (code.size()) - { - _state.m_cache[address] = Account(toInt(o["balance"]), Account::ContractConception); - _state.m_cache[address].setCode(code); - } - else - _state.m_cache[address] = Account(toInt(o["balance"]), Account::NormalCreation); - - 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) - _state.noteSending(address); - - _state.ensureCached(address, false, false); - } -} - -void ImportTest::importTransaction(json_spirit::mObject& _o) -{ - BOOST_REQUIRE(_o.count("nonce")> 0); - BOOST_REQUIRE(_o.count("gasPrice") > 0); - BOOST_REQUIRE(_o.count("gasLimit") > 0); - BOOST_REQUIRE(_o.count("to") > 0); - BOOST_REQUIRE(_o.count("value") > 0); - BOOST_REQUIRE(_o.count("secretKey") > 0); - BOOST_REQUIRE(_o.count("data") > 0); - - if (bigint(_o["nonce"].get_str()) >= c_max256plus1) - BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'nonce' is equal or greater than 2**256") ); - if (bigint(_o["gasPrice"].get_str()) >= c_max256plus1) - BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'gasPrice' is equal or greater than 2**256") ); - if (bigint(_o["gasLimit"].get_str()) >= c_max256plus1) - BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'gasLimit' is equal or greater than 2**256") ); - if (bigint(_o["value"].get_str()) >= c_max256plus1) - BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'value' is equal or greater than 2**256") ); - - m_transaction = _o["to"].get_str().empty() ? - Transaction(toInt(_o["value"]), toInt(_o["gasPrice"]), toInt(_o["gasLimit"]), importData(_o), toInt(_o["nonce"]), Secret(_o["secretKey"].get_str())) : - Transaction(toInt(_o["value"]), toInt(_o["gasPrice"]), toInt(_o["gasLimit"]), Address(_o["to"].get_str()), importData(_o), toInt(_o["nonce"]), Secret(_o["secretKey"].get_str())); -} - -void ImportTest::exportTest(bytes _output, State& _statePost) -{ - // export output - m_TestObject["out"] = "0x" + toHex(_output); - - // export logs - m_TestObject["logs"] = exportLog(_statePost.pending().size() ? _statePost.log(0) : LogEntries()); - - // export post state - json_spirit::mObject postState; - - std::map<Address, Account> genesis = genesisState(); - - for (auto const& a: _statePost.addresses()) - { - if (genesis.count(a.first)) - continue; - - json_spirit::mObject o; - o["balance"] = toString(_statePost.balance(a.first)); - o["nonce"] = toString(_statePost.transactionsFrom(a.first)); - { - json_spirit::mObject store; - for (auto const& s: _statePost.storage(a.first)) - store["0x"+toHex(toCompactBigEndian(s.first))] = "0x"+toHex(toCompactBigEndian(s.second)); - o["storage"] = store; - } - o["code"] = "0x" + toHex(_statePost.code(a.first)); - - postState[toString(a.first)] = o; - } - m_TestObject["post"] = json_spirit::mValue(postState); - - // export pre state - json_spirit::mObject preState; - - for (auto const& a: m_statePre.addresses()) - { - if (genesis.count(a.first)) - continue; - - json_spirit::mObject o; - o["balance"] = toString(m_statePre.balance(a.first)); - o["nonce"] = toString(m_statePre.transactionsFrom(a.first)); - { - json_spirit::mObject store; - for (auto const& s: m_statePre.storage(a.first)) - store["0x"+toHex(toCompactBigEndian(s.first))] = "0x"+toHex(toCompactBigEndian(s.second)); - o["storage"] = store; - } - o["code"] = "0x" + toHex(m_statePre.code(a.first)); - - preState[toString(a.first)] = o; - } - m_TestObject["pre"] = json_spirit::mValue(preState); -} - -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, ThrowType::Throw); -} - -bytes importData(json_spirit::mObject& _o) -{ - bytes data; - if (_o["data"].type() == json_spirit::str_type) - data = importByteArray(_o["data"].get_str()); - else - for (auto const& j: _o["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_first_of("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; -} - -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"] = "0x" + toHex(l.data); - o["bloom"] = toString(l.bloom()); - ret.push_back(o); - } - return ret; -} - -void checkOutput(bytes const& _output, json_spirit::mObject& _o) -{ - int j = 0; - if (_o["out"].type() == json_spirit::array_type) - for (auto const& d: _o["out"].get_array()) - { - BOOST_CHECK_MESSAGE(_output[j] == toInt(d), "Output byte [" << j << "] different!"); - ++j; - } - else if (_o["out"].get_str().find("0x") == 0) - BOOST_CHECK(_output == fromHex(_o["out"].get_str().substr(2))); - else - BOOST_CHECK(_output == fromHex(_o["out"].get_str())); -} - -void checkStorage(map<u256, u256> _expectedStore, map<u256, u256> _resultStore, Address _expectedAddr) -{ - for (auto&& expectedStorePair : _expectedStore) - { - auto& expectedStoreKey = expectedStorePair.first; - auto resultStoreIt = _resultStore.find(expectedStoreKey); - if (resultStoreIt == _resultStore.end()) - BOOST_ERROR(_expectedAddr << ": missing store key " << expectedStoreKey); - else - { - auto& expectedStoreValue = expectedStorePair.second; - auto& resultStoreValue = resultStoreIt->second; - BOOST_CHECK_MESSAGE(expectedStoreValue == resultStoreValue, _expectedAddr << ": store[" << expectedStoreKey << "] = " << resultStoreValue << ", expected " << expectedStoreValue); - } - } - BOOST_CHECK_EQUAL(_resultStore.size(), _expectedStore.size()); - for (auto&& resultStorePair: _resultStore) - { - if (!_expectedStore.count(resultStorePair.first)) - BOOST_ERROR(_expectedAddr << ": unexpected store key " << resultStorePair.first); - } -} - -void checkLog(LogEntries _resultLogs, LogEntries _expectedLogs) -{ - BOOST_REQUIRE_EQUAL(_resultLogs.size(), _expectedLogs.size()); - - for (size_t i = 0; i < _resultLogs.size(); ++i) - { - BOOST_CHECK_EQUAL(_resultLogs[i].address, _expectedLogs[i].address); - BOOST_CHECK_EQUAL(_resultLogs[i].topics, _expectedLogs[i].topics); - BOOST_CHECK(_resultLogs[i].data == _expectedLogs[i].data); - } -} - -void checkCallCreates(eth::Transactions _resultCallCreates, eth::Transactions _expectedCallCreates) -{ - BOOST_REQUIRE_EQUAL(_resultCallCreates.size(), _expectedCallCreates.size()); - - for (size_t i = 0; i < _resultCallCreates.size(); ++i) - { - BOOST_CHECK(_resultCallCreates[i].data() == _expectedCallCreates[i].data()); - BOOST_CHECK(_resultCallCreates[i].receiveAddress() == _expectedCallCreates[i].receiveAddress()); - BOOST_CHECK(_resultCallCreates[i].gas() == _expectedCallCreates[i].gas()); - BOOST_CHECK(_resultCallCreates[i].value() == _expectedCallCreates[i].value()); - } -} - -std::string getTestPath() -{ - string testPath; - const char* ptestPath = getenv("ETHEREUM_TEST_PATH"); - - if (ptestPath == NULL) - { - cnote << " could not find environment variable ETHEREUM_TEST_PATH \n"; - testPath = "../../../tests"; - } - else - testPath = ptestPath; - - return testPath; -} - -void userDefinedTest(string testTypeFlag, std::function<void(json_spirit::mValue&, bool)> doTests) -{ - for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i) - { - string arg = boost::unit_test::framework::master_test_suite().argv[i]; - if (arg == testTypeFlag) - { - if (boost::unit_test::framework::master_test_suite().argc <= i + 2) - { - cnote << "Missing filename\nUsage: testeth " << testTypeFlag << " <filename> <testname>\n"; - return; - } - string filename = boost::unit_test::framework::master_test_suite().argv[i + 1]; - string testname = boost::unit_test::framework::master_test_suite().argv[i + 2]; - int currentVerbosity = g_logVerbosity; - g_logVerbosity = 12; - try - { - cnote << "Testing user defined test: " << filename; - json_spirit::mValue v; - string s = asString(contents(filename)); - BOOST_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, false); - } - catch (Exception const& _e) - { - BOOST_ERROR("Failed Test with Exception: " << diagnostic_information(_e)); - g_logVerbosity = currentVerbosity; - } - catch (std::exception const& _e) - { - BOOST_ERROR("Failed Test with Exception: " << _e.what()); - g_logVerbosity = currentVerbosity; - } - g_logVerbosity = currentVerbosity; - } - else - continue; - } -} - -void executeTests(const string& _name, const string& _testPathAppendix, std::function<void(json_spirit::mValue&, bool)> doTests) -{ - string testPath = getTestPath(); - testPath += _testPathAppendix; - - for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i) - { - string arg = boost::unit_test::framework::master_test_suite().argv[i]; - if (arg == "--filltests") - { - try - { - cnote << "Populating tests..."; - json_spirit::mValue v; - boost::filesystem::path p(__FILE__); - boost::filesystem::path dir = p.parent_path(); - string s = asString(dev::contents(dir.string() + "/" + _name + "Filler.json")); - BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + dir.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) - { - BOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e)); - } - catch (std::exception const& _e) - { - BOOST_ERROR("Failed test with Exception: " << _e.what()); - } - break; - } - } - - try - { - cnote << "Testing ..." << _name; - json_spirit::mValue v; - string s = asString(dev::contents(testPath + "/" + _name + ".json")); - BOOST_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); - doTests(v, false); - } - catch (Exception const& _e) - { - BOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e)); - } - catch (std::exception const& _e) - { - BOOST_ERROR("Failed test with Exception: " << _e.what()); - } -} - -RLPStream createRLPStreamFromTransactionFields(json_spirit::mObject& _tObj) -{ - //Construct Rlp of the given transaction - RLPStream rlpStream; - rlpStream.appendList(_tObj.size()); - - if (_tObj.count("nonce")) - rlpStream << bigint(_tObj["nonce"].get_str()); - - if (_tObj.count("gasPrice")) - rlpStream << bigint(_tObj["gasPrice"].get_str()); - - if (_tObj.count("gasLimit")) - rlpStream << bigint(_tObj["gasLimit"].get_str()); - - if (_tObj.count("to")) - { - if (_tObj["to"].get_str().empty()) - rlpStream << ""; - else - rlpStream << importByteArray(_tObj["to"].get_str()); - } - - if (_tObj.count("value")) - rlpStream << bigint(_tObj["value"].get_str()); - - if (_tObj.count("data")) - rlpStream << importData(_tObj); - - if (_tObj.count("v")) - rlpStream << bigint(_tObj["v"].get_str()); - - if (_tObj.count("r")) - rlpStream << bigint(_tObj["r"].get_str()); - - if (_tObj.count("s")) - rlpStream << bigint(_tObj["s"].get_str()); - - if (_tObj.count("extrafield")) - rlpStream << bigint(_tObj["extrafield"].get_str()); - - return rlpStream; -} - -void processCommandLineOptions() -{ - 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) - { - if (std::string(argv[i]) == "--jit") - { - eth::VMFactory::setKind(eth::VMKind::JIT); - break; - } - } -} - -LastHashes lastHashes(u256 _currentBlockNumber) -{ - LastHashes ret; - for (u256 i = 1; i <= 256 && i <= _currentBlockNumber; ++i) - ret.push_back(sha3(toString(_currentBlockNumber - i))); - return ret; -} - -} } // namespaces |