1 /*
2 * Copyright (c) 2017-2018 Oticon A/S
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <zephyr/init.h>
7 #include <stdint.h>
8 #include <string.h>
9 #include "bs_types.h"
10 #include "bs_tracing.h"
11 #include "bstests.h"
12
13 /*
14 * Result of the testcase execution.
15 * Note that the executable will return the maximum of bst_result and
16 * {the HW model return code} to the shell and that
17 * {the HW model return code} will be 0 unless it fails or it is
18 * configured illegally
19 */
20 enum bst_result_t bst_result;
21
22 static struct bst_test_instance *current_test;
23 static struct bst_test_list *test_list_top;
24
25 __attribute__((weak)) bst_test_install_t test_installers[] = { NULL };
26
bst_add_tests(struct bst_test_list * tests,const struct bst_test_instance * test_def)27 struct bst_test_list *bst_add_tests(struct bst_test_list *tests,
28 const struct bst_test_instance *test_def)
29 {
30 int idx = 0;
31 struct bst_test_list *tail = tests;
32 struct bst_test_list *head = tests;
33
34 if (tail) {
35 /* First we 'run to end' */
36 while (tail->next) {
37 tail = tail->next;
38 }
39 } else {
40 if (test_def[idx].test_id != NULL) {
41 head = malloc(sizeof(struct bst_test_list));
42 head->next = NULL;
43 head->test_instance = (struct bst_test_instance *)
44 &test_def[idx++];
45 tail = head;
46 }
47 }
48
49 while (test_def[idx].test_id != NULL) {
50 tail->next = malloc(sizeof(struct bst_test_list));
51 tail = tail->next;
52 tail->test_instance = (struct bst_test_instance *)
53 &test_def[idx++];
54 tail->next = NULL;
55 }
56
57 return head;
58 }
59
bst_test_find(struct bst_test_list * tests,char * test_id)60 static struct bst_test_instance *bst_test_find(struct bst_test_list *tests,
61 char *test_id)
62 {
63 struct bst_test_list *top = tests;
64
65 while (top != NULL) {
66 if (!strcmp(top->test_instance->test_id, test_id)) {
67 /* Match found */
68 return top->test_instance;
69 }
70 top = top->next;
71 }
72 return NULL;
73 }
74
bst_install_tests(void)75 void bst_install_tests(void)
76 {
77 int idx = 0;
78
79 if (test_list_top) {
80 /* Tests were already installed */
81 return;
82 }
83
84 /* First execute installers until first test was installed */
85 while (!test_list_top && test_installers[idx]) {
86 test_list_top = test_installers[idx++](test_list_top);
87 }
88
89 /* After that simply add remaining tests to list */
90 while (test_installers[idx]) {
91 test_installers[idx++](test_list_top);
92 }
93 }
94
95 /**
96 * Print the tests list displayed with the --testslist command
97 * line option
98 */
bst_print_testslist(void)99 void bst_print_testslist(void)
100 {
101 struct bst_test_list *top;
102
103 /* Install tests */
104 bst_install_tests();
105
106 top = test_list_top;
107 while (top) {
108 bs_trace_raw(0, "TestID: %-10s\t%s\n",
109 top->test_instance->test_id,
110 top->test_instance->test_descr);
111 top = top->next;
112 }
113 }
114
115 /**
116 * Select the testcase to be run from its id
117 */
bst_set_testapp_mode(char * test_id)118 void bst_set_testapp_mode(char *test_id)
119 {
120 /* Install tests */
121 bst_install_tests();
122
123 /* By default all tests start as in progress */
124 bst_result = In_progress;
125
126 current_test = bst_test_find(test_list_top, test_id);
127 if (!current_test) {
128 bs_trace_error_line("test id %s doesn't exist\n", test_id);
129 }
130 }
131
132 /**
133 * Pass to the testcase the command line arguments it may have
134 *
135 * This function is called after bst_set_testapp_mode
136 * and before *init_f
137 */
bst_pass_args(int argc,char ** argv)138 void bst_pass_args(int argc, char **argv)
139 {
140 if (current_test && current_test->test_args_f) {
141 current_test->test_args_f(argc, argv);
142 }
143 }
144
145 /**
146 * Will be called before the CPU is booted
147 */
bst_pre_init(void)148 void bst_pre_init(void)
149 {
150 if (current_test && current_test->test_pre_init_f) {
151 current_test->test_pre_init_f();
152 }
153 }
154
155 /**
156 * Will be called when the CPU has gone to sleep for the first time
157 */
bst_post_init(void)158 void bst_post_init(void)
159 {
160 if (current_test && current_test->test_post_init_f) {
161 current_test->test_post_init_f();
162 }
163 }
164
165 /**
166 * Will be called each time the bstest_ticker timer is triggered
167 */
bst_tick(bs_time_t time)168 void bst_tick(bs_time_t time)
169 {
170
171 if (current_test == NULL) {
172 return;
173 }
174
175 if (current_test->test_tick_f) {
176 current_test->test_tick_f(time);
177 } else if (current_test->test_id) {
178 bs_trace_error_line("the test id %s doesn't have a tick handler"
179 " (how come did we arrive here?)\n",
180 current_test->test_id);
181 }
182
183 }
184
bst_irq_sniffer(int irq_number)185 bool bst_irq_sniffer(int irq_number)
186 {
187 if (current_test && current_test->test_irq_sniffer_f) {
188 return current_test->test_irq_sniffer_f(irq_number);
189 } else {
190 return false;
191 }
192 }
193
bst_fake_device_driver_pre2_init(void)194 static int bst_fake_device_driver_pre2_init(void)
195 {
196 if (current_test && current_test->test_fake_ddriver_prekernel_f) {
197 current_test->test_fake_ddriver_prekernel_f();
198 }
199 return 0;
200 }
201
bst_fake_device_driver_post_init(void)202 static int bst_fake_device_driver_post_init(void)
203 {
204 if (current_test && current_test->test_fake_ddriver_postkernel_f) {
205 current_test->test_fake_ddriver_postkernel_f();
206 }
207 return 0;
208 }
209
210 SYS_INIT(bst_fake_device_driver_pre2_init, PRE_KERNEL_1, 0);
211 SYS_INIT(bst_fake_device_driver_post_init, POST_KERNEL, 0);
212
bst_main(void)213 void bst_main(void)
214 {
215 if (current_test && current_test->test_main_f) {
216 current_test->test_main_f();
217 }
218 }
219
220 /**
221 * Will be called when the device is being terminated
222 */
bst_delete(void)223 uint8_t bst_delete(void)
224 {
225 if (current_test && current_test->test_delete_f) {
226 current_test->test_delete_f();
227 }
228
229 while (test_list_top) {
230 struct bst_test_list *tmp = test_list_top->next;
231
232 free(test_list_top);
233 test_list_top = tmp;
234 }
235
236 return bst_result;
237 }
238