diff options
Diffstat (limited to 'state.cpp')
-rw-r--r-- | state.cpp | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/state.cpp b/state.cpp new file mode 100644 index 00000000..1581e405 --- /dev/null +++ b/state.cpp @@ -0,0 +1,247 @@ +/* + 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 state.cpp + * @author Christoph Jentzsch <cj@ethdev.com> + * @date 2014 + * State test functions. + */ + +#include <boost/filesystem/operations.hpp> +#include <boost/test/unit_test.hpp> +#include "JsonSpiritHeaders.h" +#include <libdevcore/CommonIO.h> +#include <libethereum/CanonBlockChain.h> +#include <libethereum/State.h> +#include <libethereum/ExtVM.h> +#include <libethereum/Defaults.h> +#include <libevm/VM.h> +#include "TestHelper.h" + +using namespace std; +using namespace json_spirit; +using namespace dev; +using namespace dev::eth; + +namespace dev { namespace test { + +void doStateTests(json_spirit::mValue& v, bool _fillin) +{ + processCommandLineOptions(); + + for (auto& i: v.get_obj()) + { + cerr << i.first << endl; + mObject& o = i.second.get_obj(); + + BOOST_REQUIRE(o.count("env") > 0); + BOOST_REQUIRE(o.count("pre") > 0); + BOOST_REQUIRE(o.count("transaction") > 0); + + ImportTest importer(o, _fillin); + + 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); + } + catch (std::exception const& _e) + { + cnote << "state execution did throw an exception: " << _e.what(); + } + + if (_fillin) + importer.exportTest(output, theState); + else + { + BOOST_REQUIRE(o.count("post") > 0); + BOOST_REQUIRE(o.count("out") > 0); + + // check output + checkOutput(output, o); + + // check logs + checkLog(theState.pending().size() ? theState.log(0) : LogEntries(), importer.m_environment.sub.logs); + + // check addresses + 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); + } + } + checkAddresses<map<Address, u256> >(expectedAddrs, resultAddrs); + } + } +} +} }// Namespace Close + +BOOST_AUTO_TEST_SUITE(StateTests) + +BOOST_AUTO_TEST_CASE(stExample) +{ + dev::test::executeTests("stExample", "/StateTests", dev::test::doStateTests); +} + +BOOST_AUTO_TEST_CASE(stSystemOperationsTest) +{ + dev::test::executeTests("stSystemOperationsTest", "/StateTests", dev::test::doStateTests); +} + +BOOST_AUTO_TEST_CASE(stPreCompiledContracts) +{ + dev::test::executeTests("stPreCompiledContracts", "/StateTests", dev::test::doStateTests); +} + +BOOST_AUTO_TEST_CASE(stLogTests) +{ + dev::test::executeTests("stLogTests", "/StateTests", dev::test::doStateTests); +} + +BOOST_AUTO_TEST_CASE(stRecursiveCreate) +{ + dev::test::executeTests("stRecursiveCreate", "/StateTests", dev::test::doStateTests); +} + +BOOST_AUTO_TEST_CASE(stInitCodeTest) +{ + dev::test::executeTests("stInitCodeTest", "/StateTests", dev::test::doStateTests); +} + +BOOST_AUTO_TEST_CASE(stTransactionTest) +{ + dev::test::executeTests("stTransactionTest", "/StateTests", dev::test::doStateTests); +} + +BOOST_AUTO_TEST_CASE(stSpecialTest) +{ + dev::test::executeTests("stSpecialTest", "/StateTests", dev::test::doStateTests); +} + +BOOST_AUTO_TEST_CASE(stRefundTest) +{ + dev::test::executeTests("stRefundTest", "/StateTests", dev::test::doStateTests); +} + +BOOST_AUTO_TEST_CASE(stBlockHashTest) +{ + dev::test::executeTests("stBlockHashTest", "/StateTests", dev::test::doStateTests); +} + +BOOST_AUTO_TEST_CASE(stQuadraticComplexityTest) +{ + 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 == "--quadratic" || arg == "--all") + { + auto start = chrono::steady_clock::now(); + + dev::test::executeTests("stQuadraticComplexityTest", "/StateTests", dev::test::doStateTests); + + auto end = chrono::steady_clock::now(); + auto duration(chrono::duration_cast<chrono::milliseconds>(end - start)); + cnote << "test duration: " << duration.count() << " milliseconds.\n"; + } + } +} + +BOOST_AUTO_TEST_CASE(stMemoryStressTest) +{ + 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 == "--memory" || arg == "--all") + { + auto start = chrono::steady_clock::now(); + + dev::test::executeTests("stMemoryStressTest", "/StateTests", dev::test::doStateTests); + + auto end = chrono::steady_clock::now(); + auto duration(chrono::duration_cast<chrono::milliseconds>(end - start)); + cnote << "test duration: " << duration.count() << " milliseconds.\n"; + } + } +} + +BOOST_AUTO_TEST_CASE(stSolidityTest) +{ + dev::test::executeTests("stSolidityTest", "/StateTests", dev::test::doStateTests); +} + +BOOST_AUTO_TEST_CASE(stMemoryTest) +{ + dev::test::executeTests("stMemoryTest", "/StateTests", dev::test::doStateTests); +} + +BOOST_AUTO_TEST_CASE(stCreateTest) +{ + 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 == "--createtest") + { + if (boost::unit_test::framework::master_test_suite().argc <= i + 2) + { + cnote << "usage: ./testeth --createtest <PathToConstructor> <PathToDestiny>\n"; + return; + } + try + { + cnote << "Populating tests..."; + json_spirit::mValue v; + string s = asString(dev::contents(boost::unit_test::framework::master_test_suite().argv[i + 1])); + BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + (string)boost::unit_test::framework::master_test_suite().argv[i + 1] + " is empty."); + json_spirit::read_string(s, v); + dev::test::doStateTests(v, true); + writeFile(boost::unit_test::framework::master_test_suite().argv[i + 2], asBytes(json_spirit::write_string(v, true))); + } + catch (Exception const& _e) + { + BOOST_ERROR("Failed state test with Exception: " << diagnostic_information(_e)); + } + catch (std::exception const& _e) + { + BOOST_ERROR("Failed state test with Exception: " << _e.what()); + } + } + } +} + +BOOST_AUTO_TEST_CASE(userDefinedFileState) +{ + dev::test::userDefinedTest("--statetest", dev::test::doStateTests); +} + +BOOST_AUTO_TEST_SUITE_END() |