tests: Add tcp sendmsg/recvmsg test
[obnox/cwrap/socket_wrapper.git] / tests / test_echo_tcp_sendmsg_recvmsg.c
1 #include <stdarg.h>
2 #include <stddef.h>
3 #include <setjmp.h>
4 #include <cmocka.h>
5
6 #include "config.h"
7 #include "torture.h"
8
9 #include <errno.h>
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <netinet/in.h>
13 #include <arpa/inet.h>
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <unistd.h>
17
18 static int setup_echo_srv_tcp_ipv4(void **state)
19 {
20         torture_setup_echo_srv_tcp_ipv4(state);
21
22         return 0;
23 }
24
25 #ifdef HAVE_IPV6
26 static int setup_echo_srv_tcp_ipv6(void **state)
27 {
28         torture_setup_echo_srv_tcp_ipv6(state);
29
30         return 0;
31 }
32 #endif
33
34 static int teardown(void **state)
35 {
36         torture_teardown_echo_srv(state);
37
38         return 0;
39 }
40
41 static void test_sendmsg_recvmsg_ipv4(void **state)
42 {
43         struct torture_address addr = {
44                 .sa_socklen = sizeof(struct sockaddr_storage),
45         };
46         char send_buf[64] = {0};
47         char recv_buf[64] = {0};
48         ssize_t ret;
49         int rc;
50         int i;
51         int s;
52
53         (void) state; /* unused */
54
55         s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
56         assert_int_not_equal(s, -1);
57
58         addr.sa.in.sin_family = AF_INET;
59         addr.sa.in.sin_port = htons(torture_server_port());
60
61         rc = inet_pton(AF_INET,
62                        torture_server_address(AF_INET),
63                        &addr.sa.in.sin_addr);
64         assert_int_equal(rc, 1);
65
66         rc = connect(s, &addr.sa.s, addr.sa_socklen);
67
68         for (i = 0; i < 10; i++) {
69                 struct torture_address reply_addr = {
70                         .sa_socklen = sizeof(struct sockaddr_storage),
71                 };
72                 struct msghdr s_msg = {
73                         .msg_namelen = 0,
74                 };
75                 struct msghdr r_msg = {
76                         .msg_namelen = 0,
77                 };
78                 struct iovec s_iov;
79                 struct iovec r_iov;
80
81                 snprintf(send_buf, sizeof(send_buf), "packet.%d", i);
82
83                 /* This should be ignored */
84                 rc = inet_pton(AF_INET,
85                                "127.0.0.1",
86                                &addr.sa.in.sin_addr);
87                 assert_int_equal(rc, 1);
88
89                 s_msg.msg_name = &addr.sa.s;
90                 s_msg.msg_namelen = addr.sa_socklen;
91
92                 s_iov.iov_base = send_buf;
93                 s_iov.iov_len = sizeof(send_buf);
94
95                 s_msg.msg_iov = &s_iov;
96                 s_msg.msg_iovlen = 1;
97
98                 ret = sendmsg(s, &s_msg, 0);
99                 assert_int_not_equal(ret, -1);
100
101                 r_msg.msg_name = &reply_addr.sa.s;
102                 r_msg.msg_namelen = reply_addr.sa_socklen;
103
104                 r_iov.iov_base = recv_buf;
105                 r_iov.iov_len = sizeof(recv_buf);
106
107                 r_msg.msg_iov = &r_iov;
108                 r_msg.msg_iovlen = 1;
109
110                 ret = recvmsg(s, &r_msg, 0);
111                 assert_int_not_equal(ret, -1);
112
113                 assert_int_equal(r_msg.msg_namelen, 0);
114
115                 assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
116         }
117
118         close(s);
119 }
120
121 #ifdef HAVE_IPV6
122 static void test_sendmsg_recvmsg_ipv6(void **state)
123 {
124         struct torture_address addr = {
125                 .sa_socklen = sizeof(struct sockaddr_storage),
126         };
127         char send_buf[64] = {0};
128         char recv_buf[64] = {0};
129         ssize_t ret;
130         int rc;
131         int i;
132         int s;
133
134         (void) state; /* unused */
135
136         s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
137         assert_int_not_equal(s, -1);
138
139         addr.sa.in.sin_family = AF_INET6;
140         addr.sa.in.sin_port = htons(torture_server_port());
141
142         rc = inet_pton(AF_INET6,
143                        torture_server_address(AF_INET6),
144                        &addr.sa.in6.sin6_addr);
145         assert_int_equal(rc, 1);
146
147         rc = connect(s, &addr.sa.s, addr.sa_socklen);
148
149         for (i = 0; i < 10; i++) {
150                 struct torture_address reply_addr = {
151                         .sa_socklen = sizeof(struct sockaddr_in),
152                 };
153                 struct msghdr s_msg = {
154                         .msg_namelen = 0,
155                 };
156                 struct msghdr r_msg = {
157                         .msg_namelen = 0,
158                 };
159                 struct iovec s_iov;
160                 struct iovec r_iov;
161
162                 snprintf(send_buf, sizeof(send_buf), "packet.%d", i);
163
164                 s_iov.iov_base = send_buf;
165                 s_iov.iov_len = sizeof(send_buf);
166
167                 s_msg.msg_iov = &s_iov;
168                 s_msg.msg_iovlen = 1;
169
170                 ret = sendmsg(s, &s_msg, 0);
171                 assert_int_not_equal(ret, -1);
172
173                 r_msg.msg_name = &reply_addr.sa.s;
174                 r_msg.msg_namelen = reply_addr.sa_socklen;
175
176                 r_iov.iov_base = recv_buf;
177                 r_iov.iov_len = sizeof(recv_buf);
178
179                 r_msg.msg_iov = &r_iov;
180                 r_msg.msg_iovlen = 1;
181
182                 ret = recvmsg(s, &r_msg, 0);
183                 assert_int_not_equal(ret, -1);
184
185                 assert_int_equal(r_msg.msg_namelen, 0);
186
187                 assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
188         }
189
190         close(s);
191 }
192 #endif
193
194 static void test_sendmsg_recvmsg_ipv4_null(void **state)
195 {
196         struct torture_address s_addr = {
197                 .sa_socklen = sizeof(struct sockaddr_storage),
198         };
199         struct msghdr s_msg = {
200                 .msg_namelen = 0,
201         };
202         struct msghdr r_msg = {
203                 .msg_namelen = 0,
204         };
205         struct iovec iov;
206         char payload[] = "PACKET";
207         ssize_t ret;
208         int rc;
209         int s;
210
211         (void)state; /* unused */
212
213         s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
214         assert_int_not_equal(s, -1);
215
216         s_addr.sa.in.sin_family = AF_INET;
217         s_addr.sa.in.sin_port = htons(torture_server_port());
218
219         rc = inet_pton(AF_INET,
220                        torture_server_address(AF_INET),
221                        &s_addr.sa.in.sin_addr);
222         assert_int_equal(rc, 1);
223
224         rc = connect(s, &s_addr.sa.s, s_addr.sa_socklen);
225
226         /* msg_name = NULL */
227
228         iov.iov_base = (void *)payload;
229         iov.iov_len = sizeof(payload);
230
231         s_msg.msg_iov = &iov;
232         s_msg.msg_iovlen = 1;
233
234         ret = sendmsg(s, &s_msg, 0);
235         assert_int_not_equal(ret, -1);
236
237         /* msg_name = NULL */
238
239         memset(payload, '0', sizeof(payload));
240
241         r_msg.msg_iov = &iov;
242         r_msg.msg_iovlen = 1;
243
244         ret = recvmsg(s, &r_msg, 0);
245         assert_int_not_equal(ret, -1);
246
247         assert_int_equal(r_msg.msg_namelen, 0);
248         assert_null(r_msg.msg_name);
249
250         close(s);
251 }
252
253 int main(void) {
254         int rc;
255
256         const struct CMUnitTest sendmsg_tests[] = {
257                 cmocka_unit_test_setup_teardown(test_sendmsg_recvmsg_ipv4,
258                                                 setup_echo_srv_tcp_ipv4,
259                                                 teardown),
260                 cmocka_unit_test_setup_teardown(test_sendmsg_recvmsg_ipv4_null,
261                                                 setup_echo_srv_tcp_ipv4,
262                                                 teardown),
263 #ifdef HAVE_IPV6
264                 cmocka_unit_test_setup_teardown(test_sendmsg_recvmsg_ipv6,
265                                                 setup_echo_srv_tcp_ipv6,
266                                                 teardown),
267 #endif
268         };
269
270         rc = cmocka_run_group_tests(sendmsg_tests, NULL, NULL);
271
272         return rc;
273 }