diff options
Diffstat (limited to '')
-rw-r--r-- | test/CMakeLists.txt | 12 | ||||
-rw-r--r-- | test/unit_tests/CMakeLists.txt | 10 | ||||
-rw-r--r-- | test/unit_tests/dbghelp.cpp | 95 | ||||
-rw-r--r-- | test/unit_tests/error.cpp | 16 | ||||
-rw-r--r-- | test/unit_tests/main.cpp | 2 | ||||
-rw-r--r-- | test/unit_tests/utils.hpp | 37 |
6 files changed, 166 insertions, 6 deletions
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 "$<TARGET_PDB_FILE:call_stack>" DESTINATION bin OPTIONAL) + install(FILES "$<TARGET_PDB_FILE:call_stack>" 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 "$<TARGET_PDB_FILE:symbols>" DESTINATION bin OPTIONAL) + install(FILES "$<TARGET_PDB_FILE:symbols>" 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 "$<TARGET_PDB_FILE:unit_tests>" 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 <pdb/all.hpp> + +#include <boost/filesystem.hpp> +#include <boost/test/unit_test.hpp> + +#include <iterator> +#include <string> +#include <unordered_set> +#include <utility> + +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 <typename T> +using Set = std::unordered_set<T>; + +template <typename T> +Set<T> join(Set<T>&& xs, Set<T>&& 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<std::string> 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 <pdb/all.hpp> + +#include <boost/test/unit_test.hpp> + +#include <windows.h> + +#include <string> + +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 <boost/test/unit_test.hpp> 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 <boost/filesystem.hpp> +#include <boost/nowide/filesystem.hpp> +#include <boost/test/unit_test.hpp> + +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; +}; |