-
Notifications
You must be signed in to change notification settings - Fork 7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tests: socket: socketpair: tests for socketpair(2) syscall
Tests for issue #24366 Signed-off-by: Christopher Friedt <chrisfriedt@gmail.com>
- Loading branch information
1 parent
09f957c
commit 3bfc765
Showing
14 changed files
with
1,224 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
cmake_minimum_required(VERSION 3.13.1) | ||
find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) | ||
project(socketpair) | ||
|
||
FILE(GLOB app_sources src/*.c) | ||
target_sources(app PRIVATE ${app_sources}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
CONFIG_MP_NUM_CPUS=1 | ||
|
||
# General config | ||
CONFIG_NEWLIB_LIBC=y | ||
|
||
# Networking config | ||
CONFIG_NETWORKING=y | ||
CONFIG_NET_TEST=y | ||
CONFIG_NET_LOOPBACK=y | ||
CONFIG_NET_IPV4=y | ||
CONFIG_NET_IPV6=y | ||
CONFIG_NET_SOCKETS=y | ||
CONFIG_NET_SOCKETPAIR=y | ||
CONFIG_NET_SOCKETPAIR_BUFFER_SIZE=64 | ||
CONFIG_NET_SOCKETS_POSIX_NAMES=y | ||
# Defines fd_set size | ||
CONFIG_POSIX_MAX_FDS=33 | ||
|
||
# Network driver config | ||
CONFIG_TEST_RANDOM_GENERATOR=y | ||
|
||
# Network address config | ||
CONFIG_NET_CONFIG_SETTINGS=y | ||
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1" | ||
CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1" | ||
|
||
CONFIG_MAIN_STACK_SIZE=2048 | ||
CONFIG_ZTEST=y | ||
|
||
# User mode requirements | ||
CONFIG_TEST_USERSPACE=y | ||
CONFIG_HEAP_MEM_POOL_SIZE=2048 | ||
|
||
CONFIG_QEMU_TICKLESS_WORKAROUND=y |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/* | ||
* Copyright (c) 2020 Friedt Professional Engineering Services, Inc | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <ztest.h> | ||
|
||
/* in happy_path.c */ | ||
extern void test_socketpair_AF_LOCAL__SOCK_STREAM__0(void); | ||
extern void test_socketpair_AF_UNIX__SOCK_STREAM__0(void); | ||
|
||
/* in nonblock.c */ | ||
extern void test_socketpair_write_nonblock(void); | ||
extern void test_socketpair_read_nonblock(void); | ||
|
||
/* in block.c */ | ||
extern void test_socketpair_write_block(void); | ||
extern void test_socketpair_read_block(void); | ||
|
||
/* in closed_ends.c */ | ||
extern void test_socketpair_close_one_end_and_write_to_the_other(void); | ||
extern void test_socketpair_close_one_end_and_read_from_the_other(void); | ||
|
||
/* in expected_failures.c */ | ||
extern void test_socketpair_expected_failures(void); | ||
|
||
/* in unsupported_calls.c */ | ||
extern void test_socketpair_unsupported_calls(void); | ||
|
||
/* in fcntl.c */ | ||
extern void test_socketpair_fcntl(void); | ||
|
||
/* in poll.c */ | ||
extern void test_socketpair_poll_timeout(void); | ||
extern void test_socketpair_poll_timeout_nonblocking(void); | ||
extern void test_socketpair_poll_close_remote_end_POLLIN(void); | ||
extern void test_socketpair_poll_close_remote_end_POLLOUT(void); | ||
extern void test_socketpair_poll_immediate_data(void); | ||
extern void test_socketpair_poll_delayed_data(void); | ||
|
||
void test_main(void) | ||
{ | ||
k_thread_system_pool_assign(k_current_get()); | ||
|
||
ztest_test_suite( | ||
socketpair, | ||
ztest_user_unit_test(test_socketpair_AF_LOCAL__SOCK_STREAM__0), | ||
ztest_user_unit_test(test_socketpair_AF_UNIX__SOCK_STREAM__0), | ||
|
||
ztest_user_unit_test(test_socketpair_write_nonblock), | ||
ztest_user_unit_test(test_socketpair_read_nonblock), | ||
|
||
ztest_user_unit_test( | ||
test_socketpair_close_one_end_and_write_to_the_other), | ||
ztest_user_unit_test( | ||
test_socketpair_close_one_end_and_read_from_the_other), | ||
|
||
ztest_user_unit_test(test_socketpair_expected_failures), | ||
|
||
ztest_user_unit_test(test_socketpair_unsupported_calls), | ||
|
||
ztest_user_unit_test(test_socketpair_fcntl), | ||
|
||
ztest_user_unit_test(test_socketpair_poll_timeout), | ||
ztest_user_unit_test( | ||
test_socketpair_poll_timeout_nonblocking), | ||
ztest_user_unit_test(test_socketpair_poll_immediate_data) | ||
); | ||
|
||
ztest_run_test_suite(socketpair); | ||
|
||
/* 20200509: @cfriedt: experiencing some issues with userspace thread | ||
* / memory permissions that will require some sorting out. Currently | ||
* these tests succeeed for native_posix_64. | ||
* | ||
* This feature is experimental at present. | ||
*/ | ||
#if 0 | ||
ztest_test_suite( | ||
socketpair_only_kernel, | ||
ztest_user_unit_test(test_socketpair_write_block), | ||
ztest_user_unit_test(test_socketpair_read_block), | ||
ztest_user_unit_test(test_socketpair_poll_delayed_data), | ||
ztest_user_unit_test( | ||
test_socketpair_poll_close_remote_end_POLLIN), | ||
ztest_user_unit_test( | ||
test_socketpair_poll_close_remote_end_POLLOUT) | ||
); | ||
|
||
ztest_run_test_suite(socketpair_only_kernel); | ||
#endif | ||
} |
194 changes: 194 additions & 0 deletions
194
tests/net/socket/socketpair/src/test_socketpair_block.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
/* | ||
* Copyright (c) 2020 Friedt Professional Engineering Services, Inc | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <fcntl.h> | ||
#include <string.h> | ||
|
||
#include <logging/log.h> | ||
LOG_MODULE_REGISTER(net_test, CONFIG_NET_SOCKETS_LOG_LEVEL); | ||
|
||
#include <net/socket.h> | ||
#include <sys/util.h> | ||
#include <posix/unistd.h> | ||
|
||
#include <ztest_assert.h> | ||
|
||
#undef read | ||
#define read(fd, buf, len) zsock_recv(fd, buf, len, 0) | ||
|
||
#undef write | ||
#define write(fd, buf, len) zsock_send(fd, buf, len, 0) | ||
|
||
#define TIMEOUT K_FOREVER | ||
|
||
struct ctx { | ||
/* true if test is write_block(), false if test is read_block() */ | ||
bool write; | ||
/* the secondary-side socket of the socketpair */ | ||
int fd; | ||
/* the count of the main thread */ | ||
atomic_t m; | ||
/* the count of the secondary thread */ | ||
size_t n; | ||
/* true when secondary thread is done */ | ||
bool done; | ||
/* true if both main and secondary thread should immediately quit */ | ||
bool fail; | ||
/* thread id of the secondary thread */ | ||
k_tid_t tid; | ||
}; | ||
ZTEST_BMEM struct ctx ctx; | ||
#define STACK_SIZE 512 | ||
/* thread structure for secondary thread */ | ||
ZTEST_BMEM struct k_thread th; | ||
/* stack for the secondary thread */ | ||
static K_THREAD_STACK_DEFINE(th_stack, STACK_SIZE); | ||
|
||
static void th_fun(void *arg0, void *arg1, void *arg2) | ||
{ | ||
(void) arg0; | ||
(void) arg1; | ||
(void) arg2; | ||
|
||
int res; | ||
char c = '\0'; | ||
|
||
LOG_DBG("secondary thread running"); | ||
|
||
while (true) { | ||
if (ctx.write) { | ||
LOG_DBG("ctx.m: %u", ctx.m); | ||
if (atomic_get(&ctx.m) | ||
< CONFIG_NET_SOCKETPAIR_BUFFER_SIZE) { | ||
continue; | ||
} | ||
LOG_DBG("ready to read!"); | ||
} else { | ||
LOG_DBG("sleeping for 100ms.."); | ||
k_sleep(K_MSEC(100)); | ||
LOG_DBG("ready to write!"); | ||
} | ||
break; | ||
} | ||
|
||
LOG_DBG("%sing 1 byte %s fd %d", ctx.write ? "read" : "write", | ||
ctx.write ? "from" : "to", ctx.fd); | ||
if (ctx.write) { | ||
res = read(ctx.fd, &c, 1); | ||
} else { | ||
res = write(ctx.fd, "x", 1); | ||
} | ||
if (-1 == res || 1 != res) { | ||
LOG_DBG("%s(2) failed: %d", ctx.write ? "read" : "write", | ||
errno); | ||
goto out; | ||
} | ||
LOG_DBG("%s 1 byte", ctx.write ? "read" : "wrote"); | ||
ctx.n = 1; | ||
|
||
out: | ||
ctx.done = true; | ||
|
||
LOG_DBG("terminating.."); | ||
} | ||
|
||
void test_socketpair_write_block(void) | ||
{ | ||
int res; | ||
int sv[2] = {-1, -1}; | ||
|
||
LOG_DBG("creating socketpair.."); | ||
res = socketpair(AF_UNIX, SOCK_STREAM, 0, sv); | ||
zassert_equal(res, 0, "socketpair(2) failed: %d", errno); | ||
|
||
for (size_t i = 0; i < 2; ++i) { | ||
|
||
LOG_DBG("data direction %d -> %d", sv[i], sv[(!i) & 1]); | ||
|
||
LOG_DBG("setting up context"); | ||
memset(&ctx, 0, sizeof(ctx)); | ||
ctx.write = true; | ||
ctx.fd = sv[(!i) & 1]; | ||
|
||
LOG_DBG("creating secondary thread"); | ||
ctx.tid = k_thread_create(&th, th_stack, | ||
STACK_SIZE, th_fun, | ||
NULL, NULL, NULL, | ||
CONFIG_MAIN_THREAD_PRIORITY, | ||
K_INHERIT_PERMS, K_NO_WAIT); | ||
LOG_DBG("created secondary thread %p", ctx.tid); | ||
|
||
/* fill up the buffer */ | ||
for (ctx.m = 0; atomic_get(&ctx.m) | ||
< CONFIG_NET_SOCKETPAIR_BUFFER_SIZE;) { | ||
|
||
res = write(sv[i], "x", 1); | ||
zassert_not_equal(res, -1, "write(2) failed: %d", | ||
errno); | ||
zassert_equal(res, 1, "wrote %d bytes instead of 1", | ||
res); | ||
|
||
atomic_inc(&ctx.m); | ||
LOG_DBG("have written %u bytes", ctx.m); | ||
} | ||
|
||
/* try to write one more byte */ | ||
LOG_DBG("writing to fd %d", sv[i]); | ||
res = write(sv[i], "x", 1); | ||
zassert_not_equal(res, -1, "write(2) failed: %d", errno); | ||
zassert_equal(res, 1, "wrote %d bytes instead of 1", res); | ||
|
||
LOG_DBG("success!"); | ||
|
||
k_thread_join(&th, K_MSEC(1000)); | ||
} | ||
|
||
close(sv[0]); | ||
close(sv[1]); | ||
} | ||
|
||
void test_socketpair_read_block(void) | ||
{ | ||
int res; | ||
int sv[2] = {-1, -1}; | ||
char x; | ||
|
||
LOG_DBG("creating socketpair.."); | ||
res = socketpair(AF_UNIX, SOCK_STREAM, 0, sv); | ||
zassert_equal(res, 0, "socketpair(2) failed: %d", errno); | ||
|
||
for (size_t i = 0; i < 2; ++i) { | ||
|
||
LOG_DBG("data direction %d -> %d", sv[i], sv[(!i) & 1]); | ||
|
||
LOG_DBG("setting up context"); | ||
memset(&ctx, 0, sizeof(ctx)); | ||
ctx.write = false; | ||
ctx.fd = sv[(!i) & 1]; | ||
|
||
LOG_DBG("creating secondary thread"); | ||
ctx.tid = k_thread_create(&th, th_stack, | ||
STACK_SIZE, th_fun, | ||
NULL, NULL, NULL, | ||
CONFIG_MAIN_THREAD_PRIORITY, | ||
K_INHERIT_PERMS, K_NO_WAIT); | ||
LOG_DBG("created secondary thread %p", ctx.tid); | ||
|
||
/* try to read one byte */ | ||
LOG_DBG("reading from fd %d", sv[i]); | ||
x = '\0'; | ||
res = read(sv[i], &x, 1); | ||
zassert_not_equal(res, -1, "read(2) failed: %d", errno); | ||
zassert_equal(res, 1, "read %d bytes instead of 1", res); | ||
|
||
LOG_DBG("success!"); | ||
|
||
k_thread_join(&th, K_MSEC(1000)); | ||
} | ||
|
||
close(sv[0]); | ||
close(sv[1]); | ||
} |
Oops, something went wrong.