1047f369cy/*
2047f369cy * Copyright (c) 2009-2012 Nick Mathewson and Niels Provos
3047f369cy *
4047f369cy * Redistribution and use in source and binary forms, with or without
5047f369cy * modification, are permitted provided that the following conditions
6047f369cy * are met:
7047f369cy * 1. Redistributions of source code must retain the above copyright
8047f369cy *    notice, this list of conditions and the following disclaimer.
9047f369cy * 2. Redistributions in binary form must reproduce the above copyright
10047f369cy *    notice, this list of conditions and the following disclaimer in the
11047f369cy *    documentation and/or other materials provided with the distribution.
12047f369cy * 3. The name of the author may not be used to endorse or promote products
13047f369cy *    derived from this software without specific prior written permission.
14047f369cy *
15047f369cy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16047f369cy * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17047f369cy * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18047f369cy * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19047f369cy * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20047f369cy * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21047f369cy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22047f369cy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23047f369cy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24047f369cy * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25047f369cy */
26047f369cy#include "../util-internal.h"
27047f369cy
28047f369cy#ifdef _WIN32
29047f369cy#include <winsock2.h>
30047f369cy#include <windows.h>
31047f369cy#include <ws2tcpip.h>
32047f369cy#endif
33047f369cy
34047f369cy#include "event2/event-config.h"
35047f369cy
36047f369cy#include <sys/types.h>
37047f369cy
38047f369cy#ifndef _WIN32
39047f369cy#include <sys/socket.h>
40047f369cy#include <netinet/in.h>
41047f369cy#include <arpa/inet.h>
42047f369cy#include <unistd.h>
43047f369cy#endif
44047f369cy#ifdef EVENT__HAVE_NETINET_IN6_H
45047f369cy#include <netinet/in6.h>
46047f369cy#endif
47047f369cy#ifdef EVENT__HAVE_SYS_WAIT_H
48047f369cy#include <sys/wait.h>
49047f369cy#endif
50047f369cy#include <signal.h>
51047f369cy#include <stdio.h>
52047f369cy#include <stdlib.h>
53047f369cy#include <string.h>
54047f369cy
55047f369cy#include "event2/event.h"
56047f369cy#include "event2/util.h"
57047f369cy#include "../ipv6-internal.h"
58047f369cy#include "../log-internal.h"
59047f369cy#include "../strlcpy-internal.h"
60047f369cy#include "../mm-internal.h"
61047f369cy#include "../time-internal.h"
62047f369cy
63047f369cy#include "regress.h"
64047f369cy
65047f369cyenum entry_status { NORMAL, CANONICAL, BAD };
66047f369cy
67047f369cy/* This is a big table of results we expect from generating and parsing */
68047f369cystatic struct ipv4_entry {
69047f369cy	const char *addr;
70047f369cy	ev_uint32_t res;
71047f369cy	enum entry_status status;
72047f369cy} ipv4_entries[] = {
73047f369cy	{ "1.2.3.4", 0x01020304u, CANONICAL },
74047f369cy	{ "255.255.255.255", 0xffffffffu, CANONICAL },
75047f369cy	{ "256.0.0.0", 0, BAD },
76047f369cy	{ "ABC", 0, BAD },
77047f369cy	{ "1.2.3.4.5", 0, BAD },
78047f369cy	{ "176.192.208.244", 0xb0c0d0f4, CANONICAL },
79047f369cy	{ NULL, 0, BAD },
80047f369cy};
81047f369cy
82047f369cystatic struct ipv6_entry {
83047f369cy	const char *addr;
84047f369cy	ev_uint32_t res[4];
85047f369cy	enum entry_status status;
86047f369cy} ipv6_entries[] = {
87047f369cy	{ "::", { 0, 0, 0, 0, }, CANONICAL },
88047f369cy	{ "0:0:0:0:0:0:0:0", { 0, 0, 0, 0, }, NORMAL },
89047f369cy	{ "::1", { 0, 0, 0, 1, }, CANONICAL },
90047f369cy	{ "::1.2.3.4", { 0, 0, 0, 0x01020304, }, CANONICAL },
91047f369cy	{ "ffff:1::", { 0xffff0001u, 0, 0, 0, }, CANONICAL },
92047f369cy	{ "ffff:0000::", { 0xffff0000u, 0, 0, 0, }, NORMAL },
93047f369cy	{ "ffff::1234", { 0xffff0000u, 0, 0, 0x1234, }, CANONICAL },
94047f369cy	{ "0102::1.2.3.4", {0x01020000u, 0, 0, 0x01020304u }, NORMAL },
95047f369cy	{ "::9:c0a8:1:1", { 0, 0, 0x0009c0a8u, 0x00010001u }, CANONICAL },
96047f369cy	{ "::ffff:1.2.3.4", { 0, 0, 0x000ffffu, 0x01020304u }, CANONICAL },
97047f369cy	{ "FFFF::", { 0xffff0000u, 0, 0, 0 }, NORMAL },
98047f369cy	{ "foobar.", { 0, 0, 0, 0 }, BAD },
99047f369cy	{ "foobar", { 0, 0, 0, 0 }, BAD },
100047f369cy	{ "fo:obar", { 0, 0, 0, 0 }, BAD },
101047f369cy	{ "ffff", { 0, 0, 0, 0 }, BAD },
102047f369cy	{ "fffff::", { 0, 0, 0, 0 }, BAD },
103047f369cy	{ "fffff::", { 0, 0, 0, 0 }, BAD },
104047f369cy	{ "::1.0.1.1000", { 0, 0, 0, 0 }, BAD },
105047f369cy	{ "1:2:33333:4::", { 0, 0, 0, 0 }, BAD },
106047f369cy	{ "1:2:3:4:5:6:7:8:9", { 0, 0, 0, 0 }, BAD },
107047f369cy	{ "1::2::3", { 0, 0, 0, 0 }, BAD },
108047f369cy	{ ":::1", { 0, 0, 0, 0 }, BAD },
109047f369cy	{ NULL, { 0, 0, 0, 0,  }, BAD },
110047f369cy};
111047f369cy
112047f369cystatic void
113047f369cyregress_ipv4_parse(void *ptr)
114047f369cy{
115047f369cy	int i;
116047f369cy	for (i = 0; ipv4_entries[i].addr; ++i) {
117047f369cy		char written[128];
118047f369cy		struct ipv4_entry *ent = &ipv4_entries[i];
119047f369cy		struct in_addr in;
120047f369cy		int r;
121047f369cy		r = evutil_inet_pton(AF_INET, ent->addr, &in);
122047f369cy		if (r == 0) {
123047f369cy			if (ent->status != BAD) {
124047f369cy				TT_FAIL(("%s did not parse, but it's a good address!",
125047f369cy					ent->addr));
126047f369cy			}
127047f369cy			continue;
128047f369cy		}
129047f369cy		if (ent->status == BAD) {
130047f369cy			TT_FAIL(("%s parsed, but we expected an error", ent->addr));
131047f369cy			continue;
132047f369cy		}
133047f369cy		if (ntohl(in.s_addr) != ent->res) {
134047f369cy			TT_FAIL(("%s parsed to %lx, but we expected %lx", ent->addr,
135047f369cy				(unsigned long)ntohl(in.s_addr),
136047f369cy				(unsigned long)ent->res));
137047f369cy			continue;
138047f369cy		}
139047f369cy		if (ent->status == CANONICAL) {
140047f369cy			const char *w = evutil_inet_ntop(AF_INET, &in, written,
141047f369cy											 sizeof(written));
142047f369cy			if (!w) {
143047f369cy				TT_FAIL(("Tried to write out %s; got NULL.", ent->addr));
144047f369cy				continue;
145047f369cy			}
146047f369cy			if (strcmp(written, ent->addr)) {
147047f369cy				TT_FAIL(("Tried to write out %s; got %s",
148047f369cy					ent->addr, written));
149047f369cy				continue;
150047f369cy			}
151047f369cy		}
152047f369cy
153047f369cy	}
154047f369cy
155047f369cy}
156047f369cy
157047f369cystatic void
158047f369cyregress_ipv6_parse(void *ptr)
159047f369cy{
160047f369cy#ifdef AF_INET6
161047f369cy	int i, j;
162047f369cy
163047f369cy	for (i = 0; ipv6_entries[i].addr; ++i) {
164047f369cy		char written[128];
165047f369cy		struct ipv6_entry *ent = &ipv6_entries[i];
166047f369cy		struct in6_addr in6;
167047f369cy		int r;
168047f369cy		r = evutil_inet_pton(AF_INET6, ent->addr, &in6);
169047f369cy		if (r == 0) {
170047f369cy			if (ent->status != BAD)
171047f369cy				TT_FAIL(("%s did not parse, but it's a good address!",
172047f369cy					ent->addr));
173047f369cy			continue;
174047f369cy		}
175047f369cy		if (ent->status == BAD) {
176047f369cy			TT_FAIL(("%s parsed, but we expected an error", ent->addr));
177047f369cy			continue;
178047f369cy		}
179047f369cy		for (j = 0; j < 4; ++j) {
180047f369cy			/* Can't use s6_addr32 here; some don't have it. */
181047f369cy			ev_uint32_t u =
182f63afe2cy			    ((ev_uint32_t)in6.s6_addr[j*4  ] << 24) |
183f63afe2cy			    ((ev_uint32_t)in6.s6_addr[j*4+1] << 16) |
184f63afe2cy			    ((ev_uint32_t)in6.s6_addr[j*4+2] << 8) |
185f63afe2cy			    ((ev_uint32_t)in6.s6_addr[j*4+3]);
186047f369cy			if (u != ent->res[j]) {
187047f369cy				TT_FAIL(("%s did not parse as expected.", ent->addr));
188047f369cy				continue;
189047f369cy			}
190047f369cy		}
191047f369cy		if (ent->status == CANONICAL) {
192047f369cy			const char *w = evutil_inet_ntop(AF_INET6, &in6, written,
193047f369cy											 sizeof(written));
194047f369cy			if (!w) {
195047f369cy				TT_FAIL(("Tried to write out %s; got NULL.", ent->addr));
196047f369cy				continue;
197047f369cy			}
198047f369cy			if (strcmp(written, ent->addr)) {
199047f369cy				TT_FAIL(("Tried to write out %s; got %s", ent->addr, written));
200047f369cy				continue;
201047f369cy			}
202047f369cy		}
203047f369cy
204047f369cy	}
205047f369cy#else
206047f369cy	TT_BLATHER(("Skipping IPv6 address parsing."));
207047f369cy#endif
208047f369cy}
209047f369cy
210047f369cystatic struct sa_port_ent {
211047f369cy	const char *parse;
212047f369cy	int safamily;
213047f369cy	const char *addr;
214047f369cy	int port;
215047f369cy} sa_port_ents[] = {
216047f369cy	{ "[ffff::1]:1000", AF_INET6, "ffff::1", 1000 },
217047f369cy	{ "[ffff::1]", AF_INET6, "ffff::1", 0 },
218047f369cy	{ "[ffff::1", 0, NULL, 0 },
219047f369cy	{ "[ffff::1]:65599", 0, NULL, 0 },
220047f369cy	{ "[ffff::1]:0", 0, NULL, 0 },
221047f369cy	{ "[ffff::1]:-1", 0, NULL, 0 },
222047f369cy	{ "::1", AF_INET6, "::1", 0 },
223047f369cy	{ "1:2::1", AF_INET6, "1:2::1", 0 },
224047f369cy	{ "192.168.0.1:50", AF_INET, "192.168.0.1", 50 },
225047f369cy	{ "1.2.3.4", AF_INET, "1.2.3.4", 0 },
226047f369cy	{ NULL, 0, NULL, 0 },
227047f369cy};
228047f369cy
229047f369cystatic void
230047f369cyregress_sockaddr_port_parse(void *ptr)
231047f369cy{
232047f369cy	struct sockaddr_storage ss;
233047f369cy	int i, r;
234047f369cy
235047f369cy	for (i = 0; sa_port_ents[i].parse; ++i) {
236047f369cy		struct sa_port_ent *ent = &sa_port_ents[i];
237047f369cy		int len = sizeof(ss);
238047f369cy		memset(&ss, 0, sizeof(ss));
239047f369cy		r = evutil_parse_sockaddr_port(ent->parse, (struct sockaddr*)&ss, &len);
240047f369cy		if (r < 0) {
241047f369cy			if (ent->safamily)
242047f369cy				TT_FAIL(("Couldn't parse %s!", ent->parse));
243047f369cy			continue;
244047f369cy		} else if (! ent->safamily) {
245047f369cy			TT_FAIL(("Shouldn't have been able to parse %s!", ent->parse));
246047f369cy			continue;
247047f369cy		}
248047f369cy		if (ent->safamily == AF_INET) {
249047f369cy			struct sockaddr_in sin;
250047f369cy			memset(&sin, 0, sizeof(sin));
251047f369cy#ifdef EVENT__HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
252047f369cy			sin.sin_len = sizeof(sin);
253047f369cy#endif
254047f369cy			sin.sin_family = AF_INET;
255047f369cy			sin.sin_port = htons(ent->port);
256047f369cy			r = evutil_inet_pton(AF_INET, ent->addr, &sin.sin_addr);
257047f369cy			if (1 != r) {
258047f369cy				TT_FAIL(("Couldn't parse ipv4 target %s.", ent->addr));
259047f369cy			} else if (memcmp(&sin, &ss, sizeof(sin))) {
260047f369cy				TT_FAIL(("Parse for %s was not as expected.", ent->parse));
261047f369cy			} else if (len != sizeof(sin)) {
262047f369cy				TT_FAIL(("Length for %s not as expected.",ent->parse));
263047f369cy			}
264047f369cy		} else {
265047f369cy			struct sockaddr_in6 sin6;
266047f369cy			memset(&sin6, 0, sizeof(sin6));
267047f369cy#ifdef EVENT__HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
268047f369cy			sin6.sin6_len = sizeof(sin6);
269047f369cy#endif
270047f369cy			sin6.sin6_family = AF_INET6;
271047f369cy			sin6.sin6_port = htons(ent->port);
272047f369cy			r = evutil_inet_pton(AF_INET6, ent->addr, &sin6.sin6_addr);
273047f369cy			if (1 != r) {
274047f369cy				TT_FAIL(("Couldn't parse ipv6 target %s.", ent->addr));
275047f369cy			} else if (memcmp(&sin6, &ss, sizeof(sin6))) {
276047f369cy				TT_FAIL(("Parse for %s was not as expected.", ent->parse));
277047f369cy			} else if (len != sizeof(sin6)) {
278047f369cy				TT_FAIL(("Length for %s not as expected.",ent->parse));
279047f369cy			}
280047f369cy		}
281047f369cy	}
282047f369cy}
283047f369cy
284047f369cy
285047f369cystatic void
286047f369cyregress_sockaddr_port_format(void *ptr)
287047f369cy{
288047f369cy	struct sockaddr_storage ss;
289047f369cy	int len;
290047f369cy	const char *cp;
291047f369cy	char cbuf[128];
292047f369cy	int r;
293047f369cy
294047f369cy	len = sizeof(ss);
295047f369cy	r = evutil_parse_sockaddr_port("192.168.1.1:80",
296047f369cy	    (struct sockaddr*)&ss, &len);
297047f369cy	tt_int_op(r,==,0);
298047f369cy	cp = evutil_format_sockaddr_port_(
299047f369cy		(struct sockaddr*)&ss, cbuf, sizeof(cbuf));
300047f369cy	tt_ptr_op(cp,==,cbuf);
301047f369cy	tt_str_op(cp,==,"192.168.1.1:80");
302047f369cy
303047f369cy	len = sizeof(ss);
304047f369cy	r = evutil_parse_sockaddr_port("[ff00::8010]:999",
305047f369cy	    (struct sockaddr*)&ss, &len);
306047f369cy	tt_int_op(r,==,0);
307047f369cy	cp = evutil_format_sockaddr_port_(
308047f369cy		(struct sockaddr*)&ss, cbuf, sizeof(cbuf));
309047f369cy	tt_ptr_op(cp,==,cbuf);
310047f369cy	tt_str_op(cp,==,"[ff00::8010]:999");
311047f369cy
312047f369cy	ss.ss_family=99;
313047f369cy	cp = evutil_format_sockaddr_port_(
314047f369cy		(struct sockaddr*)&ss, cbuf, sizeof(cbuf));
315047f369cy	tt_ptr_op(cp,==,cbuf);
316047f369cy	tt_str_op(cp,==,"<addr with socktype 99>");
317047f369cyend:
318047f369cy	;
319047f369cy}
320047f369cy
321047f369cystatic struct sa_pred_ent {
322047f369cy	const char *parse;
323047f369cy
324047f369cy	int is_loopback;
325047f369cy} sa_pred_entries[] = {
326047f369cy	{ "127.0.0.1",	 1 },
327047f369cy	{ "127.0.3.2",	 1 },
328047f369cy	{ "128.1.2.3",	 0 },
329047f369cy	{ "18.0.0.1",	 0 },
330047f369cy	{ "129.168.1.1", 0 },
331047f369cy
332047f369cy	{ "::1",	 1 },
333047f369cy	{ "::0",	 0 },
334047f369cy	{ "f::1",	 0 },
335047f369cy	{ "::501",	 0 },
336047f369cy	{ NULL,		 0 },
337047f369cy
338047f369cy};
339047f369cy
340047f369cystatic void
341047f369cytest_evutil_sockaddr_predicates(void *ptr)
342047f369cy{
343047f369cy	struct sockaddr_storage ss;
344047f369cy	int r, i;
345047f369cy
346047f369cy	for (i=0; sa_pred_entries[i].parse; ++i) {
347047f369cy		struct sa_pred_ent *ent = &sa_pred_entries[i];
348047f369cy		int len = sizeof(ss);
349047f369cy
350047f369cy		r = evutil_parse_sockaddr_port(ent->parse, (struct sockaddr*)&ss, &len);
351047f369cy
352047f369cy		if (r<0) {
353047f369cy			TT_FAIL(("Couldn't parse %s!", ent->parse));
354047f369cy			continue;
355047f369cy		}
356047f369cy
357047f369cy		/* sockaddr_is_loopback */
358047f369cy		if (ent->is_loopback != evutil_sockaddr_is_loopback_((struct sockaddr*)&ss)) {
359047f369cy			TT_FAIL(("evutil_sockaddr_loopback(%s) not as expected",
360047f369cy				ent->parse));
361047f369cy		}
362047f369cy	}
363047f369cy}
364047f369cy
365047f369cystatic void
366047f369cytest_evutil_strtoll(void *ptr)
367047f369cy{
368047f369cy	const char *s;
369047f369cy	char *endptr;
370047f369cy
371047f369cy	tt_want(evutil_strtoll("5000000000", NULL, 10) ==
372047f369cy		((ev_int64_t)5000000)*1000);
373047f369cy	tt_want(evutil_strtoll("-5000000000", NULL, 10) ==
374047f369cy		((ev_int64_t)5000000)*-1000);
375047f369cy	s = " 99999stuff";
376047f369cy	tt_want(evutil_strtoll(s, &endptr, 10) == (ev_int64_t)99999);
377047f369cy	tt_want(endptr == s+6);
378047f369cy	tt_want(evutil_strtoll("foo", NULL, 10) == 0);
379047f369cy }
380047f369cy
381047f369cystatic void
382047f369cytest_evutil_snprintf(void *ptr)
383047f369cy{
384047f369cy	char buf[16];
385047f369cy	int r;
386047f369cy	ev_uint64_t u64 = ((ev_uint64_t)1000000000)*200;
387047f369cy	ev_int64_t i64 = -1 * (ev_int64_t) u64;
388047f369cy	size_t size = 8000;
389047f369cy	ev_ssize_t ssize = -9000;
390047f369cy
391047f369cy	r = evutil_snprintf(buf, sizeof(buf), "%d %d", 50, 100);
392047f369cy	tt_str_op(buf, ==, "50 100");
393047f369cy	tt_int_op(r, ==, 6);
394047f369cy
395047f369cy	r = evutil_snprintf(buf, sizeof(buf), "longish %d", 1234567890);
396047f369cy	tt_str_op(buf, ==, "longish 1234567");
397047f369cy	tt_int_op(r, ==, 18);
398047f369cy
399047f369cy	r = evutil_snprintf(buf, sizeof(buf), EV_U64_FMT, EV_U64_ARG(u64));
400047f369cy	tt_str_op(buf, ==, "200000000000");
401047f369cy	tt_int_op(r, ==, 12);
402047f369cy
403047f369cy	r = evutil_snprintf(buf, sizeof(buf), EV_I64_FMT, EV_I64_ARG(i64));
404047f369cy	tt_str_op(buf, ==, "-200000000000");
405047f369cy	tt_int_op(r, ==, 13);
406047f369cy
407047f369cy	r = evutil_snprintf(buf, sizeof(buf), EV_SIZE_FMT" "EV_SSIZE_FMT,
408047f369cy	    EV_SIZE_ARG(size), EV_SSIZE_ARG(ssize));
409047f369cy	tt_str_op(buf, ==, "8000 -9000");
410047f369cy	tt_int_op(r, ==, 10);
411047f369cy
412047f369cy      end:
413047f369cy	;
414047f369cy}
415047f369cy
416047f369cystatic void
417047f369cytest_evutil_casecmp(void *ptr)
418047f369cy{
419047f369cy	tt_int_op(evutil_ascii_strcasecmp("ABC", "ABC"), ==, 0);
420047f369cy	tt_int_op(evutil_ascii_strcasecmp("ABC", "abc"), ==, 0);
421047f369cy	tt_int_op(evutil_ascii_strcasecmp("ABC", "abcd"), <, 0);
422047f369cy	tt_int_op(evutil_ascii_strcasecmp("ABC", "abb"), >, 0);
423047f369cy	tt_int_op(evutil_ascii_strcasecmp("ABCd", "abc"), >, 0);
424047f369cy
425047f369cy	tt_int_op(evutil_ascii_strncasecmp("Libevent", "LibEvEnT", 100), ==, 0);
426047f369cy	tt_int_op(evutil_ascii_strncasecmp("Libevent", "LibEvEnT", 4), ==, 0);
427047f369cy	tt_int_op(evutil_ascii_strncasecmp("Libevent", "LibEXXXX", 4), ==, 0);
428047f369cy	tt_int_op(evutil_ascii_strncasecmp("Libevent", "LibE", 4), ==, 0);
429047f369cy	tt_int_op(evutil_ascii_strncasecmp("Libe", "LibEvEnT", 4), ==, 0);
430047f369cy	tt_int_op(evutil_ascii_strncasecmp("Lib", "LibEvEnT", 4), <, 0);
431047f369cy	tt_int_op(evutil_ascii_strncasecmp("abc", "def", 99), <, 0);
432047f369cy	tt_int_op(evutil_ascii_strncasecmp("Z", "qrst", 1), >, 0);
433047f369cyend:
434047f369cy	;
435047f369cy}
436047f369cy
437047f369cystatic void
438047f369cytest_evutil_rtrim(void *ptr)
439047f369cy{
440047f369cy#define TEST_TRIM(s, result) \
441047f369cy	do {						\
442047f369cy	    if (cp) mm_free(cp);			\
443047f369cy	    cp = mm_strdup(s);				\
444047f369cy	    tt_assert(cp);				\
445047f369cy	    evutil_rtrim_lws_(cp);			\
446047f369cy	    tt_str_op(cp, ==, result);			\
447047f369cy	} while(0)
448047f369cy
449047f369cy	char *cp = NULL;
450047f369cy	(void) ptr;
451047f369cy
452047f369cy	TEST_TRIM("", "");
453047f369cy	TEST_TRIM("a", "a");
454047f369cy	TEST_TRIM("abcdef ghi", "abcdef ghi");
455047f369cy
456047f369cy	TEST_TRIM(" ", "");
457047f369cy	TEST_TRIM("  ", "");
458047f369cy	TEST_TRIM("a ", "a");
459047f369cy	TEST_TRIM("abcdef  gH       ", "abcdef  gH");
460047f369cy
461047f369cy	TEST_TRIM("\t\t", "");
462047f369cy	TEST_TRIM(" \t", "");
463047f369cy	TEST_TRIM("\t", "");
464047f369cy	TEST_TRIM("a \t", "a");
465047f369cy	TEST_TRIM("a\t ", "a");
466047f369cy	TEST_TRIM("a\t", "a");
467047f369cy	TEST_TRIM("abcdef  gH    \t  ", "abcdef  gH");
468047f369cy
469047f369cyend:
470047f369cy	if (cp)
471047f369cy		mm_free(cp);
472047f369cy}
473047f369cy
474047f369cystatic int logsev = 0;
475047f369cystatic char *logmsg = NULL;
476047f369cy
477047f369cystatic void
478047f369cylogfn(int severity, const char *msg)
479047f369cy{
480047f369cy	logsev = severity;
481047f369cy	tt_want(msg);
482047f369cy	if (msg) {
483047f369cy		if (logmsg)
484047f369cy			free(logmsg);
485047f369cy		logmsg = strdup(msg);
486047f369cy	}
487047f369cy}
488047f369cy
489047f369cystatic int fatal_want_severity = 0;
490047f369cystatic const char *fatal_want_message = NULL;
491047f369cystatic void
492047f369cyfatalfn(int exitcode)
493047f369cy{
494047f369cy	if (logsev != fatal_want_severity ||
495047f369cy	    !logmsg ||
496047f369cy	    strcmp(logmsg, fatal_want_message))
497047f369cy		exit(0);
498047f369cy	else
499047f369cy		exit(exitcode);
500047f369cy}
501047f369cy
502047f369cy#ifndef _WIN32
503047f369cy#define CAN_CHECK_ERR
504047f369cystatic void
505047f369cycheck_error_logging(void (*fn)(void), int wantexitcode,
506047f369cy    int wantseverity, const char *wantmsg)
507047f369cy{
508047f369cy	pid_t pid;
509047f369cy	int status = 0, exitcode;
510047f369cy	fatal_want_severity = wantseverity;
511047f369cy	fatal_want_message = wantmsg;
512047f369cy	if ((pid = regress_fork()) == 0) {
513047f369cy		/* child process */
514047f369cy		fn();
515047f369cy		exit(0); /* should be unreachable. */
516047f369cy	} else {
517047f369cy		wait(&status);
518047f369cy		exitcode = WEXITSTATUS(status);
519047f369cy		tt_int_op(wantexitcode, ==, exitcode);
520047f369cy	}
521047f369cyend:
522047f369cy	;
523047f369cy}
524047f369cy
525047f369cystatic void
526047f369cyerrx_fn(void)
527047f369cy{
528047f369cy	event_errx(2, "Fatal error; too many kumquats (%d)", 5);
529047f369cy}
530047f369cy
531047f369cystatic void
532047f369cyerr_fn(void)
533047f369cy{
534047f369cy	errno = ENOENT;
535047f369cy	event_err(5,"Couldn't open %s", "/very/bad/file");
536047f369cy}
537047f369cy
538047f369cystatic void
539047f369cysock_err_fn(void)
540047f369cy{
541047f369cy	evutil_socket_t fd = socket(AF_INET, SOCK_STREAM, 0);
542047f369cy#ifdef _WIN32
543047f369cy	EVUTIL_SET_SOCKET_ERROR(WSAEWOULDBLOCK);
544047f369cy#else
545047f369cy	errno = EAGAIN;
546047f369cy#endif
547047f369cy	event_sock_err(20, fd, "Unhappy socket");
548047f369cy}
549047f369cy#endif
550047f369cy
551047f369cystatic void
552047f369cytest_evutil_log(void *ptr)
553047f369cy{
554047f369cy	evutil_socket_t fd = -1;
555047f369cy	char buf[128];
556047f369cy
557047f369cy	event_set_log_callback(logfn);
558047f369cy	event_set_fatal_callback(fatalfn);
559047f369cy#define RESET() do {				\
560047f369cy		logsev = 0;	\
561047f369cy		if (logmsg) free(logmsg);	\
562047f369cy		logmsg = NULL;			\
563047f369cy	} while (0)
564047f369cy#define LOGEQ(sev,msg) do {			\
565047f369cy		tt_int_op(logsev,==,sev);	\
566047f369cy		tt_assert(logmsg != NULL);	\
567047f369cy		tt_str_op(logmsg,==,msg);	\
568047f369cy	} while (0)
569047f369cy
570047f369cy#ifdef CAN_CHECK_ERR
571047f369cy	/* We need to disable these tests for now.  Previously, the logging
572047f369cy	 * module didn't enforce the requirement that a fatal callback
573047f369cy	 * actually exit.  Now, it exits no matter what, so if we wan to
574047f369cy	 * reinstate these tests, we'll need to fork for each one. */
575047f369cy	check_error_logging(errx_fn, 2, EVENT_LOG_ERR,
576047f369cy	    "Fatal error; too many kumquats (5)");
577047f369cy	RESET();
578047f369cy#endif
579047f369cy
580047f369cy	event_warnx("Far too many %s (%d)", "wombats", 99);
581047f369cy	LOGEQ(EVENT_LOG_WARN, "Far too many wombats (99)");
582047f369cy	RESET();
583047f369cy
584047f369cy	event_msgx("Connecting lime to coconut");
585047f369cy	LOGEQ(EVENT_LOG_MSG, "Connecting lime to coconut");
586047f369cy	RESET();
587047f369cy
588047f369cy	event_debug(("A millisecond passed! We should log that!"));
589047f369cy#ifdef USE_DEBUG
590047f369cy	LOGEQ(EVENT_LOG_DEBUG, "A millisecond passed! We should log that!");
591047f369cy#else
592047f369cy	tt_int_op(logsev,==,0);
593047f369cy	tt_ptr_op(logmsg,==,NULL);
594047f369cy#endif
595047f369cy	RESET();
596047f369cy
597047f369cy	/* Try with an errno. */
598047f369cy	errno = ENOENT;
599047f369cy	event_warn("Couldn't open %s", "/bad/file");
600047f369cy	evutil_snprintf(buf, sizeof(buf),
601047f369cy	    "Couldn't open /bad/file: %s",strerror(ENOENT));
602047f369cy	LOGEQ(EVENT_LOG_WARN,buf);
603047f369cy	RESET();
604047f369cy
605047f369cy#ifdef CAN_CHECK_ERR
606047f369cy	evutil_snprintf(buf, sizeof(buf),
607047f369cy	    "Couldn't open /very/bad/file: %s",strerror(ENOENT));
608047f369cy	check_error_logging(err_fn, 5, EVENT_LOG_ERR, buf);
609047f369cy	RESET();
610047f369cy#endif
611047f369cy
612047f369cy	/* Try with a socket errno. */
613047f369cy	fd = socket(AF_INET, SOCK_STREAM, 0);
614047f369cy#ifdef _WIN32
615047f369cy	evutil_snprintf(buf, sizeof(buf),
616047f369cy	    "Unhappy socket: %s",
617047f369cy	    evutil_socket_error_to_string(WSAEWOULDBLOCK));
618047f369cy	EVUTIL_SET_SOCKET_ERROR(WSAEWOULDBLOCK);
619047f369cy#else
620047f369cy	evutil_snprintf(buf, sizeof(buf),
621047f369cy	    "Unhappy socket: %s", strerror(EAGAIN));
622047f369cy	errno = EAGAIN;
623047f369cy#endif
624047f369cy	event_sock_warn(fd, "Unhappy socket");
625047f369cy	LOGEQ(EVENT_LOG_WARN, buf);
626047f369cy	RESET();
627047f369cy
628047f369cy#ifdef CAN_CHECK_ERR
629047f369cy	check_error_logging(sock_err_fn, 20, EVENT_LOG_ERR, buf);
630047f369cy	RESET();
631047f369cy#endif
632047f369cy
633047f369cy#undef RESET
634047f369cy#undef LOGEQ
635047f369cyend:
636047f369cy	if (logmsg)
637047f369cy		free(logmsg);
638047f369cy	if (fd >= 0)
639047f369cy		evutil_closesocket(fd);
640047f369cy}
641047f369cy
642047f369cystatic void
643047f369cytest_evutil_strlcpy(void *arg)
644047f369cy{
645047f369cy	char buf[8];
646047f369cy
647047f369cy	/* Successful case. */
648047f369cy	tt_int_op(5, ==, strlcpy(buf, "Hello", sizeof(buf)));
649047f369cy	tt_str_op(buf, ==, "Hello");
650047f369cy
651047f369cy	/* Overflow by a lot. */
652047f369cy	tt_int_op(13, ==, strlcpy(buf, "pentasyllabic", sizeof(buf)));
653047f369cy	tt_str_op(buf, ==, "pentasy");
654047f369cy
655047f369cy	/* Overflow by exactly one. */
656047f369cy	tt_int_op(8, ==, strlcpy(buf, "overlong", sizeof(buf)));
657047f369cy	tt_str_op(buf, ==, "overlon");
658047f369cyend:
659047f369cy	;
660047f369cy}
661047f369cy
662047f369cystruct example_struct {
663047f369cy	const char *a;
664047f369cy	const char *b;
665047f369cy	long c;
666047f369cy};
667047f369cy
668047f369cystatic void
669047f369cytest_evutil_upcast(void *arg)
670047f369cy{
671047f369cy	struct example_struct es1;
672047f369cy	const char **cp;
673047f369cy	es1.a = "World";
674047f369cy	es1.b = "Hello";
675047f369cy	es1.c = -99;
676047f369cy
677047f369cy	tt_int_op(evutil_offsetof(struct example_struct, b), ==, sizeof(char*));
678047f369cy
679047f369cy	cp = &es1.b;
680047f369cy	tt_ptr_op(EVUTIL_UPCAST(cp, struct example_struct, b), ==, &es1);
681047f369cy
682047f369cyend:
683047f369cy	;
684047f369cy}
685047f369cy
686047f369cystatic void
687047f369cytest_evutil_integers(void *arg)
688047f369cy{
689047f369cy	ev_int64_t i64;
690047f369cy	ev_uint64_t u64;
691047f369cy	ev_int32_t i32;
692047f369cy	ev_uint32_t u32;
693047f369cy	ev_int16_t i16;
694047f369cy	ev_uint16_t u16;
695047f369cy	ev_int8_t  i8;
696047f369cy	ev_uint8_t  u8;
697047f369cy
698047f369cy	void *ptr;
699047f369cy	ev_intptr_t iptr;
700047f369cy	ev_uintptr_t uptr;
701047f369cy
702047f369cy	ev_ssize_t ssize;
703047f369cy
704047f369cy	tt_int_op(sizeof(u64), ==, 8);
705047f369cy	tt_int_op(sizeof(i64), ==, 8);
706047f369cy	tt_int_op(sizeof(u32), ==, 4);
707047f369cy	tt_int_op(sizeof(i32), ==, 4);
708047f369cy	tt_int_op(sizeof(u16), ==, 2);
709047f369cy	tt_int_op(sizeof(i16), ==, 2);
710047f369cy	tt_int_op(sizeof(u8), ==,  1);
711047f369cy	tt_int_op(sizeof(i8), ==,  1);
712047f369cy
713047f369cy	tt_int_op(sizeof(ev_ssize_t), ==, sizeof(size_t));
714047f369cy	tt_int_op(sizeof(ev_intptr_t), >=, sizeof(void *));
715047f369cy	tt_int_op(sizeof(ev_uintptr_t), ==, sizeof(intptr_t));
716047f369cy
717047f369cy	u64 = 1000000000;
718047f369cy	u64 *= 1000000000;
719047f369cy	tt_assert(u64 / 1000000000 == 1000000000);
720047f369cy	i64 = -1000000000;
721047f369cy	i64 *= 1000000000;
722047f369cy	tt_assert(i64 / 1000000000 == -1000000000);
723047f369cy
724047f369cy	u64 = EV_UINT64_MAX;
725047f369cy	i64 = EV_INT64_MAX;
726047f369cy	tt_assert(u64 > 0);
727047f369cy	tt_assert(i64 > 0);
728047f369cy	u64++;
729f63afe2cy/*	i64++; */
730047f369cy	tt_assert(u64 == 0);
731f63afe2cy/*	tt_assert(i64 == EV_INT64_MIN); */
732f63afe2cy/*	tt_assert(i64 < 0); */
733047f369cy
734047f369cy	u32 = EV_UINT32_MAX;
735047f369cy	i32 = EV_INT32_MAX;
736047f369cy	tt_assert(u32 > 0);
737047f369cy	tt_assert(i32 > 0);
738047f369cy	u32++;
739f63afe2cy/*	i32++; */
740047f369cy	tt_assert(u32 == 0);
741f63afe2cy/*	tt_assert(i32 == EV_INT32_MIN); */
742f63afe2cy/*	tt_assert(i32 < 0); */
743047f369cy
744047f369cy	u16 = EV_UINT16_MAX;
745047f369cy	i16 = EV_INT16_MAX;
746047f369cy	tt_assert(u16 > 0);
747047f369cy	tt_assert(i16 > 0);
748047f369cy	u16++;
749f63afe2cy/*	i16++; */
750047f369cy	tt_assert(u16 == 0);
751f63afe2cy/*	tt_assert(i16 == EV_INT16_MIN); */
752f63afe2cy/* 	tt_assert(i16 < 0); */
753047f369cy
754047f369cy	u8 = EV_UINT8_MAX;
755047f369cy	i8 = EV_INT8_MAX;
756047f369cy	tt_assert(u8 > 0);
757047f369cy	tt_assert(i8 > 0);
758047f369cy	u8++;
759f63afe2cy/*	i8++;*/
760047f369cy	tt_assert(u8 == 0);
761f63afe2cy/*	tt_assert(i8 == EV_INT8_MIN); */
762f63afe2cy/*	tt_assert(i8 < 0); */
763047f369cy
764f63afe2cy/*
765047f369cy	ssize = EV_SSIZE_MAX;
766047f369cy	tt_assert(ssize > 0);
767047f369cy	ssize++;
768047f369cy	tt_assert(ssize < 0);
769047f369cy	tt_assert(ssize == EV_SSIZE_MIN);
770f63afe2cy*/
771047f369cy
772047f369cy	ptr = &ssize;
773047f369cy	iptr = (ev_intptr_t)ptr;
774047f369cy	uptr = (ev_uintptr_t)ptr;
775047f369cy	ptr = (void *)iptr;
776047f369cy	tt_assert(ptr == &ssize);
777047f369cy	ptr = (void *)uptr;
778047f369cy	tt_assert(ptr == &ssize);
779047f369cy
780047f369cy	iptr = -1;
781047f369cy	tt_assert(iptr < 0);
782047f369cyend:
783047f369cy	;
784047f369cy}
785047f369cy
786047f369cystruct evutil_addrinfo *
787047f369cyai_find_by_family(struct evutil_addrinfo *ai, int family)
788047f369cy{
789047f369cy	while (ai) {
790047f369cy		if (ai->ai_family == family)
791047f369cy			return ai;
792047f369cy		ai = ai->ai_next;
793047f369cy	}
794047f369cy	return NULL;
795047f369cy}
796047f369cy
797047f369cystruct evutil_addrinfo *
798047f369cyai_find_by_protocol(struct evutil_addrinfo *ai, int protocol)
799047f369cy{
800047f369cy	while (ai) {
801047f369cy		if (ai->ai_protocol == protocol)
802047f369cy			return ai;
803047f369cy		ai = ai->ai_next;
804047f369cy	}
805047f369cy	return NULL;
806047f369cy}
807047f369cy
808047f369cy
809047f369cyint
810047f369cytest_ai_eq_(const struct evutil_addrinfo *ai, const char *sockaddr_port,
811047f369cy    int socktype, int protocol, int line)
812047f369cy{
813047f369cy	struct sockaddr_storage ss;
814047f369cy	int slen = sizeof(ss);
815047f369cy	int gotport;
816047f369cy	char buf[128];
817047f369cy	memset(&ss, 0, sizeof(ss));
818047f369cy	if (socktype > 0)
819047f369cy		tt_int_op(ai->ai_socktype, ==, socktype);
820047f369cy	if (protocol > 0)
821047f369cy		tt_int_op(ai->ai_protocol, ==, protocol);
822047f369cy
823047f369cy	if (evutil_parse_sockaddr_port(
824047f369cy		    sockaddr_port, (struct sockaddr*)&ss, &slen)<0) {
825047f369cy		TT_FAIL(("Couldn't parse expected address %s on line %d",
826047f369cy			sockaddr_port, line));
827047f369cy		return -1;
828047f369cy	}
829047f369cy	if (ai->ai_family != ss.ss_family) {
830047f369cy		TT_FAIL(("Address family %d did not match %d on line %d",
831047f369cy			ai->ai_family, ss.ss_family, line));
832047f369cy		return -1;
833047f369cy	}
834047f369cy	if (ai->ai_addr->sa_family == AF_INET) {
835047f369cy		struct sockaddr_in *sin = (struct sockaddr_in*)ai->ai_addr;
836047f369cy		evutil_inet_ntop(AF_INET, &sin->sin_addr, buf, sizeof(buf));
837047f369cy		gotport = ntohs(sin->sin_port);
838047f369cy		if (ai->ai_addrlen != sizeof(struct sockaddr_in)) {
839047f369cy			TT_FAIL(("Addr size mismatch on line %d", line));
840047f369cy			return -1;
841047f369cy		}
842047f369cy	} else {
843047f369cy		struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)ai->ai_addr;
844047f369cy		evutil_inet_ntop(AF_INET6, &sin6->sin6_addr, buf, sizeof(buf));
845047f369cy		gotport = ntohs(sin6->sin6_port);
846047f369cy		if (ai->ai_addrlen != sizeof(struct sockaddr_in6)) {
847047f369cy			TT_FAIL(("Addr size mismatch on line %d", line));
848047f369cy			return -1;
849047f369cy		}
850047f369cy	}
851047f369cy	if (evutil_sockaddr_cmp(ai->ai_addr, (struct sockaddr*)&ss, 1)) {
852047f369cy		TT_FAIL(("Wanted %s, got %s:%d on line %d", sockaddr_port,
853047f369cy			buf, gotport, line));
854047f369cy		return -1;
855047f369cy	} else {
856047f369cy		TT_BLATHER(("Wanted %s, got %s:%d on line %d", sockaddr_port,
857047f369cy			buf, gotport, line));
858047f369cy	}
859047f369cy	return 0;
860047f369cyend:
861047f369cy	TT_FAIL(("Test failed on line %d", line));
862047f369cy	return -1;
863047f369cy}
864047f369cy
865047f369cystatic void
866047f369cytest_evutil_rand(void *arg)
867047f369cy{
868047f369cy	char buf1[32];
869047f369cy	char buf2[32];
870047f369cy	int counts[256];
871047f369cy	int i, j, k, n=0;
872047f369cy	struct evutil_weakrand_state seed = { 12346789U };
873047f369cy
874047f369cy	memset(buf2, 0, sizeof(buf2));
875047f369cy	memset(counts, 0, sizeof(counts));
876047f369cy
877047f369cy	for (k=0;k<32;++k) {
878047f369cy		/* Try a few different start and end points; try to catch
879047f369cy		 * the various misaligned cases of arc4random_buf */
880047f369cy		int startpoint = evutil_weakrand_(&seed) % 4;
881047f369cy		int endpoint = 32 - (evutil_weakrand_(&seed) % 4);
882047f369cy
883047f369cy		memset(buf2, 0, sizeof(buf2));
884047f369cy
885047f369cy		/* Do 6 runs over buf1, or-ing the result into buf2 each
886047f369cy		 * time, to make sure we're setting each byte that we mean
887047f369cy		 * to set. */
888047f369cy		for (i=0;i<8;++i) {
889047f369cy			memset(buf1, 0, sizeof(buf1));
890047f369cy			evutil_secure_rng_get_bytes(buf1 + startpoint,
891047f369cy			    endpoint-startpoint);
892047f369cy			n += endpoint - startpoint;
893047f369cy			for (j=0; j<32; ++j) {
894047f369cy				if (j >= startpoint && j < endpoint) {
895047f369cy					buf2[j] |= buf1[j];
896047f369cy					++counts[(unsigned char)buf1[j]];
897047f369cy				} else {
898047f369cy					tt_assert(buf1[j] == 0);
899047f369cy					tt_int_op(buf1[j], ==, 0);
900047f369cy
901047f369cy				}
902047f369cy			}
903047f369cy		}
904047f369cy
905047f369cy		/* This will give a false positive with P=(256**8)==(2**64)
906047f369cy		 * for each character. */
907047f369cy		for (j=startpoint;j<endpoint;++j) {
908047f369cy			tt_int_op(buf2[j], !=, 0);
909047f369cy		}
910047f369cy	}
911047f369cy
912047f369cy	evutil_weakrand_seed_(&seed, 0);
913047f369cy	for (i = 0; i < 10000; ++i) {
914047f369cy		ev_int32_t r = evutil_weakrand_range_(&seed, 9999);
915047f369cy		tt_int_op(0, <=, r);
916047f369cy		tt_int_op(r, <, 9999);
917047f369cy	}
918047f369cy
919047f369cy	/* for (i=0;i<256;++i) { printf("%3d %2d\n", i, counts[i]); } */
920047f369cyend:
921047f369cy	;
922047f369cy}
923047f369cy
924047f369cystatic void
925047f369cytest_evutil_getaddrinfo(void *arg)
926047f369cy{
927047f369cy	struct evutil_addrinfo *ai = NULL, *a;
928047f369cy	struct evutil_addrinfo hints;
929047f369cy	int r;
930047f369cy
931047f369cy	/* Try using it as a pton. */
932047f369cy	memset(&hints, 0, sizeof(hints));
933047f369cy	hints.ai_family = PF_UNSPEC;
934047f369cy	hints.ai_socktype = SOCK_STREAM;
935047f369cy	r = evutil_getaddrinfo("1.2.3.4", "8080", &hints, &ai);
936047f369cy	tt_int_op(r, ==, 0);
937047f369cy	tt_assert(ai);
938047f369cy	tt_ptr_op(ai->ai_next, ==, NULL); /* no ambiguity */
939047f369cy	test_ai_eq(ai, "1.2.3.4:8080", SOCK_STREAM, IPPROTO_TCP);
940047f369cy	evutil_freeaddrinfo(ai);
941047f369cy	ai = NULL;
942047f369cy
943047f369cy	memset(&hints, 0, sizeof(hints));
944047f369cy	hints.ai_family = PF_UNSPEC;
945047f369cy	hints.ai_protocol = IPPROTO_UDP;
946047f369cy	r = evutil_getaddrinfo("1001:b0b::f00f", "4321", &hints, &ai);
947047f369cy	tt_int_op(r, ==, 0);
948047f369cy	tt_assert(ai);
949047f369cy	tt_ptr_op(ai->ai_next, ==, NULL); /* no ambiguity */
950047f369cy	test_ai_eq(ai, "[1001:b0b::f00f]:4321", SOCK_DGRAM, IPPROTO_UDP);
951047f369cy	evutil_freeaddrinfo(ai);
952047f369cy	ai = NULL;
953047f369cy
954047f369cy	/* Try out the behavior of nodename=NULL */
955047f369cy	memset(&hints, 0, sizeof(hints));
956047f369cy	hints.ai_family = PF_INET;
957047f369cy	hints.ai_protocol = IPPROTO_TCP;
958047f369cy	hints.ai_flags = EVUTIL_AI_PASSIVE; /* as if for bind */
959047f369cy	r = evutil_getaddrinfo(NULL, "9999", &hints, &ai);
960047f369cy	tt_int_op(r,==,0);
961047f369cy	tt_assert(ai);
962047f369cy	tt_ptr_op(ai->ai_next, ==, NULL);
963047f369cy	test_ai_eq(ai, "0.0.0.0:9999", SOCK_STREAM, IPPROTO_TCP);
964047f369cy	evutil_freeaddrinfo(ai);
965047f369cy	ai = NULL;
966047f369cy	hints.ai_flags = 0; /* as if for connect */
967047f369cy	r = evutil_getaddrinfo(NULL, "9998", &hints, &ai);
968047f369cy	tt_assert(ai);
969047f369cy	tt_int_op(r,==,0);
970047f369cy	test_ai_eq(ai, "127.0.0.1:9998", SOCK_STREAM, IPPROTO_TCP);
971047f369cy	tt_ptr_op(ai->ai_next, ==, NULL);
972047f369cy	evutil_freeaddrinfo(ai);
973047f369cy	ai = NULL;
974047f369cy
975047f369cy	hints.ai_flags = 0; /* as if for connect */
976047f369cy	hints.ai_family = PF_INET6;
977047f369cy	r = evutil_getaddrinfo(NULL, "9997", &hints, &ai);
978047f369cy	tt_assert(ai);
979047f369cy	tt_int_op(r,==,0);
980047f369cy	tt_ptr_op(ai->ai_next, ==, NULL);
981047f369cy	test_ai_eq(ai, "[::1]:9997", SOCK_STREAM, IPPROTO_TCP);
982047f369cy	evutil_freeaddrinfo(ai);
983047f369cy	ai = NULL;
984047f369cy
985047f369cy	hints.ai_flags = EVUTIL_AI_PASSIVE; /* as if for bind. */
986047f369cy	hints.ai_family = PF_INET6;
987047f369cy	r = evutil_getaddrinfo(NULL, "9996", &hints, &ai);
988047f369cy	tt_assert(ai);
989047f369cy	tt_int_op(r,==,0);
990047f369cy	tt_ptr_op(ai->ai_next, ==, NULL);
991047f369cy	test_ai_eq(ai, "[::]:9996", SOCK_STREAM, IPPROTO_TCP);
992047f369cy	evutil_freeaddrinfo(ai);
993047f369cy	ai = NULL;
994047f369cy
995047f369cy	/* Now try an unspec one. We should get a v6 and a v4. */
996047f369cy	hints.ai_family = PF_UNSPEC;
997047f369cy	r = evutil_getaddrinfo(NULL, "9996", &hints, &ai);
998047f369cy	tt_assert(ai);
999047f369cy	tt_int_op(r,==,0);
1000047f369cy	a = ai_find_by_family(ai, PF_INET6);
1001047f369cy	tt_assert(a);
1002047f369cy	test_ai_eq(a, "[::]:9996", SOCK_STREAM, IPPROTO_TCP);
1003047f369cy	a = ai_find_by_family(ai, PF_INET);
1004047f369cy	tt_assert(a);
1005047f369cy	test_ai_eq(a, "0.0.0.0:9996", SOCK_STREAM, IPPROTO_TCP);
1006047f369cy	evutil_freeaddrinfo(ai);
1007047f369cy	ai = NULL;
1008047f369cy
1009047f369cy	/* Try out AI_NUMERICHOST: successful case.  Also try
1010047f369cy	 * multiprotocol. */
1011047f369cy	memset(&hints, 0, sizeof(hints));
1012047f369cy	hints.ai_family = PF_UNSPEC;
1013047f369cy	hints.ai_flags = EVUTIL_AI_NUMERICHOST;
1014047f369cy	r = evutil_getaddrinfo("1.2.3.4", NULL, &hints, &ai);
1015047f369cy	tt_int_op(r, ==, 0);
1016047f369cy	a = ai_find_by_protocol(ai, IPPROTO_TCP);
1017047f369cy	tt_assert(a);
1018047f369cy	test_ai_eq(a, "1.2.3.4", SOCK_STREAM, IPPROTO_TCP);
1019047f369cy	a = ai_find_by_protocol(ai, IPPROTO_UDP);
1020047f369cy	tt_assert(a);
1021047f369cy	test_ai_eq(a, "1.2.3.4", SOCK_DGRAM, IPPROTO_UDP);
1022047f369cy	evutil_freeaddrinfo(ai);
1023047f369cy	ai = NULL;
1024047f369cy
1025047f369cy	/* Try the failing case of AI_NUMERICHOST */
1026047f369cy	memset(&hints, 0, sizeof(hints));
1027047f369cy	hints.ai_family = PF_UNSPEC;
1028047f369cy	hints.ai_flags = EVUTIL_AI_NUMERICHOST;
1029047f369cy	r = evutil_getaddrinfo("www.google.com", "80", &hints, &ai);
1030047f369cy	tt_int_op(r, ==, EVUTIL_EAI_NONAME);
1031047f369cy	tt_ptr_op(ai, ==, NULL);
1032047f369cy
1033047f369cy	/* Try symbolic service names wit AI_NUMERICSERV */
1034047f369cy	memset(&hints, 0, sizeof(hints));
1035047f369cy	hints.ai_family = PF_UNSPEC;
1036047f369cy	hints.ai_socktype = SOCK_STREAM;
1037047f369cy	hints.ai_flags = EVUTIL_AI_NUMERICSERV;
1038047f369cy	r = evutil_getaddrinfo("1.2.3.4", "http", &hints, &ai);
1039047f369cy	tt_int_op(r,==,EVUTIL_EAI_NONAME);
1040047f369cy
1041047f369cy	/* Try symbolic service names */
1042047f369cy	memset(&hints, 0, sizeof(hints));
1043047f369cy	hints.ai_family = PF_UNSPEC;
1044047f369cy	hints.ai_socktype = SOCK_STREAM;
1045047f369cy	r = evutil_getaddrinfo("1.2.3.4", "http", &hints, &ai);
1046047f369cy	if (r!=0) {
1047047f369cy		TT_DECLARE("SKIP", ("Symbolic service names seem broken."));
1048047f369cy	} else {
1049047f369cy		tt_assert(ai);
1050047f369cy		test_ai_eq(ai, "1.2.3.4:80", SOCK_STREAM, IPPROTO_TCP);
1051047f369cy		evutil_freeaddrinfo(ai);
1052047f369cy		ai = NULL;
1053047f369cy	}
1054047f369cy
1055047f369cyend:
1056047f369cy	if (ai)
1057047f369cy		evutil_freeaddrinfo(ai);
1058047f369cy}
1059047f369cy
1060047f369cystatic void
1061047f369cytest_evutil_getaddrinfo_live(void *arg)
1062047f369cy{
1063047f369cy	struct evutil_addrinfo *ai = NULL;
1064047f369cy	struct evutil_addrinfo hints;
1065047f369cy
1066047f369cy	struct sockaddr_in6 *sin6;
1067047f369cy	struct sockaddr_in *sin;
1068047f369cy	char buf[128];
1069047f369cy	const char *cp;
1070047f369cy	int r;
1071047f369cy
1072047f369cy	/* Now do some actual lookups. */
1073047f369cy	memset(&hints, 0, sizeof(hints));
1074047f369cy	hints.ai_family = PF_INET;
1075047f369cy	hints.ai_protocol = IPPROTO_TCP;
1076047f369cy	hints.ai_socktype = SOCK_STREAM;
1077047f369cy	r = evutil_getaddrinfo("www.google.com", "80", &hints, &ai);
1078047f369cy	if (r != 0) {
1079047f369cy		TT_DECLARE("SKIP", ("Couldn't resolve www.google.com"));
1080047f369cy	} else {
1081047f369cy		tt_assert(ai);
1082047f369cy		tt_int_op(ai->ai_family, ==, PF_INET);
1083047f369cy		tt_int_op(ai->ai_protocol, ==, IPPROTO_TCP);
1084047f369cy		tt_int_op(ai->ai_socktype, ==, SOCK_STREAM);
1085047f369cy		tt_int_op(ai->ai_addrlen, ==, sizeof(struct sockaddr_in));
1086047f369cy		sin = (struct sockaddr_in*)ai->ai_addr;
1087047f369cy		tt_int_op(sin->sin_family, ==, AF_INET);
1088047f369cy		tt_int_op(sin->sin_port, ==, htons(80));
1089047f369cy		tt_int_op(sin->sin_addr.s_addr, !=, 0xffffffff);
1090047f369cy
1091047f369cy		cp = evutil_inet_ntop(AF_INET, &sin->sin_addr, buf, sizeof(buf));
1092047f369cy		TT_BLATHER(("www.google.com resolved to %s",
1093047f369cy			cp?cp:"<unwriteable>"));
1094047f369cy		evutil_freeaddrinfo(ai);
1095047f369cy		ai = NULL;
1096047f369cy	}
1097047f369cy
1098047f369cy	hints.ai_family = PF_INET6;
1099047f369cy	r = evutil_getaddrinfo("ipv6.google.com", "80", &hints, &ai);
1100047f369cy	if (r != 0) {
1101047f369cy		TT_BLATHER(("Couldn't do an ipv6 lookup for ipv6.google.com"));
1102047f369cy	} else {
1103047f369cy		tt_assert(ai);
1104047f369cy		tt_int_op(ai->ai_family, ==, PF_INET6);
1105047f369cy		tt_int_op(ai->ai_addrlen, ==, sizeof(struct sockaddr_in6));
1106047f369cy		sin6 = (struct sockaddr_in6*)ai->ai_addr;
1107047f369cy		tt_int_op(sin6->sin6_port, ==, htons(80));
1108047f369cy
1109047f369cy		cp = evutil_inet_ntop(AF_INET6, &sin6->sin6_addr, buf,
1110047f369cy		    sizeof(buf));
1111047f369cy		TT_BLATHER(("ipv6.google.com resolved to %s",
1112047f369cy			cp?cp:"<unwriteable>"));
1113047f369cy	}
1114047f369cy
1115047f369cyend:
1116047f369cy	if (ai)
1117047f369cy		evutil_freeaddrinfo(ai);
1118047f369cy}
1119047f369cy
1120047f369cy#ifdef _WIN32
1121047f369cystatic void
1122047f369cytest_evutil_loadsyslib(void *arg)
1123047f369cy{
1124f63afe2cy	HMODULE h=NULL;
1125047f369cy
1126047f369cy	h = evutil_load_windows_system_library_(TEXT("kernel32.dll"));
1127047f369cy	tt_assert(h);
1128047f369cy
1129047f369cyend:
1130047f369cy	if (h)
1131047f369cy		CloseHandle(h);
1132047f369cy
1133047f369cy}
1134047f369cy#endif
1135047f369cy
1136047f369cy/** Test mm_malloc(). */
1137047f369cystatic void
1138047f369cytest_event_malloc(void *arg)
1139047f369cy{
1140047f369cy	void *p = NULL;
1141047f369cy	(void)arg;
1142047f369cy
1143047f369cy	/* mm_malloc(0) should simply return NULL. */
1144047f369cy#ifndef EVENT__DISABLE_MM_REPLACEMENT
1145047f369cy	errno = 0;
1146047f369cy	p = mm_malloc(0);
1147047f369cy	tt_assert(p == NULL);
1148047f369cy	tt_int_op(errno, ==, 0);
1149047f369cy#endif
1150047f369cy
1151047f369cy	/* Trivial case. */
1152047f369cy	errno = 0;
1153047f369cy	p = mm_malloc(8);
1154047f369cy	tt_assert(p != NULL);
1155047f369cy	tt_int_op(errno, ==, 0);
1156047f369cy	mm_free(p);
1157047f369cy
1158047f369cy end:
1159047f369cy	errno = 0;
1160047f369cy	return;
1161047f369cy}
1162047f369cy
1163047f369cystatic void
1164047f369cytest_event_calloc(void *arg)
1165047f369cy{
1166047f369cy	void *p = NULL;
1167047f369cy	(void)arg;
1168047f369cy
1169047f369cy#ifndef EVENT__DISABLE_MM_REPLACEMENT
1170047f369cy	/* mm_calloc() should simply return NULL
1171047f369cy	 * if either argument is zero. */
1172047f369cy	errno = 0;
1173047f369cy	p = mm_calloc(0, 0);
1174047f369cy	tt_assert(p == NULL);
1175047f369cy	tt_int_op(errno, ==, 0);
1176047f369cy	errno = 0;
1177047f369cy	p = mm_calloc(0, 1);
1178047f369cy	tt_assert(p == NULL);
1179047f369cy	tt_int_op(errno, ==, 0);
1180047f369cy	errno = 0;
1181047f369cy	p = mm_calloc(1, 0);
1182047f369cy	tt_assert(p == NULL);
1183047f369cy	tt_int_op(errno, ==, 0);
1184047f369cy#endif
1185047f369cy
1186047f369cy	/* Trivial case. */
1187047f369cy	errno = 0;
1188047f369cy	p = mm_calloc(8, 8);
1189047f369cy	tt_assert(p != NULL);
1190047f369cy	tt_int_op(errno, ==, 0);
1191047f369cy	mm_free(p);
1192047f369cy	p = NULL;
1193047f369cy
1194047f369cy	/* mm_calloc() should set errno = ENOMEM and return NULL
1195047f369cy	 * in case of potential overflow. */
1196047f369cy	errno = 0;
1197047f369cy	p = mm_calloc(EV_SIZE_MAX/2, EV_SIZE_MAX/2 + 8);
1198047f369cy	tt_assert(p == NULL);
1199047f369cy	tt_int_op(errno, ==, ENOMEM);
1200047f369cy
1201047f369cy end:
1202047f369cy	errno = 0;
1203047f369cy	if (p)
1204047f369cy		mm_free(p);
1205047f369cy
1206047f369cy	return;
1207047f369cy}
1208047f369cy
1209047f369cystatic void
1210047f369cytest_event_strdup(void *arg)
1211047f369cy{
1212047f369cy	void *p = NULL;
1213047f369cy	(void)arg;
1214047f369cy
1215047f369cy#ifndef EVENT__DISABLE_MM_REPLACEMENT
1216047f369cy	/* mm_strdup(NULL) should set errno = EINVAL and return NULL. */
1217047f369cy	errno = 0;
1218047f369cy	p = mm_strdup(NULL);
1219047f369cy	tt_assert(p == NULL);
1220047f369cy	tt_int_op(errno, ==, EINVAL);
1221047f369cy#endif
1222047f369cy
1223047f369cy	/* Trivial cases. */
1224047f369cy
1225047f369cy	errno = 0;
1226047f369cy	p = mm_strdup("");
1227047f369cy	tt_assert(p != NULL);
1228047f369cy	tt_int_op(errno, ==, 0);
1229047f369cy	tt_str_op(p, ==, "");
1230047f369cy	mm_free(p);
1231047f369cy
1232047f369cy	errno = 0;
1233047f369cy	p = mm_strdup("foo");
1234047f369cy	tt_assert(p != NULL);
1235047f369cy	tt_int_op(errno, ==, 0);
1236047f369cy	tt_str_op(p, ==, "foo");
1237047f369cy	mm_free(p);
1238047f369cy
1239047f369cy	/* XXX
1240047f369cy	 * mm_strdup(str) where str is a string of length EV_SIZE_MAX
1241047f369cy	 * should set errno = ENOMEM and return NULL. */
1242047f369cy
1243047f369cy end:
1244047f369cy	errno = 0;
1245047f369cy	return;
1246047f369cy}
1247047f369cy
1248047f369cystatic void
1249047f369cytest_evutil_usleep(void *arg)
1250047f369cy{
1251047f369cy	struct timeval tv1, tv2, tv3, diff1, diff2;
1252047f369cy	const struct timeval quarter_sec = {0, 250*1000};
1253047f369cy	const struct timeval tenth_sec = {0, 100*1000};
1254047f369cy	long usec1, usec2;
1255047f369cy
1256047f369cy	evutil_gettimeofday(&tv1, NULL);
1257047f369cy	evutil_usleep_(&quarter_sec);
1258047f369cy	evutil_gettimeofday(&tv2, NULL);
1259047f369cy	evutil_usleep_(&tenth_sec);
1260047f369cy	evutil_gettimeofday(&tv3, NULL);
1261047f369cy
1262047f369cy	evutil_timersub(&tv2, &tv1, &diff1);
1263047f369cy	evutil_timersub(&tv3, &tv2, &diff2);
1264047f369cy	usec1 = diff1.tv_sec * 1000000 + diff1.tv_usec;
1265047f369cy	usec2 = diff2.tv_sec * 1000000 + diff2.tv_usec;
1266047f369cy
1267047f369cy	tt_int_op(usec1, >, 200000);
1268047f369cy	tt_int_op(usec1, <, 300000);
1269047f369cy	tt_int_op(usec2, >,  80000);
1270047f369cy	tt_int_op(usec2, <, 120000);
1271047f369cy
1272047f369cyend:
1273047f369cy	;
1274047f369cy}
1275047f369cy
1276047f369cystatic void
1277047f369cytest_evutil_monotonic_res(void *data_)
1278047f369cy{
1279047f369cy	/* Basic santity-test for monotonic timers.  What we'd really like
1280047f369cy	 * to do is make sure that they can't go backwards even when the
1281047f369cy	 * system clock goes backwards. But we haven't got a good way to
1282047f369cy	 * move the system clock backwards.
1283047f369cy	 */
1284047f369cy	struct basic_test_data *data = data_;
1285047f369cy	struct evutil_monotonic_timer timer;
1286047f369cy	const int precise = strstr(data->setup_data, "precise") != NULL;
1287047f369cy	const int fallback = strstr(data->setup_data, "fallback") != NULL;
1288047f369cy	struct timeval tv[10], delay;
1289047f369cy	int total_diff = 0;
1290047f369cy
1291047f369cy	int flags = 0, wantres, acceptdiff, i;
1292047f369cy	if (precise)
1293047f369cy		flags |= EV_MONOT_PRECISE;
1294047f369cy	if (fallback)
1295047f369cy		flags |= EV_MONOT_FALLBACK;
1296047f369cy	if (precise || fallback) {
1297047f369cy#ifdef _WIN32
1298047f369cy		wantres = 10*1000;
1299047f369cy		acceptdiff = 1000;
1300047f369cy#else
1301047f369cy		wantres = 1000;
1302047f369cy		acceptdiff = 300;
1303047f369cy#endif
1304047f369cy	} else {
1305047f369cy		wantres = 40*1000;
1306047f369cy		acceptdiff = 20*1000;
1307047f369cy	}
1308047f369cy
1309047f369cy	TT_BLATHER(("Precise = %d", precise));
1310047f369cy	TT_BLATHER(("Fallback = %d", fallback));
1311047f369cy
1312047f369cy	/* First, make sure we match up with usleep. */
1313047f369cy
1314047f369cy	delay.tv_sec = 0;
1315047f369cy	delay.tv_usec = wantres;
1316047f369cy
1317047f369cy	tt_int_op(evutil_configure_monotonic_time_(&timer, flags), ==, 0);
1318047f369cy
1319047f369cy	for (i = 0; i < 10; ++i) {
1320047f369cy		evutil_gettime_monotonic_(&timer, &tv[i]);
1321047f369cy		evutil_usleep_(&delay);
1322047f369cy	}
1323047f369cy
1324047f369cy	for (i = 0; i < 9; ++i) {
1325047f369cy		struct timeval diff;
1326047f369cy		tt_assert(evutil_timercmp(&tv[i], &tv[i+1], <));
1327047f369cy		evutil_timersub(&tv[i+1], &tv[i], &diff);
1328047f369cy		tt_int_op(diff.tv_sec, ==, 0);
1329047f369cy		total_diff += diff.tv_usec;
1330047f369cy		TT_BLATHER(("Difference = %d", (int)diff.tv_usec));
1331047f369cy	}
1332047f369cy	tt_int_op(abs(total_diff/9 - wantres), <, acceptdiff);
1333047f369cy
1334047f369cyend:
1335047f369cy	;
1336047f369cy}
1337047f369cy
1338047f369cystatic void
1339047f369cytest_evutil_monotonic_prc(void *data_)
1340047f369cy{
1341047f369cy	struct basic_test_data *data = data_;
1342047f369cy	struct evutil_monotonic_timer timer;
1343047f369cy	const int precise = strstr(data->setup_data, "precise") != NULL;
1344047f369cy	const int fallback = strstr(data->setup_data, "fallback") != NULL;
1345047f369cy	struct timeval tv[10];
1346047f369cy	int total_diff = 0;
1347047f369cy	int i, maxstep = 25*1000,flags=0;
1348047f369cy	if (precise)
1349047f369cy		maxstep = 500;
1350047f369cy	if (precise)
1351047f369cy		flags |= EV_MONOT_PRECISE;
1352047f369cy	if (fallback)
1353047f369cy		flags |= EV_MONOT_FALLBACK;
1354047f369cy	tt_int_op(evutil_configure_monotonic_time_(&timer, flags), ==, 0);
1355047f369cy
1356047f369cy	/* find out what precision we actually see. */
1357047f369cy
1358047f369cy	evutil_gettime_monotonic_(&timer, &tv[0]);
1359047f369cy	for (i = 1; i < 10; ++i) {
1360047f369cy		do {
1361047f369cy			evutil_gettime_monotonic_(&timer, &tv[i]);
1362047f369cy		} while (evutil_timercmp(&tv[i-1], &tv[i], ==));
1363047f369cy	}
1364047f369cy
1365047f369cy	total_diff = 0;
1366047f369cy	for (i = 0; i < 9; ++i) {
1367047f369cy		struct timeval diff;
1368047f369cy		tt_assert(evutil_timercmp(&tv[i], &tv[i+1], <));
1369047f369cy		evutil_timersub(&tv[i+1], &tv[i], &diff);
1370047f369cy		tt_int_op(diff.tv_sec, ==, 0);
1371047f369cy		total_diff += diff.tv_usec;
1372047f369cy		TT_BLATHER(("Step difference = %d", (int)diff.tv_usec));
1373047f369cy	}
1374047f369cy	TT_BLATHER(("Average step difference = %d", total_diff / 9));
1375047f369cy	tt_int_op(total_diff/9, <, maxstep);
1376047f369cy
1377047f369cyend:
1378047f369cy	;
1379047f369cy}
1380047f369cy
1381047f369cystruct testcase_t util_testcases[] = {
1382047f369cy	{ "ipv4_parse", regress_ipv4_parse, 0, NULL, NULL },
1383047f369cy	{ "ipv6_parse", regress_ipv6_parse, 0, NULL, NULL },
1384047f369cy	{ "sockaddr_port_parse", regress_sockaddr_port_parse, 0, NULL, NULL },
1385047f369cy	{ "sockaddr_port_format", regress_sockaddr_port_format, 0, NULL, NULL },
1386047f369cy	{ "sockaddr_predicates", test_evutil_sockaddr_predicates, 0,NULL,NULL },
1387047f369cy	{ "evutil_snprintf", test_evutil_snprintf, 0, NULL, NULL },
1388047f369cy	{ "evutil_strtoll", test_evutil_strtoll, 0, NULL, NULL },
1389047f369cy	{ "evutil_casecmp", test_evutil_casecmp, 0, NULL, NULL },
1390047f369cy	{ "evutil_rtrim", test_evutil_rtrim, 0, NULL, NULL },
1391047f369cy	{ "strlcpy", test_evutil_strlcpy, 0, NULL, NULL },
1392047f369cy	{ "log", test_evutil_log, TT_FORK, NULL, NULL },
1393047f369cy	{ "upcast", test_evutil_upcast, 0, NULL, NULL },
1394047f369cy	{ "integers", test_evutil_integers, 0, NULL, NULL },
1395047f369cy	{ "rand", test_evutil_rand, TT_FORK, NULL, NULL },
1396047f369cy	{ "getaddrinfo", test_evutil_getaddrinfo, TT_FORK, NULL, NULL },
1397047f369cy	{ "getaddrinfo_live", test_evutil_getaddrinfo_live, TT_FORK|TT_OFF_BY_DEFAULT, NULL, NULL },
1398047f369cy#ifdef _WIN32
1399047f369cy	{ "loadsyslib", test_evutil_loadsyslib, TT_FORK, NULL, NULL },
1400047f369cy#endif
1401047f369cy	{ "mm_malloc", test_event_malloc, 0, NULL, NULL },
1402047f369cy	{ "mm_calloc", test_event_calloc, 0, NULL, NULL },
1403047f369cy	{ "mm_strdup", test_event_strdup, 0, NULL, NULL },
1404047f369cy	{ "usleep", test_evutil_usleep, 0, NULL, NULL },
1405047f369cy	{ "monotonic_res", test_evutil_monotonic_res, 0, &basic_setup, (void*)"" },
1406047f369cy	{ "monotonic_res_precise", test_evutil_monotonic_res, TT_OFF_BY_DEFAULT, &basic_setup, (void*)"precise" },
1407047f369cy	{ "monotonic_res_fallback", test_evutil_monotonic_res, TT_OFF_BY_DEFAULT, &basic_setup, (void*)"fallback" },
1408047f369cy	{ "monotonic_prc", test_evutil_monotonic_prc, 0, &basic_setup, (void*)"" },
1409047f369cy	{ "monotonic_prc_precise", test_evutil_monotonic_prc, 0, &basic_setup, (void*)"precise" },
1410047f369cy	{ "monotonic_prc_fallback", test_evutil_monotonic_prc, 0, &basic_setup, (void*)"fallback" },
1411047f369cy	END_OF_TESTCASES,
1412047f369cy};
1413047f369cy
1414