| # |
| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| # |
| |
| # Configuration for code analysis tools. |
| # |
| # The RUNTIME_CHECK variable enables run-time checking when running |
| # the CTest test suite. The following tools are supported |
| # |
| # -DRUNTIME_CHECK=tsan # turns on thread sanitizer |
| # -DRUNTIME_CHECK=asan # address and undefined behavior sanitizer |
| # -DRUNTIME_CHECK=hwasan # hardware-supported asan for aarch64 |
| # -DRUNTIME_CHECK=memcheck # valgrind memcheck (in progress) |
| # -DRUNTIME_CHECK=helgrind # valgrind helgrind (in progress) |
| # |
| # This file updates the QDROUTERD_RUNNER and CMAKE_C_FLAGS |
| # appropriately for use when running the ctest suite. |
| |
| |
| # Valgrind configuration |
| # |
| find_program(VALGRIND_EXECUTABLE valgrind DOC "Location of the valgrind program") |
| set(VALGRIND_SUPPRESSIONS "${CMAKE_SOURCE_DIR}/tests/valgrind.supp" CACHE STRING "Suppressions file for valgrind") |
| set(VALGRIND_COMMON_ARGS "--error-exitcode=42 --xml=yes --xml-file=valgrind-%p.xml --quiet --suppressions=${VALGRIND_SUPPRESSIONS}") |
| mark_as_advanced(VALGRIND_EXECUTABLE VALGRIND_SUPPRESSIONS VALGRIND_COMMON_ARGS) |
| macro(assert_has_valgrind) |
| if(NOT VALGRIND_EXECUTABLE) |
| message(FATAL_ERROR "valgrind is not available") |
| endif() |
| endmacro() |
| |
| # Check for compiler's support of sanitizers. |
| # Currently have tested back to gcc 5.4.0 and clang 6.0.0, older |
| # versions may require more work |
| # |
| if((CMAKE_C_COMPILER_ID MATCHES "GNU" |
| AND (CMAKE_C_COMPILER_VERSION VERSION_GREATER 5.4 |
| OR CMAKE_C_COMPILER_VERSION VERSION_EQUAL 5.4)) |
| OR (CMAKE_C_COMPILER_ID MATCHES "Clang" |
| AND (CMAKE_C_COMPILER_VERSION VERSION_GREATER 6.0 |
| OR CMAKE_C_COMPILER_VERSION VERSION_EQUAL 6.0))) |
| set(HAS_SANITIZERS TRUE) |
| endif() |
| macro(assert_has_sanitizers) |
| if(NOT HAS_SANITIZERS) |
| message(FATAL_ERROR "compiler sanitizers are not available") |
| endif() |
| endmacro() |
| |
| # Valid options for RUNTIME_CHECK |
| # |
| set(runtime_checks OFF tsan asan hwasan memcheck helgrind) |
| |
| # Set RUNTIME_CHECK value and deal with the older cmake flags for |
| # valgrind and TSAN |
| # |
| set(RUNTIME_CHECK_DEFAULT OFF) |
| macro(deprecated_enable_check old new doc) |
| if (${old}) |
| message("WARNING: option ${old} is deprecated, use -DRUNTIME_CHECK=${new} instead") |
| set(RUNTIME_CHECK_DEFAULT ${new}) |
| endif() |
| unset(${old} CACHE) |
| endmacro() |
| option(VALGRIND_XML "Write valgrind output as XML (DEPRECATED)" OFF) |
| deprecated_enable_check(USE_VALGRIND memcheck "Use valgrind to detect run-time problems") |
| deprecated_enable_check(USE_TSAN tsan "Compile with thread sanitizer (tsan)") |
| |
| set(RUNTIME_CHECK ${RUNTIME_CHECK_DEFAULT} CACHE STRING "Enable runtime checks. Valid values: ${runtime_checks}") |
| if(CMAKE_BUILD_TYPE MATCHES "Coverage" AND RUNTIME_CHECK) |
| message(FATAL_ERROR "Cannot set RUNTIME_CHECK with CMAKE_BUILD_TYPE=Coverage") |
| endif() |
| |
| if(RUNTIME_CHECK STREQUAL "memcheck") |
| assert_has_valgrind() |
| message(STATUS "Runtime memory checker: valgrind memcheck") |
| set(QDROUTERD_RUNNER "${VALGRIND_EXECUTABLE} --tool=memcheck --leak-check=full --show-leak-kinds=definite --errors-for-leak-kinds=definite ${VALGRIND_COMMON_ARGS}") |
| |
| elseif(RUNTIME_CHECK STREQUAL "helgrind") |
| assert_has_valgrind() |
| message(STATUS "Runtime race checker: valgrind helgrind") |
| set(QDROUTERD_RUNNER "${VALGRIND_EXECUTABLE} --tool=helgrind ${VALGRIND_COMMON_ARGS}") |
| |
| elseif(RUNTIME_CHECK STREQUAL "asan" OR RUNTIME_CHECK STREQUAL "hwasan") |
| assert_has_sanitizers() |
| find_library(ASAN_LIBRARY NAME asan libasan) |
| if(ASAN_LIBRARY-NOTFOUND) |
| message(FATAL_ERROR "libasan not installed - address sanitizer not available") |
| endif(ASAN_LIBRARY-NOTFOUND) |
| find_library(UBSAN_LIBRARY NAME ubsan libubsan) |
| if(UBSAN_LIBRARY-NOTFOUND) |
| message(FATAL_ERROR "libubsan not installed - address sanitizer not available") |
| endif(UBSAN_LIBRARY-NOTFOUND) |
| if(RUNTIME_CHECK STREQUAL "asan") |
| set(ASAN_VARIANTS "address,undefined") |
| elseif(RUNTIME_CHECK STREQUAL "hwasan") |
| set(ASAN_VARIANTS "hwaddress,undefined") |
| # hwasan currently needs lld, otherwise binaries crash on invalid instruction |
| # https://github.com/google/sanitizers/issues/1241 |
| add_link_options("-fuse-ld=lld") |
| endif() |
| message(STATUS "Runtime memory checker: gcc/clang address sanitizers: ${ASAN_VARIANTS}") |
| option(SANITIZE_3RD_PARTY "Detect leaks in 3rd party libraries used by Dispatch while running tests" OFF) |
| if (SANITIZE_3RD_PARTY) |
| add_custom_command( |
| OUTPUT ${CMAKE_BINARY_DIR}/tests/lsan.supp |
| COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/tests/lsan.supp ${CMAKE_BINARY_DIR}/tests/lsan.supp |
| DEPENDS ${CMAKE_SOURCE_DIR}/tests/lsan.supp |
| VERBATIM) |
| else (SANITIZE_3RD_PARTY) |
| # Append wholesale library suppressions |
| # this is necessary if target system does not have debug symbols for these libraries installed |
| # and therefore the more specific suppressions do not match |
| add_custom_command( |
| OUTPUT ${CMAKE_BINARY_DIR}/tests/lsan.supp |
| COMMAND bash -c 'cat ${CMAKE_SOURCE_DIR}/tests/lsan.supp ${CMAKE_SOURCE_DIR}/tests/lsan_3rdparty.supp > ${CMAKE_BINARY_DIR}/tests/lsan.supp' |
| DEPENDS ${CMAKE_SOURCE_DIR}/tests/lsan.supp ${CMAKE_SOURCE_DIR}/tests/lsan_3rdparty.supp) |
| endif () |
| add_custom_target(generate_lsan.supp ALL |
| DEPENDS ${CMAKE_BINARY_DIR}/tests/lsan.supp) |
| # force QD_MEMORY_DEBUG else lsan will catch alloc_pool suppressed leaks (ok to remove this once leaks are fixed) |
| set(SANITIZE_FLAGS "-g -fno-omit-frame-pointer -fsanitize=${ASAN_VARIANTS} -DQD_MEMORY_DEBUG=1") |
| # `detect_leaks=1` is set by default where it is available; better not to set it conditionally ourselves |
| # https://github.com/openSUSE/systemd/blob/1270e56526cd5a3f485ae2aba975345c38860d37/docs/TESTING_WITH_SANITIZERS.md |
| # TODO(DISPATCH-2148) re-enable odr violation detection when Proton linking issue in test-sender is fixed |
| set(RUNTIME_ASAN_ENV_OPTIONS "detect_odr_violation=0 strict_string_checks=1 detect_stack_use_after_return=1 check_initialization_order=1 strict_init_order=1 detect_invalid_pointer_pairs=2 suppressions=${CMAKE_SOURCE_DIR}/tests/asan.supp") |
| set(RUNTIME_LSAN_ENV_OPTIONS "suppressions=${CMAKE_BINARY_DIR}/tests/lsan.supp") |
| set(RUNTIME_UBSAN_ENV_OPTIONS "print_stacktrace=1 print_summary=1") |
| |
| elseif(RUNTIME_CHECK STREQUAL "tsan") |
| assert_has_sanitizers() |
| find_library(TSAN_LIBRARY NAME tsan libtsan) |
| if(TSAN_LIBRARY-NOTFOUND) |
| message(FATAL_ERROR "libtsan not installed - thread sanitizer not available") |
| endif(TSAN_LIBRARY-NOTFOUND) |
| message(STATUS "Runtime race checker: gcc/clang thread sanitizer") |
| set(SANITIZE_FLAGS "-g -fno-omit-frame-pointer -fsanitize=thread") |
| set(RUNTIME_TSAN_ENV_OPTIONS "history_size=4 second_deadlock_stack=1 suppressions=${CMAKE_SOURCE_DIR}/tests/tsan.supp") |
| |
| elseif(RUNTIME_CHECK) |
| message(FATAL_ERROR "'RUNTIME_CHECK=${RUNTIME_CHECK}' is invalid, valid values: ${runtime_checks}") |
| endif() |