xref: /netbsd-src/external/bsd/ntp/dist/sntp/libevent/test/regress_http.c (revision d11b170b9000ada93db553723522a63d5deac310)
1 /*	$NetBSD: regress_http.c,v 1.1.1.1 2013/12/27 23:31:28 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu>
5  * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 #include "util-internal.h"
30 
31 #ifdef _WIN32
32 #include <winsock2.h>
33 #include <ws2tcpip.h>
34 #include <windows.h>
35 #endif
36 
37 #include "event2/event-config.h"
38 
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #ifdef EVENT__HAVE_SYS_TIME_H
42 #include <sys/time.h>
43 #endif
44 #include <sys/queue.h>
45 #ifndef _WIN32
46 #include <sys/socket.h>
47 #include <signal.h>
48 #include <unistd.h>
49 #include <netdb.h>
50 #endif
51 #include <fcntl.h>
52 #include <stdlib.h>
53 #include <stdio.h>
54 #include <string.h>
55 #include <errno.h>
56 
57 #include "event2/dns.h"
58 
59 #include "event2/event.h"
60 #include "event2/http.h"
61 #include "event2/buffer.h"
62 #include "event2/bufferevent.h"
63 #include "event2/util.h"
64 #include "log-internal.h"
65 #include "http-internal.h"
66 #include "regress.h"
67 #include "regress_testutils.h"
68 
69 static struct evhttp *http;
70 /* set if a test needs to call loopexit on a base */
71 static struct event_base *exit_base;
72 
73 static char const BASIC_REQUEST_BODY[] = "This is funny";
74 
75 static void http_basic_cb(struct evhttp_request *req, void *arg);
76 static void http_chunked_cb(struct evhttp_request *req, void *arg);
77 static void http_post_cb(struct evhttp_request *req, void *arg);
78 static void http_put_cb(struct evhttp_request *req, void *arg);
79 static void http_delete_cb(struct evhttp_request *req, void *arg);
80 static void http_delay_cb(struct evhttp_request *req, void *arg);
81 static void http_large_delay_cb(struct evhttp_request *req, void *arg);
82 static void http_badreq_cb(struct evhttp_request *req, void *arg);
83 static void http_dispatcher_cb(struct evhttp_request *req, void *arg);
84 static int
85 http_bind(struct evhttp *myhttp, ev_uint16_t *pport, int ipv6)
86 {
87 	int port;
88 	struct evhttp_bound_socket *sock;
89 
90 	if (ipv6)
91 		sock = evhttp_bind_socket_with_handle(myhttp, "::1", *pport);
92 	else
93 		sock = evhttp_bind_socket_with_handle(myhttp, "127.0.0.1", *pport);
94 
95 	if (sock == NULL)
96 		event_errx(1, "Could not start web server");
97 
98 	port = regress_get_socket_port(evhttp_bound_socket_get_fd(sock));
99 	if (port < 0)
100 		return -1;
101 	*pport = (ev_uint16_t) port;
102 
103 	return 0;
104 }
105 
106 static struct evhttp *
107 http_setup(ev_uint16_t *pport, struct event_base *base, int ipv6)
108 {
109 	struct evhttp *myhttp;
110 
111 	/* Try a few different ports */
112 	myhttp = evhttp_new(base);
113 
114 	if (http_bind(myhttp, pport, ipv6) < 0)
115 		return NULL;
116 
117 	/* Register a callback for certain types of requests */
118 	evhttp_set_cb(myhttp, "/test", http_basic_cb, base);
119 	evhttp_set_cb(myhttp, "/chunked", http_chunked_cb, base);
120 	evhttp_set_cb(myhttp, "/streamed", http_chunked_cb, base);
121 	evhttp_set_cb(myhttp, "/postit", http_post_cb, base);
122 	evhttp_set_cb(myhttp, "/putit", http_put_cb, base);
123 	evhttp_set_cb(myhttp, "/deleteit", http_delete_cb, base);
124 	evhttp_set_cb(myhttp, "/delay", http_delay_cb, base);
125 	evhttp_set_cb(myhttp, "/largedelay", http_large_delay_cb, base);
126 	evhttp_set_cb(myhttp, "/badrequest", http_badreq_cb, base);
127 	evhttp_set_cb(myhttp, "/", http_dispatcher_cb, base);
128 	return (myhttp);
129 }
130 
131 #ifndef NI_MAXSERV
132 #define NI_MAXSERV 1024
133 #endif
134 
135 static evutil_socket_t
136 http_connect(const char *address, u_short port)
137 {
138 	/* Stupid code for connecting */
139 	struct evutil_addrinfo ai, *aitop;
140 	char strport[NI_MAXSERV];
141 
142 	struct sockaddr *sa;
143 	int slen;
144 	evutil_socket_t fd;
145 
146 	memset(&ai, 0, sizeof(ai));
147 	ai.ai_family = AF_INET;
148 	ai.ai_socktype = SOCK_STREAM;
149 	evutil_snprintf(strport, sizeof(strport), "%d", port);
150 	if (evutil_getaddrinfo(address, strport, &ai, &aitop) != 0) {
151 		event_warn("getaddrinfo");
152 		return (-1);
153 	}
154 	sa = aitop->ai_addr;
155 	slen = aitop->ai_addrlen;
156 
157 	fd = socket(AF_INET, SOCK_STREAM, 0);
158 	if (fd == -1)
159 		event_err(1, "socket failed");
160 
161 	evutil_make_socket_nonblocking(fd);
162 	if (connect(fd, sa, slen) == -1) {
163 #ifdef _WIN32
164 		int tmp_err = WSAGetLastError();
165 		if (tmp_err != WSAEINPROGRESS && tmp_err != WSAEINVAL &&
166 		    tmp_err != WSAEWOULDBLOCK)
167 			event_err(1, "connect failed");
168 #else
169 		if (errno != EINPROGRESS)
170 			event_err(1, "connect failed");
171 #endif
172 	}
173 
174 	evutil_freeaddrinfo(aitop);
175 
176 	return (fd);
177 }
178 
179 /* Helper: do a strcmp on the contents of buf and the string s. */
180 static int
181 evbuffer_datacmp(struct evbuffer *buf, const char *s)
182 {
183 	size_t b_sz = evbuffer_get_length(buf);
184 	size_t s_sz = strlen(s);
185 	unsigned char *d;
186 	int r;
187 
188 	if (b_sz < s_sz)
189 		return -1;
190 
191 	d = evbuffer_pullup(buf, s_sz);
192 	if ((r = memcmp(d, s, s_sz)))
193 		return r;
194 
195 	if (b_sz > s_sz)
196 		return 1;
197 	else
198 		return 0;
199 }
200 
201 /* Helper: Return true iff buf contains s */
202 static int
203 evbuffer_contains(struct evbuffer *buf, const char *s)
204 {
205 	struct evbuffer_ptr ptr;
206 	ptr = evbuffer_search(buf, s, strlen(s), NULL);
207 	return ptr.pos != -1;
208 }
209 
210 static void
211 http_readcb(struct bufferevent *bev, void *arg)
212 {
213 	const char *what = BASIC_REQUEST_BODY;
214 	struct event_base *my_base = arg;
215 
216 	if (evbuffer_contains(bufferevent_get_input(bev), what)) {
217 		struct evhttp_request *req = evhttp_request_new(NULL, NULL);
218 		enum message_read_status done;
219 
220 		/* req->kind = EVHTTP_RESPONSE; */
221 		done = evhttp_parse_firstline_(req, bufferevent_get_input(bev));
222 		if (done != ALL_DATA_READ)
223 			goto out;
224 
225 		done = evhttp_parse_headers_(req, bufferevent_get_input(bev));
226 		if (done != ALL_DATA_READ)
227 			goto out;
228 
229 		if (done == 1 &&
230 		    evhttp_find_header(evhttp_request_get_input_headers(req),
231 			"Content-Type") != NULL)
232 			test_ok++;
233 
234 	 out:
235 		evhttp_request_free(req);
236 		bufferevent_disable(bev, EV_READ);
237 		if (exit_base)
238 			event_base_loopexit(exit_base, NULL);
239 		else if (my_base)
240 			event_base_loopexit(my_base, NULL);
241 		else {
242 			fprintf(stderr, "No way to exit loop!\n");
243 			exit(1);
244 		}
245 	}
246 }
247 
248 static void
249 http_writecb(struct bufferevent *bev, void *arg)
250 {
251 	if (evbuffer_get_length(bufferevent_get_output(bev)) == 0) {
252 		/* enable reading of the reply */
253 		bufferevent_enable(bev, EV_READ);
254 		test_ok++;
255 	}
256 }
257 
258 static void
259 http_errorcb(struct bufferevent *bev, short what, void *arg)
260 {
261 	test_ok = -2;
262 	event_base_loopexit(arg, NULL);
263 }
264 
265 static int found_multi = 0;
266 static int found_multi2 = 0;
267 
268 static void
269 http_basic_cb(struct evhttp_request *req, void *arg)
270 {
271 	struct evbuffer *evb = evbuffer_new();
272 	int empty = evhttp_find_header(evhttp_request_get_input_headers(req), "Empty") != NULL;
273 	event_debug(("%s: called\n", __func__));
274 	evbuffer_add_printf(evb, BASIC_REQUEST_BODY);
275 
276 	/* For multi-line headers test */
277 	{
278 		const char *multi =
279 		    evhttp_find_header(evhttp_request_get_input_headers(req),"X-Multi");
280 		if (multi) {
281 			found_multi = !strcmp(multi,"aaaaaaaa a END");
282 			if (strcmp("END", multi + strlen(multi) - 3) == 0)
283 				test_ok++;
284 			if (evhttp_find_header(evhttp_request_get_input_headers(req), "X-Last"))
285 				test_ok++;
286 		}
287 	}
288 	{
289 		const char *multi2 =
290 		    evhttp_find_header(evhttp_request_get_input_headers(req),"X-Multi-Extra-WS");
291 		if (multi2) {
292 			found_multi2 = !strcmp(multi2,"libevent 2.1");
293 		}
294 	}
295 
296 
297 	/* injecting a bad content-length */
298 	if (evhttp_find_header(evhttp_request_get_input_headers(req), "X-Negative"))
299 		evhttp_add_header(evhttp_request_get_output_headers(req),
300 		    "Content-Length", "-100");
301 
302 	/* allow sending of an empty reply */
303 	evhttp_send_reply(req, HTTP_OK, "Everything is fine",
304 	    !empty ? evb : NULL);
305 
306 	evbuffer_free(evb);
307 }
308 
309 static char const* const CHUNKS[] = {
310 	"This is funny",
311 	"but not hilarious.",
312 	"bwv 1052"
313 };
314 
315 struct chunk_req_state {
316 	struct event_base *base;
317 	struct evhttp_request *req;
318 	int i;
319 };
320 
321 static void
322 http_chunked_trickle_cb(evutil_socket_t fd, short events, void *arg)
323 {
324 	struct evbuffer *evb = evbuffer_new();
325 	struct chunk_req_state *state = arg;
326 	struct timeval when = { 0, 0 };
327 
328 	evbuffer_add_printf(evb, "%s", CHUNKS[state->i]);
329 	evhttp_send_reply_chunk(state->req, evb);
330 	evbuffer_free(evb);
331 
332 	if (++state->i < (int) (sizeof(CHUNKS)/sizeof(CHUNKS[0]))) {
333 		event_base_once(state->base, -1, EV_TIMEOUT,
334 		    http_chunked_trickle_cb, state, &when);
335 	} else {
336 		evhttp_send_reply_end(state->req);
337 		free(state);
338 	}
339 }
340 
341 static void
342 http_chunked_cb(struct evhttp_request *req, void *arg)
343 {
344 	struct timeval when = { 0, 0 };
345 	struct chunk_req_state *state = malloc(sizeof(struct chunk_req_state));
346 	event_debug(("%s: called\n", __func__));
347 
348 	memset(state, 0, sizeof(struct chunk_req_state));
349 	state->req = req;
350 	state->base = arg;
351 
352 	if (strcmp(evhttp_request_get_uri(req), "/streamed") == 0) {
353 		evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Length", "39");
354 	}
355 
356 	/* generate a chunked/streamed reply */
357 	evhttp_send_reply_start(req, HTTP_OK, "Everything is fine");
358 
359 	/* but trickle it across several iterations to ensure we're not
360 	 * assuming it comes all at once */
361 	event_base_once(arg, -1, EV_TIMEOUT, http_chunked_trickle_cb, state, &when);
362 }
363 
364 static void
365 http_complete_write(evutil_socket_t fd, short what, void *arg)
366 {
367 	struct bufferevent *bev = arg;
368 	const char *http_request = "host\r\n"
369 	    "Connection: close\r\n"
370 	    "\r\n";
371 	bufferevent_write(bev, http_request, strlen(http_request));
372 }
373 
374 static void
375 http_basic_test(void *arg)
376 {
377 	struct basic_test_data *data = arg;
378 	struct timeval tv;
379 	struct bufferevent *bev;
380 	evutil_socket_t fd;
381 	const char *http_request;
382 	ev_uint16_t port = 0, port2 = 0;
383 
384 	test_ok = 0;
385 
386 	http = http_setup(&port, data->base, 0);
387 
388 	/* bind to a second socket */
389 	if (http_bind(http, &port2, 0) == -1) {
390 		fprintf(stdout, "FAILED (bind)\n");
391 		exit(1);
392 	}
393 
394 	fd = http_connect("127.0.0.1", port);
395 
396 	/* Stupid thing to send a request */
397 	bev = bufferevent_socket_new(data->base, fd, 0);
398 	bufferevent_setcb(bev, http_readcb, http_writecb,
399 	    http_errorcb, data->base);
400 
401 	/* first half of the http request */
402 	http_request =
403 	    "GET /test HTTP/1.1\r\n"
404 	    "Host: some";
405 
406 	bufferevent_write(bev, http_request, strlen(http_request));
407 	evutil_timerclear(&tv);
408 	tv.tv_usec = 10000;
409 	event_base_once(data->base,
410 	    -1, EV_TIMEOUT, http_complete_write, bev, &tv);
411 
412 	event_base_dispatch(data->base);
413 
414 	tt_assert(test_ok == 3);
415 
416 	/* connect to the second port */
417 	bufferevent_free(bev);
418 	evutil_closesocket(fd);
419 
420 	fd = http_connect("127.0.0.1", port2);
421 
422 	/* Stupid thing to send a request */
423 	bev = bufferevent_socket_new(data->base, fd, 0);
424 	bufferevent_setcb(bev, http_readcb, http_writecb,
425 	    http_errorcb, data->base);
426 
427 	http_request =
428 	    "GET /test HTTP/1.1\r\n"
429 	    "Host: somehost\r\n"
430 	    "Connection: close\r\n"
431 	    "\r\n";
432 
433 	bufferevent_write(bev, http_request, strlen(http_request));
434 
435 	event_base_dispatch(data->base);
436 
437 	tt_assert(test_ok == 5);
438 
439 	/* Connect to the second port again. This time, send an absolute uri. */
440 	bufferevent_free(bev);
441 	evutil_closesocket(fd);
442 
443 	fd = http_connect("127.0.0.1", port2);
444 
445 	/* Stupid thing to send a request */
446 	bev = bufferevent_socket_new(data->base, fd, 0);
447 	bufferevent_setcb(bev, http_readcb, http_writecb,
448 	    http_errorcb, data->base);
449 
450 	http_request =
451 	    "GET http://somehost.net/test HTTP/1.1\r\n"
452 	    "Host: somehost\r\n"
453 	    "Connection: close\r\n"
454 	    "\r\n";
455 
456 	bufferevent_write(bev, http_request, strlen(http_request));
457 
458 	event_base_dispatch(data->base);
459 
460 	tt_assert(test_ok == 7);
461 
462 	evhttp_free(http);
463  end:
464 	;
465 }
466 
467 static void
468 http_delay_reply(evutil_socket_t fd, short what, void *arg)
469 {
470 	struct evhttp_request *req = arg;
471 
472 	evhttp_send_reply(req, HTTP_OK, "Everything is fine", NULL);
473 
474 	++test_ok;
475 }
476 
477 static void
478 http_delay_cb(struct evhttp_request *req, void *arg)
479 {
480 	struct timeval tv;
481 	evutil_timerclear(&tv);
482 	tv.tv_sec = 0;
483 	tv.tv_usec = 200 * 1000;
484 
485 	event_base_once(arg, -1, EV_TIMEOUT, http_delay_reply, req, &tv);
486 }
487 
488 static void
489 http_badreq_cb(struct evhttp_request *req, void *arg)
490 {
491 	struct evbuffer *buf = evbuffer_new();
492 
493 	evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/xml; charset=UTF-8");
494 	evbuffer_add_printf(buf, "Hello, %s!", "127.0.0.1");
495 
496 	evhttp_send_reply(req, HTTP_OK, "OK", buf);
497 	evbuffer_free(buf);
498 }
499 
500 static void
501 http_badreq_errorcb(struct bufferevent *bev, short what, void *arg)
502 {
503 	event_debug(("%s: called (what=%04x, arg=%p)", __func__, what, arg));
504 	/* ignore */
505 }
506 
507 #ifndef SHUT_WR
508 #ifdef _WIN32
509 #define SHUT_WR SD_SEND
510 #else
511 #define SHUT_WR 1
512 #endif
513 #endif
514 
515 static void
516 http_badreq_readcb(struct bufferevent *bev, void *arg)
517 {
518 	const char *what = "Hello, 127.0.0.1";
519 	const char *bad_request = "400 Bad Request";
520 
521 	if (evbuffer_contains(bufferevent_get_input(bev), bad_request)) {
522 		TT_FAIL(("%s:bad request detected", __func__));
523 		bufferevent_disable(bev, EV_READ);
524 		event_base_loopexit(arg, NULL);
525 		return;
526 	}
527 
528 	if (evbuffer_contains(bufferevent_get_input(bev), what)) {
529 		struct evhttp_request *req = evhttp_request_new(NULL, NULL);
530 		enum message_read_status done;
531 
532 		/* req->kind = EVHTTP_RESPONSE; */
533 		done = evhttp_parse_firstline_(req, bufferevent_get_input(bev));
534 		if (done != ALL_DATA_READ)
535 			goto out;
536 
537 		done = evhttp_parse_headers_(req, bufferevent_get_input(bev));
538 		if (done != ALL_DATA_READ)
539 			goto out;
540 
541 		if (done == 1 &&
542 		    evhttp_find_header(evhttp_request_get_input_headers(req),
543 			"Content-Type") != NULL)
544 			test_ok++;
545 
546 	out:
547 		evhttp_request_free(req);
548 		evbuffer_drain(bufferevent_get_input(bev), evbuffer_get_length(bufferevent_get_input(bev)));
549 	}
550 
551 	shutdown(bufferevent_getfd(bev), SHUT_WR);
552 }
553 
554 static void
555 http_badreq_successcb(evutil_socket_t fd, short what, void *arg)
556 {
557 	event_debug(("%s: called (what=%04x, arg=%p)", __func__, what, arg));
558 	event_base_loopexit(exit_base, NULL);
559 }
560 
561 static void
562 http_bad_request_test(void *arg)
563 {
564 	struct basic_test_data *data = arg;
565 	struct timeval tv;
566 	struct bufferevent *bev = NULL;
567 	evutil_socket_t fd;
568 	const char *http_request;
569 	ev_uint16_t port=0, port2=0;
570 
571 	test_ok = 0;
572 	exit_base = data->base;
573 
574 	http = http_setup(&port, data->base, 0);
575 
576 	/* bind to a second socket */
577 	if (http_bind(http, &port2, 0) == -1)
578 		TT_DIE(("Bind socket failed"));
579 
580 	/* NULL request test */
581 	fd = http_connect("127.0.0.1", port);
582 
583 	/* Stupid thing to send a request */
584 	bev = bufferevent_socket_new(data->base, fd, 0);
585 	bufferevent_setcb(bev, http_badreq_readcb, http_writecb,
586 	    http_badreq_errorcb, data->base);
587 	bufferevent_enable(bev, EV_READ);
588 
589 	/* real NULL request */
590 	http_request = "";
591 
592 	bufferevent_write(bev, http_request, strlen(http_request));
593 
594 	shutdown(fd, SHUT_WR);
595 	timerclear(&tv);
596 	tv.tv_usec = 10000;
597 	event_base_once(data->base, -1, EV_TIMEOUT, http_badreq_successcb, bev, &tv);
598 
599 	event_base_dispatch(data->base);
600 
601 	bufferevent_free(bev);
602 	evutil_closesocket(fd);
603 
604 	if (test_ok != 0) {
605 		fprintf(stdout, "FAILED\n");
606 		exit(1);
607 	}
608 
609 	/* Second answer (BAD REQUEST) on connection close */
610 
611 	/* connect to the second port */
612 	fd = http_connect("127.0.0.1", port2);
613 
614 	/* Stupid thing to send a request */
615 	bev = bufferevent_socket_new(data->base, fd, 0);
616 	bufferevent_setcb(bev, http_badreq_readcb, http_writecb,
617 	    http_badreq_errorcb, data->base);
618 	bufferevent_enable(bev, EV_READ);
619 
620 	/* first half of the http request */
621 	http_request =
622 		"GET /badrequest HTTP/1.0\r\n"	\
623 		"Connection: Keep-Alive\r\n"	\
624 		"\r\n";
625 
626 	bufferevent_write(bev, http_request, strlen(http_request));
627 
628 	timerclear(&tv);
629 	tv.tv_usec = 10000;
630 	event_base_once(data->base, -1, EV_TIMEOUT, http_badreq_successcb, bev, &tv);
631 
632 	event_base_dispatch(data->base);
633 
634 	tt_int_op(test_ok, ==, 2);
635 
636 end:
637 	evhttp_free(http);
638 	if (bev)
639 		bufferevent_free(bev);
640 }
641 
642 static struct evhttp_connection *delayed_client;
643 
644 static void
645 http_large_delay_cb(struct evhttp_request *req, void *arg)
646 {
647 	struct timeval tv;
648 	evutil_timerclear(&tv);
649 	tv.tv_usec = 500000;
650 
651 	event_base_once(arg, -1, EV_TIMEOUT, http_delay_reply, req, &tv);
652 	evhttp_connection_fail_(delayed_client, EVCON_HTTP_EOF);
653 }
654 
655 /*
656  * HTTP DELETE test,  just piggyback on the basic test
657  */
658 
659 static void
660 http_delete_cb(struct evhttp_request *req, void *arg)
661 {
662 	struct evbuffer *evb = evbuffer_new();
663 	int empty = evhttp_find_header(evhttp_request_get_input_headers(req), "Empty") != NULL;
664 
665 	/* Expecting a DELETE request */
666 	if (evhttp_request_get_command(req) != EVHTTP_REQ_DELETE) {
667 		fprintf(stdout, "FAILED (delete type)\n");
668 		exit(1);
669 	}
670 
671 	event_debug(("%s: called\n", __func__));
672 	evbuffer_add_printf(evb, BASIC_REQUEST_BODY);
673 
674 	/* allow sending of an empty reply */
675 	evhttp_send_reply(req, HTTP_OK, "Everything is fine",
676 	    !empty ? evb : NULL);
677 
678 	evbuffer_free(evb);
679 }
680 
681 static void
682 http_delete_test(void *arg)
683 {
684 	struct basic_test_data *data = arg;
685 	struct bufferevent *bev;
686 	evutil_socket_t fd;
687 	const char *http_request;
688 	ev_uint16_t port = 0;
689 
690 	test_ok = 0;
691 
692 	http = http_setup(&port, data->base, 0);
693 
694 	fd = http_connect("127.0.0.1", port);
695 
696 	/* Stupid thing to send a request */
697 	bev = bufferevent_socket_new(data->base, fd, 0);
698 	bufferevent_setcb(bev, http_readcb, http_writecb,
699 	    http_errorcb, data->base);
700 
701 	http_request =
702 	    "DELETE /deleteit HTTP/1.1\r\n"
703 	    "Host: somehost\r\n"
704 	    "Connection: close\r\n"
705 	    "\r\n";
706 
707 	bufferevent_write(bev, http_request, strlen(http_request));
708 
709 	event_base_dispatch(data->base);
710 
711 	bufferevent_free(bev);
712 	evutil_closesocket(fd);
713 
714 	evhttp_free(http);
715 
716 	tt_int_op(test_ok, ==, 2);
717  end:
718 	;
719 }
720 
721 static void
722 http_allowed_methods_eventcb(struct bufferevent *bev, short what, void *arg)
723 {
724 	char **output = arg;
725 	if ((what & (BEV_EVENT_ERROR|BEV_EVENT_EOF))) {
726 		char buf[4096];
727 		int n;
728 		n = evbuffer_remove(bufferevent_get_input(bev), buf,
729 		    sizeof(buf)-1);
730 		if (n >= 0) {
731 			buf[n]='\0';
732 			if (*output)
733 				free(*output);
734 			*output = strdup(buf);
735 		}
736 		event_base_loopexit(exit_base, NULL);
737 	}
738 }
739 
740 static void
741 http_allowed_methods_test(void *arg)
742 {
743 	struct basic_test_data *data = arg;
744 	struct bufferevent *bev1, *bev2, *bev3;
745 	evutil_socket_t fd1, fd2, fd3;
746 	const char *http_request;
747 	char *result1=NULL, *result2=NULL, *result3=NULL;
748 	ev_uint16_t port = 0;
749 
750 	exit_base = data->base;
751 	test_ok = 0;
752 
753 	http = http_setup(&port, data->base, 0);
754 
755 	fd1 = http_connect("127.0.0.1", port);
756 
757 	/* GET is out; PATCH is in. */
758 	evhttp_set_allowed_methods(http, EVHTTP_REQ_PATCH);
759 
760 	/* Stupid thing to send a request */
761 	bev1 = bufferevent_socket_new(data->base, fd1, 0);
762 	bufferevent_enable(bev1, EV_READ|EV_WRITE);
763 	bufferevent_setcb(bev1, NULL, NULL,
764 	    http_allowed_methods_eventcb, &result1);
765 
766 	http_request =
767 	    "GET /index.html HTTP/1.1\r\n"
768 	    "Host: somehost\r\n"
769 	    "Connection: close\r\n"
770 	    "\r\n";
771 
772 	bufferevent_write(bev1, http_request, strlen(http_request));
773 
774 	event_base_dispatch(data->base);
775 
776 	fd2 = http_connect("127.0.0.1", port);
777 
778 	bev2 = bufferevent_socket_new(data->base, fd2, 0);
779 	bufferevent_enable(bev2, EV_READ|EV_WRITE);
780 	bufferevent_setcb(bev2, NULL, NULL,
781 	    http_allowed_methods_eventcb, &result2);
782 
783 	http_request =
784 	    "PATCH /test HTTP/1.1\r\n"
785 	    "Host: somehost\r\n"
786 	    "Connection: close\r\n"
787 	    "\r\n";
788 
789 	bufferevent_write(bev2, http_request, strlen(http_request));
790 
791 	event_base_dispatch(data->base);
792 
793 	fd3 = http_connect("127.0.0.1", port);
794 
795 	bev3 = bufferevent_socket_new(data->base, fd3, 0);
796 	bufferevent_enable(bev3, EV_READ|EV_WRITE);
797 	bufferevent_setcb(bev3, NULL, NULL,
798 	    http_allowed_methods_eventcb, &result3);
799 
800 	http_request =
801 	    "FLOOP /test HTTP/1.1\r\n"
802 	    "Host: somehost\r\n"
803 	    "Connection: close\r\n"
804 	    "\r\n";
805 
806 	bufferevent_write(bev3, http_request, strlen(http_request));
807 
808 	event_base_dispatch(data->base);
809 
810 	bufferevent_free(bev1);
811 	bufferevent_free(bev2);
812 	bufferevent_free(bev3);
813 	evutil_closesocket(fd1);
814 	evutil_closesocket(fd2);
815 	evutil_closesocket(fd3);
816 
817 	evhttp_free(http);
818 
819 	/* Method known but disallowed */
820 	tt_assert(result1);
821 	tt_assert(!strncmp(result1, "HTTP/1.1 501 ", strlen("HTTP/1.1 501 ")));
822 
823 	/* Method known and allowed */
824 	tt_assert(result2);
825 	tt_assert(!strncmp(result2, "HTTP/1.1 200 ", strlen("HTTP/1.1 200 ")));
826 
827 	/* Method unknown */
828 	tt_assert(result3);
829 	tt_assert(!strncmp(result3, "HTTP/1.1 501 ", strlen("HTTP/1.1 501 ")));
830 
831  end:
832 	if (result1)
833 		free(result1);
834 	if (result2)
835 		free(result2);
836 	if (result3)
837 		free(result3);
838 }
839 
840 static void http_request_done(struct evhttp_request *, void *);
841 static void http_request_empty_done(struct evhttp_request *, void *);
842 
843 static void
844 http_connection_test_(struct basic_test_data *data, int persistent, const char *address, struct evdns_base *dnsbase, int ipv6)
845 {
846 	ev_uint16_t port = 0;
847 	struct evhttp_connection *evcon = NULL;
848 	struct evhttp_request *req = NULL;
849 
850 	test_ok = 0;
851 
852 	http = http_setup(&port, data->base, ipv6);
853 
854 	evcon = evhttp_connection_base_new(data->base, dnsbase, address, port);
855 	tt_assert(evcon);
856 
857 	tt_assert(evhttp_connection_get_base(evcon) == data->base);
858 
859 	exit_base = data->base;
860 	/*
861 	 * At this point, we want to schedule a request to the HTTP
862 	 * server using our make request method.
863 	 */
864 
865 	req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
866 
867 	/* Add the information that we care about */
868 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
869 
870 	/* We give ownership of the request to the connection */
871 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
872 		fprintf(stdout, "FAILED\n");
873 		exit(1);
874 	}
875 
876 	event_base_dispatch(data->base);
877 
878 	tt_assert(test_ok);
879 
880 	/* try to make another request over the same connection */
881 	test_ok = 0;
882 
883 	req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
884 
885 	/* Add the information that we care about */
886 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
887 
888 	/*
889 	 * if our connections are not supposed to be persistent; request
890 	 * a close from the server.
891 	 */
892 	if (!persistent)
893 		evhttp_add_header(evhttp_request_get_output_headers(req), "Connection", "close");
894 
895 	/* We give ownership of the request to the connection */
896 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
897 		tt_abort_msg("couldn't make request");
898 	}
899 
900 	event_base_dispatch(data->base);
901 
902 	/* make another request: request empty reply */
903 	test_ok = 0;
904 
905 	req = evhttp_request_new(http_request_empty_done, data->base);
906 
907 	/* Add the information that we care about */
908 	evhttp_add_header(evhttp_request_get_output_headers(req), "Empty", "itis");
909 
910 	/* We give ownership of the request to the connection */
911 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
912 		tt_abort_msg("Couldn't make request");
913 	}
914 
915 	event_base_dispatch(data->base);
916 
917  end:
918 	if (evcon)
919 		evhttp_connection_free(evcon);
920 	if (http)
921 		evhttp_free(http);
922 }
923 
924 static void
925 http_connection_test(void *arg)
926 {
927 	http_connection_test_(arg, 0, "127.0.0.1", NULL, 0);
928 }
929 static void
930 http_persist_connection_test(void *arg)
931 {
932 	http_connection_test_(arg, 1, "127.0.0.1", NULL, 0);
933 }
934 
935 static struct regress_dns_server_table search_table[] = {
936 	{ "localhost", "A", "127.0.0.1", 0 },
937 	{ NULL, NULL, NULL, 0 }
938 };
939 
940 static void
941 http_connection_async_test(void *arg)
942 {
943 	struct basic_test_data *data = arg;
944 	ev_uint16_t port = 0;
945 	struct evhttp_connection *evcon = NULL;
946 	struct evhttp_request *req = NULL;
947 	struct evdns_base *dns_base = NULL;
948 	ev_uint16_t portnum = 0;
949 	char address[64];
950 
951 	exit_base = data->base;
952 	tt_assert(regress_dnsserver(data->base, &portnum, search_table));
953 
954 	dns_base = evdns_base_new(data->base, 0/* init name servers */);
955 	tt_assert(dns_base);
956 
957 	/* Add ourself as the only nameserver, and make sure we really are
958 	 * the only nameserver. */
959 	evutil_snprintf(address, sizeof(address), "127.0.0.1:%d", portnum);
960 	evdns_base_nameserver_ip_add(dns_base, address);
961 
962 	test_ok = 0;
963 
964 	http = http_setup(&port, data->base, 0);
965 
966 	evcon = evhttp_connection_base_new(data->base, dns_base, "127.0.0.1", port);
967 	tt_assert(evcon);
968 
969 	/*
970 	 * At this point, we want to schedule a request to the HTTP
971 	 * server using our make request method.
972 	 */
973 
974 	req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
975 
976 	/* Add the information that we care about */
977 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
978 
979 	/* We give ownership of the request to the connection */
980 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
981 		fprintf(stdout, "FAILED\n");
982 		exit(1);
983 	}
984 
985 	event_base_dispatch(data->base);
986 
987 	tt_assert(test_ok);
988 
989 	/* try to make another request over the same connection */
990 	test_ok = 0;
991 
992 	req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
993 
994 	/* Add the information that we care about */
995 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
996 
997 	/*
998 	 * if our connections are not supposed to be persistent; request
999 	 * a close from the server.
1000 	 */
1001 	evhttp_add_header(evhttp_request_get_output_headers(req), "Connection", "close");
1002 
1003 	/* We give ownership of the request to the connection */
1004 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
1005 		tt_abort_msg("couldn't make request");
1006 	}
1007 
1008 	event_base_dispatch(data->base);
1009 
1010 	/* make another request: request empty reply */
1011 	test_ok = 0;
1012 
1013 	req = evhttp_request_new(http_request_empty_done, data->base);
1014 
1015 	/* Add the information that we care about */
1016 	evhttp_add_header(evhttp_request_get_output_headers(req), "Empty", "itis");
1017 
1018 	/* We give ownership of the request to the connection */
1019 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
1020 		tt_abort_msg("Couldn't make request");
1021 	}
1022 
1023 	event_base_dispatch(data->base);
1024 
1025  end:
1026 	if (evcon)
1027 		evhttp_connection_free(evcon);
1028 	if (http)
1029 		evhttp_free(http);
1030 	if (dns_base)
1031 		evdns_base_free(dns_base, 0);
1032 	regress_clean_dnsserver();
1033 }
1034 
1035 static void
1036 http_request_never_call(struct evhttp_request *req, void *arg)
1037 {
1038 	fprintf(stdout, "FAILED\n");
1039 	exit(1);
1040 }
1041 
1042 static void
1043 http_do_cancel(evutil_socket_t fd, short what, void *arg)
1044 {
1045 	struct evhttp_request *req = arg;
1046 	struct timeval tv;
1047 	struct event_base *base;
1048 	evutil_timerclear(&tv);
1049 	tv.tv_sec = 0;
1050 	tv.tv_usec = 500 * 1000;
1051 
1052 	base = evhttp_connection_get_base(evhttp_request_get_connection(req));
1053 	evhttp_cancel_request(req);
1054 
1055 	event_base_loopexit(base, &tv);
1056 
1057 	++test_ok;
1058 }
1059 
1060 static void
1061 http_cancel_test(void *arg)
1062 {
1063 	struct basic_test_data *data = arg;
1064 	ev_uint16_t port = 0;
1065 	struct evhttp_connection *evcon = NULL;
1066 	struct evhttp_request *req = NULL;
1067 	struct timeval tv;
1068 
1069 	exit_base = data->base;
1070 
1071 	test_ok = 0;
1072 
1073 	http = http_setup(&port, data->base, 0);
1074 
1075 	evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
1076 	tt_assert(evcon);
1077 
1078 	/*
1079 	 * At this point, we want to schedule a request to the HTTP
1080 	 * server using our make request method.
1081 	 */
1082 
1083 	req = evhttp_request_new(http_request_never_call, NULL);
1084 
1085 	/* Add the information that we care about */
1086 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
1087 
1088 	/* We give ownership of the request to the connection */
1089 	tt_int_op(evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/delay"),
1090 		  !=, -1);
1091 
1092 	evutil_timerclear(&tv);
1093 	tv.tv_sec = 0;
1094 	tv.tv_usec = 100 * 1000;
1095 
1096 	event_base_once(data->base, -1, EV_TIMEOUT, http_do_cancel, req, &tv);
1097 
1098 	event_base_dispatch(data->base);
1099 
1100 	tt_int_op(test_ok, ==, 2);
1101 
1102 	/* try to make another request over the same connection */
1103 	test_ok = 0;
1104 
1105 	req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
1106 
1107 	/* Add the information that we care about */
1108 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
1109 
1110 	/* We give ownership of the request to the connection */
1111 	tt_int_op(evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test"),
1112 		  !=, -1);
1113 
1114 	event_base_dispatch(data->base);
1115 
1116 	/* make another request: request empty reply */
1117 	test_ok = 0;
1118 
1119 	req = evhttp_request_new(http_request_empty_done, data->base);
1120 
1121 	/* Add the information that we care about */
1122 	evhttp_add_header(evhttp_request_get_output_headers(req), "Empty", "itis");
1123 
1124 	/* We give ownership of the request to the connection */
1125 	tt_int_op(evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test"),
1126 		  !=, -1);
1127 
1128 	event_base_dispatch(data->base);
1129 
1130  end:
1131 	if (evcon)
1132 		evhttp_connection_free(evcon);
1133 	if (http)
1134 		evhttp_free(http);
1135 }
1136 
1137 static void
1138 http_request_done(struct evhttp_request *req, void *arg)
1139 {
1140 	const char *what = arg;
1141 
1142 	if (evhttp_request_get_response_code(req) != HTTP_OK) {
1143 		fprintf(stderr, "FAILED\n");
1144 		exit(1);
1145 	}
1146 
1147 	if (evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Type") == NULL) {
1148 		fprintf(stderr, "FAILED\n");
1149 		exit(1);
1150 	}
1151 
1152 	if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != strlen(what)) {
1153 		fprintf(stderr, "FAILED\n");
1154 		exit(1);
1155 	}
1156 
1157 	if (evbuffer_datacmp(evhttp_request_get_input_buffer(req), what) != 0) {
1158 		fprintf(stderr, "FAILED\n");
1159 		exit(1);
1160 	}
1161 
1162 	test_ok = 1;
1163 	EVUTIL_ASSERT(exit_base);
1164 	event_base_loopexit(exit_base, NULL);
1165 }
1166 
1167 static void
1168 http_request_expect_error(struct evhttp_request *req, void *arg)
1169 {
1170 	if (evhttp_request_get_response_code(req) == HTTP_OK) {
1171 		fprintf(stderr, "FAILED\n");
1172 		exit(1);
1173 	}
1174 
1175 	test_ok = 1;
1176 	EVUTIL_ASSERT(arg);
1177 	event_base_loopexit(arg, NULL);
1178 }
1179 
1180 /* test virtual hosts */
1181 static void
1182 http_virtual_host_test(void *arg)
1183 {
1184 	struct basic_test_data *data = arg;
1185 	ev_uint16_t port = 0;
1186 	struct evhttp_connection *evcon = NULL;
1187 	struct evhttp_request *req = NULL;
1188 	struct evhttp *second = NULL, *third = NULL;
1189 	evutil_socket_t fd;
1190 	struct bufferevent *bev;
1191 	const char *http_request;
1192 
1193 	exit_base = data->base;
1194 
1195 	http = http_setup(&port, data->base, 0);
1196 
1197 	/* virtual host */
1198 	second = evhttp_new(NULL);
1199 	evhttp_set_cb(second, "/funnybunny", http_basic_cb, NULL);
1200 	third = evhttp_new(NULL);
1201 	evhttp_set_cb(third, "/blackcoffee", http_basic_cb, NULL);
1202 
1203 	if (evhttp_add_virtual_host(http, "foo.com", second) == -1) {
1204 		tt_abort_msg("Couldn't add vhost");
1205 	}
1206 
1207 	if (evhttp_add_virtual_host(http, "bar.*.foo.com", third) == -1) {
1208 		tt_abort_msg("Couldn't add wildcarded vhost");
1209 	}
1210 
1211 	/* add some aliases to the vhosts */
1212 	tt_assert(evhttp_add_server_alias(second, "manolito.info") == 0);
1213 	tt_assert(evhttp_add_server_alias(third, "bonkers.org") == 0);
1214 
1215 	evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
1216 	tt_assert(evcon);
1217 
1218 	/* make a request with a different host and expect an error */
1219 	req = evhttp_request_new(http_request_expect_error, data->base);
1220 
1221 	/* Add the information that we care about */
1222 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
1223 
1224 	/* We give ownership of the request to the connection */
1225 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
1226 		"/funnybunny") == -1) {
1227 		tt_abort_msg("Couldn't make request");
1228 	}
1229 
1230 	event_base_dispatch(data->base);
1231 
1232 	tt_assert(test_ok == 1);
1233 
1234 	test_ok = 0;
1235 
1236 	/* make a request with the right host and expect a response */
1237 	req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
1238 
1239 	/* Add the information that we care about */
1240 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "foo.com");
1241 
1242 	/* We give ownership of the request to the connection */
1243 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
1244 		"/funnybunny") == -1) {
1245 		fprintf(stdout, "FAILED\n");
1246 		exit(1);
1247 	}
1248 
1249 	event_base_dispatch(data->base);
1250 
1251 	tt_assert(test_ok == 1);
1252 
1253 	test_ok = 0;
1254 
1255 	/* make a request with the right host and expect a response */
1256 	req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
1257 
1258 	/* Add the information that we care about */
1259 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "bar.magic.foo.com");
1260 
1261 	/* We give ownership of the request to the connection */
1262 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
1263 		"/blackcoffee") == -1) {
1264 		tt_abort_msg("Couldn't make request");
1265 	}
1266 
1267 	event_base_dispatch(data->base);
1268 
1269 	tt_assert(test_ok == 1)
1270 
1271 	test_ok = 0;
1272 
1273 	/* make a request with the right host and expect a response */
1274 	req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
1275 
1276 	/* Add the information that we care about */
1277 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "manolito.info");
1278 
1279 	/* We give ownership of the request to the connection */
1280 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
1281 		"/funnybunny") == -1) {
1282 		tt_abort_msg("Couldn't make request");
1283 	}
1284 
1285 	event_base_dispatch(data->base);
1286 
1287 	tt_assert(test_ok == 1)
1288 
1289 	test_ok = 0;
1290 
1291 	/* make a request with the right host and expect a response */
1292 	req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
1293 
1294 	/* Add the Host header. This time with the optional port. */
1295 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "bonkers.org:8000");
1296 
1297 	/* We give ownership of the request to the connection */
1298 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
1299 		"/blackcoffee") == -1) {
1300 		tt_abort_msg("Couldn't make request");
1301 	}
1302 
1303 	event_base_dispatch(data->base);
1304 
1305 	tt_assert(test_ok == 1)
1306 
1307 	test_ok = 0;
1308 
1309 	/* Now make a raw request with an absolute URI. */
1310 	fd = http_connect("127.0.0.1", port);
1311 
1312 	/* Stupid thing to send a request */
1313 	bev = bufferevent_socket_new(data->base, fd, 0);
1314 	bufferevent_setcb(bev, http_readcb, http_writecb,
1315 	    http_errorcb, NULL);
1316 
1317 	/* The host in the URI should override the Host: header */
1318 	http_request =
1319 	    "GET http://manolito.info/funnybunny HTTP/1.1\r\n"
1320 	    "Host: somehost\r\n"
1321 	    "Connection: close\r\n"
1322 	    "\r\n";
1323 
1324 	bufferevent_write(bev, http_request, strlen(http_request));
1325 
1326 	event_base_dispatch(data->base);
1327 
1328 	tt_int_op(test_ok, ==, 2);
1329 
1330 	bufferevent_free(bev);
1331 	evutil_closesocket(fd);
1332 
1333  end:
1334 	if (evcon)
1335 		evhttp_connection_free(evcon);
1336 	if (http)
1337 		evhttp_free(http);
1338 }
1339 
1340 
1341 /* test date header and content length */
1342 
1343 static void
1344 http_request_empty_done(struct evhttp_request *req, void *arg)
1345 {
1346 	if (evhttp_request_get_response_code(req) != HTTP_OK) {
1347 		fprintf(stderr, "FAILED\n");
1348 		exit(1);
1349 	}
1350 
1351 	if (evhttp_find_header(evhttp_request_get_input_headers(req), "Date") == NULL) {
1352 		fprintf(stderr, "FAILED\n");
1353 		exit(1);
1354 	}
1355 
1356 
1357 	if (evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Length") == NULL) {
1358 		fprintf(stderr, "FAILED\n");
1359 		exit(1);
1360 	}
1361 
1362 	if (strcmp(evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Length"),
1363 		"0")) {
1364 		fprintf(stderr, "FAILED\n");
1365 		exit(1);
1366 	}
1367 
1368 	if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != 0) {
1369 		fprintf(stderr, "FAILED\n");
1370 		exit(1);
1371 	}
1372 
1373 	test_ok = 1;
1374 	EVUTIL_ASSERT(arg);
1375 	event_base_loopexit(arg, NULL);
1376 }
1377 
1378 /*
1379  * HTTP DISPATCHER test
1380  */
1381 
1382 void
1383 http_dispatcher_cb(struct evhttp_request *req, void *arg)
1384 {
1385 
1386 	struct evbuffer *evb = evbuffer_new();
1387 	event_debug(("%s: called\n", __func__));
1388 	evbuffer_add_printf(evb, "DISPATCHER_TEST");
1389 
1390 	evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb);
1391 
1392 	evbuffer_free(evb);
1393 }
1394 
1395 static void
1396 http_dispatcher_test_done(struct evhttp_request *req, void *arg)
1397 {
1398 	struct event_base *base = arg;
1399 	const char *what = "DISPATCHER_TEST";
1400 
1401 	if (evhttp_request_get_response_code(req) != HTTP_OK) {
1402 		fprintf(stderr, "FAILED\n");
1403 		exit(1);
1404 	}
1405 
1406 	if (evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Type") == NULL) {
1407 		fprintf(stderr, "FAILED (content type)\n");
1408 		exit(1);
1409 	}
1410 
1411 	if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != strlen(what)) {
1412 		fprintf(stderr, "FAILED (length %lu vs %lu)\n",
1413 		    (unsigned long)evbuffer_get_length(evhttp_request_get_input_buffer(req)), (unsigned long)strlen(what));
1414 		exit(1);
1415 	}
1416 
1417 	if (evbuffer_datacmp(evhttp_request_get_input_buffer(req), what) != 0) {
1418 		fprintf(stderr, "FAILED (data)\n");
1419 		exit(1);
1420 	}
1421 
1422 	test_ok = 1;
1423 	event_base_loopexit(base, NULL);
1424 }
1425 
1426 static void
1427 http_dispatcher_test(void *arg)
1428 {
1429 	struct basic_test_data *data = arg;
1430 	ev_uint16_t port = 0;
1431 	struct evhttp_connection *evcon = NULL;
1432 	struct evhttp_request *req = NULL;
1433 
1434 	test_ok = 0;
1435 
1436 	http = http_setup(&port, data->base, 0);
1437 
1438 	evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
1439 	tt_assert(evcon);
1440 
1441 	/* also bind to local host */
1442 	evhttp_connection_set_local_address(evcon, "127.0.0.1");
1443 
1444 	/*
1445 	 * At this point, we want to schedule an HTTP GET request
1446 	 * server using our make request method.
1447 	 */
1448 
1449 	req = evhttp_request_new(http_dispatcher_test_done, data->base);
1450 	tt_assert(req);
1451 
1452 	/* Add the information that we care about */
1453 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
1454 
1455 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/?arg=val") == -1) {
1456 		tt_abort_msg("Couldn't make request");
1457 	}
1458 
1459 	event_base_dispatch(data->base);
1460 
1461  end:
1462 	if (evcon)
1463 		evhttp_connection_free(evcon);
1464 	if (http)
1465 		evhttp_free(http);
1466 }
1467 
1468 /*
1469  * HTTP POST test.
1470  */
1471 
1472 void http_postrequest_done(struct evhttp_request *, void *);
1473 
1474 #define POST_DATA "Okay.  Not really printf"
1475 
1476 static void
1477 http_post_test(void *arg)
1478 {
1479 	struct basic_test_data *data = arg;
1480 	ev_uint16_t port = 0;
1481 	struct evhttp_connection *evcon = NULL;
1482 	struct evhttp_request *req = NULL;
1483 
1484 	test_ok = 0;
1485 
1486 	http = http_setup(&port, data->base, 0);
1487 
1488 	evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
1489 	tt_assert(evcon);
1490 
1491 	/*
1492 	 * At this point, we want to schedule an HTTP POST request
1493 	 * server using our make request method.
1494 	 */
1495 
1496 	req = evhttp_request_new(http_postrequest_done, data->base);
1497 	tt_assert(req);
1498 
1499 	/* Add the information that we care about */
1500 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
1501 	evbuffer_add_printf(evhttp_request_get_output_buffer(req), POST_DATA);
1502 
1503 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/postit") == -1) {
1504 		tt_abort_msg("Couldn't make request");
1505 	}
1506 
1507 	event_base_dispatch(data->base);
1508 
1509 	tt_int_op(test_ok, ==, 1);
1510 
1511 	test_ok = 0;
1512 
1513 	req = evhttp_request_new(http_postrequest_done, data->base);
1514 	tt_assert(req);
1515 
1516 	/* Now try with 100-continue. */
1517 
1518 	/* Add the information that we care about */
1519 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
1520 	evhttp_add_header(evhttp_request_get_output_headers(req), "Expect", "100-continue");
1521 	evbuffer_add_printf(evhttp_request_get_output_buffer(req), POST_DATA);
1522 
1523 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/postit") == -1) {
1524 		tt_abort_msg("Couldn't make request");
1525 	}
1526 
1527 	event_base_dispatch(data->base);
1528 
1529 	tt_int_op(test_ok, ==, 1);
1530 
1531 	evhttp_connection_free(evcon);
1532 	evhttp_free(http);
1533 
1534  end:
1535 	;
1536 }
1537 
1538 void
1539 http_post_cb(struct evhttp_request *req, void *arg)
1540 {
1541 	struct evbuffer *evb;
1542 	event_debug(("%s: called\n", __func__));
1543 
1544 	/* Yes, we are expecting a post request */
1545 	if (evhttp_request_get_command(req) != EVHTTP_REQ_POST) {
1546 		fprintf(stdout, "FAILED (post type)\n");
1547 		exit(1);
1548 	}
1549 
1550 	if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != strlen(POST_DATA)) {
1551 		fprintf(stdout, "FAILED (length: %lu vs %lu)\n",
1552 		    (unsigned long) evbuffer_get_length(evhttp_request_get_input_buffer(req)), (unsigned long) strlen(POST_DATA));
1553 		exit(1);
1554 	}
1555 
1556 	if (evbuffer_datacmp(evhttp_request_get_input_buffer(req), POST_DATA) != 0) {
1557 		fprintf(stdout, "FAILED (data)\n");
1558 		fprintf(stdout, "Got :%s\n", evbuffer_pullup(evhttp_request_get_input_buffer(req),-1));
1559 		fprintf(stdout, "Want:%s\n", POST_DATA);
1560 		exit(1);
1561 	}
1562 
1563 	evb = evbuffer_new();
1564 	evbuffer_add_printf(evb, BASIC_REQUEST_BODY);
1565 
1566 	evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb);
1567 
1568 	evbuffer_free(evb);
1569 }
1570 
1571 void
1572 http_postrequest_done(struct evhttp_request *req, void *arg)
1573 {
1574 	const char *what = BASIC_REQUEST_BODY;
1575 	struct event_base *base = arg;
1576 
1577 	if (req == NULL) {
1578 		fprintf(stderr, "FAILED (timeout)\n");
1579 		exit(1);
1580 	}
1581 
1582 	if (evhttp_request_get_response_code(req) != HTTP_OK) {
1583 
1584 		fprintf(stderr, "FAILED (response code)\n");
1585 		exit(1);
1586 	}
1587 
1588 	if (evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Type") == NULL) {
1589 		fprintf(stderr, "FAILED (content type)\n");
1590 		exit(1);
1591 	}
1592 
1593 	if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != strlen(what)) {
1594 		fprintf(stderr, "FAILED (length %lu vs %lu)\n",
1595 		    (unsigned long)evbuffer_get_length(evhttp_request_get_input_buffer(req)), (unsigned long)strlen(what));
1596 		exit(1);
1597 	}
1598 
1599 	if (evbuffer_datacmp(evhttp_request_get_input_buffer(req), what) != 0) {
1600 		fprintf(stderr, "FAILED (data)\n");
1601 		exit(1);
1602 	}
1603 
1604 	test_ok = 1;
1605 	event_base_loopexit(base, NULL);
1606 }
1607 
1608 /*
1609  * HTTP PUT test, basically just like POST, but ...
1610  */
1611 
1612 void http_putrequest_done(struct evhttp_request *, void *);
1613 
1614 #define PUT_DATA "Hi, I'm some PUT data"
1615 
1616 static void
1617 http_put_test(void *arg)
1618 {
1619 	struct basic_test_data *data = arg;
1620 	ev_uint16_t port = 0;
1621 	struct evhttp_connection *evcon = NULL;
1622 	struct evhttp_request *req = NULL;
1623 
1624 	test_ok = 0;
1625 
1626 	http = http_setup(&port, data->base, 0);
1627 
1628 	evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
1629 	tt_assert(evcon);
1630 
1631 	/*
1632 	 * Schedule the HTTP PUT request
1633 	 */
1634 
1635 	req = evhttp_request_new(http_putrequest_done, data->base);
1636 	tt_assert(req);
1637 
1638 	/* Add the information that we care about */
1639 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "someotherhost");
1640 	evbuffer_add_printf(evhttp_request_get_output_buffer(req), PUT_DATA);
1641 
1642 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_PUT, "/putit") == -1) {
1643 		tt_abort_msg("Couldn't make request");
1644 	}
1645 
1646 	event_base_dispatch(data->base);
1647 
1648 	evhttp_connection_free(evcon);
1649 	evhttp_free(http);
1650 
1651 	tt_int_op(test_ok, ==, 1);
1652  end:
1653 	;
1654 }
1655 
1656 void
1657 http_put_cb(struct evhttp_request *req, void *arg)
1658 {
1659 	struct evbuffer *evb;
1660 	event_debug(("%s: called\n", __func__));
1661 
1662 	/* Expecting a PUT request */
1663 	if (evhttp_request_get_command(req) != EVHTTP_REQ_PUT) {
1664 		fprintf(stdout, "FAILED (put type)\n");
1665 		exit(1);
1666 	}
1667 
1668 	if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != strlen(PUT_DATA)) {
1669 		fprintf(stdout, "FAILED (length: %lu vs %lu)\n",
1670 		    (unsigned long)evbuffer_get_length(evhttp_request_get_input_buffer(req)), (unsigned long)strlen(PUT_DATA));
1671 		exit(1);
1672 	}
1673 
1674 	if (evbuffer_datacmp(evhttp_request_get_input_buffer(req), PUT_DATA) != 0) {
1675 		fprintf(stdout, "FAILED (data)\n");
1676 		fprintf(stdout, "Got :%s\n", evbuffer_pullup(evhttp_request_get_input_buffer(req),-1));
1677 		fprintf(stdout, "Want:%s\n", PUT_DATA);
1678 		exit(1);
1679 	}
1680 
1681 	evb = evbuffer_new();
1682 	evbuffer_add_printf(evb, "That ain't funny");
1683 
1684 	evhttp_send_reply(req, HTTP_OK, "Everything is great", evb);
1685 
1686 	evbuffer_free(evb);
1687 }
1688 
1689 void
1690 http_putrequest_done(struct evhttp_request *req, void *arg)
1691 {
1692 	struct event_base *base = arg;
1693 	const char *what = "That ain't funny";
1694 
1695 	if (req == NULL) {
1696 		fprintf(stderr, "FAILED (timeout)\n");
1697 		exit(1);
1698 	}
1699 
1700 	if (evhttp_request_get_response_code(req) != HTTP_OK) {
1701 
1702 		fprintf(stderr, "FAILED (response code)\n");
1703 		exit(1);
1704 	}
1705 
1706 	if (evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Type") == NULL) {
1707 		fprintf(stderr, "FAILED (content type)\n");
1708 		exit(1);
1709 	}
1710 
1711 	if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != strlen(what)) {
1712 		fprintf(stderr, "FAILED (length %lu vs %lu)\n",
1713 		    (unsigned long)evbuffer_get_length(evhttp_request_get_input_buffer(req)), (unsigned long)strlen(what));
1714 		exit(1);
1715 	}
1716 
1717 
1718 	if (evbuffer_datacmp(evhttp_request_get_input_buffer(req), what) != 0) {
1719 		fprintf(stderr, "FAILED (data)\n");
1720 		exit(1);
1721 	}
1722 
1723 	test_ok = 1;
1724 	event_base_loopexit(base, NULL);
1725 }
1726 
1727 static void
1728 http_failure_readcb(struct bufferevent *bev, void *arg)
1729 {
1730 	const char *what = "400 Bad Request";
1731 	if (evbuffer_contains(bufferevent_get_input(bev), what)) {
1732 		test_ok = 2;
1733 		bufferevent_disable(bev, EV_READ);
1734 		event_base_loopexit(arg, NULL);
1735 	}
1736 }
1737 
1738 /*
1739  * Testing that the HTTP server can deal with a malformed request.
1740  */
1741 static void
1742 http_failure_test(void *arg)
1743 {
1744 	struct basic_test_data *data = arg;
1745 	struct bufferevent *bev;
1746 	evutil_socket_t fd;
1747 	const char *http_request;
1748 	ev_uint16_t port = 0;
1749 
1750 	test_ok = 0;
1751 
1752 	http = http_setup(&port, data->base, 0);
1753 
1754 	fd = http_connect("127.0.0.1", port);
1755 
1756 	/* Stupid thing to send a request */
1757 	bev = bufferevent_socket_new(data->base, fd, 0);
1758 	bufferevent_setcb(bev, http_failure_readcb, http_writecb,
1759 	    http_errorcb, data->base);
1760 
1761 	http_request = "illegal request\r\n";
1762 
1763 	bufferevent_write(bev, http_request, strlen(http_request));
1764 
1765 	event_base_dispatch(data->base);
1766 
1767 	bufferevent_free(bev);
1768 	evutil_closesocket(fd);
1769 
1770 	evhttp_free(http);
1771 
1772 	tt_int_op(test_ok, ==, 2);
1773  end:
1774 	;
1775 }
1776 
1777 static void
1778 close_detect_done(struct evhttp_request *req, void *arg)
1779 {
1780 	struct timeval tv;
1781 	tt_assert(req);
1782 	tt_assert(evhttp_request_get_response_code(req) == HTTP_OK);
1783 
1784 	test_ok = 1;
1785 
1786  end:
1787 	evutil_timerclear(&tv);
1788 	tv.tv_usec = 150000;
1789 	event_base_loopexit(arg, &tv);
1790 }
1791 
1792 static void
1793 close_detect_launch(evutil_socket_t fd, short what, void *arg)
1794 {
1795 	struct evhttp_connection *evcon = arg;
1796 	struct event_base *base = evhttp_connection_get_base(evcon);
1797 	struct evhttp_request *req;
1798 
1799 	req = evhttp_request_new(close_detect_done, base);
1800 
1801 	/* Add the information that we care about */
1802 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
1803 
1804 	/* We give ownership of the request to the connection */
1805 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
1806 		tt_fail_msg("Couldn't make request");
1807 	}
1808 }
1809 
1810 static void
1811 close_detect_cb(struct evhttp_request *req, void *arg)
1812 {
1813 	struct evhttp_connection *evcon = arg;
1814 	struct event_base *base = evhttp_connection_get_base(evcon);
1815 	struct timeval tv;
1816 
1817 	if (req != NULL && evhttp_request_get_response_code(req) != HTTP_OK) {
1818 		tt_abort_msg("Failed");
1819 	}
1820 
1821 	evutil_timerclear(&tv);
1822 	tv.tv_sec = 0;   /* longer than the http time out */
1823 	tv.tv_usec = 600000;   /* longer than the http time out */
1824 
1825 	/* launch a new request on the persistent connection in .3 seconds */
1826 	event_base_once(base, -1, EV_TIMEOUT, close_detect_launch, evcon, &tv);
1827  end:
1828 	;
1829 }
1830 
1831 
1832 static void
1833 http_close_detection_(struct basic_test_data *data, int with_delay)
1834 {
1835 	ev_uint16_t port = 0;
1836 	struct evhttp_connection *evcon = NULL;
1837 	struct evhttp_request *req = NULL;
1838 	const struct timeval sec_tenth = { 0, 100000 };
1839 
1840 	test_ok = 0;
1841 	http = http_setup(&port, data->base, 0);
1842 
1843 	/* .1 second timeout */
1844 	evhttp_set_timeout_tv(http, &sec_tenth);
1845 
1846 	evcon = evhttp_connection_base_new(data->base, NULL,
1847 	    "127.0.0.1", port);
1848 	evhttp_connection_set_timeout_tv(evcon, &sec_tenth);
1849 
1850 
1851 	tt_assert(evcon);
1852 	delayed_client = evcon;
1853 
1854 	/*
1855 	 * At this point, we want to schedule a request to the HTTP
1856 	 * server using our make request method.
1857 	 */
1858 
1859 	req = evhttp_request_new(close_detect_cb, evcon);
1860 
1861 	/* Add the information that we care about */
1862 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
1863 
1864 	/* We give ownership of the request to the connection */
1865 	if (evhttp_make_request(evcon,
1866 	    req, EVHTTP_REQ_GET, with_delay ? "/largedelay" : "/test") == -1) {
1867 		tt_abort_msg("couldn't make request");
1868 	}
1869 
1870 	event_base_dispatch(data->base);
1871 
1872 	/* at this point, the http server should have no connection */
1873 	tt_assert(TAILQ_FIRST(&http->connections) == NULL);
1874 
1875  end:
1876 	if (evcon)
1877 		evhttp_connection_free(evcon);
1878 	if (http)
1879 		evhttp_free(http);
1880 }
1881 static void
1882 http_close_detection_test(void *arg)
1883 {
1884 	http_close_detection_(arg, 0);
1885 }
1886 static void
1887 http_close_detection_delay_test(void *arg)
1888 {
1889 	http_close_detection_(arg, 1);
1890 }
1891 
1892 static void
1893 http_highport_test(void *arg)
1894 {
1895 	struct basic_test_data *data = arg;
1896 	int i = -1;
1897 	struct evhttp *myhttp = NULL;
1898 
1899 	/* Try a few different ports */
1900 	for (i = 0; i < 50; ++i) {
1901 		myhttp = evhttp_new(data->base);
1902 		if (evhttp_bind_socket(myhttp, "127.0.0.1", 65535 - i) == 0) {
1903 			test_ok = 1;
1904 			evhttp_free(myhttp);
1905 			return;
1906 		}
1907 		evhttp_free(myhttp);
1908 	}
1909 
1910 	tt_fail_msg("Couldn't get a high port");
1911 }
1912 
1913 static void
1914 http_bad_header_test(void *ptr)
1915 {
1916 	struct evkeyvalq headers;
1917 
1918 	TAILQ_INIT(&headers);
1919 
1920 	tt_want(evhttp_add_header(&headers, "One", "Two") == 0);
1921 	tt_want(evhttp_add_header(&headers, "One", "Two\r\n Three") == 0);
1922 	tt_want(evhttp_add_header(&headers, "One\r", "Two") == -1);
1923 	tt_want(evhttp_add_header(&headers, "One\n", "Two") == -1);
1924 	tt_want(evhttp_add_header(&headers, "One", "Two\r") == -1);
1925 	tt_want(evhttp_add_header(&headers, "One", "Two\n") == -1);
1926 
1927 	evhttp_clear_headers(&headers);
1928 }
1929 
1930 static int validate_header(
1931 	const struct evkeyvalq* headers,
1932 	const char *key, const char *value)
1933 {
1934 	const char *real_val = evhttp_find_header(headers, key);
1935 	tt_assert(real_val != NULL);
1936 	tt_want(strcmp(real_val, value) == 0);
1937 end:
1938 	return (0);
1939 }
1940 
1941 static void
1942 http_parse_query_test(void *ptr)
1943 {
1944 	struct evkeyvalq headers;
1945 	int r;
1946 
1947 	TAILQ_INIT(&headers);
1948 
1949 	r = evhttp_parse_query("http://www.test.com/?q=test", &headers);
1950 	tt_want(validate_header(&headers, "q", "test") == 0);
1951 	tt_int_op(r, ==, 0);
1952 	evhttp_clear_headers(&headers);
1953 
1954 	r = evhttp_parse_query("http://www.test.com/?q=test&foo=bar", &headers);
1955 	tt_want(validate_header(&headers, "q", "test") == 0);
1956 	tt_want(validate_header(&headers, "foo", "bar") == 0);
1957 	tt_int_op(r, ==, 0);
1958 	evhttp_clear_headers(&headers);
1959 
1960 	r = evhttp_parse_query("http://www.test.com/?q=test+foo", &headers);
1961 	tt_want(validate_header(&headers, "q", "test foo") == 0);
1962 	tt_int_op(r, ==, 0);
1963 	evhttp_clear_headers(&headers);
1964 
1965 	r = evhttp_parse_query("http://www.test.com/?q=test%0Afoo", &headers);
1966 	tt_want(validate_header(&headers, "q", "test\nfoo") == 0);
1967 	tt_int_op(r, ==, 0);
1968 	evhttp_clear_headers(&headers);
1969 
1970 	r = evhttp_parse_query("http://www.test.com/?q=test%0Dfoo", &headers);
1971 	tt_want(validate_header(&headers, "q", "test\rfoo") == 0);
1972 	tt_int_op(r, ==, 0);
1973 	evhttp_clear_headers(&headers);
1974 
1975 	r = evhttp_parse_query("http://www.test.com/?q=test&&q2", &headers);
1976 	tt_int_op(r, ==, -1);
1977 	evhttp_clear_headers(&headers);
1978 
1979 	r = evhttp_parse_query("http://www.test.com/?q=test+this", &headers);
1980 	tt_want(validate_header(&headers, "q", "test this") == 0);
1981 	tt_int_op(r, ==, 0);
1982 	evhttp_clear_headers(&headers);
1983 
1984 	r = evhttp_parse_query("http://www.test.com/?q=test&q2=foo", &headers);
1985 	tt_int_op(r, ==, 0);
1986 	tt_want(validate_header(&headers, "q", "test") == 0);
1987 	tt_want(validate_header(&headers, "q2", "foo") == 0);
1988 	evhttp_clear_headers(&headers);
1989 
1990 	r = evhttp_parse_query("http://www.test.com/?q&q2=foo", &headers);
1991 	tt_int_op(r, ==, -1);
1992 	evhttp_clear_headers(&headers);
1993 
1994 	r = evhttp_parse_query("http://www.test.com/?q=foo&q2", &headers);
1995 	tt_int_op(r, ==, -1);
1996 	evhttp_clear_headers(&headers);
1997 
1998 	r = evhttp_parse_query("http://www.test.com/?q=foo&q2&q3=x", &headers);
1999 	tt_int_op(r, ==, -1);
2000 	evhttp_clear_headers(&headers);
2001 
2002 	r = evhttp_parse_query("http://www.test.com/?q=&q2=&q3=", &headers);
2003 	tt_int_op(r, ==, 0);
2004 	tt_want(validate_header(&headers, "q", "") == 0);
2005 	tt_want(validate_header(&headers, "q2", "") == 0);
2006 	tt_want(validate_header(&headers, "q3", "") == 0);
2007 	evhttp_clear_headers(&headers);
2008 
2009 end:
2010 	evhttp_clear_headers(&headers);
2011 }
2012 
2013 static void
2014 http_parse_uri_test(void *ptr)
2015 {
2016 	const int nonconform = (ptr != NULL);
2017 	const unsigned parse_flags =
2018 	    nonconform ? EVHTTP_URI_NONCONFORMANT : 0;
2019 	struct evhttp_uri *uri = NULL;
2020 	char url_tmp[4096];
2021 #define URI_PARSE(uri) \
2022 	evhttp_uri_parse_with_flags((uri), parse_flags)
2023 
2024 #define TT_URI(want) do { 						\
2025 	char *ret = evhttp_uri_join(uri, url_tmp, sizeof(url_tmp));	\
2026 	tt_want(ret != NULL);						\
2027 	tt_want(ret == url_tmp);					\
2028 	if (strcmp(ret,want) != 0)					\
2029 		TT_FAIL(("\"%s\" != \"%s\"",ret,want));			\
2030 	} while(0)
2031 
2032 	tt_want(evhttp_uri_join(NULL, 0, 0) == NULL);
2033 	tt_want(evhttp_uri_join(NULL, url_tmp, 0) == NULL);
2034 	tt_want(evhttp_uri_join(NULL, url_tmp, sizeof(url_tmp)) == NULL);
2035 
2036 	/* bad URIs: parsing */
2037 #define BAD(s) do {							\
2038 		if (URI_PARSE(s) != NULL)				\
2039 			TT_FAIL(("Expected error parsing \"%s\"",s));	\
2040 	} while(0)
2041 	/* Nonconformant URIs we can parse: parsing */
2042 #define NCF(s) do {							\
2043 		uri = URI_PARSE(s);					\
2044 		if (uri != NULL && !nonconform) {			\
2045 			TT_FAIL(("Expected error parsing \"%s\"",s));	\
2046 		} else if (uri == NULL && nonconform) {			\
2047 			TT_FAIL(("Couldn't parse nonconformant URI \"%s\"", \
2048 				s));					\
2049 		}							\
2050 		if (uri) {						\
2051 			tt_want(evhttp_uri_join(uri, url_tmp,		\
2052 				sizeof(url_tmp)));			\
2053 			evhttp_uri_free(uri);				\
2054 		}							\
2055 	} while(0)
2056 
2057 	NCF("http://www.test.com/ why hello");
2058 	NCF("http://www.test.com/why-hello\x01");
2059 	NCF("http://www.test.com/why-hello?\x01");
2060 	NCF("http://www.test.com/why-hello#\x01");
2061 	BAD("http://www.\x01.test.com/why-hello");
2062 	BAD("http://www.%7test.com/why-hello");
2063 	NCF("http://www.test.com/why-hell%7o");
2064 	BAD("h%3ttp://www.test.com/why-hello");
2065 	NCF("http://www.test.com/why-hello%7");
2066 	NCF("http://www.test.com/why-hell%7o");
2067 	NCF("http://www.test.com/foo?ba%r");
2068 	NCF("http://www.test.com/foo#ba%r");
2069 	BAD("99:99/foo");
2070 	BAD("http://www.test.com:999x/");
2071 	BAD("http://www.test.com:x/");
2072 	BAD("http://[hello-there]/");
2073 	BAD("http://[::1]]/");
2074 	BAD("http://[::1/");
2075 	BAD("http://[foob/");
2076 	BAD("http://[/");
2077 	BAD("http://[ffff:ffff:ffff:ffff:Ffff:ffff:ffff:"
2078 	            "ffff:ffff:ffff:ffff:ffff:ffff:ffff]/");
2079 	BAD("http://[vX.foo]/");
2080 	BAD("http://[vX.foo]/");
2081 	BAD("http://[v.foo]/");
2082 	BAD("http://[v5.fo%o]/");
2083 	BAD("http://[v5X]/");
2084 	BAD("http://[v5]/");
2085 	BAD("http://[]/");
2086 	BAD("http://f\x01red@www.example.com/");
2087 	BAD("http://f%0red@www.example.com/");
2088 	BAD("http://www.example.com:9999999999999999999999999999999999999/");
2089 	BAD("http://www.example.com:hihi/");
2090 	BAD("://www.example.com/");
2091 
2092 	/* bad URIs: joining */
2093 	uri = evhttp_uri_new();
2094 	tt_want(0==evhttp_uri_set_host(uri, "www.example.com"));
2095 	tt_want(evhttp_uri_join(uri, url_tmp, sizeof(url_tmp)) != NULL);
2096 	/* not enough space: */
2097 	tt_want(evhttp_uri_join(uri, url_tmp, 3) == NULL);
2098 	/* host is set, but path doesn't start with "/": */
2099 	tt_want(0==evhttp_uri_set_path(uri, "hi_mom"));
2100 	tt_want(evhttp_uri_join(uri, url_tmp, sizeof(url_tmp)) == NULL);
2101 	tt_want(evhttp_uri_join(uri, NULL, sizeof(url_tmp))==NULL);
2102 	tt_want(evhttp_uri_join(uri, url_tmp, 0)==NULL);
2103 	evhttp_uri_free(uri);
2104 	uri = URI_PARSE("mailto:foo@bar");
2105 	tt_want(uri != NULL);
2106 	tt_want(evhttp_uri_get_host(uri) == NULL);
2107 	tt_want(evhttp_uri_get_userinfo(uri) == NULL);
2108 	tt_want(evhttp_uri_get_port(uri) == -1);
2109 	tt_want(!strcmp(evhttp_uri_get_scheme(uri), "mailto"));
2110 	tt_want(!strcmp(evhttp_uri_get_path(uri), "foo@bar"));
2111 	tt_want(evhttp_uri_get_query(uri) == NULL);
2112 	tt_want(evhttp_uri_get_fragment(uri) == NULL);
2113 	TT_URI("mailto:foo@bar");
2114 	evhttp_uri_free(uri);
2115 
2116 	uri = evhttp_uri_new();
2117 	/* Bad URI usage: setting invalid values */
2118 	tt_want(-1 == evhttp_uri_set_scheme(uri,""));
2119 	tt_want(-1 == evhttp_uri_set_scheme(uri,"33"));
2120 	tt_want(-1 == evhttp_uri_set_scheme(uri,"hi!"));
2121 	tt_want(-1 == evhttp_uri_set_userinfo(uri,"hello@"));
2122 	tt_want(-1 == evhttp_uri_set_host(uri,"[1.2.3.4]"));
2123 	tt_want(-1 == evhttp_uri_set_host(uri,"["));
2124 	tt_want(-1 == evhttp_uri_set_host(uri,"www.[foo].com"));
2125 	tt_want(-1 == evhttp_uri_set_port(uri,-3));
2126 	tt_want(-1 == evhttp_uri_set_path(uri,"hello?world"));
2127 	tt_want(-1 == evhttp_uri_set_query(uri,"hello#world"));
2128 	tt_want(-1 == evhttp_uri_set_fragment(uri,"hello#world"));
2129 	/* Valid URI usage: setting valid values */
2130 	tt_want(0 == evhttp_uri_set_scheme(uri,"http"));
2131 	tt_want(0 == evhttp_uri_set_scheme(uri,NULL));
2132 	tt_want(0 == evhttp_uri_set_userinfo(uri,"username:pass"));
2133 	tt_want(0 == evhttp_uri_set_userinfo(uri,NULL));
2134 	tt_want(0 == evhttp_uri_set_host(uri,"www.example.com"));
2135 	tt_want(0 == evhttp_uri_set_host(uri,"1.2.3.4"));
2136 	tt_want(0 == evhttp_uri_set_host(uri,"[1:2:3:4::]"));
2137 	tt_want(0 == evhttp_uri_set_host(uri,"[v7.wobblewobble]"));
2138 	tt_want(0 == evhttp_uri_set_host(uri,NULL));
2139 	tt_want(0 == evhttp_uri_set_host(uri,""));
2140 	tt_want(0 == evhttp_uri_set_port(uri, -1));
2141 	tt_want(0 == evhttp_uri_set_port(uri, 80));
2142 	tt_want(0 == evhttp_uri_set_port(uri, 65535));
2143 	tt_want(0 == evhttp_uri_set_path(uri, ""));
2144 	tt_want(0 == evhttp_uri_set_path(uri, "/documents/public/index.html"));
2145 	tt_want(0 == evhttp_uri_set_path(uri, NULL));
2146 	tt_want(0 == evhttp_uri_set_query(uri, "key=val&key2=val2"));
2147 	tt_want(0 == evhttp_uri_set_query(uri, "keyvalblarg"));
2148 	tt_want(0 == evhttp_uri_set_query(uri, ""));
2149 	tt_want(0 == evhttp_uri_set_query(uri, NULL));
2150 	tt_want(0 == evhttp_uri_set_fragment(uri, ""));
2151 	tt_want(0 == evhttp_uri_set_fragment(uri, "here?i?am"));
2152 	tt_want(0 == evhttp_uri_set_fragment(uri, NULL));
2153 	evhttp_uri_free(uri);
2154 
2155 	/* Valid parsing */
2156 	uri = URI_PARSE("http://www.test.com/?q=t%33est");
2157 	tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
2158 	tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0);
2159 	tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
2160 	tt_want(strcmp(evhttp_uri_get_query(uri), "q=t%33est") == 0);
2161 	tt_want(evhttp_uri_get_userinfo(uri) == NULL);
2162 	tt_want(evhttp_uri_get_port(uri) == -1);
2163 	tt_want(evhttp_uri_get_fragment(uri) == NULL);
2164 	TT_URI("http://www.test.com/?q=t%33est");
2165 	evhttp_uri_free(uri);
2166 
2167 	uri = URI_PARSE("http://%77ww.test.com");
2168 	tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
2169 	tt_want(strcmp(evhttp_uri_get_host(uri), "%77ww.test.com") == 0);
2170 	tt_want(strcmp(evhttp_uri_get_path(uri), "") == 0);
2171 	tt_want(evhttp_uri_get_query(uri) == NULL);
2172 	tt_want(evhttp_uri_get_userinfo(uri) == NULL);
2173 	tt_want(evhttp_uri_get_port(uri) == -1);
2174 	tt_want(evhttp_uri_get_fragment(uri) == NULL);
2175 	TT_URI("http://%77ww.test.com");
2176 	evhttp_uri_free(uri);
2177 
2178 	uri = URI_PARSE("http://www.test.com?q=test");
2179 	tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
2180 	tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0);
2181 	tt_want(strcmp(evhttp_uri_get_path(uri), "") == 0);
2182 	tt_want(strcmp(evhttp_uri_get_query(uri), "q=test") == 0);
2183 	tt_want(evhttp_uri_get_userinfo(uri) == NULL);
2184 	tt_want(evhttp_uri_get_port(uri) == -1);
2185 	tt_want(evhttp_uri_get_fragment(uri) == NULL);
2186 	TT_URI("http://www.test.com?q=test");
2187 	evhttp_uri_free(uri);
2188 
2189 	uri = URI_PARSE("http://www.test.com#fragment");
2190 	tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
2191 	tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0);
2192 	tt_want(strcmp(evhttp_uri_get_path(uri), "") == 0);
2193 	tt_want(evhttp_uri_get_query(uri) == NULL);
2194 	tt_want(evhttp_uri_get_userinfo(uri) == NULL);
2195 	tt_want(evhttp_uri_get_port(uri) == -1);
2196 	tt_want_str_op(evhttp_uri_get_fragment(uri), ==, "fragment");
2197 	TT_URI("http://www.test.com#fragment");
2198 	evhttp_uri_free(uri);
2199 
2200 	uri = URI_PARSE("http://8000/");
2201 	tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
2202 	tt_want(strcmp(evhttp_uri_get_host(uri), "8000") == 0);
2203 	tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
2204 	tt_want(evhttp_uri_get_query(uri) == NULL);
2205 	tt_want(evhttp_uri_get_userinfo(uri) == NULL);
2206 	tt_want(evhttp_uri_get_port(uri) == -1);
2207 	tt_want(evhttp_uri_get_fragment(uri) == NULL);
2208 	TT_URI("http://8000/");
2209 	evhttp_uri_free(uri);
2210 
2211 	uri = URI_PARSE("http://:8000/");
2212 	tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
2213 	tt_want(strcmp(evhttp_uri_get_host(uri), "") == 0);
2214 	tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
2215 	tt_want(evhttp_uri_get_query(uri) == NULL);
2216 	tt_want(evhttp_uri_get_userinfo(uri) == NULL);
2217 	tt_want(evhttp_uri_get_port(uri) == 8000);
2218 	tt_want(evhttp_uri_get_fragment(uri) == NULL);
2219 	TT_URI("http://:8000/");
2220 	evhttp_uri_free(uri);
2221 
2222 	uri = URI_PARSE("http://www.test.com:/"); /* empty port */
2223 	tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
2224 	tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0);
2225 	tt_want_str_op(evhttp_uri_get_path(uri), ==, "/");
2226 	tt_want(evhttp_uri_get_query(uri) == NULL);
2227 	tt_want(evhttp_uri_get_userinfo(uri) == NULL);
2228 	tt_want(evhttp_uri_get_port(uri) == -1);
2229 	tt_want(evhttp_uri_get_fragment(uri) == NULL);
2230 	TT_URI("http://www.test.com/");
2231 	evhttp_uri_free(uri);
2232 
2233 	uri = URI_PARSE("http://www.test.com:"); /* empty port 2 */
2234 	tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
2235 	tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0);
2236 	tt_want(strcmp(evhttp_uri_get_path(uri), "") == 0);
2237 	tt_want(evhttp_uri_get_query(uri) == NULL);
2238 	tt_want(evhttp_uri_get_userinfo(uri) == NULL);
2239 	tt_want(evhttp_uri_get_port(uri) == -1);
2240 	tt_want(evhttp_uri_get_fragment(uri) == NULL);
2241 	TT_URI("http://www.test.com");
2242 	evhttp_uri_free(uri);
2243 
2244 	uri = URI_PARSE("ftp://www.test.com/?q=test");
2245 	tt_want(strcmp(evhttp_uri_get_scheme(uri), "ftp") == 0);
2246 	tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0);
2247 	tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
2248 	tt_want(strcmp(evhttp_uri_get_query(uri), "q=test") == 0);
2249 	tt_want(evhttp_uri_get_userinfo(uri) == NULL);
2250 	tt_want(evhttp_uri_get_port(uri) == -1);
2251 	tt_want(evhttp_uri_get_fragment(uri) == NULL);
2252 	TT_URI("ftp://www.test.com/?q=test");
2253 	evhttp_uri_free(uri);
2254 
2255 	uri = URI_PARSE("ftp://[::1]:999/?q=test");
2256 	tt_want(strcmp(evhttp_uri_get_scheme(uri), "ftp") == 0);
2257 	tt_want(strcmp(evhttp_uri_get_host(uri), "[::1]") == 0);
2258 	tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
2259 	tt_want(strcmp(evhttp_uri_get_query(uri), "q=test") == 0);
2260 	tt_want(evhttp_uri_get_userinfo(uri) == NULL);
2261 	tt_want(evhttp_uri_get_port(uri) == 999);
2262 	tt_want(evhttp_uri_get_fragment(uri) == NULL);
2263 	TT_URI("ftp://[::1]:999/?q=test");
2264 	evhttp_uri_free(uri);
2265 
2266 	uri = URI_PARSE("ftp://[ff00::127.0.0.1]/?q=test");
2267 	tt_want(strcmp(evhttp_uri_get_scheme(uri), "ftp") == 0);
2268 	tt_want(strcmp(evhttp_uri_get_host(uri), "[ff00::127.0.0.1]") == 0);
2269 	tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
2270 	tt_want(strcmp(evhttp_uri_get_query(uri), "q=test") == 0);
2271 	tt_want(evhttp_uri_get_userinfo(uri) == NULL);
2272 	tt_want(evhttp_uri_get_port(uri) == -1);
2273 	tt_want(evhttp_uri_get_fragment(uri) == NULL);
2274 	TT_URI("ftp://[ff00::127.0.0.1]/?q=test");
2275 	evhttp_uri_free(uri);
2276 
2277 	uri = URI_PARSE("ftp://[v99.not_(any:time)_soon]/?q=test");
2278 	tt_want(strcmp(evhttp_uri_get_scheme(uri), "ftp") == 0);
2279 	tt_want(strcmp(evhttp_uri_get_host(uri), "[v99.not_(any:time)_soon]") == 0);
2280 	tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
2281 	tt_want(strcmp(evhttp_uri_get_query(uri), "q=test") == 0);
2282 	tt_want(evhttp_uri_get_userinfo(uri) == NULL);
2283 	tt_want(evhttp_uri_get_port(uri) == -1);
2284 	tt_want(evhttp_uri_get_fragment(uri) == NULL);
2285 	TT_URI("ftp://[v99.not_(any:time)_soon]/?q=test");
2286 	evhttp_uri_free(uri);
2287 
2288 	uri = URI_PARSE("scheme://user:pass@foo.com:42/?q=test&s=some+thing#fragment");
2289 	tt_want(strcmp(evhttp_uri_get_scheme(uri), "scheme") == 0);
2290 	tt_want(strcmp(evhttp_uri_get_userinfo(uri), "user:pass") == 0);
2291 	tt_want(strcmp(evhttp_uri_get_host(uri), "foo.com") == 0);
2292 	tt_want(evhttp_uri_get_port(uri) == 42);
2293 	tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
2294 	tt_want(strcmp(evhttp_uri_get_query(uri), "q=test&s=some+thing") == 0);
2295 	tt_want(strcmp(evhttp_uri_get_fragment(uri), "fragment") == 0);
2296 	TT_URI("scheme://user:pass@foo.com:42/?q=test&s=some+thing#fragment");
2297 	evhttp_uri_free(uri);
2298 
2299 	uri = URI_PARSE("scheme://user@foo.com/#fragment");
2300 	tt_want(strcmp(evhttp_uri_get_scheme(uri), "scheme") == 0);
2301 	tt_want(strcmp(evhttp_uri_get_userinfo(uri), "user") == 0);
2302 	tt_want(strcmp(evhttp_uri_get_host(uri), "foo.com") == 0);
2303 	tt_want(evhttp_uri_get_port(uri) == -1);
2304 	tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
2305 	tt_want(evhttp_uri_get_query(uri) == NULL);
2306 	tt_want(strcmp(evhttp_uri_get_fragment(uri), "fragment") == 0);
2307 	TT_URI("scheme://user@foo.com/#fragment");
2308 	evhttp_uri_free(uri);
2309 
2310 	uri = URI_PARSE("scheme://%75ser@foo.com/#frag@ment");
2311 	tt_want(strcmp(evhttp_uri_get_scheme(uri), "scheme") == 0);
2312 	tt_want(strcmp(evhttp_uri_get_userinfo(uri), "%75ser") == 0);
2313 	tt_want(strcmp(evhttp_uri_get_host(uri), "foo.com") == 0);
2314 	tt_want(evhttp_uri_get_port(uri) == -1);
2315 	tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
2316 	tt_want(evhttp_uri_get_query(uri) == NULL);
2317 	tt_want(strcmp(evhttp_uri_get_fragment(uri), "frag@ment") == 0);
2318 	TT_URI("scheme://%75ser@foo.com/#frag@ment");
2319 	evhttp_uri_free(uri);
2320 
2321 	uri = URI_PARSE("file:///some/path/to/the/file");
2322 	tt_want(strcmp(evhttp_uri_get_scheme(uri), "file") == 0);
2323 	tt_want(evhttp_uri_get_userinfo(uri) == NULL);
2324 	tt_want(strcmp(evhttp_uri_get_host(uri), "") == 0);
2325 	tt_want(evhttp_uri_get_port(uri) == -1);
2326 	tt_want(strcmp(evhttp_uri_get_path(uri), "/some/path/to/the/file") == 0);
2327 	tt_want(evhttp_uri_get_query(uri) == NULL);
2328 	tt_want(evhttp_uri_get_fragment(uri) == NULL);
2329 	TT_URI("file:///some/path/to/the/file");
2330 	evhttp_uri_free(uri);
2331 
2332 	uri = URI_PARSE("///some/path/to/the-file");
2333 	tt_want(uri != NULL);
2334 	tt_want(evhttp_uri_get_scheme(uri) == NULL);
2335 	tt_want(evhttp_uri_get_userinfo(uri) == NULL);
2336 	tt_want(strcmp(evhttp_uri_get_host(uri), "") == 0);
2337 	tt_want(evhttp_uri_get_port(uri) == -1);
2338 	tt_want(strcmp(evhttp_uri_get_path(uri), "/some/path/to/the-file") == 0);
2339 	tt_want(evhttp_uri_get_query(uri) == NULL);
2340 	tt_want(evhttp_uri_get_fragment(uri) == NULL);
2341 	TT_URI("///some/path/to/the-file");
2342 	evhttp_uri_free(uri);
2343 
2344 	uri = URI_PARSE("/s:ome/path/to/the-file?q=99#fred");
2345 	tt_want(uri != NULL);
2346 	tt_want(evhttp_uri_get_scheme(uri) == NULL);
2347 	tt_want(evhttp_uri_get_userinfo(uri) == NULL);
2348 	tt_want(evhttp_uri_get_host(uri) == NULL);
2349 	tt_want(evhttp_uri_get_port(uri) == -1);
2350 	tt_want(strcmp(evhttp_uri_get_path(uri), "/s:ome/path/to/the-file") == 0);
2351 	tt_want(strcmp(evhttp_uri_get_query(uri), "q=99") == 0);
2352 	tt_want(strcmp(evhttp_uri_get_fragment(uri), "fred") == 0);
2353 	TT_URI("/s:ome/path/to/the-file?q=99#fred");
2354 	evhttp_uri_free(uri);
2355 
2356 	uri = URI_PARSE("relative/path/with/co:lon");
2357 	tt_want(uri != NULL);
2358 	tt_want(evhttp_uri_get_scheme(uri) == NULL);
2359 	tt_want(evhttp_uri_get_userinfo(uri) == NULL);
2360 	tt_want(evhttp_uri_get_host(uri) == NULL);
2361 	tt_want(evhttp_uri_get_port(uri) == -1);
2362 	tt_want(strcmp(evhttp_uri_get_path(uri), "relative/path/with/co:lon") == 0);
2363 	tt_want(evhttp_uri_get_query(uri) == NULL);
2364 	tt_want(evhttp_uri_get_fragment(uri) == NULL);
2365 	TT_URI("relative/path/with/co:lon");
2366 	evhttp_uri_free(uri);
2367 
2368 	uri = URI_PARSE("bob?q=99&q2=q?33#fr?ed");
2369 	tt_want(uri != NULL);
2370 	tt_want(evhttp_uri_get_scheme(uri) == NULL);
2371 	tt_want(evhttp_uri_get_userinfo(uri) == NULL);
2372 	tt_want(evhttp_uri_get_host(uri) == NULL);
2373 	tt_want(evhttp_uri_get_port(uri) == -1);
2374 	tt_want(strcmp(evhttp_uri_get_path(uri), "bob") == 0);
2375 	tt_want(strcmp(evhttp_uri_get_query(uri), "q=99&q2=q?33") == 0);
2376 	tt_want(strcmp(evhttp_uri_get_fragment(uri), "fr?ed") == 0);
2377 	TT_URI("bob?q=99&q2=q?33#fr?ed");
2378 	evhttp_uri_free(uri);
2379 
2380 	uri = URI_PARSE("#fr?ed");
2381 	tt_want(uri != NULL);
2382 	tt_want(evhttp_uri_get_scheme(uri) == NULL);
2383 	tt_want(evhttp_uri_get_userinfo(uri) == NULL);
2384 	tt_want(evhttp_uri_get_host(uri) == NULL);
2385 	tt_want(evhttp_uri_get_port(uri) == -1);
2386 	tt_want(strcmp(evhttp_uri_get_path(uri), "") == 0);
2387 	tt_want(evhttp_uri_get_query(uri) == NULL);
2388 	tt_want(strcmp(evhttp_uri_get_fragment(uri), "fr?ed") == 0);
2389 	TT_URI("#fr?ed");
2390 	evhttp_uri_free(uri);
2391 #undef URI_PARSE
2392 #undef TT_URI
2393 #undef BAD
2394 }
2395 
2396 static void
2397 http_uriencode_test(void *ptr)
2398 {
2399 	char *s=NULL, *s2=NULL;
2400 	size_t sz;
2401 	int bytes_decoded;
2402 
2403 #define ENC(from,want,plus) do {				\
2404 		s = evhttp_uriencode((from), -1, (plus));	\
2405 		tt_assert(s);					\
2406 		tt_str_op(s,==,(want));				\
2407 		sz = -1;					\
2408 		s2 = evhttp_uridecode((s), (plus), &sz);	\
2409 		tt_assert(s2);					\
2410 		tt_str_op(s2,==,(from));			\
2411 		tt_int_op(sz,==,strlen(from));			\
2412 		free(s);					\
2413 		free(s2);					\
2414 		s = s2 = NULL;					\
2415 	} while (0)
2416 
2417 #define DEC(from,want,dp) do {					\
2418 		s = evhttp_uridecode((from),(dp),&sz);		\
2419 		tt_assert(s);					\
2420 		tt_str_op(s,==,(want));				\
2421 		tt_int_op(sz,==,strlen(want));			\
2422 		free(s);					\
2423 		s = NULL;					\
2424 	} while (0)
2425 
2426 #define OLD_DEC(from,want)  do {				\
2427 		s = evhttp_decode_uri((from));			\
2428 		tt_assert(s);					\
2429 		tt_str_op(s,==,(want));				\
2430 		free(s);					\
2431 		s = NULL;					\
2432 	} while (0)
2433 
2434 
2435       	ENC("Hello", "Hello",0);
2436 	ENC("99", "99",0);
2437 	ENC("", "",0);
2438 	ENC(
2439 	 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789-.~_",
2440 	 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789-.~_",0);
2441 	ENC(" ", "%20",0);
2442 	ENC(" ", "+",1);
2443 	ENC("\xff\xf0\xe0", "%FF%F0%E0",0);
2444 	ENC("\x01\x19", "%01%19",1);
2445 	ENC("http://www.ietf.org/rfc/rfc3986.txt",
2446 	    "http%3A%2F%2Fwww.ietf.org%2Frfc%2Frfc3986.txt",1);
2447 
2448 	ENC("1+2=3", "1%2B2%3D3",1);
2449 	ENC("1+2=3", "1%2B2%3D3",0);
2450 
2451 	/* Now try encoding with internal NULs. */
2452 	s = evhttp_uriencode("hello\0world", 11, 0);
2453 	tt_assert(s);
2454 	tt_str_op(s,==,"hello%00world");
2455 	free(s);
2456 	s = NULL;
2457 
2458 	/* Now try decoding just part of string. */
2459 	s = malloc(6 + 1 /* NUL byte */);
2460 	bytes_decoded = evhttp_decode_uri_internal("hello%20%20", 6, s, 0);
2461 	tt_assert(s);
2462 	tt_int_op(bytes_decoded,==,6);
2463 	tt_str_op(s,==,"hello%");
2464 	free(s);
2465 	s = NULL;
2466 
2467 	/* Now try out some decoding cases that we don't generate with
2468 	 * encode_uri: Make sure that malformed stuff doesn't crash... */
2469 	DEC("%%xhello th+ere \xff",
2470 	    "%%xhello th+ere \xff", 0);
2471 	/* Make sure plus decoding works */
2472 	DEC("plus+should%20work+", "plus should work ",1);
2473 	/* Try some lowercase hex */
2474 	DEC("%f0%a0%b0", "\xf0\xa0\xb0",1);
2475 
2476 	/* Try an internal NUL. */
2477 	sz = 0;
2478 	s = evhttp_uridecode("%00%00x%00%00", 1, &sz);
2479 	tt_int_op(sz,==,5);
2480 	tt_assert(!memcmp(s, "\0\0x\0\0", 5));
2481 	free(s);
2482 	s = NULL;
2483 
2484 	/* Try with size == NULL */
2485 	sz = 0;
2486 	s = evhttp_uridecode("%00%00x%00%00", 1, NULL);
2487 	tt_assert(!memcmp(s, "\0\0x\0\0", 5));
2488 	free(s);
2489 	s = NULL;
2490 
2491 	/* Test out the crazy old behavior of the deprecated
2492 	 * evhttp_decode_uri */
2493 	OLD_DEC("http://example.com/normal+path/?key=val+with+spaces",
2494 	        "http://example.com/normal+path/?key=val with spaces");
2495 
2496 end:
2497 	if (s)
2498 		free(s);
2499 	if (s2)
2500 		free(s2);
2501 #undef ENC
2502 #undef DEC
2503 #undef OLD_DEC
2504 }
2505 
2506 static void
2507 http_base_test(void *ptr)
2508 {
2509 	struct event_base *base = NULL;
2510 	struct bufferevent *bev;
2511 	evutil_socket_t fd;
2512 	const char *http_request;
2513 	ev_uint16_t port = 0;
2514 
2515 	test_ok = 0;
2516 	base = event_base_new();
2517 	http = http_setup(&port, base, 0);
2518 
2519 	fd = http_connect("127.0.0.1", port);
2520 
2521 	/* Stupid thing to send a request */
2522 	bev = bufferevent_socket_new(base, fd, 0);
2523 	bufferevent_setcb(bev, http_readcb, http_writecb,
2524 	    http_errorcb, base);
2525 	bufferevent_base_set(base, bev);
2526 
2527 	http_request =
2528 	    "GET /test HTTP/1.1\r\n"
2529 	    "Host: somehost\r\n"
2530 	    "Connection: close\r\n"
2531 	    "\r\n";
2532 
2533 	bufferevent_write(bev, http_request, strlen(http_request));
2534 
2535 	event_base_dispatch(base);
2536 
2537 	bufferevent_free(bev);
2538 	evutil_closesocket(fd);
2539 
2540 	evhttp_free(http);
2541 
2542 	tt_int_op(test_ok, ==, 2);
2543 
2544 end:
2545 	if (base)
2546 		event_base_free(base);
2547 }
2548 
2549 /*
2550  * the server is just going to close the connection if it times out during
2551  * reading the headers.
2552  */
2553 
2554 static void
2555 http_incomplete_readcb(struct bufferevent *bev, void *arg)
2556 {
2557 	test_ok = -1;
2558 	event_base_loopexit(exit_base,NULL);
2559 }
2560 
2561 static void
2562 http_incomplete_errorcb(struct bufferevent *bev, short what, void *arg)
2563 {
2564 	if (what == (BEV_EVENT_READING|BEV_EVENT_EOF))
2565 		test_ok++;
2566 	else
2567 		test_ok = -2;
2568 	event_base_loopexit(exit_base,NULL);
2569 }
2570 
2571 static void
2572 http_incomplete_writecb(struct bufferevent *bev, void *arg)
2573 {
2574 	if (arg != NULL) {
2575 		evutil_socket_t fd = *(evutil_socket_t *)arg;
2576 		/* terminate the write side to simulate EOF */
2577 		shutdown(fd, SHUT_WR);
2578 	}
2579 	if (evbuffer_get_length(bufferevent_get_output(bev)) == 0) {
2580 		/* enable reading of the reply */
2581 		bufferevent_enable(bev, EV_READ);
2582 		test_ok++;
2583 	}
2584 }
2585 
2586 static void
2587 http_incomplete_test_(struct basic_test_data *data, int use_timeout)
2588 {
2589 	struct bufferevent *bev;
2590 	evutil_socket_t fd;
2591 	const char *http_request;
2592 	ev_uint16_t port = 0;
2593 	struct timeval tv_start, tv_end;
2594 
2595 	exit_base = data->base;
2596 
2597 	test_ok = 0;
2598 
2599 	http = http_setup(&port, data->base, 0);
2600 	evhttp_set_timeout(http, 1);
2601 
2602 	fd = http_connect("127.0.0.1", port);
2603 
2604 	/* Stupid thing to send a request */
2605 	bev = bufferevent_socket_new(data->base, fd, 0);
2606 	bufferevent_setcb(bev,
2607 	    http_incomplete_readcb, http_incomplete_writecb,
2608 	    http_incomplete_errorcb, use_timeout ? NULL : &fd);
2609 
2610 	http_request =
2611 	    "GET /test HTTP/1.1\r\n"
2612 	    "Host: somehost\r\n";
2613 
2614 	bufferevent_write(bev, http_request, strlen(http_request));
2615 
2616 	evutil_gettimeofday(&tv_start, NULL);
2617 
2618 	event_base_dispatch(data->base);
2619 
2620 	evutil_gettimeofday(&tv_end, NULL);
2621 	evutil_timersub(&tv_end, &tv_start, &tv_end);
2622 
2623 	bufferevent_free(bev);
2624 	if (use_timeout) {
2625 		evutil_closesocket(fd);
2626 	}
2627 
2628 	evhttp_free(http);
2629 
2630 	if (use_timeout && tv_end.tv_sec >= 3) {
2631 		tt_abort_msg("time");
2632 	} else if (!use_timeout && tv_end.tv_sec >= 1) {
2633 		/* we should be done immediately */
2634 		tt_abort_msg("time");
2635 	}
2636 
2637 	tt_int_op(test_ok, ==, 2);
2638  end:
2639 	;
2640 }
2641 static void
2642 http_incomplete_test(void *arg)
2643 {
2644 	http_incomplete_test_(arg, 0);
2645 }
2646 static void
2647 http_incomplete_timeout_test(void *arg)
2648 {
2649 	http_incomplete_test_(arg, 1);
2650 }
2651 
2652 /*
2653  * the server is going to reply with chunked data.
2654  */
2655 
2656 static void
2657 http_chunked_readcb(struct bufferevent *bev, void *arg)
2658 {
2659 	/* nothing here */
2660 }
2661 
2662 static void
2663 http_chunked_errorcb(struct bufferevent *bev, short what, void *arg)
2664 {
2665 	if (!test_ok)
2666 		goto out;
2667 
2668 	test_ok = -1;
2669 
2670 	if ((what & BEV_EVENT_EOF) != 0) {
2671 		struct evhttp_request *req = evhttp_request_new(NULL, NULL);
2672 		const char *header;
2673 		enum message_read_status done;
2674 
2675 		/* req->kind = EVHTTP_RESPONSE; */
2676 		done = evhttp_parse_firstline_(req, bufferevent_get_input(bev));
2677 		if (done != ALL_DATA_READ)
2678 			goto out;
2679 
2680 		done = evhttp_parse_headers_(req, bufferevent_get_input(bev));
2681 		if (done != ALL_DATA_READ)
2682 			goto out;
2683 
2684 		header = evhttp_find_header(evhttp_request_get_input_headers(req), "Transfer-Encoding");
2685 		if (header == NULL || strcmp(header, "chunked"))
2686 			goto out;
2687 
2688 		header = evhttp_find_header(evhttp_request_get_input_headers(req), "Connection");
2689 		if (header == NULL || strcmp(header, "close"))
2690 			goto out;
2691 
2692 		header = evbuffer_readln(bufferevent_get_input(bev), NULL, EVBUFFER_EOL_CRLF);
2693 		if (header == NULL)
2694 			goto out;
2695 		/* 13 chars */
2696 		if (strcmp(header, "d")) {
2697 			free((void*)header);
2698 			goto out;
2699 		}
2700 		free((void*)header);
2701 
2702 		if (strncmp((char *)evbuffer_pullup(bufferevent_get_input(bev), 13),
2703 			"This is funny", 13))
2704 			goto out;
2705 
2706 		evbuffer_drain(bufferevent_get_input(bev), 13 + 2);
2707 
2708 		header = evbuffer_readln(bufferevent_get_input(bev), NULL, EVBUFFER_EOL_CRLF);
2709 		if (header == NULL)
2710 			goto out;
2711 		/* 18 chars */
2712 		if (strcmp(header, "12"))
2713 			goto out;
2714 		free((char *)header);
2715 
2716 		if (strncmp((char *)evbuffer_pullup(bufferevent_get_input(bev), 18),
2717 			"but not hilarious.", 18))
2718 			goto out;
2719 
2720 		evbuffer_drain(bufferevent_get_input(bev), 18 + 2);
2721 
2722 		header = evbuffer_readln(bufferevent_get_input(bev), NULL, EVBUFFER_EOL_CRLF);
2723 		if (header == NULL)
2724 			goto out;
2725 		/* 8 chars */
2726 		if (strcmp(header, "8")) {
2727 			free((void*)header);
2728 			goto out;
2729 		}
2730 		free((char *)header);
2731 
2732 		if (strncmp((char *)evbuffer_pullup(bufferevent_get_input(bev), 8),
2733 			"bwv 1052.", 8))
2734 			goto out;
2735 
2736 		evbuffer_drain(bufferevent_get_input(bev), 8 + 2);
2737 
2738 		header = evbuffer_readln(bufferevent_get_input(bev), NULL, EVBUFFER_EOL_CRLF);
2739 		if (header == NULL)
2740 			goto out;
2741 		/* 0 chars */
2742 		if (strcmp(header, "0")) {
2743 			free((void*)header);
2744 			goto out;
2745 		}
2746 		free((void *)header);
2747 
2748 		test_ok = 2;
2749 
2750 		evhttp_request_free(req);
2751 	}
2752 
2753 out:
2754 	event_base_loopexit(arg, NULL);
2755 }
2756 
2757 static void
2758 http_chunked_writecb(struct bufferevent *bev, void *arg)
2759 {
2760 	if (evbuffer_get_length(bufferevent_get_output(bev)) == 0) {
2761 		/* enable reading of the reply */
2762 		bufferevent_enable(bev, EV_READ);
2763 		test_ok++;
2764 	}
2765 }
2766 
2767 static void
2768 http_chunked_request_done(struct evhttp_request *req, void *arg)
2769 {
2770 	if (evhttp_request_get_response_code(req) != HTTP_OK) {
2771 		fprintf(stderr, "FAILED\n");
2772 		exit(1);
2773 	}
2774 
2775 	if (evhttp_find_header(evhttp_request_get_input_headers(req),
2776 		"Transfer-Encoding") == NULL) {
2777 		fprintf(stderr, "FAILED\n");
2778 		exit(1);
2779 	}
2780 
2781 	if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != 13 + 18 + 8) {
2782 		fprintf(stderr, "FAILED\n");
2783 		exit(1);
2784 	}
2785 
2786 	if (strncmp((char *)evbuffer_pullup(evhttp_request_get_input_buffer(req), 13 + 18 + 8),
2787 		"This is funnybut not hilarious.bwv 1052",
2788 		13 + 18 + 8)) {
2789 		fprintf(stderr, "FAILED\n");
2790 		exit(1);
2791 	}
2792 
2793 	test_ok = 1;
2794 	event_base_loopexit(arg, NULL);
2795 }
2796 
2797 static void
2798 http_chunk_out_test(void *arg)
2799 {
2800 	struct basic_test_data *data = arg;
2801 	struct bufferevent *bev;
2802 	evutil_socket_t fd;
2803 	const char *http_request;
2804 	ev_uint16_t port = 0;
2805 	struct timeval tv_start, tv_end;
2806 	struct evhttp_connection *evcon = NULL;
2807 	struct evhttp_request *req = NULL;
2808 	int i;
2809 
2810 	exit_base = data->base;
2811 	test_ok = 0;
2812 
2813 	http = http_setup(&port, data->base, 0);
2814 
2815 	fd = http_connect("127.0.0.1", port);
2816 
2817 	/* Stupid thing to send a request */
2818 	bev = bufferevent_socket_new(data->base, fd, 0);
2819 	bufferevent_setcb(bev,
2820 	    http_chunked_readcb, http_chunked_writecb,
2821 	    http_chunked_errorcb, data->base);
2822 
2823 	http_request =
2824 	    "GET /chunked HTTP/1.1\r\n"
2825 	    "Host: somehost\r\n"
2826 	    "Connection: close\r\n"
2827 	    "\r\n";
2828 
2829 	bufferevent_write(bev, http_request, strlen(http_request));
2830 
2831 	evutil_gettimeofday(&tv_start, NULL);
2832 
2833 	event_base_dispatch(data->base);
2834 
2835 	bufferevent_free(bev);
2836 
2837 	evutil_gettimeofday(&tv_end, NULL);
2838 	evutil_timersub(&tv_end, &tv_start, &tv_end);
2839 
2840 	tt_int_op(tv_end.tv_sec, <, 1);
2841 
2842 	tt_int_op(test_ok, ==, 2);
2843 
2844 	/* now try again with the regular connection object */
2845 	evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
2846 	tt_assert(evcon);
2847 
2848 	/* make two requests to check the keepalive behavior */
2849 	for (i = 0; i < 2; i++) {
2850 		test_ok = 0;
2851 		req = evhttp_request_new(http_chunked_request_done,data->base);
2852 
2853 		/* Add the information that we care about */
2854 		evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
2855 
2856 		/* We give ownership of the request to the connection */
2857 		if (evhttp_make_request(evcon, req,
2858 			EVHTTP_REQ_GET, "/chunked") == -1) {
2859 			tt_abort_msg("Couldn't make request");
2860 		}
2861 
2862 		event_base_dispatch(data->base);
2863 
2864 		tt_assert(test_ok == 1);
2865 	}
2866 
2867  end:
2868 	if (evcon)
2869 		evhttp_connection_free(evcon);
2870 	if (http)
2871 		evhttp_free(http);
2872 }
2873 
2874 static void
2875 http_stream_out_test(void *arg)
2876 {
2877 	struct basic_test_data *data = arg;
2878 	ev_uint16_t port = 0;
2879 	struct evhttp_connection *evcon = NULL;
2880 	struct evhttp_request *req = NULL;
2881 
2882 	test_ok = 0;
2883 	exit_base = data->base;
2884 
2885 	http = http_setup(&port, data->base, 0);
2886 
2887 	evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
2888 	tt_assert(evcon);
2889 
2890 	/*
2891 	 * At this point, we want to schedule a request to the HTTP
2892 	 * server using our make request method.
2893 	 */
2894 
2895 	req = evhttp_request_new(http_request_done,
2896 	    (void *)"This is funnybut not hilarious.bwv 1052");
2897 
2898 	/* Add the information that we care about */
2899 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
2900 
2901 	/* We give ownership of the request to the connection */
2902 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/streamed")
2903 	    == -1) {
2904 		tt_abort_msg("Couldn't make request");
2905 	}
2906 
2907 	event_base_dispatch(data->base);
2908 
2909  end:
2910 	if (evcon)
2911 		evhttp_connection_free(evcon);
2912 	if (http)
2913 		evhttp_free(http);
2914 }
2915 
2916 static void
2917 http_stream_in_chunk(struct evhttp_request *req, void *arg)
2918 {
2919 	struct evbuffer *reply = arg;
2920 
2921 	if (evhttp_request_get_response_code(req) != HTTP_OK) {
2922 		fprintf(stderr, "FAILED\n");
2923 		exit(1);
2924 	}
2925 
2926 	evbuffer_add_buffer(reply, evhttp_request_get_input_buffer(req));
2927 }
2928 
2929 static void
2930 http_stream_in_done(struct evhttp_request *req, void *arg)
2931 {
2932 	if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != 0) {
2933 		fprintf(stderr, "FAILED\n");
2934 		exit(1);
2935 	}
2936 
2937 	event_base_loopexit(exit_base, NULL);
2938 }
2939 
2940 /**
2941  * Makes a request and reads the response in chunks.
2942  */
2943 static void
2944 http_stream_in_test_(struct basic_test_data *data, char const *url,
2945     size_t expected_len, char const *expected)
2946 {
2947 	struct evhttp_connection *evcon;
2948 	struct evbuffer *reply = evbuffer_new();
2949 	struct evhttp_request *req = NULL;
2950 	ev_uint16_t port = 0;
2951 
2952 	exit_base = data->base;
2953 	http = http_setup(&port, data->base, 0);
2954 
2955 	evcon = evhttp_connection_base_new(data->base, NULL,"127.0.0.1", port);
2956 	tt_assert(evcon);
2957 
2958 	req = evhttp_request_new(http_stream_in_done, reply);
2959 	evhttp_request_set_chunked_cb(req, http_stream_in_chunk);
2960 
2961 	/* We give ownership of the request to the connection */
2962 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, url) == -1) {
2963 		tt_abort_msg("Couldn't make request");
2964 	}
2965 
2966 	event_base_dispatch(data->base);
2967 
2968 	if (evbuffer_get_length(reply) != expected_len) {
2969 		TT_DIE(("reply length %lu; expected %lu; FAILED (%s)\n",
2970 				(unsigned long)evbuffer_get_length(reply),
2971 				(unsigned long)expected_len,
2972 				(char*)evbuffer_pullup(reply, -1)));
2973 	}
2974 
2975 	if (memcmp(evbuffer_pullup(reply, -1), expected, expected_len) != 0) {
2976 		tt_abort_msg("Memory mismatch");
2977 	}
2978 
2979 	test_ok = 1;
2980  end:
2981 	if (reply)
2982 		evbuffer_free(reply);
2983 	if (evcon)
2984 		evhttp_connection_free(evcon);
2985 	if (http)
2986 		evhttp_free(http);
2987 }
2988 
2989 static void
2990 http_stream_in_test(void *arg)
2991 {
2992 	http_stream_in_test_(arg, "/chunked", 13 + 18 + 8,
2993 	    "This is funnybut not hilarious.bwv 1052");
2994 
2995 	http_stream_in_test_(arg, "/test", strlen(BASIC_REQUEST_BODY),
2996 	    BASIC_REQUEST_BODY);
2997 }
2998 
2999 static void
3000 http_stream_in_cancel_chunk(struct evhttp_request *req, void *arg)
3001 {
3002 	tt_int_op(evhttp_request_get_response_code(req), ==, HTTP_OK);
3003 
3004  end:
3005 	evhttp_cancel_request(req);
3006 	event_base_loopexit(arg, NULL);
3007 }
3008 
3009 static void
3010 http_stream_in_cancel_done(struct evhttp_request *req, void *arg)
3011 {
3012 	/* should never be called */
3013 	tt_fail_msg("In cancel done");
3014 }
3015 
3016 static void
3017 http_stream_in_cancel_test(void *arg)
3018 {
3019 	struct basic_test_data *data = arg;
3020 	struct evhttp_connection *evcon;
3021 	struct evhttp_request *req = NULL;
3022 	ev_uint16_t port = 0;
3023 
3024 	http = http_setup(&port, data->base, 0);
3025 
3026 	evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
3027 	tt_assert(evcon);
3028 
3029 	req = evhttp_request_new(http_stream_in_cancel_done, data->base);
3030 	evhttp_request_set_chunked_cb(req, http_stream_in_cancel_chunk);
3031 
3032 	/* We give ownership of the request to the connection */
3033 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/chunked") == -1) {
3034 		tt_abort_msg("Couldn't make request");
3035 	}
3036 
3037 	event_base_dispatch(data->base);
3038 
3039 	test_ok = 1;
3040  end:
3041 	evhttp_connection_free(evcon);
3042 	evhttp_free(http);
3043 
3044 }
3045 
3046 static void
3047 http_connection_fail_done(struct evhttp_request *req, void *arg)
3048 {
3049        struct evhttp_connection *evcon = arg;
3050        struct event_base *base = evhttp_connection_get_base(evcon);
3051 
3052        /* An ENETUNREACH error results in an unrecoverable
3053         * evhttp_connection error (see evhttp_connection_fail_()).  The
3054         * connection will be reset, and the user will be notified with a NULL
3055         * req parameter. */
3056        tt_assert(!req);
3057 
3058        evhttp_connection_free(evcon);
3059 
3060        test_ok = 1;
3061 
3062  end:
3063        event_base_loopexit(base, NULL);
3064 }
3065 
3066 /* Test unrecoverable evhttp_connection errors by generating an ENETUNREACH
3067  * error on connection. */
3068 static void
3069 http_connection_fail_test(void *arg)
3070 {
3071        struct basic_test_data *data = arg;
3072        ev_uint16_t port = 0;
3073        struct evhttp_connection *evcon = NULL;
3074        struct evhttp_request *req = NULL;
3075 
3076        exit_base = data->base;
3077        test_ok = 0;
3078 
3079        /* auto detect a port */
3080        http = http_setup(&port, data->base, 0);
3081        evhttp_free(http);
3082        http = NULL;
3083 
3084        /* Pick an unroutable address.  This administratively scoped multicast
3085 	* address should do when working with TCP. */
3086        evcon = evhttp_connection_base_new(data->base, NULL, "239.10.20.30", 80);
3087        tt_assert(evcon);
3088 
3089        /*
3090         * At this point, we want to schedule an HTTP GET request
3091         * server using our make request method.
3092         */
3093 
3094        req = evhttp_request_new(http_connection_fail_done, evcon);
3095        tt_assert(req);
3096 
3097        if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/") == -1) {
3098                tt_abort_msg("Couldn't make request");
3099        }
3100 
3101        event_base_dispatch(data->base);
3102 
3103        tt_int_op(test_ok, ==, 1);
3104 
3105  end:
3106         ;
3107 }
3108 
3109 static void
3110 http_connection_retry_done(struct evhttp_request *req, void *arg)
3111 {
3112 	tt_assert(req);
3113 	tt_int_op(evhttp_request_get_response_code(req), !=, HTTP_OK);
3114 	if (evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Type") != NULL) {
3115 		tt_abort_msg("(content type)\n");
3116 	}
3117 
3118 	tt_uint_op(evbuffer_get_length(evhttp_request_get_input_buffer(req)), ==, 0);
3119 
3120 	test_ok = 1;
3121  end:
3122 	event_base_loopexit(arg,NULL);
3123 }
3124 
3125 static struct event_base *http_make_web_server_base=NULL;
3126 static void
3127 http_make_web_server(evutil_socket_t fd, short what, void *arg)
3128 {
3129 	ev_uint16_t port = *(ev_uint16_t*)arg;
3130 	http = http_setup(&port, http_make_web_server_base, 0);
3131 }
3132 
3133 static void
3134 http_connection_retry_test(void *arg)
3135 {
3136 	struct basic_test_data *data = arg;
3137 	ev_uint16_t port = 0;
3138 	struct evhttp_connection *evcon = NULL;
3139 	struct evhttp_request *req = NULL;
3140 	struct timeval tv, tv_start, tv_end;
3141 
3142 	exit_base = data->base;
3143 	test_ok = 0;
3144 
3145 	/* auto detect a port */
3146 	http = http_setup(&port, data->base, 0);
3147 	evhttp_free(http);
3148 	http = NULL;
3149 
3150 	evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
3151 	tt_assert(evcon);
3152 
3153 	evhttp_connection_set_timeout(evcon, 1);
3154 	/* also bind to local host */
3155 	evhttp_connection_set_local_address(evcon, "127.0.0.1");
3156 
3157 	/*
3158 	 * At this point, we want to schedule an HTTP GET request
3159 	 * server using our make request method.
3160 	 */
3161 
3162 	req = evhttp_request_new(http_connection_retry_done, data->base);
3163 	tt_assert(req);
3164 
3165 	/* Add the information that we care about */
3166 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
3167 
3168 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
3169 		"/?arg=val") == -1) {
3170 		tt_abort_msg("Couldn't make request");
3171 	}
3172 
3173 	evutil_gettimeofday(&tv_start, NULL);
3174 	event_base_dispatch(data->base);
3175 	evutil_gettimeofday(&tv_end, NULL);
3176 	evutil_timersub(&tv_end, &tv_start, &tv_end);
3177 	tt_int_op(tv_end.tv_sec, <, 1);
3178 
3179 	tt_int_op(test_ok, ==, 1);
3180 
3181 	/*
3182 	 * now test the same but with retries
3183 	 */
3184 	test_ok = 0;
3185 
3186 	{
3187 		const struct timeval tv_timeout = { 0, 500000 };
3188 		const struct timeval tv_retry = { 0, 500000 };
3189 		evhttp_connection_set_timeout_tv(evcon, &tv_timeout);
3190 		evhttp_connection_set_initial_retry_tv(evcon, &tv_retry);
3191 	}
3192 	evhttp_connection_set_retries(evcon, 1);
3193 
3194 	req = evhttp_request_new(http_connection_retry_done, data->base);
3195 	tt_assert(req);
3196 
3197 	/* Add the information that we care about */
3198 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
3199 
3200 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
3201 		"/?arg=val") == -1) {
3202 		tt_abort_msg("Couldn't make request");
3203 	}
3204 
3205 	evutil_gettimeofday(&tv_start, NULL);
3206 	event_base_dispatch(data->base);
3207 	evutil_gettimeofday(&tv_end, NULL);
3208 
3209 	/* fails fast, .5 sec to wait to retry, fails fast again. */
3210 	test_timeval_diff_leq(&tv_start, &tv_end, 500, 200);
3211 
3212 	tt_assert(test_ok == 1);
3213 
3214 	/*
3215 	 * now test the same but with retries and give it a web server
3216 	 * at the end
3217 	 */
3218 	test_ok = 0;
3219 
3220 	evhttp_connection_set_timeout(evcon, 1);
3221 	evhttp_connection_set_retries(evcon, 3);
3222 
3223 	req = evhttp_request_new(http_dispatcher_test_done, data->base);
3224 	tt_assert(req);
3225 
3226 	/* Add the information that we care about */
3227 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
3228 
3229 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
3230 		"/?arg=val") == -1) {
3231 		tt_abort_msg("Couldn't make request");
3232 	}
3233 
3234 	/* start up a web server .2 seconds after the connection tried
3235 	 * to send a request
3236 	 */
3237 	evutil_timerclear(&tv);
3238 	tv.tv_usec = 200000;
3239 	http_make_web_server_base = data->base;
3240 	event_base_once(data->base, -1, EV_TIMEOUT, http_make_web_server, &port, &tv);
3241 
3242 	evutil_gettimeofday(&tv_start, NULL);
3243 	event_base_dispatch(data->base);
3244 	evutil_gettimeofday(&tv_end, NULL);
3245 	/* We'll wait twice as long as we did last time. */
3246 	test_timeval_diff_leq(&tv_start, &tv_end, 1000, 400);
3247 
3248 	tt_int_op(test_ok, ==, 1);
3249 
3250  end:
3251 	if (evcon)
3252 		evhttp_connection_free(evcon);
3253 	if (http)
3254 		evhttp_free(http);
3255 }
3256 
3257 static void
3258 http_primitives(void *ptr)
3259 {
3260 	char *escaped = NULL;
3261 	struct evhttp *http = NULL;
3262 
3263 	escaped = evhttp_htmlescape("<script>");
3264 	tt_assert(escaped);
3265 	tt_str_op(escaped, ==, "&lt;script&gt;");
3266 	free(escaped);
3267 
3268 	escaped = evhttp_htmlescape("\"\'&");
3269 	tt_assert(escaped);
3270 	tt_str_op(escaped, ==, "&quot;&#039;&amp;");
3271 
3272 	http = evhttp_new(NULL);
3273 	tt_assert(http);
3274 	tt_int_op(evhttp_set_cb(http, "/test", http_basic_cb, NULL), ==, 0);
3275 	tt_int_op(evhttp_set_cb(http, "/test", http_basic_cb, NULL), ==, -1);
3276 	tt_int_op(evhttp_del_cb(http, "/test"), ==, 0);
3277 	tt_int_op(evhttp_del_cb(http, "/test"), ==, -1);
3278 	tt_int_op(evhttp_set_cb(http, "/test", http_basic_cb, NULL), ==, 0);
3279 
3280  end:
3281 	if (escaped)
3282 		free(escaped);
3283 	if (http)
3284 		evhttp_free(http);
3285 }
3286 
3287 static void
3288 http_multi_line_header_test(void *arg)
3289 {
3290 	struct basic_test_data *data = arg;
3291 	struct bufferevent *bev= NULL;
3292 	evutil_socket_t fd = -1;
3293 	const char *http_start_request;
3294 	ev_uint16_t port = 0;
3295 
3296 	test_ok = 0;
3297 
3298 	http = http_setup(&port, data->base, 0);
3299 
3300 	fd = http_connect("127.0.0.1", port);
3301 
3302 	/* Stupid thing to send a request */
3303 	bev = bufferevent_socket_new(data->base, fd, 0);
3304 	bufferevent_setcb(bev, http_readcb, http_writecb,
3305 	    http_errorcb, data->base);
3306 
3307 	http_start_request =
3308 	    "GET /test HTTP/1.1\r\n"
3309 	    "Host: somehost\r\n"
3310 	    "Connection: close\r\n"
3311 	    "X-Multi-Extra-WS:  libevent  \r\n"
3312 	    "\t\t\t2.1 \r\n"
3313 	    "X-Multi:  aaaaaaaa\r\n"
3314 	    " a\r\n"
3315 	    "\tEND\r\n"
3316 	    "X-Last: last\r\n"
3317 	    "\r\n";
3318 
3319 	bufferevent_write(bev, http_start_request, strlen(http_start_request));
3320 	found_multi = found_multi2 = 0;
3321 
3322 	event_base_dispatch(data->base);
3323 
3324 	tt_int_op(found_multi, ==, 1);
3325 	tt_int_op(found_multi2, ==, 1);
3326 	tt_int_op(test_ok, ==, 4);
3327  end:
3328 	if (bev)
3329 		bufferevent_free(bev);
3330 	if (fd >= 0)
3331 		evutil_closesocket(fd);
3332 	if (http)
3333 		evhttp_free(http);
3334 }
3335 
3336 static void
3337 http_request_bad(struct evhttp_request *req, void *arg)
3338 {
3339 	if (req != NULL) {
3340 		fprintf(stderr, "FAILED\n");
3341 		exit(1);
3342 	}
3343 
3344 	test_ok = 1;
3345 	event_base_loopexit(arg, NULL);
3346 }
3347 
3348 static void
3349 http_negative_content_length_test(void *arg)
3350 {
3351 	struct basic_test_data *data = arg;
3352 	ev_uint16_t port = 0;
3353 	struct evhttp_connection *evcon = NULL;
3354 	struct evhttp_request *req = NULL;
3355 
3356 	test_ok = 0;
3357 
3358 	http = http_setup(&port, data->base, 0);
3359 
3360 	evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
3361 	tt_assert(evcon);
3362 
3363 	/*
3364 	 * At this point, we want to schedule a request to the HTTP
3365 	 * server using our make request method.
3366 	 */
3367 
3368 	req = evhttp_request_new(http_request_bad, data->base);
3369 
3370 	/* Cause the response to have a negative content-length */
3371 	evhttp_add_header(evhttp_request_get_output_headers(req), "X-Negative", "makeitso");
3372 
3373 	/* We give ownership of the request to the connection */
3374 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
3375 		tt_abort_msg("Couldn't make request");
3376 	}
3377 
3378 	event_base_dispatch(data->base);
3379 
3380  end:
3381 	if (evcon)
3382 		evhttp_connection_free(evcon);
3383 	if (http)
3384 		evhttp_free(http);
3385 }
3386 
3387 
3388 static void
3389 http_data_length_constraints_test_done(struct evhttp_request *req, void *arg)
3390 {
3391 	tt_assert(req);
3392 	tt_int_op(evhttp_request_get_response_code(req), ==, HTTP_BADREQUEST);
3393 end:
3394 	event_base_loopexit(arg, NULL);
3395 }
3396 
3397 static void
3398 http_large_entity_test_done(struct evhttp_request *req, void *arg)
3399 {
3400 	tt_assert(req);
3401 	tt_int_op(evhttp_request_get_response_code(req), ==, HTTP_ENTITYTOOLARGE);
3402 end:
3403 	event_base_loopexit(arg, NULL);
3404 }
3405 
3406 static void
3407 http_data_length_constraints_test(void *arg)
3408 {
3409 	struct basic_test_data *data = arg;
3410 	ev_uint16_t port = 0;
3411 	struct evhttp_connection *evcon = NULL;
3412 	struct evhttp_request *req = NULL;
3413 	char long_str[8192];
3414 
3415 	test_ok = 0;
3416 
3417 	http = http_setup(&port, data->base, 0);
3418 
3419 	evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
3420 	tt_assert(evcon);
3421 
3422 	/* also bind to local host */
3423 	evhttp_connection_set_local_address(evcon, "127.0.0.1");
3424 
3425 	/*
3426 	 * At this point, we want to schedule an HTTP GET request
3427 	 * server using our make request method.
3428 	 */
3429 
3430 	req = evhttp_request_new(http_data_length_constraints_test_done, data->base);
3431 	tt_assert(req);
3432 
3433 	memset(long_str, 'a', 8192);
3434 	long_str[8191] = '\0';
3435 	/* Add the information that we care about */
3436 	evhttp_set_max_headers_size(http, 8191);
3437 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
3438 	evhttp_add_header(evhttp_request_get_output_headers(req), "Longheader", long_str);
3439 
3440 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/?arg=val") == -1) {
3441 		tt_abort_msg("Couldn't make request");
3442 	}
3443 	event_base_dispatch(data->base);
3444 
3445 	req = evhttp_request_new(http_data_length_constraints_test_done, data->base);
3446 	tt_assert(req);
3447 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
3448 
3449 	/* GET /?arg=verylongvalue HTTP/1.1 */
3450 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, long_str) == -1) {
3451 		tt_abort_msg("Couldn't make request");
3452 	}
3453 	event_base_dispatch(data->base);
3454 
3455 	evhttp_set_max_body_size(http, 8190);
3456 	req = evhttp_request_new(http_data_length_constraints_test_done, data->base);
3457 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
3458 	evbuffer_add_printf(evhttp_request_get_output_buffer(req), "%s", long_str);
3459 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/") == -1) {
3460 		tt_abort_msg("Couldn't make request");
3461 	}
3462 	event_base_dispatch(data->base);
3463 
3464 	req = evhttp_request_new(http_large_entity_test_done, data->base);
3465 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
3466 	evhttp_add_header(evhttp_request_get_output_headers(req), "Expect", "100-continue");
3467 	evbuffer_add_printf(evhttp_request_get_output_buffer(req), "%s", long_str);
3468 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/") == -1) {
3469 		tt_abort_msg("Couldn't make request");
3470 	}
3471 	event_base_dispatch(data->base);
3472 
3473 	test_ok = 1;
3474  end:
3475 	if (evcon)
3476 		evhttp_connection_free(evcon);
3477 	if (http)
3478 		evhttp_free(http);
3479 }
3480 
3481 /*
3482  * Testing client reset of server chunked connections
3483  */
3484 
3485 struct terminate_state {
3486 	struct event_base *base;
3487 	struct evhttp_request *req;
3488 	struct bufferevent *bev;
3489 	evutil_socket_t fd;
3490 	int gotclosecb: 1;
3491 };
3492 
3493 static void
3494 terminate_chunked_trickle_cb(evutil_socket_t fd, short events, void *arg)
3495 {
3496 	struct terminate_state *state = arg;
3497 	struct evbuffer *evb;
3498 	struct timeval tv;
3499 
3500 	if (evhttp_request_get_connection(state->req) == NULL) {
3501 		test_ok = 1;
3502 		evhttp_request_free(state->req);
3503 		event_base_loopexit(state->base,NULL);
3504 		return;
3505 	}
3506 
3507 	evb = evbuffer_new();
3508 	evbuffer_add_printf(evb, "%p", evb);
3509 	evhttp_send_reply_chunk(state->req, evb);
3510 	evbuffer_free(evb);
3511 
3512 	tv.tv_sec = 0;
3513 	tv.tv_usec = 3000;
3514 	EVUTIL_ASSERT(state);
3515 	EVUTIL_ASSERT(state->base);
3516 	event_base_once(state->base, -1, EV_TIMEOUT, terminate_chunked_trickle_cb, arg, &tv);
3517 }
3518 
3519 static void
3520 terminate_chunked_close_cb(struct evhttp_connection *evcon, void *arg)
3521 {
3522 	struct terminate_state *state = arg;
3523 	state->gotclosecb = 1;
3524 }
3525 
3526 static void
3527 terminate_chunked_cb(struct evhttp_request *req, void *arg)
3528 {
3529 	struct terminate_state *state = arg;
3530 	struct timeval tv;
3531 
3532 	/* we want to know if this connection closes on us */
3533 	evhttp_connection_set_closecb(
3534 		evhttp_request_get_connection(req),
3535 		terminate_chunked_close_cb, arg);
3536 
3537 	state->req = req;
3538 
3539 	evhttp_send_reply_start(req, HTTP_OK, "OK");
3540 
3541 	tv.tv_sec = 0;
3542 	tv.tv_usec = 3000;
3543 	event_base_once(state->base, -1, EV_TIMEOUT, terminate_chunked_trickle_cb, arg, &tv);
3544 }
3545 
3546 static void
3547 terminate_chunked_client(evutil_socket_t fd, short event, void *arg)
3548 {
3549 	struct terminate_state *state = arg;
3550 	bufferevent_free(state->bev);
3551 	evutil_closesocket(state->fd);
3552 }
3553 
3554 static void
3555 terminate_readcb(struct bufferevent *bev, void *arg)
3556 {
3557 	/* just drop the data */
3558 	evbuffer_drain(bufferevent_get_input(bev), -1);
3559 }
3560 
3561 
3562 static void
3563 http_terminate_chunked_test(void *arg)
3564 {
3565 	struct basic_test_data *data = arg;
3566 	struct bufferevent *bev = NULL;
3567 	struct timeval tv;
3568 	const char *http_request;
3569 	ev_uint16_t port = 0;
3570 	evutil_socket_t fd = -1;
3571 	struct terminate_state terminate_state;
3572 
3573 	test_ok = 0;
3574 
3575 	http = http_setup(&port, data->base, 0);
3576 	evhttp_del_cb(http, "/test");
3577 	tt_assert(evhttp_set_cb(http, "/test",
3578 		terminate_chunked_cb, &terminate_state) == 0);
3579 
3580 	fd = http_connect("127.0.0.1", port);
3581 
3582 	/* Stupid thing to send a request */
3583 	bev = bufferevent_socket_new(data->base, fd, 0);
3584 	bufferevent_setcb(bev, terminate_readcb, http_writecb,
3585 	    http_errorcb, data->base);
3586 
3587 	memset(&terminate_state, 0, sizeof(terminate_state));
3588 	terminate_state.base = data->base;
3589 	terminate_state.fd = fd;
3590 	terminate_state.bev = bev;
3591 	terminate_state.gotclosecb = 0;
3592 
3593 	/* first half of the http request */
3594 	http_request =
3595 	    "GET /test HTTP/1.1\r\n"
3596 	    "Host: some\r\n\r\n";
3597 
3598 	bufferevent_write(bev, http_request, strlen(http_request));
3599 	evutil_timerclear(&tv);
3600 	tv.tv_usec = 10000;
3601 	event_base_once(data->base, -1, EV_TIMEOUT, terminate_chunked_client, &terminate_state,
3602 	    &tv);
3603 
3604 	event_base_dispatch(data->base);
3605 
3606 	if (terminate_state.gotclosecb == 0)
3607 		test_ok = 0;
3608 
3609  end:
3610 	if (fd >= 0)
3611 		evutil_closesocket(fd);
3612 	if (http)
3613 		evhttp_free(http);
3614 }
3615 
3616 static struct regress_dns_server_table ipv6_search_table[] = {
3617 	{ "localhost", "AAAA", "::1", 0 },
3618 	{ NULL, NULL, NULL, 0 }
3619 };
3620 
3621 static void
3622 http_ipv6_for_domain_test(void *arg)
3623 {
3624 	struct basic_test_data *data = arg;
3625 	struct evdns_base *dns_base = NULL;
3626 	ev_uint16_t portnum = 0;
3627 	char address[64];
3628 
3629 	tt_assert(regress_dnsserver(data->base, &portnum, ipv6_search_table));
3630 
3631 	dns_base = evdns_base_new(data->base, 0/* init name servers */);
3632 	tt_assert(dns_base);
3633 
3634 	/* Add ourself as the only nameserver, and make sure we really are
3635 	 * the only nameserver. */
3636 	evutil_snprintf(address, sizeof(address), "127.0.0.1:%d", portnum);
3637 	evdns_base_nameserver_ip_add(dns_base, address);
3638 
3639 	http_connection_test_(arg, 0 /* not persistent */, "localhost", dns_base, 1 /* ipv6 */);
3640 
3641  end:
3642 	if (dns_base)
3643 		evdns_base_free(dns_base, 0);
3644 	regress_clean_dnsserver();
3645 }
3646 
3647 #define HTTP_LEGACY(name)						\
3648 	{ #name, run_legacy_test_fn, TT_ISOLATED|TT_LEGACY, &legacy_setup, \
3649 		    http_##name##_test }
3650 
3651 #define HTTP(name) \
3652 	{ #name, http_##name##_test, TT_ISOLATED, &basic_setup, NULL }
3653 
3654 struct testcase_t http_testcases[] = {
3655 	{ "primitives", http_primitives, 0, NULL, NULL },
3656 	{ "base", http_base_test, TT_FORK, NULL, NULL },
3657 	{ "bad_headers", http_bad_header_test, 0, NULL, NULL },
3658 	{ "parse_query", http_parse_query_test, 0, NULL, NULL },
3659 	{ "parse_uri", http_parse_uri_test, 0, NULL, NULL },
3660 	{ "parse_uri_nc", http_parse_uri_test, 0, &basic_setup, (void*)"nc" },
3661 	{ "uriencode", http_uriencode_test, 0, NULL, NULL },
3662 	HTTP(basic),
3663 	HTTP(cancel),
3664 	HTTP(virtual_host),
3665 	HTTP(post),
3666 	HTTP(put),
3667 	HTTP(delete),
3668 	HTTP(allowed_methods),
3669 	HTTP(failure),
3670 	HTTP(connection),
3671 	HTTP(persist_connection),
3672 	HTTP(connection_async),
3673 	HTTP(close_detection),
3674 	HTTP(close_detection_delay),
3675 	HTTP(bad_request),
3676 	HTTP(incomplete),
3677 	HTTP(incomplete_timeout),
3678 	HTTP(terminate_chunked),
3679 
3680 	HTTP(highport),
3681 	HTTP(dispatcher),
3682 	HTTP(multi_line_header),
3683 	HTTP(negative_content_length),
3684 	HTTP(chunk_out),
3685 	HTTP(stream_out),
3686 
3687 	HTTP(stream_in),
3688 	HTTP(stream_in_cancel),
3689 
3690 	HTTP(connection_fail),
3691 	HTTP(connection_retry),
3692 	HTTP(data_length_constraints),
3693 
3694 	HTTP(ipv6_for_domain),
3695 
3696 	END_OF_TESTCASES
3697 };
3698 
3699