xref: /aosp_15_r20/trusty/kernel/include/shared/lk/trusty_unittest.h (revision 344aa361028b423587d4ef3fa52a23d194628137)
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 
24 #pragma once
25 
26 #include <inttypes.h>
27 #include <lk/compiler.h>
28 #include <lk/list.h>
29 #include <stdbool.h>
30 #include <string.h>
31 
32 __BEGIN_CDECLS
33 
34 /*
35  * This function returns a time in nanoseconds based on hardware counters
36  * it is expected to:
37  *  - Be non-wrapping or have very long (years) roll-over period
38  *  - Have a resolution below 100nsc
39  */
40 uint64_t get_current_time_ns(void);
41 
42 /*
43  * Test functions can be defined with:
44  * TEST(SuiteName, TestName) {
45  *   ... test body ...
46  * }
47  * or with:
48  * TEST_F(SuiteName, TestName) {
49  *   ... test body ...
50  * }
51  * or with:
52  * TEST_P(SuiteName, TestName) {
53  *   ... test body ...
54  * }
55  *
56  * NOTE: SuiteName and TestName should not contain underscores.
57  *
58  * Use EXPECT_<op> or ASSERT_<op> directly in test functions or from nested
59  * functions to check test conditions. Where <op> can be:
60  *   EQ for ==
61  *   NE for !=
62  *   LT for <
63  *   LE for <=
64  *   GT for >
65  *   GE for >=
66  *
67  * The test functions follows this pattern:
68  *   <EXPECT|ASSERT>_<op>(val1, val2 [, format, ...])
69  * If val1 <op> val2 is not true, then both values will be printed and a test
70  * failure will be recorded. For ASSERT_<op> it will also jump to a test_abort
71  * label in the calling function.
72  *
73  * Call RUN_ALL_TESTS() to run all tests defined by TEST (or
74  * RUN_ALL_SUITE_TESTS("SuiteName") to only run tests with the specified
75  * SuiteName). RUN_ALL_TESTS and RUN_ALL_SUITE_TESTS return true if all the
76  * tests passed.
77  *
78  * Test functions defined with TEST_F or TEST_P expect the type <SuiteName>_t
79  * and <SuiteName>_SetUp and <SuiteName>_TearDown functions to be defined.
80  * The <SuiteName>_SetUp function will be called once before each test in
81  * SuiteName in run and the <SuiteName>_TearDown function will be called once
82  * after each test in SuiteName is run. These functions can be defined with
83  * TEST_F_SETUP(<SuiteName>) {
84  *  ... setup body ...
85  * }
86  * and with:
87  * TEST_F_TEARDOWN(<SuiteName>) {
88  *  ... teardown body ...
89  * }
90  * A pointer to a <SuiteName>_t variable will be passed as "_state" to the
91  * setup, teardown and test functions.
92  *
93  * TEST_FIXTURE_ALIAS(NewSuiteName, OldSuiteName) can be used to use the test
94  * fixture defined for OldSuiteName with NewSuiteName.
95  *
96  * Tests defined with TEST_P will only run when their suite is run if they have
97  * been instantiated with parameters using INSTANTIATE_TEST_SUITE_P. These tests
98  * can access their parameter using GetParam()
99  */
100 
101 #ifndef trusty_unittest_printf
102 #error trusty_unittest_printf must be defined
103 #endif
104 
105 /**
106  * struct test_context - struct representing the state of a test run.
107  * @tests_total:      Number of conditions checked
108  * @tests_skipped:    Number of tests skipped
109  * @tests_disabled:   Number of disabled tests skipped
110  * @tests_failed:     Number of conditions failed
111  * @inst_name:        Name of the current parameter instantiation
112  * @suite_name:       Name of the current test suite
113  * @param_name:       Name of the current parameter
114  * @test_name:        Name of current test case
115  * @test_param:       The current test parameter
116  * @all_ok:           State of current test case
117  * @skipped:          Current test was skipped.
118  * @hard_fail:        Type of test failure (when @all_ok is false)
119  * @test_start_time:  Test Start Time in ns
120  * @suite_duration_ms:Test Suite duration in ms
121  */
122 struct test_context {
123     unsigned int tests_total;
124     unsigned int tests_skipped;
125     unsigned int tests_disabled;
126     unsigned int tests_failed;
127     const char* inst_name;
128     const char* suite_name;
129     const char* param_name;
130     const char* test_name;
131     const void* test_param;
132     bool all_ok;
133     bool skipped;
134     bool hard_fail;
135     uint64_t test_start_time;
136     uint64_t suite_duration_ms;
137 };
138 
139 /**
140  * struct test_list_node - node to hold test function in list of tests
141  * @node:           List node
142  * @suite:          Name of test suite (optionally used for filtering)
143  * @name:           Name of test (optionally used for filtering)
144  * @func:           Test function
145  * @needs_param:    Indicates if the test function is parameterized
146  */
147 
148 struct test_list_node {
149     struct list_node node;
150     const char* suite;
151     const char* name;
152     void (*func)(void);
153     bool needs_param;
154 };
155 
156 /**
157  * struct test_param_gen -  struct representing a parameter generator
158  * @gen_param:              Function to generate the parameter for a test
159  * @priv:                   Private data passed to gen_param
160  */
161 struct test_param_gen {
162     const void* (*gen_param)(void*, int);
163     void* priv;
164 };
165 
166 /**
167  * typedef test_param_to_string_t - Converts a test parameter to its string form
168  * @param:      Parameter to convert
169  * @buf:        Buffer to fill with a NULL terminated string representation of
170  *              @param
171  * @buf_size:   Size in bytes of @buf
172  *
173  * When called, this function is passed a pointer to the parameter for the test
174  * that is being executed in @param and must return a null-terminated string
175  * representing the passed in parameter in @buf of at most size @buf_size.
176  */
177 typedef void (*test_param_to_string_t)(const void* param,
178                                        char* buf,
179                                        size_t buf_size);
180 
181 /**
182  * struct test_param_list_node - holds parameter generators
183  * @node:               List node
184  * @param_gen:          Parameter generator
185  * @to_string:          Function to convert a parameter to its string form
186  * @inst_name:          Name of the instantiation associated with the generator
187  * @suite:              Name of test suite associated with the generator
188  */
189 
190 struct test_param_list_node {
191     struct list_node node;
192     struct test_param_gen param_gen;
193     test_param_to_string_t to_string;
194     const char* inst_name;
195     const char* suite;
196 };
197 
198 static struct test_context _test_context;
199 
200 /*
201  * List of tests. Tests are added by a __attribute__((constructor)) function
202  * per test defined by the TEST macro.
203  */
204 static struct list_node _test_list = LIST_INITIAL_VALUE(_test_list);
205 
206 /*
207  * List of parameter generators. Parameter generators  are added by a
208  * __attribute__((constructor)) function per instantiation defined with
209  * INSTANTIATE_TEST_SUITE_P.
210  */
211 static struct list_node _test_param_list = LIST_INITIAL_VALUE(_test_param_list);
212 
trusty_unittest_print_status_name_param_duration(const char * status,const char * param_gen_inst_name,const char * suite_name,const char * test_name,const char * param_name,const char * duration_ms)213 static inline void trusty_unittest_print_status_name_param_duration(
214         const char* status,
215         const char* param_gen_inst_name, /* parameter generator instance name */
216         const char* suite_name,
217         const char* test_name,
218         const char* param_name,
219         const char* duration_ms) {
220     if (param_gen_inst_name) {
221         trusty_unittest_printf("[ %s ] %s/%s.%s/%s%s\n", status,
222                                param_gen_inst_name, suite_name, test_name,
223                                param_name, duration_ms);
224     } else {
225         trusty_unittest_printf("[ %s ] %s.%s%s\n", status, suite_name,
226                                test_name, duration_ms);
227     }
228 }
229 
trusty_unittest_print_status_name(const char * suite_name,const char * test_name,const char * status)230 static inline void trusty_unittest_print_status_name(const char* suite_name,
231                                                      const char* test_name,
232                                                      const char* status) {
233     trusty_unittest_print_status_name_param_duration(
234             status, _test_context.inst_name, suite_name, test_name,
235             _test_context.param_name, "");
236 }
237 
trusty_unittest_print_status(const char * status)238 static inline void trusty_unittest_print_status(const char* status) {
239     trusty_unittest_print_status_name_param_duration(
240             status, _test_context.inst_name, _test_context.suite_name,
241             _test_context.test_name, _test_context.param_name, "");
242 }
243 
trusty_unittest_print_status_duration(const char * status,uint64_t test_duration_ms)244 static inline void trusty_unittest_print_status_duration(
245         const char* status,
246         uint64_t test_duration_ms) {
247     char duration_str[16] = "";
248 
249     /* print duration at end of test case */
250     snprintf(duration_str, sizeof(duration_str), " (%" PRIu64 " ms)",
251              test_duration_ms);
252     trusty_unittest_print_status_name_param_duration(
253             status, _test_context.inst_name, _test_context.suite_name,
254             _test_context.test_name, _test_context.param_name,
255             (const char*)duration_str);
256 }
257 
TEST_BEGIN_FUNC(const char * suite_name,const char * test_name)258 static inline void TEST_BEGIN_FUNC(const char* suite_name,
259                                    const char* test_name) {
260     _test_context.suite_name = suite_name;
261     _test_context.test_name = test_name;
262     _test_context.all_ok = true;
263     _test_context.hard_fail = false;
264     _test_context.skipped = false;
265     _test_context.tests_total++;
266     trusty_unittest_print_status("RUN     ");
267     /*
268      * initialize the test start time
269      * (after the print status is slightly better)
270      */
271     _test_context.test_start_time = get_current_time_ns();
272 }
273 
TEST_END_FUNC(void)274 static inline void TEST_END_FUNC(void) {
275     uint64_t test_duration_ms =
276             (get_current_time_ns() - _test_context.test_start_time) / 1000000;
277     _test_context.suite_duration_ms += test_duration_ms;
278     if (_test_context.skipped) {
279         trusty_unittest_print_status_duration(" SKIPPED", test_duration_ms);
280     } else if (_test_context.all_ok) {
281         trusty_unittest_print_status_duration("      OK", test_duration_ms);
282     } else {
283         trusty_unittest_print_status_duration(" FAILED ", test_duration_ms);
284     }
285     _test_context.test_name = NULL;
286 }
287 
288 #define STRINGIFY(x) #x
289 
290 #define TEST_FIXTURE_ALIAS(new_suite_name, old_suite_name)              \
291     typedef old_suite_name##_t new_suite_name##_t;                      \
292                                                                         \
293     static void new_suite_name##_SetUp(new_suite_name##_t* _state) {    \
294         old_suite_name##_SetUp(_state);                                 \
295     }                                                                   \
296     static void new_suite_name##_TearDown(new_suite_name##_t* _state) { \
297         old_suite_name##_TearDown(_state);                              \
298     }
299 
300 #define TEST_INTERNAL(suite_name, test_name, w_param, pre, post, arg, argp)  \
301     static void suite_name##_##test_name##_inner argp;                       \
302                                                                              \
303     static void suite_name##_##test_name(void) {                             \
304         TEST_BEGIN_FUNC(STRINGIFY(suite_name), STRINGIFY(test_name));        \
305         {                                                                    \
306             pre;                                                             \
307             if (!_test_context.hard_fail && !_test_context.skipped) {        \
308                 suite_name##_##test_name##_inner arg;                        \
309             }                                                                \
310             post;                                                            \
311         }                                                                    \
312         TEST_END_FUNC();                                                     \
313     }                                                                        \
314                                                                              \
315     static struct test_list_node suite_name##_##test_name##_node = {         \
316             .node = LIST_INITIAL_CLEARED_VALUE,                              \
317             .suite = #suite_name,                                            \
318             .name = #test_name,                                              \
319             .func = suite_name##_##test_name,                                \
320             .needs_param = w_param,                                          \
321     };                                                                       \
322                                                                              \
323     __attribute__((constructor)) void suite_name##_##test_name##_add(void) { \
324         list_add_tail(&_test_list, &suite_name##_##test_name##_node.node);   \
325     }                                                                        \
326                                                                              \
327     static void suite_name##_##test_name##_inner argp
328 
329 #define TEST_F_SETUP(suite_name) \
330     static void suite_name##_SetUp(suite_name##_t* _state)
331 
332 #define TEST_F_TEARDOWN(suite_name) \
333     static void suite_name##_TearDown(suite_name##_t* _state)
334 
335 #define TEST(suite_name, test_name) \
336     TEST_INTERNAL(suite_name, test_name, false, , , (), (void))
337 
338 #define TEST_F_CUSTOM_ARGS(suite_name, test_name, arg, argp)                  \
339     TEST_INTERNAL(suite_name, test_name, false, suite_name##_t state;         \
340                   suite_name##_SetUp(&state);, suite_name##_TearDown(&state); \
341                   , arg, argp)
342 
343 #define TEST_F(suite_name, test_name)                   \
344     TEST_F_CUSTOM_ARGS(suite_name, test_name, (&state), \
345                        (suite_name##_t * _state))
346 
347 #define TEST_P_CUSTOM_ARGS(suite_name, test_name, arg, argp)                  \
348     TEST_INTERNAL(suite_name, test_name, true, suite_name##_t state;          \
349                   suite_name##_SetUp(&state);, suite_name##_TearDown(&state); \
350                   , arg, argp)
351 
352 #define TEST_P(suite_name, test_name)                   \
353     TEST_P_CUSTOM_ARGS(suite_name, test_name, (&state), \
354                        (suite_name##_t * _state))
355 
356 struct test_array_param {
357     const void* arr;
358     int elem_size;
359     int count;
360 };
361 
test_gen_array_param(void * priv,int i)362 static inline const void* test_gen_array_param(void* priv, int i) {
363     struct test_array_param* param = (struct test_array_param*)priv;
364 
365     if (i >= param->count) {
366         return NULL;
367     }
368 
369     return (uint8_t*)param->arr + param->elem_size * i;
370 }
371 
372 struct test_range_param {
373     long begin;
374     long end;
375     long step;
376     long current;
377 };
378 
test_gen_range_param(void * priv,int i)379 static inline const void* test_gen_range_param(void* priv, int i) {
380     struct test_range_param* range_param = (struct test_range_param*)priv;
381 
382     range_param->current = range_param->begin + range_param->step * i;
383 
384     if (range_param->current >= range_param->end) {
385         return NULL;
386     }
387 
388     return &range_param->current;
389 }
390 
391 struct combined_params {
392     struct test_param_gen* generators;
393     int generator_count;
394     int* idxs;
395     const void** current;
396 };
397 
update_combined_params(struct combined_params * params,int j,bool reset)398 static inline void update_combined_params(struct combined_params* params,
399                                           int j,
400                                           bool reset) {
401     if (reset) {
402         params->idxs[j] = 0;
403     }
404 
405     params->current[j] = params->generators[j].gen_param(
406             params->generators[j].priv, params->idxs[j]);
407     params->idxs[j]++;
408 }
409 
test_gen_combined_param(void * priv,int i)410 static inline const void* test_gen_combined_param(void* priv, int i) {
411     struct combined_params* params = (struct combined_params*)priv;
412 
413     if (i == 0) {
414         for (int j = 0; j < params->generator_count; j++) {
415             update_combined_params(params, j, true);
416         }
417         return params->current;
418     }
419 
420     for (int j = 0; j < params->generator_count; j++) {
421         update_combined_params(params, j, false);
422 
423         if (params->current[j] != NULL) {
424             return params->current;
425         }
426 
427         update_combined_params(params, j, true);
428     }
429 
430     return NULL;
431 }
432 
433 #define FIRST_ARG(arg0, args...) arg0
434 #define SECOND_ARG(arg0, arg1, args...) arg1
435 /* Parentheses are used to prevent commas from being interpreted when they are
436  * passed in macro arguments. DELETE_PAREN is used to remove these parentheses
437  * inside the macro that uses the commas e.g.:
438  *
439  * MY_MACRO((1, 2, 3))
440  *
441  * #define MY_MACRO(arg)
442  *      DELETE_PAREN arg
443  */
444 #define DELETE_PAREN(args...) args
445 
446 #define testing_Range(_begin, end_step...)                  \
447     (static struct test_range_param range_param =           \
448              {                                              \
449                      .begin = _begin,                       \
450                      .end = FIRST_ARG(end_step, ),          \
451                      .step = SECOND_ARG(end_step, 1, ),     \
452              };                                             \
453      param_node.param_gen.gen_param = test_gen_range_param; \
454      param_node.param_gen.priv = &range_param;)
455 
456 #define testing_ValuesIn(array)                             \
457     (static struct test_array_param array_param =           \
458              {                                              \
459                      .arr = array,                          \
460                      .elem_size = sizeof(array[0]),         \
461                      .count = countof(array),               \
462              };                                             \
463                                                             \
464      param_node.param_gen.gen_param = test_gen_array_param; \
465      param_node.param_gen.priv = &array_param;)
466 
467 /*
468  * (args, args) is passed to __typeof__ to guarantee that it resolves to const
469  * char* instead of const char[] in cases where args contains a single string.
470  * When args is a single string, it is inlined and typeof will resolve to const
471  * char[].
472  */
473 #define testing_Values(args...)                        \
474     (static __typeof__(args, args) new_arr[] = {args}; \
475      DELETE_PAREN testing_ValuesIn(new_arr))
476 
477 #define testing_Bool() testing_Values(false, true)
478 
479 #define test_set_combine_params(generator, i, count)                  \
480     {                                                                 \
481         DELETE_PAREN generator;                                       \
482         if (i < count) {                                              \
483             param_gens[i].gen_param = param_node.param_gen.gen_param; \
484             param_gens[i].priv = param_node.param_gen.priv;           \
485         }                                                             \
486     }
487 
488 #define testing_Combine_internal(arg0, arg1, arg2, arg3, arg4, arg5, arg6,   \
489                                  arg7, arg8, arg9, da0, da1, da2, da3, da4,  \
490                                  da5, da6, da7, da8, da9, count, args...)    \
491     (static struct test_param_gen param_gens[count]; static int idxs[count]; \
492      static const void* current_params[count];                               \
493      static struct combined_params combined_params =                         \
494              {                                                               \
495                      param_gens,                                             \
496                      count,                                                  \
497                      idxs,                                                   \
498                      current_params,                                         \
499              };                                                              \
500                                                                              \
501      test_set_combine_params(arg0, 0, count);                                \
502      test_set_combine_params(arg1, 1, count);                                \
503      test_set_combine_params(arg2, 2, count);                                \
504      test_set_combine_params(arg3, 3, count);                                \
505      test_set_combine_params(arg4, 4, count);                                \
506      test_set_combine_params(arg5, 5, count);                                \
507      test_set_combine_params(arg6, 6, count);                                \
508      test_set_combine_params(arg7, 7, count);                                \
509      test_set_combine_params(arg8, 8, count);                                \
510      test_set_combine_params(arg9, 9, count);                                \
511      param_node.param_gen.gen_param = test_gen_combined_param;               \
512      param_node.param_gen.priv = &combined_params;)
513 
514 #define testing_Combine(generators...)                                       \
515     testing_Combine_internal(generators, (), (), (), (), (), (), (), (), (), \
516                              (), 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
517 
518 #define INSTANTIATE_TEST_SUITE_P_INTERNAL(_inst_name, suite_name, param_gen, \
519                                           param_to_string, args...)          \
520                                                                              \
521     __attribute__((constructor)) void suite_name##_##_inst_name##param_add(  \
522             void) {                                                          \
523         static struct test_param_list_node param_node = {                    \
524                 .node = LIST_INITIAL_CLEARED_VALUE,                          \
525                 .to_string = param_to_string,                                \
526                 .inst_name = STRINGIFY(_inst_name),                          \
527                 .suite = #suite_name,                                        \
528         };                                                                   \
529                                                                              \
530         DELETE_PAREN param_gen;                                              \
531                                                                              \
532         list_add_tail(&_test_param_list, &param_node.node);                  \
533     }
534 
has_disabled_prefix(const char * str)535 static inline bool has_disabled_prefix(const char* str) {
536     const char disabled_prefix[] = "DISABLED_";
537     return strncmp(str, disabled_prefix, strlen(disabled_prefix)) == 0;
538 }
539 
trusty_unittest_test_is_disabled(struct test_list_node * entry)540 static inline bool trusty_unittest_test_is_disabled(
541         struct test_list_node* entry) {
542     return has_disabled_prefix(entry->suite) ||
543            has_disabled_prefix(entry->name);
544 }
545 
546 /**
547  * trusty_unittest_count_param_entries - Count parameter entries for a given
548  * test suite.
549  *
550  * @suite: Name of test suite associated with the parameters
551  *         suite is never going to be NULL (see invocation),
552  *         no need to guard against this case.
553  *
554  * For each parameter generator associated with the suite, accrue
555  * the number of parameter entries.
556  *
557  * Not meant for external use.
558  *
559  * Return: count of parameter entries
560  */
trusty_unittest_count_param_entries(struct test_list_node * test_case)561 static int trusty_unittest_count_param_entries(
562         struct test_list_node* test_case) {
563     int param_count = 0;
564     int i;
565     struct test_param_list_node* param_entry;
566     bool has_param_gen = 0;
567     bool invalid_run = false;
568     /*
569      * for each parameter generator associated with the suite,
570      * accrue the number of parameter entries
571      */
572     list_for_every_entry(&_test_param_list, param_entry,
573                          struct test_param_list_node, node) {
574         if (!strcmp(test_case->suite, param_entry->suite)) {
575             i = 0;
576             has_param_gen = true;
577             /* For each parameter from the generator */
578             while (param_entry->param_gen.gen_param(param_entry->param_gen.priv,
579                                                     i)) {
580                 i++;
581             }
582             if (!i) {
583                 /*
584                  * No parameter entries: parameterized test case exist
585                  * but the test generator is empty
586                  */
587                 trusty_unittest_print_status_name_param_duration(
588                         " FAILED ", param_entry->inst_name, test_case->suite,
589                         test_case->name,
590                         "NO PARAMS: Parameterized Test Case Generator without Params!",
591                         "");
592                 invalid_run = true;
593             }
594             param_count += i;
595         }
596     }
597     /*
598      * No parameter generator: parameterized test case exist
599      * but the test suite is not associated with any param generator
600      */
601     if (!has_param_gen) {
602         trusty_unittest_print_status_name_param_duration(
603                 " FAILED ", "NO PARAM GENERATOR", test_case->suite,
604                 test_case->name,
605                 "NO PARAMS: Parameterized Test Case without Param Generator!",
606                 "");
607     }
608     return invalid_run ? 0 : param_count;
609 }
610 
611 /**
612  * trusty_unittest_has_parameterized_test_case - test suite with parameterized
613  * test cases
614  *
615  * @suite: Name of test suite associated with the parameters.
616  *         suite is never going to be NULL (see invocation),
617  *         no need to guard against this case.
618  *
619  * Check whether a test suite has parameterized test cases.
620  * Not meant for external use.
621  *
622  * Return: True if parameterized test
623  */
trusty_unittest_has_parameterized_test_case(const char * suite)624 static bool trusty_unittest_has_parameterized_test_case(const char* suite) {
625     struct test_list_node* test_case;
626     list_for_every_entry(&_test_list, test_case, struct test_list_node, node) {
627         if (!strcmp(suite, test_case->suite)) {
628             if (test_case->needs_param) {
629                 return true;
630             }
631         }
632     }
633     return false;
634 }
635 
636 /**
637  * trusty_unittest_count_test_cases - Count test cases associated with test
638  * suite.
639  *
640  * @suite: Name of test suite.
641  *         When suite is NULL, all test cases from all test suites are counted.
642  *
643  * This test case count shall comply to the GTest parser requirements
644  * and thus shall not include disabled test cases.
645  * Not meant for external use.
646  *
647  * Return: count of test cases, -1 in case of detected test suite coding error
648  */
trusty_unittest_count_test_cases(const char * suite)649 static int trusty_unittest_count_test_cases(const char* suite) {
650     struct test_list_node* test_case;
651     struct test_param_list_node* param_entry;
652     bool test_code_error = false;
653     size_t test_case_count = 0;
654     bool disabled;
655     int param_entries = 0;
656     const char* param_entries_suite = NULL;
657     int current_test_case_count;
658     /* count all non parameterized and parameterized test cases */
659     list_for_every_entry(&_test_list, test_case, struct test_list_node, node) {
660         /* exclude tests not part of the requested suite */
661         if (suite && strcmp(suite, test_case->suite)) {
662             continue;
663         }
664         /* only count non-disabled test case as required by the GTest parser */
665         disabled = trusty_unittest_test_is_disabled(test_case);
666         if (test_case->needs_param) {
667             if (!param_entries_suite || !param_entries ||
668                 strcmp(param_entries_suite, test_case->suite)) {
669                 /* count param_entries for test_case->suite */
670                 param_entries = trusty_unittest_count_param_entries(test_case);
671                 param_entries_suite = test_case->suite;
672             }
673             if (!param_entries) {
674                 /*
675                  * Test code error shall be fixed and will prevent test
676                  * execution however we don't bail right away with the goal of
677                  * logging all erroneous test cases.
678                  */
679                 test_code_error = true;
680                 continue;
681             }
682             current_test_case_count = param_entries;
683         } else {
684             current_test_case_count = 1;
685         }
686         if (!disabled) {
687             /* non parameterized (singular) test case */
688             test_case_count += current_test_case_count;
689         }
690     }
691     /*
692      * Search for a test coding issue where a test generator exists
693      * but is not backed by existing test case
694      */
695     list_for_every_entry(&_test_param_list, param_entry,
696                          struct test_param_list_node, node) {
697         if (!trusty_unittest_has_parameterized_test_case(param_entry->suite)) {
698             test_code_error = true;
699             trusty_unittest_print_status_name_param_duration(
700                     " FAILED ", param_entry->inst_name, param_entry->suite,
701                     "NO_TESTS", "Parameter Generator without tests!", "");
702         }
703     }
704     return test_code_error ? -1 : test_case_count;
705 }
706 
707 /**
708  * trusty_unittest_run_test_suite - run each test case associated with test
709  * suite.
710  *
711  * @suite:      Name of test suite
712  *              when suite is NULL, all test cases
713  *              from all test suites are executed.
714  * @needs_param: when true run the parameterised test cases,
715  *               otherwise run the non-parameterised test cases
716  *
717  * Not meant for external use.
718  *
719  * Return: count of executed test cases
720  */
trusty_unittest_run_test_suite(const char * suite,bool needs_param)721 static int trusty_unittest_run_test_suite(const char* suite, bool needs_param) {
722     struct test_list_node* entry;
723     int test_case_count = 0;
724 
725     list_for_every_entry(&_test_list, entry, struct test_list_node, node) {
726         if ((!suite || !strcmp(suite, entry->suite)) &&
727             (entry->needs_param == needs_param)) {
728             if (trusty_unittest_test_is_disabled(entry)) {
729                 trusty_unittest_print_status_name(entry->suite, entry->name,
730                                                   "DISABLED");
731                 _test_context.tests_disabled++;
732             } else {
733                 test_case_count++;
734                 entry->func();
735             }
736         }
737     }
738     return test_case_count;
739 }
740 
741 /*
742  * The testing framework uses 3 global variables to keep track of tests and
743  * related data:
744  *
745  * _test_context: contains information about the overall execution of the
746  * framework (e.g. total tests run) and information about the currently
747  * executing test (e.g. test name, suite name).
748  *
749  * _test_list: contains a list of tests that can be run. Each test belongs to a
750  * test suite and may require parameters to be run.
751  *
752  * _test_param_list: contains a list of parameter generators for tests that
753  * require parameters. Each generator is associated with a specific test suite.
754  * Parameter generators are functions that return parameters that apply to all
755  * the tests that require parameters (i.e. parameterized tests) in a given test
756  * suite.
757  *
758  * Tests are only run as part of test suites. When a test suite is run all of
759  * the non-paremeterized tests belonging to that suite are run first followed by
760  * the parameterized tests in the suite. All of the parameterized tests in a
761  * suite are run once for each value returned by a parameter generator
762  * associated with that suite.
763  */
RUN_ALL_SUITE_TESTS(const char * suite)764 static inline bool RUN_ALL_SUITE_TESTS(const char* suite) {
765     struct test_param_list_node* param_entry;
766     const void* test_param;
767     int i;
768     char param_str[64];
769     int actual_test_count = 0;
770     int expected_test_count = trusty_unittest_count_test_cases(suite);
771     if (expected_test_count == -1) {
772         trusty_unittest_printf("Test Coding Error - aborting execution.\n");
773         return false;
774     }
775 
776     trusty_unittest_printf(
777             "[==========] Running %d tests from %s test suite%s.\n",
778             expected_test_count, suite ? suite : "all", suite ? "" : "s");
779 
780     _test_context.tests_total = 0;
781     _test_context.tests_disabled = 0;
782     _test_context.tests_failed = 0;
783     _test_context.test_param = NULL;
784     _test_context.inst_name = NULL;
785     _test_context.param_name = param_str;
786     _test_context.suite_duration_ms = 0;
787     /* Run all the non-parameterized tests in the suite */
788     actual_test_count = trusty_unittest_run_test_suite(suite, false);
789 
790     /* For each parameter generator associated with the suite */
791     list_for_every_entry(&_test_param_list, param_entry,
792                          struct test_param_list_node, node) {
793         if (!suite || !strcmp(suite, param_entry->suite)) {
794             i = 0;
795             /* For each parameter from the generator */
796             while ((test_param = param_entry->param_gen.gen_param(
797                             param_entry->param_gen.priv, i))) {
798                 /* Set the parameter for the next run */
799                 _test_context.inst_name = param_entry->inst_name;
800                 _test_context.test_param = test_param;
801                 if (param_entry->to_string) {
802                     param_entry->to_string(test_param, param_str,
803                                            sizeof(param_str));
804                 } else {
805                     snprintf(param_str, sizeof(param_str), "%d", i);
806                 }
807                 /* Run all the parameterized tests in the suite */
808                 actual_test_count += trusty_unittest_run_test_suite(
809                         param_entry->suite, true);
810                 i++;
811             }
812         }
813     }
814     if (actual_test_count != expected_test_count) {
815         trusty_unittest_printf("[ RUN      ] %s.test_count_match_check\n",
816                                suite ? suite : "all_suites");
817         trusty_unittest_printf(
818                 "[----------] %d tests ran, but expected %d tests.\n",
819                 actual_test_count, expected_test_count);
820         trusty_unittest_print_status_name(suite ? suite : "all_suites",
821                                           "test_count_match_check", " FAILED ");
822         ++_test_context.tests_failed;
823         ++_test_context.tests_total;
824     } else if (actual_test_count == 0 && _test_context.tests_disabled == 0) {
825         trusty_unittest_printf("[ RUN      ] %s.test_count_empty_check\n",
826                                suite ? suite : "all_suites");
827         trusty_unittest_printf("[----------] 0 tests but none disabled.\n");
828         trusty_unittest_print_status_name(suite ? suite : "all_suites",
829                                           "test_count_empty_check", " FAILED ");
830         ++_test_context.tests_failed;
831         ++_test_context.tests_total;
832     }
833 
834     trusty_unittest_printf(
835             "[==========] %d tests ran (%" PRIu64 " ms total).\n",
836             _test_context.tests_total, _test_context.suite_duration_ms);
837 
838     if (_test_context.tests_total != _test_context.tests_failed) {
839         trusty_unittest_printf(
840                 "[  PASSED  ] %d tests.\n",
841                 _test_context.tests_total - _test_context.tests_failed);
842     }
843     if (_test_context.tests_skipped) {
844         trusty_unittest_printf("[  SKIPPED ] %d tests.\n",
845                                _test_context.tests_skipped);
846     }
847     if (_test_context.tests_disabled) {
848         trusty_unittest_printf("[ DISABLED ] %d tests.\n",
849                                _test_context.tests_disabled);
850     }
851     if (_test_context.tests_failed) {
852         trusty_unittest_printf("[  FAILED  ] %d tests.\n",
853                                _test_context.tests_failed);
854     }
855     return _test_context.tests_failed == 0;
856 }
857 
RUN_ALL_TESTS(void)858 static inline bool RUN_ALL_TESTS(void) {
859     return RUN_ALL_SUITE_TESTS(NULL);
860 }
861 
862 /**
863  * GTEST_SKIP() - Skip current test
864  *
865  * This will skip the current test without triggering a failure. It will use
866  * same test_abort label as the ASSERT_... macros. Calling this after a test has
867  * failed or calling ASSERT_.../EXPECT_... macros after GTEST_SKIP has jumped
868  * to test_abort is not supported.
869  */
870 #define GTEST_SKIP()                       \
871     {                                      \
872         if (!_test_context.skipped) {      \
873             _test_context.skipped = true;  \
874             _test_context.tests_skipped++; \
875         }                                  \
876         goto test_abort;                   \
877     }
878 
879 #define ASSERT_EXPECT_TEST(op, op_pre, op_sep, op_args, is_hard_fail,        \
880                            fail_action, vals_type, vals_format_placeholder,  \
881                            print_cast, print_op, val1, val2, extra_msg...)   \
882     {                                                                        \
883         vals_type _val1 = val1;                                              \
884         vals_type _val2 = val2;                                              \
885         if (!op_pre(_val1 DELETE_PAREN op_sep _val2 DELETE_PAREN op_args)) { \
886             trusty_unittest_printf("%s: @ %s:%d\n", _test_context.test_name, \
887                                    __FILE__, __LINE__);                      \
888             trusty_unittest_printf(                                          \
889                     "  expected: %s (" vals_format_placeholder ") " print_op \
890                     " %s (" vals_format_placeholder ")\n",                   \
891                     #val1, print_cast _val1, #val2, print_cast _val2);       \
892             trusty_unittest_printf("  " extra_msg);                          \
893             trusty_unittest_printf("\n");                                    \
894             if (_test_context.all_ok) {                                      \
895                 _test_context.all_ok = false;                                \
896                 _test_context.tests_failed++;                                \
897             }                                                                \
898             _test_context.hard_fail |= is_hard_fail;                         \
899             fail_action                                                      \
900         }                                                                    \
901     }
902 
HasFailure(void)903 static inline bool HasFailure(void) {
904     return !_test_context.all_ok;
905 }
906 
907 /**
908  * INSTANTIATE_TEST_SUITE_P - Instantiate parameters for a test suite
909  * @inst_name:          Name for instantiation of parameters. Should not contain
910  *                      underscores.
911  * @suite_name:         Name of test suite associated with the parameters
912  * @param_gen:          One of the parameter generators (see below)
913  * @param_to_string:    Function of type &typedef test_param_to_string_t
914  *                      used to convert a parameter to its string form. This
915  *                      argument is optional.
916  *
917  * Parameter Generators:
918  *  testing_Range(being, end, step):
919  *  Returns the values {begin, being+step, being+step+step, ...} up to but not
920  *  including end. step is optional and defaults to 1.
921  *
922  *  testing_Values(v1, v2, ..., vN):
923  *  Returns the values {v1, v2, ..., vN)
924  *
925  *  testing_ValuesIn(array)
926  *  Returns the values in array
927  *
928  *  testing_Bool()
929  *  Returns {false, true}
930  *
931  *  testing_Combine(g1, [g2, g3, g4, g5]):
932  *  Returns the values of the combinations of the provided generators
933  *  (min 1, max 5) an as an array.
934  */
935 #define INSTANTIATE_TEST_SUITE_P(inst_name, suite_name, param_gen_args...)   \
936     INSTANTIATE_TEST_SUITE_P_INTERNAL(inst_name, suite_name, param_gen_args, \
937                                       NULL, )
938 
939 /**
940  * GetParam() - Returns a pointer to the current test parameter
941  *
942  * Context: This function can be called within a parameterized test to
943  *          retrieve the current parameter to the test.
944  *
945  * Return: a pointer to the current test parameter.
946  *
947  * This pointer should be cast to the expected parameter type for the executing
948  * test.
949  */
GetParam(void)950 static inline const void* GetParam(void) {
951     return _test_context.test_param;
952 }
953 
954 #define ASSERT_EXPECT_LONG_TEST(op, is_hard_fail, fail_action, val1, val2, \
955                                 args...)                                   \
956     ASSERT_EXPECT_TEST(op, , (op), (), is_hard_fail, fail_action,          \
957                        __typeof__(val2), "%ld", (long), #op, val1, val2, args)
958 
959 #define ASSERT_EXPECT_STR_TEST(func, is_hard_fail, fail_action, args...) \
960     ASSERT_EXPECT_TEST(func, func, (, ), (), is_hard_fail, fail_action,  \
961                        const char*, "\"%s\"", , args)
962 
963 #define ASSERT_EXPECT_STRN_TEST(func, n, is_hard_fail, fail_action, args...) \
964     ASSERT_EXPECT_TEST(func, func, (, ), (, n), is_hard_fail, fail_action,   \
965                        const char*, "\"%s\"", , args)
966 
967 #define EXPECT_TEST(op, args...) ASSERT_EXPECT_LONG_TEST(op, false, , args)
968 #define EXPECT_EQ(args...) EXPECT_TEST(==, args)
969 #define EXPECT_NE(args...) EXPECT_TEST(!=, args)
970 #define EXPECT_LT(args...) EXPECT_TEST(<, args)
971 #define EXPECT_LE(args...) EXPECT_TEST(<=, args)
972 #define EXPECT_GT(args...) EXPECT_TEST(>, args)
973 #define EXPECT_GE(args...) EXPECT_TEST(>=, args)
974 #define EXPECT_STR_TEST(func, args...) \
975     ASSERT_EXPECT_STR_TEST(func, false, , args)
976 #define EXPECT_STREQ(args...) EXPECT_STR_TEST(!strcmp, "==", args)
977 #define EXPECT_STRNE(args...) EXPECT_STR_TEST(strcmp, "!=", args)
978 #define EXPECT_STRCASEEQ(args...) \
979     EXPECT_STR_TEST(!strcasecmp, "== (ignoring case)", args)
980 #define EXPECT_STRCASENE(args...) \
981     EXPECT_STR_TEST(strcasecmp, "!= (ignoring case)", args)
982 #define EXPECT_STRN_TEST(func, n, args...) \
983     ASSERT_EXPECT_STRN_TEST(func, n, false, , args)
984 #define EXPECT_STREQN(val1, val2, n, args...) \
985     EXPECT_STR_TEST(!strncmp, n, "==", val1, val2, args)
986 #define EXPECT_STRNEN(val1, val2, n, args...) \
987     EXPECT_STR_TEST(strncmp, n, "!=", val1, val2, args)
988 #define EXPECT_STRCASEEQN(val1, val2, n, args...) \
989     EXPECT_STR_TEST(!strncasecmp, n, "== (ignoring case)", val1, val2, args)
990 #define EXPECT_STRCASENEN(val1, val2, n, args...) \
991     EXPECT_STR_TEST(strncasecmp, n, "!= (ignoring case)", val1, val2, args)
992 
993 #define ASSERT_TEST(op, args...) \
994     ASSERT_EXPECT_LONG_TEST(op, true, goto test_abort;, args)
995 #define ASSERT_EQ(args...) ASSERT_TEST(==, args)
996 #define ASSERT_NE(args...) ASSERT_TEST(!=, args)
997 #define ASSERT_LT(args...) ASSERT_TEST(<, args)
998 #define ASSERT_LE(args...) ASSERT_TEST(<=, args)
999 #define ASSERT_GT(args...) ASSERT_TEST(>, args)
1000 #define ASSERT_GE(args...) ASSERT_TEST(>=, args)
1001 #define ASSERT_STR_TEST(func, args...) \
1002     ASSERT_EXPECT_STR_TEST(func, true, goto test_abort;, args)
1003 #define ASSERT_STREQ(args...) ASSERT_STR_TEST(!strcmp, "==", args)
1004 #define ASSERT_STRNE(args...) ASSERT_STR_TEST(strcmp, "!=", args)
1005 #define ASSERT_STRCASEEQ(args...) \
1006     ASSERT_STR_TEST(!strcasecmp, "== (ignoring case)", args)
1007 #define ASSERT_STRCASENE(args...) \
1008     ASSERT_STR_TEST(strcasecmp, "!= (ignoring case)", args)
1009 #define ASSERT_STRN_TEST(func, n, args...) \
1010     ASSERT_EXPECT_STRN_TEST(func, n, true, goto test_abort;, args)
1011 #define ASSERT_STREQN(val1, val2, n, args...) \
1012     ASSERT_STRN_TEST(!strncmp, n, "==", val1, val2, args)
1013 #define ASSERT_STRNEN(val1, val2, n, args...) \
1014     ASSERT_STRN_TEST(strncmp, n, "!=", val1, val2, args)
1015 #define ASSERT_STRCASEEQN(val1, val2, n, args...) \
1016     ASSERT_STRN_TEST(!strncasecmp, n, "== (ignoring case)", val1, val2, args)
1017 #define ASSERT_STRCASENEN(val1, val2, n, args...) \
1018     ASSERT_STRN_TEST(strncasecmp, n, "!= (ignoring case)", val1, val2, args)
1019 
1020 __END_CDECLS
1021