diff options
-rw-r--r-- | CMakeLists.txt | 25 | ||||
-rw-r--r-- | checkRandomStateTest.cpp | 219 | ||||
-rw-r--r-- | checkRandomVMTest.cpp (renamed from checkRandomTest.cpp) | 0 | ||||
-rw-r--r-- | createRandomStateTest.cpp | 158 | ||||
-rw-r--r-- | createRandomVMTest.cpp (renamed from createRandomTest.cpp) | 0 | ||||
-rw-r--r-- | state.cpp | 33 |
6 files changed, 342 insertions, 93 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 83f61c76..45f83e5e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,10 @@ cmake_policy(SET CMP0015 NEW) aux_source_directory(. SRC_LIST) -list(REMOVE_ITEM SRC_LIST "./createRandomTest.cpp") +list(REMOVE_ITEM SRC_LIST "./createRandomVMTest.cpp") list(REMOVE_ITEM SRC_LIST "./createRandomStateTest.cpp") -list(REMOVE_ITEM SRC_LIST "./checkRandomTest.cpp") +list(REMOVE_ITEM SRC_LIST "./checkRandomVMTest.cpp") +list(REMOVE_ITEM SRC_LIST "./checkRandomStateTest.cpp") if (NOT JSONRPC) list(REMOVE_ITEM SRC_LIST "./AccountHolder.cpp") @@ -18,9 +19,10 @@ include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) file(GLOB HEADERS "*.h") add_executable(testeth ${SRC_LIST} ${HEADERS}) -add_executable(createRandomTest createRandomTest.cpp vm.cpp TestHelper.cpp) +add_executable(createRandomVMTest createRandomVMTest.cpp vm.cpp TestHelper.cpp) add_executable(createRandomStateTest createRandomStateTest.cpp state.cpp TestHelper.cpp) -add_executable(checkRandomTest checkRandomTest.cpp vm.cpp TestHelper.cpp) +add_executable(checkRandomVMTest checkRandomVMTest.cpp vm.cpp TestHelper.cpp) +add_executable(checkRandomStateTest checkRandomStateTest.cpp state.cpp TestHelper.cpp) target_link_libraries(testeth ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) target_link_libraries(testeth ${CURL_LIBRARIES}) @@ -37,13 +39,16 @@ if (JSONRPC) target_link_libraries(testeth ${JSON_RPC_CPP_CLIENT_LIBRARIES}) endif() -target_link_libraries(createRandomTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) -target_link_libraries(createRandomTest ethereum) -target_link_libraries(createRandomTest ethcore) +target_link_libraries(createRandomVMTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) +target_link_libraries(createRandomVMTest ethereum) +target_link_libraries(createRandomVMTest ethcore) target_link_libraries(createRandomStateTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) target_link_libraries(createRandomStateTest ethereum) target_link_libraries(createRandomStateTest ethcore) -target_link_libraries(checkRandomTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) -target_link_libraries(checkRandomTest ethereum) -target_link_libraries(checkRandomTest ethcore) +target_link_libraries(checkRandomVMTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) +target_link_libraries(checkRandomVMTest ethereum) +target_link_libraries(checkRandomVMTest ethcore) +target_link_libraries(checkRandomStateTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) +target_link_libraries(checkRandomStateTest ethereum) +target_link_libraries(checkRandomStateTest ethcore) diff --git a/checkRandomStateTest.cpp b/checkRandomStateTest.cpp new file mode 100644 index 00000000..29ccc2eb --- /dev/null +++ b/checkRandomStateTest.cpp @@ -0,0 +1,219 @@ +/* + 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 checkRandomTest.cpp + * @author Christoph Jentzsch <jentzsch.simulationsoftware@gmail.com> + * @date 2015 + * Check a random test and return 0/1 for success or failure. To be used for efficiency in the random test simulation. + */ + +#include <libdevcore/Common.h> +#include <libdevcore/Exceptions.h> +#include <libdevcore/Log.h> +#include <libevm/VMFactory.h> +#include "TestHelper.h" +#include "vm.h" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +using namespace std; +using namespace json_spirit; +using namespace dev::test; +using namespace dev; + +bool doStateTest(mValue& v); + +int main(int argc, char *argv[]) +{ + g_logVerbosity = 0; + bool ret = false; + + try + { + mValue v; + string s; + for (int i = 1; i < argc; ++i) + s += argv[i]; + if (asserts(s.length() > 0)) + { + cout << "Content of argument is empty\n"; + return 1; + } + read_string(s, v); + ret = doStateTest(v); + } + catch (Exception const& _e) + { + cout << "Failed test with Exception: " << diagnostic_information(_e) << endl; + ret = false; + } + catch (std::exception const& _e) + { + cout << "Failed test with Exception: " << _e.what() << endl; + ret = false; + } + return ret; +} + +bool doStateTest(mValue& v) +{ + eth::VMFactory::setKind(eth::VMKind::JIT); + + for (auto& i: v.get_obj()) + { + //cerr << i.first << endl; + mObject& o = i.second.get_obj(); + + assert(o.count("env") > 0); + assert(o.count("pre") > 0); + assert(o.count("transaction") > 0); + + ImportTest importer(o, false); + + eth::State theState = importer.m_statePre; + bytes tx = importer.m_transaction.rlp(); + bytes output; + + try + { + theState.execute(lastHashes(importer.m_environment.currentBlock.number), tx, &output); + } + catch (Exception const& _e) + { + cnote << "state execution did throw an exception: " << diagnostic_information(_e); + theState.commit(); + } + catch (std::exception const& _e) + { + cnote << "state execution did throw an exception: " << _e.what(); + } + + assert(o.count("post") > 0); + assert(o.count("out") > 0); + + + //checkOutput(output, o); + int j = 0; + if (o["out"].type() == array_type) + for (auto const& d: o["out"].get_array()) + { + if (asserts(output[j] == toInt(d))) + { + cout << "Output byte [" << j << "] different!"; + return 1; + } + ++j; + } + else if (o["out"].get_str().find("0x") == 0) + { + if (asserts(output == fromHex(o["out"].get_str().substr(2)))) + return 1; + } + else + { + if (asserts(output == fromHex(o["out"].get_str()))) + return 1; + } + + + // check logs + //checkLog(theState.pending().size() ? theState.log(0) : LogEntries(), importer.m_environment.sub.logs); + eth::LogEntries logs = theState.pending().size() ? theState.log(0) : eth::LogEntries(); + + //checkLog(logs, importer.m_environment.sub.logs); + { + if (assertsEqual(logs.size(), importer.m_environment.sub.logs.size())) + return 1; + + for (size_t i = 0; i < logs.size(); ++i) + { + if (assertsEqual(logs[i].address, importer.m_environment.sub.logs[i].address)) + return 1; + if (assertsEqual(logs[i].topics, importer.m_environment.sub.logs[i].topics)) + return 1; + if (asserts(logs[i].data == importer.m_environment.sub.logs[i].data)) + return 1; + } + } + + // check addresses +#if ETH_FATDB + auto expectedAddrs = importer.m_statePost.addresses(); + auto resultAddrs = theState.addresses(); + for (auto& expectedPair : expectedAddrs) + { + auto& expectedAddr = expectedPair.first; + auto resultAddrIt = resultAddrs.find(expectedAddr); + if (resultAddrIt == resultAddrs.end()) + BOOST_ERROR("Missing expected address " << expectedAddr); + else + { + BOOST_CHECK_MESSAGE(importer.m_statePost.balance(expectedAddr) == theState.balance(expectedAddr), expectedAddr << ": incorrect balance " << theState.balance(expectedAddr) << ", expected " << importer.m_statePost.balance(expectedAddr)); + BOOST_CHECK_MESSAGE(importer.m_statePost.transactionsFrom(expectedAddr) == theState.transactionsFrom(expectedAddr), expectedAddr << ": incorrect txCount " << theState.transactionsFrom(expectedAddr) << ", expected " << importer.m_statePost.transactionsFrom(expectedAddr)); + BOOST_CHECK_MESSAGE(importer.m_statePost.code(expectedAddr) == theState.code(expectedAddr), expectedAddr << ": incorrect code"); + + //checkStorage(importer.m_statePost.storage(expectedAddr), theState.storage(expectedAddr), expectedAddr); + + map<u256, u256> _resultStore = theState.storage(expectedAddr); + + for (auto&& expectedStorePair : importer.m_statePost.storage(expectedAddr)) + { + auto& expectedStoreKey = expectedStorePair.first; + auto resultStoreIt = _resultStore.find(expectedStoreKey); + if (resultStoreIt == _resultStore.end()) + { + cout << expectedAddr << ": missing store key " << expectedStoreKey << endl; + return 1; + } + else + { + auto& expectedStoreValue = expectedStorePair.second; + auto& resultStoreValue = resultStoreIt->second; + if (asserts(expectedStoreValue == resultStoreValue)) + { + cout << expectedAddr << ": store[" << expectedStoreKey << "] = " << resultStoreValue << ", expected " << expectedStoreValue << endl; + return 1; + } + } + } + if (assertsEqual(_resultStore.size(), importer.m_statePost.storage(expectedAddr).size())) + return 1; + for (auto&& resultStorePair: _resultStore) + { + if (!importer.m_statePost.storage(expectedAddr).count(resultStorePair.first)) + { + cout << expectedAddr << ": unexpected store key " << resultStorePair.first << endl; + return 1; + } + } + } + } + //checkAddresses<map<Address, u256> >(expectedAddrs, resultAddrs); + for (auto& resultPair : resultAddrs) + { + auto& resultAddr = resultPair.first; + auto expectedAddrIt = expectedAddrs.find(resultAddr); + if (expectedAddrIt == expectedAddrs.end()) + return 1; + } + if(expectedAddrs != resultAddrs) + return 1; + +#endif + if(theState.rootHash() != h256(o["postStateRoot"].get_str()), "wrong post state root") + return 1; + } + return 0; +} diff --git a/checkRandomTest.cpp b/checkRandomVMTest.cpp index e3442d43..e3442d43 100644 --- a/checkRandomTest.cpp +++ b/checkRandomVMTest.cpp diff --git a/createRandomStateTest.cpp b/createRandomStateTest.cpp index 2743ad19..06a332e0 100644 --- a/createRandomStateTest.cpp +++ b/createRandomStateTest.cpp @@ -82,57 +82,53 @@ int main(int argc, char *argv[]) i--; } - string const s = R"( - { - "randomStatetest" : { - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "1000000", - "currentNumber" : "0", - "currentTimestamp" : 1, - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "1000000000000000000", - "code" : "0x6001600101600055", - "nonce" : "0", - "storage" : { - } - }, - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "code" : "0x", - "nonce" : "0", - "storage" : { - } - } - }, - "transaction" : { - "data" : "", - "gasLimit" : "400000", - "gasPrice" : "1", - "nonce" : "0", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", - "value" : "100000" - } - } - } + string const s = R"( + { + "randomStatetest" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "code" : "0x6001600101600055", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "", + "gasLimit" : "400000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000" + } + } + } )"; - - - cout << "the test: " << s << endl; - - mValue v; + mValue v; read_string(s, v); // insert new random code - v.get_obj().find("randomStatetest")->second.get_obj().find("pre")->second.get_obj().begin()->second.get_obj()["code"] = "0x" + randomCode + (randGen() > 128 ? "55" : ""); + v.get_obj().find("randomStatetest")->second.get_obj().find("pre")->second.get_obj().begin()->second.get_obj()["code"] = "0x" + randomCode + (randGen() > 128 ? "55" : ""); - // fill test - doStateTests(v); + // fill test + doStateTests(v); // stream to output for further handling by the bash script cout << json_spirit::write_string(v, true); @@ -142,45 +138,41 @@ int main(int argc, char *argv[]) void doStateTests(json_spirit::mValue& _v) { - try{ - for (auto& i: _v.get_obj()) - { - cerr << i.first << endl; - mObject& o = i.second.get_obj(); - - assert(o.count("env") > 0); - assert(o.count("pre") > 0); - assert(o.count("transaction") > 0); - - test::ImportTest importer(o, true); - - eth::State theState = importer.m_statePre; - bytes tx = importer.m_transaction.rlp(); - bytes output; - - try - { - theState.execute(test::lastHashes(importer.m_environment.currentBlock.number), tx, &output); - } - catch (Exception const& _e) - { - cnote << "state execution did throw an exception: " << diagnostic_information(_e); - theState.commit(); - } - catch (std::exception const& _e) - { - cnote << "state execution did throw an exception: " << _e.what(); - } + eth::VMFactory::setKind(eth::VMKind::Interpreter); + + for (auto& i: _v.get_obj()) + { + //cerr << i.first << endl; + mObject& o = i.second.get_obj(); + + assert(o.count("env") > 0); + assert(o.count("pre") > 0); + assert(o.count("transaction") > 0); + + test::ImportTest importer(o, true); + + eth::State theState = importer.m_statePre; + bytes tx = importer.m_transaction.rlp(); + bytes output; + + try + { + theState.execute(test::lastHashes(importer.m_environment.currentBlock.number), tx, &output); + } + catch (Exception const& _e) + { + cnote << "state execution did throw an exception: " << diagnostic_information(_e); + theState.commit(); + } + catch (std::exception const& _e) + { + cnote << "state execution did throw an exception: " << _e.what(); + } #if ETH_FATDB - importer.exportTest(output, theState); + importer.exportTest(output, theState); #else - BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("You can not fill tests when FATDB is switched off")); + cout << "You can not fill tests when FATDB is switched off"; #endif - } - } - catch (Exception const& _e) - { - cout << "problem: " << diagnostic_information(_e); - } + } } diff --git a/createRandomTest.cpp b/createRandomVMTest.cpp index 55e02375..55e02375 100644 --- a/createRandomTest.cpp +++ b/createRandomVMTest.cpp @@ -251,6 +251,39 @@ BOOST_AUTO_TEST_CASE(stCreateTest) } } +BOOST_AUTO_TEST_CASE(stRandom) +{ + string testPath = dev::test::getTestPath(); + testPath += "/StateTests/RandomTests"; + + vector<boost::filesystem::path> testFiles; + boost::filesystem::directory_iterator iterator(testPath); + for(; iterator != boost::filesystem::directory_iterator(); ++iterator) + if (boost::filesystem::is_regular_file(iterator->path()) && iterator->path().extension() == ".json") + testFiles.push_back(iterator->path()); + + for (auto& path: testFiles) + { + try + { + cnote << "Testing ..." << path.filename(); + json_spirit::mValue v; + string s = asString(dev::contents(path.string())); + BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + path.string() + " is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?"); + json_spirit::read_string(s, v); + dev::test::doStateTests(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()); + } + } +} + BOOST_AUTO_TEST_CASE(userDefinedFileState) { dev::test::userDefinedTest("--singletest", dev::test::doStateTests); |