Merge from release/0.10
This commit is contained in:
commit
85cc1669a2
@ -95,7 +95,7 @@ references:
|
|||||||
save_cache:
|
save_cache:
|
||||||
key: v4_upgrade_boost_cache_{{ checksum "/tmp/_build_env_vars" }}_{{ arch }}
|
key: v4_upgrade_boost_cache_{{ checksum "/tmp/_build_env_vars" }}_{{ arch }}
|
||||||
paths:
|
paths:
|
||||||
- /tmp/boost_1_58_0
|
- /tmp/boost_1_65_1
|
||||||
upgrade_boost: &upgrade_boost
|
upgrade_boost: &upgrade_boost
|
||||||
run:
|
run:
|
||||||
name: Upgrade Boost
|
name: Upgrade Boost
|
||||||
@ -104,10 +104,10 @@ references:
|
|||||||
export NUMCORES=`nproc`
|
export NUMCORES=`nproc`
|
||||||
echo Using $NUMCORES cores
|
echo Using $NUMCORES cores
|
||||||
# Download and prepare boost (only if not already present from cache)
|
# Download and prepare boost (only if not already present from cache)
|
||||||
if [ ! -d "/tmp/boost_1_58_0" ]; then
|
if [ ! -d "/tmp/boost_1_65_1" ]; then
|
||||||
echo "Didn't find boost in cache. Downloading and building."
|
echo "Didn't find boost in cache. Downloading and building."
|
||||||
wget -O /tmp/boost.tar.bz2 https://sourceforge.net/projects/boost/files/boost/1.58.0/boost_1_58_0.tar.bz2/download
|
wget -O /tmp/boost.tar.bz2 https://sourceforge.net/projects/boost/files/boost/1.65.1/boost_1_65_1.tar.bz2/download
|
||||||
if [ $(sha512sum /tmp/boost.tar.bz2 | awk '{print $1;}') == "7480ec713b0aa13f0ec990603e87e3b5c8d53f4411329b10fae37fc963b90aad12dbd9290a33c3669ae801e9012a68683eadff057591e9ca2ebcd22b1a67b5d1" ]; then
|
if [ $(sha512sum /tmp/boost.tar.bz2 | awk '{print $1;}') == "a9e6866d3bb3e7c198f442ff09f5322f58064dca79bc420f2f0168eb63964226dfbc4f034a5a5e5958281fdf7518a1b057c894fbda0b61fced59c1661bf30f1a" ]; then
|
||||||
echo Correct sha512sum
|
echo Correct sha512sum
|
||||||
else
|
else
|
||||||
echo Wrong sha512sum
|
echo Wrong sha512sum
|
||||||
@ -117,14 +117,14 @@ references:
|
|||||||
echo Extracting...
|
echo Extracting...
|
||||||
tar -xf /tmp/boost.tar.bz2 -C /tmp
|
tar -xf /tmp/boost.tar.bz2 -C /tmp
|
||||||
rm -rf boost.tar.bz2
|
rm -rf boost.tar.bz2
|
||||||
cd /tmp/boost_1_58_0
|
cd /tmp/boost_1_65_1
|
||||||
./bootstrap.sh --with-toolset=${BUILD_TOOLSET} --with-libraries=filesystem,thread,chrono,program_options
|
./bootstrap.sh --with-toolset=${BUILD_TOOLSET} --with-libraries=filesystem,thread,chrono,program_options
|
||||||
cd ..
|
cd ..
|
||||||
else
|
else
|
||||||
echo Found boost in cache. Use cache and build.
|
echo Found boost in cache. Use cache and build.
|
||||||
fi
|
fi
|
||||||
# Compile and install boost (if cached, this should be fast)
|
# Compile and install boost (if cached, this should be fast)
|
||||||
cd /tmp/boost_1_58_0
|
cd /tmp/boost_1_65_1
|
||||||
sudo ./b2 toolset=${BUILD_TOOLSET} link=static cxxflags=-fPIC -d0 -j$NUMCORES install
|
sudo ./b2 toolset=${BUILD_TOOLSET} link=static cxxflags=-fPIC -d0 -j$NUMCORES install
|
||||||
build_pre: &build_pre
|
build_pre: &build_pre
|
||||||
restore_cache:
|
restore_cache:
|
||||||
@ -419,18 +419,6 @@ jobs:
|
|||||||
GTEST_ARGS: ""
|
GTEST_ARGS: ""
|
||||||
CMAKE_FLAGS: "-DUSE_WERROR=on"
|
CMAKE_FLAGS: "-DUSE_WERROR=on"
|
||||||
RUN_TESTS: false
|
RUN_TESTS: false
|
||||||
gcc_werror:
|
|
||||||
<<: *job_definition
|
|
||||||
environment:
|
|
||||||
CC: gcc-8
|
|
||||||
CXX: g++-8
|
|
||||||
BUILD_TOOLSET: gcc
|
|
||||||
APT_COMPILER_PACKAGE: "g++-8"
|
|
||||||
CXXFLAGS: "-Werror"
|
|
||||||
BUILD_TYPE: "Release"
|
|
||||||
GTEST_ARGS: ""
|
|
||||||
CMAKE_FLAGS: ""
|
|
||||||
RUN_TESTS: false
|
|
||||||
no_compatibility:
|
no_compatibility:
|
||||||
<<: *job_definition
|
<<: *job_definition
|
||||||
environment:
|
environment:
|
||||||
@ -479,7 +467,7 @@ jobs:
|
|||||||
OMP_NUM_THREADS: "1"
|
OMP_NUM_THREADS: "1"
|
||||||
CXXFLAGS: "-O2 -fsanitize=thread -fno-omit-frame-pointer"
|
CXXFLAGS: "-O2 -fsanitize=thread -fno-omit-frame-pointer"
|
||||||
BUILD_TYPE: "Debug"
|
BUILD_TYPE: "Debug"
|
||||||
GTEST_ARGS: "--gtest_filter=-LoggingTest.LoggingAlsoWorksAfterFork:AssertTest_DebugBuild.*:SignalCatcherTest.*_thenDies:SignalHandlerTest.*_thenDies:SignalHandlerTest.givenMultipleSigIntHandlers_whenRaising_thenCatchesCorrectSignal:CliTest_Setup.*:CliTest_IntegrityCheck.*:*/CliTest_WrongEnvironment.*:CliTest_Unmount.*"
|
GTEST_ARGS: "--gtest_filter=-LoggingTest.LoggingAlsoWorksAfterFork:AssertTest_*:BacktraceTest.*:SignalCatcherTest.*_thenDies:SignalHandlerTest.*_thenDies:SignalHandlerTest.givenMultipleSigIntHandlers_whenRaising_thenCatchesCorrectSignal:CliTest_Setup.*:CliTest_IntegrityCheck.*:*/CliTest_WrongEnvironment.*:CliTest_Unmount.*"
|
||||||
CMAKE_FLAGS: ""
|
CMAKE_FLAGS: ""
|
||||||
RUN_TESTS: true
|
RUN_TESTS: true
|
||||||
clang_tidy:
|
clang_tidy:
|
||||||
|
@ -7,7 +7,8 @@ cmake_policy(SET CMP0054 NEW)
|
|||||||
|
|
||||||
project(cryfs)
|
project(cryfs)
|
||||||
|
|
||||||
include(cmake-utils/utils.cmake)
|
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake-utils)
|
||||||
|
include(utils)
|
||||||
|
|
||||||
require_gcc_version(5.0)
|
require_gcc_version(5.0)
|
||||||
require_clang_version(4.0)
|
require_clang_version(4.0)
|
||||||
@ -47,7 +48,7 @@ if(MSVC)
|
|||||||
add_definitions(/bigobj)
|
add_definitions(/bigobj)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(vendor)
|
add_subdirectory(vendor EXCLUDE_FROM_ALL)
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
add_subdirectory(doc)
|
add_subdirectory(doc)
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
|
@ -1,12 +1,23 @@
|
|||||||
Version 0.10.1 (unreleased)
|
Version 0.10.2 (unreleased)
|
||||||
|
---------------
|
||||||
|
|
||||||
|
|
||||||
|
Version 0.10.1
|
||||||
---------------
|
---------------
|
||||||
Fixed bugs:
|
Fixed bugs:
|
||||||
* If file system migration encounters files or folders with the wrong format in the base directory, it now just ignores them instead of crashing.
|
* If file system migration encounters files or folders with the wrong format in the base directory, it now just ignores them instead of crashing.
|
||||||
* When trying to migrate a file system from CryFS 0.9.3 or older, show an error message suggesting to first open it with 0.9.10 because we can't load that anymore.
|
* When trying to migrate a file system from CryFS 0.9.3 or older, show an error message suggesting to first open it with 0.9.10 because we can't load that anymore.
|
||||||
* The '--unmount-idle' parameter works again
|
* The '--unmount-idle' parameter works again
|
||||||
|
* Fix building with boost 1.67
|
||||||
|
|
||||||
|
Compatibility:
|
||||||
|
* Fixed some incompatibilities with systems using the musl libc
|
||||||
|
* Use boost::stacktrace instead of libbacktrace to build stack traces. This fixes a segfault issue with platforms using libexecinfo and is generally more portable.
|
||||||
|
|
||||||
Other:
|
Other:
|
||||||
* Updated to crypto++ 8.1
|
* Updated to crypto++ 8.1
|
||||||
|
* Updated to DokanY 1.2.1
|
||||||
|
* Unit tests can now be run from any directory
|
||||||
|
|
||||||
|
|
||||||
Version 0.10.0
|
Version 0.10.0
|
||||||
|
@ -46,7 +46,7 @@ Requirements
|
|||||||
- GCC version >= 5.0 or Clang >= 4.0
|
- GCC version >= 5.0 or Clang >= 4.0
|
||||||
- CMake version >= 3.0
|
- CMake version >= 3.0
|
||||||
- libcurl4 (including development headers)
|
- libcurl4 (including development headers)
|
||||||
- Boost libraries version >= 1.58 (including development headers)
|
- Boost libraries version >= 1.65.1 (including development headers)
|
||||||
- filesystem
|
- filesystem
|
||||||
- system
|
- system
|
||||||
- chrono
|
- chrono
|
||||||
@ -60,7 +60,7 @@ Requirements
|
|||||||
You can use the following commands to install these requirements
|
You can use the following commands to install these requirements
|
||||||
|
|
||||||
# Ubuntu
|
# Ubuntu
|
||||||
$ sudo apt-get install git g++ cmake make libcurl4-openssl-dev libboost-filesystem-dev libboost-system-dev libboost-chrono-dev libboost-program-options-dev libboost-thread-dev libssl-dev libfuse-dev python
|
$ sudo apt install git g++ cmake make libcurl4-openssl-dev libboost-filesystem-dev libboost-system-dev libboost-chrono-dev libboost-program-options-dev libboost-thread-dev libssl-dev libfuse-dev python
|
||||||
|
|
||||||
# Fedora
|
# Fedora
|
||||||
sudo dnf install git gcc-c++ cmake make libcurl-devel boost-devel boost-static openssl-devel fuse-devel python
|
sudo dnf install git gcc-c++ cmake make libcurl-devel boost-devel boost-static openssl-devel fuse-devel python
|
||||||
@ -96,7 +96,7 @@ Building on Windows (experimental)
|
|||||||
|
|
||||||
Build with Visual Studio 2017 and pass in the following flags to CMake:
|
Build with Visual Studio 2017 and pass in the following flags to CMake:
|
||||||
|
|
||||||
-DDOKAN_PATH=[dokan library location, e.g. "C:\Program Files\Dokan\DokanLibrary-1.1.0"]
|
-DDOKAN_PATH=[dokan library location, e.g. "C:\Program Files\Dokan\DokanLibrary-1.2.1"]
|
||||||
-DBOOST_ROOT=[path to root of boost installation]
|
-DBOOST_ROOT=[path to root of boost installation]
|
||||||
|
|
||||||
If you set these variables correctly in the `CMakeSettings.json` file, you should be able to open the cryfs source folder with Visual Studio 2017.
|
If you set these variables correctly in the `CMakeSettings.json` file, you should be able to open the cryfs source folder with Visual Studio 2017.
|
||||||
|
@ -25,18 +25,18 @@ init:
|
|||||||
- cmd: call "C:\Program Files (x86)\Microsoft Visual Studio\%VisualStudioVersion%\Community\VC\Auxiliary\Build\vcvars%arch%.bat"
|
- cmd: call "C:\Program Files (x86)\Microsoft Visual Studio\%VisualStudioVersion%\Community\VC\Auxiliary\Build\vcvars%arch%.bat"
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- choco install -y dokany --version 1.1.0.2000 --installargs INSTALLDEVFILES=1
|
- choco install -y dokany --version 1.2.1.2000 --installargs INSTALLDEVFILES=1
|
||||||
- cmake --version
|
- cmake --version
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- cmd: mkdir build
|
- cmd: mkdir build
|
||||||
- cmd: cd build
|
- cmd: cd build
|
||||||
# note: The cmake+ninja workflow requires us to set build type in both cmake commands ('cmake' and 'cmake --build'), otherwise the cryfs.exe will depend on debug versions of the visual studio c++ runtime (i.e. msvcp140d.dll)
|
# note: The cmake+ninja workflow requires us to set build type in both cmake commands ('cmake' and 'cmake --build'), otherwise the cryfs.exe will depend on debug versions of the visual studio c++ runtime (i.e. msvcp140d.dll)
|
||||||
- cmd: cmake .. -G "Ninja" -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DBUILD_TESTING=on -DBOOST_ROOT="C:/Libraries/boost_1_65_1" -DDOKAN_PATH="C:/Program Files/Dokan/DokanLibrary-1.1.0"
|
- cmd: cmake .. -G "Ninja" -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DBUILD_TESTING=on -DBOOST_ROOT="C:/Libraries/boost_1_67_0" -DDOKAN_PATH="C:/Program Files/Dokan/DokanLibrary-1.2.1"
|
||||||
- cmd: cmake --build . --config %CONFIGURATION%
|
- cmd: cmake --build . --config %CONFIGURATION%
|
||||||
- cmd: .\test\gitversion\gitversion-test.exe
|
- cmd: .\test\gitversion\gitversion-test.exe
|
||||||
# cpp-utils-test disables ThreadDebuggingTest_ThreadName.*_thenIsCorrect because the appveyor image is too old to support the API needed for that
|
# cpp-utils-test disables ThreadDebuggingTest_ThreadName.*_thenIsCorrect because the appveyor image is too old to support the API needed for that
|
||||||
- cmd: cd .\test\cpp-utils\ && .\cpp-utils-test.exe --gtest_filter=-ThreadDebuggingTest_ThreadName.*_thenIsCorrect && cd ..\..
|
- cmd: .\test\cpp-utils\cpp-utils-test.exe --gtest_filter=-ThreadDebuggingTest_ThreadName.*_thenIsCorrect
|
||||||
#- cmd: .\test\fspp\fspp-test.exe
|
#- cmd: .\test\fspp\fspp-test.exe
|
||||||
- cmd: .\test\parallelaccessstore\parallelaccessstore-test.exe
|
- cmd: .\test\parallelaccessstore\parallelaccessstore-test.exe
|
||||||
- cmd: .\test\blockstore\blockstore-test.exe
|
- cmd: .\test\blockstore\blockstore-test.exe
|
||||||
|
44
cmake-utils/FindLibunwind.cmake
Normal file
44
cmake-utils/FindLibunwind.cmake
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# Taken from https://github.com/monero-project/monero/blob/31bdf7bd113c2576fe579ef3a25a2d8fef419ffc/cmake/FindLibunwind.cmake
|
||||||
|
# modifications:
|
||||||
|
# - remove linkage against gcc_eh because it was causing segfaults in various of our unit tests
|
||||||
|
|
||||||
|
# - Try to find libunwind
|
||||||
|
# Once done this will define
|
||||||
|
#
|
||||||
|
# LIBUNWIND_FOUND - system has libunwind
|
||||||
|
# LIBUNWIND_INCLUDE_DIR - the libunwind include directory
|
||||||
|
# LIBUNWIND_LIBRARIES - Link these to use libunwind
|
||||||
|
# LIBUNWIND_DEFINITIONS - Compiler switches required for using libunwind
|
||||||
|
|
||||||
|
# Copyright (c) 2006, Alexander Dymo, <adymo@kdevelop.org>
|
||||||
|
#
|
||||||
|
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||||
|
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||||
|
|
||||||
|
find_path(LIBUNWIND_INCLUDE_DIR libunwind.h
|
||||||
|
/usr/include
|
||||||
|
/usr/local/include
|
||||||
|
)
|
||||||
|
|
||||||
|
find_library(LIBUNWIND_LIBRARIES NAMES unwind )
|
||||||
|
if(NOT LIBUNWIND_LIBRARIES STREQUAL "LIBUNWIND_LIBRARIES-NOTFOUND")
|
||||||
|
if (CMAKE_COMPILER_IS_GNUCC)
|
||||||
|
set(LIBUNWIND_LIBRARIES "${LIBUNWIND_LIBRARIES}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# some versions of libunwind need liblzma, and we don't use pkg-config
|
||||||
|
# so we just look whether liblzma is installed, and add it if it is.
|
||||||
|
# It might not be actually needed, but doesn't hurt if it is not.
|
||||||
|
# We don't need any headers, just the lib, as it's privately needed.
|
||||||
|
message(STATUS "looking for liblzma")
|
||||||
|
find_library(LIBLZMA_LIBRARIES lzma )
|
||||||
|
if(NOT LIBLZMA_LIBRARIES STREQUAL "LIBLZMA_LIBRARIES-NOTFOUND")
|
||||||
|
message(STATUS "liblzma found")
|
||||||
|
set(LIBUNWIND_LIBRARIES "${LIBUNWIND_LIBRARIES};${LIBLZMA_LIBRARIES}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(Libunwind "Could not find libunwind" LIBUNWIND_INCLUDE_DIR LIBUNWIND_LIBRARIES)
|
||||||
|
# show the LIBUNWIND_INCLUDE_DIR and LIBUNWIND_LIBRARIES variables only in the advanced view
|
||||||
|
mark_as_advanced(LIBUNWIND_INCLUDE_DIR LIBUNWIND_LIBRARIES )
|
@ -108,7 +108,7 @@ endfunction(target_enable_style_warnings)
|
|||||||
function(target_add_boost TARGET)
|
function(target_add_boost TARGET)
|
||||||
# Load boost libraries
|
# Load boost libraries
|
||||||
if(NOT DEFINED Boost_USE_STATIC_LIBS OR Boost_USE_STATIC_LIBS)
|
if(NOT DEFINED Boost_USE_STATIC_LIBS OR Boost_USE_STATIC_LIBS)
|
||||||
# Many supported systems don't have boost >= 1.58. Better link it statically.
|
# Many supported systems don't have boost >= 1.65.1. Better link it statically.
|
||||||
message(STATUS "Boost will be statically linked")
|
message(STATUS "Boost will be statically linked")
|
||||||
set(Boost_USE_STATIC_LIBS ON)
|
set(Boost_USE_STATIC_LIBS ON)
|
||||||
else(NOT DEFINED Boost_USE_STATIC_LIBS OR Boost_USE_STATIC_LIBS)
|
else(NOT DEFINED Boost_USE_STATIC_LIBS OR Boost_USE_STATIC_LIBS)
|
||||||
@ -116,7 +116,7 @@ function(target_add_boost TARGET)
|
|||||||
set(Boost_USE_STATIC_LIBS OFF)
|
set(Boost_USE_STATIC_LIBS OFF)
|
||||||
endif(NOT DEFINED Boost_USE_STATIC_LIBS OR Boost_USE_STATIC_LIBS)
|
endif(NOT DEFINED Boost_USE_STATIC_LIBS OR Boost_USE_STATIC_LIBS)
|
||||||
set(BOOST_THREAD_VERSION 4)
|
set(BOOST_THREAD_VERSION 4)
|
||||||
find_package(Boost 1.58.0
|
find_package(Boost 1.65.1
|
||||||
REQUIRED
|
REQUIRED
|
||||||
COMPONENTS ${ARGN})
|
COMPONENTS ${ARGN})
|
||||||
target_include_directories(${TARGET} SYSTEM PUBLIC ${Boost_INCLUDE_DIRS})
|
target_include_directories(${TARGET} SYSTEM PUBLIC ${Boost_INCLUDE_DIRS})
|
||||||
|
@ -61,13 +61,19 @@ set(SOURCES
|
|||||||
|
|
||||||
add_library(${PROJECT_NAME} STATIC ${SOURCES})
|
add_library(${PROJECT_NAME} STATIC ${SOURCES})
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
if(NOT MSVC)
|
target_link_libraries(${PROJECT_NAME} PUBLIC DbgHelp)
|
||||||
find_package(Backtrace REQUIRED)
|
elseif (APPLE)
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ${Backtrace_INCLUDE_DIRS})
|
target_compile_definitions(${PROJECT_NAME} PRIVATE BOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${Backtrace_LIBRARIES})
|
|
||||||
else()
|
else()
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC DbgHelp)
|
find_program(ADDR2LINE addr2line)
|
||||||
|
if ("${ADDR2LINE}" STREQUAL "ADDR2LINE-NOTFOUND")
|
||||||
|
message(WARNING "addr2line not found. Backtraces will be reduced.")
|
||||||
|
else()
|
||||||
|
message(STATUS "addr2line found. Using it for backtraces.")
|
||||||
|
target_compile_definitions(${PROJECT_NAME} PRIVATE BOOST_STACKTRACE_USE_ADDR2LINE)
|
||||||
|
target_compile_definitions(${PROJECT_NAME} PRIVATE BOOST_STACKTRACE_ADDR2LINE_LOCATION=${ADDR2LINE})
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT MSVC)
|
if (NOT MSVC)
|
||||||
@ -85,6 +91,6 @@ target_link_libraries(${PROJECT_NAME} PUBLIC ${CMAKE_DL_LIBS})
|
|||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC spdlog cryptopp)
|
target_link_libraries(${PROJECT_NAME} PUBLIC spdlog cryptopp)
|
||||||
|
|
||||||
target_add_boost(${PROJECT_NAME} filesystem system thread)
|
target_add_boost(${PROJECT_NAME} filesystem system thread chrono)
|
||||||
target_enable_style_warnings(${PROJECT_NAME})
|
target_enable_style_warnings(${PROJECT_NAME})
|
||||||
target_activate_cpp14(${PROJECT_NAME})
|
target_activate_cpp14(${PROJECT_NAME})
|
||||||
|
@ -1,19 +1,12 @@
|
|||||||
#if !defined(_MSC_VER)
|
#if !defined(_MSC_VER)
|
||||||
|
|
||||||
#include "backtrace.h"
|
|
||||||
#include <execinfo.h>
|
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <iostream>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <cxxabi.h>
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#include "../logging/logging.h"
|
#include "../logging/logging.h"
|
||||||
#include <cpp-utils/process/SignalHandler.h>
|
#include <cpp-utils/process/SignalHandler.h>
|
||||||
|
|
||||||
// TODO Add file and line number on non-windows
|
#include <boost/stacktrace.hpp>
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::ostringstream;
|
using std::ostringstream;
|
||||||
@ -21,91 +14,36 @@ using namespace cpputils::logging;
|
|||||||
|
|
||||||
namespace cpputils {
|
namespace cpputils {
|
||||||
|
|
||||||
namespace {
|
string backtrace() {
|
||||||
std::string demangle(const string &mangledName) {
|
std::ostringstream str;
|
||||||
string result;
|
str << boost::stacktrace::stacktrace();
|
||||||
int status = -10;
|
return str.str();
|
||||||
char *demangledName = nullptr;
|
|
||||||
try {
|
|
||||||
demangledName = abi::__cxa_demangle(mangledName.c_str(), NULL, NULL, &status);
|
|
||||||
if (status == 0) {
|
|
||||||
result = demangledName;
|
|
||||||
} else {
|
|
||||||
result = "[demangling error " + std::to_string(status) + "]" + mangledName;
|
|
||||||
}
|
|
||||||
free(demangledName);
|
|
||||||
return result;
|
|
||||||
} catch (...) {
|
|
||||||
free(demangledName);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void pretty_print(std::ostream& str, const void *addr) {
|
|
||||||
Dl_info info;
|
|
||||||
if (0 == dladdr(addr, &info)) {
|
|
||||||
str << "[failed parsing line]";
|
|
||||||
} else {
|
|
||||||
if (nullptr == info.dli_fname) {
|
|
||||||
str << "[no dli_fname]";
|
|
||||||
} else {
|
|
||||||
str << info.dli_fname;
|
|
||||||
}
|
|
||||||
str << ":" << std::hex << info.dli_fbase << " ";
|
|
||||||
if (nullptr == info.dli_sname) {
|
|
||||||
str << "[no symbol name]";
|
|
||||||
} else if (info.dli_sname[0] == '_') {
|
|
||||||
// is a mangled name
|
|
||||||
str << demangle(info.dli_sname);
|
|
||||||
} else {
|
|
||||||
// is not a mangled name
|
|
||||||
str << info.dli_sname;
|
|
||||||
}
|
|
||||||
str << " : " << std::hex << info.dli_saddr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string backtrace_to_string(void *array[], size_t size) {
|
|
||||||
ostringstream result;
|
|
||||||
for (size_t i = 0; i < size; ++i) {
|
|
||||||
result << "#" << std::dec << i << " ";
|
|
||||||
pretty_print(result, array[i]);
|
|
||||||
result << "\n";
|
|
||||||
}
|
|
||||||
return result.str();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string backtrace() {
|
|
||||||
constexpr unsigned int MAX_SIZE = 100;
|
|
||||||
void *array[MAX_SIZE];
|
|
||||||
size_t size = ::backtrace(array, MAX_SIZE);
|
|
||||||
return backtrace_to_string(array, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void sigsegv_handler(int) {
|
void sigsegv_handler(int) {
|
||||||
LOG(ERR, "SIGSEGV\n{}", backtrace());
|
LOG(ERR, "SIGSEGV\n{}", backtrace());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
void sigill_handler(int) {
|
void sigill_handler(int) {
|
||||||
LOG(ERR, "SIGILL\n{}", backtrace());
|
LOG(ERR, "SIGILL\n{}", backtrace());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
void sigabrt_handler(int) {
|
void sigabrt_handler(int) {
|
||||||
LOG(ERR, "SIGABRT\n{}", backtrace());
|
LOG(ERR, "SIGABRT\n{}", backtrace());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void showBacktraceOnCrash() {
|
void showBacktraceOnCrash() {
|
||||||
// the signal handler RAII objects will be initialized on first call (which will register the signal handler)
|
// the signal handler RAII objects will be initialized on first call (which will register the signal handler)
|
||||||
// and destroyed on program exit (which will unregister the signal handler)
|
// and destroyed on program exit (which will unregister the signal handler)
|
||||||
|
|
||||||
|
static SignalHandlerRAII<&sigsegv_handler> segv(SIGSEGV);
|
||||||
|
static SignalHandlerRAII<&sigabrt_handler> abrt(SIGABRT);
|
||||||
|
static SignalHandlerRAII<&sigill_handler> ill(SIGILL);
|
||||||
|
}
|
||||||
|
|
||||||
static SignalHandlerRAII<&sigsegv_handler> segv(SIGSEGV);
|
|
||||||
static SignalHandlerRAII<&sigabrt_handler> abrt(SIGABRT);
|
|
||||||
static SignalHandlerRAII<&sigill_handler> ill(SIGILL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -88,7 +88,8 @@ public:
|
|||||||
, _registerer(signal, this)
|
, _registerer(signal, this)
|
||||||
, _handler(signal) {
|
, _handler(signal) {
|
||||||
// note: the order of the members ensures that:
|
// note: the order of the members ensures that:
|
||||||
// - when registering the signal handler fails, the registerer will be destroyed, unregistering the signal_occurred_flag,
|
// - when registering the signal handler, the SignalCatcher impl already has a valid _signal_occurred_flag set.
|
||||||
|
// - when registering the signal handler fails, the _registerer will be destroyed again, unregistering this SignalCatcherImpl,
|
||||||
// i.e. there is no leak.
|
// i.e. there is no leak.
|
||||||
|
|
||||||
// Allow only the set of signals that is supported on all platforms, see for Windows: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/signal?view=vs-2017
|
// Allow only the set of signals that is supported on all platforms, see for Windows: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/signal?view=vs-2017
|
||||||
|
@ -9,7 +9,11 @@ namespace cpputils {
|
|||||||
|
|
||||||
void set_thread_name(const char* name);
|
void set_thread_name(const char* name);
|
||||||
std::string get_thread_name();
|
std::string get_thread_name();
|
||||||
|
|
||||||
|
#if defined(__GLIBC__) || defined(__APPLE__) || defined(_MSC_VER)
|
||||||
|
// this is not supported on musl systems, that's why we ifdef it for glibc only.
|
||||||
std::string get_thread_name(std::thread* thread);
|
std::string get_thread_name(std::thread* thread);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,14 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <cpp-utils/assert/assert.h>
|
#include <cpp-utils/assert/assert.h>
|
||||||
|
#if !(defined(__GLIBC__) || defined(__APPLE__))
|
||||||
|
// for pthread_getname_np_gcompat
|
||||||
|
#include <errno.h> // errno
|
||||||
|
#include <fcntl.h> // O_CLOEXEC, O_RDONLY
|
||||||
|
#include <unistd.h> // open, read
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace cpputils {
|
namespace cpputils {
|
||||||
|
|
||||||
@ -28,9 +36,47 @@ void set_thread_name(const char* name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
#if !(defined(__GLIBC__) || defined(__APPLE__))
|
||||||
|
|
||||||
|
struct OpenFileRAII final {
|
||||||
|
explicit OpenFileRAII(const char* filename) : fd(::open(filename, O_RDONLY | O_CLOEXEC)) {}
|
||||||
|
~OpenFileRAII() {
|
||||||
|
int result = close(fd);
|
||||||
|
if (result != 0) {
|
||||||
|
throw std::runtime_error("Error closing file. Errno: " + std::to_string(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
// get the name of a thread
|
||||||
|
int pthread_getname_np_gcompat(pthread_t thread, char *name, size_t len) {
|
||||||
|
ASSERT(thread == pthread_self(), "On musl systems, it's only supported to get the name of the current thread.");
|
||||||
|
|
||||||
|
auto file = OpenFileRAII("/proc/thread-self/comm");
|
||||||
|
ssize_t n;
|
||||||
|
if (file.fd < 0)
|
||||||
|
return errno;
|
||||||
|
n = read(file.fd, name, len);
|
||||||
|
if (n < 0)
|
||||||
|
return errno;
|
||||||
|
// if the trailing newline was not read, the buffer was too small
|
||||||
|
if (n == 0 || name[n - 1] != '\n')
|
||||||
|
return ERANGE;
|
||||||
|
// null-terminate string
|
||||||
|
name[n - 1] = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
std::string get_thread_name(pthread_t thread) {
|
std::string get_thread_name(pthread_t thread) {
|
||||||
char name[MAX_NAME_LEN];
|
char name[MAX_NAME_LEN];
|
||||||
|
#if defined(__GLIBC__) || defined(__APPLE__)
|
||||||
int result = pthread_getname_np(thread, name, MAX_NAME_LEN);
|
int result = pthread_getname_np(thread, name, MAX_NAME_LEN);
|
||||||
|
#else
|
||||||
|
int result = pthread_getname_np_gcompat(thread, name, MAX_NAME_LEN);
|
||||||
|
#endif
|
||||||
if (0 != result) {
|
if (0 != result) {
|
||||||
throw std::runtime_error("Error getting thread name with pthread_getname_np. Code: " + std::to_string(result));
|
throw std::runtime_error("Error getting thread name with pthread_getname_np. Code: " + std::to_string(result));
|
||||||
}
|
}
|
||||||
@ -39,16 +85,19 @@ std::string get_thread_name(pthread_t thread) {
|
|||||||
name[MAX_NAME_LEN - 1] = '\0';
|
name[MAX_NAME_LEN - 1] = '\0';
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get_thread_name() {
|
std::string get_thread_name() {
|
||||||
return get_thread_name(pthread_self());
|
return get_thread_name(pthread_self());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__GLIBC__) || defined(__APPLE__)
|
||||||
std::string get_thread_name(std::thread* thread) {
|
std::string get_thread_name(std::thread* thread) {
|
||||||
ASSERT(thread->joinable(), "Thread not running");
|
ASSERT(thread->joinable(), "Thread not running");
|
||||||
return get_thread_name(thread->native_handle());
|
return get_thread_name(thread->native_handle());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
if (BUILD_TESTING)
|
if (BUILD_TESTING)
|
||||||
include_directories(../src)
|
include_directories(../src)
|
||||||
|
|
||||||
|
add_subdirectory(my-gtest-main)
|
||||||
add_subdirectory(gitversion)
|
add_subdirectory(gitversion)
|
||||||
add_subdirectory(cpp-utils)
|
add_subdirectory(cpp-utils)
|
||||||
if (NOT MSVC)
|
if (NOT MSVC)
|
||||||
|
@ -27,7 +27,7 @@ set(SOURCES
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||||
target_link_libraries(${PROJECT_NAME} googletest blobstore)
|
target_link_libraries(${PROJECT_NAME} my-gtest-main googletest blobstore)
|
||||||
add_test(${PROJECT_NAME} ${PROJECT_NAME})
|
add_test(${PROJECT_NAME} ${PROJECT_NAME})
|
||||||
|
|
||||||
target_enable_style_warnings(${PROJECT_NAME})
|
target_enable_style_warnings(${PROJECT_NAME})
|
||||||
|
@ -42,7 +42,7 @@ set(SOURCES
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||||
target_link_libraries(${PROJECT_NAME} googletest blockstore)
|
target_link_libraries(${PROJECT_NAME} my-gtest-main googletest blockstore)
|
||||||
add_test(${PROJECT_NAME} ${PROJECT_NAME})
|
add_test(${PROJECT_NAME} ${PROJECT_NAME})
|
||||||
|
|
||||||
target_enable_style_warnings(${PROJECT_NAME})
|
target_enable_style_warnings(${PROJECT_NAME})
|
||||||
|
@ -71,7 +71,7 @@ target_activate_cpp14(${PROJECT_NAME}_exit_signal)
|
|||||||
target_link_libraries(${PROJECT_NAME}_exit_signal cpp-utils)
|
target_link_libraries(${PROJECT_NAME}_exit_signal cpp-utils)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||||
target_link_libraries(${PROJECT_NAME} googletest cpp-utils)
|
target_link_libraries(${PROJECT_NAME} my-gtest-main googletest cpp-utils)
|
||||||
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}_exit_status ${PROJECT_NAME}_exit_signal)
|
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}_exit_status ${PROJECT_NAME}_exit_signal)
|
||||||
add_test(${PROJECT_NAME} ${PROJECT_NAME})
|
add_test(${PROJECT_NAME} ${PROJECT_NAME})
|
||||||
|
|
||||||
|
@ -2,33 +2,30 @@
|
|||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include "cpp-utils/assert/backtrace.h"
|
#include "cpp-utils/assert/backtrace.h"
|
||||||
#include "cpp-utils/process/subprocess.h"
|
#include "cpp-utils/process/subprocess.h"
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include "my-gtest-main.h"
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using testing::HasSubstr;
|
using testing::HasSubstr;
|
||||||
|
namespace bf = boost::filesystem;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
std::string call_process_exiting_with(const std::string& kind, const std::string& signal = "") {
|
std::string call_process_exiting_with(const std::string& kind, const std::string& signal = "") {
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
constexpr const char* executable = "cpp-utils-test_exit_signal.exe";
|
auto executable = get_executable().parent_path() / "cpp-utils-test_exit_signal.exe";
|
||||||
#else
|
#else
|
||||||
constexpr const char* executable = "./test/cpp-utils/cpp-utils-test_exit_signal";
|
auto executable = get_executable().parent_path() / "cpp-utils-test_exit_signal";
|
||||||
#endif
|
#endif
|
||||||
const std::string command = std::string(executable) + " \"" + kind + "\" \"" + signal + "\" 2>&1";
|
if (!bf::exists(executable)) {
|
||||||
|
throw std::runtime_error(executable.string() + " not found.");
|
||||||
|
}
|
||||||
|
const std::string command = executable.string() + " \"" + kind + "\" \"" + signal + "\" 2>&1";
|
||||||
auto result = cpputils::Subprocess::call(command);
|
auto result = cpputils::Subprocess::call(command);
|
||||||
return result.output;
|
return result.output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BacktraceTest, ContainsBacktrace) {
|
|
||||||
string backtrace = cpputils::backtrace();
|
|
||||||
EXPECT_THAT(backtrace, HasSubstr("#1"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !(defined(_MSC_VER) && defined(NDEBUG))
|
#if !(defined(_MSC_VER) && defined(NDEBUG))
|
||||||
TEST(BacktraceTest, ContainsExecutableName) {
|
|
||||||
string backtrace = cpputils::backtrace();
|
|
||||||
EXPECT_THAT(backtrace, HasSubstr("cpp-utils-test"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(BacktraceTest, ContainsTopLevelLine) {
|
TEST(BacktraceTest, ContainsTopLevelLine) {
|
||||||
string backtrace = cpputils::backtrace();
|
string backtrace = cpputils::backtrace();
|
||||||
@ -84,26 +81,55 @@ TEST(BacktraceTest, DoesntCrashOnCaughtException) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if !(defined(_MSC_VER) && defined(NDEBUG))
|
#if !(defined(_MSC_VER) && defined(NDEBUG))
|
||||||
|
TEST(BacktraceTest, ContainsBacktrace) {
|
||||||
|
string backtrace = cpputils::backtrace();
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
EXPECT_THAT(backtrace, HasSubstr("testing::Test::Run"));
|
||||||
|
#else
|
||||||
|
EXPECT_THAT(backtrace, HasSubstr("BacktraceTest_ContainsBacktrace_Test::TestBody"));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
TEST(BacktraceTest, ShowBacktraceOnNullptrAccess) {
|
TEST(BacktraceTest, ShowBacktraceOnNullptrAccess) {
|
||||||
auto output = call_process_exiting_with_nullptr_violation();
|
auto output = call_process_exiting_with_nullptr_violation();
|
||||||
EXPECT_THAT(output, HasSubstr("cpp-utils-test_exit_signal"));
|
#if defined(_MSC_VER)
|
||||||
|
EXPECT_THAT(output, HasSubstr("handle_exit_signal"));
|
||||||
|
#else
|
||||||
|
EXPECT_THAT(output, HasSubstr("cpputils::backtrace"));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BacktraceTest, ShowBacktraceOnSigSegv) {
|
TEST(BacktraceTest, ShowBacktraceOnSigSegv) {
|
||||||
auto output = call_process_exiting_with_sigsegv();
|
auto output = call_process_exiting_with_sigsegv();
|
||||||
EXPECT_THAT(output, HasSubstr("cpp-utils-test_exit_signal"));
|
#if defined(_MSC_VER)
|
||||||
|
EXPECT_THAT(output, HasSubstr("handle_exit_signal"));
|
||||||
|
#else
|
||||||
|
EXPECT_THAT(output, HasSubstr("cpputils::backtrace"));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BacktraceTest, ShowBacktraceOnUnhandledException) {
|
TEST(BacktraceTest, ShowBacktraceOnUnhandledException) {
|
||||||
auto output = call_process_exiting_with_exception("my_exception_message");
|
auto output = call_process_exiting_with_exception("my_exception_message");
|
||||||
EXPECT_THAT(output, HasSubstr("cpp-utils-test_exit_signal"));
|
#if defined(_MSC_VER)
|
||||||
|
EXPECT_THAT(output, HasSubstr("handle_exit_signal"));
|
||||||
|
#else
|
||||||
|
EXPECT_THAT(output, HasSubstr("cpputils::backtrace"));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BacktraceTest, ShowBacktraceOnSigIll) {
|
TEST(BacktraceTest, ShowBacktraceOnSigIll) {
|
||||||
auto output = call_process_exiting_with_sigill();
|
auto output = call_process_exiting_with_sigill();
|
||||||
EXPECT_THAT(output, HasSubstr("cpp-utils-test_exit_signal"));
|
#if defined(_MSC_VER)
|
||||||
|
EXPECT_THAT(output, HasSubstr("handle_exit_signal"));
|
||||||
|
#else
|
||||||
|
EXPECT_THAT(output, HasSubstr("cpputils::backtrace"));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
TEST(BacktraceTest, ContainsBacktrace) {
|
||||||
|
string backtrace = cpputils::backtrace();
|
||||||
|
EXPECT_THAT(backtrace, HasSubstr("#1"));
|
||||||
|
}
|
||||||
TEST(BacktraceTest, ShowBacktraceOnNullptrAccess) {
|
TEST(BacktraceTest, ShowBacktraceOnNullptrAccess) {
|
||||||
auto output = call_process_exiting_with_nullptr_violation();
|
auto output = call_process_exiting_with_nullptr_violation();
|
||||||
EXPECT_THAT(output, HasSubstr("#1"));
|
EXPECT_THAT(output, HasSubstr("#1"));
|
||||||
@ -128,7 +154,7 @@ TEST(BacktraceTest, ShowBacktraceOnSigIll) {
|
|||||||
#if !defined(_MSC_VER)
|
#if !defined(_MSC_VER)
|
||||||
TEST(BacktraceTest, ShowBacktraceOnSigAbrt) {
|
TEST(BacktraceTest, ShowBacktraceOnSigAbrt) {
|
||||||
auto output = call_process_exiting_with_sigabrt();
|
auto output = call_process_exiting_with_sigabrt();
|
||||||
EXPECT_THAT(output, HasSubstr("cpp-utils-test_exit_signal"));
|
EXPECT_THAT(output, HasSubstr("cpputils::backtrace"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BacktraceTest, ShowBacktraceOnSigAbrt_ShowsCorrectSignalName) {
|
TEST(BacktraceTest, ShowBacktraceOnSigAbrt_ShowsCorrectSignalName) {
|
||||||
|
@ -1,19 +1,26 @@
|
|||||||
#include <cpp-utils/process/subprocess.h>
|
#include <cpp-utils/process/subprocess.h>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
#include <cpp-utils/lock/ConditionBarrier.h>
|
#include <cpp-utils/lock/ConditionBarrier.h>
|
||||||
|
#include "my-gtest-main.h"
|
||||||
|
|
||||||
using cpputils::Subprocess;
|
using cpputils::Subprocess;
|
||||||
using cpputils::SubprocessError;
|
using cpputils::SubprocessError;
|
||||||
|
using std::string;
|
||||||
|
namespace bf = boost::filesystem;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
std::string exit_with_message_and_status(const char* message, int status) {
|
std::string exit_with_message_and_status(const char* message, int status) {
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
constexpr const char* executable = "cpp-utils-test_exit_status.exe";
|
auto executable = get_executable().parent_path() / "cpp-utils-test_exit_status.exe";
|
||||||
#else
|
#else
|
||||||
constexpr const char* executable = "./test/cpp-utils/cpp-utils-test_exit_status";
|
auto executable = get_executable().parent_path() / "cpp-utils-test_exit_status";
|
||||||
#endif
|
#endif
|
||||||
return std::string(executable) + " \"" + message + "\" " + std::to_string(status);
|
if (!bf::exists(executable)) {
|
||||||
|
throw std::runtime_error(executable.string() + " not found.");
|
||||||
|
}
|
||||||
|
return executable.string() + " \"" + message + "\" " + std::to_string(status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,24 @@ TEST(ThreadDebuggingTest_ThreadName, givenMainThread_whenSettingAndGetting_thenD
|
|||||||
get_thread_name();
|
get_thread_name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ThreadDebuggingTest_ThreadName, givenMainThread_whenGettingFromInside_thenIsCorrect) {
|
||||||
|
set_thread_name("my_thread_name");
|
||||||
|
string name = get_thread_name();
|
||||||
|
EXPECT_EQ("my_thread_name", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ThreadDebuggingTest_ThreadName, givenChildThread_whenGettingFromInside_thenIsCorrect) {
|
||||||
|
std::thread child([] {
|
||||||
|
set_thread_name("my_thread_name");
|
||||||
|
string name = get_thread_name();
|
||||||
|
EXPECT_EQ("my_thread_name", name);
|
||||||
|
});
|
||||||
|
child.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__GLIBC__) || defined(__APPLE__) || defined(_MSC_VER)
|
||||||
|
// disabled on musl because getting the thread name for a child thread doesn't work there
|
||||||
TEST(ThreadDebuggingTest_ThreadName, givenChildThread_whenSettingAndGetting_thenDoesntCrash) {
|
TEST(ThreadDebuggingTest_ThreadName, givenChildThread_whenSettingAndGetting_thenDoesntCrash) {
|
||||||
ConditionBarrier nameIsChecked;
|
ConditionBarrier nameIsChecked;
|
||||||
|
|
||||||
@ -27,37 +45,22 @@ TEST(ThreadDebuggingTest_ThreadName, givenChildThread_whenSettingAndGetting_then
|
|||||||
EXPECT_TRUE(child_didnt_crash);
|
EXPECT_TRUE(child_didnt_crash);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ThreadDebuggingTest_ThreadName, givenMainThread_whenGettingFromInside_thenIsCorrect) {
|
|
||||||
set_thread_name("my_thread_name");
|
|
||||||
string name = get_thread_name();
|
|
||||||
EXPECT_EQ("my_thread_name", name);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(ThreadDebuggingTest_ThreadName, givenChildThread_whenGettingFromInside_thenIsCorrect) {
|
|
||||||
std::thread child([] {
|
|
||||||
set_thread_name("my_thread_name");
|
|
||||||
string name = get_thread_name();
|
|
||||||
EXPECT_EQ("my_thread_name", name);
|
|
||||||
});
|
|
||||||
child.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(ThreadDebuggingTest_ThreadName, givenChildThread_whenGettingFromOutside_thenIsCorrect) {
|
TEST(ThreadDebuggingTest_ThreadName, givenChildThread_whenGettingFromOutside_thenIsCorrect) {
|
||||||
ConditionBarrier nameIsSet;
|
ConditionBarrier nameIsSet;
|
||||||
ConditionBarrier nameIsChecked;
|
ConditionBarrier nameIsChecked;
|
||||||
|
|
||||||
std::thread child([&] {
|
std::thread child([&] {
|
||||||
set_thread_name("my_thread_name");
|
set_thread_name("my_thread_name");
|
||||||
nameIsSet.release();
|
nameIsSet.release();
|
||||||
nameIsChecked.wait();
|
nameIsChecked.wait();
|
||||||
});
|
});
|
||||||
|
|
||||||
nameIsSet.wait();
|
nameIsSet.wait();
|
||||||
set_thread_name("outer_thread_name"); // just to make sure the next line doesn't read the outer thread name
|
set_thread_name("outer_thread_name"); // just to make sure the next line doesn't read the outer thread name
|
||||||
string name = get_thread_name(&child);
|
string name = get_thread_name(&child);
|
||||||
EXPECT_EQ("my_thread_name", name);
|
EXPECT_EQ("my_thread_name", name);
|
||||||
|
|
||||||
nameIsChecked.release();
|
nameIsChecked.release();
|
||||||
child.join();
|
child.join();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -16,7 +16,7 @@ set(SOURCES
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||||
target_link_libraries(${PROJECT_NAME} googletest cryfs-cli cryfs-unmount fspp-fuse)
|
target_link_libraries(${PROJECT_NAME} my-gtest-main googletest cryfs-cli cryfs-unmount fspp-fuse)
|
||||||
add_test(${PROJECT_NAME} ${PROJECT_NAME})
|
add_test(${PROJECT_NAME} ${PROJECT_NAME})
|
||||||
|
|
||||||
target_enable_style_warnings(${PROJECT_NAME})
|
target_enable_style_warnings(${PROJECT_NAME})
|
||||||
|
@ -24,7 +24,7 @@ set(SOURCES
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||||
target_link_libraries(${PROJECT_NAME} googletest cryfs)
|
target_link_libraries(${PROJECT_NAME} my-gtest-main googletest cryfs)
|
||||||
add_test(${PROJECT_NAME} ${PROJECT_NAME})
|
add_test(${PROJECT_NAME} ${PROJECT_NAME})
|
||||||
|
|
||||||
target_enable_style_warnings(${PROJECT_NAME})
|
target_enable_style_warnings(${PROJECT_NAME})
|
||||||
|
@ -102,7 +102,7 @@ set(SOURCES
|
|||||||
testutils/OpenFileHandle.cpp testutils/OpenFileHandle.h)
|
testutils/OpenFileHandle.cpp testutils/OpenFileHandle.h)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||||
target_link_libraries(${PROJECT_NAME} googletest fspp-interface fspp-fuse)
|
target_link_libraries(${PROJECT_NAME} my-gtest-main googletest fspp-interface fspp-fuse)
|
||||||
add_test(${PROJECT_NAME} ${PROJECT_NAME})
|
add_test(${PROJECT_NAME} ${PROJECT_NAME})
|
||||||
|
|
||||||
target_enable_style_warnings(${PROJECT_NAME})
|
target_enable_style_warnings(${PROJECT_NAME})
|
||||||
|
@ -14,7 +14,13 @@ using fspp::fuse::FuseErrnoException;
|
|||||||
|
|
||||||
class FuseFlushErrorTest: public FuseFlushTest, public WithParamInterface<int> {
|
class FuseFlushErrorTest: public FuseFlushTest, public WithParamInterface<int> {
|
||||||
};
|
};
|
||||||
INSTANTIATE_TEST_CASE_P(FuseFlushErrorTest, FuseFlushErrorTest, Values(EBADF, EINTR, EIO));
|
INSTANTIATE_TEST_CASE_P(FuseFlushErrorTest, FuseFlushErrorTest, Values(
|
||||||
|
EBADF,
|
||||||
|
#if defined(__GLIBC__) || defined(__APPLE__)
|
||||||
|
// musl has different handling for EINTR, see https://ewontfix.com/4/
|
||||||
|
EINTR,
|
||||||
|
#endif
|
||||||
|
EIO));
|
||||||
|
|
||||||
TEST_P(FuseFlushErrorTest, ReturnErrorFromFlush) {
|
TEST_P(FuseFlushErrorTest, ReturnErrorFromFlush) {
|
||||||
ReturnIsFileOnLstat(FILENAME);
|
ReturnIsFileOnLstat(FILENAME);
|
||||||
|
@ -29,9 +29,7 @@ void FuseThread::start(const bf::path &mountDir, const vector<string> &fuseOptio
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FuseThread::stop() {
|
void FuseThread::stop() {
|
||||||
if (0 != pthread_kill(_child.native_handle(), SIGINT)) {
|
_fuse->stop();
|
||||||
throw std::runtime_error("Error sending stop signal");
|
|
||||||
}
|
|
||||||
bool thread_stopped = _child.try_join_for(seconds(10));
|
bool thread_stopped = _child.try_join_for(seconds(10));
|
||||||
ASSERT(thread_stopped, "FuseThread could not be stopped");
|
ASSERT(thread_stopped, "FuseThread could not be stopped");
|
||||||
//Wait until it is properly shutdown (busy waiting is simple and doesn't hurt much here)
|
//Wait until it is properly shutdown (busy waiting is simple and doesn't hurt much here)
|
||||||
|
@ -6,7 +6,7 @@ set(SOURCES
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||||
target_link_libraries(${PROJECT_NAME} googletest gitversion)
|
target_link_libraries(${PROJECT_NAME} my-gtest-main googletest gitversion)
|
||||||
add_test(${PROJECT_NAME} ${PROJECT_NAME})
|
add_test(${PROJECT_NAME} ${PROJECT_NAME})
|
||||||
|
|
||||||
target_enable_style_warnings(${PROJECT_NAME})
|
target_enable_style_warnings(${PROJECT_NAME})
|
||||||
|
13
test/my-gtest-main/CMakeLists.txt
Normal file
13
test/my-gtest-main/CMakeLists.txt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
project (my-gtest-main)
|
||||||
|
|
||||||
|
set(SOURCES
|
||||||
|
my-gtest-main.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(${PROJECT_NAME} STATIC ${SOURCES})
|
||||||
|
target_link_libraries(${PROJECT_NAME} PUBLIC googletest cpp-utils)
|
||||||
|
target_add_boost(${PROJECT_NAME} filesystem system)
|
||||||
|
target_include_directories(${PROJECT_NAME} PUBLIC .)
|
||||||
|
|
||||||
|
target_enable_style_warnings(${PROJECT_NAME})
|
||||||
|
target_activate_cpp14(${PROJECT_NAME})
|
27
test/my-gtest-main/my-gtest-main.cpp
Normal file
27
test/my-gtest-main/my-gtest-main.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include "my-gtest-main.h"
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
#include <cpp-utils/assert/assert.h>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
boost::optional<boost::filesystem::path> executable;
|
||||||
|
}
|
||||||
|
|
||||||
|
const boost::filesystem::path& get_executable() {
|
||||||
|
ASSERT(executable != boost::none, "Executable path not set");
|
||||||
|
return *executable;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
executable = boost::filesystem::path(argv[0]);
|
||||||
|
|
||||||
|
// Since Google Mock depends on Google Test, InitGoogleMock() is
|
||||||
|
// also responsible for initializing Google Test. Therefore there's
|
||||||
|
// no need for calling testing::InitGoogleTest() separately.
|
||||||
|
testing::InitGoogleMock(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
5
test/my-gtest-main/my-gtest-main.h
Normal file
5
test/my-gtest-main/my-gtest-main.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
const boost::filesystem::path& get_executable();
|
@ -6,7 +6,7 @@ set(SOURCES
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||||
target_link_libraries(${PROJECT_NAME} googletest parallelaccessstore)
|
target_link_libraries(${PROJECT_NAME} my-gtest-main googletest parallelaccessstore)
|
||||||
add_test(${PROJECT_NAME} ${PROJECT_NAME})
|
add_test(${PROJECT_NAME} ${PROJECT_NAME})
|
||||||
|
|
||||||
target_enable_style_warnings(${PROJECT_NAME})
|
target_enable_style_warnings(${PROJECT_NAME})
|
||||||
|
1
vendor/googletest/CMakeLists.txt
vendored
1
vendor/googletest/CMakeLists.txt
vendored
@ -10,7 +10,6 @@ if (BUILD_TESTING)
|
|||||||
project (googletest)
|
project (googletest)
|
||||||
add_library(${PROJECT_NAME} dummy.cpp)
|
add_library(${PROJECT_NAME} dummy.cpp)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC gtest gmock)
|
target_link_libraries(${PROJECT_NAME} PUBLIC gtest gmock)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE gmock_main)
|
|
||||||
target_include_directories(${PROJECT_NAME} SYSTEM INTERFACE ${gtest_INCLUDE_DIRS}/include SYSTEM ${gmock_INCLUDE_DIRS}/include)
|
target_include_directories(${PROJECT_NAME} SYSTEM INTERFACE ${gtest_INCLUDE_DIRS}/include SYSTEM ${gmock_INCLUDE_DIRS}/include)
|
||||||
|
|
||||||
# Disable "missing override" warning because gmock MOCK_METHOD() don't use override :(
|
# Disable "missing override" warning because gmock MOCK_METHOD() don't use override :(
|
||||||
|
Loading…
Reference in New Issue
Block a user