]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ntp/lib/isc/tests/socket_test.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / ntp / lib / isc / tests / socket_test.c
1 /*
2  * Copyright (C) 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14  * PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 /* $Id$ */
18
19 /*! \file */
20
21 #include <config.h>
22
23 #include <atf-c.h>
24
25 #include <unistd.h>
26 #include <time.h>
27
28 #include <isc/socket.h>
29
30 #include "../task_p.h"
31 #include "isctest.h"
32
33 /*
34  * Helper functions
35  */
36 typedef struct {
37         isc_boolean_t done;
38         isc_result_t result;
39 } completion_t;
40
41 static void
42 completion_init(completion_t *completion) {
43         completion->done = ISC_FALSE;
44 }
45
46 static void
47 event_done(isc_task_t *task, isc_event_t *event) {
48         isc_socketevent_t *dev;
49         completion_t *completion = event->ev_arg;
50
51         UNUSED(task);
52
53         dev = (isc_socketevent_t *) event;
54         completion->result = dev->result;
55         completion->done = ISC_TRUE;
56         isc_event_free(&event);
57 }
58
59 static isc_result_t
60 waitfor(completion_t *completion) {
61         int i = 0;
62         while (!completion->done && i++ < 5000) {
63 #ifndef ISC_PLATFORM_USETHREADS
64                 while (isc__taskmgr_ready(taskmgr))
65                         isc__taskmgr_dispatch(taskmgr);
66 #endif
67                 isc_test_nap(1000);
68         }
69         if (completion->done)
70                 return (ISC_R_SUCCESS);
71         return (ISC_R_FAILURE);
72 }
73
74 /*
75  * Individual unit tests
76  */
77
78 /* Test UDP sendto/recv (IPv4) */
79 ATF_TC(udp_sendto);
80 ATF_TC_HEAD(udp_sendto, tc) {
81         atf_tc_set_md_var(tc, "descr", "UDP sendto/recv");
82 }
83 ATF_TC_BODY(udp_sendto, tc) {
84         isc_result_t result;
85         isc_sockaddr_t addr1, addr2;
86         struct in_addr in;
87         isc_socket_t *s1 = NULL, *s2 = NULL;
88         isc_task_t *task = NULL;
89         char sendbuf[BUFSIZ], recvbuf[BUFSIZ];
90         completion_t completion;
91         isc_region_t r;
92
93         UNUSED(tc);
94
95         result = isc_test_begin(NULL, ISC_TRUE);
96         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
97
98         /*
99          * Create two sockets: 127.0.0.1/5444 and 127.0.0.1/5445, talking to
100          * each other.
101          */
102         in.s_addr = inet_addr("127.0.0.1");
103         isc_sockaddr_fromin(&addr1, &in, 5444);
104         isc_sockaddr_fromin(&addr2, &in, 5445);
105
106         result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s1);
107         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
108         result = isc_socket_bind(s1, &addr1, ISC_SOCKET_REUSEADDRESS);
109         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
110
111         result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s2);
112         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
113         result = isc_socket_bind(s2, &addr2, ISC_SOCKET_REUSEADDRESS);
114         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
115
116         result = isc_task_create(taskmgr, 0, &task);
117         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
118
119         strcpy(sendbuf, "Hello");
120         r.base = (void *) sendbuf;
121         r.length = strlen(sendbuf) + 1;
122
123         completion_init(&completion);
124         result = isc_socket_sendto(s1, &r, task, event_done, &completion,
125                                    &addr2, NULL);
126         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
127         waitfor(&completion);
128         ATF_CHECK(completion.done);
129         ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
130
131         r.base = (void *) recvbuf;
132         r.length = BUFSIZ;
133         completion_init(&completion);
134         result = isc_socket_recv(s2, &r, 1, task, event_done, &completion);
135         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
136         waitfor(&completion);
137         ATF_CHECK(completion.done);
138         ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
139         ATF_CHECK_STREQ(recvbuf, "Hello");
140
141         isc_task_detach(&task);
142
143         isc_socket_detach(&s1);
144         isc_socket_detach(&s2);
145
146         isc_test_end();
147 }
148
149 /* Test UDP sendto/recv with duplicated socket */
150 ATF_TC(udp_dup);
151 ATF_TC_HEAD(udp_dup, tc) {
152         atf_tc_set_md_var(tc, "descr", "duplicated socket sendto/recv");
153 }
154 ATF_TC_BODY(udp_dup, tc) {
155         isc_result_t result;
156         isc_sockaddr_t addr1, addr2;
157         struct in_addr in;
158         isc_socket_t *s1 = NULL, *s2 = NULL, *s3 = NULL;
159         isc_task_t *task = NULL;
160         char sendbuf[BUFSIZ], recvbuf[BUFSIZ];
161         completion_t completion;
162         isc_region_t r;
163
164         UNUSED(tc);
165
166         result = isc_test_begin(NULL, ISC_TRUE);
167         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
168
169         /*
170          * Create two sockets: 127.0.0.1/5444 and 127.0.0.1/5445, talking to
171          * each other.
172          */
173         in.s_addr = inet_addr("127.0.0.1");
174         isc_sockaddr_fromin(&addr1, &in, 5444);
175         isc_sockaddr_fromin(&addr2, &in, 5445);
176
177         result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s1);
178         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
179         result = isc_socket_bind(s1, &addr1, ISC_SOCKET_REUSEADDRESS);
180         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
181
182         result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s2);
183         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
184         result = isc_socket_bind(s2, &addr2, ISC_SOCKET_REUSEADDRESS);
185         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
186
187         result = isc_socket_dup(s2, &s3);
188         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
189
190         result = isc_task_create(taskmgr, 0, &task);
191         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
192
193         strcpy(sendbuf, "Hello");
194         r.base = (void *) sendbuf;
195         r.length = strlen(sendbuf) + 1;
196
197         completion_init(&completion);
198         result = isc_socket_sendto(s1, &r, task, event_done, &completion,
199                                    &addr2, NULL);
200         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
201         waitfor(&completion);
202         ATF_CHECK(completion.done);
203         ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
204
205         strcpy(sendbuf, "World");
206         r.base = (void *) sendbuf;
207         r.length = strlen(sendbuf) + 1;
208
209         completion_init(&completion);
210         result = isc_socket_sendto(s1, &r, task, event_done, &completion,
211                                    &addr2, NULL);
212         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
213         waitfor(&completion);
214         ATF_CHECK(completion.done);
215         ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
216
217         r.base = (void *) recvbuf;
218         r.length = BUFSIZ;
219         completion_init(&completion);
220         result = isc_socket_recv(s2, &r, 1, task, event_done, &completion);
221         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
222         waitfor(&completion);
223         ATF_CHECK(completion.done);
224         ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
225         ATF_CHECK_STREQ(recvbuf, "Hello");
226
227         r.base = (void *) recvbuf;
228         r.length = BUFSIZ;
229         completion_init(&completion);
230         result = isc_socket_recv(s3, &r, 1, task, event_done, &completion);
231         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
232         waitfor(&completion);
233         ATF_CHECK(completion.done);
234         ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
235         ATF_CHECK_STREQ(recvbuf, "World");
236
237         isc_task_detach(&task);
238
239         isc_socket_detach(&s1);
240         isc_socket_detach(&s2);
241         isc_socket_detach(&s3);
242
243         isc_test_end();
244 }
245
246 /*
247  * Main
248  */
249 ATF_TP_ADD_TCS(tp) {
250         ATF_TP_ADD_TC(tp, udp_sendto);
251         ATF_TP_ADD_TC(tp, udp_dup);
252
253         return (atf_no_error());
254 }
255