Add unit tests to CI (#140)
This commit is contained in:
parent
ce075b056f
commit
7a9ed920d5
57
.github/workflows/test.yml
vendored
57
.github/workflows/test.yml
vendored
@ -136,3 +136,60 @@ jobs:
|
|||||||
- name: build and test
|
- name: build and test
|
||||||
run: |
|
run: |
|
||||||
python3 ci/test-all-configs.py --${{matrix.compiler}}
|
python3 ci/test-all-configs.py --${{matrix.compiler}}
|
||||||
|
|
||||||
|
|
||||||
|
unittest-linux:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
compiler: [g++-10, clang++-14]
|
||||||
|
shared: [OFF, ON]
|
||||||
|
build_type: [Debug, RelWithDebInfo]
|
||||||
|
has_dl_find_object: [OFF, ON]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt install gcc-10 g++-10 libgcc-10-dev ninja-build
|
||||||
|
- name: build and test
|
||||||
|
run: |
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake .. \
|
||||||
|
-GNinja \
|
||||||
|
-DCMAKE_CXX_COMPILER=${{matrix.compiler}} \
|
||||||
|
-DCMAKE_C_COMPILER=${{matrix.compiler == 'g++-10' && 'gcc-10' || 'clang-14'}} \
|
||||||
|
-DCMAKE_BUILD_TYPE=${{matrix.build_type}} \
|
||||||
|
-DBUILD_SHARED_LIBS=${{matrix.shared}} \
|
||||||
|
-DHAS_DL_FIND_OBJECT=${{matrix.has_dl_find_object}} \
|
||||||
|
-DCPPTRACE_WERROR_BUILD=On \
|
||||||
|
-DCPPTRACE_BUILD_TESTING=On
|
||||||
|
ninja
|
||||||
|
./unittest
|
||||||
|
bash -c "exec -a u ./unittest"
|
||||||
|
unittest-windows:
|
||||||
|
runs-on: windows-2022
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
compiler: [cl, clang++]
|
||||||
|
shared: [OFF] # TODO: Re-enable shared
|
||||||
|
build_type: [Debug, RelWithDebInfo]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Enable Developer Command Prompt
|
||||||
|
uses: ilammy/msvc-dev-cmd@v1.13.0
|
||||||
|
- name: build and test
|
||||||
|
run: |
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake .. `
|
||||||
|
-DCMAKE_CXX_COMPILER=${{matrix.compiler}} `
|
||||||
|
-DCMAKE_C_COMPILER=${{matrix.compiler == 'clang++' && 'clang' || matrix.compiler}} `
|
||||||
|
-DBUILD_SHARED_LIBS=${{matrix.shared}} `
|
||||||
|
-DCPPTRACE_WERROR_BUILD=On `
|
||||||
|
-DCPPTRACE_BUILD_TESTING=On
|
||||||
|
cmake --build . --config ${{matrix.build_type}}
|
||||||
|
./${{matrix.build_type}}/unittest
|
||||||
|
# TODO: Macos, mingw
|
||||||
|
|||||||
@ -10,7 +10,9 @@ cd build
|
|||||||
cmake .. -DZSTD_BUILD_SHARED=On -DZSTD_BUILD_SHARED=Off -DZSTD_LEGACY_SUPPORT=Off -DZSTD_BUILD_PROGRAMS=Off -DZSTD_BUILD_CONTRIB=Off -DZSTD_BUILD_TESTS=Off -G"Unix Makefiles"
|
cmake .. -DZSTD_BUILD_SHARED=On -DZSTD_BUILD_SHARED=Off -DZSTD_LEGACY_SUPPORT=Off -DZSTD_BUILD_PROGRAMS=Off -DZSTD_BUILD_CONTRIB=Off -DZSTD_BUILD_TESTS=Off -G"Unix Makefiles"
|
||||||
make -j
|
make -j
|
||||||
make install
|
make install
|
||||||
|
|
||||||
cd ../../../..
|
cd ../../../..
|
||||||
|
|
||||||
mkdir libdwarf
|
mkdir libdwarf
|
||||||
cd libdwarf
|
cd libdwarf
|
||||||
git init
|
git init
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
sudo apt install libgtest-dev
|
||||||
|
|
||||||
mkdir zstd
|
mkdir zstd
|
||||||
cd zstd
|
cd zstd
|
||||||
git init
|
git init
|
||||||
@ -7,7 +9,9 @@ git fetch --depth 1 origin 63779c798237346c2b245c546c40b72a5a5913fe # 1.5.5
|
|||||||
git checkout FETCH_HEAD
|
git checkout FETCH_HEAD
|
||||||
make -j
|
make -j
|
||||||
sudo make install
|
sudo make install
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
mkdir libdwarf
|
mkdir libdwarf
|
||||||
cd libdwarf
|
cd libdwarf
|
||||||
git init
|
git init
|
||||||
|
|||||||
@ -177,7 +177,7 @@ def build(matrix):
|
|||||||
f"-D{matrix['demangle']}=On",
|
f"-D{matrix['demangle']}=On",
|
||||||
"-DCPPTRACE_BACKTRACE_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/include/backtrace.h",
|
"-DCPPTRACE_BACKTRACE_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/include/backtrace.h",
|
||||||
"-DCPPTRACE_BUILD_TESTING=On",
|
"-DCPPTRACE_BUILD_TESTING=On",
|
||||||
"-DCPPTRACE_IS_GH_ACTIONS=On",
|
"-DCPPTRACE_SKIP_UNIT=On",
|
||||||
f"-DBUILD_SHARED_LIBS={matrix['shared']}"
|
f"-DBUILD_SHARED_LIBS={matrix['shared']}"
|
||||||
]
|
]
|
||||||
if matrix['symbols'] == "CPPTRACE_GET_SYMBOLS_WITH_LIBDL":
|
if matrix['symbols'] == "CPPTRACE_GET_SYMBOLS_WITH_LIBDL":
|
||||||
@ -200,7 +200,7 @@ def build(matrix):
|
|||||||
f"-D{matrix['symbols']}=On",
|
f"-D{matrix['symbols']}=On",
|
||||||
f"-D{matrix['demangle']}=On",
|
f"-D{matrix['demangle']}=On",
|
||||||
"-DCPPTRACE_BUILD_TESTING=On",
|
"-DCPPTRACE_BUILD_TESTING=On",
|
||||||
"-DCPPTRACE_IS_GH_ACTIONS=On",
|
"-DCPPTRACE_SKIP_UNIT=On",
|
||||||
f"-DBUILD_SHARED_LIBS={matrix['shared']}"
|
f"-DBUILD_SHARED_LIBS={matrix['shared']}"
|
||||||
]
|
]
|
||||||
if matrix["compiler"] == "g++":
|
if matrix["compiler"] == "g++":
|
||||||
@ -227,7 +227,7 @@ def build_full_or_auto(matrix):
|
|||||||
f"-DCPPTRACE_WERROR_BUILD=On",
|
f"-DCPPTRACE_WERROR_BUILD=On",
|
||||||
f"-DCPPTRACE_BACKTRACE_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/include/backtrace.h",
|
f"-DCPPTRACE_BACKTRACE_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/include/backtrace.h",
|
||||||
"-DCPPTRACE_BUILD_TESTING=On",
|
"-DCPPTRACE_BUILD_TESTING=On",
|
||||||
"-DCPPTRACE_IS_GH_ACTIONS=On",
|
"-DCPPTRACE_SKIP_UNIT=On",
|
||||||
f"-DBUILD_SHARED_LIBS={matrix['shared']}"
|
f"-DBUILD_SHARED_LIBS={matrix['shared']}"
|
||||||
]
|
]
|
||||||
if matrix["config"] != "":
|
if matrix["config"] != "":
|
||||||
@ -247,7 +247,7 @@ def build_full_or_auto(matrix):
|
|||||||
f"-DCPPTRACE_USE_EXTERNAL_ZSTD=On",
|
f"-DCPPTRACE_USE_EXTERNAL_ZSTD=On",
|
||||||
f"-DCPPTRACE_WERROR_BUILD=On",
|
f"-DCPPTRACE_WERROR_BUILD=On",
|
||||||
"-DCPPTRACE_BUILD_TESTING=On",
|
"-DCPPTRACE_BUILD_TESTING=On",
|
||||||
"-DCPPTRACE_IS_GH_ACTIONS=On",
|
"-DCPPTRACE_SKIP_UNIT=On",
|
||||||
f"-DBUILD_SHARED_LIBS={matrix['shared']}"
|
f"-DBUILD_SHARED_LIBS={matrix['shared']}"
|
||||||
]
|
]
|
||||||
if matrix["config"] != "":
|
if matrix["config"] != "":
|
||||||
|
|||||||
@ -166,7 +166,7 @@ option(CPPTRACE_VCPKG "" OFF)
|
|||||||
option(CPPTRACE_SANITIZER_BUILD "" OFF)
|
option(CPPTRACE_SANITIZER_BUILD "" OFF)
|
||||||
option(CPPTRACE_WERROR_BUILD "" OFF)
|
option(CPPTRACE_WERROR_BUILD "" OFF)
|
||||||
option(CPPTRACE_POSITION_INDEPENDENT_CODE "" ON)
|
option(CPPTRACE_POSITION_INDEPENDENT_CODE "" ON)
|
||||||
option(CPPTRACE_IS_GH_ACTIONS "" OFF)
|
option(CPPTRACE_SKIP_UNIT "" OFF)
|
||||||
option(CPPTRACE_USE_EXTERNAL_GTEST "" OFF)
|
option(CPPTRACE_USE_EXTERNAL_GTEST "" OFF)
|
||||||
|
|
||||||
mark_as_advanced(
|
mark_as_advanced(
|
||||||
@ -177,6 +177,6 @@ mark_as_advanced(
|
|||||||
CPPTRACE_WERROR_BUILD
|
CPPTRACE_WERROR_BUILD
|
||||||
CPPTRACE_CONAN
|
CPPTRACE_CONAN
|
||||||
CPPTRACE_VCPKG
|
CPPTRACE_VCPKG
|
||||||
CPPTRACE_IS_GH_ACTIONS
|
CPPTRACE_SKIP_UNIT
|
||||||
CPPTRACE_USE_EXTERNAL_GTEST
|
CPPTRACE_USE_EXTERNAL_GTEST
|
||||||
)
|
)
|
||||||
|
|||||||
@ -37,7 +37,7 @@ if(UNIX)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# primarily a workaround for github actions issue https://github.com/actions/runner-images/issues/8659
|
# primarily a workaround for github actions issue https://github.com/actions/runner-images/issues/8659
|
||||||
if(NOT CPPTRACE_IS_GH_ACTIONS)
|
if(NOT CPPTRACE_SKIP_UNIT)
|
||||||
if(CPPTRACE_USE_EXTERNAL_GTEST)
|
if(CPPTRACE_USE_EXTERNAL_GTEST)
|
||||||
find_package(GTest)
|
find_package(GTest)
|
||||||
else()
|
else()
|
||||||
@ -60,6 +60,6 @@ if(NOT CPPTRACE_IS_GH_ACTIONS)
|
|||||||
)
|
)
|
||||||
target_compile_features(unittest PRIVATE cxx_std_20)
|
target_compile_features(unittest PRIVATE cxx_std_20)
|
||||||
target_link_libraries(unittest PRIVATE ${target_name} GTest::gtest_main GTest::gmock_main)
|
target_link_libraries(unittest PRIVATE ${target_name} GTest::gtest_main GTest::gmock_main)
|
||||||
target_compile_options(unittest PRIVATE ${warning_options} -Wno-pedantic)
|
target_compile_options(unittest PRIVATE ${warning_options} $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wno-pedantic -Wno-attributes>)
|
||||||
add_test(NAME unittest COMMAND unittest)
|
add_test(NAME unittest COMMAND unittest)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@ -49,16 +49,25 @@ TEST(ObjectTrace, BasicResolution) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: dbghelp uses raw address, not object
|
||||||
CPPTRACE_FORCE_NO_INLINE void object_resolve_3(std::vector<int>& line_numbers) {
|
#ifndef _MSC_VER
|
||||||
|
CPPTRACE_FORCE_NO_INLINE int object_resolve_3(std::vector<int>& line_numbers) {
|
||||||
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
||||||
auto dummy = cpptrace::generate_trace();
|
auto dummy = cpptrace::generate_trace();
|
||||||
auto dummy_otrace = cpptrace::generate_object_trace();
|
auto dummy_otrace = cpptrace::generate_object_trace();
|
||||||
cpptrace::object_trace otrace;
|
cpptrace::object_trace otrace;
|
||||||
otrace.frames.push_back(cpptrace::object_frame{0, dummy.frames[0].object_address, dummy_otrace.frames[0].object_path});
|
otrace.frames.push_back(
|
||||||
otrace.frames.push_back(cpptrace::object_frame{0, dummy.frames[1].object_address, dummy_otrace.frames[1].object_path});
|
cpptrace::object_frame{0, dummy.frames[0].object_address, dummy_otrace.frames[0].object_path}
|
||||||
otrace.frames.push_back(cpptrace::object_frame{0, dummy.frames[2].object_address, dummy_otrace.frames[2].object_path});
|
);
|
||||||
otrace.frames.push_back(cpptrace::object_frame{0, dummy.frames[3].object_address, dummy_otrace.frames[3].object_path});
|
otrace.frames.push_back(
|
||||||
|
cpptrace::object_frame{0, dummy.frames[1].object_address, dummy_otrace.frames[1].object_path}
|
||||||
|
);
|
||||||
|
otrace.frames.push_back(
|
||||||
|
cpptrace::object_frame{0, dummy.frames[2].object_address, dummy_otrace.frames[2].object_path}
|
||||||
|
);
|
||||||
|
otrace.frames.push_back(
|
||||||
|
cpptrace::object_frame{0, dummy.frames[3].object_address, dummy_otrace.frames[3].object_path}
|
||||||
|
);
|
||||||
auto trace = otrace.resolve();
|
auto trace = otrace.resolve();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
EXPECT_THAT(trace.frames[i].filename, testing::EndsWith("object_trace.cpp"));
|
EXPECT_THAT(trace.frames[i].filename, testing::EndsWith("object_trace.cpp"));
|
||||||
@ -76,16 +85,17 @@ CPPTRACE_FORCE_NO_INLINE void object_resolve_3(std::vector<int>& line_numbers) {
|
|||||||
EXPECT_THAT(trace.frames[i].filename, testing::EndsWith("object_trace.cpp"));
|
EXPECT_THAT(trace.frames[i].filename, testing::EndsWith("object_trace.cpp"));
|
||||||
EXPECT_EQ(trace.frames[i].line.value(), line_numbers[i]);
|
EXPECT_EQ(trace.frames[i].line.value(), line_numbers[i]);
|
||||||
EXPECT_THAT(trace.frames[i].symbol, testing::HasSubstr("ObjectTrace_Resolution_Test::TestBody"));
|
EXPECT_THAT(trace.frames[i].symbol, testing::HasSubstr("ObjectTrace_Resolution_Test::TestBody"));
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPTRACE_FORCE_NO_INLINE void object_resolve_2(std::vector<int>& line_numbers) {
|
CPPTRACE_FORCE_NO_INLINE int object_resolve_2(std::vector<int>& line_numbers) {
|
||||||
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
||||||
object_resolve_3(line_numbers);
|
return object_resolve_3(line_numbers) * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPTRACE_FORCE_NO_INLINE void object_resolve_1(std::vector<int>& line_numbers) {
|
CPPTRACE_FORCE_NO_INLINE int object_resolve_1(std::vector<int>& line_numbers) {
|
||||||
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
||||||
object_resolve_2(line_numbers);
|
return object_resolve_2(line_numbers) * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ObjectTrace, Resolution) {
|
TEST(ObjectTrace, Resolution) {
|
||||||
@ -93,3 +103,4 @@ TEST(ObjectTrace, Resolution) {
|
|||||||
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
||||||
object_resolve_1(line_numbers);
|
object_resolve_1(line_numbers);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@ -16,7 +16,8 @@ using namespace std::literals;
|
|||||||
|
|
||||||
// This is fickle, however, it's the only way to do it really. It's reasonably reliable test in practice.
|
// This is fickle, however, it's the only way to do it really. It's reasonably reliable test in practice.
|
||||||
|
|
||||||
CPPTRACE_FORCE_NO_INLINE void raw_trace_basic() {
|
// NOTE: MSVC likes creating trampoline-like entries for non-static functions
|
||||||
|
CPPTRACE_FORCE_NO_INLINE static void raw_trace_basic() {
|
||||||
auto raw_trace = cpptrace::generate_raw_trace();
|
auto raw_trace = cpptrace::generate_raw_trace();
|
||||||
// look for within 90 bytes of the start of the function
|
// 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_GE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(raw_trace_basic));
|
||||||
@ -28,7 +29,14 @@ CPPTRACE_FORCE_NO_INLINE void raw_trace_basic_precise() {
|
|||||||
a:
|
a:
|
||||||
auto raw_trace = cpptrace::generate_raw_trace();
|
auto raw_trace = cpptrace::generate_raw_trace();
|
||||||
b:
|
b:
|
||||||
// look for within 30 bytes of the start of the function
|
// This is stupid, but without it gcc was optimizing both &&a and &&b to point to the start of the function's body
|
||||||
|
volatile auto x = 0;
|
||||||
|
if(x) {
|
||||||
|
goto* &&a;
|
||||||
|
}
|
||||||
|
if(x) {
|
||||||
|
goto* &&b;
|
||||||
|
}
|
||||||
EXPECT_GE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&a));
|
EXPECT_GE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&a));
|
||||||
EXPECT_LE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&b));
|
EXPECT_LE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&b));
|
||||||
}
|
}
|
||||||
@ -39,11 +47,12 @@ TEST(RawTrace, Basic) {
|
|||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
raw_trace_basic_precise();
|
raw_trace_basic_precise();
|
||||||
#endif
|
#endif
|
||||||
|
[[maybe_unused]] volatile int x = 0; // prevent raw_trace_basic_precise() above being a jmp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CPPTRACE_FORCE_NO_INLINE void raw_trace_multi_2(
|
CPPTRACE_FORCE_NO_INLINE static void raw_trace_multi_2(
|
||||||
cpptrace::frame_ptr parent_low_bound,
|
cpptrace::frame_ptr parent_low_bound,
|
||||||
cpptrace::frame_ptr parent_high_bound
|
cpptrace::frame_ptr parent_high_bound
|
||||||
) {
|
) {
|
||||||
@ -54,7 +63,7 @@ CPPTRACE_FORCE_NO_INLINE void raw_trace_multi_2(
|
|||||||
EXPECT_LE(raw_trace.frames[1], parent_high_bound);
|
EXPECT_LE(raw_trace.frames[1], parent_high_bound);
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPTRACE_FORCE_NO_INLINE void raw_trace_multi_1() {
|
CPPTRACE_FORCE_NO_INLINE static void raw_trace_multi_1() {
|
||||||
auto raw_trace = cpptrace::generate_raw_trace();
|
auto raw_trace = cpptrace::generate_raw_trace();
|
||||||
raw_trace_multi_2(reinterpret_cast<uintptr_t>(raw_trace_multi_1), reinterpret_cast<uintptr_t>(raw_trace_multi_1) + 300);
|
raw_trace_multi_2(reinterpret_cast<uintptr_t>(raw_trace_multi_1), reinterpret_cast<uintptr_t>(raw_trace_multi_1) + 300);
|
||||||
EXPECT_GE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(raw_trace_multi_1));
|
EXPECT_GE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(raw_trace_multi_1));
|
||||||
@ -63,8 +72,8 @@ CPPTRACE_FORCE_NO_INLINE void raw_trace_multi_1() {
|
|||||||
|
|
||||||
std::vector<std::pair<cpptrace::frame_ptr, cpptrace::frame_ptr>> parents;
|
std::vector<std::pair<cpptrace::frame_ptr, cpptrace::frame_ptr>> parents;
|
||||||
|
|
||||||
CPPTRACE_FORCE_NO_INLINE void record_parent(cpptrace::frame_ptr low_bound, cpptrace::frame_ptr high_bound) {
|
CPPTRACE_FORCE_NO_INLINE void record_parent(uintptr_t low_bound, uintptr_t high_bound) {
|
||||||
parents.insert(parents.begin(), {reinterpret_cast<uintptr_t>(low_bound), reinterpret_cast<uintptr_t>(high_bound)});
|
parents.insert(parents.begin(), {low_bound, high_bound});
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
@ -72,6 +81,13 @@ CPPTRACE_FORCE_NO_INLINE void raw_trace_multi_precise_3() {
|
|||||||
a:
|
a:
|
||||||
auto raw_trace = cpptrace::generate_raw_trace();
|
auto raw_trace = cpptrace::generate_raw_trace();
|
||||||
b:
|
b:
|
||||||
|
volatile auto x = 0;
|
||||||
|
if(x) {
|
||||||
|
goto* &&a;
|
||||||
|
}
|
||||||
|
if(x) {
|
||||||
|
goto* &&b;
|
||||||
|
}
|
||||||
EXPECT_GE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&a)); // this frame
|
EXPECT_GE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&a)); // this frame
|
||||||
EXPECT_LE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&b));
|
EXPECT_LE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&b));
|
||||||
for(size_t i = 0; i < parents.size(); i++) { // parent frames
|
for(size_t i = 0; i < parents.size(); i++) { // parent frames
|
||||||
@ -84,6 +100,13 @@ CPPTRACE_FORCE_NO_INLINE void raw_trace_multi_precise_2() {
|
|||||||
a:
|
a:
|
||||||
auto raw_trace = cpptrace::generate_raw_trace();
|
auto raw_trace = cpptrace::generate_raw_trace();
|
||||||
b:
|
b:
|
||||||
|
volatile auto x = 0;
|
||||||
|
if(x) {
|
||||||
|
goto* &&a;
|
||||||
|
}
|
||||||
|
if(x) {
|
||||||
|
goto* &&b;
|
||||||
|
}
|
||||||
EXPECT_GE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&a)); // this frame
|
EXPECT_GE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&a)); // this frame
|
||||||
EXPECT_LE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&b));
|
EXPECT_LE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&b));
|
||||||
for(size_t i = 0; i < parents.size(); i++) { // parent frames
|
for(size_t i = 0; i < parents.size(); i++) { // parent frames
|
||||||
@ -93,19 +116,38 @@ CPPTRACE_FORCE_NO_INLINE void raw_trace_multi_precise_2() {
|
|||||||
record_parent(reinterpret_cast<uintptr_t>(&&c), reinterpret_cast<uintptr_t>(&&d));
|
record_parent(reinterpret_cast<uintptr_t>(&&c), reinterpret_cast<uintptr_t>(&&d));
|
||||||
c:
|
c:
|
||||||
raw_trace_multi_precise_3();
|
raw_trace_multi_precise_3();
|
||||||
d:;
|
d:
|
||||||
|
if(x) {
|
||||||
|
goto* &&c;
|
||||||
|
}
|
||||||
|
if(x) {
|
||||||
|
goto* &&d;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPTRACE_FORCE_NO_INLINE void raw_trace_multi_precise_1() {
|
CPPTRACE_FORCE_NO_INLINE void raw_trace_multi_precise_1() {
|
||||||
a:
|
a:
|
||||||
auto raw_trace = cpptrace::generate_raw_trace();
|
auto raw_trace = cpptrace::generate_raw_trace();
|
||||||
b:
|
b:
|
||||||
|
volatile auto x = 0;
|
||||||
|
if(x) {
|
||||||
|
goto* &&a;
|
||||||
|
}
|
||||||
|
if(x) {
|
||||||
|
goto* &&b;
|
||||||
|
}
|
||||||
EXPECT_GE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&a));
|
EXPECT_GE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&a));
|
||||||
EXPECT_LE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&b));
|
EXPECT_LE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(&&b));
|
||||||
record_parent(reinterpret_cast<uintptr_t>(&&c), reinterpret_cast<uintptr_t>(&&d));
|
record_parent(reinterpret_cast<uintptr_t>(&&c), reinterpret_cast<uintptr_t>(&&d));
|
||||||
c:
|
c:
|
||||||
raw_trace_multi_precise_2();
|
raw_trace_multi_precise_2();
|
||||||
d:;
|
d:
|
||||||
|
if(x) {
|
||||||
|
goto* &&c;
|
||||||
|
}
|
||||||
|
if(x) {
|
||||||
|
goto* &&d;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -42,7 +42,9 @@ TEST(Stacktrace, Basic) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
CPPTRACE_FORCE_NO_INLINE void stacktrace_multi_3(std::vector<int>& line_numbers) {
|
// NOTE: returning something and then return stacktrace_multi_3(line_numbers) * 2; later helps prevent the call from
|
||||||
|
// being optimized to a jmp
|
||||||
|
CPPTRACE_FORCE_NO_INLINE int stacktrace_multi_3(std::vector<int>& line_numbers) {
|
||||||
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
||||||
auto trace = cpptrace::generate_trace();
|
auto trace = cpptrace::generate_trace();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -61,16 +63,17 @@ CPPTRACE_FORCE_NO_INLINE void stacktrace_multi_3(std::vector<int>& line_numbers)
|
|||||||
EXPECT_THAT(trace.frames[i].filename, testing::EndsWith("stacktrace.cpp"));
|
EXPECT_THAT(trace.frames[i].filename, testing::EndsWith("stacktrace.cpp"));
|
||||||
EXPECT_EQ(trace.frames[i].line.value(), line_numbers[i]);
|
EXPECT_EQ(trace.frames[i].line.value(), line_numbers[i]);
|
||||||
EXPECT_THAT(trace.frames[i].symbol, testing::HasSubstr("Stacktrace_MultipleFrames_Test::TestBody"));
|
EXPECT_THAT(trace.frames[i].symbol, testing::HasSubstr("Stacktrace_MultipleFrames_Test::TestBody"));
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPTRACE_FORCE_NO_INLINE void stacktrace_multi_2(std::vector<int>& line_numbers) {
|
CPPTRACE_FORCE_NO_INLINE int stacktrace_multi_2(std::vector<int>& line_numbers) {
|
||||||
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
||||||
stacktrace_multi_3(line_numbers);
|
return stacktrace_multi_3(line_numbers) * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPTRACE_FORCE_NO_INLINE void stacktrace_multi_1(std::vector<int>& line_numbers) {
|
CPPTRACE_FORCE_NO_INLINE int stacktrace_multi_1(std::vector<int>& line_numbers) {
|
||||||
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
||||||
stacktrace_multi_2(line_numbers);
|
return stacktrace_multi_2(line_numbers) * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Stacktrace, MultipleFrames) {
|
TEST(Stacktrace, MultipleFrames) {
|
||||||
@ -121,7 +124,8 @@ TEST(Stacktrace, RawTraceResolution) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
CPPTRACE_FORCE_NO_INLINE void stacktrace_inline_resolution_3(std::vector<int>& line_numbers) {
|
#ifndef _MSC_VER
|
||||||
|
CPPTRACE_FORCE_NO_INLINE int stacktrace_inline_resolution_3(std::vector<int>& line_numbers) {
|
||||||
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
||||||
auto trace = cpptrace::generate_trace();
|
auto trace = cpptrace::generate_trace();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -152,16 +156,17 @@ CPPTRACE_FORCE_NO_INLINE void stacktrace_inline_resolution_3(std::vector<int>& l
|
|||||||
EXPECT_FALSE(trace.frames[i].is_inline);
|
EXPECT_FALSE(trace.frames[i].is_inline);
|
||||||
EXPECT_NE(trace.frames[i].raw_address, 0);
|
EXPECT_NE(trace.frames[i].raw_address, 0);
|
||||||
EXPECT_NE(trace.frames[i].object_address, 0);
|
EXPECT_NE(trace.frames[i].object_address, 0);
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPTRACE_FORCE_INLINE void stacktrace_inline_resolution_2(std::vector<int>& line_numbers) {
|
CPPTRACE_FORCE_INLINE int stacktrace_inline_resolution_2(std::vector<int>& line_numbers) {
|
||||||
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
||||||
stacktrace_inline_resolution_3(line_numbers);
|
return stacktrace_inline_resolution_3(line_numbers) * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPTRACE_FORCE_NO_INLINE void stacktrace_inline_resolution_1(std::vector<int>& line_numbers) {
|
CPPTRACE_FORCE_NO_INLINE int stacktrace_inline_resolution_1(std::vector<int>& line_numbers) {
|
||||||
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
||||||
stacktrace_inline_resolution_2(line_numbers);
|
return stacktrace_inline_resolution_2(line_numbers) * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Stacktrace, InlineResolution) {
|
TEST(Stacktrace, InlineResolution) {
|
||||||
@ -169,3 +174,4 @@ TEST(Stacktrace, InlineResolution) {
|
|||||||
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
line_numbers.insert(line_numbers.begin(), __LINE__ + 1);
|
||||||
stacktrace_inline_resolution_1(line_numbers);
|
stacktrace_inline_resolution_1(line_numbers);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user