From 8b101d04e9b82c4e07e579b95b5dbcafcfd87da6 Mon Sep 17 00:00:00 2001 From: Jeremy Rifkin <51220084+jeremy-rifkin@users.noreply.github.com> Date: Sun, 2 Jul 2023 21:23:35 -0400 Subject: [PATCH] Add testing workflow (#3) --- .github/workflows/build.yml | 6 +- .github/workflows/test.yml | 154 ++++++++++++++++++++++ CMakeLists.txt | 40 +++--- README.md | 3 +- cmake/has_backtrace.cpp | 4 +- src/full/full_trace_with_libbacktrace.cpp | 4 +- src/symbols/symbols_with_libbacktrace.cpp | 10 +- test/CMakeLists.txt | 29 ---- test/expected/clang.txt | 27 ++++ test/expected/gcc.txt | 27 ++++ test/expected/windows_clang.txt | 30 +++++ test/expected/windows_msvc.txt | 30 +++++ test/test.cpp | 24 +++- test/test.py | 54 ++++++++ 14 files changed, 385 insertions(+), 57 deletions(-) create mode 100644 .github/workflows/test.yml delete mode 100644 test/CMakeLists.txt create mode 100644 test/expected/clang.txt create mode 100644 test/expected/gcc.txt create mode 100644 test/expected/windows_clang.txt create mode 100644 test/expected/windows_msvc.txt create mode 100644 test/test.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e03dc38..48f01e6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,7 +40,7 @@ jobs: -D${{matrix.unwind}}=On \ -D${{matrix.symbols}}=On \ -D${{matrix.demangle}}=On \ - -DLIBCPP_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 make build-windows: runs-on: windows-2019 @@ -103,7 +103,7 @@ jobs: -DCMAKE_BUILD_TYPE=${{matrix.target}} \ -DCMAKE_CXX_COMPILER=${{matrix.compiler}} \ -DCMAKE_CXX_STANDARD=${{matrix.std}} \ - -DLIBCPP_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 \ ${{matrix.config}} make # TODO: -DCMAKE_CXX_STANDARD isn't being honored? @@ -131,7 +131,7 @@ jobs: # -DCMAKE_BUILD_TYPE=${{matrix.target}} \ # -DCMAKE_CXX_COMPILER=${{matrix.compiler}} \ # -DCMAKE_CXX_STANDARD=${{matrix.std}} \ - # -DLIBCPP_BACKTRACE_PATH=/usr/lib/gcc/x86_64-linux-gnu/12/include/backtrace.h \ + # -DCPPTRACE_BACKTRACE_PATH=/usr/lib/gcc/x86_64-linux-gnu/12/include/backtrace.h \ # ${{matrix.config}} # make build-windows-full-or-auto: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..6c01a58 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,154 @@ +name: test + +on: + push: + pull_request: + +jobs: + test-linux: + runs-on: ubuntu-22.04 + strategy: + fail-fast: false + matrix: + compiler: [g++-10, clang++-14] + target: [Debug] + std: [11, 20] + unwind: [ + CPPTRACE_UNWIND_WITH_EXECINFO, + #CPPTRACE_UNWIND_WITH_NOTHING, + ] + symbols: [ + CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE, + #CPPTRACE_GET_SYMBOLS_WITH_NOTHING, + ] + demangle: [ + CPPTRACE_DEMANGLE_WITH_CXXABI, + #CPPTRACE_DEMANGLE_WITH_NOTHING, + ] + steps: + - uses: actions/checkout@v2 + - name: dependencies + run: sudo apt install gcc-10 g++-10 libgcc-10-dev + - name: build + run: | + mkdir -p build + cd build + cmake .. \ + -DCMAKE_BUILD_TYPE=${{matrix.target}} \ + -DCMAKE_CXX_COMPILER=${{matrix.compiler}} \ + -DCMAKE_CXX_STANDARD=${{matrix.std}} \ + -D${{matrix.unwind}}=On \ + -D${{matrix.symbols}}=On \ + -D${{matrix.demangle}}=On \ + -DCPPTRACE_BACKTRACE_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/include/backtrace.h \ + -DCPPTRACE_BUILD_TEST=On + make + - name: test + working-directory: build + run: | + #readelf --debug-dump=info test | grep foo + ./test | python3 ../test/test.py "${{matrix.compiler}}" + test-windows: + runs-on: windows-2019 + strategy: + fail-fast: false + matrix: + compiler: [cl, clang++] + target: [Debug] + std: [11, 20] + unwind: [ + CPPTRACE_UNWIND_WITH_WINAPI, + # CPPTRACE_UNWIND_WITH_NOTHING, + ] + symbols: [ + CPPTRACE_GET_SYMBOLS_WITH_DBGHELP, + # CPPTRACE_GET_SYMBOLS_WITH_NOTHING, + ] + demangle: [ + # CPPTRACE_DEMANGLE_WITH_CXXABI, + CPPTRACE_DEMANGLE_WITH_NOTHING, + ] + exclude: + - demangle: CPPTRACE_DEMANGLE_WITH_CXXABI + compiler: cl + steps: + - uses: actions/checkout@v2 + - name: Enable Developer Command Prompt + uses: ilammy/msvc-dev-cmd@v1.10.0 + - name: build + run: | + mkdir -p build + cd build + cmake .. ` + -DCMAKE_BUILD_TYPE=Debug ` + -DCMAKE_CXX_COMPILER=${{matrix.compiler}} ` + -DCMAKE_CXX_STANDARD=${{matrix.std}} ` + -D${{matrix.unwind}}=On ` + -D${{matrix.symbols}}=On ` + -D${{matrix.demangle}}=On ` + -DCPPTRACE_BUILD_TEST=On + msbuild .\cpptrace.sln + - name: test + working-directory: build + run: | + .\${{matrix.target}}\test.exe | python3 ..\test\test.py "${{matrix.compiler}}" + + test-linux-full-or-auto: + runs-on: ubuntu-22.04 + strategy: + fail-fast: false + matrix: + compiler: [g++-10, clang++-14] + target: [Debug] + std: [11, 20] + config: ["-DCPPTRACE_FULL_TRACE_WITH_LIBBACKTRACE=On", ""] + steps: + - uses: actions/checkout@v2 + - name: dependencies + run: sudo apt install gcc-10 g++-10 libgcc-10-dev + - name: build + run: | + mkdir -p build + cd build + cmake .. \ + -DCMAKE_BUILD_TYPE=${{matrix.target}} \ + -DCMAKE_CXX_COMPILER=${{matrix.compiler}} \ + -DCMAKE_CXX_STANDARD=${{matrix.std}} \ + -DCPPTRACE_BACKTRACE_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/include/backtrace.h \ + ${{matrix.config}} \ + -DCPPTRACE_BUILD_TEST=On + make + - name: test + working-directory: build + run: | + ./test | python3 ../test/test.py "${{matrix.compiler}}" + test-windows-full-or-auto: + runs-on: windows-2019 + strategy: + fail-fast: false + matrix: + compiler: [cl, clang++] + target: [Debug] + std: [11, 20] + config: [""] + exclude: + - config: -DCPPTRACE_FULL_TRACE_WITH_LIBBACKTRACE=On # TODO + steps: + - uses: actions/checkout@v2 + - name: Enable Developer Command Prompt + uses: ilammy/msvc-dev-cmd@v1.10.0 + - name: build & test + run: | + mkdir -p build + cd build + cmake .. ` + -DCMAKE_BUILD_TYPE=Debug ` + -DCMAKE_CXX_COMPILER=${{matrix.compiler}} ` + -DCMAKE_CXX_STANDARD=${{matrix.std}} ` + ${{matrix.config}} ` + -DCPPTRACE_BUILD_TEST=On + msbuild .\cpptrace.sln + - name: test + working-directory: build + run: | + .\${{matrix.target}}\test.exe | python3 ..\test\test.py "${{matrix.compiler}}" diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b5c01e..5e552fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,21 +63,23 @@ option(CPPTRACE_UNWIND_WITH_NOTHING "" OFF) option(CPPTRACE_DEMANGLE_WITH_CXXABI "" OFF) option(CPPTRACE_DEMANGLE_WITH_NOTHING "" OFF) -set(LIBCPP_BACKTRACE_PATH "" CACHE STRING "Path to backtrace.h, if the compiler doesn't already know it. Check /usr/lib/gcc/x86_64-linux-gnu/*/include.") +option(CPPTRACE_BUILD_TEST "" OFF) + +set(CPPTRACE_BACKTRACE_PATH "" CACHE STRING "Path to backtrace.h, if the compiler doesn't already know it. Check /usr/lib/gcc/x86_64-linux-gnu/*/include.") set(CPPTRACE_HARD_MAX_FRAMES "" CACHE STRING "Hard limit on unwinding depth. Default is 100.") -if(NOT "${LIBCPP_BACKTRACE_PATH}" STREQUAL "") +if(NOT "${CPPTRACE_BACKTRACE_PATH}" STREQUAL "") # quotes used over <> because of a macro substitution issue where # # is expanded to # - string(CONCAT LIBCPP_BACKTRACE_PATH "\"" ${LIBCPP_BACKTRACE_PATH}) - string(CONCAT LIBCPP_BACKTRACE_PATH ${LIBCPP_BACKTRACE_PATH} "\"") - #message(STATUS ${LIBCPP_BACKTRACE_PATH}) - string(CONCAT LIBCPP_BACKTRACE_PATH_DEFINITION "-DLIBCPP_BACKTRACE_PATH=" ${LIBCPP_BACKTRACE_PATH}) - #message(STATUS ${LIBCPP_BACKTRACE_PATH_DEFINITION}) + string(CONCAT CPPTRACE_BACKTRACE_PATH "\"" ${CPPTRACE_BACKTRACE_PATH}) + string(CONCAT CPPTRACE_BACKTRACE_PATH ${CPPTRACE_BACKTRACE_PATH} "\"") + #message(STATUS ${CPPTRACE_BACKTRACE_PATH}) + string(CONCAT CPPTRACE_BACKTRACE_PATH_DEFINITION "-DCPPTRACE_BACKTRACE_PATH=" ${CPPTRACE_BACKTRACE_PATH}) + #message(STATUS ${CPPTRACE_BACKTRACE_PATH_DEFINITION}) else() - set(LIBCPP_BACKTRACE_PATH_DEFINITION "") + set(CPPTRACE_BACKTRACE_PATH_DEFINITION "") endif() function(check_support var source includes libraries definitions) @@ -91,7 +93,7 @@ function(check_support var source includes libraries definitions) endfunction() check_support(HAS_EXECINFO has_execinfo.cpp "" "" "") -check_support(HAS_BACKTRACE has_backtrace.cpp "" "backtrace" "${LIBCPP_BACKTRACE_PATH_DEFINITION}") +check_support(HAS_BACKTRACE has_backtrace.cpp "" "backtrace" "${CPPTRACE_BACKTRACE_PATH_DEFINITION}") check_support(HAS_CXXABI has_cxxabi.cpp "" "" "") if(NOT MSVC) set(STACKTRACE_LINK_LIB "stdc++_libbacktrace") @@ -173,11 +175,11 @@ if( set(CPPTRACE_FULL_TRACE_WITH_LIBBACKTRACE On) message(STATUS "Cpptrace auto config: Using libbacktrace for symbols") else() - message(FATAL_ERROR "Cpptrace auto config: No symbol back end could be automatically configured. To compile anyway set CPPTRACE_GET_SYMBOLS_WITH_NOTHING.") + message(FATAL_ERROR "Cpptrace auto config: No symbol back-end could be automatically configured. To compile anyway set CPPTRACE_GET_SYMBOLS_WITH_NOTHING.") endif() elseif(WIN32) - #set(CPPTRACE_UNWIND_WITH_WINAPI On) - #message(STATUS "Cpptrace auto config: Using winapi for unwinding") + set(CPPTRACE_GET_SYMBOLS_WITH_DBGHELP On) + message(STATUS "Cpptrace auto config: Using dbghelp for symbols") endif() else() #message(STATUS "MANUAL CONFIG SPECIFIED") @@ -204,10 +206,10 @@ endif() function(check_backtrace_error) if(NOT HAS_BACKTRACE) - if(NOT "${LIBCPP_BACKTRACE_PATH}" STREQUAL "") + if(NOT "${CPPTRACE_BACKTRACE_PATH}" STREQUAL "") message(WARNING "Cpptrace: CPPTRACE_FULL_TRACE_WITH_LIBBACKTRACE specified but libbacktrace doesn't appear installed or configured properly.") else() - message(WARNING "Cpptrace: CPPTRACE_FULL_TRACE_WITH_LIBBACKTRACE specified but libbacktrace doesn't appear installed or configured properly. You may need to specify LIBCPP_BACKTRACE_PATH.") + message(WARNING "Cpptrace: CPPTRACE_FULL_TRACE_WITH_LIBBACKTRACE specified but libbacktrace doesn't appear installed or configured properly. You may need to specify CPPTRACE_BACKTRACE_PATH.") endif() endif() endfunction() @@ -231,6 +233,7 @@ endif() if(CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE) check_backtrace_error() target_compile_definitions(cpptrace PUBLIC CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE) + target_link_libraries(cpptrace PRIVATE backtrace) endif() if(CPPTRACE_GET_SYMBOLS_WITH_LIBDL) @@ -278,8 +281,8 @@ if(CPPTRACE_DEMANGLE_WITH_NOTHING) target_compile_definitions(cpptrace PUBLIC CPPTRACE_DEMANGLE_WITH_NOTHING) endif() -if(NOT "${LIBCPP_BACKTRACE_PATH}" STREQUAL "") - target_compile_definitions(cpptrace PUBLIC LIBCPP_BACKTRACE_PATH=${LIBCPP_BACKTRACE_PATH}) +if(NOT "${CPPTRACE_BACKTRACE_PATH}" STREQUAL "") + target_compile_definitions(cpptrace PUBLIC CPPTRACE_BACKTRACE_PATH=${CPPTRACE_BACKTRACE_PATH}) endif() if(NOT "${CPPTRACE_HARD_MAX_FRAMES}" STREQUAL "") @@ -349,3 +352,8 @@ if(NOT CMAKE_SKIP_INSTALL_RULES) DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cpptrace ) endif() + +if(CPPTRACE_BUILD_TEST) + add_executable(test test/test.cpp) + target_link_libraries(test PRIVATE cpptrace) +endif() diff --git a/README.md b/README.md index 7db430f..0fd165e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Cpptrace [![build](https://github.com/jeremy-rifkin/cpptrace/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/jeremy-rifkin/cpptrace/actions/workflows/build.yml) +[![test](https://github.com/jeremy-rifkin/cpptrace/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/jeremy-rifkin/cpptrace/actions/workflows/test.yml) 🚧 WIP 🏗️ @@ -64,7 +65,7 @@ can hold addresses for 100 frames. This is configurable with `CPPTRACE_HARD_MAX_ | Library | CMake config | Windows | Linux | Info | |---------|--------------|---------|-------|------| -| libbacktrace | `CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE` | ❌ | ✔️ | Libbacktrace is already installed on most systems, or available through the compiler directly. If it is installed but backtrace.h is not already in the include path (this can happen when using clang when backtrace lives in gcc's include folder), `LIBCPP_BACKTRACE_PATH` can be used to specify where the library should be looked for. | +| libbacktrace | `CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE` | ❌ | ✔️ | Libbacktrace is already installed on most systems, or available through the compiler directly. If it is installed but backtrace.h is not already in the include path (this can happen when using clang when backtrace lives in gcc's include folder), `CPPTRACE_BACKTRACE_PATH` can be used to specify where the library should be looked for. | | libdl | `CPPTRACE_GET_SYMBOLS_WITH_LIBDL` | ❌ | ✔️ | Libdl uses dynamic export information. Compiling with `-rdynamic` is often needed. | | addr2line | `CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE` | ❌ | ✔️ | Symbols are resolved by invoking `addr2line` via `fork()`. | | dbghelp | `CPPTRACE_GET_SYMBOLS_WITH_DBGHELP` | ✔️ | ❌ | Dbghelp.h allows access to symbols via debug info. | diff --git a/cmake/has_backtrace.cpp b/cmake/has_backtrace.cpp index 7696251..784994a 100644 --- a/cmake/has_backtrace.cpp +++ b/cmake/has_backtrace.cpp @@ -1,5 +1,5 @@ -#ifdef LIBCPP_BACKTRACE_PATH -#include LIBCPP_BACKTRACE_PATH +#ifdef CPPTRACE_BACKTRACE_PATH +#include CPPTRACE_BACKTRACE_PATH #else #include #endif diff --git a/src/full/full_trace_with_libbacktrace.cpp b/src/full/full_trace_with_libbacktrace.cpp index 252e853..9f0ed74 100644 --- a/src/full/full_trace_with_libbacktrace.cpp +++ b/src/full/full_trace_with_libbacktrace.cpp @@ -7,8 +7,8 @@ #include -#ifdef LIBCPP_BACKTRACE_PATH -#include LIBCPP_BACKTRACE_PATH +#ifdef CPPTRACE_BACKTRACE_PATH +#include CPPTRACE_BACKTRACE_PATH #else #include #endif diff --git a/src/symbols/symbols_with_libbacktrace.cpp b/src/symbols/symbols_with_libbacktrace.cpp index 319e7ea..ceb82cc 100644 --- a/src/symbols/symbols_with_libbacktrace.cpp +++ b/src/symbols/symbols_with_libbacktrace.cpp @@ -7,8 +7,8 @@ #include #include -#ifdef LIBCPP_BACKTRACE_PATH -#include LIBCPP_BACKTRACE_PATH +#ifdef CPPTRACE_BACKTRACE_PATH +#include CPPTRACE_BACKTRACE_PATH #else #include #endif @@ -17,6 +17,9 @@ namespace cpptrace { namespace detail { int full_callback(void* data, uintptr_t address, const char* file, int line, const char* symbol) { stacktrace_frame& frame = *static_cast(data); + if(line == 0) { + fprintf(stderr, "Getting bad data for some reason\n"); + } frame.address = address; frame.line = line; frame.filename = file ? file : ""; @@ -24,8 +27,9 @@ namespace cpptrace { return 0; } - void error_callback(void*, const char*, int) { + void error_callback(void* data, const char* msg, int errnum) { // nothing at the moment + fprintf(stderr, "Backtrace error %s %d %p\n", msg, errnum, data); } backtrace_state* get_backtrace_state() { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt deleted file mode 100644 index 19051e4..0000000 --- a/test/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -cmake_minimum_required(VERSION 3.8...3.23) - -if(${CMAKE_VERSION} VERSION_LESS 3.12) - cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) -endif() - -project( - test-cpptrace - VERSION 1.0.0 - LANGUAGES CXX -) - -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${OUTPUT_DIRECTORY}") -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${OUTPUT_DIRECTORY}") -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${OUTPUT_DIRECTORY}") -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${OUTPUT_DIRECTORY}") -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${OUTPUT_DIRECTORY}") -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${OUTPUT_DIRECTORY}") - -add_executable(test test.cpp) -target_link_libraries(test PRIVATE cpptrace) -target_include_directories(test PRIVATE ../include) -target_link_directories(test PRIVATE ../build) - -file(GLOB_RECURSE CPPTRACE_PATHS ../build/cpptrace.dll ../build/cpptrace.so ../build/**/cpptrace.dll ../build/**/cpptrace.so) -list(POP_BACK CPPTRACE_PATHS CPPTRACE_PATH) -#find_library(CPPTRACE_PATH NAMES "cpptrace.dll" "cpptrace.so" PATHS ../build PATH_SUFFIXES Debug Release) -message(STATUS "Copying lib from " ${CPPTRACE_PATH}) -file(COPY ${CPPTRACE_PATH} DESTINATION .) diff --git a/test/expected/clang.txt b/test/expected/clang.txt new file mode 100644 index 0000000..649cfb5 --- /dev/null +++ b/test/expected/clang.txt @@ -0,0 +1,27 @@ +test/test.cpp||18||trace() +test/test.cpp||31||foo(int) +test/test.cpp||33||foo(int) +test/test.cpp||33||foo(int) +test/test.cpp||33||foo(int) +test/test.cpp||33||foo(int) +test/test.cpp||33||foo(int) +test/test.cpp||33||foo(int) +test/test.cpp||33||foo(int) +test/test.cpp||33||foo(int) +test/test.cpp||33||foo(int) +test/test.cpp||33||foo(int) +test/test.cpp||39||void foo(int, int) +test/test.cpp||39||void foo(int, int, int) +test/test.cpp||39||void foo(int, int, int, int) +test/test.cpp||39||void foo(int, int, int, int, int) +test/test.cpp||39||void foo(int, int, int, int, int, int) +test/test.cpp||39||void foo(int, int, int, int, int, int, int) +test/test.cpp||39||void foo(int, int, int, int, int, int, int, int) +test/test.cpp||39||void foo(int, int, int, int, int, int, int, int, int) +test/test.cpp||39||void foo(int, int, int, int, int, int, int, int, int, int) +test/test.cpp||43||function_two(int, float) +test/test.cpp||47||function_one(int) +test/test.cpp||51||main +../csu/libc-start.c||308||__libc_start_main +||0|| +||0|| \ No newline at end of file diff --git a/test/expected/gcc.txt b/test/expected/gcc.txt new file mode 100644 index 0000000..649cfb5 --- /dev/null +++ b/test/expected/gcc.txt @@ -0,0 +1,27 @@ +test/test.cpp||18||trace() +test/test.cpp||31||foo(int) +test/test.cpp||33||foo(int) +test/test.cpp||33||foo(int) +test/test.cpp||33||foo(int) +test/test.cpp||33||foo(int) +test/test.cpp||33||foo(int) +test/test.cpp||33||foo(int) +test/test.cpp||33||foo(int) +test/test.cpp||33||foo(int) +test/test.cpp||33||foo(int) +test/test.cpp||33||foo(int) +test/test.cpp||39||void foo(int, int) +test/test.cpp||39||void foo(int, int, int) +test/test.cpp||39||void foo(int, int, int, int) +test/test.cpp||39||void foo(int, int, int, int, int) +test/test.cpp||39||void foo(int, int, int, int, int, int) +test/test.cpp||39||void foo(int, int, int, int, int, int, int) +test/test.cpp||39||void foo(int, int, int, int, int, int, int, int) +test/test.cpp||39||void foo(int, int, int, int, int, int, int, int, int) +test/test.cpp||39||void foo(int, int, int, int, int, int, int, int, int, int) +test/test.cpp||43||function_two(int, float) +test/test.cpp||47||function_one(int) +test/test.cpp||51||main +../csu/libc-start.c||308||__libc_start_main +||0|| +||0|| \ No newline at end of file diff --git a/test/expected/windows_clang.txt b/test/expected/windows_clang.txt new file mode 100644 index 0000000..4f2bcf0 --- /dev/null +++ b/test/expected/windows_clang.txt @@ -0,0 +1,30 @@ +test\test.cpp||18||trace() +test\test.cpp||32||foo(int) +test\test.cpp||35||foo(int) +test\test.cpp||35||foo(int) +test\test.cpp||35||foo(int) +test\test.cpp||35||foo(int) +test\test.cpp||35||foo(int) +test\test.cpp||35||foo(int) +test\test.cpp||35||foo(int) +test\test.cpp||35||foo(int) +test\test.cpp||35||foo(int) +test\test.cpp||35||foo(int) +test\test.cpp||40||foo(int, int) +test\test.cpp||40||foo(int, int, int) +test\test.cpp||40||foo(int, int, int, int) +test\test.cpp||40||foo(int, int, int, int, int) +test\test.cpp||40||foo(int, int, int, int, int, int) +test\test.cpp||40||foo(int, int, int, int, int, int, int) +test\test.cpp||40||foo(int, int, int, int, int, int, int, int) +test\test.cpp||40||foo(int, int, int, int, int, int, int, int, int) +test\test.cpp||40||foo(int, int, int, int, int, int, int, int, int, int) +test\test.cpp||44||function_two(int, float) +test\test.cpp||48||function_one(int) +test\test.cpp||52||main() +D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl||79||invoke_main() +D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl||288||__scrt_common_main_seh() +D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl||331||__scrt_common_main() +D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp||17||mainCRTStartup(void*) +||-1||BaseThreadInitThunk +||-1||RtlUserThreadStart \ No newline at end of file diff --git a/test/expected/windows_msvc.txt b/test/expected/windows_msvc.txt new file mode 100644 index 0000000..4f2bcf0 --- /dev/null +++ b/test/expected/windows_msvc.txt @@ -0,0 +1,30 @@ +test\test.cpp||18||trace() +test\test.cpp||32||foo(int) +test\test.cpp||35||foo(int) +test\test.cpp||35||foo(int) +test\test.cpp||35||foo(int) +test\test.cpp||35||foo(int) +test\test.cpp||35||foo(int) +test\test.cpp||35||foo(int) +test\test.cpp||35||foo(int) +test\test.cpp||35||foo(int) +test\test.cpp||35||foo(int) +test\test.cpp||35||foo(int) +test\test.cpp||40||foo(int, int) +test\test.cpp||40||foo(int, int, int) +test\test.cpp||40||foo(int, int, int, int) +test\test.cpp||40||foo(int, int, int, int, int) +test\test.cpp||40||foo(int, int, int, int, int, int) +test\test.cpp||40||foo(int, int, int, int, int, int, int) +test\test.cpp||40||foo(int, int, int, int, int, int, int, int) +test\test.cpp||40||foo(int, int, int, int, int, int, int, int, int) +test\test.cpp||40||foo(int, int, int, int, int, int, int, int, int, int) +test\test.cpp||44||function_two(int, float) +test\test.cpp||48||function_one(int) +test\test.cpp||52||main() +D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl||79||invoke_main() +D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl||288||__scrt_common_main_seh() +D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl||331||__scrt_common_main() +D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp||17||mainCRTStartup(void*) +||-1||BaseThreadInitThunk +||-1||RtlUserThreadStart \ No newline at end of file diff --git a/test/test.cpp b/test/test.cpp index fc55abc..889b029 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -1,7 +1,29 @@ #include +#include +#include +#include +#include + +std::string normalize_filename(std::string name) { + if(name.find('/') == 0 || (name.find(':') == 1 && std::isupper(name[0]))) { + auto p = std::min(name.rfind("test/"), name.rfind("test\\")); + return p == std::string::npos ? name : name.substr(p); + } else { + return name; + } +} + void trace() { - cpptrace::print_trace(); + for(const auto& frame : cpptrace::generate_trace()) { + std::cout + << normalize_filename(frame.filename) + << "||" + << frame.line + << "||" + << frame.symbol + << std::endl; + } } void foo(int n) { diff --git a/test/test.py b/test/test.py new file mode 100644 index 0000000..e65ba6f --- /dev/null +++ b/test/test.py @@ -0,0 +1,54 @@ +import os +import sys + +MAX_LINE_DIFF = 2 + +def main(): + if len(sys.argv) != 2: + print("Expected one argument") + sys.exit(1) + + if sys.argv[1].startswith("gcc") or sys.argv[1].startswith("g++"): + name = "gcc" + elif sys.argv[1].startswith("clang"): + name = "clang" + elif sys.argv[1].startswith("cl"): + name = "msvc" + if os.name == "nt": + name = "windows_" + name + + with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), "expected/", name + ".txt"), "r") as f: + expected = f.read() + + output = sys.stdin.read() + + if output.strip() == "": + print(f"Error: No output from test", file=sys.stderr) + sys.exit(1) + + raw_output = output + + expected = [line.split("||") for line in expected.split("\n")] + output = [line.split("||") for line in output.split("\n")] + + errored = False + + for i, ((output_file, output_line, output_symbol), (expected_file, expected_line, expected_symbol)) in enumerate(zip(output, expected)): + if output_file != expected_file: + print(f"Error: File name mismatch on line {i + 1}, found \"{output_file}\" expected \"{expected_file}\"", file=sys.stderr) + errored = True + if abs(int(output_line) - int(expected_line)) > MAX_LINE_DIFF: + print(f"Error: File line mismatch on line {i + 1}, found {output_line} expected {expected_line}", file=sys.stderr) + errored = True + if output_symbol != expected_symbol: + print(f"Error: File symbol mismatch on line {i + 1}, found \"{output_symbol}\" expected \"{expected_symbol}\"", file=sys.stderr) + errored = True + if expected_symbol == "main" or expected_symbol == "main()": + break + + if errored: + print("Test output:", file=sys.stderr) + print(raw_output, file=sys.stderr) + sys.exit(1) + +main()