xref: /NextBSD/contrib/ntp/lib/isc/tests/socket_test.c (revision 287e3b14e9552995def1802ec9c5034f4adf28ec)
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
completion_init(completion_t * completion)42 completion_init(completion_t *completion) {
43 	completion->done = ISC_FALSE;
44 }
45 
46 static void
event_done(isc_task_t * task,isc_event_t * event)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
waitfor(completion_t * completion)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);
ATF_TC_HEAD(udp_sendto,tc)80 ATF_TC_HEAD(udp_sendto, tc) {
81 	atf_tc_set_md_var(tc, "descr", "UDP sendto/recv");
82 }
ATF_TC_BODY(udp_sendto,tc)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);
ATF_TC_HEAD(udp_dup,tc)151 ATF_TC_HEAD(udp_dup, tc) {
152 	atf_tc_set_md_var(tc, "descr", "duplicated socket sendto/recv");
153 }
ATF_TC_BODY(udp_dup,tc)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  */
ATF_TP_ADD_TCS(tp)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 
256