socket_test.c revision 290001
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 */
36typedef struct {
37	isc_boolean_t done;
38	isc_result_t result;
39} completion_t;
40
41static void
42completion_init(completion_t *completion) {
43	completion->done = ISC_FALSE;
44}
45
46static void
47event_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
59static isc_result_t
60waitfor(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) */
79ATF_TC(udp_sendto);
80ATF_TC_HEAD(udp_sendto, tc) {
81	atf_tc_set_md_var(tc, "descr", "UDP sendto/recv");
82}
83ATF_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 */
150ATF_TC(udp_dup);
151ATF_TC_HEAD(udp_dup, tc) {
152	atf_tc_set_md_var(tc, "descr", "duplicated socket sendto/recv");
153}
154ATF_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 */
249ATF_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