diff --git a/tests/kernel/pipe/pipe/src/main.c b/tests/kernel/pipe/pipe/src/main.c index 57a9650df10287..83b9e839986f0e 100644 --- a/tests/kernel/pipe/pipe/src/main.c +++ b/tests/kernel/pipe/pipe/src/main.c @@ -17,8 +17,10 @@ extern void test_pipe_get_invalid_size(void); extern void test_pipe_get_min_xfer(void); extern void test_pipe_put_min_xfer(void); extern void test_pipe_define_at_runtime(void); +extern void test_pipe_flush(void); extern struct k_pipe test_pipe; +extern struct k_pipe small_pipe; extern struct k_sem put_sem, get_sem, sync_sem, multiple_send_sem; extern struct k_stack stack_1; extern struct k_thread get_single_tid; @@ -27,7 +29,7 @@ extern struct k_thread get_single_tid; void test_main(void) { k_thread_access_grant(k_current_get(), - &test_pipe, &put_sem, &get_sem, + &test_pipe, &small_pipe, &put_sem, &get_sem, &sync_sem, &multiple_send_sem, &get_single_tid, &stack_1); @@ -42,7 +44,8 @@ void test_main(void) ztest_user_unit_test(test_pipe_get_invalid_size), ztest_user_unit_test(test_pipe_get_min_xfer), ztest_user_unit_test(test_pipe_put_min_xfer), - ztest_unit_test(test_pipe_define_at_runtime) + ztest_unit_test(test_pipe_define_at_runtime), + ztest_unit_test(test_pipe_flush) ); ztest_run_test_suite(test_pipe); diff --git a/tests/kernel/pipe/pipe/src/test_pipe.c b/tests/kernel/pipe/pipe/src/test_pipe.c index b1a20c40efc51a..1f33285581613e 100644 --- a/tests/kernel/pipe/pipe/src/test_pipe.c +++ b/tests/kernel/pipe/pipe/src/test_pipe.c @@ -14,6 +14,8 @@ K_PIPE_DEFINE(test_pipe, 256, 4); #define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACKSIZE) #define PIPE_SIZE (256) +K_PIPE_DEFINE(small_pipe, 10, 4); + K_THREAD_STACK_DEFINE(stack_1, STACK_SIZE); K_SEM_DEFINE(get_sem, 0, 1); @@ -1024,3 +1026,131 @@ void test_pipe_define_at_runtime(void) PIPE_SIZE, &read, PIPE_SIZE, TIMEOUT_VAL), -EAGAIN, NULL); } + +/** + * @brief Helper thread to test k_pipe_flush() and k_pipe_buffer_flush() + * + * This helper thread attempts to write 50 bytes to the pipe identified by + * [p1], which has an internal buffer size of 10. This helper thread is + * expected to fill the internal buffer, and then block until it can complete + * the write. + */ +void test_pipe_flush_helper(void *p1, void *p2, void *p3) +{ + struct k_pipe *pipe = (struct k_pipe *)p1; + char buffer[50]; + size_t i; + size_t bytes_written; + int rv; + + for (i = 0; i < sizeof(buffer); i++) { + buffer[i] = i; + } + + rv = k_pipe_put(pipe, buffer, sizeof(buffer), &bytes_written, + sizeof(buffer), K_FOREVER); + + zassert_true(rv == 0, "k_pipe_put() failed with %d", rv); + zassert_true(bytes_written == sizeof(buffer), + "Expected %zu bytes written, not %zu", + sizeof(buffer), bytes_written); +} + +/** + * @brief Test flushing a pipe + * + * @ingroup kernel_pipe_tests + * + * @details + * Test Objective: + * - Check if the kernel flushes a pipe properly at runtime. + * + * Testing techniques: + * - function and block box testing,Interface testing, + * Dynamic analysis and testing. + * + * Prerequisite Conditions: + * - CONFIG_TEST_USERSPACE. + * + * Input Specifications: + * - N/A + * + * Test Procedure: + * -# Define and initialize a pipe at run time + * -# Use this pipe to transfer data. + * -# Have a thread fill and block on writing to the pipe + * -# Flush the pipe and check that the pipe is completely empty + * -# Have a thread fill and block on writing to the pipe + * -# Flush only the pipe's buffer and check the results + * + * Expected Test Result: + * - Reading from the pipe after k_pipe_flush() results in no data to read. + * - Reading from the pipe after k_pipe_buffer_flush() results in read data, + * but missing the original data that was in the buffer prior to the flush. + * + * Pass/Fail Criteria: + * - Successful if check points in test procedure are all passed, otherwise + * failure. + * + * Assumptions and Constraints: + * - N/A + */ +void test_pipe_flush(void) +{ + unsigned char results_buffer[50]; + size_t bytes_read; + size_t i; + int rv; + + memset(results_buffer, 0, sizeof(results_buffer)); + + (void)k_thread_create(&get_single_tid, stack_1, STACK_SIZE, + test_pipe_flush_helper, &small_pipe, NULL, NULL, + K_PRIO_PREEMPT(0), K_INHERIT_PERMS | K_USER, + K_NO_WAIT); + + k_sleep(K_MSEC(50)); /* give helper thread time to execute */ + + /* Completely flush the pipe */ + + k_pipe_flush(&small_pipe); + + rv = k_pipe_get(&small_pipe, results_buffer, sizeof(results_buffer), + &bytes_read, 0, K_MSEC(100)); + + zassert_true(rv == 0, "k_pipe_get() failed with %d\n", rv); + zassert_true(bytes_read == 0, + "k_pipe_get() unexpectedly read %zu bytes\n", bytes_read); + + rv = k_thread_join(&get_single_tid, K_MSEC(50)); + zassert_true(rv == 0, "Wait for helper thread failed (%d)", rv); + + (void)k_thread_create(&get_single_tid, stack_1, STACK_SIZE, + test_pipe_flush_helper, &small_pipe, NULL, NULL, + K_PRIO_PREEMPT(0), K_INHERIT_PERMS | K_USER, + K_NO_WAIT); + + k_sleep(K_MSEC(50)); /* give helper thread time to execute */ + + /* + * Only flush the pipe's buffer. This is expected to leave 40 bytes + * left to receive. + */ + + k_pipe_buffer_flush(&small_pipe); + + rv = k_pipe_get(&small_pipe, results_buffer, sizeof(results_buffer), + &bytes_read, 0, K_MSEC(100)); + + zassert_true(rv == 0, "k_pipe_get() failed with %d\n", rv); + zassert_true(bytes_read == 40, + "k_pipe_get() unexpectedly read %zu bytes\n", bytes_read); + for (i = 0; i < 40; i++) { + zassert_true(results_buffer[i] == (unsigned char)(i + 10), + "At offset %zd, expected byte %02x, not %02x\n", + i, (i + 10), results_buffer[i]); + } + + rv = k_thread_join(&get_single_tid, K_MSEC(50)); + zassert_true(rv == 0, "Wait for helper thread failed (%d)", rv); +}