Skip to content

Commit 012520d

Browse files
gbarkadiuszaescolar
authored andcommitted
Kernel: Integration test
Propose scenarios of integration test for kernel testing. Signed-off-by: Arkadiusz Cholewinski <[email protected]>
1 parent c6345c6 commit 012520d

File tree

4 files changed

+321
-0
lines changed

4 files changed

+321
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
5+
project(kernel)
6+
7+
FILE(GLOB app_sources src/*.c)
8+
target_sources(app PRIVATE ${app_sources})

tests/integration/kernel/prj.conf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
CONFIG_ZTEST=y
2+
CONFIG_MP_MAX_NUM_CPUS=1

tests/integration/kernel/src/main.c

Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
/*
2+
* Copyright (c) 2024 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/kernel.h>
8+
#include <zephyr/ztest.h>
9+
#include <stdio.h>
10+
11+
12+
/* COMMON DEFFINITIONS */
13+
#define STACK_SIZE 500
14+
#define LIST_LEN 8
15+
16+
static struct k_sem sema;
17+
static struct k_thread tdata;
18+
19+
static K_THREAD_STACK_DEFINE(tstack, STACK_SIZE);
20+
21+
22+
/* FIFO SCENARIO */
23+
/* Thread A enters items into a fifo, starts Thread B and waits for a semaphore. */
24+
/* Thread B extracts all items from the fifo and enters some items back into the fifo. */
25+
/* Thread B gives the semaphore for Thread A to continue. */
26+
/* Once the control is returned back to Thread A, it extracts all items from the fifo. */
27+
/* Verify the data's correctness. */
28+
29+
static K_FIFO_DEFINE(fifo);
30+
struct fifo_item_t {
31+
void *fifo_reserved; /* 1st word reserved for use by FIFO */
32+
uint8_t value;
33+
};
34+
static struct fifo_item_t fifo_data[LIST_LEN];
35+
36+
static void thread_entry_fn_fifo(void *p1, void *p2, void *p3)
37+
{
38+
struct fifo_item_t *rx_data;
39+
uint32_t i;
40+
41+
/* Get items from fifo */
42+
for (i = 0U; i < LIST_LEN; i++) {
43+
rx_data = k_fifo_get((struct k_fifo *)p1, K_NO_WAIT);
44+
zassert_equal(rx_data->value, fifo_data[i].value);
45+
}
46+
47+
/* Put items into fifo */
48+
for (i = 0U; i < LIST_LEN; i++) {
49+
fifo_data[i].value *= i;
50+
k_fifo_put((struct k_fifo *)p1, &fifo_data[i]);
51+
}
52+
53+
/* Give control back to Thread A */
54+
k_sem_give(&sema);
55+
}
56+
57+
58+
ZTEST(kernel, test_fifo_usage)
59+
{
60+
struct fifo_item_t *rx_data;
61+
uint32_t i;
62+
63+
/* Init binary semaphore */
64+
k_sem_init(&sema, 0, 1);
65+
66+
/* Set and Put items into fifo */
67+
for (i = 0U; i < LIST_LEN; i++) {
68+
fifo_data[i].value = i;
69+
k_fifo_put(&fifo, &fifo_data[i]);
70+
}
71+
72+
/* Create the Thread B */
73+
k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
74+
thread_entry_fn_fifo, &fifo, NULL, NULL,
75+
K_PRIO_PREEMPT(0), K_INHERIT_PERMS, K_NO_WAIT);
76+
77+
/* Let the thread B run */
78+
k_sem_take(&sema, K_FOREVER);
79+
80+
/* Get items from fifo */
81+
for (i = 0U; i < LIST_LEN; i++) {
82+
rx_data = k_fifo_get(&fifo, K_NO_WAIT);
83+
zassert_equal(rx_data->value, fifo_data[i].value);
84+
}
85+
86+
/* Clear the spawn thread */
87+
k_thread_abort(tid);
88+
}
89+
90+
/* LIFO SCENARIO */
91+
/* Thread A enters items into a lifo, starts Thread B and waits for a semaphore. */
92+
/* Thread B extracts all items from the lifo and enters some items back into the lifo. */
93+
/* Thread B gives the semaphore for Thread A to continue. */
94+
/* Once the control is returned back to Thread A, it extracts all items from the lifo. */
95+
/* Verify the data's correctness. */
96+
97+
struct lifo_item_t {
98+
void *LIFO_reserved; /* 1st word reserved for use by LIFO */
99+
uint8_t value;
100+
};
101+
static struct lifo_item_t lifo_data[LIST_LEN];
102+
K_LIFO_DEFINE(lifo);
103+
104+
105+
static void thread_entry_fn_lifo(void *p1, void *p2, void *p3)
106+
{
107+
struct lifo_item_t *rx_data;
108+
uint32_t i;
109+
110+
/* Get items from lifo */
111+
for (i = 0U; i < LIST_LEN; i++) {
112+
rx_data = k_lifo_get((struct k_lifo *)p1, K_NO_WAIT);
113+
zassert_equal(rx_data->value, lifo_data[LIST_LEN-1-i].value);
114+
}
115+
116+
/* Put items into lifo */
117+
for (i = 0U; i < LIST_LEN; i++) {
118+
lifo_data[i].value *= i;
119+
k_lifo_put((struct k_lifo *)p1, &lifo_data[i]);
120+
}
121+
122+
/* Give control back to Thread A */
123+
k_sem_give(&sema);
124+
}
125+
126+
ZTEST(kernel, test_lifo_usage)
127+
{
128+
struct lifo_item_t *rx_data;
129+
uint32_t i;
130+
131+
/* Init binary semaphore */
132+
k_sem_init(&sema, 0, 1);
133+
134+
/* Set and Put items into lifo */
135+
for (i = 0U; i < LIST_LEN; i++) {
136+
lifo_data[i].value = i;
137+
k_lifo_put(&lifo, &lifo_data[i]);
138+
}
139+
140+
/* Create the Thread B */
141+
k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
142+
thread_entry_fn_lifo, &lifo, NULL, NULL,
143+
K_PRIO_PREEMPT(0), K_INHERIT_PERMS, K_NO_WAIT);
144+
145+
/* Let the thread B run */
146+
k_sem_take(&sema, K_FOREVER);
147+
148+
/* Get items from lifo */
149+
for (i = 0U; i < LIST_LEN; i++) {
150+
rx_data = k_lifo_get(&lifo, K_NO_WAIT);
151+
zassert_equal(rx_data->value, lifo_data[LIST_LEN-1-i].value);
152+
}
153+
154+
/* Clear the spawn thread */
155+
k_thread_abort(tid);
156+
157+
}
158+
159+
/* STACK SCENARIO */
160+
/* Thread A enters items into a stack, starts thread B and waits for a semaphore. */
161+
/* Thread B extracts all items from the stack and enters some items back into the stack. */
162+
/* Thread B gives the semaphore for Thread A to continue. */
163+
/* Once the control is returned back to Thread A, it extracts all items from the stack. */
164+
/* Verify the data's correctness. */
165+
166+
167+
#define STACK_LEN 8
168+
#define MAX_ITEMS 8
169+
170+
K_STACK_DEFINE(stack, STACK_LEN);
171+
stack_data_t stack_data[MAX_ITEMS];
172+
173+
174+
static void thread_entry_fn_stack(void *p1, void *p2, void *p3)
175+
{
176+
stack_data_t *rx_data;
177+
stack_data_t data[MAX_ITEMS];
178+
179+
/* fill data to compare */
180+
for (int i = 0; i < STACK_LEN; i++) {
181+
data[i] = i;
182+
}
183+
184+
/* read data from a stack */
185+
for (int i = 0; i < STACK_LEN; i++) {
186+
k_stack_pop((struct k_stack *)p1, (stack_data_t *)&rx_data, K_NO_WAIT);
187+
}
188+
189+
zassert_false(memcmp(rx_data, data, STACK_LEN),
190+
"Push & Pop items does not match");
191+
192+
/* Push data into a stack */
193+
for (int i = 0; i < STACK_LEN; i++) {
194+
stack_data[i] *= i;
195+
k_stack_push((struct k_stack *)p1, (stack_data_t)&stack_data[i]);
196+
}
197+
198+
/* Give control back to Thread A */
199+
k_sem_give(&sema);
200+
}
201+
202+
203+
ZTEST(kernel, test_stack_usage)
204+
{
205+
stack_data_t *rx_data;
206+
207+
/* Init binary semaphore */
208+
k_sem_init(&sema, 0, 1);
209+
210+
/* Push data into a stack */
211+
for (int i = 0; i < STACK_LEN; i++) {
212+
stack_data[i] = i;
213+
k_stack_push(&stack, (stack_data_t)&stack_data[i]);
214+
}
215+
216+
/* Create the Thread B */
217+
k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
218+
thread_entry_fn_stack, &stack, NULL, NULL,
219+
K_PRIO_PREEMPT(0), K_INHERIT_PERMS, K_NO_WAIT);
220+
221+
/* Let the thread B run */
222+
k_sem_take(&sema, K_FOREVER);
223+
224+
/* read data from a stack */
225+
for (int i = 0; i < STACK_LEN; i++) {
226+
k_stack_pop(&stack, (stack_data_t *)&rx_data, K_NO_WAIT);
227+
}
228+
229+
230+
/* Verify the correctness */
231+
zassert_false(memcmp(rx_data, stack_data, STACK_LEN),
232+
"Push & Pop items does not match");
233+
234+
/* Clear the spawn thread */
235+
k_thread_abort(tid);
236+
}
237+
238+
/* MUTEX SCENARIO */
239+
/* Initialize the mutex. */
240+
/* Start the two Threads with the entry points. */
241+
/* The entry points change variable and use lock and unlock mutex functions to */
242+
/* synchronize the access to that variable. */
243+
/* Join all threads. */
244+
/* Verify the variable. */
245+
246+
#define NUMBER_OF_ITERATIONS 10000
247+
248+
static uint32_t mutex_data;
249+
static struct k_thread tdata_2;
250+
static K_THREAD_STACK_DEFINE(tstack_2, STACK_SIZE);
251+
252+
K_MUTEX_DEFINE(mutex);
253+
254+
static void thread_entry_fn_mutex(void *p1, void *p2, void *p3)
255+
{
256+
uint32_t i;
257+
258+
for (i = 0; i < NUMBER_OF_ITERATIONS; i++) {
259+
k_mutex_lock((struct k_mutex *)p1, K_FOREVER);
260+
mutex_data += 1;
261+
k_mutex_unlock((struct k_mutex *)p1);
262+
}
263+
}
264+
265+
static void thread_entry_fn_mutex_2(void *p1, void *p2, void *p3)
266+
{
267+
uint32_t i;
268+
269+
for (i = 0; i < NUMBER_OF_ITERATIONS*2; i++) {
270+
k_mutex_lock((struct k_mutex *)p1, K_FOREVER);
271+
mutex_data -= 1;
272+
k_mutex_unlock((struct k_mutex *)p1);
273+
}
274+
}
275+
276+
ZTEST(kernel, test_mutex_usage)
277+
{
278+
279+
/* Create the Thread A */
280+
k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
281+
thread_entry_fn_mutex, &mutex, &mutex_data, NULL,
282+
K_PRIO_PREEMPT(0), K_INHERIT_PERMS, K_FOREVER);
283+
284+
/* Create the Thread B */
285+
k_tid_t tid2 = k_thread_create(&tdata_2, tstack_2, STACK_SIZE,
286+
thread_entry_fn_mutex_2, &mutex, &mutex_data, NULL,
287+
K_PRIO_PREEMPT(0), K_INHERIT_PERMS, K_FOREVER);
288+
289+
/* Start the Thread A */
290+
k_thread_start(tid);
291+
/* Start the Thread B */
292+
k_thread_start(tid2);
293+
/* Wait for end of Thread A */
294+
k_thread_join(&tdata, K_FOREVER);
295+
/* Wait for end of Thread B */
296+
k_thread_join(&tdata_2, K_FOREVER);
297+
/* Verify data after the end of the threads */
298+
zassert_equal(mutex_data, -10000);
299+
300+
/* Clear the spawn threads */
301+
k_thread_abort(tid);
302+
k_thread_abort(tid2);
303+
}
304+
305+
306+
ZTEST_SUITE(kernel, NULL, NULL,
307+
ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL);
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
tests:
2+
integration.kernel:
3+
tags:
4+
- kernel

0 commit comments

Comments
 (0)