1 /*
2  * Copyright(c) 2023 Legrand North America, LLC.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  *
10  * @brief Zephyr testing framework FFF extension macros
11  */
12 
13 #ifndef ZEPHYR_SUBSYS_TESTSUITE_INCLUDE_ZEPHYR_FFF_EXTENSIONS_H_
14 #define ZEPHYR_SUBSYS_TESTSUITE_INCLUDE_ZEPHYR_FFF_EXTENSIONS_H_
15 
16 #include <zephyr/fff.h>
17 #include <zephyr/sys/util.h> /* for CONTAINER_OF */
18 
19 /**
20  * @defgroup fff_extensions FFF extensions
21  * @ingroup testing
22  *
23  * This module provides extensions to FFF for simplifying the
24  * configuration and usage of fakes.
25  *
26  * @{
27  */
28 
29 
30 /**
31  * @brief Wrap custom fake body to extract defined context struct
32  *
33  * Add extension macro for simplified creation of
34  * fake functions needing call-specific context data.
35  *
36  * This macro enables a fake to be implemented as follows and
37  * requires no familiarity with the inner workings of FFF.
38  *
39  * @code
40  * struct FUNCNAME##_custom_fake_context
41  * {
42  *     struct instance * const instance;
43  *     int result;
44  * };
45  *
46  * int FUNCNAME##_custom_fake(
47  *     const struct instance **instance_out)
48  * {
49  *     RETURN_HANDLED_CONTEXT(
50  *         FUNCNAME,
51  *         struct FUNCNAME##_custom_fake_context,
52  *         result,
53  *         context,
54  *         {
55  *             if (context != NULL)
56  *             {
57  *                 if (context->result == 0)
58  *                 {
59  *                     if (instance_out != NULL)
60  *                     {
61  *                         *instance_out = context->instance;
62  *                     }
63  *                 }
64  *                 return context->result;
65  *             }
66  *             return FUNCNAME##_fake.return_val;
67  *         }
68  *     );
69  * }
70  * @endcode
71  *
72  * @param FUNCNAME Name of function being faked
73  * @param CONTEXTTYPE type of custom defined fake context struct
74  * @param RESULTFIELD name of field holding the return type & value
75  * @param CONTEXTPTRNAME expected name of pointer to custom defined fake context struct
76  * @param HANDLERBODY in-line custom fake handling logic
77  */
78 
79 #define RETURN_HANDLED_CONTEXT(FUNCNAME,                                      \
80 		CONTEXTTYPE, RESULTFIELD, CONTEXTPTRNAME, HANDLERBODY)        \
81 	if (FUNCNAME##_fake.return_val_seq_len) {                             \
82 		CONTEXTTYPE * const contexts =                                \
83 		CONTAINER_OF(FUNCNAME##_fake.return_val_seq,                  \
84 				CONTEXTTYPE, RESULTFIELD);                    \
85 		size_t const seq_idx = (FUNCNAME##_fake.return_val_seq_idx <  \
86 					FUNCNAME##_fake.return_val_seq_len) ? \
87 					FUNCNAME##_fake.return_val_seq_idx++ :\
88 					FUNCNAME##_fake.return_val_seq_idx - 1;\
89 		CONTEXTTYPE * const CONTEXTPTRNAME = &contexts[seq_idx];      \
90 		HANDLERBODY;                                                  \
91 	}                                                                     \
92 	return FUNCNAME##_fake.return_val
93 
94 /**
95  * @}
96  */
97 
98 #endif /* ZEPHYR_SUBSYS_TESTSUITE_INCLUDE_ZEPHYR_FFF_EXTENSIONS_H_ */
99