1 /*
2  * Copyright (c) 2016 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <zephyr/irq_offload.h>
9 #include <zephyr/ztest_error_hook.h>
10 
11 #define TIMEOUT K_MSEC(100)
12 #define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
13 #define STACK_LEN 2
14 
15 static ZTEST_BMEM stack_data_t data[STACK_LEN];
16 extern struct k_stack stack;
17 K_THREAD_STACK_DEFINE(threadstack2, STACK_SIZE);
18 struct k_thread thread_data2;
19 
stack_pop_fail(struct k_stack * rx_data_stack)20 static void stack_pop_fail(struct k_stack *rx_data_stack)
21 {
22 	stack_data_t rx_data;
23 
24 	/**TESTPOINT: stack pop returns -EBUSY*/
25 	zassert_equal(k_stack_pop(rx_data_stack, &rx_data, K_NO_WAIT), -EBUSY);
26 	/**TESTPOINT: stack pop returns -EAGAIN*/
27 	zassert_equal(k_stack_pop(rx_data_stack, &rx_data, TIMEOUT), -EAGAIN);
28 }
29 
30 /**
31  * @addtogroup kernel_stack_tests
32  * @{
33  */
34 
35 /* Sub-thread entry */
tStack_pop_entry(void * p1,void * p2,void * p3)36 void tStack_pop_entry(void *p1, void *p2, void *p3)
37 {
38 	zassert_true(k_stack_pop(p1, p2, K_FOREVER), "stack pop failed\n");
39 }
40 
41 /**
42  * @brief Verifies stack pop functionality
43  * @see k_stack_init(), k_stack_pop()
44  */
ZTEST(stack_fail,test_stack_pop_fail)45 ZTEST(stack_fail, test_stack_pop_fail)
46 {
47 	k_stack_init(&stack, data, STACK_LEN);
48 
49 	stack_pop_fail(&stack);
50 }
51 
52 /**
53  * @brief Verifies cleanup a stack that still be needed by another
54  * thread.
55  * @see k_stack_cleanup()
56  */
ZTEST(stack_fail,test_stack_cleanup_error)57 ZTEST(stack_fail, test_stack_cleanup_error)
58 {
59 	stack_data_t rx_data[STACK_LEN - 1];
60 
61 	k_stack_init(&stack, data, STACK_LEN);
62 	/* Creat a new thread */
63 	k_tid_t tid = k_thread_create(&thread_data2, threadstack2, STACK_SIZE,
64 					tStack_pop_entry, &stack,
65 					rx_data, NULL, K_PRIO_PREEMPT(0), 0,
66 					K_NO_WAIT);
67 	/* Delay for finishing some actions of the new thread */
68 	k_sleep(K_MSEC(500));
69 	/* Try to clean up the stack, that still be waited by the thread */
70 	zassert_true(k_stack_cleanup(&stack) == -EAGAIN, "The stack is cleanuped successful");
71 	/* clear the spawn thread to avoid side effect */
72 	k_thread_abort(tid);
73 }
74 
75 /**
76  * @brief Verifies push a data in the full stack.
77  * @see k_stack_push()
78  */
ZTEST(stack_fail,test_stack_push_full)79 ZTEST(stack_fail, test_stack_push_full)
80 {
81 	stack_data_t tx_data[STACK_LEN] = {0};
82 	stack_data_t data_tmp = 0;
83 
84 	k_stack_init(&stack, data, STACK_LEN);
85 	for (int i = 0; i < STACK_LEN; i++) {
86 		zassert_true(k_stack_push(&stack, tx_data[i]) == 0, "push data into stack failed");
87 	}
88 	/* Verify that push a data in the full stack, a negative value will be met */
89 	zassert_true(k_stack_push(&stack, data_tmp) == -ENOMEM, "push data successful");
90 }
91 
92 #ifdef CONFIG_USERSPACE
93 /**
94  * @brief Verifies stack pop from a user thread
95  * @see k_stack_init(), k_stack_pop()
96  */
ZTEST_USER(stack_fail,test_stack_user_pop_fail)97 ZTEST_USER(stack_fail, test_stack_user_pop_fail)
98 {
99 	struct k_stack *alloc_stack = k_object_alloc(K_OBJ_STACK);
100 
101 	zassert_not_null(alloc_stack, "couldn't allocate stack object");
102 	zassert_false(k_stack_alloc_init(alloc_stack, STACK_LEN),
103 		      "stack init failed");
104 
105 	stack_pop_fail(alloc_stack);
106 }
107 
108 /**
109  * @brief Verifies stack alloc and initialize a null pointer.
110  * @see k_stack_alloc_init()
111  */
ZTEST_USER(stack_fail,test_stack_user_init_null)112 ZTEST_USER(stack_fail, test_stack_user_init_null)
113 {
114 	ztest_set_fault_valid(true);
115 	k_stack_alloc_init(NULL, STACK_LEN);
116 }
117 
118 /**
119  * @brief Verify that alloc and initialize a stack with
120  * 0 memory.
121  * @see k_stack_alloc_init()
122  */
ZTEST_USER(stack_fail,test_stack_user_init_invalid_value)123 ZTEST_USER(stack_fail, test_stack_user_init_invalid_value)
124 {
125 	ztest_set_fault_valid(true);
126 	struct k_stack *alloc_stack = k_object_alloc(K_OBJ_STACK);
127 
128 	zassert_not_null(alloc_stack, "couldn't allocate stack object");
129 	k_stack_alloc_init(alloc_stack, 0);
130 }
131 
132 /**
133  * @brief Verify that push some data into a NULL
134  * pointer.
135  * @see k_stack_push()
136  */
ZTEST_USER(stack_fail,test_stack_user_push_null)137 ZTEST_USER(stack_fail, test_stack_user_push_null)
138 {
139 	ztest_set_fault_valid(true);
140 	k_stack_push(NULL, 0);
141 }
142 
143 /**
144  * @brief Verifies pop data from a NULL pointer.
145  * @see k_stack_pop()
146  */
ZTEST_USER(stack_fail,test_stack_user_pop_null)147 ZTEST_USER(stack_fail, test_stack_user_pop_null)
148 {
149 	ztest_set_fault_valid(true);
150 	k_stack_pop(NULL, 0, K_NO_WAIT);
151 }
152 
153 /**
154  * @brief Verifies cleanup a stack that its data still be waited by
155  * another thread.
156  * @see k_stack_pop()
157  */
ZTEST_USER(stack_fail,test_stack_user_pop_permission)158 ZTEST_USER(stack_fail, test_stack_user_pop_permission)
159 {
160 	ztest_set_fault_valid(true);
161 	struct k_stack *alloc_stack = k_object_alloc(K_OBJ_STACK);
162 
163 	zassert_not_null(alloc_stack, "couldn't allocate stack object");
164 	zassert_false(k_stack_alloc_init(alloc_stack, STACK_LEN),
165 		      "stack init failed");
166 	/* Try to access and to write data at invalid address */
167 	k_stack_pop(alloc_stack, (stack_data_t *)alloc_stack, K_NO_WAIT);
168 }
169 #endif
170 /**
171  * @}
172  */
173