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