1 /*
2 * Copyright (c) 2012-2014 Wind River Systems, Inc.
3 * Copyright (c) 2020-2023, Intel Corporation.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <zephyr/kernel.h>
9 #include <zephyr/sys/printk.h>
10
11 #include <zephyr/ztest.h>
12 #include <assert.h>
13 #include <zephyr/tc_util.h>
14
15 #include <zephyr/debug/coredump.h>
16
17 #define STACK_SIZE (1024 + CONFIG_TEST_EXTRA_STACK_SIZE)
18
19 static struct k_thread dump_thread;
20 static K_THREAD_STACK_DEFINE(dump_stack, STACK_SIZE);
21
k_sys_fatal_error_handler(unsigned int reason,const struct arch_esf * pEsf)22 void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf)
23 {
24 ARG_UNUSED(reason);
25 ARG_UNUSED(pEsf);
26 }
27
dump_entry(void * p1,void * p2,void * p3)28 void dump_entry(void *p1, void *p2, void *p3)
29 {
30 unsigned int key;
31
32 key = irq_lock();
33 k_oops();
34 TC_ERROR("SHOULD NEVER SEE THIS\n");
35 irq_unlock(key);
36 }
37
check_error(void)38 void check_error(void)
39 {
40 int ret;
41
42 /* Check backend error if backend supports this query */
43 ret = coredump_query(COREDUMP_QUERY_GET_ERROR, NULL);
44 if (ret != -ENOTSUP) {
45 zassert_equal(ret, 0, "Error encountered! (%d)", ret);
46 }
47 }
48
clear_error(void)49 void clear_error(void)
50 {
51 int ret;
52
53 /* Clear backend error if backend supports this query */
54 ret = coredump_cmd(COREDUMP_CMD_CLEAR_ERROR, NULL);
55 if (ret != -ENOTSUP) {
56 zassert_equal(ret, 0, "Error encountered! (%d)", ret);
57 }
58 }
59
raise_coredump(void)60 static void *raise_coredump(void)
61 {
62 k_tid_t tid;
63
64 clear_error();
65
66 /* Create a thread that crashes */
67 tid = k_thread_create(&dump_thread, dump_stack,
68 K_THREAD_STACK_SIZEOF(dump_stack),
69 dump_entry, NULL, NULL, NULL,
70 0, 0, K_NO_WAIT);
71
72 k_thread_join(tid, K_FOREVER);
73
74 return &dump_thread;
75 }
76
test_has_stored_dump(bool is_expected)77 void test_has_stored_dump(bool is_expected)
78 {
79 int ret;
80
81 /* Cannot proceed with previous errors */
82 check_error();
83
84 /* There should be a stored coredump now if backend has storage */
85 ret = coredump_query(COREDUMP_QUERY_HAS_STORED_DUMP, NULL);
86 if (ret == -ENOTSUP) {
87 #ifdef CONFIG_TEST_STORED_COREDUMP
88 TC_ERROR("Can't query stored dump: unexpectedly not supported.\n");
89 ztest_test_fail();
90 #else
91 TC_PRINT("Can't query stored dump: expectedly not supported.\n");
92 ztest_test_skip();
93 #endif
94 } else if (ret == 1) {
95 #ifdef CONFIG_TEST_STORED_COREDUMP
96 check_error();
97 zassert_true(is_expected, "Unexpected coredump found.\n");
98 ztest_test_pass();
99 #else
100 TC_ERROR("Can't have a stored dump: not supported.\n");
101 ztest_test_fail();
102 #endif
103 } else if (ret == 0) {
104 #ifdef CONFIG_TEST_STORED_COREDUMP
105 check_error();
106 zassert_false(is_expected, "Should have stored dump!\n");
107 ztest_test_pass();
108 #else
109 TC_ERROR("Can't have an empty stored dump: not supported.\n");
110 ztest_test_fail();
111 #endif
112 } else {
113 TC_ERROR("Error reading stored dump! (%d)\n", ret);
114 ztest_test_fail();
115 }
116 }
117
test_verify_stored_dump(void)118 void test_verify_stored_dump(void)
119 {
120 int ret;
121
122 /* Cannot proceed with previous errors */
123 check_error();
124
125 /* There should be a stored coredump now if backend has storage */
126 ret = coredump_cmd(COREDUMP_CMD_VERIFY_STORED_DUMP, NULL);
127 if (ret == -ENOTSUP) {
128 #ifdef CONFIG_TEST_STORED_COREDUMP
129 TC_ERROR("Can't verify stored dump: unexpectedly not supported.\n");
130 ztest_test_fail();
131 #else
132 TC_PRINT("Can't verify stored dump: expectedly not supported.\n");
133 ztest_test_skip();
134 #endif
135 } else if (ret == 1) {
136 #ifdef CONFIG_TEST_STORED_COREDUMP
137 check_error();
138 ztest_test_pass();
139 #else
140 TC_ERROR("Can't have a stored dump: not supported.\n");
141 ztest_test_fail();
142 #endif
143 } else if (ret == 0) {
144 #ifdef CONFIG_TEST_STORED_COREDUMP
145 TC_ERROR("Verification of stored dump failed!\n");
146 ztest_test_fail();
147 #else
148 TC_ERROR("Can't have a stored dump: not supported.\n");
149 ztest_test_fail();
150 #endif
151 } else {
152 TC_ERROR("Error reading stored dump! (%d)\n", ret);
153 ztest_test_fail();
154 }
155 }
156
test_invalidate_stored_dump(void)157 void test_invalidate_stored_dump(void)
158 {
159 int ret;
160
161 /* Cannot proceed with previous errors */
162 check_error();
163
164 /* There should be a stored coredump now if backend has storage */
165 ret = coredump_cmd(COREDUMP_CMD_INVALIDATE_STORED_DUMP, NULL);
166 if (ret == -ENOTSUP) {
167 #ifdef CONFIG_TEST_STORED_COREDUMP
168 TC_ERROR("Can't invalidate stored dump: unexpectedly not supported.\n");
169 ztest_test_fail();
170 #else
171 TC_PRINT("Can't invalidate stored dump: expectedly not supported.\n");
172 ztest_test_skip();
173 #endif
174 } else if (ret == 0) {
175 #ifdef CONFIG_TEST_STORED_COREDUMP
176 check_error();
177 ztest_test_pass();
178 #else
179 TC_ERROR("Can't invalidate the stored dump: not supported.\n");
180 ztest_test_fail();
181 #endif
182 } else {
183 TC_ERROR("Error invalidating stored dump! (%d)\n", ret);
184 ztest_test_fail();
185 }
186 }
187
test_erase_stored_dump(void)188 void test_erase_stored_dump(void)
189 {
190 int ret;
191
192 /* Cannot proceed with previous errors */
193 check_error();
194
195 /* There should be a stored coredump now if backend has storage */
196 ret = coredump_cmd(COREDUMP_CMD_ERASE_STORED_DUMP, NULL);
197 if (ret == -ENOTSUP) {
198 #ifdef CONFIG_TEST_STORED_COREDUMP
199 TC_ERROR("Can't erase stored dump: unexpectedly not supported.\n");
200 ztest_test_fail();
201 #else
202 TC_PRINT("Can't erase stored dump: expectedly not supported.\n");
203 ztest_test_skip();
204 #endif
205 } else if (ret == 0) {
206 #ifdef CONFIG_TEST_STORED_COREDUMP
207 check_error();
208 ztest_test_pass();
209 #else
210 TC_ERROR("Can't erase the stored dump: not supported.\n");
211 ztest_test_fail();
212 #endif
213 } else {
214 TC_ERROR("Error erasing stored dump! (%d)\n", ret);
215 ztest_test_fail();
216 }
217 }
218
test_get_stored_dump_size(int size_expected)219 void test_get_stored_dump_size(int size_expected)
220 {
221 int ret;
222
223 /* Cannot proceed with previous errors */
224 check_error();
225
226 ret = coredump_query(COREDUMP_QUERY_GET_STORED_DUMP_SIZE, NULL);
227 if (ret == -ENOTSUP) {
228 #ifdef CONFIG_TEST_STORED_COREDUMP
229 TC_ERROR("Can't query stored dump size: unexpectedly not supported.\n");
230 ztest_test_fail();
231 #else
232 TC_PRINT("Can't query stored dump size: expectedly not supported.\n");
233 ztest_test_skip();
234 #endif
235 } else if (ret >= 0) {
236 #ifdef CONFIG_TEST_STORED_COREDUMP
237 check_error();
238 if (size_expected > 0) {
239 zassert_equal(ret, size_expected,
240 "Coredump size %d != %d size expected.\n",
241 ret, size_expected);
242 }
243 ztest_test_pass();
244 #else
245 TC_ERROR("Can't have a stored dump: not supported.\n");
246 ztest_test_fail();
247 #endif
248 } else {
249 TC_ERROR("Error reading stored dump size! (%d)\n", ret);
250 ztest_test_fail();
251 }
252 }
253
254 /* Excecute tests in exact sequence with the stored core dump. */
255
ZTEST(coredump_backends,test_coredump_0_ready)256 ZTEST(coredump_backends, test_coredump_0_ready) {
257 check_error();
258 ztest_test_pass();
259 }
260
ZTEST(coredump_backends,test_coredump_1_stored)261 ZTEST(coredump_backends, test_coredump_1_stored) {
262 test_has_stored_dump(true);
263 }
264
ZTEST(coredump_backends,test_coredump_2_size)265 ZTEST(coredump_backends, test_coredump_2_size) {
266 test_get_stored_dump_size(CONFIG_TEST_STORED_DUMP_SIZE);
267 }
268
ZTEST(coredump_backends,test_coredump_3_verify)269 ZTEST(coredump_backends, test_coredump_3_verify) {
270 test_verify_stored_dump();
271 }
272
ZTEST(coredump_backends,test_coredump_4_invalidate)273 ZTEST(coredump_backends, test_coredump_4_invalidate) {
274 test_invalidate_stored_dump();
275 }
276
ZTEST(coredump_backends,test_coredump_5_erase)277 ZTEST(coredump_backends, test_coredump_5_erase) {
278 test_erase_stored_dump();
279 }
280
281 ZTEST_SUITE(coredump_backends, NULL, raise_coredump, NULL, NULL, NULL);
282