From 10b3c9e5a8ce46cfbc3c80042fcaf6079f6a8a34 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Tue, 24 Mar 2020 19:22:40 +0300 Subject: add some unit tests --- test/CMakeLists.txt | 12 +++--- test/unit_tests/CMakeLists.txt | 10 +++++ test/unit_tests/dbghelp.cpp | 95 ++++++++++++++++++++++++++++++++++++++++++ test/unit_tests/error.cpp | 16 +++++++ test/unit_tests/main.cpp | 2 + test/unit_tests/utils.hpp | 37 ++++++++++++++++ 6 files changed, 166 insertions(+), 6 deletions(-) create mode 100644 test/unit_tests/CMakeLists.txt create mode 100644 test/unit_tests/dbghelp.cpp create mode 100644 test/unit_tests/error.cpp create mode 100644 test/unit_tests/main.cpp create mode 100644 test/unit_tests/utils.hpp (limited to 'test') diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ac3e8b3..c4406c8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -2,16 +2,16 @@ add_executable(call_stack call_stack.cpp) target_link_libraries(call_stack PRIVATE pdb_repo) target_link_libraries(call_stack PRIVATE Boost::nowide) -install(TARGETS call_stack RUNTIME DESTINATION bin) +install(TARGETS call_stack RUNTIME DESTINATION bin/test) if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - install(FILES "$" DESTINATION bin OPTIONAL) + install(FILES "$" DESTINATION bin/test OPTIONAL) endif() -set(CC_STATIC_RUNTIME OFF) # Reduce the number of symbols in this test utility - add_executable(symbols symbols.cpp) -install(TARGETS symbols RUNTIME DESTINATION bin) +install(TARGETS symbols RUNTIME DESTINATION bin/test) if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - install(FILES "$" DESTINATION bin OPTIONAL) + install(FILES "$" DESTINATION bin/test OPTIONAL) endif() + +add_subdirectory(unit_tests) diff --git a/test/unit_tests/CMakeLists.txt b/test/unit_tests/CMakeLists.txt new file mode 100644 index 0000000..e7362e1 --- /dev/null +++ b/test/unit_tests/CMakeLists.txt @@ -0,0 +1,10 @@ +find_package(Boost REQUIRED COMPONENTS filesystem unit_test_framework) + +add_executable(unit_tests main.cpp dbghelp.cpp error.cpp) +target_link_libraries(unit_tests PRIVATE pdb_repo) +target_link_libraries(unit_tests PRIVATE Boost::disable_autolinking Boost::filesystem Boost::nowide Boost::unit_test_framework) + +install(TARGETS unit_tests RUNTIME DESTINATION bin/test) +if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + install(FILES "$" DESTINATION bin/test OPTIONAL) +endif() diff --git a/test/unit_tests/dbghelp.cpp b/test/unit_tests/dbghelp.cpp new file mode 100644 index 0000000..86cf1ff --- /dev/null +++ b/test/unit_tests/dbghelp.cpp @@ -0,0 +1,95 @@ +#include "utils.hpp" + +#include + +#include +#include + +#include +#include +#include +#include + +namespace { + +class DbgHelp { +public: + DbgHelp() : dbghelp{pdb::DbgHelp::post_mortem()} { BOOST_TEST_MESSAGE("Initializing DbgHelp"); } + + ~DbgHelp() { BOOST_TEST_MESSAGE("Cleaning up DbgHelp"); } + + const pdb::DbgHelp dbghelp; + +private: + DbgHelp(const DbgHelp&) = delete; + DbgHelp& operator=(const DbgHelp&) = delete; +}; + +template +using Set = std::unordered_set; + +template +Set join(Set&& xs, Set&& ys) { + xs.insert(std::make_move_iterator(ys.begin()), std::make_move_iterator(ys.end())); + return std::move(xs); +} + +class DbgHelpWithSymbols : public DbgHelp { +public: + DbgHelpWithSymbols() { load_symbols_pdb(); } + + static const std::string& get_namespace() { + static const std::string name{"foobar_ns"}; + return name; + } + + typedef std::unordered_set SymbolList; + + static SymbolList expected_functions() { return make_qualified({"foo", "bar", "baz"}); } + + static SymbolList expected_variables() { return make_qualified({"exit_code"}); } + + static SymbolList expected_symbols() { + return join(expected_functions(), expected_variables()); + } + +private: + static SymbolList make_qualified(SymbolList&& plain) { + SymbolList qualified; + for (auto&& name : plain) { + qualified.emplace(get_namespace() + "::" + std::move(name)); + } + return qualified; + } + + void load_symbols_pdb() { + const auto pdb_path = get_symbols_pdb_path().string(); + BOOST_TEST_MESSAGE("Loading PDB: " << pdb_path); + dbghelp.load_pdb(pdb_path); + } + + static boost::filesystem::path get_symbols_pdb_path() { + return Paths::get().exe_dir / "symbols.pdb"; + } +}; + +} // namespace + +BOOST_AUTO_TEST_SUITE(dbghelp_tests) +BOOST_FIXTURE_TEST_SUITE(enum_symbols_tests, DbgHelpWithSymbols) + +BOOST_AUTO_TEST_CASE(basic) { + // Symbols can be enumerated, and all the expected symbols are there. + auto all_symbols = expected_symbols(); + const auto callback = [&all_symbols](const pdb::SymbolInfo& symbol) { + const auto name = symbol.get_name(); + all_symbols.erase(name); + }; + dbghelp.enum_symbols(callback); + for (const auto& missing : all_symbols) { + BOOST_TEST(false, "Symbol wasn't enumerated: " << missing); + } +} + +BOOST_AUTO_TEST_SUITE_END() +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/unit_tests/error.cpp b/test/unit_tests/error.cpp new file mode 100644 index 0000000..10eb8b4 --- /dev/null +++ b/test/unit_tests/error.cpp @@ -0,0 +1,16 @@ +#include + +#include + +#include + +#include + +BOOST_AUTO_TEST_SUITE(error_tests) + +BOOST_AUTO_TEST_CASE(file_not_found) { + const std::string actual{pdb::error::windows(ERROR_FILE_NOT_FOUND).what()}; + BOOST_TEST(actual == "The system cannot find the file specified."); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/unit_tests/main.cpp b/test/unit_tests/main.cpp new file mode 100644 index 0000000..937bea3 --- /dev/null +++ b/test/unit_tests/main.cpp @@ -0,0 +1,2 @@ +#define BOOST_TEST_MODULE pdb_repo tests +#include diff --git a/test/unit_tests/utils.hpp b/test/unit_tests/utils.hpp new file mode 100644 index 0000000..561ca4d --- /dev/null +++ b/test/unit_tests/utils.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include + +using path = boost::filesystem::path; + +class FixFilesystem { +public: + FixFilesystem() { boost::nowide::nowide_filesystem(); } +}; + +class Paths { +public: + typedef boost::filesystem::path path; + + static Paths& get() { + static FixFilesystem fix_filesystem; + static Paths instance; + return instance; + } + + Paths() : exe_path{get_executable_path()}, exe_dir{exe_path.parent_path()} {} + + const path exe_path; + const path exe_dir; + +private: + static path get_executable_path() { + const auto argv0 = boost::unit_test::framework::master_test_suite().argv[0]; + return boost::filesystem::system_complete(argv0); + } + + Paths(const Paths&) = delete; + Paths& operator=(const Paths&) = delete; +}; -- cgit v1.2.3