1 /*
2 * Copyright (c) 2020 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <zephyr/ztest.h>
7 #include <zephyr/irq_offload.h>
8 #include <zephyr/ztest_error_hook.h>
9
10 #define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
11 #define THREAD_TEST_PRIORITY 5
12
13 /* use to pass case type to threads */
14 static ZTEST_DMEM int case_type;
15
16 static struct k_mutex mutex;
17 static struct k_sem sem;
18 static struct k_pipe pipe;
19 static struct k_queue queue;
20
21
22 static K_THREAD_STACK_DEFINE(tstack, STACK_SIZE);
23 static struct k_thread tdata;
24
25 /* enumerate our negative case scenario */
26 enum {
27 MUTEX_INIT_NULL,
28 MUTEX_INIT_INVALID_OBJ,
29 MUTEX_LOCK_NULL,
30 MUTEX_LOCK_INVALID_OBJ,
31 MUTEX_UNLOCK_NULL,
32 MUTEX_UNLOCK_INVALID_OBJ,
33 NOT_DEFINE
34 } neg_case;
35
36 /* This is a semaphore using inside irq_offload */
37 extern struct k_sem offload_sem;
38
39 /* A call back function which is hooked in default assert handler. */
ztest_post_fatal_error_hook(unsigned int reason,const struct arch_esf * pEsf)40 void ztest_post_fatal_error_hook(unsigned int reason,
41 const struct arch_esf *pEsf)
42
43 {
44 /* check if expected error */
45 zassert_equal(reason, K_ERR_KERNEL_OOPS);
46 }
47
tThread_entry_negative(void * p1,void * p2,void * p3)48 static void tThread_entry_negative(void *p1, void *p2, void *p3)
49 {
50 ARG_UNUSED(p1);
51 ARG_UNUSED(p3);
52
53 int choice = *((int *)p2);
54
55 TC_PRINT("current case is %d\n", choice);
56
57 /* Set up the fault or assert are expected before we call
58 * the target tested function.
59 */
60 switch (choice) {
61 case MUTEX_INIT_NULL:
62 ztest_set_fault_valid(true);
63 k_mutex_init(NULL);
64 break;
65 case MUTEX_INIT_INVALID_OBJ:
66 ztest_set_fault_valid(true);
67 k_mutex_init((struct k_mutex *)&sem);
68 break;
69 case MUTEX_LOCK_NULL:
70 ztest_set_fault_valid(true);
71 k_mutex_lock(NULL, K_NO_WAIT);
72 break;
73 case MUTEX_LOCK_INVALID_OBJ:
74 ztest_set_fault_valid(true);
75 k_mutex_lock((struct k_mutex *)&pipe, K_NO_WAIT);
76 break;
77 case MUTEX_UNLOCK_NULL:
78 ztest_set_fault_valid(true);
79 k_mutex_unlock(NULL);
80 break;
81 case MUTEX_UNLOCK_INVALID_OBJ:
82 ztest_set_fault_valid(true);
83 k_mutex_unlock((struct k_mutex *)&queue);
84 break;
85 default:
86 TC_PRINT("should not be here!\n");
87 break;
88 }
89
90 /* If negative comes here, it means error condition not been
91 * detected.
92 */
93 ztest_test_fail();
94 }
95
create_negative_test_thread(int choice)96 static int create_negative_test_thread(int choice)
97 {
98 int ret;
99 uint32_t perm = K_INHERIT_PERMS;
100
101 if (k_is_user_context()) {
102 perm = perm | K_USER;
103 }
104
105 case_type = choice;
106
107 k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
108 tThread_entry_negative,
109 &mutex, (void *)&case_type, NULL,
110 K_PRIO_PREEMPT(THREAD_TEST_PRIORITY),
111 perm, K_NO_WAIT);
112
113 ret = k_thread_join(tid, K_FOREVER);
114
115 return ret;
116 }
117
118
119 /**
120 * @brief Test initializing mutex with a NULL pointer
121 *
122 * @details Pass a null pointer as parameter, then see if the
123 * expected error happens.
124 *
125 * @ingroup kernel_mutex_tests
126 *
127 * @see k_mutex_init()
128 */
ZTEST_USER(mutex_api_error,test_mutex_init_null)129 ZTEST_USER(mutex_api_error, test_mutex_init_null)
130 {
131 create_negative_test_thread(MUTEX_INIT_NULL);
132 }
133
134 /**
135 * @brief Test initialize mutex with a invalid kernel object
136 *
137 * @details Pass a invalid kobject as parameter, then see if the
138 * expected error happens.
139 *
140 * @ingroup kernel_mutex_tests
141 *
142 * @see k_mutex_init()
143 */
ZTEST_USER(mutex_api_error,test_mutex_init_invalid_obj)144 ZTEST_USER(mutex_api_error, test_mutex_init_invalid_obj)
145 {
146 create_negative_test_thread(MUTEX_INIT_INVALID_OBJ);
147 }
148
149 /**
150 * @brief Test locking mutex with a NULL pointer
151 *
152 * @details Pass a null pointer as parameter, then see if the
153 * expected error happens.
154 *
155 * @ingroup kernel_mutex_tests
156 *
157 * @see k_mutex_lock()
158 */
ZTEST_USER(mutex_api_error,test_mutex_lock_null)159 ZTEST_USER(mutex_api_error, test_mutex_lock_null)
160 {
161 create_negative_test_thread(MUTEX_LOCK_NULL);
162 }
163
164 /**
165 * @brief Test locking mutex with a invalid kernel object
166 *
167 * @details Pass a invalid kobject as parameter, then see if the
168 * expected error happens.
169 *
170 * @ingroup kernel_mutex_tests
171 *
172 * @see k_mutex_lock()
173 */
174 /* TESTPOINT: Pass a invalid kobject into the API k_mutex_lock */
ZTEST_USER(mutex_api_error,test_mutex_lock_invalid_obj)175 ZTEST_USER(mutex_api_error, test_mutex_lock_invalid_obj)
176 {
177 create_negative_test_thread(MUTEX_LOCK_INVALID_OBJ);
178 }
179
180 /**
181 * @brief Test unlocking mutex with a NULL pointer
182 *
183 * @details Pass a null pointer as parameter, then see if the
184 * expected error happens.
185 *
186 * @ingroup kernel_mutex_tests
187 *
188 * @see k_mutex_unlock()
189 */
ZTEST_USER(mutex_api_error,test_mutex_unlock_null)190 ZTEST_USER(mutex_api_error, test_mutex_unlock_null)
191 {
192 create_negative_test_thread(MUTEX_UNLOCK_NULL);
193 }
194
195 /**
196 * @brief Test unlocking mutex with a invalid kernel object
197 *
198 * @details Pass a invalid kobject as parameter, then see if the
199 * expected error happens.
200 *
201 * @ingroup kernel_mutex_tests
202 *
203 * @see k_mutex_unlock()
204 */
205 /* TESTPOINT: Pass a invalid kobject into the API k_mutex_unlock */
ZTEST_USER(mutex_api_error,test_mutex_unlock_invalid_obj)206 ZTEST_USER(mutex_api_error, test_mutex_unlock_invalid_obj)
207 {
208 create_negative_test_thread(MUTEX_UNLOCK_INVALID_OBJ);
209 }
210
mutex_api_tests_setup(void)211 static void *mutex_api_tests_setup(void)
212 {
213 #ifdef CONFIG_USERSPACE
214 k_thread_access_grant(k_current_get(), &tdata, &tstack,
215 &mutex, &sem, &pipe, &queue);
216 #endif
217 return NULL;
218 }
219
220 ZTEST_SUITE(mutex_api_error, NULL, mutex_api_tests_setup, NULL, NULL, NULL);
221