1 /*
2  * Copyright (c) 2025 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/ztest.h>
9 
10 #define TEST_WORK_TIMEOUT_MS     100
11 #define TEST_WORK_DURATION_MS    (TEST_WORK_TIMEOUT_MS / 2)
12 #define TEST_WORK_DELAY          K_MSEC(TEST_WORK_DURATION_MS * 6)
13 #define TEST_WORK_BLOCKING_DELAY K_MSEC(TEST_WORK_TIMEOUT_MS * 2)
14 
15 static struct k_work_q test_workq;
16 static K_KERNEL_STACK_DEFINE(test_workq_stack, CONFIG_MAIN_STACK_SIZE);
17 
test_work_handler(struct k_work * work)18 static void test_work_handler(struct k_work *work)
19 {
20 	k_msleep(TEST_WORK_DURATION_MS);
21 }
22 
23 static K_WORK_DEFINE(test_work0, test_work_handler);
24 static K_WORK_DEFINE(test_work1, test_work_handler);
25 static K_WORK_DEFINE(test_work2, test_work_handler);
26 static K_WORK_DEFINE(test_work3, test_work_handler);
27 
test_work_handler_blocking(struct k_work * work)28 static void test_work_handler_blocking(struct k_work *work)
29 {
30 	k_sleep(K_FOREVER);
31 }
32 
33 static K_WORK_DEFINE(test_work_blocking, test_work_handler_blocking);
34 
test_setup(void)35 static void *test_setup(void)
36 {
37 	const struct k_work_queue_config config = {
38 		.name = "sysworkq",
39 		.no_yield = false,
40 		.essential = false,
41 		.work_timeout_ms = TEST_WORK_TIMEOUT_MS,
42 	};
43 
44 	k_work_queue_start(&test_workq,
45 			   test_workq_stack,
46 			   K_KERNEL_STACK_SIZEOF(test_workq_stack),
47 			   0,
48 			   &config);
49 
50 	return NULL;
51 }
52 
53 ZTEST_SUITE(workqueue_work_timeout, NULL, test_setup, NULL, NULL, NULL);
54 
ZTEST(workqueue_work_timeout,test_work)55 ZTEST(workqueue_work_timeout, test_work)
56 {
57 	int ret;
58 
59 	/* Submit multiple items which take less time than TEST_WORK_TIMEOUT_MS each */
60 	zassert_equal(k_work_submit_to_queue(&test_workq, &test_work0), 1);
61 	zassert_equal(k_work_submit_to_queue(&test_workq, &test_work1), 1);
62 	zassert_equal(k_work_submit_to_queue(&test_workq, &test_work2), 1);
63 	zassert_equal(k_work_submit_to_queue(&test_workq, &test_work3), 1);
64 
65 	/*
66 	 * Submitted items takes longer than TEST_WORK_TIMEOUT_MS, but each item takes
67 	 * less time than TEST_WORK_DELAY so workqueue thread will not be aborted.
68 	 */
69 	zassert_equal(k_thread_join(&test_workq.thread, TEST_WORK_DELAY), -EAGAIN);
70 
71 	/* Submit single item which takes longer than TEST_WORK_TIMEOUT_MS */
72 	zassert_equal(k_work_submit_to_queue(&test_workq, &test_work_blocking), 1);
73 
74 	/*
75 	 * Submitted item shall cause the work to time out and the workqueue thread be
76 	 * aborted if CONFIG_WORKQUEUE_WORK_TIMEOUT is enabled.
77 	 */
78 	ret = k_thread_join(&test_workq.thread, TEST_WORK_BLOCKING_DELAY);
79 	if (IS_ENABLED(CONFIG_WORKQUEUE_WORK_TIMEOUT)) {
80 		zassert_equal(ret, 0);
81 	} else {
82 		zassert_equal(ret, -EAGAIN);
83 	}
84 }
85