option(ADMINIVE_ENABLE_ASAN "Enable AddressSanitizer for Adminive targets" OFF) option(ADMINIVE_ENABLE_UBSAN "Enable UndefinedBehaviorSanitizer for Adminive targets" OFF) option(ADMINIVE_ENABLE_TSAN "Enable ThreadSanitizer for Adminive targets" OFF) option(ADMINIVE_ENABLE_FRONTEND_TESTS "Register Adminive frontend unit and browser tests in CTest" OFF) if(ADMINIVE_ENABLE_ASAN AND ADMINIVE_ENABLE_TSAN) message(FATAL_ERROR "ASan and TSan cannot be enabled together") endif() if((ADMINIVE_ENABLE_ASAN OR ADMINIVE_ENABLE_UBSAN OR ADMINIVE_ENABLE_TSAN) AND NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU|MSVC") message(FATAL_ERROR "Requested sanitizer configuration is unsupported by ${CMAKE_CXX_COMPILER_ID}") endif() if(MSVC AND (ADMINIVE_ENABLE_UBSAN OR ADMINIVE_ENABLE_TSAN)) message(FATAL_ERROR "MSVC verification supports ASan only; UBSan and TSan require Clang or GNU") endif() get_filename_component(adminive_verification_root "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE) set(adminive_test_support_dir "${adminive_verification_root}/backend/test_support") function(adminive_configure_sanitizers target) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") if(ADMINIVE_ENABLE_ASAN) target_compile_options(${target} PRIVATE -fsanitize=address -fno-omit-frame-pointer) target_link_options(${target} PRIVATE -fsanitize=address) endif() if(ADMINIVE_ENABLE_UBSAN) target_compile_options(${target} PRIVATE -fsanitize=undefined -fno-omit-frame-pointer) target_link_options(${target} PRIVATE -fsanitize=undefined) endif() if(ADMINIVE_ENABLE_TSAN) target_compile_options(${target} PRIVATE -fsanitize=thread -fno-omit-frame-pointer) target_link_options(${target} PRIVATE -fsanitize=thread) endif() elseif(MSVC AND ADMINIVE_ENABLE_ASAN) target_compile_options(${target} PRIVATE /fsanitize=address) target_link_options(${target} PRIVATE /fsanitize=address) endif() endfunction() function(adminive_configure_test_target target) target_include_directories(${target} PRIVATE "${adminive_test_support_dir}") if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND (ADMINIVE_ENABLE_ASAN OR ADMINIVE_ENABLE_UBSAN OR ADMINIVE_ENABLE_TSAN)) target_compile_options(${target} PRIVATE -g1) endif() adminive_configure_sanitizers(${target}) endfunction() function(adminive_register_test target labels) add_test(NAME ${target} COMMAND ${target}) set_tests_properties(${target} PROPERTIES LABELS "${labels}") adminive_configure_test_target(${target}) endfunction() function(adminive_register_header_test target header link_target) set(source "${CMAKE_CURRENT_BINARY_DIR}/${target}.cpp") file(GENERATE OUTPUT "${source}" CONTENT "#include <${header}>\nint main() {\n return 0;\n}\n") add_executable(${target} "${source}") target_link_libraries(${target} PRIVATE ${link_target}) if(MSVC) target_compile_options(${target} PRIVATE /permissive-) endif() adminive_register_test(${target} "unit;header;compile") endfunction() function(adminive_register_frontend_tests binary_dir configuration) if(NOT ADMINIVE_ENABLE_FRONTEND_TESTS) return() endif() find_program(adminive_npm NAMES npm npm.cmd REQUIRED) find_package(Python3 COMPONENTS Interpreter REQUIRED) set(adminive_frontend_dir "${adminive_verification_root}/frontend") add_test(NAME Adminive_Frontend_Unit_Test COMMAND "${adminive_npm}" run test:unit) set_tests_properties(Adminive_Frontend_Unit_Test PROPERTIES WORKING_DIRECTORY "${adminive_frontend_dir}" LABELS "frontend;unit") add_test(NAME Adminive_Frontend_E2E_Test COMMAND "${Python3_EXECUTABLE}" "${adminive_verification_root}/scripts/verify.py" --e2e-only --binary-dir "${binary_dir}" --configuration "${configuration}") set_tests_properties(Adminive_Frontend_E2E_Test PROPERTIES LABELS "frontend;e2e;browser;chromium") if(WIN32) add_test(NAME Adminive_Frontend_Edge_E2E_Test COMMAND "${Python3_EXECUTABLE}" "${adminive_verification_root}/scripts/verify.py" --e2e-only --edge --binary-dir "${binary_dir}" --configuration "${configuration}") set_tests_properties(Adminive_Frontend_Edge_E2E_Test PROPERTIES LABELS "frontend;e2e;browser;edge") endif() endfunction()