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