Add basic unittest
This commit is contained in:
parent
f8ebdd26be
commit
93b1d1c76a
@ -575,5 +575,6 @@ endif()
|
||||
# =============================================== Demo/test ===============================================
|
||||
|
||||
if(CPPTRACE_BUILD_TESTING)
|
||||
enable_testing()
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
15
Makefile
15
Makefile
@ -5,6 +5,9 @@ default: help
|
||||
help: # with thanks to Ben Rady
|
||||
@grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
.PHONY: build
|
||||
build: debug ## build in debug mode
|
||||
|
||||
.PHONY: debug
|
||||
debug: ## build in debug mode
|
||||
cmake -S . -B build -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=On -DCPPTRACE_BUILD_TESTING=On
|
||||
@ -29,13 +32,13 @@ release-msvc: ## build in release mode (with debug info)
|
||||
clean: ## clean
|
||||
rm -rf build
|
||||
|
||||
# .PHONY: test
|
||||
# test: debug ## test
|
||||
# cd build && ninja test
|
||||
.PHONY: test
|
||||
test: debug ## test
|
||||
cd build && ninja test
|
||||
|
||||
# .PHONY: test-release
|
||||
# test-release: release ## test-release
|
||||
# cd build && ninja test
|
||||
.PHONY: test-release
|
||||
test-release: release ## test-release
|
||||
cd build && ninja test
|
||||
|
||||
# .PHONY: test-msvc
|
||||
# test-msvc: debug-msvc ## test
|
||||
|
||||
@ -34,3 +34,18 @@ if(UNIX)
|
||||
target_compile_features(signal_tracer PRIVATE cxx_std_11)
|
||||
target_link_libraries(signal_tracer PRIVATE ${target_name})
|
||||
endif()
|
||||
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
GIT_REPOSITORY "https://github.com/google/googletest.git"
|
||||
GIT_TAG f8d7d77c06936315286eb55f8de22cd23c188571 # v1.14.0
|
||||
)
|
||||
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
add_executable(unittest unittest.cpp)
|
||||
target_compile_features(unittest PRIVATE cxx_std_20)
|
||||
target_link_libraries(unittest PRIVATE ${target_name} GTest::gtest_main GTest::gmock_main)
|
||||
add_test(NAME unittest COMMAND unittest)
|
||||
|
||||
115
test/unittest.cpp
Normal file
115
test/unittest.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gtest/gtest-matchers.h>
|
||||
#include <gmock/gmock.h>
|
||||
#include <gmock/gmock-matchers.h>
|
||||
#include <cpptrace/cpptrace.hpp>
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
// Raw trace tests
|
||||
|
||||
// This is fickle, however, it's the only way to do it really. It's a reliable test in practice.
|
||||
|
||||
[[gnu::noinline]] void raw_trace_basic() {
|
||||
auto raw_trace = cpptrace::generate_raw_trace();
|
||||
// look for within 90 bytes of the start of the function
|
||||
EXPECT_GE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(raw_trace_basic));
|
||||
EXPECT_LE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(raw_trace_basic) + 90);
|
||||
}
|
||||
|
||||
#ifndef _MSC_VER
|
||||
[[gnu::noinline]] void raw_trace_basic_precise() {
|
||||
a:
|
||||
auto raw_trace = cpptrace::generate_raw_trace();
|
||||
b:
|
||||
// look for within 30 bytes of the start of the function
|
||||
EXPECT_GE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&a));
|
||||
EXPECT_LE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&b));
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(RawTrace, Basic) {
|
||||
raw_trace_basic();
|
||||
raw_trace_basic_precise();
|
||||
}
|
||||
|
||||
[[gnu::noinline]] void raw_trace_multi_1(std::pair<cpptrace::frame_ptr, cpptrace::frame_ptr> parent) {
|
||||
auto raw_trace = cpptrace::generate_raw_trace();
|
||||
EXPECT_GE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(raw_trace_multi_1));
|
||||
EXPECT_LE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(raw_trace_multi_1) + 90);
|
||||
EXPECT_GE(raw_trace.frames[1], parent.first);
|
||||
EXPECT_LE(raw_trace.frames[1], parent.second);
|
||||
}
|
||||
|
||||
[[gnu::noinline]] void raw_trace_multi_top() {
|
||||
auto raw_trace = cpptrace::generate_raw_trace();
|
||||
raw_trace_multi_1({reinterpret_cast<uintptr_t>(raw_trace_multi_top), reinterpret_cast<uintptr_t>(raw_trace_multi_top) + 300});
|
||||
EXPECT_GE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(raw_trace_multi_top));
|
||||
EXPECT_LE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(raw_trace_multi_top) + 90);
|
||||
}
|
||||
|
||||
#ifndef _MSC_VER
|
||||
[[gnu::noinline]] void raw_trace_multi_precise_2(std::vector<std::pair<cpptrace::frame_ptr, cpptrace::frame_ptr>>& parents) {
|
||||
a:
|
||||
auto raw_trace = cpptrace::generate_raw_trace();
|
||||
b:
|
||||
EXPECT_GE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&a)); // this frame
|
||||
EXPECT_LE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&b));
|
||||
for(size_t i = 0; i < parents.size(); i++) { // parent frames
|
||||
EXPECT_GE(raw_trace.frames[i + 1], parents[i].first);
|
||||
EXPECT_LE(raw_trace.frames[i + 1], parents[i].second);
|
||||
}
|
||||
}
|
||||
|
||||
[[gnu::noinline]] void raw_trace_multi_precise_1(std::vector<std::pair<cpptrace::frame_ptr, cpptrace::frame_ptr>>& parents) {
|
||||
a:
|
||||
auto raw_trace = cpptrace::generate_raw_trace();
|
||||
b:
|
||||
EXPECT_GE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&a)); // this frame
|
||||
EXPECT_LE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&b));
|
||||
for(size_t i = 0; i < parents.size(); i++) { // parent frames
|
||||
EXPECT_GE(raw_trace.frames[i + 1], parents[i].first);
|
||||
EXPECT_LE(raw_trace.frames[i + 1], parents[i].second);
|
||||
}
|
||||
parents.insert(parents.begin(), {reinterpret_cast<uintptr_t>(&&c), reinterpret_cast<uintptr_t>(&&d)});
|
||||
c:
|
||||
raw_trace_multi_precise_2(parents);
|
||||
d:;
|
||||
}
|
||||
|
||||
[[gnu::noinline]] void raw_trace_multi_precise_top() {
|
||||
a:
|
||||
auto raw_trace = cpptrace::generate_raw_trace();
|
||||
b:
|
||||
EXPECT_GE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&a));
|
||||
EXPECT_LE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&b));
|
||||
std::vector<std::pair<cpptrace::frame_ptr, cpptrace::frame_ptr>> parents;
|
||||
parents.insert(parents.begin(), {reinterpret_cast<uintptr_t>(&&c), reinterpret_cast<uintptr_t>(&&d)});
|
||||
c:
|
||||
raw_trace_multi_precise_1(parents);
|
||||
d:;
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(RawTrace, MultipleCalls) {
|
||||
raw_trace_multi_top();
|
||||
raw_trace_multi_precise_top();
|
||||
}
|
||||
|
||||
[[gnu::noinline]] void stacktrace_basic() {
|
||||
auto line = __LINE__ + 1;
|
||||
auto trace = cpptrace::generate_trace();
|
||||
EXPECT_THAT(trace.frames[0].filename, testing::EndsWith("unittest.cpp"));
|
||||
EXPECT_EQ(trace.frames[0].line.value(), line);
|
||||
EXPECT_THAT(trace.frames[0].symbol, testing::HasSubstr("stacktrace_basic"));
|
||||
}
|
||||
|
||||
TEST(Stacktrace, Basic) {
|
||||
stacktrace_basic();
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user