1# Copyright (c) 2021-2022 Huawei Device Co., Ltd. 2# Licensed under the Apache License, Version 2.0 (the "License"); 3# you may not use this file except in compliance with the License. 4# You may obtain a copy of the License at 5# 6# http://www.apache.org/licenses/LICENSE-2.0 7# 8# Unless required by applicable law or agreed to in writing, software 9# distributed under the License is distributed on an "AS IS" BASIS, 10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11# See the License for the specific language governing permissions and 12# limitations under the License. 13# Convenience functions for testing Panda. 14 15include(${CMAKE_CURRENT_LIST_DIR}/PandaCmakeFunctions.cmake) 16 17function(common_add_gtest) 18 if(NOT PANDA_WITH_TESTS) 19 return() 20 endif() 21 22 set(prefix ARG) 23 set(noValues CONTAINS_MAIN NO_CORES RAPIDCHECK_ON USE_CATCH2) 24 set(singleValues NAME OUTPUT_DIRECTORY TSAN_EXTRA_OPTIONS PANDA_STD_LIB ARK_BOOTCLASSPATH CUSTOM_PRERUN_ENVIRONMENT TEST_RUN_DIR) 25 set(multiValues SOURCES INCLUDE_DIRS LIBRARIES SANITIZERS DEPS_TARGETS) 26 set(TIMEOUT_SIGNAL USR1) 27 28 cmake_parse_arguments(${prefix} 29 "${noValues}" 30 "${singleValues}" 31 "${multiValues}" 32 ${ARGN}) 33 34 if (ARG_RAPIDCHECK_ON AND DEFINED DONT_USE_RAPIDCHECK) 35 return() 36 endif() 37 38 if (NOT DEFINED ARG_OUTPUT_DIRECTORY) 39 message(FATAL_ERROR "OUTPUT_DIRECTORY is not defined") 40 endif() 41 42 if (NOT ARG_CONTAINS_MAIN) 43 if(ARG_USE_CATCH2) 44 set(ARG_SOURCES ${ARG_SOURCES} ${PANDA_THIRD_PARTY_SOURCES_DIR}/rapidcheck/test/main.cpp) 45 elseif (NOT CMAKE_CROSSCOMPILING) 46 set(ARG_SOURCES ${ARG_SOURCES} ${PANDA_ROOT}/tests/gtest_launcher/main.cpp) 47 endif() 48 endif() 49 50 if (ARG_RAPIDCHECK_ON) 51 panda_add_executable(${ARG_NAME} RAPIDCHECK_ON ${ARG_SOURCES}) 52 set_target_properties(${ARG_NAME} PROPERTIES LINK_FLAGS "-frtti -fexceptions") 53 target_compile_definitions(${ARG_NAME} PRIVATE PANDA_RAPIDCHECK) 54 target_compile_options(${ARG_NAME} PRIVATE "-frtti" "-fexceptions" "-fPIC") 55 target_compile_definitions(${ARG_NAME} PUBLIC PANDA_RAPIDCHECK) 56 else() 57 panda_add_executable(${ARG_NAME} ${ARG_SOURCES}) 58 endif() 59 60 if (ARG_USE_CATCH2) 61 target_compile_definitions(${ARG_NAME} PUBLIC PANDA_CATCH2) 62 else() 63 target_compile_definitions(${ARG_NAME} PUBLIC PANDA_GTEST) 64 if (NOT ARG_CONTAINS_MAIN AND NOT CMAKE_CROSSCOMPILING) 65 find_program(GDB_PATH gdb REQUIRED) 66 target_compile_definitions(${ARG_NAME} PUBLIC -DTIMEOUT_SIGNAL=SIG${TIMEOUT_SIGNAL} -DGDB_PATH=${GDB_PATH}) 67 endif() 68 endif() 69 70 if(PANDA_CI_TESTING_MODE STREQUAL "Nightly") 71 target_compile_definitions(${ARG_NAME} PUBLIC PANDA_NIGHTLY_TEST_ON) 72 endif() 73 # By default tests are just built, running is available either via an 74 # umbrella target or via `ctest -R ...`. But one can always do something 75 # like this if really needed: 76 # add_custom_target(${ARG_NAME}_run 77 # COMMENT "Run ${ARG_NAME}" 78 # COMMAND ${CMAKE_CTEST_COMMAND} 79 # DEPENDS ${ARG_NAME}) 80 if (ARG_USE_CATCH2) 81 foreach(include_dir ${ARG_INCLUDE_DIRS} ${PANDA_THIRD_PARTY_SOURCES_DIR}/rapidcheck/ext/catch/single_include) 82 target_include_directories(${ARG_NAME} PUBLIC ${include_dir}) 83 endforeach() 84 else() 85 foreach(include_dir ${ARG_INCLUDE_DIRS} ${PANDA_THIRD_PARTY_SOURCES_DIR}/googletest/googlemock/include) 86 target_include_directories(${ARG_NAME} PUBLIC ${include_dir}) 87 endforeach() 88 endif() 89 90 if (NOT ARG_USE_CATCH2) 91 if (CONTAINS_MAIN OR NOT CMAKE_CROSSCOMPILING) 92 target_link_libraries(${ARG_NAME} gtest) 93 else() 94 target_link_libraries(${ARG_NAME} gtest_main) 95 endif() 96 endif() 97 98 if (NOT (PANDA_TARGET_MOBILE OR PANDA_TARGET_OHOS)) 99 target_link_libraries(${ARG_NAME} pthread) 100 endif() 101 target_link_libraries(${ARG_NAME} ${ARG_LIBRARIES}) 102 103 add_dependencies(gtests_build ${ARG_NAME} ${ARG_DEPS_TARGETS}) 104 105 if (ARG_RAPIDCHECK_ON) 106 target_link_libraries(${ARG_NAME} rapidcheck) 107 target_link_libraries(${ARG_NAME} rapidcheck_catch) 108 add_dependencies(${ARG_NAME} rapidcheck) 109 endif() 110 111 panda_add_sanitizers(TARGET ${ARG_NAME} SANITIZERS ${ARG_SANITIZERS}) 112 113 set(prlimit_prefix "") 114 if (ARG_NO_CORES) 115 set(prlimit_prefix prlimit --core=0) 116 endif() 117 set_target_properties(${ARG_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${ARG_OUTPUT_DIRECTORY}") 118 119 set(tsan_options "") 120 if ("thread" IN_LIST PANDA_SANITIZERS_LIST) 121 if (DEFINED ENV{TSAN_OPTIONS}) 122 set(tsan_options "TSAN_OPTIONS=$ENV{TSAN_OPTIONS},${ARG_TSAN_EXTRA_OPTIONS}") 123 endif() 124 endif() 125 126 # Yes, this is hardcoded. No, do not ask for an option. Go and fix your tests. 127 if (PANDA_CI_TESTING_MODE STREQUAL "Nightly") 128 set(timeout_prefix timeout --preserve-status --signal=${TIMEOUT_SIGNAL} --kill-after=30s 40m) 129 else () 130 set(timeout_prefix timeout --preserve-status --signal=${TIMEOUT_SIGNAL} --kill-after=30s 20m) 131 endif() 132 133 if (ARG_RAPIDCHECK_ON) 134 add_custom_target(${ARG_NAME}_rapidcheck_tests 135 COMMAND ${tsan_options} ${prlimit_prefix} ${timeout_prefix} 136 ${PANDA_RUN_PREFIX} "${ARG_OUTPUT_DIRECTORY}/${ARG_NAME}" 137 DEPENDS ${ARG_NAME} ${ARG_DEPS_TARGETS} 138 ) 139 add_dependencies(gtests ${ARG_NAME}_rapidcheck_tests) 140 else() 141 set(PANDA_STD_LIB "") 142 if (DEFINED ARG_PANDA_STD_LIB) 143 set(PANDA_STD_LIB "PANDA_STD_LIB=${ARG_PANDA_STD_LIB}") 144 endif() 145 146 set(ARK_BOOTCLASSPATH "") 147 if (DEFINED ARG_ARK_BOOTCLASSPATH) 148 set(ARK_BOOTCLASSPATH "ARK_BOOTCLASSPATH=${ARG_ARK_BOOTCLASSPATH}") 149 endif() 150 151 set(CUSTOM_PRERUN_ENVIRONMENT "") 152 if(DEFINED ARG_CUSTOM_PRERUN_ENVIRONMENT) 153 set(CUSTOM_PRERUN_ENVIRONMENT ${ARG_CUSTOM_PRERUN_ENVIRONMENT}) 154 endif() 155 156 set(TEST_RUN_DIR ${CMAKE_CURRENT_BINARY_DIR}) 157 if(DEFINED ARG_TEST_RUN_DIR) 158 set(TEST_RUN_DIR ${ARG_TEST_RUN_DIR}) 159 endif() 160 161 set(output_file "${ARG_OUTPUT_DIRECTORY}/${ARG_NAME}_gtest_output.txt") 162 add_custom_target(${ARG_NAME}_gtests 163 COMMAND ${PANDA_STD_LIB} ${ARK_BOOTCLASSPATH} ${CUSTOM_PRERUN_ENVIRONMENT} 164 ${tsan_options} ${prlimit_prefix} ${timeout_prefix} 165 ${PANDA_RUN_PREFIX} "${ARG_OUTPUT_DIRECTORY}/${ARG_NAME}" 166 --gtest_shuffle --gtest_death_test_style=threadsafe 167 --gtest_brief=0 168 >${output_file} 2>&1 169 || (cat ${output_file} && false) 170 DEPENDS ${ARG_NAME} ${ARG_DEPS_TARGETS} 171 WORKING_DIRECTORY ${TEST_RUN_DIR} 172 ) 173 add_dependencies(gtests ${ARG_NAME}_gtests) 174 endif() 175endfunction() 176