1set(libs
2    ${mbedtls_target}
3    ${CMAKE_THREAD_LIBS_INIT}
4)
5
6if(NOT MBEDTLS_PYTHON_EXECUTABLE)
7    message(FATAL_ERROR "Cannot build test suites without Python 3")
8endif()
9
10# generated .data files will go there
11file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/suites)
12
13# Get base names for generated files
14execute_process(
15    COMMAND
16        ${MBEDTLS_PYTHON_EXECUTABLE}
17        ${MBEDTLS_FRAMEWORK_DIR}/scripts/generate_config_tests.py
18        --list-for-cmake
19    WORKING_DIRECTORY
20        ${CMAKE_CURRENT_SOURCE_DIR}/..
21    OUTPUT_VARIABLE
22        base_config_generated_data_files)
23string(REGEX REPLACE "[^;]*/" ""
24       base_config_generated_data_files "${base_config_generated_data_files}")
25
26# Derive generated file paths in the build directory. The generated data
27# files go into the suites/ subdirectory.
28set(base_generated_data_files
29    ${base_config_generated_data_files})
30string(REGEX REPLACE "([^;]+)" "suites/\\1"
31       all_generated_data_files "${base_generated_data_files}")
32set(config_generated_data_files "")
33foreach(file ${base_config_generated_data_files})
34    list(APPEND config_generated_data_files ${CMAKE_CURRENT_BINARY_DIR}/suites/${file})
35endforeach()
36
37if(GEN_FILES)
38    add_custom_command(
39        OUTPUT
40            ${config_generated_data_files}
41        WORKING_DIRECTORY
42            ${CMAKE_CURRENT_SOURCE_DIR}/..
43        COMMAND
44            ${MBEDTLS_PYTHON_EXECUTABLE}
45            ${MBEDTLS_FRAMEWORK_DIR}/scripts/generate_config_tests.py
46            --directory ${CMAKE_CURRENT_BINARY_DIR}/suites
47        DEPENDS
48            ${MBEDTLS_FRAMEWORK_DIR}/scripts/generate_config_tests.py
49            # Do not declare the configuration files as dependencies: they
50            # change too often in ways that don't affect the result
51            # ((un)commenting some options).
52    )
53
54    add_custom_command(
55        OUTPUT
56            ${CMAKE_CURRENT_SOURCE_DIR}/opt-testcases/handshake-generated.sh
57        WORKING_DIRECTORY
58            ${CMAKE_CURRENT_SOURCE_DIR}/..
59        COMMAND
60            "${MBEDTLS_PYTHON_EXECUTABLE}"
61            "${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_tls_handshake_tests.py"
62        DEPENDS
63            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/tls_test_case.py
64            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_tls_handshake_tests.py
65    )
66    add_custom_target(handshake-generated.sh
67        DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/opt-testcases/handshake-generated.sh)
68    set_target_properties(handshake-generated.sh PROPERTIES EXCLUDE_FROM_ALL NO)
69    add_dependencies(${ssl_opt_target} handshake-generated.sh)
70
71    add_custom_command(
72        OUTPUT
73            ${CMAKE_CURRENT_SOURCE_DIR}/opt-testcases/tls13-compat.sh
74        WORKING_DIRECTORY
75            ${CMAKE_CURRENT_SOURCE_DIR}/..
76        COMMAND
77            "${MBEDTLS_PYTHON_EXECUTABLE}"
78            "${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_tls13_compat_tests.py"
79        DEPENDS
80            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_tls13_compat_tests.py
81    )
82    add_custom_target(tls13-compat.sh
83        DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/opt-testcases/tls13-compat.sh)
84    set_target_properties(tls13-compat.sh PROPERTIES EXCLUDE_FROM_ALL NO)
85    add_dependencies(${ssl_opt_target} tls13-compat.sh)
86
87else()
88    foreach(file ${all_generated_data_files})
89        link_to_source(${file})
90    endforeach()
91endif()
92# CMake generates sub-makefiles for each target and calls them in subprocesses.
93# Without this command, cmake will generate rules in each sub-makefile. As a result,
94# they can cause race conditions in parallel builds.
95# With this line, only 4 sub-makefiles include the above command, that reduces
96# the risk of a race.
97add_custom_target(test_suite_config_generated_data DEPENDS ${config_generated_data_files})
98# If SKIP_TEST_SUITES is not defined with -D, get it from the environment.
99if((NOT DEFINED SKIP_TEST_SUITES) AND (DEFINED ENV{SKIP_TEST_SUITES}))
100    set(SKIP_TEST_SUITES $ENV{SKIP_TEST_SUITES})
101endif()
102# Test suites caught by SKIP_TEST_SUITES are built but not executed.
103# "foo" as a skip pattern skips "test_suite_foo" and "test_suite_foo.bar"
104# but not "test_suite_foobar".
105string(REGEX REPLACE "[ ,;]" "|" SKIP_TEST_SUITES_REGEX "${SKIP_TEST_SUITES}")
106string(REPLACE "." "\\." SKIP_TEST_SUITES_REGEX "${SKIP_TEST_SUITES_REGEX}")
107set(SKIP_TEST_SUITES_REGEX "^(${SKIP_TEST_SUITES_REGEX})(\$|\\.)")
108
109function(add_test_suite suite_name)
110    if(ARGV1)
111        set(data_name ${ARGV1})
112    else()
113        set(data_name ${suite_name})
114    endif()
115
116    # Get the test names of the tests with generated .data files
117    # from the generated_data_files list in parent scope.
118    set(config_generated_data_names "")
119    foreach(generated_data_file ${config_generated_data_files})
120        # Get the plain filename
121        get_filename_component(generated_data_name ${generated_data_file} NAME)
122        # Remove the ".data" extension
123        get_name_without_last_ext(generated_data_name ${generated_data_name})
124        # Remove leading "test_suite_"
125        string(SUBSTRING ${generated_data_name} 11 -1 generated_data_name)
126        list(APPEND config_generated_data_names ${generated_data_name})
127    endforeach()
128
129    if(";${config_generated_data_names};" MATCHES ";${data_name};")
130        set(data_file
131            ${CMAKE_CURRENT_BINARY_DIR}/suites/test_suite_${data_name}.data)
132        set(dependency test_suite_config_generated_data)
133    else()
134        set(data_file
135            ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${data_name}.data)
136        set(dependency
137            test_suite_config_generated_data)
138    endif()
139
140    add_custom_command(
141        OUTPUT
142            # The output filename of generate_test_code.py is derived from the -d
143            # input argument.
144            test_suite_${data_name}.c
145        COMMAND
146            ${MBEDTLS_PYTHON_EXECUTABLE}
147            ${MBEDTLS_FRAMEWORK_DIR}/scripts/generate_test_code.py
148            -f ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${suite_name}.function
149            -d ${data_file}
150            -t ${CMAKE_CURRENT_SOURCE_DIR}/../tf-psa-crypto/tests/suites/main_test.function
151            -p ${CMAKE_CURRENT_SOURCE_DIR}/../tf-psa-crypto/tests/suites/host_test.function
152            -s ${CMAKE_CURRENT_SOURCE_DIR}/suites
153            --helpers-file ${CMAKE_CURRENT_SOURCE_DIR}/../tf-psa-crypto/tests/suites/helpers.function
154            -o .
155        DEPENDS
156            ${MBEDTLS_FRAMEWORK_DIR}/scripts/generate_test_code.py
157            ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${suite_name}.function
158            ${data_file}
159            ${CMAKE_CURRENT_SOURCE_DIR}/../tf-psa-crypto/tests/suites/main_test.function
160            ${CMAKE_CURRENT_SOURCE_DIR}/../tf-psa-crypto/tests/suites/host_test.function
161            ${CMAKE_CURRENT_SOURCE_DIR}/../tf-psa-crypto/tests/suites/helpers.function
162            ${mbedtls_target}
163        BYPRODUCTS
164            test_suite_${data_name}.datax
165    )
166
167    add_executable(test_suite_${data_name} test_suite_${data_name}.c
168                   $<TARGET_OBJECTS:mbedtls_test>
169                   $<TARGET_OBJECTS:mbedtls_test_helpers>)
170    set_base_compile_options(test_suite_${data_name})
171    target_compile_options(test_suite_${data_name} PRIVATE ${TEST_C_FLAGS})
172    add_dependencies(test_suite_${data_name} ${dependency})
173    target_link_libraries(test_suite_${data_name} ${libs})
174    # Include test-specific header files from ./include and private header
175    # files (used by some invasive tests) from ../library. Public header
176    # files are automatically included because the library targets declare
177    # them as PUBLIC.
178    target_include_directories(test_suite_${data_name}
179        PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/include
180        PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
181        PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../framework/tests/include
182        PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../library
183        PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../tf-psa-crypto/core
184        PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../tf-psa-crypto/drivers/builtin/src)
185    # Request C11, which is needed for memory poisoning tests
186    set_target_properties(test_suite_${data_name} PROPERTIES C_STANDARD 11)
187
188    if(${data_name} MATCHES ${SKIP_TEST_SUITES_REGEX})
189        message(STATUS "The test suite ${data_name} will not be executed.")
190    else()
191        add_test(${data_name}-suite test_suite_${data_name} --verbose)
192    endif()
193endfunction(add_test_suite)
194
195# Enable definition of various functions used throughout the testsuite
196# (gethostname, strdup, fileno...) even when compiling with -std=c99. Harmless
197# on non-POSIX platforms.
198add_definitions("-D_POSIX_C_SOURCE=200809L")
199
200if(CMAKE_COMPILER_IS_CLANG)
201    set(TEST_C_FLAGS -Wdocumentation -Wno-documentation-deprecated-sync -Wunreachable-code)
202endif(CMAKE_COMPILER_IS_CLANG)
203
204if(MSVC)
205    # If a warning level has been defined, suppress all warnings for test code
206    set(TEST_C_FLAGS /W0 /WX-)
207endif(MSVC)
208
209file(GLOB test_suites RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" suites/*.data)
210list(APPEND test_suites ${all_generated_data_files})
211# If the generated .data files are present in the source tree, we just added
212# them twice, both through GLOB and through ${all_generated_data_files}.
213list(REMOVE_DUPLICATES test_suites)
214list(SORT test_suites)
215foreach(test_suite ${test_suites})
216    get_filename_component(data_name ${test_suite} NAME)
217    string(REGEX REPLACE "\\.data\$" "" data_name "${data_name}")
218    string(REPLACE "test_suite_" "" data_name "${data_name}")
219    string(REGEX MATCH "[^.]*" function_name "${data_name}")
220    add_test_suite(${function_name} ${data_name})
221endforeach(test_suite)
222
223# Make scripts and data files needed for testing available in an
224# out-of-source build.
225if (NOT ${CMAKE_CURRENT_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
226    if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/seedfile")
227        link_to_source(seedfile)
228    endif()
229    link_to_source(Descriptions.txt)
230    link_to_source(compat.sh)
231    link_to_source(context-info.sh)
232    link_to_source(../framework/data_files)
233    link_to_source(scripts)
234    link_to_source(ssl-opt.sh)
235    link_to_source(opt-testcases)
236endif()
237