From 8d9eb6830781cc107d09a92a59f71914a341ad3c Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 20 Aug 2015 00:55:41 +0200 Subject: Modularise CMakeLists files and integrate tests. --- CMakeLists.txt | 32 +- libsolidity/CMakeLists.txt | 12 +- test/CMakeLists.txt | 85 +---- test/TestHelper.cpp | 833 --------------------------------------------- test/TestHelper.h | 177 ---------- test/TestUtils.cpp | 122 ------- test/TestUtils.h | 83 ----- test/boostTest.cpp | 59 ---- 8 files changed, 34 insertions(+), 1369 deletions(-) delete mode 100644 test/TestUtils.cpp delete mode 100644 test/TestUtils.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e3c48341..5198adb4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,31 +20,39 @@ else() endif() # Figure out environment. -set(CPPETHEREUM_BUILD "${CMAKE_CURRENT_SOURCE_DIR}/../cpp-ethereum/${BUILD_DIR_NAME}" CACHE STRING "The absolute build directory of cpp-ethereum.") set(ETH_CMAKE_DIR "${CMAKE_CURRENT_LIST_DIR}/../cpp-ethereum-cmake" CACHE PATH "The the path to the cmake directory") set(ETH_DIR "${CMAKE_CURRENT_LIST_DIR}/../cpp-ethereum" CACHE PATH "The path to the cpp-ethereum directory") set(BUILD_DIR_NAME "build" CACHE STRING "The name of the build directory in cpp-ethereum") set(ETH_BUILD_DIR "${ETH_DIR}/${BUILD_DIR_NAME}") +# A place where should we look for *.cmake files list(APPEND CMAKE_MODULE_PATH ${ETH_CMAKE_DIR}) +# A place where we should look for ethereum libraries +set(CMAKE_LIBRARY_PATH ${ETH_BUILD_DIR}) + +# Let's find our dependencies include(EthDependencies) -include(EthExecutableHelper) + +# Figure out what compiler and system are we using include(EthCompilerSettings) -include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) -include_directories(BEFORE ..) -include_directories(${Boost_INCLUDE_DIRS}) -include_directories(libsolidity) +# Include helper macros +include(EthExecutableHelper) + # Include a directory with BuildInfo.h include_directories(${ETH_BUILD_DIR}) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../cpp-ethereum) -include_directories(${CPPETHEREUM_BUILD}) -file(GLOB_RECURSE SRC_LIST "libsolidity/*.cpp") -file(GLOB_RECURSE HEADERS "libsolidity/*.h") +find_package(Eth) + +include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) +include_directories(BEFORE .) +include_directories(${Boost_INCLUDE_DIRS}) +include_directories(${ETH_DIR}) +include_directories(${CPPETHEREUM_BUILD}) -set(EXECUTABLE solidity) -add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) +add_subdirectory(libsolidity) +add_subdirectory(solc) +add_subdirectory(test) # TODO installation and packaging rules diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index 787e5576..159405a2 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -5,20 +5,20 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) -include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) -include_directories(BEFORE ..) -include_directories(${Boost_INCLUDE_DIRS}) - set(EXECUTABLE solidity) file(GLOB HEADERS "*.h") +include_directories(BEFORE ..) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) add_dependencies(${EXECUTABLE} BuildInfo.h) target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) -target_link_libraries(${EXECUTABLE} evmasm) -target_link_libraries(${EXECUTABLE} devcrypto) +target_link_libraries(${EXECUTABLE} ${Boost_LIBRARIES}) +target_link_libraries(${EXECUTABLE} ${ETH_DEVCORE_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${ETH_EVMCORE_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${ETH_EVMASM_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${ETH_DEVCRYPTO_LIBRARY}) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f7475112..81053d82 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -17,41 +17,11 @@ macro (add_sources) endif() endmacro() -add_subdirectory(fuzzTesting) -add_subdirectory(libdevcore) -add_subdirectory(libdevcrypto) -add_subdirectory(libethcore) -add_subdirectory(libethereum) -add_subdirectory(libevm) -add_subdirectory(libnatspec) -add_subdirectory(libp2p) -add_subdirectory(external-dependencies) - -if (JSCONSOLE) - add_subdirectory(libjsengine) -endif() - -if (SOLIDITY) - add_subdirectory(libsolidity) - add_subdirectory(contracts) -endif () -if (JSONRPC) -add_subdirectory(libweb3jsonrpc) -endif () -add_subdirectory(libwhisper) +add_subdirectory(contracts) +add_subdirectory(libsolidity) set(SRC_LIST ${SRC_LIST} ${SRC}) -include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) -include_directories(BEFORE ..) -include_directories(${Boost_INCLUDE_DIRS}) -include_directories(${CRYPTOPP_INCLUDE_DIRS}) -include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) - -if (JSCONSOLE) - include_directories(${V8_INCLUDE_DIRS}) -endif() - # search for test names and create ctest tests enable_testing() foreach(file ${SRC_LIST}) @@ -63,59 +33,20 @@ foreach(file ${SRC_LIST}) string(SUBSTRING ${test} 6 -1 TestSuite) elseif(test MATCHES "^CASE .*") string(SUBSTRING ${test} 5 -1 TestCase) - add_test(NAME ${TestSuite}/${TestCase} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/test COMMAND testeth -t ${TestSuite}/${TestCase}) + add_test(NAME ${TestSuite}/${TestCase} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/test COMMAND test -t ${TestSuite}/${TestCase}) endif(test MATCHES "^SUITE .*") endforeach(test_raw) endforeach(file) file(GLOB HEADERS "*.h") -add_executable(testeth ${SRC_LIST} ${HEADERS}) - -target_link_libraries(testeth ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) -target_link_libraries(testeth ${CURL_LIBRARIES}) -target_link_libraries(testeth ${CRYPTOPP_LIBRARIES}) -target_link_libraries(testeth ethereum) -target_link_libraries(testeth ethcore) -if (NOT WIN32) - target_link_libraries(testeth secp256k1) -endif () - -if (JSCONSOLE) - target_link_libraries(testeth jsengine) -endif() +add_executable(test ${SRC_LIST} ${HEADERS}) -if (SOLIDITY) - target_link_libraries(testeth solidity) -endif () - -target_link_libraries(testeth testutils) - -if (GUI AND NOT JUSTTESTS) - target_link_libraries(testeth webthree) - target_link_libraries(testeth natspec) -endif() - -if (JSONRPC) - target_link_libraries(testeth web3jsonrpc) - target_link_libraries(testeth ${JSON_RPC_CPP_CLIENT_LIBRARIES}) -endif() +target_link_libraries(test ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) +target_link_libraries(test ${ETH_ETHEREUM_LIBRARY}) +target_link_libraries(test ${ETH_ETHCORE_LIBRARY}) +target_link_libraries(test solidity) enable_testing() set(CTEST_OUTPUT_ON_FAILURE TRUE) include(EthUtils) - -eth_add_test(ClientBase - ARGS --eth_testfile=BlockTests/bcJS_API_Test --eth_threads=1 - ARGS --eth_testfile=BlockTests/bcJS_API_Test --eth_threads=3 - ARGS --eth_testfile=BlockTests/bcJS_API_Test --eth_threads=10 - ARGS --eth_testfile=BlockTests/bcValidBlockTest --eth_threads=1 - ARGS --eth_testfile=BlockTests/bcValidBlockTest --eth_threads=3 - ARGS --eth_testfile=BlockTests/bcValidBlockTest --eth_threads=10 -) - -eth_add_test(JsonRpc - ARGS --eth_testfile=BlockTests/bcJS_API_Test - ARGS --eth_testfile=BlockTests/bcValidBlockTest -) - 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 -#include -#include -#include -#include -#include -#include -#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 sealer(Ethash::createSealEngine()); - s.commitToSeal(_bc); - Notified 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 sealer(Ethash::createSealEngine()); - Notified 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 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 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 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 _expectedStore, map _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 doTests) -{ - if (!Options::get().singleTest) - return; - - if (Options::get().singleTestFile.empty() || Options::get().singleTestName.empty()) - { - cnote << "Missing user test specification\nUsage: testeth --singletest \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 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; diff --git a/test/TestHelper.h b/test/TestHelper.h index e5cf1323..0bf62224 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -25,47 +25,8 @@ #include #include -#include "JsonSpiritHeaders.h" -#include -#include -#include -#include - -#ifdef NOBOOST - #define TBOOST_REQUIRE(arg) if(arg == false) throw dev::Exception(); - #define TBOOST_REQUIRE_EQUAL(arg1, arg2) if(arg1 != arg2) throw dev::Exception(); - #define TBOOST_CHECK_EQUAL(arg1, arg2) if(arg1 != arg2) throw dev::Exception(); - #define TBOOST_CHECK(arg) if(arg == false) throw dev::Exception(); - #define TBOOST_REQUIRE_MESSAGE(arg1, arg2) if(arg1 == false) throw dev::Exception(); - #define TBOOST_CHECK_MESSAGE(arg1, arg2) if(arg1 == false) throw dev::Exception(); - #define TBOOST_WARN_MESSAGE(arg1, arg2) throw dev::Exception(); - #define TBOOST_ERROR(arg) throw dev::Exception(); -#else - #define TBOOST_REQUIRE(arg) BOOST_REQUIRE(arg) - #define TBOOST_REQUIRE_EQUAL(arg1, arg2) BOOST_REQUIRE_EQUAL(arg1, arg2) - #define TBOOST_CHECK(arg) BOOST_CHECK(arg) - #define TBOOST_CHECK_EQUAL(arg1, arg2) BOOST_CHECK_EQUAL(arg1, arg2) - #define TBOOST_CHECK_MESSAGE(arg1, arg2) BOOST_CHECK_MESSAGE(arg1, arg2) - #define TBOOST_REQUIRE_MESSAGE(arg1, arg2) BOOST_REQUIRE_MESSAGE(arg1, arg2) - #define TBOOST_WARN_MESSAGE(arg1, arg2) BOOST_WARN_MESSAGE(arg1, arg2) - #define TBOOST_ERROR(arg) BOOST_ERROR(arg) -#endif - namespace dev { -namespace eth -{ - -class Client; -class State; - -void mine(Client& c, int numBlocks); -void connectClients(Client& c1, Client& c2); -void mine(Block& _s, BlockChain const& _bc); -void mine(Ethash::BlockHeader& _bi); - -} - namespace test { @@ -121,144 +82,6 @@ namespace test } \ while (0) -enum class testType -{ - StateTests, - BlockChainTests, - Other -}; - -class ImportTest -{ -public: - ImportTest(json_spirit::mObject& _o, bool isFiller, testType testTemplate = testType::StateTests); - - // imports - void importEnv(json_spirit::mObject& _o); - static void importState(json_spirit::mObject& _o, eth::State& _state); - static void importState(json_spirit::mObject& _o, eth::State& _state, eth::AccountMaskMap& o_mask); - static void importTransaction (json_spirit::mObject const& _o, eth::Transaction& o_tr); - void importTransaction(json_spirit::mObject const& _o); - static json_spirit::mObject& makeAllFieldsHex(json_spirit::mObject& _o); - - bytes executeTest(); - int exportTest(bytes const& _output); - static int 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::Transaction m_transaction; - eth::LogEntries m_logs; - eth::LogEntries m_logsExpected; - -private: - json_spirit::mObject& m_testObject; -}; - -class ZeroGasPricer: public eth::GasPricer -{ -protected: - u256 ask(eth::Block const&) const override { return 0; } - u256 bid(eth::TransactionPriority = eth::TransactionPriority::Medium) const override { return 0; } -}; - -// helping functions -u256 toInt(json_spirit::mValue const& _v); -byte toByte(json_spirit::mValue const& _v); -bytes importCode(json_spirit::mObject& _o); -bytes importData(json_spirit::mObject const& _o); -bytes importByteArray(std::string const& _str); -eth::LogEntries importLog(json_spirit::mArray& _o); -json_spirit::mArray exportLog(eth::LogEntries _logs); -void checkOutput(bytes const& _output, json_spirit::mObject& _o); -void checkStorage(std::map _expectedStore, std::map _resultStore, Address _expectedAddr); -void checkLog(eth::LogEntries _resultLogs, eth::LogEntries _expectedLogs); -void checkCallCreates(eth::Transactions _resultCallCreates, eth::Transactions _expectedCallCreates); -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); -void updateEthashSeal(dev::eth::Ethash::BlockHeader& _header, h256 const& _mixHash, dev::eth::Nonce const& _nonce); -void executeTests(const std::string& _name, const std::string& _testPathAppendix, const boost::filesystem::path _pathToFiller, std::function doTests); -void userDefinedTest(std::function doTests); -RLPStream createRLPStreamFromTransactionFields(json_spirit::mObject const& _tObj); -eth::LastHashes lastHashes(u256 _currentBlockNumber); -json_spirit::mObject fillJsonWithState(eth::State _state); -json_spirit::mObject fillJsonWithTransaction(eth::Transaction _txn); - -//Fill Test Functions -void doTransactionTests(json_spirit::mValue& _v, bool _fillin); -void doStateTests(json_spirit::mValue& v, bool _fillin); -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 -void checkAddresses(mapType& _expectedAddrs, mapType& _resultAddrs) -{ - for (auto& resultPair : _resultAddrs) - { - auto& resultAddr = resultPair.first; - auto expectedAddrIt = _expectedAddrs.find(resultAddr); - if (expectedAddrIt == _expectedAddrs.end()) - TBOOST_ERROR("Missing result address " << resultAddr); - } - TBOOST_CHECK((_expectedAddrs == _resultAddrs)); -}*/ - -enum class Verbosity -{ - Full, - NiceReport, - None -}; - -class Options -{ -public: - bool vmtrace = false; ///< Create EVM execution tracer // TODO: Link with log verbosity? - bool fillTests = false; ///< Create JSON test files from execution results - bool stats = false; ///< Execution time stats - std::string statsOutFile; ///< Stats output file. "out" for standard output - bool checkState = false;///< Throw error when checking test states - bool fulloutput = false;///< Replace large output to just it's length - Verbosity logVerbosity = Verbosity::NiceReport; - - /// Test selection - /// @{ - bool singleTest = false; - std::string singleTestFile; - std::string singleTestName; - bool performance = false; - bool quadratic = false; - bool memory = false; - bool inputLimits = false; - bool bigData = false; - bool wallet = false; - bool nonetwork = true; - bool nodag = true; - /// @} - - /// Get reference to options - /// The first time used, options are parsed - static Options const& get(); - -private: - Options(); - Options(Options const&) = delete; -}; - /// Allows observing test execution process. /// This class also provides methods for registering and notifying the listener class Listener diff --git a/test/TestUtils.cpp b/test/TestUtils.cpp deleted file mode 100644 index 5e0619c0..00000000 --- a/test/TestUtils.cpp +++ /dev/null @@ -1,122 +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 . - */ -/** @file TestUtils.cpp - * @author Marek Kotewicz - * @date 2015 - */ - -#include -#include -#include -#include -#include -#include -#include -#include "TestUtils.h" - -using namespace std; -using namespace dev; -using namespace dev::eth; -using namespace dev::test; - -namespace dev -{ -namespace test -{ - -bool getCommandLineOption(std::string const& _name); -std::string getCommandLineArgument(std::string const& _name, bool _require = false); - -} -} - -bool dev::test::getCommandLineOption(string const& _name) -{ - auto argc = boost::unit_test::framework::master_test_suite().argc; - auto argv = boost::unit_test::framework::master_test_suite().argv; - bool result = false; - for (auto i = 0; !result && i < argc; ++i) - result = _name == argv[i]; - return result; -} - -std::string dev::test::getCommandLineArgument(string const& _name, bool _require) -{ - auto argc = boost::unit_test::framework::master_test_suite().argc; - auto argv = boost::unit_test::framework::master_test_suite().argv; - for (auto i = 1; i < argc; ++i) - { - string str = argv[i]; - if (_name == str.substr(0, _name.size())) - return str.substr(str.find("=") + 1); - } - if (_require) - BOOST_ERROR("Failed getting command line argument: " << _name << " from: " << argv); - return ""; -} - -LoadTestFileFixture::LoadTestFileFixture() -{ - m_json = loadJsonFromFile(toTestFilePath(getCommandLineArgument("--eth_testfile"))); -} - -void ParallelFixture::enumerateThreads(std::function callback) const -{ - size_t threadsCount = std::stoul(getCommandLineArgument("--eth_threads"), nullptr, 10); - - vector workers; - for (size_t i = 0; i < threadsCount; i++) - workers.emplace_back(callback); - - for_each(workers.begin(), workers.end(), [](thread &t) - { - t.join(); - }); -} - -void BlockChainFixture::enumerateBlockchains(std::function callback) const -{ - for (string const& name: m_json.getMemberNames()) - { - BlockChainLoader bcl(m_json[name]); - callback(m_json[name], bcl.bc(), bcl.state()); - } -} - -void ClientBaseFixture::enumerateClients(std::function callback) const -{ - enumerateBlockchains([&callback](Json::Value const& _json, BlockChain const& _bc, State _state) -> void - { - 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); - }); -} - -void ParallelClientBaseFixture::enumerateClients(std::function callback) const -{ - ClientBaseFixture::enumerateClients([this, &callback](Json::Value const& _json, dev::eth::ClientBase& _client) -> void - { - // json is being copied here - enumerateThreads([callback, _json, &_client]() -> void - { - callback(_json, _client); - }); - }); -} - diff --git a/test/TestUtils.h b/test/TestUtils.h deleted file mode 100644 index a7a0eacf..00000000 --- a/test/TestUtils.h +++ /dev/null @@ -1,83 +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 . - */ -/** @file TestUtils.h - * @author Marek Kotewicz - * @date 2015 - */ - -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace dev -{ -namespace test -{ - -// should be used for multithread tests -static SharedMutex x_boostTest; -#define ETH_CHECK_EQUAL(x, y) { dev::WriteGuard(x_boostTest); BOOST_CHECK_EQUAL(x, y); } -#define ETH_CHECK_EQUAL_COLLECTIONS(xb, xe, yb, ye) { dev::WriteGuard(x_boostTest); BOOST_CHECK_EQUAL_COLLECTIONS(xb, xe, yb, ye); } -#define ETH_REQUIRE(x) { dev::WriteGuard(x_boostTest); BOOST_REQUIRE(x); } - -struct LoadTestFileFixture -{ - LoadTestFileFixture(); - -protected: - Json::Value m_json; -}; - -struct ParallelFixture -{ - void enumerateThreads(std::function callback) const; -}; - -struct BlockChainFixture: public LoadTestFileFixture -{ - void enumerateBlockchains(std::function callback) const; -}; - -struct ClientBaseFixture: public BlockChainFixture -{ - void enumerateClients(std::function callback) const; -}; - -// important BOOST TEST do have problems with thread safety!!! -// BOOST_CHECK is not thread safe -// BOOST_MESSAGE is not thread safe -// http://boost.2283326.n4.nabble.com/Is-boost-test-thread-safe-td3471644.html -// http://lists.boost.org/boost-users/2010/03/57691.php -// worth reading -// https://codecrafter.wordpress.com/2012/11/01/c-unit-test-framework-adapter-part-3/ -struct ParallelClientBaseFixture: public ClientBaseFixture, public ParallelFixture -{ - void enumerateClients(std::function callback) const; -}; - -struct JsonRpcFixture: public ClientBaseFixture -{ - -}; - -} -} diff --git a/test/boostTest.cpp b/test/boostTest.cpp index f448c48e..f3400a31 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -25,68 +25,9 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" //#define BOOST_DISABLE_WIN32 //disables SEH warning -#define BOOST_TEST_NO_MAIN #include #pragma GCC diagnostic pop #include using namespace boost::unit_test; -//Custom Boost Initialization -test_suite* init_func( int argc, char* argv[] ) -{ - if (argc == 0) - argv[1]=(char*)"a"; - - dev::test::Options::get(); - - return 0; -} - -//Custom Boost Unit Test Main -int main( int argc, char* argv[] ) -{ - try - { - framework::init( init_func, argc, argv ); - - if( !runtime_config::test_to_run().is_empty() ) - { - test_case_filter filter( runtime_config::test_to_run() ); - - traverse_test_tree( framework::master_test_suite().p_id, filter ); - } - - framework::run(); - - results_reporter::make_report(); - - return runtime_config::no_result_code() - ? boost::exit_success - : results_collector.results( framework::master_test_suite().p_id ).result_code(); - } - catch (framework::nothing_to_test const&) - { - return boost::exit_success; - } - catch (framework::internal_error const& ex) - { - results_reporter::get_stream() << "Boost.Test framework internal error: " << ex.what() << std::endl; - - return boost::exit_exception_failure; - } - catch (framework::setup_error const& ex) - { - results_reporter::get_stream() << "Test setup error: " << ex.what() << std::endl; - - return boost::exit_exception_failure; - } - catch (...) - { - results_reporter::get_stream() << "Boost.Test framework internal error: unknown reason" << std::endl; - - return boost::exit_exception_failure; - } - - return 0; -} -- cgit