Skip to content
Open

tests-c #2411

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1496,6 +1496,8 @@ if(UNICORN_FUZZ)
endif()

if(UNICORN_BUILD_TESTS)
include(cmake/Acutest.cmake)

enable_testing()
foreach(SAMPLE_FILE ${UNICORN_SAMPLE_FILE})
add_executable(${SAMPLE_FILE}
Expand All @@ -1506,7 +1508,7 @@ if(UNICORN_BUILD_TESTS)
)
endforeach()

foreach(TEST_FILE ${UNICORN_TEST_FILE})
foreach(TEST_FILE ${UNICORN_TEST_FILE})
add_executable(${TEST_FILE}
${CMAKE_CURRENT_SOURCE_DIR}/tests/unit/${TEST_FILE}.c
)
Expand All @@ -1516,16 +1518,40 @@ if(UNICORN_BUILD_TESTS)
target_link_libraries(${TEST_FILE} PRIVATE
${SAMPLES_LIB}
)
add_test(${TEST_FILE} ${TEST_FILE})
if(ANDROID_ABI)
file(APPEND ${CMAKE_BINARY_DIR}/adb.sh "adb push ${TEST_FILE} /data/local/tmp/build/\n")
file(APPEND ${CMAKE_BINARY_DIR}/adb.sh "adb shell \"chmod +x /data/local/tmp/build/${TEST_FILE}\"\n")
file(APPEND ${CMAKE_BINARY_DIR}/adb.sh "adb shell \'LD_LIBRARY_PATH=/data/local/tmp/build:$LD_LIBRARY_PATH /data/local/tmp/build/${TEST_FILE}\' || exit -1\n")
endif()
string(REGEX REPLACE "^test_" "" TEST_ARCHITECTURE "${TEST_FILE}")
set(TEST_ALLOW_EMPTY FALSE)
if(TEST_FILE STREQUAL "test_tricore")
set(TEST_ALLOW_EMPTY TRUE)
endif()
unicorn_discover_acutest(
${TEST_FILE}
900
"unit;${TEST_ARCHITECTURE}"
${TEST_ALLOW_EMPTY}
)
if (UNICORN_TARGET_ARCH STREQUAL "aarch64" OR UNICORN_TARGET_ARCH STREQUAL "ppc")
target_compile_definitions(${TEST_FILE} PRIVATE TARGET_READ_INLINED)
endif()
endforeach()
if(NOT ANDROID_ABI)
include(ProcessorCount)
ProcessorCount(UNICORN_CTEST_PARALLEL_LEVEL)
if(UNICORN_CTEST_PARALLEL_LEVEL EQUAL 0)
set(UNICORN_CTEST_PARALLEL_LEVEL 1)
endif()
add_custom_target(test_parallel
COMMAND ${CMAKE_CTEST_COMMAND}
--parallel ${UNICORN_CTEST_PARALLEL_LEVEL}
--output-on-failure
USES_TERMINAL
)
add_dependencies(test_parallel ${UNICORN_TEST_FILE})
endif()
endif()


Expand Down
81 changes: 81 additions & 0 deletions cmake/Acutest.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
set(UNICORN_ACUTEST_MODULE_DIR "${CMAKE_CURRENT_LIST_DIR}")

function(unicorn_discover_acutest target timeout labels allow_empty)
if(ANDROID_ABI)
file(APPEND ${CMAKE_BINARY_DIR}/adb.sh
"adb shell 'LD_LIBRARY_PATH=/data/local/tmp/build:$LD_LIBRARY_PATH /data/local/tmp/build/${target}' || exit -1\n")
return()
endif()

get_target_property(test_executor ${target} CROSSCOMPILING_EMULATOR)
if(test_executor MATCHES "-NOTFOUND$")
set(test_executor ${CMAKE_CROSSCOMPILING_EMULATOR})
endif()
if(CMAKE_CROSSCOMPILING AND NOT test_executor)
message(STATUS
"Skipping Acutest discovery for ${target}: "
"no cross-compiling emulator is configured")
return()
endif()

if(CMAKE_VERSION VERSION_LESS 3.10)
set(test_command ${test_executor} $<TARGET_FILE:${target}>)
add_test(NAME "unit.${target}" COMMAND ${test_command})
set_tests_properties("unit.${target}" PROPERTIES
LABELS "${labels}"
TIMEOUT ${timeout}
)
return()
endif()

set(include_file
"${CMAKE_CURRENT_BINARY_DIR}/${target}_include.cmake")
get_property(generator_is_multi_config GLOBAL PROPERTY
GENERATOR_IS_MULTI_CONFIG)
if(generator_is_multi_config)
set(tests_file
"${CMAKE_CURRENT_BINARY_DIR}/${target}_tests-$<CONFIG>.cmake")
set(byproducts_arg)
else()
set(tests_file
"${CMAKE_CURRENT_BINARY_DIR}/${target}_tests.cmake")
set(byproducts_arg BYPRODUCTS "${tests_file}")
endif()
set_property(TARGET ${target} APPEND PROPERTY LINK_DEPENDS
"${UNICORN_ACUTEST_MODULE_DIR}/AcutestAddTests.cmake")
add_custom_command(TARGET ${target} POST_BUILD
${byproducts_arg}
COMMAND ${CMAKE_COMMAND}
"-DTEST_TARGET=${target}"
"-DTEST_EXECUTABLE=$<TARGET_FILE:${target}>"
"-DTEST_EXECUTOR=${test_executor}"
"-DTEST_TIMEOUT=${timeout}"
"-DTEST_LABELS=${labels}"
"-DTEST_ALLOW_EMPTY=${allow_empty}"
"-DCTEST_FILE=${tests_file}"
-P ${UNICORN_ACUTEST_MODULE_DIR}/AcutestAddTests.cmake
VERBATIM
)
if(generator_is_multi_config)
file(WRITE "${include_file}"
"if(DEFINED CTEST_CONFIGURATION_TYPE AND NOT "
"CTEST_CONFIGURATION_TYPE STREQUAL \"\")\n"
" if(EXISTS \"${CMAKE_CURRENT_BINARY_DIR}/${target}_tests-"
"\${CTEST_CONFIGURATION_TYPE}.cmake\")\n"
" include(\"${CMAKE_CURRENT_BINARY_DIR}/${target}_tests-"
"\${CTEST_CONFIGURATION_TYPE}.cmake\")\n"
" else()\n"
" add_test(unit.${target}_NOT_BUILT unit.${target}_NOT_BUILT)\n"
" endif()\n"
"endif()\n"
)
else()
file(WRITE "${include_file}"
"if(EXISTS [==[${tests_file}]==])\n"
" include([==[${tests_file}]==])\n"
"endif()\n"
)
endif()
set_property(DIRECTORY APPEND PROPERTY TEST_INCLUDE_FILES
"${include_file}")
endfunction()
72 changes: 72 additions & 0 deletions cmake/AcutestAddTests.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
function(acutest_quote value output)
set(equals "=")
string(FIND "${value}" "]${equals}]" closing_bracket)
while(NOT closing_bracket EQUAL -1)
set(equals "${equals}=")
string(FIND "${value}" "]${equals}]" closing_bracket)
endwhile()
set(${output} "[${equals}[${value}]${equals}]" PARENT_SCOPE)
endfunction()

if(NOT EXISTS "${TEST_EXECUTABLE}")
message(FATAL_ERROR "Acutest executable does not exist: ${TEST_EXECUTABLE}")
endif()

execute_process(
COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" --list
TIMEOUT 30
OUTPUT_VARIABLE test_output
ERROR_VARIABLE test_error
RESULT_VARIABLE test_result
)
if(NOT test_result EQUAL 0)
message(FATAL_ERROR
"Acutest discovery failed for ${TEST_TARGET}: ${test_error}")
endif()

string(REPLACE "\r\n" "\n" test_output "${test_output}")
string(REPLACE "\r" "\n" test_output "${test_output}")
string(REPLACE ";" "\\;" test_output "${test_output}")
string(REPLACE "\n" ";" test_names "${test_output}")

set(discovered_names)
set(test_script "")
foreach(test_name ${test_names})
string(STRIP "${test_name}" test_name)
if(test_name STREQUAL "" OR test_name STREQUAL "Unit tests:")
continue()
endif()
list(FIND discovered_names "${test_name}" duplicate_index)
if(NOT duplicate_index EQUAL -1)
message(FATAL_ERROR
"Duplicate Acutest case ${test_name} in ${TEST_TARGET}")
endif()
list(APPEND discovered_names "${test_name}")

set(ctest_name "unit.${TEST_TARGET}.${test_name}")
acutest_quote("${ctest_name}" quoted_ctest_name)
acutest_quote("${TEST_EXECUTABLE}" quoted_executable)
acutest_quote("${test_name}" quoted_test_name)
acutest_quote("${TEST_LABELS}" quoted_labels)

set(quoted_executor "")
foreach(executor_argument ${TEST_EXECUTOR})
acutest_quote("${executor_argument}" quoted_argument)
set(quoted_executor "${quoted_executor} ${quoted_argument}")
endforeach()

set(test_script "${test_script}add_test(${quoted_ctest_name}${quoted_executor} ${quoted_executable} ${quoted_test_name})\n")
set(test_script "${test_script}set_tests_properties(${quoted_ctest_name} PROPERTIES LABELS ${quoted_labels} TIMEOUT ${TEST_TIMEOUT})\n")
endforeach()

if(NOT discovered_names)
if(NOT TEST_ALLOW_EMPTY)
message(FATAL_ERROR
"Acutest discovery found no cases in ${TEST_TARGET}")
endif()
message(STATUS "Acutest discovery found no cases in ${TEST_TARGET}")
endif()

set(temporary_file "${CTEST_FILE}.tmp")
file(WRITE "${temporary_file}" "${test_script}")
file(RENAME "${temporary_file}" "${CTEST_FILE}")
Loading