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