diff --git a/cmake/QtBaseGlobalTargets.cmake b/cmake/QtBaseGlobalTargets.cmake index facc800d18d..a81c6cbcfc8 100644 --- a/cmake/QtBaseGlobalTargets.cmake +++ b/cmake/QtBaseGlobalTargets.cmake @@ -400,4 +400,6 @@ qt_path_join(__qt_libexec_install_dir "${QT_INSTALL_DIR}" "${INSTALL_LIBEXECDIR} qt_copy_or_install(FILES coin/instructions/qmake/ensure_pro_file.cmake DESTINATION "${__qt_libexec_install_dir}") qt_copy_or_install(PROGRAMS "util/testrunner/qt-testrunner.py" - DESTINATION "${__qt_libexec_install_dir}") + DESTINATION "${__qt_libexec_install_dir}") +qt_copy_or_install(PROGRAMS "util/testrunner/sanitizer-testrunner.py" + DESTINATION "${__qt_libexec_install_dir}") diff --git a/coin/instructions/cmake_run_ctest_enforce_exit_code.yaml b/coin/instructions/cmake_run_ctest_enforce_exit_code.yaml index 913e00ddd96..e1e16bca890 100644 --- a/coin/instructions/cmake_run_ctest_enforce_exit_code.yaml +++ b/coin/instructions/cmake_run_ctest_enforce_exit_code.yaml @@ -29,6 +29,20 @@ instructions: condition: property property: host.os equals_value: Windows + - type: Group + enable_if: + condition: property + property: features + contains_value: UseAddressSanitizer + instructions: + - type: EnvironmentVariable + variableName: ASAN_OPTIONS + variableValue: "malloc_context_size=100" + - type: EnvironmentVariable + # Override qt-testrunner as we don't want to gather test statistics + # because many tests FAIL when built with ASAN. + variableName: TESTRUNNER + variableValue: "{{.InstallDir}}/libexec/sanitizer-testrunner.py" - type: EnvironmentVariable variableName: COIN_CTEST_RESULTSDIR variableValue: "{{.AgentWorkingDir}}\\testresults" diff --git a/coin/instructions/prepare_building_env.yaml b/coin/instructions/prepare_building_env.yaml index e1ff30ea70d..09b686ec0d1 100644 --- a/coin/instructions/prepare_building_env.yaml +++ b/coin/instructions/prepare_building_env.yaml @@ -407,6 +407,27 @@ instructions: property: features contains_value: WarningsAreErrors + - type: Group + enable_if: + condition: property + property: features + contains_value: UseAddressSanitizer + instructions: + - type: AppendToEnvironmentVariable + variableName: COMMON_CMAKE_ARGS + variableValue: " -DFEATURE_sanitize_address=ON" + disable_if: + condition: property + property: features + contains_value: UseConfigure + - type: AppendToEnvironmentVariable + variableName: CONFIGURE_ARGS + variableValue: " -sanitize address" + enable_if: + condition: property + property: features + contains_value: UseConfigure + - type: Group instructions: - type: AppendToEnvironmentVariable diff --git a/util/testrunner/sanitizer-testrunner.py b/util/testrunner/sanitizer-testrunner.py new file mode 100755 index 00000000000..d1f0310d16e --- /dev/null +++ b/util/testrunner/sanitizer-testrunner.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import os +import re +import sys +import logging as L +from subprocess import Popen, PIPE + + +# Thin testrunner that ignores failures in tests and only catches +# crashes or ASAN errors. +# +# It executes its arguments as a command line, and parses the stderr for the +# following regex: +detect_ASAN = re.compile(r"^==[0-9]+==ERROR: AddressSanitizer") + + +my_name = os.path.basename(sys.argv[0]) +logging_format = my_name + " %(levelname)8s: %(message)s" +L.basicConfig(format=logging_format, level=L.DEBUG) + +proc = None +if sys.argv[1] == "-f": # hidden option to parse pre-existing files + f = open(sys.argv[2], "r", errors="ignore") +else: + proc = Popen(sys.argv[1:], stderr=PIPE, universal_newlines=True, errors="ignore") + f = proc.stderr + +issues_detected = False +for line in f: + if proc: + # We don't want the stderr of the subprocess to disappear, so print it. + print(line, file=sys.stderr, end="") + if detect_ASAN.match(line): + issues_detected = True +f.close() +if proc: + proc.wait() + rc = proc.returncode + L.info("Test exit code was: %d", rc) + if not ( 0 <= rc <= 127 ): + L.error("Crash detected") + exit(1) + +if issues_detected: + L.error("ASAN issues detected") + exit(1)