blob: aaf0cdb35d58e501eb17bca85853ee1d5b58764a [file] [log] [blame]
Jianliang Shen5f7b1b72022-05-03 19:01:27 +08001#################################
2Adding TF-M Regression Test Suite
3#################################
4
5.. contents:: Table of Contents
6
7*************************************
8Introduction of TF-M regression tests
9*************************************
10
11TF-M regression tests test whether changes to TF-M code work as expected.
12A new regression test can consist of following 3 components:
13
141. ``test suite``: A series of tests of a certain function.
152. ``test case``: A specific test instance in test suites.
163. ``test service or partition``: Optional secure services or partitions to
17 support related test suites.
18
19Source structure
20================
21
22+---------------------------------------+---------------------------------------------------------------+
23| Folder name | Description |
24+=======================================+===============================================================+
25| test/bl1 | TF-M bl1 test suites source code. |
26+---------------------------------------+---------------------------------------------------------------+
27| test/bl2 | TF-M bL2 test suites source code. |
28+---------------------------------------+---------------------------------------------------------------+
29| test/config | The CMAKE test configurations files. |
30+---------------------------------------+---------------------------------------------------------------+
31| test/framework | Source code for test framework code, managing test suites. |
32+---------------------------------------+---------------------------------------------------------------+
33| test/secure_fw/suites | Test suites divided into subdirectories. |
34+---------------------------------------+---------------------------------------------------------------+
35| test/secure_fw/suites/<suite>/service | Test service divided into corresponding suite subdirectories. |
36+---------------------------------------+---------------------------------------------------------------+
37| test/secure_fw/common_test_services | Common test services. |
38+---------------------------------------+---------------------------------------------------------------+
39
40***********************
41Adding a new test suite
42***********************
43
44This section introduces how to add a new test suite and control its compilation
45with a test configuration in ``tf-m-tests`` repository.
46
47Source code
48===========
49
50The test suite example subdirectory named ``<test_name>`` is located under the
51path ``tf-m-tests/test/secure_fw/suites``. If the new test suite includes both
52non-secure and secure parts, the source code shall be divided shared code and
53specific code. An example test suite folder can be organized as the figure
54below.
55
56.. code-block:: bash
57
58 .
59 ├── CMakeLists.txt
60 ├── <test_name>_tests_common.c
61 ├── non_secure
62 ├── <test_name>_ns_interface_testsuite.c
63 └── <test_name>_ns_tests.h
64 └── secure
65 ├── <test_name>_s_interface_testsuite.c
66 └── <test_name>_s_tests.h
67
68Creating test configurations
69============================
70
71A test configuration controls whether one or multiple test suites are enabled.
72The doc `TF-M Build Instructionsn <https://tf-m-user-guide.trustedfirmware.org/technical_references/instructions/tfm_build_instruction.html>`_.
73shows some test configurations which are already supported in current TF-M.
74An example usage of test configuration shows below.
75
76.. code-block:: bash
77
78 cmake -S . -B cmake_build -DTFM_PLATFORM=arm/mps2/an521 \
79 -DTFM_TOOLCHAIN_FILE=toolchain_GNUARM.cmake \
80 -DCMAKE_BUILD_TYPE=Release \
81 -DTEST_NS_ATTESTATION=ON
82
83With this command, only non-secure initial attestation test suite will be built.
84
85Developers shall assign corresponding test configurations to control the test
86suites.
87
88Naming test configurations
89--------------------------
90
91The test configurations of example test suites are ``TEST_NS_<TEST_NAME>``
92in non-secure and ``TEST_S_<TEST_NAME>`` in secure.
93
94.. Note::
95 The test configurations must be named with the prefixes ``TEST_S_`` and
96 ``TEST_NS_``, for secure regression tests and non-secure regression tests
97 respectively. Otherwise, tf-m-tests build system may not recognize it.
98
99Setting test configurations
100---------------------------
101
102When the test configurations have dependences, the default value need to be set.
103The setting is performed in following four steps.
104
105#. Command line input: The configuration can be enabled or disabled by the
106 command ``-DTEST_NS_<TEST_NAME>=ON/OFF -DTEST_S_<TEST_NAME>=ON/OFF``, and
107 the value cannot be changed throughout the whole compilation of TF-M tests.
108
109#. ``tf-m-tests/config/set_config.cmake``: The test configurations shall be
110 OFF if its dependences are not supported. The dependences are probably
111 from:
112
113 #. TF-M partitions configurations like ``TFM_PARTITION_CRYPTO``,
114 ``TFM_PARTITION_INITIAL_ATTESTATION``, etc.
115 #. TF-M build mode configuration like ``TFM_LIB_MODEL``.
116 #. TF-M other configurations like ``TFM_PARTITION_FIRMWARE_UPDATE``,
117 ``FORWARD_PROT_MSG``, etc.
118
119#. ``tf-m-tests/config/default_ns_test_config.cmake`` or
120 ``tf-m-tests/config/default_s_test_config.cmake``: It is required to give
121 the default value of the new test configuration in these two files when
122 ``TEST_NS`` or ``TEST_S`` is ON. The recommended value is ON unless the
123 single test's code or data size is very large.
124
125#. ``tf-m-tests/config/default_test_config.cmake``: It is required to give the
126 default value of the new test configuration in the file when both
127 ``TEST_NS`` and ``TEST_S`` are OFF. The default value must be OFF.
128
129.. Note::
130 The test configurations must be set as CACHE value in CMAKE files. The CACHE
131 set cannot replace the value from command line, see
132 `Set Cache Entry <https://cmake.org/cmake/help/latest/command/set.html#set-cache-entry>`_.
133
134Checking test configurations
135----------------------------
136
137The new test configurations must be checked by function ``tfm_invalid_config()``
138if they have any dependence. The value comes from command line may be wrong when
139the dependences are conflicting. In addition to the dependences quoted in
140``tf-m-tests/config/set_config.cmake``, some other test configurations may be
141necessary.
142
143Applicating test configurations
144===============================
145
146The mission of test configurations is to control the build. They are applied
147in ``test/secure_fw/suites/<test_name>/CMakeLists.txt`` like the example below.
148
149.. code-block:: cmake
150
151 cmake_policy(SET CMP0079 NEW)
152
153 if (NOT TEST_NS_<TEST_NAME> AND NOT TEST_S_<TEST_NAME>)
154 return()
155 endif()
156
157 ####################### Non Secure #########################################
158
159 if (TEST_NS_<TEST_NAME>)
160 add_library(tfm_test_suite_<test_name>_ns STATIC EXCLUDE_FROM_ALL)
161 # target_sources()
162 # target_include_directories()
163 target_compile_definitions(tfm_test_suite_<test_name>_ns
164 INTERFACE
165 TEST_NS_<TEST_NAME>
166 )
167 # target_link_libraries()
168 endif()
169
170 ####################### Secure #############################################
171
172 if (TEST_S_<TEST_NAME>)
173 add_library(tfm_test_suite_<test_name>_s STATIC EXCLUDE_FROM_ALL)
174 # target_sources()
175 # target_include_directories()
176 target_compile_definitions(tfm_test_suite_<test_name>_s
177 INTERFACE
178 TEST_S_<TEST_NAME>
179 )
180 # target_link_libraries()
181 endif()
182
183The function ``target_compile_definitions`` will export the macros
184``TEST_NS_<TEST_NAME>`` or ``TEST_S_<TEST_NAME>`` into source code. and in the
185file ``tf-m-tests/framework/non_secure_suites.c`` or
186``tests/framework/secure_suites.c``, the definitions of these macros will be
187checked, and then the head file will be included and test cases will be
188registered if the macro is defined.
189
190.. code-block:: c
191
192 #ifdef TEST_NS_<TEST_NAME>
193 #include "<test_name>_ns_tests.h"
194 #endif
195
196 static struct test_suite_t test_suites[] = {
197 /* Non-secure example test cases */
198 // ......
199 #ifdef TEST_NS_<TEST_NAME>
200 {&register_testsuite_ns_<test_name>_interface, 0, 0, 0},
201 #endif
202 };
203
204.. code-block:: c
205
206 #ifdef TEST_S_<TEST_NAME>
207 #include "<test_name>_s_tests.h"
208 #endif
209
210 static struct test_suite_t test_suites[] = {
211 /* Secure example test cases */
212 // ......
213 #ifdef TEST_S_<TEST_NAME>
214 {&register_testsuite_s_<test_name>_interface, 0, 0, 0},
215 #endif
216 };
217
218.. Note::
219 On most platforms non-secure tests and secure tests run on the same CPU
220 core, but dual-core platform is an exception. So secure test library and
221 secure sevices shall be linked together in the file
222 ``tf-m-tests/test/secure_fw/secure_tests.cmake``. Thus they can be built on
223 secure CPU core and non-secure tests library and RTOS are built on
224 non-secure CPU core.
225
226.. code-block:: cmake
227
228 if (TEST_FRAMEWORK_S)
229 # ...
230 if (TEST_S_<TEST_NAME>)
231 add_library(tfm_test_suite_<test_name>_s STATIC EXCLUDE_FROM_ALL)
232 endif()
233 endif()
234
235************************************
236Adding a new test case in test suite
237************************************
238
239The test cases usually express as a function in source code. They will be added
240into an array with structure type called ``test_t`` defined in
241``tf-m-tests/test/framework/test_framework.h``.
242
243.. code-block:: c
244
245 struct test_t {
246 TEST_FUN * const test; /*!< Test function to call */
247 const char *name; /*!< Test name */
248 const char *desc; /*!< Test description */
249 };
250
251For example, a new test case called ``TFM_NS_<TEST_NAME>_TEST_1001`` is created
252and the function ``tfm_<test_name>_test_1001`` needs to be defined in file
253``<test_name>_ns_interface_testsuite.c``. Then the function shall be appended
254into the array which will be quoted in function
255``register_testsuite_ns_<test_name>_interface``. See the reference code below.
256
257.. code-block:: c
258
259 /* List of test cases */
260 static void tfm_<test_name>_test_1001(struct test_result_t *ret);
261
262 /* Append test cases */
263 static struct test_t <test_name>_tests[] = {
264 {&tfm_<test_name>_test_1001, "TFM_NS_<TEST_NAME>_TEST_1001",
265 "Example test case"},
266 };
267
268 /* Register test case into test suites */
269 void register_testsuite_ns_<test_name>_interface(struct test_suite_t *p_test_suite)
270 {
271 uint32_t list_size;
272
273 list_size = (sizeof(<test_name>_tests) / sizeof(<test_name>_tests[0]));
274
275 set_testsuite("<TEST_NAME> non-secure interface test (TFM_NS_<TEST_NAME>_TEST_1XXX)",
276 <test_name>_tests, list_size, p_test_suite);
277 }
278
279 static void tfm_<test_name>_test_1001(struct test_result_t *ret)
280 {
281 /* test case code */
282 }
283
284********************
285Adding test services
286********************
287
288Some test group may need specific test services. These test services may support
289one or more groups thus developers shall determine the proper test scope. Refer
290to
291`Adding partitions for regression tests <https://git.trustedfirmware.org/TF-M/tf-m-tests.git/tree/docs/tfm_test_services_addition.rst>`_
292to get more information.
293
294**********************************
295Out-of-tree regression test suites
296**********************************
297
298TF-M supports out-of-tree regression test suites build, whose source code
299folders are maintained outside tf-m-tests repo. There are two configurations
300for developers to include the source code.
301
302- ``EXTRA_NS_TEST_SUITES_PATHS``
303
304 A list of the absolute directories of the out-of-tree non-secure test suites
305 source code folder(s). TF-M build system searches ``CMakeLists.txt`` of
306 non-secure test suites in the source code folder(s).
307 Use semicolons ``;`` to separate multiple out-of-tree non-secure test suites
308 directorires.
309
310- ``EXTRA_S_TEST_SUITES_PATHS``
311
312 A list of the absolute directories of the out-of-tree secure test suites
313 source code folder(s).
314
315Example usage
316=============
317
318Take non-secure test as an example in
319`tf-m-extras <https://git.trustedfirmware.org/TF-M/tf-m-extras.git/>`_.
320A single out-of-tree test suite folder can be organized as the figure below:
321
322.. code-block:: bash
323
324 extra_ns
325 ├── CMakeLists.txt
326 ├── ns_test.c
327 ├── ns_test_config.cmake
328 └── ns_test.h
329
330In the example above, ``EXTRA_NS_TEST_SUITES_PATHS`` in the build command can be
331specified as listed below.
332
333.. code-block:: bash
334
335 -DEXTRA_NS_TEST_SUITES_PATHS=<Absolute-path-extra-test-folder>
336
337Coding instructions
338===================
339
340This is a demo of source code so the structure has been simplified. Files like
341``ns_test.c`` and ``ns_test.h`` can be expanded to ``src`` and ``include``
342folders. The ``CMakeLists.txt`` is required in the root path and
343``ns_test_config.cmake`` is optional.
344
345Header Files
346------------
347
348The header file ``extra_ns_tests.h`` must be included by out-of-tree source
349code. This file contains the definition of ``struct extra_tests_t``,
350``int32_t register_extra_tests()`` and declaration of
351``int32_t extra_ns_tests_init()``.
352
353Source code
354-----------
355
356To connect the out-of-tree source code and tf-m-tests framework, the high-level
357test function must be defined first. An example format is:
358
359.. code-block:: c
360
361 int32_t ns_test(void)
362 {
363 /* Add platform specific non-secure test suites code here. */
364
365 return EXTRA_TEST_SUCCESS;
366 }
367
368This function is the main entry to test framework. All the out-of-tree's test
369cases can be added into it. The returned error code of this function is
370specified as ``int32_t``. This function shall return an expected value which is
371same as the part ``expected_ret`` set in ``plat_ns_t`` below, take the macro
372EXTRA_TEST_SUCCESS as an example.
373
374After ``ns_test()`` is defined, a structure variable need to be created like:
375
376.. code-block:: c
377
378 const struct extra_tests_t plat_ns_t = {
379 .test_entry = ns_test,
380 .expected_ret = EXTRA_TEST_SUCCESS
381 };
382
383It will be used by function ``extra_ns_tests_init()`` to register the test by
384function ``register_extra_tests()``:
385
386.. code-block:: c
387
388 int32_t extra_ns_tests_init(struct extra_tests_t *internal_test_t)
389 {
390 /* Add platform init code here. */
391
392 return register_extra_tests(internal_test_t, &plat_ns_t);
393 }
394
395The platform initialization code can be added in this function because it runs
396before ``ns_test()``.
397
398.. Note::
399 Function ``extra_ns_tests_init()`` is declared in tf-m-tests repository
400 without definition. It is supplied to out-of-tree source code and need to be
401 defined with no change of its format, like returns error code and parameter
402 name.
403
404
405CMakeLists.txt
406--------------
407
408In addition to the implementation of CMAKE target like ``example_test_ns`` of
409out-of-tree source code, the configuration below needs to be appended:
410
411.. code-block:: cmake
412
413 # Example test must link tfm_test_suite_extra_common to use related interface
414 target_link_libraries(example_test_ns
415 PRIVATE
416 tfm_test_suite_extra_common
417 )
418
419 # The example_test_ns library must be linked by tfm_test_suite_extra_common
420 target_link_libraries(tfm_test_suite_extra_ns
421 PRIVATE
422 example_test_ns
423 )
424
425To use the interfaces come from tf-m-tests repository, library
426``tfm_test_suite_extra_common`` must be linked by ``example_test_ns``.
427To add out-of-tree test into TF-M, library ``example_test_ns`` must be linked
428by ``tfm_test_suite_extra_ns``.
429
430ns_test_config.cmake
431--------------------
432
433The CMAKE configuration file is optional. If out-of-tree source already exists
434another configuration file, a new one can be ignored.
435
436--------------
437
438*Copyright (c) 2021-2022, Arm Limited. All rights reserved.*