Skip to content

Commit 3bfc765

Browse files
cfriedtcarlescufi
authored andcommitted
tests: socket: socketpair: tests for socketpair(2) syscall
Tests for issue #24366 Signed-off-by: Christopher Friedt <[email protected]>
1 parent 09f957c commit 3bfc765

14 files changed

+1224
-3
lines changed

CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,7 @@
498498
/tests/net/lib/http_header_fields/ @jukkar @tbursztyka
499499
/tests/net/lib/mqtt_packet/ @jukkar @tbursztyka
500500
/tests/net/lib/coap/ @rveerama1
501+
/tests/net/socket/socketpair/ @cfriedt
501502
/tests/net/socket/ @jukkar @tbursztyka @pfalcon
502503
/tests/subsys/fs/ @nashif @wentongwu
503504
/tests/subsys/settings/ @nvlsianpu

subsys/net/lib/sockets/socketpair.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ static ssize_t spair_write(void *obj, const void *buffer, size_t count)
568568
*/
569569
static ssize_t spair_read(void *obj, void *buffer, size_t count)
570570
{
571-
ssize_t res;
571+
int res;
572572

573573
bool is_connected;
574574
size_t avail;
@@ -783,7 +783,7 @@ static int zsock_poll_update_ctx(struct spair *const spair,
783783
if (pfd->events & ZSOCK_POLLOUT) {
784784
if (!sock_is_connected(spair)) {
785785
pfd->revents |= ZSOCK_POLLHUP;
786-
goto check_pollin;
786+
goto pollout_done;
787787
}
788788

789789
remote = z_get_fd_obj(spair->remote,
@@ -850,7 +850,6 @@ static int zsock_poll_update_ctx(struct spair *const spair,
850850

851851
(*pev)++;
852852

853-
out:
854853
if (remote != NULL && have_remote_sem) {
855854
k_sem_give(&remote->sem);
856855
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.13.1)
4+
find_package(Zephyr HINTS $ENV{ZEPHYR_BASE})
5+
project(socketpair)
6+
7+
FILE(GLOB app_sources src/*.c)
8+
target_sources(app PRIVATE ${app_sources})
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
CONFIG_MP_NUM_CPUS=1
2+
3+
# General config
4+
CONFIG_NEWLIB_LIBC=y
5+
6+
# Networking config
7+
CONFIG_NETWORKING=y
8+
CONFIG_NET_TEST=y
9+
CONFIG_NET_LOOPBACK=y
10+
CONFIG_NET_IPV4=y
11+
CONFIG_NET_IPV6=y
12+
CONFIG_NET_SOCKETS=y
13+
CONFIG_NET_SOCKETPAIR=y
14+
CONFIG_NET_SOCKETPAIR_BUFFER_SIZE=64
15+
CONFIG_NET_SOCKETS_POSIX_NAMES=y
16+
# Defines fd_set size
17+
CONFIG_POSIX_MAX_FDS=33
18+
19+
# Network driver config
20+
CONFIG_TEST_RANDOM_GENERATOR=y
21+
22+
# Network address config
23+
CONFIG_NET_CONFIG_SETTINGS=y
24+
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1"
25+
CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1"
26+
27+
CONFIG_MAIN_STACK_SIZE=2048
28+
CONFIG_ZTEST=y
29+
30+
# User mode requirements
31+
CONFIG_TEST_USERSPACE=y
32+
CONFIG_HEAP_MEM_POOL_SIZE=2048
33+
34+
CONFIG_QEMU_TICKLESS_WORKAROUND=y
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright (c) 2020 Friedt Professional Engineering Services, Inc
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <ztest.h>
8+
9+
/* in happy_path.c */
10+
extern void test_socketpair_AF_LOCAL__SOCK_STREAM__0(void);
11+
extern void test_socketpair_AF_UNIX__SOCK_STREAM__0(void);
12+
13+
/* in nonblock.c */
14+
extern void test_socketpair_write_nonblock(void);
15+
extern void test_socketpair_read_nonblock(void);
16+
17+
/* in block.c */
18+
extern void test_socketpair_write_block(void);
19+
extern void test_socketpair_read_block(void);
20+
21+
/* in closed_ends.c */
22+
extern void test_socketpair_close_one_end_and_write_to_the_other(void);
23+
extern void test_socketpair_close_one_end_and_read_from_the_other(void);
24+
25+
/* in expected_failures.c */
26+
extern void test_socketpair_expected_failures(void);
27+
28+
/* in unsupported_calls.c */
29+
extern void test_socketpair_unsupported_calls(void);
30+
31+
/* in fcntl.c */
32+
extern void test_socketpair_fcntl(void);
33+
34+
/* in poll.c */
35+
extern void test_socketpair_poll_timeout(void);
36+
extern void test_socketpair_poll_timeout_nonblocking(void);
37+
extern void test_socketpair_poll_close_remote_end_POLLIN(void);
38+
extern void test_socketpair_poll_close_remote_end_POLLOUT(void);
39+
extern void test_socketpair_poll_immediate_data(void);
40+
extern void test_socketpair_poll_delayed_data(void);
41+
42+
void test_main(void)
43+
{
44+
k_thread_system_pool_assign(k_current_get());
45+
46+
ztest_test_suite(
47+
socketpair,
48+
ztest_user_unit_test(test_socketpair_AF_LOCAL__SOCK_STREAM__0),
49+
ztest_user_unit_test(test_socketpair_AF_UNIX__SOCK_STREAM__0),
50+
51+
ztest_user_unit_test(test_socketpair_write_nonblock),
52+
ztest_user_unit_test(test_socketpair_read_nonblock),
53+
54+
ztest_user_unit_test(
55+
test_socketpair_close_one_end_and_write_to_the_other),
56+
ztest_user_unit_test(
57+
test_socketpair_close_one_end_and_read_from_the_other),
58+
59+
ztest_user_unit_test(test_socketpair_expected_failures),
60+
61+
ztest_user_unit_test(test_socketpair_unsupported_calls),
62+
63+
ztest_user_unit_test(test_socketpair_fcntl),
64+
65+
ztest_user_unit_test(test_socketpair_poll_timeout),
66+
ztest_user_unit_test(
67+
test_socketpair_poll_timeout_nonblocking),
68+
ztest_user_unit_test(test_socketpair_poll_immediate_data)
69+
);
70+
71+
ztest_run_test_suite(socketpair);
72+
73+
/* 20200509: @cfriedt: experiencing some issues with userspace thread
74+
* / memory permissions that will require some sorting out. Currently
75+
* these tests succeeed for native_posix_64.
76+
*
77+
* This feature is experimental at present.
78+
*/
79+
#if 0
80+
ztest_test_suite(
81+
socketpair_only_kernel,
82+
ztest_user_unit_test(test_socketpair_write_block),
83+
ztest_user_unit_test(test_socketpair_read_block),
84+
ztest_user_unit_test(test_socketpair_poll_delayed_data),
85+
ztest_user_unit_test(
86+
test_socketpair_poll_close_remote_end_POLLIN),
87+
ztest_user_unit_test(
88+
test_socketpair_poll_close_remote_end_POLLOUT)
89+
);
90+
91+
ztest_run_test_suite(socketpair_only_kernel);
92+
#endif
93+
}
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/*
2+
* Copyright (c) 2020 Friedt Professional Engineering Services, Inc
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <fcntl.h>
8+
#include <string.h>
9+
10+
#include <logging/log.h>
11+
LOG_MODULE_REGISTER(net_test, CONFIG_NET_SOCKETS_LOG_LEVEL);
12+
13+
#include <net/socket.h>
14+
#include <sys/util.h>
15+
#include <posix/unistd.h>
16+
17+
#include <ztest_assert.h>
18+
19+
#undef read
20+
#define read(fd, buf, len) zsock_recv(fd, buf, len, 0)
21+
22+
#undef write
23+
#define write(fd, buf, len) zsock_send(fd, buf, len, 0)
24+
25+
#define TIMEOUT K_FOREVER
26+
27+
struct ctx {
28+
/* true if test is write_block(), false if test is read_block() */
29+
bool write;
30+
/* the secondary-side socket of the socketpair */
31+
int fd;
32+
/* the count of the main thread */
33+
atomic_t m;
34+
/* the count of the secondary thread */
35+
size_t n;
36+
/* true when secondary thread is done */
37+
bool done;
38+
/* true if both main and secondary thread should immediately quit */
39+
bool fail;
40+
/* thread id of the secondary thread */
41+
k_tid_t tid;
42+
};
43+
ZTEST_BMEM struct ctx ctx;
44+
#define STACK_SIZE 512
45+
/* thread structure for secondary thread */
46+
ZTEST_BMEM struct k_thread th;
47+
/* stack for the secondary thread */
48+
static K_THREAD_STACK_DEFINE(th_stack, STACK_SIZE);
49+
50+
static void th_fun(void *arg0, void *arg1, void *arg2)
51+
{
52+
(void) arg0;
53+
(void) arg1;
54+
(void) arg2;
55+
56+
int res;
57+
char c = '\0';
58+
59+
LOG_DBG("secondary thread running");
60+
61+
while (true) {
62+
if (ctx.write) {
63+
LOG_DBG("ctx.m: %u", ctx.m);
64+
if (atomic_get(&ctx.m)
65+
< CONFIG_NET_SOCKETPAIR_BUFFER_SIZE) {
66+
continue;
67+
}
68+
LOG_DBG("ready to read!");
69+
} else {
70+
LOG_DBG("sleeping for 100ms..");
71+
k_sleep(K_MSEC(100));
72+
LOG_DBG("ready to write!");
73+
}
74+
break;
75+
}
76+
77+
LOG_DBG("%sing 1 byte %s fd %d", ctx.write ? "read" : "write",
78+
ctx.write ? "from" : "to", ctx.fd);
79+
if (ctx.write) {
80+
res = read(ctx.fd, &c, 1);
81+
} else {
82+
res = write(ctx.fd, "x", 1);
83+
}
84+
if (-1 == res || 1 != res) {
85+
LOG_DBG("%s(2) failed: %d", ctx.write ? "read" : "write",
86+
errno);
87+
goto out;
88+
}
89+
LOG_DBG("%s 1 byte", ctx.write ? "read" : "wrote");
90+
ctx.n = 1;
91+
92+
out:
93+
ctx.done = true;
94+
95+
LOG_DBG("terminating..");
96+
}
97+
98+
void test_socketpair_write_block(void)
99+
{
100+
int res;
101+
int sv[2] = {-1, -1};
102+
103+
LOG_DBG("creating socketpair..");
104+
res = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
105+
zassert_equal(res, 0, "socketpair(2) failed: %d", errno);
106+
107+
for (size_t i = 0; i < 2; ++i) {
108+
109+
LOG_DBG("data direction %d -> %d", sv[i], sv[(!i) & 1]);
110+
111+
LOG_DBG("setting up context");
112+
memset(&ctx, 0, sizeof(ctx));
113+
ctx.write = true;
114+
ctx.fd = sv[(!i) & 1];
115+
116+
LOG_DBG("creating secondary thread");
117+
ctx.tid = k_thread_create(&th, th_stack,
118+
STACK_SIZE, th_fun,
119+
NULL, NULL, NULL,
120+
CONFIG_MAIN_THREAD_PRIORITY,
121+
K_INHERIT_PERMS, K_NO_WAIT);
122+
LOG_DBG("created secondary thread %p", ctx.tid);
123+
124+
/* fill up the buffer */
125+
for (ctx.m = 0; atomic_get(&ctx.m)
126+
< CONFIG_NET_SOCKETPAIR_BUFFER_SIZE;) {
127+
128+
res = write(sv[i], "x", 1);
129+
zassert_not_equal(res, -1, "write(2) failed: %d",
130+
errno);
131+
zassert_equal(res, 1, "wrote %d bytes instead of 1",
132+
res);
133+
134+
atomic_inc(&ctx.m);
135+
LOG_DBG("have written %u bytes", ctx.m);
136+
}
137+
138+
/* try to write one more byte */
139+
LOG_DBG("writing to fd %d", sv[i]);
140+
res = write(sv[i], "x", 1);
141+
zassert_not_equal(res, -1, "write(2) failed: %d", errno);
142+
zassert_equal(res, 1, "wrote %d bytes instead of 1", res);
143+
144+
LOG_DBG("success!");
145+
146+
k_thread_join(&th, K_MSEC(1000));
147+
}
148+
149+
close(sv[0]);
150+
close(sv[1]);
151+
}
152+
153+
void test_socketpair_read_block(void)
154+
{
155+
int res;
156+
int sv[2] = {-1, -1};
157+
char x;
158+
159+
LOG_DBG("creating socketpair..");
160+
res = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
161+
zassert_equal(res, 0, "socketpair(2) failed: %d", errno);
162+
163+
for (size_t i = 0; i < 2; ++i) {
164+
165+
LOG_DBG("data direction %d -> %d", sv[i], sv[(!i) & 1]);
166+
167+
LOG_DBG("setting up context");
168+
memset(&ctx, 0, sizeof(ctx));
169+
ctx.write = false;
170+
ctx.fd = sv[(!i) & 1];
171+
172+
LOG_DBG("creating secondary thread");
173+
ctx.tid = k_thread_create(&th, th_stack,
174+
STACK_SIZE, th_fun,
175+
NULL, NULL, NULL,
176+
CONFIG_MAIN_THREAD_PRIORITY,
177+
K_INHERIT_PERMS, K_NO_WAIT);
178+
LOG_DBG("created secondary thread %p", ctx.tid);
179+
180+
/* try to read one byte */
181+
LOG_DBG("reading from fd %d", sv[i]);
182+
x = '\0';
183+
res = read(sv[i], &x, 1);
184+
zassert_not_equal(res, -1, "read(2) failed: %d", errno);
185+
zassert_equal(res, 1, "read %d bytes instead of 1", res);
186+
187+
LOG_DBG("success!");
188+
189+
k_thread_join(&th, K_MSEC(1000));
190+
}
191+
192+
close(sv[0]);
193+
close(sv[1]);
194+
}

0 commit comments

Comments
 (0)