Skip to content

Commit 0849895

Browse files
SecureSheIInashif
authored andcommitted
tests: kernel: pipe: testcases to improve code coverage for pipes
Added back test_pipe_alloc because the z_thread_malloc called in the API has been updated to use k_heap instead of k_mem_pool. Adjusted test_resource_pool_auto_free by replacing z_mem_pool_malloc with k_heap_alloc. Added new test_k_pipe_cleanup to cover one more branch in k_pipe_cleanup. Modified test_half_pipe_put_get to cover branches for (reader != NULL) in k_pipe_put. Added test test_pipe_get_put to cover branches for (writer != NULL) in k_pipe_get. Added trivial tests to cover input validity checks. Line coverage has been improved by 52%, function cov by 56%, and branch cov by 46%. Signed-off-by: Shihao Shen <[email protected]>
1 parent 2638f2e commit 0849895

File tree

2 files changed

+210
-10
lines changed

2 files changed

+210
-10
lines changed

tests/kernel/pipe/pipe_api/src/main.c

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,25 @@
1313

1414
#include <ztest.h>
1515
extern void test_pipe_thread2thread(void);
16-
1716
extern void test_pipe_put_fail(void);
1817
extern void test_pipe_get_fail(void);
1918
extern void test_pipe_block_put(void);
2019
extern void test_pipe_block_put_sema(void);
2120
extern void test_pipe_get_put(void);
22-
extern void test_half_pipe_get_put(void);
21+
22+
extern void test_half_pipe_put_get(void);
2323
extern void test_half_pipe_saturating_block_put(void);
2424
extern void test_half_pipe_block_put_sema(void);
2525
extern void test_pipe_alloc(void);
2626
extern void test_pipe_reader_wait(void);
2727
extern void test_pipe_block_writer_wait(void);
28+
extern void test_pipe_cleanup(void);
29+
#ifdef CONFIG_USERSPACE
30+
extern void test_pipe_user_thread2thread(void);
31+
extern void test_pipe_user_put_fail(void);
32+
extern void test_pipe_user_get_fail(void);
33+
extern void test_resource_pool_auto_free(void);
34+
#endif
2835

2936
extern void test_pipe_avail_r_lt_w(void);
3037
extern void test_pipe_avail_w_lt_r(void);
@@ -37,6 +44,20 @@ extern struct k_pipe pipe, kpipe, khalfpipe, put_get_pipe;
3744
extern struct k_sem end_sema;
3845
extern struct k_stack tstack;
3946
extern struct k_thread tdata;
47+
extern struct k_heap test_pool;
48+
49+
#ifndef CONFIG_USERSPACE
50+
#define dummy_test(_name) \
51+
static void _name(void) \
52+
{ \
53+
ztest_test_skip(); \
54+
}
55+
56+
dummy_test(test_pipe_user_thread2thread);
57+
dummy_test(test_pipe_user_put_fail);
58+
dummy_test(test_pipe_user_get_fail);
59+
dummy_test(test_resource_pool_auto_free);
60+
#endif /* !CONFIG_USERSPACE */
4061

4162
/*test case main entry*/
4263
void test_main(void)
@@ -45,11 +66,20 @@ void test_main(void)
4566
&kpipe, &end_sema, &tdata, &tstack,
4667
&khalfpipe, &put_get_pipe);
4768

69+
k_thread_heap_assign(k_current_get(), &test_pool);
70+
4871
ztest_test_suite(pipe_api,
4972
ztest_1cpu_unit_test(test_pipe_thread2thread),
73+
ztest_1cpu_user_unit_test(test_pipe_user_thread2thread),
74+
ztest_1cpu_user_unit_test(test_pipe_user_put_fail),
75+
ztest_user_unit_test(test_pipe_user_get_fail),
76+
ztest_unit_test(test_resource_pool_auto_free),
5077
ztest_1cpu_unit_test(test_pipe_put_fail),
5178
ztest_unit_test(test_pipe_get_fail),
52-
ztest_unit_test(test_half_pipe_get_put),
79+
ztest_unit_test(test_half_pipe_put_get),
80+
ztest_unit_test(test_pipe_get_put),
81+
ztest_1cpu_unit_test(test_pipe_alloc),
82+
ztest_unit_test(test_pipe_cleanup),
5383
ztest_unit_test(test_pipe_reader_wait),
5484
ztest_unit_test(test_pipe_avail_r_lt_w),
5585
ztest_unit_test(test_pipe_avail_w_lt_r),

tests/kernel/pipe/pipe_api/src/test_pipe_contexts.c

Lines changed: 177 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#define BYTES_TO_WRITE 16
1212
#define BYTES_TO_READ BYTES_TO_WRITE
1313

14+
K_HEAP_DEFINE(mpool, PIPE_LEN * 1);
15+
1416
static ZTEST_DMEM unsigned char __aligned(4) data[] =
1517
"abcd1234$%^&PIPEefgh5678!/?*EPIPijkl9012[]<>PEPImnop3456{}()IPEP";
1618
BUILD_ASSERT(sizeof(data) >= PIPE_LEN);
@@ -20,7 +22,7 @@ K_PIPE_DEFINE(kpipe, PIPE_LEN, 4);
2022
K_PIPE_DEFINE(khalfpipe, (PIPE_LEN / 2), 4);
2123
K_PIPE_DEFINE(kpipe1, PIPE_LEN, 4);
2224
K_PIPE_DEFINE(pipe_test_alloc, PIPE_LEN, 4);
23-
struct k_pipe pipe;
25+
struct k_pipe pipe, pipe1;
2426

2527
K_THREAD_STACK_DEFINE(tstack, STACK_SIZE);
2628
K_THREAD_STACK_DEFINE(tstack1, STACK_SIZE);
@@ -30,6 +32,17 @@ struct k_thread tdata1;
3032
struct k_thread tdata2;
3133
K_SEM_DEFINE(end_sema, 0, 1);
3234

35+
#ifdef CONFIG_64BIT
36+
#define SZ 256
37+
#else
38+
#define SZ 128
39+
#endif
40+
K_HEAP_DEFINE(test_pool, SZ * 4);
41+
42+
struct mem_block {
43+
void *data;
44+
};
45+
3346
static void tpipe_put(struct k_pipe *ppipe, k_timeout_t timeout)
3447
{
3548
size_t to_wt, wt_byte = 0;
@@ -90,6 +103,23 @@ static void tpipe_thread_thread(struct k_pipe *ppipe)
90103
k_thread_abort(tid);
91104
}
92105

106+
static void tpipe_kthread_to_kthread(struct k_pipe *ppipe)
107+
{
108+
/**TESTPOINT: thread-thread data passing via pipe*/
109+
k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
110+
tThread_entry, ppipe, NULL, NULL,
111+
K_PRIO_PREEMPT(0), 0, K_NO_WAIT);
112+
113+
tpipe_put(ppipe, K_NO_WAIT);
114+
k_sem_take(&end_sema, K_FOREVER);
115+
116+
k_sem_take(&end_sema, K_FOREVER);
117+
tpipe_get(ppipe, K_FOREVER);
118+
119+
/* clear the spawned thread avoid side effect */
120+
k_thread_abort(tid);
121+
}
122+
93123
static void tpipe_put_no_wait(struct k_pipe *ppipe)
94124
{
95125
size_t to_wt, wt_byte = 0;
@@ -104,6 +134,89 @@ static void tpipe_put_no_wait(struct k_pipe *ppipe)
104134
}
105135
}
106136

137+
static void tpipe_put_small_size(struct k_pipe *ppipe, k_timeout_t timeout)
138+
{
139+
size_t to_wt, wt_byte = 0;
140+
141+
for (int i = 0; i < PIPE_LEN; i += wt_byte) {
142+
/**TESTPOINT: pipe put*/
143+
to_wt = (PIPE_LEN - i) >= 24 ?
144+
24 : (PIPE_LEN - i);
145+
k_pipe_put(ppipe, &data[i], to_wt, &wt_byte, 1, timeout);
146+
}
147+
}
148+
149+
static void tpipe_get_small_size(struct k_pipe *ppipe, k_timeout_t timeout)
150+
{
151+
unsigned char rx_data[PIPE_LEN];
152+
size_t to_rd, rd_byte = 0;
153+
154+
/*get pipe data from "pipe_put"*/
155+
for (int i = 0; i < PIPE_LEN; i += rd_byte) {
156+
/**TESTPOINT: pipe get*/
157+
to_rd = (PIPE_LEN - i) >= 24 ?
158+
24 : (PIPE_LEN - i);
159+
zassert_false(k_pipe_get(ppipe, &rx_data[i], to_rd,
160+
&rd_byte, 1, timeout), NULL);
161+
}
162+
}
163+
164+
165+
/**
166+
* @brief Test Initialization and buffer allocation of pipe,
167+
* with various parameters
168+
* @see k_pipe_alloc_init(), k_pipe_cleanup()
169+
*/
170+
void test_pipe_alloc(void)
171+
{
172+
int ret;
173+
174+
zassert_false(k_pipe_alloc_init(&pipe_test_alloc, PIPE_LEN), NULL);
175+
176+
tpipe_kthread_to_kthread(&pipe_test_alloc);
177+
k_pipe_cleanup(&pipe_test_alloc);
178+
179+
zassert_false(k_pipe_alloc_init(&pipe_test_alloc, 0), NULL);
180+
k_pipe_cleanup(&pipe_test_alloc);
181+
182+
ret = k_pipe_alloc_init(&pipe_test_alloc, 2048);
183+
zassert_true(ret == -ENOMEM,
184+
"resource pool max block size is not smaller then requested buffer");
185+
}
186+
187+
static void thread_for_get_forever(void *p1, void *p2, void *p3)
188+
{
189+
tpipe_get((struct k_pipe *)p1, K_FOREVER);
190+
}
191+
192+
void test_pipe_cleanup(void)
193+
{
194+
int ret;
195+
196+
zassert_false(k_pipe_alloc_init(&pipe_test_alloc, PIPE_LEN), NULL);
197+
198+
/**TESTPOINT: test if a dynamically allocated buffer can be freed*/
199+
ret = k_pipe_cleanup(&pipe_test_alloc);
200+
zassert_true((ret == 0) && (pipe_test_alloc.buffer == NULL),
201+
"Failed to free buffer with k_pipe_cleanup().");
202+
203+
/**TESTPOINT: nothing to do with k_pipe_cleanup() for static buffer in pipe*/
204+
ret = k_pipe_cleanup(&kpipe);
205+
zassert_true((ret == 0) && (kpipe.buffer != NULL),
206+
"Static buffer should not be freed.");
207+
208+
zassert_false(k_pipe_alloc_init(&pipe_test_alloc, PIPE_LEN), NULL);
209+
210+
k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
211+
thread_for_get_forever, &pipe_test_alloc, NULL,
212+
NULL, K_PRIO_PREEMPT(0), 0, K_NO_WAIT);
213+
k_sleep(K_MSEC(100));
214+
215+
ret = k_pipe_cleanup(&pipe_test_alloc);
216+
zassert_true(ret == -EAGAIN, "k_pipe_cleanup() should not return with 0.");
217+
k_thread_abort(tid);
218+
}
219+
107220
static void thread_handler(void *p1, void *p2, void *p3)
108221
{
109222
tpipe_put_no_wait((struct k_pipe *)p1);
@@ -162,7 +275,6 @@ static void thread_handler(void *p1, void *p2, void *p3)
162275
void test_pipe_thread2thread(void)
163276
{
164277
/**TESTPOINT: test k_pipe_init pipe*/
165-
166278
k_pipe_init(&pipe, data, PIPE_LEN);
167279
tpipe_thread_thread(&pipe);
168280

@@ -189,27 +301,85 @@ void test_pipe_user_thread2thread(void)
189301
}
190302
#endif
191303

304+
/**
305+
* @brief Test resource pool free
306+
* @see k_heap_alloc()
307+
*/
308+
#ifdef CONFIG_USERSPACE
309+
void test_resource_pool_auto_free(void)
310+
{
311+
/* Pool has 2 blocks, both should succeed if kernel object and pipe
312+
* buffer are auto-freed when the allocating threads exit
313+
*/
314+
zassert_true(k_heap_alloc(&test_pool, 64, K_NO_WAIT) != NULL, NULL);
315+
zassert_true(k_heap_alloc(&test_pool, 64, K_NO_WAIT) != NULL, NULL);
316+
}
317+
#endif
318+
192319
static void tThread_half_pipe_put(void *p1, void *p2, void *p3)
193320
{
194321
tpipe_put((struct k_pipe *)p1, K_FOREVER);
195322
}
196323

324+
static void tThread_half_pipe_get(void *p1, void *p2, void *p3)
325+
{
326+
tpipe_get((struct k_pipe *)p1, K_FOREVER);
327+
}
328+
197329
/**
198-
* @brief Test get/put with smaller pipe buffer
330+
* @brief Test put/get with smaller pipe buffer
199331
* @see k_pipe_put(), k_pipe_get()
200332
*/
201-
void test_half_pipe_get_put(void)
333+
void test_half_pipe_put_get(void)
202334
{
203335
/**TESTPOINT: thread-thread data passing via pipe*/
204-
k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
336+
k_tid_t tid1 = k_thread_create(&tdata1, tstack1, STACK_SIZE,
337+
tThread_half_pipe_get, &khalfpipe,
338+
NULL, NULL, K_PRIO_PREEMPT(0),
339+
K_INHERIT_PERMS | K_USER, K_NO_WAIT);
340+
341+
k_tid_t tid2 = k_thread_create(&tdata2, tstack2, STACK_SIZE,
342+
tThread_half_pipe_get, &khalfpipe,
343+
NULL, NULL, K_PRIO_PREEMPT(0),
344+
K_INHERIT_PERMS | K_USER, K_NO_WAIT);
345+
346+
k_sleep(K_MSEC(100));
347+
tpipe_put_small_size(&khalfpipe, K_NO_WAIT);
348+
349+
/* clear the spawned thread avoid side effect */
350+
k_thread_abort(tid1);
351+
k_thread_abort(tid2);
352+
}
353+
354+
void test_pipe_get_put(void)
355+
{
356+
unsigned char rx_data[PIPE_LEN];
357+
size_t rd_byte = 0;
358+
int ret;
359+
360+
/* TESTPOINT: min_xfer > bytes_to_read */
361+
ret = k_pipe_get(&kpipe, &rx_data[0], 1, &rd_byte, 24, K_NO_WAIT);
362+
zassert_true(ret == -EINVAL, NULL);
363+
ret = k_pipe_get(&kpipe, &rx_data[0], 24, NULL, 1, K_NO_WAIT);
364+
zassert_true(ret == -EINVAL, NULL);
365+
366+
/**TESTPOINT: thread-thread data passing via pipe*/
367+
k_tid_t tid1 = k_thread_create(&tdata1, tstack1, STACK_SIZE,
368+
tThread_half_pipe_put, &khalfpipe,
369+
NULL, NULL, K_PRIO_PREEMPT(0),
370+
K_INHERIT_PERMS | K_USER, K_NO_WAIT);
371+
372+
k_tid_t tid2 = k_thread_create(&tdata2, tstack2, STACK_SIZE,
205373
tThread_half_pipe_put, &khalfpipe,
206374
NULL, NULL, K_PRIO_PREEMPT(0),
207375
K_INHERIT_PERMS | K_USER, K_NO_WAIT);
208376

209-
tpipe_get(&khalfpipe, K_FOREVER);
377+
k_sleep(K_MSEC(100));
378+
tpipe_get_small_size(&khalfpipe, K_NO_WAIT);
210379

211380
/* clear the spawned thread avoid side effect */
212-
k_thread_abort(tid);
381+
k_thread_abort(tid1);
382+
k_thread_abort(tid2);
213383
}
214384

215385
/**

0 commit comments

Comments
 (0)