Skip to content

Commit e089e26

Browse files
committed
tests: socket: tcp_rw: Test for using read()/write() on socket fd
With POSIX subsystem enabled (CONFIG_POSIX_API=y), it's possible to use generic POSIX read()/write() calls on a socket file descriptor. This test verifies their operaration on this case. Signed-off-by: Paul Sokolovsky <[email protected]>
1 parent 1cd0ae8 commit e089e26

File tree

5 files changed

+266
-0
lines changed

5 files changed

+266
-0
lines changed

tests/net/socket/socket_helpers.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@
66

77
#include <ztest_assert.h>
88

9+
#ifdef CONFIG_POSIX_API
10+
#include <sys/socket.h>
11+
#include <arpa/inet.h>
12+
#else
913
#include <net/socket.h>
14+
#endif
1015

1116
#define clear_buf(buf) memset(buf, 0, sizeof(buf))
1217

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.13.1)
4+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
5+
project(socket_tcp_rw)
6+
7+
target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/net/ip)
8+
FILE(GLOB app_sources src/*.c)
9+
target_sources(app PRIVATE ${app_sources})

tests/net/socket/tcp_rw/prj.conf

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Setup for self-contained net testing without requiring a SLIP driver
2+
CONFIG_NET_TEST=y
3+
4+
# General config
5+
CONFIG_NEWLIB_LIBC=y
6+
CONFIG_POSIX_API=y
7+
8+
# Networking config
9+
CONFIG_NETWORKING=y
10+
CONFIG_NET_IPV4=y
11+
CONFIG_NET_IPV6=y
12+
CONFIG_NET_TCP=y
13+
CONFIG_NET_SOCKETS=y
14+
CONFIG_NET_SOCKETS_POSIX_NAMES=y
15+
CONFIG_POSIX_MAX_FDS=20
16+
17+
# Network driver config
18+
CONFIG_NET_LOOPBACK=y
19+
CONFIG_TEST_RANDOM_GENERATOR=y
20+
21+
# Network address config
22+
CONFIG_NET_CONFIG_SETTINGS=y
23+
CONFIG_NET_CONFIG_NEED_IPV4=y
24+
CONFIG_NET_CONFIG_NEED_IPV6=y
25+
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1"
26+
CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1"
27+
28+
CONFIG_MAIN_STACK_SIZE=2048
29+
CONFIG_TEST_USERSPACE=y
30+
31+
# The test requires lot of bufs
32+
CONFIG_NET_PKT_TX_COUNT=24
33+
34+
CONFIG_ZTEST=y
35+
CONFIG_ZTEST_STACKSIZE=2048

tests/net/socket/tcp_rw/src/main.c

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
/*
2+
* Copyright (c) 2020 Linaro Limited
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <logging/log.h>
8+
LOG_MODULE_REGISTER(net_test, CONFIG_NET_SOCKETS_LOG_LEVEL);
9+
10+
#include <ztest_assert.h>
11+
#include <fcntl.h>
12+
#include <net/socket.h>
13+
14+
#ifdef CONFIG_POSIX_API
15+
#include <unistd.h>
16+
#endif
17+
18+
#include "../../socket_helpers.h"
19+
20+
#define TEST_STR_SMALL "test"
21+
22+
#define ANY_PORT 0
23+
#define SERVER_PORT 4242
24+
25+
#define MAX_CONNS 5
26+
27+
#define TCP_TEARDOWN_TIMEOUT K_SECONDS(1)
28+
29+
static void test_bind(int sock, struct sockaddr *addr, socklen_t addrlen)
30+
{
31+
zassert_equal(bind(sock, addr, addrlen),
32+
0,
33+
"bind failed");
34+
}
35+
36+
static void test_listen(int sock)
37+
{
38+
zassert_equal(listen(sock, MAX_CONNS),
39+
0,
40+
"listen failed");
41+
}
42+
43+
static void test_connect(int sock, struct sockaddr *addr, socklen_t addrlen)
44+
{
45+
zassert_equal(connect(sock, addr, addrlen),
46+
0,
47+
"connect failed");
48+
}
49+
50+
51+
static void test_accept(int sock, int *new_sock, struct sockaddr *addr,
52+
socklen_t *addrlen)
53+
{
54+
zassert_not_null(new_sock, "null newsock");
55+
56+
*new_sock = accept(sock, addr, addrlen);
57+
zassert_true(*new_sock >= 0, "accept failed");
58+
}
59+
60+
#ifdef CONFIG_POSIX_API
61+
static void test_write(int sock, const void *buf, size_t len)
62+
{
63+
zassert_equal(write(sock, buf, len),
64+
len,
65+
"write failed");
66+
}
67+
68+
static void test_read(int sock)
69+
{
70+
ssize_t recved = 0;
71+
char rx_buf[30] = {0};
72+
73+
recved = read(sock, rx_buf, sizeof(rx_buf));
74+
zassert_equal(recved,
75+
strlen(TEST_STR_SMALL),
76+
"unexpected received bytes");
77+
zassert_equal(strncmp(rx_buf, TEST_STR_SMALL, strlen(TEST_STR_SMALL)),
78+
0,
79+
"unexpected data");
80+
}
81+
#endif
82+
83+
static void test_close(int sock)
84+
{
85+
zassert_equal(close(sock),
86+
0,
87+
"close failed");
88+
}
89+
90+
/* Test that EOF handling works correctly. Should be called with socket
91+
* whose peer socket was closed.
92+
*/
93+
static void test_eof(int sock)
94+
{
95+
char rx_buf[1];
96+
ssize_t recved;
97+
98+
/* Test that EOF properly detected. */
99+
recved = recv(sock, rx_buf, sizeof(rx_buf), 0);
100+
zassert_equal(recved, 0, "");
101+
102+
/* Calling again should be OK. */
103+
recved = recv(sock, rx_buf, sizeof(rx_buf), 0);
104+
zassert_equal(recved, 0, "");
105+
106+
/* Calling when TCP connection is fully torn down should be still OK. */
107+
k_sleep(TCP_TEARDOWN_TIMEOUT);
108+
recved = recv(sock, rx_buf, sizeof(rx_buf), 0);
109+
zassert_equal(recved, 0, "");
110+
}
111+
112+
/* These tests require POSIX API. */
113+
#ifdef CONFIG_POSIX_API
114+
115+
void test_v4_write_read(void)
116+
{
117+
int c_sock;
118+
int s_sock;
119+
int new_sock;
120+
struct sockaddr_in c_saddr;
121+
struct sockaddr_in s_saddr;
122+
struct sockaddr addr;
123+
socklen_t addrlen = sizeof(addr);
124+
125+
prepare_sock_tcp_v4(CONFIG_NET_CONFIG_MY_IPV4_ADDR, ANY_PORT,
126+
&c_sock, &c_saddr);
127+
prepare_sock_tcp_v4(CONFIG_NET_CONFIG_MY_IPV4_ADDR, SERVER_PORT,
128+
&s_sock, &s_saddr);
129+
130+
test_bind(s_sock, (struct sockaddr *)&s_saddr, sizeof(s_saddr));
131+
test_listen(s_sock);
132+
133+
test_connect(c_sock, (struct sockaddr *)&s_saddr, sizeof(s_saddr));
134+
test_write(c_sock, TEST_STR_SMALL, strlen(TEST_STR_SMALL));
135+
136+
test_accept(s_sock, &new_sock, &addr, &addrlen);
137+
zassert_equal(addrlen, sizeof(struct sockaddr_in), "wrong addrlen");
138+
139+
test_read(new_sock);
140+
141+
test_close(c_sock);
142+
test_eof(new_sock);
143+
144+
test_close(new_sock);
145+
test_close(s_sock);
146+
147+
k_sleep(TCP_TEARDOWN_TIMEOUT);
148+
}
149+
150+
void test_v6_write_read(void)
151+
{
152+
int c_sock;
153+
int s_sock;
154+
int new_sock;
155+
struct sockaddr_in6 c_saddr;
156+
struct sockaddr_in6 s_saddr;
157+
struct sockaddr addr;
158+
socklen_t addrlen = sizeof(addr);
159+
160+
prepare_sock_tcp_v6(CONFIG_NET_CONFIG_MY_IPV6_ADDR, ANY_PORT,
161+
&c_sock, &c_saddr);
162+
prepare_sock_tcp_v6(CONFIG_NET_CONFIG_MY_IPV6_ADDR, SERVER_PORT,
163+
&s_sock, &s_saddr);
164+
165+
test_bind(s_sock, (struct sockaddr *)&s_saddr, sizeof(s_saddr));
166+
test_listen(s_sock);
167+
168+
test_connect(c_sock, (struct sockaddr *)&s_saddr, sizeof(s_saddr));
169+
test_write(c_sock, TEST_STR_SMALL, strlen(TEST_STR_SMALL));
170+
171+
test_accept(s_sock, &new_sock, &addr, &addrlen);
172+
zassert_equal(addrlen, sizeof(struct sockaddr_in6), "wrong addrlen");
173+
174+
test_read(new_sock);
175+
176+
test_close(c_sock);
177+
test_eof(new_sock);
178+
179+
test_close(new_sock);
180+
test_close(s_sock);
181+
182+
k_sleep(TCP_TEARDOWN_TIMEOUT);
183+
}
184+
185+
#else /* CONFIG_POSIX_API */
186+
187+
void test_v4_write_read(void)
188+
{
189+
ztest_test_skip();
190+
}
191+
192+
void test_v6_write_read(void)
193+
{
194+
ztest_test_skip();
195+
}
196+
197+
#endif /* CONFIG_POSIX_API */
198+
199+
void test_main(void)
200+
{
201+
ztest_test_suite(
202+
socket_tcp_read_write,
203+
ztest_user_unit_test(test_v4_write_read),
204+
ztest_user_unit_test(test_v6_write_read)
205+
);
206+
207+
ztest_run_test_suite(socket_tcp_read_write);
208+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
common:
2+
depends_on: netif
3+
min_ram: 32
4+
tags: net socket userspace
5+
tests:
6+
net.socket.tcp_rw.posix:
7+
extra_configs:
8+
- CONFIG_POSIX_API=y
9+
arch_exclude: posix

0 commit comments

Comments
 (0)