1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 #include <internal/fwk_module.h>
8 
9 #include <fwk_assert.h>
10 #include <fwk_macros.h>
11 #include <fwk_module_idx.h>
12 #include <fwk_status.h>
13 #include <fwk_test.h>
14 
15 #include <stdlib.h>
16 #include <string.h>
17 
18 #define ELEM0_IDX          0
19 #define ELEM1_IDX          1
20 #define ELEM2_IDX          0
21 #define SUB_ELEM0_IDX      0
22 #define API0_IDX           0
23 #define API1_IDX           1
24 #define EVENT0_IDX         0
25 #define EVENT1_IDX         1
26 #define EVENT2_IDX         2
27 #define NOTIFICATION0_IDX  0
28 #define NOTIFICATION1_IDX  1
29 #define NOTIFICATION2_IDX  2
30 
31 #define ELEM0_ID FWK_ID_ELEMENT(FWK_MODULE_IDX_FAKE0, ELEM0_IDX)
32 #define ELEM1_ID FWK_ID_ELEMENT(FWK_MODULE_IDX_FAKE0, ELEM1_IDX)
33 #define ELEM2_ID FWK_ID_ELEMENT(FWK_MODULE_IDX_FAKE1, ELEM2_IDX)
34 #define SUB_ELEM0_ID \
35     FWK_ID_SUB_ELEMENT(FWK_MODULE_IDX_FAKE0, ELEM0_IDX, SUB_ELEM0_IDX)
36 #define API0_ID FWK_ID_API(FWK_MODULE_IDX_FAKE0, API0_IDX)
37 #define API1_ID FWK_ID_API(FWK_MODULE_IDX_FAKE0, API1_IDX)
38 #define EVENT0_ID FWK_ID_EVENT(FWK_MODULE_IDX_FAKE1, EVENT0_IDX)
39 #define EVENT1_ID FWK_ID_EVENT(FWK_MODULE_IDX_FAKE1, EVENT1_IDX)
40 #define EVENT2_ID FWK_ID_EVENT(FWK_MODULE_IDX_FAKE1, EVENT2_IDX)
41 #define NOTIFICATION0_ID \
42     FWK_ID_NOTIFICATION(FWK_MODULE_IDX_FAKE0, NOTIFICATION0_IDX)
43 #define NOTIFICATION1_ID \
44     FWK_ID_NOTIFICATION(FWK_MODULE_IDX_FAKE0, NOTIFICATION1_IDX)
45 #define NOTIFICATION2_ID \
46     FWK_ID_NOTIFICATION(FWK_MODULE_IDX_FAKE0, NOTIFICATION2_IDX)
47 
48 /* Fake API */
49 struct fake_api {
50     int (*init)(fwk_id_t module_id, unsigned int element_count,
51                 const void *data);
52     int (*element_init)(fwk_id_t element_id, unsigned int sub_element_count,
53                         const void *data);
54 };
55 
56 /* Fake element data */
57 struct config_element_data {
58     int fake_val;
59     fwk_id_t ref;
60 };
61 
62 static struct config_element_data config_elem0;
63 static struct config_element_data config_elem1;
64 static struct config_element_data config_elem2;
65 
66 static struct fwk_element fake_element_desc_table0[3];
67 static struct fwk_element fake_element_desc_table1[2];
68 
69 /* Fake module data */
70 struct config_module_data {
71     int fake_val;
72 };
73 
74 static struct config_module_data config_module0;
75 static struct config_module_data config_module1;
76 
77 extern struct fwk_module *module_table[FWK_MODULE_IDX_COUNT];
78 extern struct fwk_module_config *module_config_table[FWK_MODULE_IDX_COUNT];
79 
80 static struct fwk_module fake_module_desc0;
81 static struct fwk_module fake_module_desc1;
82 
83 static struct fwk_module_config fake_module_config0;
84 static struct fwk_module_config fake_module_config1;
85 
86 /* Mock functions */
87 static int init_return_val;
88 static int element_init_return_val;
89 static int post_init_return_val;
90 static int bind_return_val;
91 static int bind_count_call;
92 static int start_return_val;
93 static int start_count_call;
94 static int process_bind_request_return_val;
95 static bool process_bind_request_return_api;
96 static bool get_element_table0_return_val;
97 static bool get_element_table1_return_val;
98 static int process_event_return_val;
99 static int init_return_val;
100 
init(fwk_id_t module_id,unsigned int element_count,const void * data)101 static int init(fwk_id_t module_id, unsigned int element_count,
102     const void *data)
103 {
104     (void) module_id;
105     (void) element_count;
106     (void) data;
107     return init_return_val;
108 }
109 
element_init(fwk_id_t element_id,unsigned int sub_element_count,const void * data)110 static int element_init(fwk_id_t element_id, unsigned int sub_element_count,
111     const void *data)
112 {
113     (void) element_id;
114     (void) data;
115     return element_init_return_val;
116 }
117 
post_init(fwk_id_t module_id)118 static int post_init(fwk_id_t module_id)
119 {
120     (void) module_id;
121     return post_init_return_val;
122 }
123 
bind(fwk_id_t id,unsigned int round_number)124 static int bind(fwk_id_t id, unsigned int round_number)
125 {
126     (void) id;
127     (void) round_number;
128     bind_count_call++;
129     return bind_return_val;
130 }
131 
start(fwk_id_t id)132 static int start(fwk_id_t id)
133 {
134     (void) id;
135     start_count_call++;
136     return start_return_val;
137 }
138 
139 static struct fake_api fake_api = {
140     .init = init,
141     .element_init = element_init
142 };
143 
process_bind_request(fwk_id_t source_id,fwk_id_t target_id,fwk_id_t api_id,const void ** api)144 static int process_bind_request(fwk_id_t source_id, fwk_id_t target_id,
145     fwk_id_t api_id, const void **api)
146 {
147     (void) source_id;
148     (void) target_id;
149     (void) api_id;
150     if (process_bind_request_return_api)
151         *api = &fake_api;
152 
153     return process_bind_request_return_val;
154 }
155 
get_element_table0(fwk_id_t module_id)156 static const struct fwk_element *get_element_table0(fwk_id_t module_id)
157 {
158     (void) module_id;
159     if (get_element_table0_return_val)
160         return fake_element_desc_table0;
161     else
162         return NULL;
163 }
164 
get_element_table1(fwk_id_t module_id)165 static const struct fwk_element *get_element_table1(fwk_id_t module_id)
166 {
167     (void) module_id;
168     if (get_element_table1_return_val)
169         return fake_element_desc_table1;
170     else
171         return NULL;
172 }
173 
174 /* Wrapped functions */
175 
176 /*
177  * Allow to choose the behavior of the wrapped function fwk_mm_calloc.
178  * If 0, fwk_mm_calloc(num, size) returns calloc(num, size).
179  * If 1, fwk_mm_calloc(num, size) return calloc(num, size) the first time it
180  * is called and NULL the following times.
181  * If 2, fwk_mm_calloc(num, size) returns NULL.
182  */
183 static int fwk_mm_calloc_return;
__wrap_fwk_mm_calloc(size_t num,size_t size)184 void * __wrap_fwk_mm_calloc(size_t num, size_t size)
185 {
186     if (num == 0)
187         return NULL;
188     if (fwk_mm_calloc_return == 0)
189         return calloc(num, size);
190     else if (fwk_mm_calloc_return <= 4) {
191         fwk_mm_calloc_return++;
192         return calloc(num, size);
193     }
194     return NULL;
195 }
196 
__wrap___fwk_init(size_t event_count)197 int __wrap___fwk_init(size_t event_count)
198 {
199     (void) event_count;
200     return init_return_val;
201 }
202 
__wrap___fwk_run_main_loop(void)203 void __wrap___fwk_run_main_loop(void)
204 {
205 }
206 
__wrap___fwk_notification_init(size_t notification_count)207 int __wrap___fwk_notification_init(size_t notification_count)
208 {
209     (void) notification_count;
210     return FWK_SUCCESS;
211 }
212 
test_case_setup(void)213 static void test_case_setup(void)
214 {
215     /* Default values */
216     get_element_table0_return_val = true;
217     get_element_table1_return_val = true;
218     fwk_mm_calloc_return = 0;
219     init_return_val = FWK_SUCCESS;
220     element_init_return_val = FWK_SUCCESS;
221     post_init_return_val = FWK_SUCCESS;
222     bind_return_val = FWK_SUCCESS;
223     start_return_val = FWK_SUCCESS;
224     process_bind_request_return_val = FWK_SUCCESS;
225     process_bind_request_return_api = true;
226     process_event_return_val = FWK_SUCCESS;
227     init_return_val = FWK_SUCCESS;
228 
229     bind_count_call = 0;
230     start_count_call = 0;
231 
232     config_elem0.fake_val = 5;
233     config_elem0.ref = fwk_id_build_element_id(fwk_module_id_fake0, ELEM0_IDX);
234 
235     config_elem1.fake_val = 6;
236     config_elem1.ref = fwk_id_build_element_id(fwk_module_id_fake0, ELEM1_IDX);
237 
238     config_elem2.fake_val = 7;
239     config_elem2.ref = fwk_id_build_element_id(fwk_module_id_fake1, ELEM2_IDX);
240 
241     config_module0.fake_val = 8;
242     config_module1.fake_val = 9;
243 
244     fake_module_desc0.api_count = 2;
245     fake_module_desc0.event_count = 0;
246     fake_module_desc0.notification_count = 3;
247     fake_module_desc0.type = FWK_MODULE_TYPE_DRIVER;
248     fake_module_desc0.init = init;
249     fake_module_desc0.element_init = element_init;
250     fake_module_desc0.post_init = post_init;
251     fake_module_desc0.bind = bind;
252     fake_module_desc0.start = start;
253     fake_module_desc0.process_bind_request = process_bind_request;
254 
255     fake_module_desc1.api_count = 0;
256     fake_module_desc1.event_count = 3;
257     fake_module_desc1.notification_count = 0;
258     fake_module_desc1.type = FWK_MODULE_TYPE_DRIVER;
259     fake_module_desc1.init = init;
260     fake_module_desc1.element_init = element_init;
261     fake_module_desc1.post_init = post_init;
262     fake_module_desc1.bind = bind;
263     fake_module_desc1.start = start;
264 
265     fake_element_desc_table0[0].name = "FAKE ELEM 0";
266     fake_element_desc_table0[0].data = &config_elem0;
267     fake_element_desc_table0[0].sub_element_count = 1;
268     fake_element_desc_table0[1].name = "FAKE ELEM 1";
269     fake_element_desc_table0[1].data = &config_elem1;
270     fake_element_desc_table0[2].name = NULL;
271     fake_element_desc_table0[2].data = NULL;
272 
273     fake_element_desc_table1[0].name = "FAKE ELEM 2";
274     fake_element_desc_table1[0].data = &config_elem2;
275     fake_element_desc_table1[1].name = NULL;
276     fake_element_desc_table1[1].data = NULL;
277 
278     fake_module_config0.elements.type = FWK_MODULE_ELEMENTS_TYPE_DYNAMIC;
279     fake_module_config0.elements.generator = get_element_table0;
280     fake_module_config0.data = &config_module0;
281 
282     fake_module_config1.elements.type = FWK_MODULE_ELEMENTS_TYPE_DYNAMIC;
283     fake_module_config1.elements.generator = get_element_table1;
284     fake_module_config1.data = &config_module1;
285 
286     module_table[0] = &fake_module_desc0;
287     module_table[1] = &fake_module_desc1;
288     module_table[2] = NULL;
289 
290     module_config_table[0] = &fake_module_config0;
291     module_config_table[1] = &fake_module_config1;
292     module_config_table[2] = NULL;
293 
294     fwk_module_reset();
295     fwk_module_start();
296 }
297 
test_fwk_module_is_valid_module_id(void)298 static void test_fwk_module_is_valid_module_id(void)
299 {
300     fwk_id_t id;
301     bool result;
302 
303     /* Valid module ID */
304     id = fwk_module_id_fake0;
305     result = fwk_module_is_valid_module_id(id);
306     assert(result);
307 
308     /* Valid module ID */
309     id = fwk_module_id_fake1;
310     result = fwk_module_is_valid_module_id(id);
311     assert(result);
312 
313     /* ID larger than the number of modules */
314     id = FWK_ID_MODULE(0x3);
315     result = fwk_module_is_valid_module_id(id);
316     assert(!result);
317 
318     /* Invalid type */
319     id = ELEM0_ID;
320     result = fwk_module_is_valid_module_id(id);
321     assert(!result);
322 }
323 
test_fwk_module_is_valid_event_id(void)324 static void test_fwk_module_is_valid_event_id(void)
325 {
326     fwk_id_t id;
327     bool result;
328 
329     /* Valid event ID */
330     id = EVENT0_ID;
331     result = fwk_module_is_valid_event_id(id);
332     assert(result);
333 
334     /* Valid event ID */
335     id = EVENT2_ID;
336     result = fwk_module_is_valid_event_id(id);
337     assert(result);
338 
339     /* Module IDX non valid */
340     id = FWK_ID_EVENT(0x03, 0x00);
341     result = fwk_module_is_valid_event_id(id);
342     assert(!result);
343 
344     /* Event IDX non valid */
345     id = FWK_ID_EVENT(FWK_MODULE_IDX_FAKE1, 0x03);
346     result = fwk_module_is_valid_event_id(id);
347     assert(!result);
348 
349     /* Module IDX non valid */
350     id = FWK_ID_EVENT(FWK_MODULE_IDX_FAKE0, 0x00);
351     result = fwk_module_is_valid_event_id(id);
352     assert(!result);
353 
354     /* Invalid type */
355     id = fwk_module_id_fake0;
356     result = fwk_module_is_valid_event_id(id);
357     assert(!result);
358 }
359 
test_fwk_module_is_valid_notification_id(void)360 static void test_fwk_module_is_valid_notification_id(void)
361 {
362     fwk_id_t id;
363     bool result;
364 
365     /* Valid notification ID */
366     id = NOTIFICATION0_ID;
367     result = fwk_module_is_valid_notification_id(id);
368     assert(result);
369 
370     /* Valid notification ID */
371     id = NOTIFICATION2_ID;
372     result = fwk_module_is_valid_notification_id(id);
373     assert(result);
374 
375     /* Module IDX non valid */
376     id = FWK_ID_NOTIFICATION(0x03, 0x00);
377     result = fwk_module_is_valid_notification_id(id);
378     assert(!result);
379 
380     /* Event IDX non valid */
381     id = FWK_ID_NOTIFICATION(FWK_MODULE_IDX_FAKE0, 0x03);
382     result = fwk_module_is_valid_notification_id(id);
383     assert(!result);
384 
385     /* Module IDX non valid */
386     id = FWK_ID_NOTIFICATION(FWK_MODULE_IDX_FAKE1, 0x00);
387     result = fwk_module_is_valid_notification_id(id);
388     assert(!result);
389 
390     /* Invalid type */
391     id = fwk_module_id_fake0;
392     result = fwk_module_is_valid_notification_id(id);
393     assert(!result);
394 }
395 
396 static const struct fwk_test_case_desc test_case_table[] = {
397     FWK_TEST_CASE(test_fwk_module_is_valid_module_id),
398     FWK_TEST_CASE(test_fwk_module_is_valid_event_id),
399     FWK_TEST_CASE(test_fwk_module_is_valid_notification_id),
400 };
401 
402 struct fwk_test_suite_desc test_suite = {
403     .name = "fwk_module",
404     .test_case_setup = test_case_setup,
405     .test_case_count = FWK_ARRAY_SIZE(test_case_table),
406     .test_case_table = test_case_table,
407 };
408