From 67af6f88442e56d9632bf0e777abb41dbac73bf5 Mon Sep 17 00:00:00 2001 From: Sharron LIU Date: Wed, 30 Nov 2016 15:14:22 +0800 Subject: [PATCH] tests: kernel: added test_workq_api Change-Id: Iaadba1a720130a496a83c245c7da4b95dff168fd Signed-off-by: Sharron LIU Signed-off-by: Anas Nashif --- tests/kernel/workq/workq_api/Makefile | 4 + tests/kernel/workq/workq_api/prj.conf | 2 + tests/kernel/workq/workq_api/src/Makefile | 3 + tests/kernel/workq/workq_api/src/main.c | 50 ++++ .../workq/workq_api/src/test_workq_api.c | 281 ++++++++++++++++++ tests/kernel/workq/workq_api/testcase.ini | 2 + 6 files changed, 342 insertions(+) create mode 100644 tests/kernel/workq/workq_api/Makefile create mode 100644 tests/kernel/workq/workq_api/prj.conf create mode 100644 tests/kernel/workq/workq_api/src/Makefile create mode 100644 tests/kernel/workq/workq_api/src/main.c create mode 100644 tests/kernel/workq/workq_api/src/test_workq_api.c create mode 100644 tests/kernel/workq/workq_api/testcase.ini diff --git a/tests/kernel/workq/workq_api/Makefile b/tests/kernel/workq/workq_api/Makefile new file mode 100644 index 00000000000..4de50f93d4d --- /dev/null +++ b/tests/kernel/workq/workq_api/Makefile @@ -0,0 +1,4 @@ +BOARD ?= qemu_x86 +CONF_FILE = prj.conf + +include ${ZEPHYR_BASE}/Makefile.inc diff --git a/tests/kernel/workq/workq_api/prj.conf b/tests/kernel/workq/workq_api/prj.conf new file mode 100644 index 00000000000..9a75212e89d --- /dev/null +++ b/tests/kernel/workq/workq_api/prj.conf @@ -0,0 +1,2 @@ +CONFIG_ZTEST=y +CONFIG_IRQ_OFFLOAD=y diff --git a/tests/kernel/workq/workq_api/src/Makefile b/tests/kernel/workq/workq_api/src/Makefile new file mode 100644 index 00000000000..3c8f8239ae1 --- /dev/null +++ b/tests/kernel/workq/workq_api/src/Makefile @@ -0,0 +1,3 @@ +include $(ZEPHYR_BASE)/tests/Makefile.test + +obj-y = main.o test_workq_api.o diff --git a/tests/kernel/workq/workq_api/src/main.c b/tests/kernel/workq/workq_api/src/main.c new file mode 100644 index 00000000000..12995d77905 --- /dev/null +++ b/tests/kernel/workq/workq_api/src/main.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +extern void test_workq_start_before_submit(void); +extern void test_work_submit_to_queue_thread(void); +extern void test_work_submit_to_queue_isr(void); +extern void test_work_submit_thread(void); +extern void test_work_submit_isr(void); +extern void test_delayed_work_submit_to_queue_thread(void); +extern void test_delayed_work_submit_to_queue_isr(void); +extern void test_delayed_work_submit_thread(void); +extern void test_delayed_work_submit_isr(void); +extern void test_delayed_work_cancel_from_queue_thread(void); +extern void test_delayed_work_cancel_from_queue_isr(void); +extern void test_delayed_work_cancel_thread(void); +extern void test_delayed_work_cancel_isr(void); + +/*test case main entry*/ +void test_main(void *p1, void *p2, void *p3) +{ + ztest_test_suite(test_workq_api, + ztest_unit_test(test_workq_start_before_submit),/*keep first!*/ + ztest_unit_test(test_work_submit_to_queue_thread), + ztest_unit_test(test_work_submit_to_queue_isr), + ztest_unit_test(test_work_submit_thread), + ztest_unit_test(test_work_submit_isr), + ztest_unit_test(test_delayed_work_submit_to_queue_thread), + ztest_unit_test(test_delayed_work_submit_to_queue_isr), + ztest_unit_test(test_delayed_work_submit_thread), + ztest_unit_test(test_delayed_work_submit_isr), + ztest_unit_test(test_delayed_work_cancel_from_queue_thread), + ztest_unit_test(test_delayed_work_cancel_from_queue_isr), + ztest_unit_test(test_delayed_work_cancel_thread), + ztest_unit_test(test_delayed_work_cancel_isr)); + ztest_run_test_suite(test_workq_api); +} diff --git a/tests/kernel/workq/workq_api/src/test_workq_api.c b/tests/kernel/workq/workq_api/src/test_workq_api.c new file mode 100644 index 00000000000..425431aaaba --- /dev/null +++ b/tests/kernel/workq/workq_api/src/test_workq_api.c @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND + , either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @addtogroup t_workq + * @{ + * @defgroup t_workq_api test_workq_api + * @brief TestPurpose: verify work queue API functionalities + * - API coverage + * -# k_work_init + * -# k_delayed_work_init + * -# k_work_q_start + * -# k_work_submit_to_queue + * -# k_work_submit + * -# k_delayed_work_submit_to_queue + * -# k_delayed_work_submit + * -# k_delayed_work_cancel + * -# k_work_pending + * -# + * @} + */ + +#include +#include + +#define TIMEOUT 100 +#define STACK_SIZE 512 +#define NUM_OF_WORK 2 + +static char __noinit __stack tstack[STACK_SIZE]; +static struct k_work_q workq; +static struct k_work work[NUM_OF_WORK]; +static struct k_delayed_work delayed_work[NUM_OF_WORK], delayed_work_sleepy; +static struct k_sem sync_sema; + +static void work_sleepy(struct k_work *w) +{ + k_sleep(TIMEOUT); + k_sem_give(&sync_sema); +} + +static void work_handler(struct k_work *w) +{ + k_sem_give(&sync_sema); +} + +static void twork_submit(void *data) +{ + struct k_work_q *work_q = (struct k_work_q *)data; + + for (int i = 0; i < NUM_OF_WORK; i++) { + /**TESTPOINT: init via k_work_init*/ + k_work_init(&work[i], work_handler); + /**TESTPOINT: check pending after work init*/ + assert_false(k_work_pending(&work[i]), NULL); + if (work_q) { + /**TESTPOINT: work submit to queue*/ + k_work_submit_to_queue(work_q, &work[i]); + } else { + /**TESTPOINT: work submit to system queue*/ + k_work_submit(&work[i]); + } + } +} + +static void tdelayed_work_submit(void *data) +{ + struct k_work_q *work_q = (struct k_work_q *)data; + + for (int i = 0; i < NUM_OF_WORK; i++) { + /**TESTPOINT: init via k_delayed_work_init*/ + k_delayed_work_init(&delayed_work[i], work_handler); + /**TESTPOINT: check pending after delayed work init*/ + assert_false(k_work_pending((struct k_work *)&delayed_work[i]), + NULL); + if (work_q) { + /**TESTPOINT: delayed work submit to queue*/ + assert_true(k_delayed_work_submit_to_queue(work_q, + &delayed_work[i], TIMEOUT) == 0, NULL); + } else { + /**TESTPOINT: delayed work submit to system queue*/ + assert_true(k_delayed_work_submit(&delayed_work[i], + TIMEOUT) == 0, NULL); + } + /**TESTPOINT: check pending after delayed work submit*/ + assert_true(k_work_pending((struct k_work *)&delayed_work[i]) + == 0, NULL); + } +} + +static void tdelayed_work_cancel(void *data) +{ + struct k_work_q *work_q = (struct k_work_q *)data; + int ret; + + k_delayed_work_init(&delayed_work_sleepy, work_sleepy); + k_delayed_work_init(&delayed_work[0], work_handler); + k_delayed_work_init(&delayed_work[1], work_handler); + + if (work_q) { + ret = k_delayed_work_submit_to_queue(work_q, + &delayed_work_sleepy, TIMEOUT); + ret |= k_delayed_work_submit_to_queue(work_q, &delayed_work[0], + TIMEOUT); + ret |= k_delayed_work_submit_to_queue(work_q, &delayed_work[1], + TIMEOUT); + } else { + ret = k_delayed_work_submit(&delayed_work_sleepy, TIMEOUT); + ret |= k_delayed_work_submit(&delayed_work[0], TIMEOUT); + ret |= k_delayed_work_submit(&delayed_work[1], TIMEOUT); + } + /* + * t0: delayed submit three work items, all with delay=TIMEOUT + * >t0: cancel delayed_work[0], expected cancellation success + * >t0+TIMEOUT: handling delayed_work_sleepy, which do k_sleep TIMEOUT + * pending delayed_work[1], check pending flag, expected 1 + * cancel delayed_work[1], expected -EINPROGRESS + * >t0+2*TIMEOUT: delayed_work_sleepy completed + * delayed_work[1] completed + * cancel delayed_work_sleepy, expected -EINVAL + */ + assert_true(ret == 0, NULL); + /**TESTPOINT: delayed work cancel when countdown*/ + ret = k_delayed_work_cancel(&delayed_work[0]); + assert_true(ret == 0, NULL); + /**TESTPOINT: check pending after delayed work cancel*/ + assert_false(k_work_pending((struct k_work *)&delayed_work[0]), NULL); + if (!k_is_in_isr()) { + /*wait for handling work_sleepy*/ + k_sleep(TIMEOUT); + /**TESTPOINT: check pending when work pending*/ + assert_true(k_work_pending((struct k_work *)&delayed_work[1]), + NULL); + /**TESTPOINT: delayed work cancel when pending*/ + ret = k_delayed_work_cancel(&delayed_work[1]); + assert_equal(ret, -EINPROGRESS, NULL); + /*wait for completed work_sleepy and delayed_work[1]*/ + k_sleep(TIMEOUT); + /**TESTPOINT: check pending when work completed*/ + assert_false(k_work_pending( + (struct k_work *)&delayed_work_sleepy), NULL); + /**TESTPOINT: delayed work cancel when completed*/ + ret = k_delayed_work_cancel(&delayed_work_sleepy); + assert_equal(ret, -EINVAL, NULL); + } + /*work items not cancelled: delayed_work[1], delayed_work_sleepy*/ +} + +/*test cases*/ +void test_workq_start_before_submit(void) +{ + k_sem_init(&sync_sema, 0, NUM_OF_WORK); + k_work_q_start(&workq, tstack, STACK_SIZE, + CONFIG_MAIN_THREAD_PRIORITY); +} + +void test_work_submit_to_queue_thread(void) +{ + k_sem_reset(&sync_sema); + twork_submit(&workq); + for (int i = 0; i < NUM_OF_WORK; i++) { + k_sem_take(&sync_sema, K_FOREVER); + } +} + +void test_work_submit_to_queue_isr(void) +{ + k_sem_reset(&sync_sema); + irq_offload(twork_submit, (void *)&workq); + for (int i = 0; i < NUM_OF_WORK; i++) { + k_sem_take(&sync_sema, K_FOREVER); + } +} + +void test_work_submit_thread(void) +{ + k_sem_reset(&sync_sema); + twork_submit(NULL); + for (int i = 0; i < NUM_OF_WORK; i++) { + k_sem_take(&sync_sema, K_FOREVER); + } +} + +void test_work_submit_isr(void) +{ + k_sem_reset(&sync_sema); + irq_offload(twork_submit, NULL); + for (int i = 0; i < NUM_OF_WORK; i++) { + k_sem_take(&sync_sema, K_FOREVER); + } +} + +void test_delayed_work_submit_to_queue_thread(void) +{ + k_sem_reset(&sync_sema); + tdelayed_work_submit(&workq); + for (int i = 0; i < NUM_OF_WORK; i++) { + k_sem_take(&sync_sema, K_FOREVER); + } +} + +void test_delayed_work_submit_to_queue_isr(void) +{ + k_sem_reset(&sync_sema); + irq_offload(tdelayed_work_submit, (void *)&workq); + for (int i = 0; i < NUM_OF_WORK; i++) { + k_sem_take(&sync_sema, K_FOREVER); + } +} + +void test_delayed_work_submit_thread(void) +{ + k_sem_reset(&sync_sema); + tdelayed_work_submit(NULL); + for (int i = 0; i < NUM_OF_WORK; i++) { + k_sem_take(&sync_sema, K_FOREVER); + } +} + +void test_delayed_work_submit_isr(void) +{ + k_sem_reset(&sync_sema); + irq_offload(tdelayed_work_submit, NULL); + for (int i = 0; i < NUM_OF_WORK; i++) { + k_sem_take(&sync_sema, K_FOREVER); + } +} + +void test_delayed_work_cancel_from_queue_thread(void) +{ + k_sem_reset(&sync_sema); + tdelayed_work_cancel(&workq); + /*wait for work items that could not be cancelled*/ + for (int i = 0; i < NUM_OF_WORK; i++) { + k_sem_take(&sync_sema, K_FOREVER); + } +} + +void test_delayed_work_cancel_from_queue_isr(void) +{ + k_sem_reset(&sync_sema); + irq_offload(tdelayed_work_cancel, &workq); + /*wait for work items that could not be cancelled*/ + for (int i = 0; i < NUM_OF_WORK; i++) { + k_sem_take(&sync_sema, K_FOREVER); + } +} + +void test_delayed_work_cancel_thread(void) +{ + k_sem_reset(&sync_sema); + tdelayed_work_cancel(NULL); + /*wait for work items that could not be cancelled*/ + for (int i = 0; i < NUM_OF_WORK; i++) { + k_sem_take(&sync_sema, K_FOREVER); + } +} + +void test_delayed_work_cancel_isr(void) +{ + k_sem_reset(&sync_sema); + irq_offload(tdelayed_work_cancel, NULL); + /*wait for work items that could not be cancelled*/ + for (int i = 0; i < NUM_OF_WORK; i++) { + k_sem_take(&sync_sema, K_FOREVER); + } +} diff --git a/tests/kernel/workq/workq_api/testcase.ini b/tests/kernel/workq/workq_api/testcase.ini new file mode 100644 index 00000000000..58c4d1a1747 --- /dev/null +++ b/tests/kernel/workq/workq_api/testcase.ini @@ -0,0 +1,2 @@ +[test] +tags = kernel