From 78f5da18622c49dffcbf08d4758d060bbf6e29b5 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Mon, 23 Apr 2018 14:58:21 -0400 Subject: [PATCH] Add new unittests dir for moving over passing tests --- CMakeLists.txt | 1 + unittests/CMakeLists.txt | 76 ++++++++++++++++ unittests/main.cpp | 45 ++++++++++ unittests/wallet_tests.cpp | 172 +++++++++++++++++++++++++++++++++++++ 4 files changed, 294 insertions(+) create mode 100644 unittests/CMakeLists.txt create mode 100644 unittests/main.cpp create mode 100644 unittests/wallet_tests.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3bb934024..daff866d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -187,6 +187,7 @@ add_subdirectory( plugins ) add_subdirectory( programs ) add_subdirectory( scripts ) add_subdirectory( tests ) +add_subdirectory( unittests ) add_subdirectory( tools ) add_subdirectory( debian ) diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt new file mode 100644 index 000000000..61efcac65 --- /dev/null +++ b/unittests/CMakeLists.txt @@ -0,0 +1,76 @@ +#file(GLOB COMMON_SOURCES "common/*.cpp") + +find_package( Gperftools QUIET ) +if( GPERFTOOLS_FOUND ) + message( STATUS "Found gperftools; compiling tests with TCMalloc") + list( APPEND PLATFORM_SPECIFIC_LIBS tcmalloc ) +endif() + +find_package(LLVM 4.0 REQUIRED CONFIG) + +link_directories(${LLVM_LIBRARY_DIR}) + +set( CMAKE_CXX_STANDARD 14 ) + +include_directories("${CMAKE_BINARY_DIR}/contracts") +include_directories("${CMAKE_SOURCE_DIR}/contracts") +include_directories("${CMAKE_SOURCE_DIR}/plugins/wallet_plugin/include") + +file(GLOB UNIT_TESTS "*.cpp") + +add_executable( unit_test ${UNIT_TESTS} ${WASM_UNIT_TESTS} ) +target_link_libraries( unit_test eosio_chain chainbase eos_utilities chain_plugin wallet_plugin abi_generator fc ${PLATFORM_SPECIFIC_LIBS} ) + +target_include_directories( unit_test PUBLIC ${CMAKE_BINARY_DIR}/contracts ${CMAKE_CURRENT_BINARY_DIR}/tests/contracts ) +target_include_directories( unit_test PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/wasm_tests ) +target_include_directories( unit_test PUBLIC ${CMAKE_SOURCE_DIR}/plugins/net_plugin/include ) +target_include_directories( unit_test PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ) +add_dependencies(unit_test asserter test_api test_api_mem test_api_db test_api_multi_index exchange currency proxy identity identity_test stltest infinite eosio.system eosio.token eosio.bios test.inline multi_index_test noop dice eosio.msig) + +#Manually run chain_test for all supported runtimes +#To run chain_test with all log from blockchain displayed, put --verbose after --, i.e. chain_test -- --verbose +add_test(NAME unit_test_binaryen COMMAND chain_test --report_level=detailed --color_output -- --binaryen) +add_test(NAME unit_test_wavm COMMAND chain_test --report_level=detailed --color_output -- --wavm) + +if(ENABLE_COVERAGE_TESTING) + + set(Coverage_NAME ${PROJECT_NAME}_coverage) + set(Coverage_EXECUTABLE unit_test) + + if(NOT LCOV_PATH) + message(FATAL_ERROR "lcov not found! Aborting...") + endif() # NOT LCOV_PATH + + if(NOT GENHTML_PATH) + message(FATAL_ERROR "genhtml not found! Aborting...") + endif() # NOT GENHTML_PATH + + # Setup target + add_custom_target(${Coverage_NAME} + + # Cleanup lcov + COMMAND ${LCOV_PATH} --directory . --zerocounters + # Create baseline to make sure untouched files show up in the report + COMMAND ${LCOV_PATH} -c -i -d . -o ${Coverage_NAME}.base + + # Run tests + COMMAND ${Coverage_EXECUTABLE} + + # Capturing lcov counters and generating report + COMMAND ${LCOV_PATH} --directory . --capture --output-file ${Coverage_NAME}.info + # add baseline counters + COMMAND ${LCOV_PATH} -a ${Coverage_NAME}.base -a ${Coverage_NAME}.info --output-file ${Coverage_NAME}.total + COMMAND ${LCOV_PATH} --remove ${Coverage_NAME}.total ${COVERAGE_EXCLUDES} --output-file ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned + COMMAND ${GENHTML_PATH} -o ${Coverage_NAME} ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned + COMMAND ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.base ${Coverage_NAME}.info ${Coverage_NAME}.total ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned + + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report." + ) + + # Show info where to find the report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ; + COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." + ) +endif() diff --git a/unittests/main.cpp b/unittests/main.cpp new file mode 100644 index 000000000..ad2b58462 --- /dev/null +++ b/unittests/main.cpp @@ -0,0 +1,45 @@ +/** + * @file + * @copyright defined in eos/LICENSE.txt + */ +#include +#include +#include +#include +#include + +//extern uint32_t EOS_TESTING_GENESIS_TIMESTAMP; + +void translate_fc_exception(const fc::exception &e) { + std::cerr << "\033[33m" << e.to_detail_string() << "\033[0m" << std::endl; + BOOST_TEST_FAIL("Caught Unexpected Exception"); +} + +boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) { + // Turn off blockchain logging if no --verbose parameter is not added + // To have verbose enabled, call "tests/chain_test -- --verbose" + bool is_verbose = false; + std::string verbose_arg = "--verbose"; + for (int i = 0; i < argc; i++) { + if (verbose_arg == argv[i]) { + is_verbose = true; + break; + } + } + if(!is_verbose) fc::logger::get(DEFAULT_LOGGER).set_log_level(fc::log_level::off); + + // Register fc::exception translator + boost::unit_test::unit_test_monitor.register_exception_translator(&translate_fc_exception); + + std::srand(time(NULL)); + std::cout << "Random number generator seeded to " << time(NULL) << std::endl; + /* + const char* genesis_timestamp_str = getenv("EOS_TESTING_GENESIS_TIMESTAMP"); + if( genesis_timestamp_str != nullptr ) + { + EOS_TESTING_GENESIS_TIMESTAMP = std::stoul( genesis_timestamp_str ); + } + std::cout << "EOS_TESTING_GENESIS_TIMESTAMP is " << EOS_TESTING_GENESIS_TIMESTAMP << std::endl; + */ + return nullptr; +} diff --git a/unittests/wallet_tests.cpp b/unittests/wallet_tests.cpp new file mode 100644 index 000000000..afff7d743 --- /dev/null +++ b/unittests/wallet_tests.cpp @@ -0,0 +1,172 @@ +/** + * @file + * @copyright defined in eos/LICENSE.txt + */ +#include +#include +#include +#include + +#include +#include + +namespace eosio { + +BOOST_AUTO_TEST_SUITE(wallet_tests) + + +/// Test creating the wallet +BOOST_AUTO_TEST_CASE(wallet_test) +{ try { + using namespace eosio::wallet; + using namespace eosio::utilities; + + wallet_data d; + wallet_api wallet(d); + BOOST_CHECK(wallet.is_locked()); + + wallet.set_password("pass"); + BOOST_CHECK(wallet.is_locked()); + + wallet.unlock("pass"); + BOOST_CHECK(!wallet.is_locked()); + + wallet.set_wallet_filename("test"); + BOOST_CHECK_EQUAL("test", wallet.get_wallet_filename()); + + BOOST_CHECK_EQUAL(0, wallet.list_keys().size()); + + auto priv = fc::crypto::private_key::generate(); + auto pub = priv.get_public_key(); + auto wif = (std::string)priv; + wallet.import_key(wif); + BOOST_CHECK_EQUAL(1, wallet.list_keys().size()); + + auto privCopy = wallet.get_private_key(pub); + BOOST_CHECK_EQUAL(wif, (std::string)privCopy); + + wallet.lock(); + BOOST_CHECK(wallet.is_locked()); + wallet.unlock("pass"); + BOOST_CHECK_EQUAL(1, wallet.list_keys().size()); + wallet.save_wallet_file("wallet_test.json"); + + wallet_data d2; + wallet_api wallet2(d2); + + BOOST_CHECK(wallet2.is_locked()); + wallet2.load_wallet_file("wallet_test.json"); + BOOST_CHECK(wallet2.is_locked()); + + wallet2.unlock("pass"); + BOOST_CHECK_EQUAL(1, wallet2.list_keys().size()); + + auto privCopy2 = wallet2.get_private_key(pub); + BOOST_CHECK_EQUAL(wif, (std::string)privCopy2); +} FC_LOG_AND_RETHROW() } + +/// Test wallet manager +BOOST_AUTO_TEST_CASE(wallet_manager_test) +{ try { + using namespace eosio::wallet; + + if (fc::exists("test.wallet")) fc::remove("test.wallet"); + if (fc::exists("test2.wallet")) fc::remove("test2.wallet"); + + constexpr auto key1 = "5JktVNHnRX48BUdtewU7N1CyL4Z886c42x7wYW7XhNWkDQRhdcS"; + constexpr auto key2 = "5Ju5RTcVDo35ndtzHioPMgebvBM6LkJ6tvuU6LTNQv8yaz3ggZr"; + constexpr auto key3 = "5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3"; // eosio key + + wallet_manager wm; + BOOST_CHECK_EQUAL(0, wm.list_wallets().size()); + BOOST_CHECK_EQUAL(0, wm.list_keys().size()); + BOOST_CHECK_NO_THROW(wm.lock_all()); + + BOOST_CHECK_THROW(wm.lock("test"), fc::exception); + BOOST_CHECK_THROW(wm.unlock("test", "pw"), fc::exception); + BOOST_CHECK_THROW(wm.import_key("test", "pw"), fc::exception); + + auto pw = wm.create("test"); + BOOST_CHECK(!pw.empty()); + BOOST_CHECK_EQUAL(0, pw.find("PW")); // starts with PW + BOOST_CHECK_EQUAL(1, wm.list_wallets().size()); + // eosio key is imported automatically when a wallet is created + BOOST_CHECK_EQUAL(1, wm.list_keys().size()); + BOOST_CHECK(wm.list_wallets().at(0).find("*") != std::string::npos); + wm.lock("test"); + BOOST_CHECK(wm.list_wallets().at(0).find("*") == std::string::npos); + wm.unlock("test", pw); + BOOST_CHECK(wm.list_wallets().at(0).find("*") != std::string::npos); + wm.import_key("test", key1); + BOOST_CHECK_EQUAL(2, wm.list_keys().size()); + auto keys = wm.list_keys(); + + auto pub_pri_pair = [](const char *key) -> auto { + private_key_type prikey = private_key_type(std::string(key)); + return std::pair(prikey.get_public_key(), prikey); + }; + + BOOST_CHECK(std::find(keys.cbegin(), keys.cend(), pub_pri_pair(key1)) != keys.cend()); + + wm.import_key("test", key2); + keys = wm.list_keys(); + BOOST_CHECK(std::find(keys.cbegin(), keys.cend(), pub_pri_pair(key1)) != keys.cend()); + BOOST_CHECK(std::find(keys.cbegin(), keys.cend(), pub_pri_pair(key2)) != keys.cend()); + // key3 was automatically imported + BOOST_CHECK(std::find(keys.cbegin(), keys.cend(), pub_pri_pair(key3)) != keys.cend()); + wm.lock("test"); + BOOST_CHECK_EQUAL(0, wm.list_keys().size()); + wm.unlock("test", pw); + BOOST_CHECK_EQUAL(3, wm.list_keys().size()); + wm.lock_all(); + BOOST_CHECK_EQUAL(0, wm.list_keys().size()); + BOOST_CHECK(wm.list_wallets().at(0).find("*") == std::string::npos); + + auto pw2 = wm.create("test2"); + BOOST_CHECK_EQUAL(2, wm.list_wallets().size()); + // eosio key is imported automatically when a wallet is created + BOOST_CHECK_EQUAL(1, wm.list_keys().size()); + BOOST_CHECK_THROW(wm.import_key("test2", key3), fc::exception); + keys = wm.list_keys(); + BOOST_CHECK(std::find(keys.cbegin(), keys.cend(), pub_pri_pair(key1)) == keys.cend()); + BOOST_CHECK(std::find(keys.cbegin(), keys.cend(), pub_pri_pair(key2)) == keys.cend()); + BOOST_CHECK(std::find(keys.cbegin(), keys.cend(), pub_pri_pair(key3)) != keys.cend()); + wm.unlock("test", pw); + keys = wm.list_keys(); + BOOST_CHECK(std::find(keys.cbegin(), keys.cend(), pub_pri_pair(key1)) != keys.cend()); + BOOST_CHECK(std::find(keys.cbegin(), keys.cend(), pub_pri_pair(key2)) != keys.cend()); + BOOST_CHECK(std::find(keys.cbegin(), keys.cend(), pub_pri_pair(key3)) != keys.cend()); + + private_key_type pkey1{std::string(key1)}; + private_key_type pkey2{std::string(key2)}; + private_key_type pkey3{std::string(key3)}; + + chain::signed_transaction trx; + flat_set pubkeys; + pubkeys.emplace(pkey1.get_public_key()); + pubkeys.emplace(pkey2.get_public_key()); + pubkeys.emplace(pkey3.get_public_key()); + trx = wm.sign_transaction(trx, pubkeys, chain_id_type{}); + const auto& pks = trx.get_signature_keys(chain_id_type{}); + BOOST_CHECK_EQUAL(3, pks.size()); + BOOST_CHECK(find(pks.cbegin(), pks.cend(), pkey1.get_public_key()) != pks.cend()); + BOOST_CHECK(find(pks.cbegin(), pks.cend(), pkey2.get_public_key()) != pks.cend()); + BOOST_CHECK(find(pks.cbegin(), pks.cend(), pkey3.get_public_key()) != pks.cend()); + + BOOST_CHECK_EQUAL(3, wm.list_keys().size()); + wm.set_timeout(chrono::seconds(0)); + BOOST_CHECK_EQUAL(0, wm.list_keys().size()); + + + BOOST_CHECK(fc::exists("test.wallet")); + BOOST_CHECK(fc::exists("test2.wallet")); + fc::remove("test.wallet"); + fc::remove("test2.wallet"); + +} FC_LOG_AND_RETHROW() } + + + +BOOST_AUTO_TEST_SUITE_END() + +} // namespace eos -- GitLab