diff --git a/.arclint b/.arclint index 2fe97064d..5aa9156ae 100644 --- a/.arclint +++ b/.arclint @@ -1,254 +1,254 @@ { "linters": { "generated": { "type": "generated" }, "clang-format": { "type": "clang-format", "version": ">=8.0", "bin": ["clang-format-8", "clang-format"], "include": "(^src/.*\\.(h|c|cpp|mm)$)", "exclude": [ "(^src/(secp256k1|univalue|leveldb)/)" ] }, "autopep8": { "type": "autopep8", "version": ">=1.3.4", "include": "(\\.py$)", "exclude": [ "(^contrib/gitian-builder/)" ], "flags": [ "--aggressive", "--ignore=W503,W504" ] }, "flake8": { "type": "flake8", "version": ">=3.0", "include": "(\\.py$)", "exclude": [ "(^contrib/gitian-builder/)" ], "flags": [ "--ignore=E501,E704,W503,W504" ] }, "lint-format-strings": { "type": "lint-format-strings", "include": "(^src/.*\\.(h|c|cpp)$)", "exclude": [ "(^src/(secp256k1|univalue|leveldb)/)" ] }, "check-doc": { "type": "check-doc", "include": "(^src/.*\\.(h|c|cpp)$)" }, "lint-tests": { "type": "lint-tests", "include": "(^src/(seeder/|rpc/|wallet/)?test/.*\\.(cpp)$)" }, "lint-python-format": { "type": "lint-python-format", "include": "(\\.py$)", "exclude": [ "(^test/lint/lint-python-format\\.py$)", "(^contrib/gitian-builder/)" ] }, "phpcs": { "type": "phpcs", "include": "(\\.php$)", "exclude": [ "(^arcanist/__phutil_library_.+\\.php$)" ], "phpcs.standard": "arcanist/phpcs.xml" }, "lint-locale-dependence": { "type": "lint-locale-dependence", "include": "(^src/.*\\.(h|cpp)$)", "exclude": [ "(^src/(crypto/ctaes/|leveldb/|secp256k1/|tinyformat.h|univalue/))" ] }, "lint-cheader": { "type": "lint-cheader", "include": "(^src/.*\\.(h|cpp)$)", "exclude": [ "(^src/(crypto/ctaes|secp256k1|univalue|leveldb)/)" ] }, "spelling": { "type": "spelling", "exclude": [ "(^build-aux/m4/)", "(^depends/)", "(^doc/release-notes/)", "(^contrib/gitian-builder/)", "(^src/(qt/locale|secp256k1|univalue|leveldb)/)", "(^test/lint/dictionary/)" ], "spelling.dictionaries": [ "test/lint/dictionary/english.json" ] }, "lint-assert-with-side-effects": { "type": "lint-assert-with-side-effects", "include": "(^src/.*\\.(h|cpp)$)", "exclude": [ "(^src/(secp256k1|univalue|leveldb)/)" ] }, "lint-include-quotes": { "type": "lint-include-quotes", "include": "(^src/.*\\.(h|cpp)$)", "exclude": [ "(^src/(secp256k1|univalue|leveldb)/)" ] }, "lint-include-guard": { "type": "lint-include-guard", "include": "(^src/.*\\.h$)", "exclude": [ "(^src/(crypto/ctaes|secp256k1|univalue|leveldb)/)", "(^src/tinyformat.h$)" ] }, "lint-include-source": { "type": "lint-include-source", "include": "(^src/.*\\.(h|c|cpp)$)", "exclude": [ "(^src/(secp256k1|univalue|leveldb)/)" ] }, "lint-stdint": { "type": "lint-stdint", "include": "(^src/.*\\.(h|c|cpp)$)", "exclude": [ "(^src/(secp256k1|univalue|leveldb)/)", "(^src/compat/assumptions.h$)" ] }, "lint-source-filename": { "type": "lint-source-filename", "include": "(^src/.*\\.(h|c|cpp)$)", "exclude": [ "(^src/(secp256k1|univalue|leveldb)/)" ] }, "lint-boost-dependencies": { "type": "lint-boost-dependencies", "include": "(^src/.*\\.(h|cpp)$)" }, "check-rpc-mappings": { "type": "check-rpc-mappings", "include": "(^src/(rpc/|wallet/rpc).*\\.cpp$)" }, "lint-python-encoding": { "type": "lint-python-encoding", "include": "(\\.py$)", "exclude": [ "(^contrib/gitian-builder/)" ] }, "lint-python-shebang": { "type": "lint-python-shebang", "include": "(\\.py$)", "exclude": [ "(__init__\\.py$)", "(^contrib/gitian-builder/)" ] }, "lint-bash-shebang": { "type": "lint-bash-shebang", "include": "(\\.sh$)", "exclude": [ "(^contrib/gitian-builder/)" ] }, "shellcheck": { "type": "shellcheck", "version": ">=0.7.0", "flags": [ "--external-sources", "--source-path=SCRIPTDIR" ], "include": "(\\.sh$)", "exclude": [ "(^contrib/gitian-builder/)", "(^src/(secp256k1|univalue)/)" ] }, "lint-shell-locale": { "type": "lint-shell-locale", "include": "(\\.sh$)", "exclude": [ "(^contrib/gitian-builder/)", "(^src/(secp256k1|univalue)/)", - "(^cmake/utils/test_wrapper.sh)" + "(^cmake/utils/log-and-print-on-failure.sh)" ] }, "lint-cpp-void-parameters": { "type": "lint-cpp-void-parameters", "include": "(^src/.*\\.(h|cpp)$)", "exclude": [ "(^src/(crypto/ctaes|secp256k1|univalue|leveldb)/)", "(^src/compat/glibc_compat.cpp$)" ] }, "lint-logs": { "type": "lint-logs", "include": "(^src/.*\\.(h|cpp)$)" }, "lint-qt": { "type": "lint-qt", "include": "(^src/qt/.*\\.(h|cpp)$)", "exclude": [ "(^src/qt/(locale|forms|res)/)" ] }, "lint-doxygen": { "type": "lint-doxygen", "include": "(^src/.*\\.(h|c|cpp)$)", "exclude": [ "(^src/(crypto/ctaes|secp256k1|univalue|leveldb)/)" ] }, "lint-whitespace": { "type": "lint-whitespace", "include": "(\\.(ac|am|cmake|conf|in|include|json|m4|md|openrc|php|pl|sh|txt|yml)$)", "exclude": [ "(^contrib/gitian-builder/)", "(^src/(secp256k1|univalue|leveldb)/)" ] }, "lint-cppcheck": { "type": "lint-cppcheck", "include": "(^src/.*\\.(h|c|cpp)$)", "exclude": [ "(^src/(crypto/ctaes|secp256k1|univalue|leveldb)/)" ] }, "yamllint": { "type": "yamllint", "include": "(\\.(yml|yaml)$)" }, "lint-check-nonfatal": { "type": "lint-check-nonfatal", "include": [ "(^src/rpc/.*\\.(h|c|cpp)$)", "(^src/wallet/rpc*.*\\.(h|c|cpp)$)" ], "exclude": "(^src/rpc/server.cpp)" }, "lint-markdown": { "type": "lint-markdown", "include": [ "(\\.md$)" ], "exclude": "(^contrib/gitian-builder/)" } } } diff --git a/cmake/modules/TestSuite.cmake b/cmake/modules/TestSuite.cmake index 6dd8b0178..7d0038ac9 100644 --- a/cmake/modules/TestSuite.cmake +++ b/cmake/modules/TestSuite.cmake @@ -1,217 +1,217 @@ # Allow to easily build test suites option(ENABLE_JUNIT_REPORT "Enable Junit report generation for targets that support it" OFF) set(JUNIT_REPORT_DIRECTORY "${CMAKE_BINARY_DIR}/test/junit") set(TEST_LOG_DIRECTORY "${CMAKE_BINARY_DIR}/test/log") set_property( DIRECTORY "${CMAKE_SOURCE_DIR}" APPEND PROPERTY ADDITIONAL_CLEAN_FILES "${CMAKE_BINARY_DIR}/test/tmp" "${JUNIT_REPORT_DIRECTORY}" "${TEST_LOG_DIRECTORY}" ) macro(add_test_environment VARIABLE VALUE) set_property(GLOBAL APPEND PROPERTY TEST_ENVIRONMENT "${VARIABLE}=${VALUE}") endmacro() function(add_test_custom_target TARGET) cmake_parse_arguments(ARG "" "" "CUSTOM_TARGET_ARGS;TEST_COMMAND" ${ARGN}) get_property(TEST_ENVIRONMENT GLOBAL PROPERTY TEST_ENVIRONMENT) add_custom_target(${TARGET} ${ARG_CUSTOM_TARGET_ARGS} COMMAND ${CMAKE_COMMAND} -E make_directory "${JUNIT_REPORT_DIRECTORY}" COMMAND ${CMAKE_COMMAND} -E make_directory "${TEST_LOG_DIRECTORY}" COMMAND ${CMAKE_COMMAND} -E env ${TEST_ENVIRONMENT} ${ARG_TEST_COMMAND} ) endfunction() # Define a new target property to hold the list of tests associated with a test # suite. This property is named UNIT_TESTS to avoid confusion with the directory # level property TESTS. define_property(TARGET PROPERTY UNIT_TESTS BRIEF_DOCS "List of tests" FULL_DOCS "A list of the tests associated with a test suite" ) macro(get_target_from_suite SUITE TARGET) set(${TARGET} "check-${SUITE}") endmacro() macro(get_pool_from_suite SUITE POOL) set(${POOL} "${SUITE}-pool") endmacro() include(Coverage) function(create_test_suite_with_parent_targets NAME) get_target_from_suite(${NAME} TARGET) add_custom_target(${TARGET} COMMENT "Running ${NAME} test suite" COMMAND "${CMAKE_COMMAND}" -E echo "PASSED: ${NAME} test suite" ) foreach(PARENT_TARGET ${ARGN}) if(TARGET ${PARENT_TARGET}) add_dependencies(${PARENT_TARGET} ${TARGET}) endif() endforeach() add_custom_target_coverage(${TARGET}) endfunction() macro(create_test_suite NAME) create_test_suite_with_parent_targets(${NAME} check-all check-extended) endmacro() # After this call, all the tests added to the suite will also be added to the # pool. Works only with the Ninja generators. function(test_suite_create_pool SUITE JOBS) # Create a pool for the test suite get_pool_from_suite(${SUITE} POOL) set_property(GLOBAL APPEND PROPERTY JOB_POOLS ${POOL}=${JOBS}) endfunction() include(InstallationHelper) function(install_test SUITE NAME) # Allow for installing all tests ... if(NOT TARGET install-tests) add_custom_target(install-tests) endif() # ... a complete test suite ... if(NOT TARGET install-test-suite-${SUITE}) add_custom_target(install-test-suite-${SUITE}) endif() if(NOT TARGET install-${SUITE}-${NAME}) # ... or a single test install_target(${NAME} COMPONENT ${SUITE}-${NAME} EXCLUDE_FROM_ALL ) add_dependencies(install-test-suite-${SUITE} install-${SUITE}-${NAME}) add_dependencies(install-tests install-${SUITE}-${NAME}) endif() endfunction() set(TEST_RUNNER_TEMPLATE "${CMAKE_CURRENT_LIST_DIR}/../templates/TestRunner.cmake.in") function(add_test_runner SUITE NAME EXECUTABLE) cmake_parse_arguments(ARG "JUNIT" "" "" ${ARGN}) get_target_from_suite(${SUITE} SUITE_TARGET) set(TARGET "${SUITE_TARGET}-${NAME}") # If there is a pool associated to the test suite, then add the test to the # pool. get_property(JOB_POOLS GLOBAL PROPERTY JOB_POOLS) get_pool_from_suite(${SUITE} POOL) if(JOB_POOLS MATCHES ${POOL}) set(JOB_POOL_ARG JOB_POOL ${POOL}) endif() add_test_custom_target(${TARGET} TEST_COMMAND - "${CMAKE_SOURCE_DIR}/cmake/utils/test_wrapper.sh" + "${CMAKE_SOURCE_DIR}/cmake/utils/log-and-print-on-failure.sh" "${TEST_LOG_DIRECTORY}/${SUITE}-${NAME}.log" ${CMAKE_CROSSCOMPILING_EMULATOR} "$" ${ARG_UNPARSED_ARGUMENTS} CUSTOM_TARGET_ARGS COMMENT "${SUITE}: testing ${NAME}" DEPENDS ${EXECUTABLE} VERBATIM ${JOB_POOL_ARG} ) add_dependencies(${SUITE_TARGET} ${TARGET}) if(ENABLE_JUNIT_REPORT AND ARG_JUNIT) add_custom_command(TARGET ${TARGET} POST_BUILD COMMENT "Processing junit report for test ${NAME} from suite ${SUITE}" COMMAND_EXPAND_LISTS COMMAND "${Python_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/cmake/utils/junit-reports-merge.py" "${JUNIT_REPORT_DIRECTORY}" "${CMAKE_BINARY_DIR}/test/tmp" "${SUITE}" "${NAME}" ) endif() install_test(${SUITE} ${EXECUTABLE}) endfunction() function(add_test_to_suite SUITE NAME) add_executable(${NAME} EXCLUDE_FROM_ALL ${ARGN}) add_test_runner(${SUITE} ${NAME} ${NAME}) get_target_from_suite(${SUITE} TARGET) set_property( TARGET ${TARGET} APPEND PROPERTY UNIT_TESTS ${NAME} ) endfunction(add_test_to_suite) function(add_boost_unit_tests_to_suite SUITE NAME) cmake_parse_arguments(ARG "" "" "TESTS" ${ARGN} ) get_target_from_suite(${SUITE} SUITE_TARGET) add_executable(${NAME} EXCLUDE_FROM_ALL ${ARG_UNPARSED_ARGUMENTS}) add_dependencies("${SUITE_TARGET}" ${NAME}) set(HRF_LOGGER "HRF,test_suite") foreach(_test_source ${ARG_TESTS}) target_sources(${NAME} PRIVATE "${_test_source}") get_filename_component(_test_name "${_test_source}" NAME_WE) if(ENABLE_JUNIT_REPORT) set(JUNIT_REPORT_FILE "${SUITE}-${_test_name}.xml") set(JUNIT_LOGGER ":JUNIT,message,${JUNIT_REPORT_FILE}") set_property( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY ADDITIONAL_CLEAN_FILES "${JUNIT_REPORT_FILE}" ) endif() add_test_runner( ${SUITE} ${_test_name} ${NAME} JUNIT "--run_test=${_test_name}" "--logger=${HRF_LOGGER}${JUNIT_LOGGER}" ) set_property( TARGET ${SUITE_TARGET} APPEND PROPERTY UNIT_TESTS ${_test_name} ) endforeach() find_package(Boost 1.59 REQUIRED unit_test_framework) target_link_libraries(${NAME} Boost::unit_test_framework) # We need to detect if the BOOST_TEST_DYN_LINK flag is required include(CheckCXXSourceCompiles) set(CMAKE_REQUIRED_LIBRARIES Boost::unit_test_framework) check_cxx_source_compiles(" #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MAIN #include " BOOST_REQUIRES_TEST_DYN_LINK) if(BOOST_REQUIRES_TEST_DYN_LINK) target_compile_definitions(${NAME} PRIVATE BOOST_TEST_DYN_LINK) endif() endfunction(add_boost_unit_tests_to_suite) diff --git a/cmake/utils/test_wrapper.sh b/cmake/utils/log-and-print-on-failure.sh similarity index 80% rename from cmake/utils/test_wrapper.sh rename to cmake/utils/log-and-print-on-failure.sh index b89c8aa03..238f7d767 100755 --- a/cmake/utils/test_wrapper.sh +++ b/cmake/utils/log-and-print-on-failure.sh @@ -1,11 +1,11 @@ #!/bin/sh -# USAGE test_wrapper.sh executable log [args] +# USAGE log-and-print-on-failure.sh log executable [args] # Run the with supplied arguments. # The stdout and stderr outputs are redirected to the file, which is only # printed on error. LOG="$1" shift 1 "$@" > "${LOG}" 2>&1 || (cat "${LOG}" && exit 1)