1 /*
2  * Copyright (c) 2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <zephyr/ztest.h>
7 #include <zephyr/ztest_error_hook.h>
8 
9 #define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
10 #define THREAD_TEST_PRIORITY 5
11 
12 /* use to pass case type to threads */
13 static ZTEST_DMEM int case_type;
14 
15 static K_THREAD_STACK_DEFINE(tstack, STACK_SIZE);
16 static K_THREAD_STACK_DEFINE(test_stack, STACK_SIZE);
17 static struct k_thread tdata;
18 static struct k_thread test_tdata;
19 
20 /* enumerate our negative case scenario */
21 enum {
22 	THREAD_START,
23 	FLOAT_DISABLE,
24 	TIMEOUT_REMAINING_TICKS,
25 	TIMEOUT_EXPIRES_TICKS,
26 	THREAD_CREATE_NEWTHREAD_NULL,
27 	THREAD_CREATE_STACK_NULL,
28 	THREAD_CTEATE_STACK_SIZE_OVERFLOW
29 } neg_case;
30 
test_thread(void * p1,void * p2,void * p3)31 static void test_thread(void *p1, void *p2, void *p3)
32 {
33 	/* do nothing here */
34 }
35 
tThread_entry_negative(void * p1,void * p2,void * p3)36 static void tThread_entry_negative(void *p1, void *p2, void *p3)
37 {
38 	ARG_UNUSED(p2);
39 	ARG_UNUSED(p3);
40 
41 	int choice = *((int *)p1);
42 	uint32_t perm = K_INHERIT_PERMS;
43 
44 	TC_PRINT("current case is %d\n", choice);
45 
46 	/* Set up the fault or assert are expected before we call
47 	 * the target tested function.
48 	 */
49 	switch (choice) {
50 	case THREAD_START:
51 		ztest_set_fault_valid(true);
52 		k_thread_start(NULL);
53 		break;
54 	case FLOAT_DISABLE:
55 		ztest_set_fault_valid(true);
56 		k_float_disable(NULL);
57 		break;
58 	case TIMEOUT_REMAINING_TICKS:
59 		ztest_set_fault_valid(true);
60 		k_thread_timeout_remaining_ticks(NULL);
61 		break;
62 	case TIMEOUT_EXPIRES_TICKS:
63 		ztest_set_fault_valid(true);
64 		k_thread_timeout_expires_ticks(NULL);
65 		break;
66 	case THREAD_CREATE_NEWTHREAD_NULL:
67 		ztest_set_fault_valid(true);
68 		if (k_is_user_context()) {
69 			perm = perm | K_USER;
70 		}
71 
72 		k_thread_create((struct k_thread *)NULL, test_stack, STACK_SIZE,
73 			test_thread, NULL, NULL, NULL,
74 			K_PRIO_PREEMPT(THREAD_TEST_PRIORITY),
75 			perm, K_NO_WAIT);
76 		break;
77 	case THREAD_CREATE_STACK_NULL:
78 		ztest_set_fault_valid(true);
79 		if (k_is_user_context()) {
80 			perm = perm | K_USER;
81 		}
82 
83 		k_thread_create(&test_tdata, NULL, STACK_SIZE,
84 			test_thread, NULL, NULL, NULL,
85 			K_PRIO_PREEMPT(THREAD_TEST_PRIORITY),
86 			perm, K_NO_WAIT);
87 		break;
88 	case THREAD_CTEATE_STACK_SIZE_OVERFLOW:
89 		ztest_set_fault_valid(true);
90 		if (k_is_user_context()) {
91 			perm = perm | K_USER;
92 		}
93 		k_thread_create(&test_tdata, test_stack, -1,
94 			test_thread, NULL, NULL, NULL,
95 			K_PRIO_PREEMPT(THREAD_TEST_PRIORITY),
96 			perm, K_NO_WAIT);
97 		break;
98 	default:
99 		TC_PRINT("should not be here!\n");
100 		break;
101 	}
102 
103 	/* If negative comes here, it means error condition not been
104 	 * detected.
105 	 */
106 	ztest_test_fail();
107 }
108 
create_negative_test_thread(int choice)109 static void create_negative_test_thread(int choice)
110 {
111 	uint32_t perm = K_INHERIT_PERMS;
112 
113 	if (k_is_user_context()) {
114 		perm = perm | K_USER;
115 	}
116 
117 	case_type = choice;
118 
119 	k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
120 			tThread_entry_negative,
121 			(void *)&case_type, NULL, NULL,
122 			K_PRIO_PREEMPT(THREAD_TEST_PRIORITY),
123 			perm, K_NO_WAIT);
124 
125 	(void)k_thread_join(tid, K_FOREVER);
126 }
127 
128 /* TESTPOINT: Pass a null pointer into the API k_thread_start() */
ZTEST_USER(thread_error_case,test_thread_start)129 ZTEST_USER(thread_error_case, test_thread_start)
130 {
131 	create_negative_test_thread(THREAD_START);
132 }
133 
134 /* TESTPOINT: Pass a null pointer into the API k_float_disable() */
ZTEST_USER(thread_error_case,test_float_disable)135 ZTEST_USER(thread_error_case, test_float_disable)
136 {
137 	create_negative_test_thread(FLOAT_DISABLE);
138 }
139 
140 /* TESTPOINT: Pass a null pointer into the API */
ZTEST_USER(thread_error_case,test_timeout_remaining_ticks)141 ZTEST_USER(thread_error_case, test_timeout_remaining_ticks)
142 {
143 	create_negative_test_thread(TIMEOUT_REMAINING_TICKS);
144 }
145 
146 /* TESTPOINT: Pass a null pointer into the API */
ZTEST_USER(thread_error_case,test_timeout_expires_ticks)147 ZTEST_USER(thread_error_case, test_timeout_expires_ticks)
148 {
149 	create_negative_test_thread(TIMEOUT_EXPIRES_TICKS);
150 }
151 
152 /* TESTPOINT: Pass new thread with NULL into API */
ZTEST_USER(thread_error_case,test_thread_create_uninit)153 ZTEST_USER(thread_error_case, test_thread_create_uninit)
154 {
155 	create_negative_test_thread(THREAD_CREATE_NEWTHREAD_NULL);
156 }
157 
158 /* TESTPOINT: Pass a NULL stack into API */
ZTEST_USER(thread_error_case,test_thread_create_stack_null)159 ZTEST_USER(thread_error_case, test_thread_create_stack_null)
160 {
161 	create_negative_test_thread(THREAD_CREATE_STACK_NULL);
162 }
163 
164 /* TESTPOINT: Pass a overflow stack into API */
ZTEST_USER(thread_error_case,test_thread_create_stack_overflow)165 ZTEST_USER(thread_error_case, test_thread_create_stack_overflow)
166 {
167 	create_negative_test_thread(THREAD_CTEATE_STACK_SIZE_OVERFLOW);
168 }
169 
170 /*test case main entry*/
thread_grant_setup(void)171 void *thread_grant_setup(void)
172 {
173 	k_thread_access_grant(k_current_get(), &tdata, &tstack, &test_tdata, &test_stack);
174 
175 	return NULL;
176 }
177 
178 ZTEST_SUITE(thread_error_case, NULL, thread_grant_setup, NULL, NULL, NULL);
179