Skip to content

Commit

Permalink
Add basic unittest
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremy-rifkin committed May 5, 2024
1 parent f8ebdd2 commit 93b1d1c
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 6 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -575,5 +575,6 @@ endif()
# =============================================== Demo/test ===============================================

if(CPPTRACE_BUILD_TESTING)
enable_testing()
add_subdirectory(test)
endif()
15 changes: 9 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
15 changes: 15 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 115 additions & 0 deletions test/unittest.cpp
Original file line number Diff line number Diff line change
@@ -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();
}

0 comments on commit 93b1d1c

Please sign in to comment.