1275970Scy/* 2275970Scy * Copyright (c) 2009-2012 Nick Mathewson and Niels Provos 3275970Scy * 4275970Scy * Redistribution and use in source and binary forms, with or without 5275970Scy * modification, are permitted provided that the following conditions 6275970Scy * are met: 7275970Scy * 1. Redistributions of source code must retain the above copyright 8275970Scy * notice, this list of conditions and the following disclaimer. 9275970Scy * 2. Redistributions in binary form must reproduce the above copyright 10275970Scy * notice, this list of conditions and the following disclaimer in the 11275970Scy * documentation and/or other materials provided with the distribution. 12275970Scy * 3. The name of the author may not be used to endorse or promote products 13275970Scy * derived from this software without specific prior written permission. 14275970Scy * 15275970Scy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16275970Scy * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17275970Scy * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18275970Scy * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19275970Scy * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20275970Scy * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21275970Scy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22275970Scy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23275970Scy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24275970Scy * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25275970Scy */ 26275970Scy#include "../util-internal.h" 27275970Scy 28275970Scy#ifdef _WIN32 29275970Scy#include <winsock2.h> 30275970Scy#include <windows.h> 31275970Scy#include <ws2tcpip.h> 32275970Scy#endif 33275970Scy 34275970Scy#include "event2/event-config.h" 35275970Scy 36275970Scy#include <sys/types.h> 37275970Scy 38275970Scy#ifndef _WIN32 39275970Scy#include <sys/socket.h> 40275970Scy#include <netinet/in.h> 41275970Scy#include <arpa/inet.h> 42275970Scy#include <unistd.h> 43275970Scy#endif 44275970Scy#ifdef EVENT__HAVE_NETINET_IN6_H 45275970Scy#include <netinet/in6.h> 46275970Scy#endif 47275970Scy#ifdef EVENT__HAVE_SYS_WAIT_H 48275970Scy#include <sys/wait.h> 49275970Scy#endif 50275970Scy#include <signal.h> 51275970Scy#include <stdio.h> 52275970Scy#include <stdlib.h> 53275970Scy#include <string.h> 54275970Scy 55275970Scy#include "event2/event.h" 56275970Scy#include "event2/util.h" 57275970Scy#include "../ipv6-internal.h" 58275970Scy#include "../log-internal.h" 59275970Scy#include "../strlcpy-internal.h" 60275970Scy#include "../mm-internal.h" 61275970Scy#include "../time-internal.h" 62275970Scy 63275970Scy#include "regress.h" 64275970Scy 65275970Scyenum entry_status { NORMAL, CANONICAL, BAD }; 66275970Scy 67275970Scy/* This is a big table of results we expect from generating and parsing */ 68275970Scystatic struct ipv4_entry { 69275970Scy const char *addr; 70275970Scy ev_uint32_t res; 71275970Scy enum entry_status status; 72275970Scy} ipv4_entries[] = { 73275970Scy { "1.2.3.4", 0x01020304u, CANONICAL }, 74275970Scy { "255.255.255.255", 0xffffffffu, CANONICAL }, 75275970Scy { "256.0.0.0", 0, BAD }, 76275970Scy { "ABC", 0, BAD }, 77275970Scy { "1.2.3.4.5", 0, BAD }, 78275970Scy { "176.192.208.244", 0xb0c0d0f4, CANONICAL }, 79275970Scy { NULL, 0, BAD }, 80275970Scy}; 81275970Scy 82275970Scystatic struct ipv6_entry { 83275970Scy const char *addr; 84275970Scy ev_uint32_t res[4]; 85275970Scy enum entry_status status; 86275970Scy} ipv6_entries[] = { 87275970Scy { "::", { 0, 0, 0, 0, }, CANONICAL }, 88275970Scy { "0:0:0:0:0:0:0:0", { 0, 0, 0, 0, }, NORMAL }, 89275970Scy { "::1", { 0, 0, 0, 1, }, CANONICAL }, 90275970Scy { "::1.2.3.4", { 0, 0, 0, 0x01020304, }, CANONICAL }, 91275970Scy { "ffff:1::", { 0xffff0001u, 0, 0, 0, }, CANONICAL }, 92275970Scy { "ffff:0000::", { 0xffff0000u, 0, 0, 0, }, NORMAL }, 93275970Scy { "ffff::1234", { 0xffff0000u, 0, 0, 0x1234, }, CANONICAL }, 94275970Scy { "0102::1.2.3.4", {0x01020000u, 0, 0, 0x01020304u }, NORMAL }, 95275970Scy { "::9:c0a8:1:1", { 0, 0, 0x0009c0a8u, 0x00010001u }, CANONICAL }, 96275970Scy { "::ffff:1.2.3.4", { 0, 0, 0x000ffffu, 0x01020304u }, CANONICAL }, 97275970Scy { "FFFF::", { 0xffff0000u, 0, 0, 0 }, NORMAL }, 98275970Scy { "foobar.", { 0, 0, 0, 0 }, BAD }, 99275970Scy { "foobar", { 0, 0, 0, 0 }, BAD }, 100275970Scy { "fo:obar", { 0, 0, 0, 0 }, BAD }, 101275970Scy { "ffff", { 0, 0, 0, 0 }, BAD }, 102275970Scy { "fffff::", { 0, 0, 0, 0 }, BAD }, 103275970Scy { "fffff::", { 0, 0, 0, 0 }, BAD }, 104275970Scy { "::1.0.1.1000", { 0, 0, 0, 0 }, BAD }, 105275970Scy { "1:2:33333:4::", { 0, 0, 0, 0 }, BAD }, 106275970Scy { "1:2:3:4:5:6:7:8:9", { 0, 0, 0, 0 }, BAD }, 107275970Scy { "1::2::3", { 0, 0, 0, 0 }, BAD }, 108275970Scy { ":::1", { 0, 0, 0, 0 }, BAD }, 109275970Scy { NULL, { 0, 0, 0, 0, }, BAD }, 110275970Scy}; 111275970Scy 112275970Scystatic void 113275970Scyregress_ipv4_parse(void *ptr) 114275970Scy{ 115275970Scy int i; 116275970Scy for (i = 0; ipv4_entries[i].addr; ++i) { 117275970Scy char written[128]; 118275970Scy struct ipv4_entry *ent = &ipv4_entries[i]; 119275970Scy struct in_addr in; 120275970Scy int r; 121275970Scy r = evutil_inet_pton(AF_INET, ent->addr, &in); 122275970Scy if (r == 0) { 123275970Scy if (ent->status != BAD) { 124275970Scy TT_FAIL(("%s did not parse, but it's a good address!", 125275970Scy ent->addr)); 126275970Scy } 127275970Scy continue; 128275970Scy } 129275970Scy if (ent->status == BAD) { 130275970Scy TT_FAIL(("%s parsed, but we expected an error", ent->addr)); 131275970Scy continue; 132275970Scy } 133275970Scy if (ntohl(in.s_addr) != ent->res) { 134275970Scy TT_FAIL(("%s parsed to %lx, but we expected %lx", ent->addr, 135275970Scy (unsigned long)ntohl(in.s_addr), 136275970Scy (unsigned long)ent->res)); 137275970Scy continue; 138275970Scy } 139275970Scy if (ent->status == CANONICAL) { 140275970Scy const char *w = evutil_inet_ntop(AF_INET, &in, written, 141275970Scy sizeof(written)); 142275970Scy if (!w) { 143275970Scy TT_FAIL(("Tried to write out %s; got NULL.", ent->addr)); 144275970Scy continue; 145275970Scy } 146275970Scy if (strcmp(written, ent->addr)) { 147275970Scy TT_FAIL(("Tried to write out %s; got %s", 148275970Scy ent->addr, written)); 149275970Scy continue; 150275970Scy } 151275970Scy } 152275970Scy 153275970Scy } 154275970Scy 155275970Scy} 156275970Scy 157275970Scystatic void 158275970Scyregress_ipv6_parse(void *ptr) 159275970Scy{ 160275970Scy#ifdef AF_INET6 161275970Scy int i, j; 162275970Scy 163275970Scy for (i = 0; ipv6_entries[i].addr; ++i) { 164275970Scy char written[128]; 165275970Scy struct ipv6_entry *ent = &ipv6_entries[i]; 166275970Scy struct in6_addr in6; 167275970Scy int r; 168275970Scy r = evutil_inet_pton(AF_INET6, ent->addr, &in6); 169275970Scy if (r == 0) { 170275970Scy if (ent->status != BAD) 171275970Scy TT_FAIL(("%s did not parse, but it's a good address!", 172275970Scy ent->addr)); 173275970Scy continue; 174275970Scy } 175275970Scy if (ent->status == BAD) { 176275970Scy TT_FAIL(("%s parsed, but we expected an error", ent->addr)); 177275970Scy continue; 178275970Scy } 179275970Scy for (j = 0; j < 4; ++j) { 180275970Scy /* Can't use s6_addr32 here; some don't have it. */ 181275970Scy ev_uint32_t u = 182282408Scy ((ev_uint32_t)in6.s6_addr[j*4 ] << 24) | 183282408Scy ((ev_uint32_t)in6.s6_addr[j*4+1] << 16) | 184282408Scy ((ev_uint32_t)in6.s6_addr[j*4+2] << 8) | 185282408Scy ((ev_uint32_t)in6.s6_addr[j*4+3]); 186275970Scy if (u != ent->res[j]) { 187275970Scy TT_FAIL(("%s did not parse as expected.", ent->addr)); 188275970Scy continue; 189275970Scy } 190275970Scy } 191275970Scy if (ent->status == CANONICAL) { 192275970Scy const char *w = evutil_inet_ntop(AF_INET6, &in6, written, 193275970Scy sizeof(written)); 194275970Scy if (!w) { 195275970Scy TT_FAIL(("Tried to write out %s; got NULL.", ent->addr)); 196275970Scy continue; 197275970Scy } 198275970Scy if (strcmp(written, ent->addr)) { 199275970Scy TT_FAIL(("Tried to write out %s; got %s", ent->addr, written)); 200275970Scy continue; 201275970Scy } 202275970Scy } 203275970Scy 204275970Scy } 205275970Scy#else 206275970Scy TT_BLATHER(("Skipping IPv6 address parsing.")); 207275970Scy#endif 208275970Scy} 209275970Scy 210275970Scystatic struct sa_port_ent { 211275970Scy const char *parse; 212275970Scy int safamily; 213275970Scy const char *addr; 214275970Scy int port; 215275970Scy} sa_port_ents[] = { 216275970Scy { "[ffff::1]:1000", AF_INET6, "ffff::1", 1000 }, 217275970Scy { "[ffff::1]", AF_INET6, "ffff::1", 0 }, 218275970Scy { "[ffff::1", 0, NULL, 0 }, 219275970Scy { "[ffff::1]:65599", 0, NULL, 0 }, 220275970Scy { "[ffff::1]:0", 0, NULL, 0 }, 221275970Scy { "[ffff::1]:-1", 0, NULL, 0 }, 222275970Scy { "::1", AF_INET6, "::1", 0 }, 223275970Scy { "1:2::1", AF_INET6, "1:2::1", 0 }, 224275970Scy { "192.168.0.1:50", AF_INET, "192.168.0.1", 50 }, 225275970Scy { "1.2.3.4", AF_INET, "1.2.3.4", 0 }, 226275970Scy { NULL, 0, NULL, 0 }, 227275970Scy}; 228275970Scy 229275970Scystatic void 230275970Scyregress_sockaddr_port_parse(void *ptr) 231275970Scy{ 232275970Scy struct sockaddr_storage ss; 233275970Scy int i, r; 234275970Scy 235275970Scy for (i = 0; sa_port_ents[i].parse; ++i) { 236275970Scy struct sa_port_ent *ent = &sa_port_ents[i]; 237275970Scy int len = sizeof(ss); 238275970Scy memset(&ss, 0, sizeof(ss)); 239275970Scy r = evutil_parse_sockaddr_port(ent->parse, (struct sockaddr*)&ss, &len); 240275970Scy if (r < 0) { 241275970Scy if (ent->safamily) 242275970Scy TT_FAIL(("Couldn't parse %s!", ent->parse)); 243275970Scy continue; 244275970Scy } else if (! ent->safamily) { 245275970Scy TT_FAIL(("Shouldn't have been able to parse %s!", ent->parse)); 246275970Scy continue; 247275970Scy } 248275970Scy if (ent->safamily == AF_INET) { 249275970Scy struct sockaddr_in sin; 250275970Scy memset(&sin, 0, sizeof(sin)); 251275970Scy#ifdef EVENT__HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 252275970Scy sin.sin_len = sizeof(sin); 253275970Scy#endif 254275970Scy sin.sin_family = AF_INET; 255275970Scy sin.sin_port = htons(ent->port); 256275970Scy r = evutil_inet_pton(AF_INET, ent->addr, &sin.sin_addr); 257275970Scy if (1 != r) { 258275970Scy TT_FAIL(("Couldn't parse ipv4 target %s.", ent->addr)); 259275970Scy } else if (memcmp(&sin, &ss, sizeof(sin))) { 260275970Scy TT_FAIL(("Parse for %s was not as expected.", ent->parse)); 261275970Scy } else if (len != sizeof(sin)) { 262275970Scy TT_FAIL(("Length for %s not as expected.",ent->parse)); 263275970Scy } 264275970Scy } else { 265275970Scy struct sockaddr_in6 sin6; 266275970Scy memset(&sin6, 0, sizeof(sin6)); 267275970Scy#ifdef EVENT__HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN 268275970Scy sin6.sin6_len = sizeof(sin6); 269275970Scy#endif 270275970Scy sin6.sin6_family = AF_INET6; 271275970Scy sin6.sin6_port = htons(ent->port); 272275970Scy r = evutil_inet_pton(AF_INET6, ent->addr, &sin6.sin6_addr); 273275970Scy if (1 != r) { 274275970Scy TT_FAIL(("Couldn't parse ipv6 target %s.", ent->addr)); 275275970Scy } else if (memcmp(&sin6, &ss, sizeof(sin6))) { 276275970Scy TT_FAIL(("Parse for %s was not as expected.", ent->parse)); 277275970Scy } else if (len != sizeof(sin6)) { 278275970Scy TT_FAIL(("Length for %s not as expected.",ent->parse)); 279275970Scy } 280275970Scy } 281275970Scy } 282275970Scy} 283275970Scy 284275970Scy 285275970Scystatic void 286275970Scyregress_sockaddr_port_format(void *ptr) 287275970Scy{ 288275970Scy struct sockaddr_storage ss; 289275970Scy int len; 290275970Scy const char *cp; 291275970Scy char cbuf[128]; 292275970Scy int r; 293275970Scy 294275970Scy len = sizeof(ss); 295275970Scy r = evutil_parse_sockaddr_port("192.168.1.1:80", 296275970Scy (struct sockaddr*)&ss, &len); 297275970Scy tt_int_op(r,==,0); 298275970Scy cp = evutil_format_sockaddr_port_( 299275970Scy (struct sockaddr*)&ss, cbuf, sizeof(cbuf)); 300275970Scy tt_ptr_op(cp,==,cbuf); 301275970Scy tt_str_op(cp,==,"192.168.1.1:80"); 302275970Scy 303275970Scy len = sizeof(ss); 304275970Scy r = evutil_parse_sockaddr_port("[ff00::8010]:999", 305275970Scy (struct sockaddr*)&ss, &len); 306275970Scy tt_int_op(r,==,0); 307275970Scy cp = evutil_format_sockaddr_port_( 308275970Scy (struct sockaddr*)&ss, cbuf, sizeof(cbuf)); 309275970Scy tt_ptr_op(cp,==,cbuf); 310275970Scy tt_str_op(cp,==,"[ff00::8010]:999"); 311275970Scy 312275970Scy ss.ss_family=99; 313275970Scy cp = evutil_format_sockaddr_port_( 314275970Scy (struct sockaddr*)&ss, cbuf, sizeof(cbuf)); 315275970Scy tt_ptr_op(cp,==,cbuf); 316275970Scy tt_str_op(cp,==,"<addr with socktype 99>"); 317275970Scyend: 318275970Scy ; 319275970Scy} 320275970Scy 321275970Scystatic struct sa_pred_ent { 322275970Scy const char *parse; 323275970Scy 324275970Scy int is_loopback; 325275970Scy} sa_pred_entries[] = { 326275970Scy { "127.0.0.1", 1 }, 327275970Scy { "127.0.3.2", 1 }, 328275970Scy { "128.1.2.3", 0 }, 329275970Scy { "18.0.0.1", 0 }, 330275970Scy { "129.168.1.1", 0 }, 331275970Scy 332275970Scy { "::1", 1 }, 333275970Scy { "::0", 0 }, 334275970Scy { "f::1", 0 }, 335275970Scy { "::501", 0 }, 336275970Scy { NULL, 0 }, 337275970Scy 338275970Scy}; 339275970Scy 340275970Scystatic void 341275970Scytest_evutil_sockaddr_predicates(void *ptr) 342275970Scy{ 343275970Scy struct sockaddr_storage ss; 344275970Scy int r, i; 345275970Scy 346275970Scy for (i=0; sa_pred_entries[i].parse; ++i) { 347275970Scy struct sa_pred_ent *ent = &sa_pred_entries[i]; 348275970Scy int len = sizeof(ss); 349275970Scy 350275970Scy r = evutil_parse_sockaddr_port(ent->parse, (struct sockaddr*)&ss, &len); 351275970Scy 352275970Scy if (r<0) { 353275970Scy TT_FAIL(("Couldn't parse %s!", ent->parse)); 354275970Scy continue; 355275970Scy } 356275970Scy 357275970Scy /* sockaddr_is_loopback */ 358275970Scy if (ent->is_loopback != evutil_sockaddr_is_loopback_((struct sockaddr*)&ss)) { 359275970Scy TT_FAIL(("evutil_sockaddr_loopback(%s) not as expected", 360275970Scy ent->parse)); 361275970Scy } 362275970Scy } 363275970Scy} 364275970Scy 365275970Scystatic void 366275970Scytest_evutil_strtoll(void *ptr) 367275970Scy{ 368275970Scy const char *s; 369275970Scy char *endptr; 370275970Scy 371275970Scy tt_want(evutil_strtoll("5000000000", NULL, 10) == 372275970Scy ((ev_int64_t)5000000)*1000); 373275970Scy tt_want(evutil_strtoll("-5000000000", NULL, 10) == 374275970Scy ((ev_int64_t)5000000)*-1000); 375275970Scy s = " 99999stuff"; 376275970Scy tt_want(evutil_strtoll(s, &endptr, 10) == (ev_int64_t)99999); 377275970Scy tt_want(endptr == s+6); 378275970Scy tt_want(evutil_strtoll("foo", NULL, 10) == 0); 379275970Scy } 380275970Scy 381275970Scystatic void 382275970Scytest_evutil_snprintf(void *ptr) 383275970Scy{ 384275970Scy char buf[16]; 385275970Scy int r; 386275970Scy ev_uint64_t u64 = ((ev_uint64_t)1000000000)*200; 387275970Scy ev_int64_t i64 = -1 * (ev_int64_t) u64; 388275970Scy size_t size = 8000; 389275970Scy ev_ssize_t ssize = -9000; 390275970Scy 391275970Scy r = evutil_snprintf(buf, sizeof(buf), "%d %d", 50, 100); 392275970Scy tt_str_op(buf, ==, "50 100"); 393275970Scy tt_int_op(r, ==, 6); 394275970Scy 395275970Scy r = evutil_snprintf(buf, sizeof(buf), "longish %d", 1234567890); 396275970Scy tt_str_op(buf, ==, "longish 1234567"); 397275970Scy tt_int_op(r, ==, 18); 398275970Scy 399275970Scy r = evutil_snprintf(buf, sizeof(buf), EV_U64_FMT, EV_U64_ARG(u64)); 400275970Scy tt_str_op(buf, ==, "200000000000"); 401275970Scy tt_int_op(r, ==, 12); 402275970Scy 403275970Scy r = evutil_snprintf(buf, sizeof(buf), EV_I64_FMT, EV_I64_ARG(i64)); 404275970Scy tt_str_op(buf, ==, "-200000000000"); 405275970Scy tt_int_op(r, ==, 13); 406275970Scy 407275970Scy r = evutil_snprintf(buf, sizeof(buf), EV_SIZE_FMT" "EV_SSIZE_FMT, 408275970Scy EV_SIZE_ARG(size), EV_SSIZE_ARG(ssize)); 409275970Scy tt_str_op(buf, ==, "8000 -9000"); 410275970Scy tt_int_op(r, ==, 10); 411275970Scy 412275970Scy end: 413275970Scy ; 414275970Scy} 415275970Scy 416275970Scystatic void 417275970Scytest_evutil_casecmp(void *ptr) 418275970Scy{ 419275970Scy tt_int_op(evutil_ascii_strcasecmp("ABC", "ABC"), ==, 0); 420275970Scy tt_int_op(evutil_ascii_strcasecmp("ABC", "abc"), ==, 0); 421275970Scy tt_int_op(evutil_ascii_strcasecmp("ABC", "abcd"), <, 0); 422275970Scy tt_int_op(evutil_ascii_strcasecmp("ABC", "abb"), >, 0); 423275970Scy tt_int_op(evutil_ascii_strcasecmp("ABCd", "abc"), >, 0); 424275970Scy 425275970Scy tt_int_op(evutil_ascii_strncasecmp("Libevent", "LibEvEnT", 100), ==, 0); 426275970Scy tt_int_op(evutil_ascii_strncasecmp("Libevent", "LibEvEnT", 4), ==, 0); 427275970Scy tt_int_op(evutil_ascii_strncasecmp("Libevent", "LibEXXXX", 4), ==, 0); 428275970Scy tt_int_op(evutil_ascii_strncasecmp("Libevent", "LibE", 4), ==, 0); 429275970Scy tt_int_op(evutil_ascii_strncasecmp("Libe", "LibEvEnT", 4), ==, 0); 430275970Scy tt_int_op(evutil_ascii_strncasecmp("Lib", "LibEvEnT", 4), <, 0); 431275970Scy tt_int_op(evutil_ascii_strncasecmp("abc", "def", 99), <, 0); 432275970Scy tt_int_op(evutil_ascii_strncasecmp("Z", "qrst", 1), >, 0); 433275970Scyend: 434275970Scy ; 435275970Scy} 436275970Scy 437275970Scystatic void 438275970Scytest_evutil_rtrim(void *ptr) 439275970Scy{ 440275970Scy#define TEST_TRIM(s, result) \ 441275970Scy do { \ 442275970Scy if (cp) mm_free(cp); \ 443275970Scy cp = mm_strdup(s); \ 444275970Scy tt_assert(cp); \ 445275970Scy evutil_rtrim_lws_(cp); \ 446275970Scy tt_str_op(cp, ==, result); \ 447275970Scy } while(0) 448275970Scy 449275970Scy char *cp = NULL; 450275970Scy (void) ptr; 451275970Scy 452275970Scy TEST_TRIM("", ""); 453275970Scy TEST_TRIM("a", "a"); 454275970Scy TEST_TRIM("abcdef ghi", "abcdef ghi"); 455275970Scy 456275970Scy TEST_TRIM(" ", ""); 457275970Scy TEST_TRIM(" ", ""); 458275970Scy TEST_TRIM("a ", "a"); 459275970Scy TEST_TRIM("abcdef gH ", "abcdef gH"); 460275970Scy 461275970Scy TEST_TRIM("\t\t", ""); 462275970Scy TEST_TRIM(" \t", ""); 463275970Scy TEST_TRIM("\t", ""); 464275970Scy TEST_TRIM("a \t", "a"); 465275970Scy TEST_TRIM("a\t ", "a"); 466275970Scy TEST_TRIM("a\t", "a"); 467275970Scy TEST_TRIM("abcdef gH \t ", "abcdef gH"); 468275970Scy 469275970Scyend: 470275970Scy if (cp) 471275970Scy mm_free(cp); 472275970Scy} 473275970Scy 474275970Scystatic int logsev = 0; 475275970Scystatic char *logmsg = NULL; 476275970Scy 477275970Scystatic void 478275970Scylogfn(int severity, const char *msg) 479275970Scy{ 480275970Scy logsev = severity; 481275970Scy tt_want(msg); 482275970Scy if (msg) { 483275970Scy if (logmsg) 484275970Scy free(logmsg); 485275970Scy logmsg = strdup(msg); 486275970Scy } 487275970Scy} 488275970Scy 489275970Scystatic int fatal_want_severity = 0; 490275970Scystatic const char *fatal_want_message = NULL; 491275970Scystatic void 492275970Scyfatalfn(int exitcode) 493275970Scy{ 494275970Scy if (logsev != fatal_want_severity || 495275970Scy !logmsg || 496275970Scy strcmp(logmsg, fatal_want_message)) 497275970Scy exit(0); 498275970Scy else 499275970Scy exit(exitcode); 500275970Scy} 501275970Scy 502275970Scy#ifndef _WIN32 503275970Scy#define CAN_CHECK_ERR 504275970Scystatic void 505275970Scycheck_error_logging(void (*fn)(void), int wantexitcode, 506275970Scy int wantseverity, const char *wantmsg) 507275970Scy{ 508275970Scy pid_t pid; 509275970Scy int status = 0, exitcode; 510275970Scy fatal_want_severity = wantseverity; 511275970Scy fatal_want_message = wantmsg; 512275970Scy if ((pid = regress_fork()) == 0) { 513275970Scy /* child process */ 514275970Scy fn(); 515275970Scy exit(0); /* should be unreachable. */ 516275970Scy } else { 517275970Scy wait(&status); 518275970Scy exitcode = WEXITSTATUS(status); 519275970Scy tt_int_op(wantexitcode, ==, exitcode); 520275970Scy } 521275970Scyend: 522275970Scy ; 523275970Scy} 524275970Scy 525275970Scystatic void 526275970Scyerrx_fn(void) 527275970Scy{ 528275970Scy event_errx(2, "Fatal error; too many kumquats (%d)", 5); 529275970Scy} 530275970Scy 531275970Scystatic void 532275970Scyerr_fn(void) 533275970Scy{ 534275970Scy errno = ENOENT; 535275970Scy event_err(5,"Couldn't open %s", "/very/bad/file"); 536275970Scy} 537275970Scy 538275970Scystatic void 539275970Scysock_err_fn(void) 540275970Scy{ 541275970Scy evutil_socket_t fd = socket(AF_INET, SOCK_STREAM, 0); 542275970Scy#ifdef _WIN32 543275970Scy EVUTIL_SET_SOCKET_ERROR(WSAEWOULDBLOCK); 544275970Scy#else 545275970Scy errno = EAGAIN; 546275970Scy#endif 547275970Scy event_sock_err(20, fd, "Unhappy socket"); 548275970Scy} 549275970Scy#endif 550275970Scy 551275970Scystatic void 552275970Scytest_evutil_log(void *ptr) 553275970Scy{ 554275970Scy evutil_socket_t fd = -1; 555275970Scy char buf[128]; 556275970Scy 557275970Scy event_set_log_callback(logfn); 558275970Scy event_set_fatal_callback(fatalfn); 559275970Scy#define RESET() do { \ 560275970Scy logsev = 0; \ 561275970Scy if (logmsg) free(logmsg); \ 562275970Scy logmsg = NULL; \ 563275970Scy } while (0) 564275970Scy#define LOGEQ(sev,msg) do { \ 565275970Scy tt_int_op(logsev,==,sev); \ 566275970Scy tt_assert(logmsg != NULL); \ 567275970Scy tt_str_op(logmsg,==,msg); \ 568275970Scy } while (0) 569275970Scy 570275970Scy#ifdef CAN_CHECK_ERR 571275970Scy /* We need to disable these tests for now. Previously, the logging 572275970Scy * module didn't enforce the requirement that a fatal callback 573275970Scy * actually exit. Now, it exits no matter what, so if we wan to 574275970Scy * reinstate these tests, we'll need to fork for each one. */ 575275970Scy check_error_logging(errx_fn, 2, EVENT_LOG_ERR, 576275970Scy "Fatal error; too many kumquats (5)"); 577275970Scy RESET(); 578275970Scy#endif 579275970Scy 580275970Scy event_warnx("Far too many %s (%d)", "wombats", 99); 581275970Scy LOGEQ(EVENT_LOG_WARN, "Far too many wombats (99)"); 582275970Scy RESET(); 583275970Scy 584275970Scy event_msgx("Connecting lime to coconut"); 585275970Scy LOGEQ(EVENT_LOG_MSG, "Connecting lime to coconut"); 586275970Scy RESET(); 587275970Scy 588275970Scy event_debug(("A millisecond passed! We should log that!")); 589275970Scy#ifdef USE_DEBUG 590275970Scy LOGEQ(EVENT_LOG_DEBUG, "A millisecond passed! We should log that!"); 591275970Scy#else 592275970Scy tt_int_op(logsev,==,0); 593275970Scy tt_ptr_op(logmsg,==,NULL); 594275970Scy#endif 595275970Scy RESET(); 596275970Scy 597275970Scy /* Try with an errno. */ 598275970Scy errno = ENOENT; 599275970Scy event_warn("Couldn't open %s", "/bad/file"); 600275970Scy evutil_snprintf(buf, sizeof(buf), 601275970Scy "Couldn't open /bad/file: %s",strerror(ENOENT)); 602275970Scy LOGEQ(EVENT_LOG_WARN,buf); 603275970Scy RESET(); 604275970Scy 605275970Scy#ifdef CAN_CHECK_ERR 606275970Scy evutil_snprintf(buf, sizeof(buf), 607275970Scy "Couldn't open /very/bad/file: %s",strerror(ENOENT)); 608275970Scy check_error_logging(err_fn, 5, EVENT_LOG_ERR, buf); 609275970Scy RESET(); 610275970Scy#endif 611275970Scy 612275970Scy /* Try with a socket errno. */ 613275970Scy fd = socket(AF_INET, SOCK_STREAM, 0); 614275970Scy#ifdef _WIN32 615275970Scy evutil_snprintf(buf, sizeof(buf), 616275970Scy "Unhappy socket: %s", 617275970Scy evutil_socket_error_to_string(WSAEWOULDBLOCK)); 618275970Scy EVUTIL_SET_SOCKET_ERROR(WSAEWOULDBLOCK); 619275970Scy#else 620275970Scy evutil_snprintf(buf, sizeof(buf), 621275970Scy "Unhappy socket: %s", strerror(EAGAIN)); 622275970Scy errno = EAGAIN; 623275970Scy#endif 624275970Scy event_sock_warn(fd, "Unhappy socket"); 625275970Scy LOGEQ(EVENT_LOG_WARN, buf); 626275970Scy RESET(); 627275970Scy 628275970Scy#ifdef CAN_CHECK_ERR 629275970Scy check_error_logging(sock_err_fn, 20, EVENT_LOG_ERR, buf); 630275970Scy RESET(); 631275970Scy#endif 632275970Scy 633275970Scy#undef RESET 634275970Scy#undef LOGEQ 635275970Scyend: 636275970Scy if (logmsg) 637275970Scy free(logmsg); 638275970Scy if (fd >= 0) 639275970Scy evutil_closesocket(fd); 640275970Scy} 641275970Scy 642275970Scystatic void 643275970Scytest_evutil_strlcpy(void *arg) 644275970Scy{ 645275970Scy char buf[8]; 646275970Scy 647275970Scy /* Successful case. */ 648275970Scy tt_int_op(5, ==, strlcpy(buf, "Hello", sizeof(buf))); 649275970Scy tt_str_op(buf, ==, "Hello"); 650275970Scy 651275970Scy /* Overflow by a lot. */ 652275970Scy tt_int_op(13, ==, strlcpy(buf, "pentasyllabic", sizeof(buf))); 653275970Scy tt_str_op(buf, ==, "pentasy"); 654275970Scy 655275970Scy /* Overflow by exactly one. */ 656275970Scy tt_int_op(8, ==, strlcpy(buf, "overlong", sizeof(buf))); 657275970Scy tt_str_op(buf, ==, "overlon"); 658275970Scyend: 659275970Scy ; 660275970Scy} 661275970Scy 662275970Scystruct example_struct { 663275970Scy const char *a; 664275970Scy const char *b; 665275970Scy long c; 666275970Scy}; 667275970Scy 668275970Scystatic void 669275970Scytest_evutil_upcast(void *arg) 670275970Scy{ 671275970Scy struct example_struct es1; 672275970Scy const char **cp; 673275970Scy es1.a = "World"; 674275970Scy es1.b = "Hello"; 675275970Scy es1.c = -99; 676275970Scy 677275970Scy tt_int_op(evutil_offsetof(struct example_struct, b), ==, sizeof(char*)); 678275970Scy 679275970Scy cp = &es1.b; 680275970Scy tt_ptr_op(EVUTIL_UPCAST(cp, struct example_struct, b), ==, &es1); 681275970Scy 682275970Scyend: 683275970Scy ; 684275970Scy} 685275970Scy 686275970Scystatic void 687275970Scytest_evutil_integers(void *arg) 688275970Scy{ 689275970Scy ev_int64_t i64; 690275970Scy ev_uint64_t u64; 691275970Scy ev_int32_t i32; 692275970Scy ev_uint32_t u32; 693275970Scy ev_int16_t i16; 694275970Scy ev_uint16_t u16; 695275970Scy ev_int8_t i8; 696275970Scy ev_uint8_t u8; 697275970Scy 698275970Scy void *ptr; 699275970Scy ev_intptr_t iptr; 700275970Scy ev_uintptr_t uptr; 701275970Scy 702275970Scy ev_ssize_t ssize; 703275970Scy 704275970Scy tt_int_op(sizeof(u64), ==, 8); 705275970Scy tt_int_op(sizeof(i64), ==, 8); 706275970Scy tt_int_op(sizeof(u32), ==, 4); 707275970Scy tt_int_op(sizeof(i32), ==, 4); 708275970Scy tt_int_op(sizeof(u16), ==, 2); 709275970Scy tt_int_op(sizeof(i16), ==, 2); 710275970Scy tt_int_op(sizeof(u8), ==, 1); 711275970Scy tt_int_op(sizeof(i8), ==, 1); 712275970Scy 713275970Scy tt_int_op(sizeof(ev_ssize_t), ==, sizeof(size_t)); 714275970Scy tt_int_op(sizeof(ev_intptr_t), >=, sizeof(void *)); 715275970Scy tt_int_op(sizeof(ev_uintptr_t), ==, sizeof(intptr_t)); 716275970Scy 717275970Scy u64 = 1000000000; 718275970Scy u64 *= 1000000000; 719275970Scy tt_assert(u64 / 1000000000 == 1000000000); 720275970Scy i64 = -1000000000; 721275970Scy i64 *= 1000000000; 722275970Scy tt_assert(i64 / 1000000000 == -1000000000); 723275970Scy 724275970Scy u64 = EV_UINT64_MAX; 725275970Scy i64 = EV_INT64_MAX; 726275970Scy tt_assert(u64 > 0); 727275970Scy tt_assert(i64 > 0); 728275970Scy u64++; 729282408Scy/* i64++; */ 730275970Scy tt_assert(u64 == 0); 731282408Scy/* tt_assert(i64 == EV_INT64_MIN); */ 732282408Scy/* tt_assert(i64 < 0); */ 733275970Scy 734275970Scy u32 = EV_UINT32_MAX; 735275970Scy i32 = EV_INT32_MAX; 736275970Scy tt_assert(u32 > 0); 737275970Scy tt_assert(i32 > 0); 738275970Scy u32++; 739282408Scy/* i32++; */ 740275970Scy tt_assert(u32 == 0); 741282408Scy/* tt_assert(i32 == EV_INT32_MIN); */ 742282408Scy/* tt_assert(i32 < 0); */ 743275970Scy 744275970Scy u16 = EV_UINT16_MAX; 745275970Scy i16 = EV_INT16_MAX; 746275970Scy tt_assert(u16 > 0); 747275970Scy tt_assert(i16 > 0); 748275970Scy u16++; 749282408Scy/* i16++; */ 750275970Scy tt_assert(u16 == 0); 751282408Scy/* tt_assert(i16 == EV_INT16_MIN); */ 752282408Scy/* tt_assert(i16 < 0); */ 753275970Scy 754275970Scy u8 = EV_UINT8_MAX; 755275970Scy i8 = EV_INT8_MAX; 756275970Scy tt_assert(u8 > 0); 757275970Scy tt_assert(i8 > 0); 758275970Scy u8++; 759282408Scy/* i8++;*/ 760275970Scy tt_assert(u8 == 0); 761282408Scy/* tt_assert(i8 == EV_INT8_MIN); */ 762282408Scy/* tt_assert(i8 < 0); */ 763275970Scy 764282408Scy/* 765275970Scy ssize = EV_SSIZE_MAX; 766275970Scy tt_assert(ssize > 0); 767275970Scy ssize++; 768275970Scy tt_assert(ssize < 0); 769275970Scy tt_assert(ssize == EV_SSIZE_MIN); 770282408Scy*/ 771275970Scy 772275970Scy ptr = &ssize; 773275970Scy iptr = (ev_intptr_t)ptr; 774275970Scy uptr = (ev_uintptr_t)ptr; 775275970Scy ptr = (void *)iptr; 776275970Scy tt_assert(ptr == &ssize); 777275970Scy ptr = (void *)uptr; 778275970Scy tt_assert(ptr == &ssize); 779275970Scy 780275970Scy iptr = -1; 781275970Scy tt_assert(iptr < 0); 782275970Scyend: 783275970Scy ; 784275970Scy} 785275970Scy 786275970Scystruct evutil_addrinfo * 787275970Scyai_find_by_family(struct evutil_addrinfo *ai, int family) 788275970Scy{ 789275970Scy while (ai) { 790275970Scy if (ai->ai_family == family) 791275970Scy return ai; 792275970Scy ai = ai->ai_next; 793275970Scy } 794275970Scy return NULL; 795275970Scy} 796275970Scy 797275970Scystruct evutil_addrinfo * 798275970Scyai_find_by_protocol(struct evutil_addrinfo *ai, int protocol) 799275970Scy{ 800275970Scy while (ai) { 801275970Scy if (ai->ai_protocol == protocol) 802275970Scy return ai; 803275970Scy ai = ai->ai_next; 804275970Scy } 805275970Scy return NULL; 806275970Scy} 807275970Scy 808275970Scy 809275970Scyint 810275970Scytest_ai_eq_(const struct evutil_addrinfo *ai, const char *sockaddr_port, 811275970Scy int socktype, int protocol, int line) 812275970Scy{ 813275970Scy struct sockaddr_storage ss; 814275970Scy int slen = sizeof(ss); 815275970Scy int gotport; 816275970Scy char buf[128]; 817275970Scy memset(&ss, 0, sizeof(ss)); 818275970Scy if (socktype > 0) 819275970Scy tt_int_op(ai->ai_socktype, ==, socktype); 820275970Scy if (protocol > 0) 821275970Scy tt_int_op(ai->ai_protocol, ==, protocol); 822275970Scy 823275970Scy if (evutil_parse_sockaddr_port( 824275970Scy sockaddr_port, (struct sockaddr*)&ss, &slen)<0) { 825275970Scy TT_FAIL(("Couldn't parse expected address %s on line %d", 826275970Scy sockaddr_port, line)); 827275970Scy return -1; 828275970Scy } 829275970Scy if (ai->ai_family != ss.ss_family) { 830275970Scy TT_FAIL(("Address family %d did not match %d on line %d", 831275970Scy ai->ai_family, ss.ss_family, line)); 832275970Scy return -1; 833275970Scy } 834275970Scy if (ai->ai_addr->sa_family == AF_INET) { 835275970Scy struct sockaddr_in *sin = (struct sockaddr_in*)ai->ai_addr; 836275970Scy evutil_inet_ntop(AF_INET, &sin->sin_addr, buf, sizeof(buf)); 837275970Scy gotport = ntohs(sin->sin_port); 838275970Scy if (ai->ai_addrlen != sizeof(struct sockaddr_in)) { 839275970Scy TT_FAIL(("Addr size mismatch on line %d", line)); 840275970Scy return -1; 841275970Scy } 842275970Scy } else { 843275970Scy struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)ai->ai_addr; 844275970Scy evutil_inet_ntop(AF_INET6, &sin6->sin6_addr, buf, sizeof(buf)); 845275970Scy gotport = ntohs(sin6->sin6_port); 846275970Scy if (ai->ai_addrlen != sizeof(struct sockaddr_in6)) { 847275970Scy TT_FAIL(("Addr size mismatch on line %d", line)); 848275970Scy return -1; 849275970Scy } 850275970Scy } 851275970Scy if (evutil_sockaddr_cmp(ai->ai_addr, (struct sockaddr*)&ss, 1)) { 852275970Scy TT_FAIL(("Wanted %s, got %s:%d on line %d", sockaddr_port, 853275970Scy buf, gotport, line)); 854275970Scy return -1; 855275970Scy } else { 856275970Scy TT_BLATHER(("Wanted %s, got %s:%d on line %d", sockaddr_port, 857275970Scy buf, gotport, line)); 858275970Scy } 859275970Scy return 0; 860275970Scyend: 861275970Scy TT_FAIL(("Test failed on line %d", line)); 862275970Scy return -1; 863275970Scy} 864275970Scy 865275970Scystatic void 866275970Scytest_evutil_rand(void *arg) 867275970Scy{ 868275970Scy char buf1[32]; 869275970Scy char buf2[32]; 870275970Scy int counts[256]; 871275970Scy int i, j, k, n=0; 872275970Scy struct evutil_weakrand_state seed = { 12346789U }; 873275970Scy 874275970Scy memset(buf2, 0, sizeof(buf2)); 875275970Scy memset(counts, 0, sizeof(counts)); 876275970Scy 877275970Scy for (k=0;k<32;++k) { 878275970Scy /* Try a few different start and end points; try to catch 879275970Scy * the various misaligned cases of arc4random_buf */ 880275970Scy int startpoint = evutil_weakrand_(&seed) % 4; 881275970Scy int endpoint = 32 - (evutil_weakrand_(&seed) % 4); 882275970Scy 883275970Scy memset(buf2, 0, sizeof(buf2)); 884275970Scy 885275970Scy /* Do 6 runs over buf1, or-ing the result into buf2 each 886275970Scy * time, to make sure we're setting each byte that we mean 887275970Scy * to set. */ 888275970Scy for (i=0;i<8;++i) { 889275970Scy memset(buf1, 0, sizeof(buf1)); 890275970Scy evutil_secure_rng_get_bytes(buf1 + startpoint, 891275970Scy endpoint-startpoint); 892275970Scy n += endpoint - startpoint; 893275970Scy for (j=0; j<32; ++j) { 894275970Scy if (j >= startpoint && j < endpoint) { 895275970Scy buf2[j] |= buf1[j]; 896275970Scy ++counts[(unsigned char)buf1[j]]; 897275970Scy } else { 898275970Scy tt_assert(buf1[j] == 0); 899275970Scy tt_int_op(buf1[j], ==, 0); 900275970Scy 901275970Scy } 902275970Scy } 903275970Scy } 904275970Scy 905275970Scy /* This will give a false positive with P=(256**8)==(2**64) 906275970Scy * for each character. */ 907275970Scy for (j=startpoint;j<endpoint;++j) { 908275970Scy tt_int_op(buf2[j], !=, 0); 909275970Scy } 910275970Scy } 911275970Scy 912275970Scy evutil_weakrand_seed_(&seed, 0); 913275970Scy for (i = 0; i < 10000; ++i) { 914275970Scy ev_int32_t r = evutil_weakrand_range_(&seed, 9999); 915275970Scy tt_int_op(0, <=, r); 916275970Scy tt_int_op(r, <, 9999); 917275970Scy } 918275970Scy 919275970Scy /* for (i=0;i<256;++i) { printf("%3d %2d\n", i, counts[i]); } */ 920275970Scyend: 921275970Scy ; 922275970Scy} 923275970Scy 924275970Scystatic void 925275970Scytest_evutil_getaddrinfo(void *arg) 926275970Scy{ 927275970Scy struct evutil_addrinfo *ai = NULL, *a; 928275970Scy struct evutil_addrinfo hints; 929275970Scy int r; 930275970Scy 931275970Scy /* Try using it as a pton. */ 932275970Scy memset(&hints, 0, sizeof(hints)); 933275970Scy hints.ai_family = PF_UNSPEC; 934275970Scy hints.ai_socktype = SOCK_STREAM; 935275970Scy r = evutil_getaddrinfo("1.2.3.4", "8080", &hints, &ai); 936275970Scy tt_int_op(r, ==, 0); 937275970Scy tt_assert(ai); 938275970Scy tt_ptr_op(ai->ai_next, ==, NULL); /* no ambiguity */ 939275970Scy test_ai_eq(ai, "1.2.3.4:8080", SOCK_STREAM, IPPROTO_TCP); 940275970Scy evutil_freeaddrinfo(ai); 941275970Scy ai = NULL; 942275970Scy 943275970Scy memset(&hints, 0, sizeof(hints)); 944275970Scy hints.ai_family = PF_UNSPEC; 945275970Scy hints.ai_protocol = IPPROTO_UDP; 946275970Scy r = evutil_getaddrinfo("1001:b0b::f00f", "4321", &hints, &ai); 947275970Scy tt_int_op(r, ==, 0); 948275970Scy tt_assert(ai); 949275970Scy tt_ptr_op(ai->ai_next, ==, NULL); /* no ambiguity */ 950275970Scy test_ai_eq(ai, "[1001:b0b::f00f]:4321", SOCK_DGRAM, IPPROTO_UDP); 951275970Scy evutil_freeaddrinfo(ai); 952275970Scy ai = NULL; 953275970Scy 954275970Scy /* Try out the behavior of nodename=NULL */ 955275970Scy memset(&hints, 0, sizeof(hints)); 956275970Scy hints.ai_family = PF_INET; 957275970Scy hints.ai_protocol = IPPROTO_TCP; 958275970Scy hints.ai_flags = EVUTIL_AI_PASSIVE; /* as if for bind */ 959275970Scy r = evutil_getaddrinfo(NULL, "9999", &hints, &ai); 960275970Scy tt_int_op(r,==,0); 961275970Scy tt_assert(ai); 962275970Scy tt_ptr_op(ai->ai_next, ==, NULL); 963275970Scy test_ai_eq(ai, "0.0.0.0:9999", SOCK_STREAM, IPPROTO_TCP); 964275970Scy evutil_freeaddrinfo(ai); 965275970Scy ai = NULL; 966275970Scy hints.ai_flags = 0; /* as if for connect */ 967275970Scy r = evutil_getaddrinfo(NULL, "9998", &hints, &ai); 968275970Scy tt_assert(ai); 969275970Scy tt_int_op(r,==,0); 970275970Scy test_ai_eq(ai, "127.0.0.1:9998", SOCK_STREAM, IPPROTO_TCP); 971275970Scy tt_ptr_op(ai->ai_next, ==, NULL); 972275970Scy evutil_freeaddrinfo(ai); 973275970Scy ai = NULL; 974275970Scy 975275970Scy hints.ai_flags = 0; /* as if for connect */ 976275970Scy hints.ai_family = PF_INET6; 977275970Scy r = evutil_getaddrinfo(NULL, "9997", &hints, &ai); 978275970Scy tt_assert(ai); 979275970Scy tt_int_op(r,==,0); 980275970Scy tt_ptr_op(ai->ai_next, ==, NULL); 981275970Scy test_ai_eq(ai, "[::1]:9997", SOCK_STREAM, IPPROTO_TCP); 982275970Scy evutil_freeaddrinfo(ai); 983275970Scy ai = NULL; 984275970Scy 985275970Scy hints.ai_flags = EVUTIL_AI_PASSIVE; /* as if for bind. */ 986275970Scy hints.ai_family = PF_INET6; 987275970Scy r = evutil_getaddrinfo(NULL, "9996", &hints, &ai); 988275970Scy tt_assert(ai); 989275970Scy tt_int_op(r,==,0); 990275970Scy tt_ptr_op(ai->ai_next, ==, NULL); 991275970Scy test_ai_eq(ai, "[::]:9996", SOCK_STREAM, IPPROTO_TCP); 992275970Scy evutil_freeaddrinfo(ai); 993275970Scy ai = NULL; 994275970Scy 995275970Scy /* Now try an unspec one. We should get a v6 and a v4. */ 996275970Scy hints.ai_family = PF_UNSPEC; 997275970Scy r = evutil_getaddrinfo(NULL, "9996", &hints, &ai); 998275970Scy tt_assert(ai); 999275970Scy tt_int_op(r,==,0); 1000275970Scy a = ai_find_by_family(ai, PF_INET6); 1001275970Scy tt_assert(a); 1002275970Scy test_ai_eq(a, "[::]:9996", SOCK_STREAM, IPPROTO_TCP); 1003275970Scy a = ai_find_by_family(ai, PF_INET); 1004275970Scy tt_assert(a); 1005275970Scy test_ai_eq(a, "0.0.0.0:9996", SOCK_STREAM, IPPROTO_TCP); 1006275970Scy evutil_freeaddrinfo(ai); 1007275970Scy ai = NULL; 1008275970Scy 1009275970Scy /* Try out AI_NUMERICHOST: successful case. Also try 1010275970Scy * multiprotocol. */ 1011275970Scy memset(&hints, 0, sizeof(hints)); 1012275970Scy hints.ai_family = PF_UNSPEC; 1013275970Scy hints.ai_flags = EVUTIL_AI_NUMERICHOST; 1014275970Scy r = evutil_getaddrinfo("1.2.3.4", NULL, &hints, &ai); 1015275970Scy tt_int_op(r, ==, 0); 1016275970Scy a = ai_find_by_protocol(ai, IPPROTO_TCP); 1017275970Scy tt_assert(a); 1018275970Scy test_ai_eq(a, "1.2.3.4", SOCK_STREAM, IPPROTO_TCP); 1019275970Scy a = ai_find_by_protocol(ai, IPPROTO_UDP); 1020275970Scy tt_assert(a); 1021275970Scy test_ai_eq(a, "1.2.3.4", SOCK_DGRAM, IPPROTO_UDP); 1022275970Scy evutil_freeaddrinfo(ai); 1023275970Scy ai = NULL; 1024275970Scy 1025275970Scy /* Try the failing case of AI_NUMERICHOST */ 1026275970Scy memset(&hints, 0, sizeof(hints)); 1027275970Scy hints.ai_family = PF_UNSPEC; 1028275970Scy hints.ai_flags = EVUTIL_AI_NUMERICHOST; 1029275970Scy r = evutil_getaddrinfo("www.google.com", "80", &hints, &ai); 1030275970Scy tt_int_op(r, ==, EVUTIL_EAI_NONAME); 1031275970Scy tt_ptr_op(ai, ==, NULL); 1032275970Scy 1033275970Scy /* Try symbolic service names wit AI_NUMERICSERV */ 1034275970Scy memset(&hints, 0, sizeof(hints)); 1035275970Scy hints.ai_family = PF_UNSPEC; 1036275970Scy hints.ai_socktype = SOCK_STREAM; 1037275970Scy hints.ai_flags = EVUTIL_AI_NUMERICSERV; 1038275970Scy r = evutil_getaddrinfo("1.2.3.4", "http", &hints, &ai); 1039275970Scy tt_int_op(r,==,EVUTIL_EAI_NONAME); 1040275970Scy 1041275970Scy /* Try symbolic service names */ 1042275970Scy memset(&hints, 0, sizeof(hints)); 1043275970Scy hints.ai_family = PF_UNSPEC; 1044275970Scy hints.ai_socktype = SOCK_STREAM; 1045275970Scy r = evutil_getaddrinfo("1.2.3.4", "http", &hints, &ai); 1046275970Scy if (r!=0) { 1047275970Scy TT_DECLARE("SKIP", ("Symbolic service names seem broken.")); 1048275970Scy } else { 1049275970Scy tt_assert(ai); 1050275970Scy test_ai_eq(ai, "1.2.3.4:80", SOCK_STREAM, IPPROTO_TCP); 1051275970Scy evutil_freeaddrinfo(ai); 1052275970Scy ai = NULL; 1053275970Scy } 1054275970Scy 1055275970Scyend: 1056275970Scy if (ai) 1057275970Scy evutil_freeaddrinfo(ai); 1058275970Scy} 1059275970Scy 1060275970Scystatic void 1061275970Scytest_evutil_getaddrinfo_live(void *arg) 1062275970Scy{ 1063275970Scy struct evutil_addrinfo *ai = NULL; 1064275970Scy struct evutil_addrinfo hints; 1065275970Scy 1066275970Scy struct sockaddr_in6 *sin6; 1067275970Scy struct sockaddr_in *sin; 1068275970Scy char buf[128]; 1069275970Scy const char *cp; 1070275970Scy int r; 1071275970Scy 1072275970Scy /* Now do some actual lookups. */ 1073275970Scy memset(&hints, 0, sizeof(hints)); 1074275970Scy hints.ai_family = PF_INET; 1075275970Scy hints.ai_protocol = IPPROTO_TCP; 1076275970Scy hints.ai_socktype = SOCK_STREAM; 1077275970Scy r = evutil_getaddrinfo("www.google.com", "80", &hints, &ai); 1078275970Scy if (r != 0) { 1079275970Scy TT_DECLARE("SKIP", ("Couldn't resolve www.google.com")); 1080275970Scy } else { 1081275970Scy tt_assert(ai); 1082275970Scy tt_int_op(ai->ai_family, ==, PF_INET); 1083275970Scy tt_int_op(ai->ai_protocol, ==, IPPROTO_TCP); 1084275970Scy tt_int_op(ai->ai_socktype, ==, SOCK_STREAM); 1085275970Scy tt_int_op(ai->ai_addrlen, ==, sizeof(struct sockaddr_in)); 1086275970Scy sin = (struct sockaddr_in*)ai->ai_addr; 1087275970Scy tt_int_op(sin->sin_family, ==, AF_INET); 1088275970Scy tt_int_op(sin->sin_port, ==, htons(80)); 1089275970Scy tt_int_op(sin->sin_addr.s_addr, !=, 0xffffffff); 1090275970Scy 1091275970Scy cp = evutil_inet_ntop(AF_INET, &sin->sin_addr, buf, sizeof(buf)); 1092275970Scy TT_BLATHER(("www.google.com resolved to %s", 1093275970Scy cp?cp:"<unwriteable>")); 1094275970Scy evutil_freeaddrinfo(ai); 1095275970Scy ai = NULL; 1096275970Scy } 1097275970Scy 1098275970Scy hints.ai_family = PF_INET6; 1099275970Scy r = evutil_getaddrinfo("ipv6.google.com", "80", &hints, &ai); 1100275970Scy if (r != 0) { 1101275970Scy TT_BLATHER(("Couldn't do an ipv6 lookup for ipv6.google.com")); 1102275970Scy } else { 1103275970Scy tt_assert(ai); 1104275970Scy tt_int_op(ai->ai_family, ==, PF_INET6); 1105275970Scy tt_int_op(ai->ai_addrlen, ==, sizeof(struct sockaddr_in6)); 1106275970Scy sin6 = (struct sockaddr_in6*)ai->ai_addr; 1107275970Scy tt_int_op(sin6->sin6_port, ==, htons(80)); 1108275970Scy 1109275970Scy cp = evutil_inet_ntop(AF_INET6, &sin6->sin6_addr, buf, 1110275970Scy sizeof(buf)); 1111275970Scy TT_BLATHER(("ipv6.google.com resolved to %s", 1112275970Scy cp?cp:"<unwriteable>")); 1113275970Scy } 1114275970Scy 1115275970Scyend: 1116275970Scy if (ai) 1117275970Scy evutil_freeaddrinfo(ai); 1118275970Scy} 1119275970Scy 1120275970Scy#ifdef _WIN32 1121275970Scystatic void 1122275970Scytest_evutil_loadsyslib(void *arg) 1123275970Scy{ 1124282408Scy HMODULE h=NULL; 1125275970Scy 1126275970Scy h = evutil_load_windows_system_library_(TEXT("kernel32.dll")); 1127275970Scy tt_assert(h); 1128275970Scy 1129275970Scyend: 1130275970Scy if (h) 1131275970Scy CloseHandle(h); 1132275970Scy 1133275970Scy} 1134275970Scy#endif 1135275970Scy 1136275970Scy/** Test mm_malloc(). */ 1137275970Scystatic void 1138275970Scytest_event_malloc(void *arg) 1139275970Scy{ 1140275970Scy void *p = NULL; 1141275970Scy (void)arg; 1142275970Scy 1143275970Scy /* mm_malloc(0) should simply return NULL. */ 1144275970Scy#ifndef EVENT__DISABLE_MM_REPLACEMENT 1145275970Scy errno = 0; 1146275970Scy p = mm_malloc(0); 1147275970Scy tt_assert(p == NULL); 1148275970Scy tt_int_op(errno, ==, 0); 1149275970Scy#endif 1150275970Scy 1151275970Scy /* Trivial case. */ 1152275970Scy errno = 0; 1153275970Scy p = mm_malloc(8); 1154275970Scy tt_assert(p != NULL); 1155275970Scy tt_int_op(errno, ==, 0); 1156275970Scy mm_free(p); 1157275970Scy 1158275970Scy end: 1159275970Scy errno = 0; 1160275970Scy return; 1161275970Scy} 1162275970Scy 1163275970Scystatic void 1164275970Scytest_event_calloc(void *arg) 1165275970Scy{ 1166275970Scy void *p = NULL; 1167275970Scy (void)arg; 1168275970Scy 1169275970Scy#ifndef EVENT__DISABLE_MM_REPLACEMENT 1170275970Scy /* mm_calloc() should simply return NULL 1171275970Scy * if either argument is zero. */ 1172275970Scy errno = 0; 1173275970Scy p = mm_calloc(0, 0); 1174275970Scy tt_assert(p == NULL); 1175275970Scy tt_int_op(errno, ==, 0); 1176275970Scy errno = 0; 1177275970Scy p = mm_calloc(0, 1); 1178275970Scy tt_assert(p == NULL); 1179275970Scy tt_int_op(errno, ==, 0); 1180275970Scy errno = 0; 1181275970Scy p = mm_calloc(1, 0); 1182275970Scy tt_assert(p == NULL); 1183275970Scy tt_int_op(errno, ==, 0); 1184275970Scy#endif 1185275970Scy 1186275970Scy /* Trivial case. */ 1187275970Scy errno = 0; 1188275970Scy p = mm_calloc(8, 8); 1189275970Scy tt_assert(p != NULL); 1190275970Scy tt_int_op(errno, ==, 0); 1191275970Scy mm_free(p); 1192275970Scy p = NULL; 1193275970Scy 1194275970Scy /* mm_calloc() should set errno = ENOMEM and return NULL 1195275970Scy * in case of potential overflow. */ 1196275970Scy errno = 0; 1197275970Scy p = mm_calloc(EV_SIZE_MAX/2, EV_SIZE_MAX/2 + 8); 1198275970Scy tt_assert(p == NULL); 1199275970Scy tt_int_op(errno, ==, ENOMEM); 1200275970Scy 1201275970Scy end: 1202275970Scy errno = 0; 1203275970Scy if (p) 1204275970Scy mm_free(p); 1205275970Scy 1206275970Scy return; 1207275970Scy} 1208275970Scy 1209275970Scystatic void 1210275970Scytest_event_strdup(void *arg) 1211275970Scy{ 1212275970Scy void *p = NULL; 1213275970Scy (void)arg; 1214275970Scy 1215275970Scy#ifndef EVENT__DISABLE_MM_REPLACEMENT 1216275970Scy /* mm_strdup(NULL) should set errno = EINVAL and return NULL. */ 1217275970Scy errno = 0; 1218275970Scy p = mm_strdup(NULL); 1219275970Scy tt_assert(p == NULL); 1220275970Scy tt_int_op(errno, ==, EINVAL); 1221275970Scy#endif 1222275970Scy 1223275970Scy /* Trivial cases. */ 1224275970Scy 1225275970Scy errno = 0; 1226275970Scy p = mm_strdup(""); 1227275970Scy tt_assert(p != NULL); 1228275970Scy tt_int_op(errno, ==, 0); 1229275970Scy tt_str_op(p, ==, ""); 1230275970Scy mm_free(p); 1231275970Scy 1232275970Scy errno = 0; 1233275970Scy p = mm_strdup("foo"); 1234275970Scy tt_assert(p != NULL); 1235275970Scy tt_int_op(errno, ==, 0); 1236275970Scy tt_str_op(p, ==, "foo"); 1237275970Scy mm_free(p); 1238275970Scy 1239275970Scy /* XXX 1240275970Scy * mm_strdup(str) where str is a string of length EV_SIZE_MAX 1241275970Scy * should set errno = ENOMEM and return NULL. */ 1242275970Scy 1243275970Scy end: 1244275970Scy errno = 0; 1245275970Scy return; 1246275970Scy} 1247275970Scy 1248275970Scystatic void 1249275970Scytest_evutil_usleep(void *arg) 1250275970Scy{ 1251275970Scy struct timeval tv1, tv2, tv3, diff1, diff2; 1252275970Scy const struct timeval quarter_sec = {0, 250*1000}; 1253275970Scy const struct timeval tenth_sec = {0, 100*1000}; 1254275970Scy long usec1, usec2; 1255275970Scy 1256275970Scy evutil_gettimeofday(&tv1, NULL); 1257275970Scy evutil_usleep_(&quarter_sec); 1258275970Scy evutil_gettimeofday(&tv2, NULL); 1259275970Scy evutil_usleep_(&tenth_sec); 1260275970Scy evutil_gettimeofday(&tv3, NULL); 1261275970Scy 1262275970Scy evutil_timersub(&tv2, &tv1, &diff1); 1263275970Scy evutil_timersub(&tv3, &tv2, &diff2); 1264275970Scy usec1 = diff1.tv_sec * 1000000 + diff1.tv_usec; 1265275970Scy usec2 = diff2.tv_sec * 1000000 + diff2.tv_usec; 1266275970Scy 1267275970Scy tt_int_op(usec1, >, 200000); 1268275970Scy tt_int_op(usec1, <, 300000); 1269275970Scy tt_int_op(usec2, >, 80000); 1270275970Scy tt_int_op(usec2, <, 120000); 1271275970Scy 1272275970Scyend: 1273275970Scy ; 1274275970Scy} 1275275970Scy 1276275970Scystatic void 1277275970Scytest_evutil_monotonic_res(void *data_) 1278275970Scy{ 1279275970Scy /* Basic santity-test for monotonic timers. What we'd really like 1280275970Scy * to do is make sure that they can't go backwards even when the 1281275970Scy * system clock goes backwards. But we haven't got a good way to 1282275970Scy * move the system clock backwards. 1283275970Scy */ 1284275970Scy struct basic_test_data *data = data_; 1285275970Scy struct evutil_monotonic_timer timer; 1286275970Scy const int precise = strstr(data->setup_data, "precise") != NULL; 1287275970Scy const int fallback = strstr(data->setup_data, "fallback") != NULL; 1288275970Scy struct timeval tv[10], delay; 1289275970Scy int total_diff = 0; 1290275970Scy 1291275970Scy int flags = 0, wantres, acceptdiff, i; 1292275970Scy if (precise) 1293275970Scy flags |= EV_MONOT_PRECISE; 1294275970Scy if (fallback) 1295275970Scy flags |= EV_MONOT_FALLBACK; 1296275970Scy if (precise || fallback) { 1297275970Scy#ifdef _WIN32 1298275970Scy wantres = 10*1000; 1299275970Scy acceptdiff = 1000; 1300275970Scy#else 1301275970Scy wantres = 1000; 1302275970Scy acceptdiff = 300; 1303275970Scy#endif 1304275970Scy } else { 1305275970Scy wantres = 40*1000; 1306275970Scy acceptdiff = 20*1000; 1307275970Scy } 1308275970Scy 1309275970Scy TT_BLATHER(("Precise = %d", precise)); 1310275970Scy TT_BLATHER(("Fallback = %d", fallback)); 1311275970Scy 1312275970Scy /* First, make sure we match up with usleep. */ 1313275970Scy 1314275970Scy delay.tv_sec = 0; 1315275970Scy delay.tv_usec = wantres; 1316275970Scy 1317275970Scy tt_int_op(evutil_configure_monotonic_time_(&timer, flags), ==, 0); 1318275970Scy 1319275970Scy for (i = 0; i < 10; ++i) { 1320275970Scy evutil_gettime_monotonic_(&timer, &tv[i]); 1321275970Scy evutil_usleep_(&delay); 1322275970Scy } 1323275970Scy 1324275970Scy for (i = 0; i < 9; ++i) { 1325275970Scy struct timeval diff; 1326275970Scy tt_assert(evutil_timercmp(&tv[i], &tv[i+1], <)); 1327275970Scy evutil_timersub(&tv[i+1], &tv[i], &diff); 1328275970Scy tt_int_op(diff.tv_sec, ==, 0); 1329275970Scy total_diff += diff.tv_usec; 1330275970Scy TT_BLATHER(("Difference = %d", (int)diff.tv_usec)); 1331275970Scy } 1332275970Scy tt_int_op(abs(total_diff/9 - wantres), <, acceptdiff); 1333275970Scy 1334275970Scyend: 1335275970Scy ; 1336275970Scy} 1337275970Scy 1338275970Scystatic void 1339275970Scytest_evutil_monotonic_prc(void *data_) 1340275970Scy{ 1341275970Scy struct basic_test_data *data = data_; 1342275970Scy struct evutil_monotonic_timer timer; 1343275970Scy const int precise = strstr(data->setup_data, "precise") != NULL; 1344275970Scy const int fallback = strstr(data->setup_data, "fallback") != NULL; 1345275970Scy struct timeval tv[10]; 1346275970Scy int total_diff = 0; 1347275970Scy int i, maxstep = 25*1000,flags=0; 1348275970Scy if (precise) 1349275970Scy maxstep = 500; 1350275970Scy if (precise) 1351275970Scy flags |= EV_MONOT_PRECISE; 1352275970Scy if (fallback) 1353275970Scy flags |= EV_MONOT_FALLBACK; 1354275970Scy tt_int_op(evutil_configure_monotonic_time_(&timer, flags), ==, 0); 1355275970Scy 1356275970Scy /* find out what precision we actually see. */ 1357275970Scy 1358275970Scy evutil_gettime_monotonic_(&timer, &tv[0]); 1359275970Scy for (i = 1; i < 10; ++i) { 1360275970Scy do { 1361275970Scy evutil_gettime_monotonic_(&timer, &tv[i]); 1362275970Scy } while (evutil_timercmp(&tv[i-1], &tv[i], ==)); 1363275970Scy } 1364275970Scy 1365275970Scy total_diff = 0; 1366275970Scy for (i = 0; i < 9; ++i) { 1367275970Scy struct timeval diff; 1368275970Scy tt_assert(evutil_timercmp(&tv[i], &tv[i+1], <)); 1369275970Scy evutil_timersub(&tv[i+1], &tv[i], &diff); 1370275970Scy tt_int_op(diff.tv_sec, ==, 0); 1371275970Scy total_diff += diff.tv_usec; 1372275970Scy TT_BLATHER(("Step difference = %d", (int)diff.tv_usec)); 1373275970Scy } 1374275970Scy TT_BLATHER(("Average step difference = %d", total_diff / 9)); 1375275970Scy tt_int_op(total_diff/9, <, maxstep); 1376275970Scy 1377275970Scyend: 1378275970Scy ; 1379275970Scy} 1380275970Scy 1381275970Scystruct testcase_t util_testcases[] = { 1382275970Scy { "ipv4_parse", regress_ipv4_parse, 0, NULL, NULL }, 1383275970Scy { "ipv6_parse", regress_ipv6_parse, 0, NULL, NULL }, 1384275970Scy { "sockaddr_port_parse", regress_sockaddr_port_parse, 0, NULL, NULL }, 1385275970Scy { "sockaddr_port_format", regress_sockaddr_port_format, 0, NULL, NULL }, 1386275970Scy { "sockaddr_predicates", test_evutil_sockaddr_predicates, 0,NULL,NULL }, 1387275970Scy { "evutil_snprintf", test_evutil_snprintf, 0, NULL, NULL }, 1388275970Scy { "evutil_strtoll", test_evutil_strtoll, 0, NULL, NULL }, 1389275970Scy { "evutil_casecmp", test_evutil_casecmp, 0, NULL, NULL }, 1390275970Scy { "evutil_rtrim", test_evutil_rtrim, 0, NULL, NULL }, 1391275970Scy { "strlcpy", test_evutil_strlcpy, 0, NULL, NULL }, 1392275970Scy { "log", test_evutil_log, TT_FORK, NULL, NULL }, 1393275970Scy { "upcast", test_evutil_upcast, 0, NULL, NULL }, 1394275970Scy { "integers", test_evutil_integers, 0, NULL, NULL }, 1395275970Scy { "rand", test_evutil_rand, TT_FORK, NULL, NULL }, 1396275970Scy { "getaddrinfo", test_evutil_getaddrinfo, TT_FORK, NULL, NULL }, 1397275970Scy { "getaddrinfo_live", test_evutil_getaddrinfo_live, TT_FORK|TT_OFF_BY_DEFAULT, NULL, NULL }, 1398275970Scy#ifdef _WIN32 1399275970Scy { "loadsyslib", test_evutil_loadsyslib, TT_FORK, NULL, NULL }, 1400275970Scy#endif 1401275970Scy { "mm_malloc", test_event_malloc, 0, NULL, NULL }, 1402275970Scy { "mm_calloc", test_event_calloc, 0, NULL, NULL }, 1403275970Scy { "mm_strdup", test_event_strdup, 0, NULL, NULL }, 1404275970Scy { "usleep", test_evutil_usleep, 0, NULL, NULL }, 1405275970Scy { "monotonic_res", test_evutil_monotonic_res, 0, &basic_setup, (void*)"" }, 1406275970Scy { "monotonic_res_precise", test_evutil_monotonic_res, TT_OFF_BY_DEFAULT, &basic_setup, (void*)"precise" }, 1407275970Scy { "monotonic_res_fallback", test_evutil_monotonic_res, TT_OFF_BY_DEFAULT, &basic_setup, (void*)"fallback" }, 1408275970Scy { "monotonic_prc", test_evutil_monotonic_prc, 0, &basic_setup, (void*)"" }, 1409275970Scy { "monotonic_prc_precise", test_evutil_monotonic_prc, 0, &basic_setup, (void*)"precise" }, 1410275970Scy { "monotonic_prc_fallback", test_evutil_monotonic_prc, 0, &basic_setup, (void*)"fallback" }, 1411275970Scy END_OF_TESTCASES, 1412275970Scy}; 1413275970Scy 1414