mirror of https://github.com/lukechilds/node.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
746 lines
22 KiB
746 lines
22 KiB
/* unit tests for request parser
|
|
* Copyright 2008 ryah dahl, ry@ndahl.us
|
|
*
|
|
* This software may be distributed under the "MIT" license included in the
|
|
* README
|
|
*/
|
|
#include "ebb_request_parser.h"
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#define TRUE 1
|
|
#define FALSE 0
|
|
|
|
#define MAX_HEADERS 500
|
|
#define MAX_ELEMENT_SIZE 500
|
|
|
|
static ebb_request_parser parser;
|
|
struct request_data {
|
|
const char *raw;
|
|
int request_method;
|
|
char request_path[MAX_ELEMENT_SIZE];
|
|
char request_uri[MAX_ELEMENT_SIZE];
|
|
char fragment[MAX_ELEMENT_SIZE];
|
|
char query_string[MAX_ELEMENT_SIZE];
|
|
char body[MAX_ELEMENT_SIZE];
|
|
int num_headers;
|
|
char header_fields[MAX_HEADERS][MAX_ELEMENT_SIZE];
|
|
char header_values[MAX_HEADERS][MAX_ELEMENT_SIZE];
|
|
int should_keep_alive;
|
|
ebb_request request;
|
|
};
|
|
static struct request_data requests[5];
|
|
static int num_requests;
|
|
|
|
const struct request_data curl_get =
|
|
{ raw: "GET /test HTTP/1.1\r\n"
|
|
"User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1\r\n"
|
|
"Host: 0.0.0.0:5000\r\n"
|
|
"Accept: */*\r\n"
|
|
"\r\n"
|
|
, should_keep_alive: TRUE
|
|
, request_method: EBB_GET
|
|
, query_string: ""
|
|
, fragment: ""
|
|
, request_path: "/test"
|
|
, request_uri: "/test"
|
|
, num_headers: 3
|
|
, header_fields: { "User-Agent", "Host", "Accept" }
|
|
, header_values: { "curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1", "0.0.0.0:5000", "*/*" }
|
|
, body: ""
|
|
};
|
|
|
|
const struct request_data firefox_get =
|
|
{ raw: "GET /favicon.ico HTTP/1.1\r\n"
|
|
"Host: 0.0.0.0:5000\r\n"
|
|
"User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0\r\n"
|
|
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
|
|
"Accept-Language: en-us,en;q=0.5\r\n"
|
|
"Accept-Encoding: gzip,deflate\r\n"
|
|
"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
|
|
"Keep-Alive: 300\r\n"
|
|
"Connection: keep-alive\r\n"
|
|
"\r\n"
|
|
, should_keep_alive: TRUE
|
|
, request_method: EBB_GET
|
|
, query_string: ""
|
|
, fragment: ""
|
|
, request_path: "/favicon.ico"
|
|
, request_uri: "/favicon.ico"
|
|
, num_headers: 8
|
|
, header_fields:
|
|
{ "Host"
|
|
, "User-Agent"
|
|
, "Accept"
|
|
, "Accept-Language"
|
|
, "Accept-Encoding"
|
|
, "Accept-Charset"
|
|
, "Keep-Alive"
|
|
, "Connection"
|
|
}
|
|
, header_values:
|
|
{ "0.0.0.0:5000"
|
|
, "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0"
|
|
, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
|
|
, "en-us,en;q=0.5"
|
|
, "gzip,deflate"
|
|
, "ISO-8859-1,utf-8;q=0.7,*;q=0.7"
|
|
, "300"
|
|
, "keep-alive"
|
|
}
|
|
, body: ""
|
|
};
|
|
|
|
const struct request_data dumbfuck =
|
|
{ raw: "GET /dumbfuck HTTP/1.1\r\n"
|
|
"aaaaaaaaaaaaa:++++++++++\r\n"
|
|
"\r\n"
|
|
, should_keep_alive: TRUE
|
|
, request_method: EBB_GET
|
|
, query_string: ""
|
|
, fragment: ""
|
|
, request_path: "/dumbfuck"
|
|
, request_uri: "/dumbfuck"
|
|
, num_headers: 1
|
|
, header_fields: { "aaaaaaaaaaaaa" }
|
|
, header_values: { "++++++++++" }
|
|
, body: ""
|
|
};
|
|
|
|
const struct request_data fragment_in_uri =
|
|
{ raw: "GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n"
|
|
"\r\n"
|
|
, should_keep_alive: TRUE
|
|
, request_method: EBB_GET
|
|
, query_string: "page=1"
|
|
, fragment: "posts-17408"
|
|
, request_path: "/forums/1/topics/2375"
|
|
/* XXX request uri does not include fragment? */
|
|
, request_uri: "/forums/1/topics/2375?page=1"
|
|
, num_headers: 0
|
|
, body: ""
|
|
};
|
|
|
|
|
|
// get - no headers - no body
|
|
const struct request_data get_no_headers_no_body =
|
|
{ raw: "GET /get_no_headers_no_body/world HTTP/1.1\r\n"
|
|
"\r\n"
|
|
, should_keep_alive: TRUE
|
|
, request_method: EBB_GET
|
|
, query_string: ""
|
|
, fragment: ""
|
|
, request_path: "/get_no_headers_no_body/world"
|
|
, request_uri: "/get_no_headers_no_body/world"
|
|
, num_headers: 0
|
|
, body: ""
|
|
};
|
|
|
|
// get - one header - no body
|
|
const struct request_data get_one_header_no_body =
|
|
{ raw: "GET /get_one_header_no_body HTTP/1.1\r\n"
|
|
"Accept: */*\r\n"
|
|
"\r\n"
|
|
, should_keep_alive: TRUE
|
|
, request_method: EBB_GET
|
|
, query_string: ""
|
|
, fragment: ""
|
|
, request_path: "/get_one_header_no_body"
|
|
, request_uri: "/get_one_header_no_body"
|
|
, num_headers: 1
|
|
, header_fields: { "Accept" }
|
|
, header_values: { "*/*" }
|
|
, body: ""
|
|
};
|
|
|
|
// get - no headers - body "HELLO"
|
|
const struct request_data get_funky_content_length_body_hello =
|
|
{ raw: "GET /get_funky_content_length_body_hello HTTP/1.0\r\n"
|
|
"conTENT-Length: 5\r\n"
|
|
"\r\n"
|
|
"HELLO"
|
|
, should_keep_alive: FALSE
|
|
, request_method: EBB_GET
|
|
, query_string: ""
|
|
, fragment: ""
|
|
, request_path: "/get_funky_content_length_body_hello"
|
|
, request_uri: "/get_funky_content_length_body_hello"
|
|
, num_headers: 1
|
|
, header_fields: { "conTENT-Length" }
|
|
, header_values: { "5" }
|
|
, body: "HELLO"
|
|
};
|
|
|
|
// post - one header - body "World"
|
|
const struct request_data post_identity_body_world =
|
|
{ raw: "POST /post_identity_body_world?q=search#hey HTTP/1.1\r\n"
|
|
"Accept: */*\r\n"
|
|
"Transfer-Encoding: identity\r\n"
|
|
"Content-Length: 5\r\n"
|
|
"\r\n"
|
|
"World"
|
|
, should_keep_alive: TRUE
|
|
, request_method: EBB_POST
|
|
, query_string: "q=search"
|
|
, fragment: "hey"
|
|
, request_path: "/post_identity_body_world"
|
|
, request_uri: "/post_identity_body_world?q=search"
|
|
, num_headers: 3
|
|
, header_fields: { "Accept", "Transfer-Encoding", "Content-Length" }
|
|
, header_values: { "*/*", "identity", "5" }
|
|
, body: "World"
|
|
};
|
|
|
|
// post - no headers - chunked body "all your base are belong to us"
|
|
const struct request_data post_chunked_all_your_base =
|
|
{ raw: "POST /post_chunked_all_your_base HTTP/1.1\r\n"
|
|
"Transfer-Encoding: chunked\r\n"
|
|
"\r\n"
|
|
"1e\r\nall your base are belong to us\r\n"
|
|
"0\r\n"
|
|
"\r\n"
|
|
, should_keep_alive: TRUE
|
|
, request_method: EBB_POST
|
|
, query_string: ""
|
|
, fragment: ""
|
|
, request_path: "/post_chunked_all_your_base"
|
|
, request_uri: "/post_chunked_all_your_base"
|
|
, num_headers: 1
|
|
, header_fields: { "Transfer-Encoding" }
|
|
, header_values: { "chunked" }
|
|
, body: "all your base are belong to us"
|
|
};
|
|
|
|
// two chunks ; triple zero ending
|
|
const struct request_data two_chunks_mult_zero_end =
|
|
{ raw: "POST /two_chunks_mult_zero_end HTTP/1.1\r\n"
|
|
"Transfer-Encoding: chunked\r\n"
|
|
"\r\n"
|
|
"5\r\nhello\r\n"
|
|
"6\r\n world\r\n"
|
|
"000\r\n"
|
|
"\r\n"
|
|
, should_keep_alive: TRUE
|
|
, request_method: EBB_POST
|
|
, query_string: ""
|
|
, fragment: ""
|
|
, request_path: "/two_chunks_mult_zero_end"
|
|
, request_uri: "/two_chunks_mult_zero_end"
|
|
, num_headers: 1
|
|
, header_fields: { "Transfer-Encoding" }
|
|
, header_values: { "chunked" }
|
|
, body: "hello world"
|
|
};
|
|
|
|
|
|
// chunked with trailing headers. blech.
|
|
const struct request_data chunked_w_trailing_headers =
|
|
{ raw: "POST /chunked_w_trailing_headers HTTP/1.1\r\n"
|
|
"Transfer-Encoding: chunked\r\n"
|
|
"\r\n"
|
|
"5\r\nhello\r\n"
|
|
"6\r\n world\r\n"
|
|
"0\r\n"
|
|
"Vary: *\r\n"
|
|
"Content-Type: text/plain\r\n"
|
|
"\r\n"
|
|
, should_keep_alive: TRUE
|
|
, request_method: EBB_POST
|
|
, query_string: ""
|
|
, fragment: ""
|
|
, request_path: "/chunked_w_trailing_headers"
|
|
, request_uri: "/chunked_w_trailing_headers"
|
|
, num_headers: 1
|
|
, header_fields: { "Transfer-Encoding" }
|
|
, header_values: { "chunked" }
|
|
, body: "hello world"
|
|
};
|
|
|
|
// with bullshit after the length
|
|
const struct request_data chunked_w_bullshit_after_length =
|
|
{ raw: "POST /chunked_w_bullshit_after_length HTTP/1.1\r\n"
|
|
"Transfer-Encoding: chunked\r\n"
|
|
"\r\n"
|
|
"5; ihatew3;whatthefuck=aretheseparametersfor\r\nhello\r\n"
|
|
"6; blahblah; blah\r\n world\r\n"
|
|
"0\r\n"
|
|
"\r\n"
|
|
, should_keep_alive: TRUE
|
|
, request_method: EBB_POST
|
|
, query_string: ""
|
|
, fragment: ""
|
|
, request_path: "/chunked_w_bullshit_after_length"
|
|
, request_uri: "/chunked_w_bullshit_after_length"
|
|
, num_headers: 1
|
|
, header_fields: { "Transfer-Encoding" }
|
|
, header_values: { "chunked" }
|
|
, body: "hello world"
|
|
};
|
|
|
|
const struct request_data *fixtures[] =
|
|
{ &curl_get
|
|
, &firefox_get
|
|
, &dumbfuck
|
|
, &fragment_in_uri
|
|
, &get_no_headers_no_body
|
|
, &get_one_header_no_body
|
|
, &get_funky_content_length_body_hello
|
|
, &post_identity_body_world
|
|
, &post_chunked_all_your_base
|
|
, &two_chunks_mult_zero_end
|
|
, &chunked_w_trailing_headers
|
|
, &chunked_w_bullshit_after_length
|
|
, NULL
|
|
};
|
|
|
|
|
|
int request_data_eq
|
|
( struct request_data *r1
|
|
, const struct request_data *r2
|
|
)
|
|
{
|
|
if(ebb_request_should_keep_alive(&r1->request) != r2->should_keep_alive) {
|
|
printf("requests disagree on keep-alive");
|
|
return FALSE;
|
|
}
|
|
|
|
if(0 != strcmp(r1->body, r2->body)) {
|
|
printf("body '%s' != '%s'\n", r1->body, r2->body);
|
|
return FALSE;
|
|
}
|
|
if(0 != strcmp(r1->fragment, r2->fragment)) {
|
|
printf("fragment '%s' != '%s'\n", r1->fragment, r2->fragment);
|
|
return FALSE;
|
|
}
|
|
if(0 != strcmp(r1->query_string, r2->query_string)) {
|
|
printf("query_string '%s' != '%s'\n", r1->query_string, r2->query_string);
|
|
return FALSE;
|
|
}
|
|
if(r1->request.method != r2->request_method) {
|
|
printf("request_method '%d' != '%d'\n", r1->request.method, r2->request_method);
|
|
return FALSE;
|
|
}
|
|
if(0 != strcmp(r1->request_path, r2->request_path)) {
|
|
printf("request_path '%s' != '%s'\n", r1->request_path, r2->request_path);
|
|
return FALSE;
|
|
}
|
|
if(0 != strcmp(r1->request_uri, r2->request_uri)) {
|
|
printf("request_uri '%s' != '%s'\n", r1->request_uri, r2->request_uri);
|
|
return FALSE;
|
|
}
|
|
if(r1->num_headers != r2->num_headers) {
|
|
printf("num_headers '%d' != '%d'\n", r1->num_headers, r2->num_headers);
|
|
return FALSE;
|
|
}
|
|
int i;
|
|
for(i = 0; i < r1->num_headers; i++) {
|
|
if(0 != strcmp(r1->header_fields[i], r2->header_fields[i])) {
|
|
printf("header field '%s' != '%s'\n", r1->header_fields[i], r2->header_fields[i]);
|
|
return FALSE;
|
|
}
|
|
if(0 != strcmp(r1->header_values[i], r2->header_values[i])) {
|
|
printf("header field '%s' != '%s'\n", r1->header_values[i], r2->header_values[i]);
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
int request_eq
|
|
( int index
|
|
, const struct request_data *expected
|
|
)
|
|
{
|
|
return request_data_eq(&requests[index], expected);
|
|
}
|
|
|
|
void request_complete(ebb_request *info)
|
|
{
|
|
num_requests++;
|
|
}
|
|
|
|
void request_path_cb(ebb_request *request, const char *p, size_t len)
|
|
{
|
|
strncat(requests[num_requests].request_path, p, len);
|
|
}
|
|
|
|
void request_uri_cb(ebb_request *request, const char *p, size_t len)
|
|
{
|
|
strncat(requests[num_requests].request_uri, p, len);
|
|
}
|
|
|
|
void query_string_cb(ebb_request *request, const char *p, size_t len)
|
|
{
|
|
strncat(requests[num_requests].query_string, p, len);
|
|
}
|
|
|
|
void fragment_cb(ebb_request *request, const char *p, size_t len)
|
|
{
|
|
strncat(requests[num_requests].fragment, p, len);
|
|
}
|
|
|
|
void header_field_cb(ebb_request *request, const char *p, size_t len, int header_index)
|
|
{
|
|
strncat(requests[num_requests].header_fields[header_index], p, len);
|
|
}
|
|
|
|
void header_value_cb(ebb_request *request, const char *p, size_t len, int header_index)
|
|
{
|
|
strncat(requests[num_requests].header_values[header_index], p, len);
|
|
requests[num_requests].num_headers = header_index + 1;
|
|
}
|
|
|
|
void body_handler(ebb_request *request, const char *p, size_t len)
|
|
{
|
|
strncat(requests[num_requests].body, p, len);
|
|
// printf("body_handler: '%s'\n", requests[num_requests].body);
|
|
}
|
|
|
|
ebb_request* new_request ()
|
|
{
|
|
requests[num_requests].num_headers = 0;
|
|
requests[num_requests].request_method = -1;
|
|
requests[num_requests].request_path[0] = 0;
|
|
requests[num_requests].request_uri[0] = 0;
|
|
requests[num_requests].fragment[0] = 0;
|
|
requests[num_requests].query_string[0] = 0;
|
|
requests[num_requests].body[0] = 0;
|
|
int i;
|
|
for(i = 0; i < MAX_HEADERS; i++) {
|
|
requests[num_requests].header_fields[i][0] = 0;
|
|
requests[num_requests].header_values[i][0] = 0;
|
|
}
|
|
|
|
ebb_request *r = &requests[num_requests].request;
|
|
ebb_request_init(r);
|
|
|
|
r->on_complete = request_complete;
|
|
r->on_header_field = header_field_cb;
|
|
r->on_header_value = header_value_cb;
|
|
r->on_path = request_path_cb;
|
|
r->on_uri = request_uri_cb;
|
|
r->on_fragment = fragment_cb;
|
|
r->on_query_string = query_string_cb;
|
|
r->on_body = body_handler;
|
|
r->on_headers_complete = NULL;
|
|
|
|
r->data = &requests[num_requests];
|
|
// printf("new request %d\n", num_requests);
|
|
return r;
|
|
}
|
|
|
|
void parser_init()
|
|
{
|
|
num_requests = 0;
|
|
|
|
ebb_request_parser_init(&parser);
|
|
|
|
parser.new_request = new_request;
|
|
}
|
|
|
|
int test_request
|
|
( const struct request_data *request_data
|
|
)
|
|
{
|
|
size_t traversed = 0;
|
|
parser_init();
|
|
|
|
traversed = ebb_request_parser_execute( &parser
|
|
, request_data->raw
|
|
, strlen(request_data->raw)
|
|
);
|
|
if( ebb_request_parser_has_error(&parser) )
|
|
return FALSE;
|
|
if(! ebb_request_parser_is_finished(&parser) )
|
|
return FALSE;
|
|
if(num_requests != 1)
|
|
return FALSE;
|
|
|
|
return request_eq(0, request_data);
|
|
}
|
|
|
|
int test_error
|
|
( const char *buf
|
|
)
|
|
{
|
|
size_t traversed = 0;
|
|
parser_init();
|
|
|
|
traversed = ebb_request_parser_execute(&parser, buf, strlen(buf));
|
|
|
|
return ebb_request_parser_has_error(&parser);
|
|
}
|
|
|
|
|
|
int test_multiple3
|
|
( const struct request_data *r1
|
|
, const struct request_data *r2
|
|
, const struct request_data *r3
|
|
)
|
|
{
|
|
char total[80*1024] = "\0";
|
|
|
|
strcat(total, r1->raw);
|
|
strcat(total, r2->raw);
|
|
strcat(total, r3->raw);
|
|
|
|
size_t traversed = 0;
|
|
parser_init();
|
|
|
|
traversed = ebb_request_parser_execute(&parser, total, strlen(total));
|
|
|
|
|
|
if( ebb_request_parser_has_error(&parser) )
|
|
return FALSE;
|
|
if(! ebb_request_parser_is_finished(&parser) )
|
|
return FALSE;
|
|
if(num_requests != 3)
|
|
return FALSE;
|
|
|
|
if(!request_eq(0, r1)){
|
|
printf("request 1 error.\n");
|
|
return FALSE;
|
|
}
|
|
if(!request_eq(1, r2)){
|
|
printf("request 2 error.\n");
|
|
return FALSE;
|
|
}
|
|
if(!request_eq(2, r3)){
|
|
printf("request 3 error.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* SCAN through every possible breaking to make sure the
|
|
* parser can handle getting the content in any chunks that
|
|
* might come from the socket
|
|
*/
|
|
int test_scan2
|
|
( const struct request_data *r1
|
|
, const struct request_data *r2
|
|
, const struct request_data *r3
|
|
)
|
|
{
|
|
char total[80*1024] = "\0";
|
|
char buf1[80*1024] = "\0";
|
|
char buf2[80*1024] = "\0";
|
|
|
|
strcat(total, r1->raw);
|
|
strcat(total, r2->raw);
|
|
strcat(total, r3->raw);
|
|
|
|
int total_len = strlen(total);
|
|
|
|
//printf("total_len = %d\n", total_len);
|
|
int i;
|
|
for(i = 1; i < total_len - 1; i ++ ) {
|
|
|
|
parser_init();
|
|
|
|
int buf1_len = i;
|
|
strncpy(buf1, total, buf1_len);
|
|
buf1[buf1_len] = 0;
|
|
|
|
int buf2_len = total_len - i;
|
|
strncpy(buf2, total+i, buf2_len);
|
|
buf2[buf2_len] = 0;
|
|
|
|
ebb_request_parser_execute(&parser, buf1, buf1_len);
|
|
|
|
if( ebb_request_parser_has_error(&parser) ) {
|
|
return FALSE;
|
|
}
|
|
/*
|
|
if(ebb_request_parser_is_finished(&parser))
|
|
return FALSE;
|
|
*/
|
|
|
|
ebb_request_parser_execute(&parser, buf2, buf2_len);
|
|
|
|
if( ebb_request_parser_has_error(&parser))
|
|
return FALSE;
|
|
if(!ebb_request_parser_is_finished(&parser))
|
|
return FALSE;
|
|
|
|
if(3 != num_requests) {
|
|
printf("scan error: got %d requests in iteration %d\n", num_requests, i);
|
|
return FALSE;
|
|
}
|
|
|
|
if(!request_eq(0, r1)) {
|
|
printf("not maching r1\n");
|
|
return FALSE;
|
|
}
|
|
if(!request_eq(1, r2)) {
|
|
printf("not maching r2\n");
|
|
return FALSE;
|
|
}
|
|
if(!request_eq(2, r3)) {
|
|
printf("not maching r3\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
int test_scan3
|
|
( const struct request_data *r1
|
|
, const struct request_data *r2
|
|
, const struct request_data *r3
|
|
)
|
|
{
|
|
char total[80*1024] = "\0";
|
|
char buf1[80*1024] = "\0";
|
|
char buf2[80*1024] = "\0";
|
|
char buf3[80*1024] = "\0";
|
|
|
|
strcat(total, r1->raw);
|
|
strcat(total, r2->raw);
|
|
strcat(total, r3->raw);
|
|
|
|
int total_len = strlen(total);
|
|
|
|
//printf("total_len = %d\n", total_len);
|
|
int i,j;
|
|
for(j = 2; j < total_len - 1; j ++ ) {
|
|
for(i = 1; i < j; i ++ ) {
|
|
|
|
parser_init();
|
|
|
|
|
|
|
|
|
|
int buf1_len = i;
|
|
strncpy(buf1, total, buf1_len);
|
|
buf1[buf1_len] = 0;
|
|
|
|
int buf2_len = j - i;
|
|
strncpy(buf2, total+i, buf2_len);
|
|
buf2[buf2_len] = 0;
|
|
|
|
int buf3_len = total_len - j;
|
|
strncpy(buf3, total+j, buf3_len);
|
|
buf3[buf3_len] = 0;
|
|
|
|
/*
|
|
printf("buf1: %s - %d\n", buf1, buf1_len);
|
|
printf("buf2: %s - %d \n", buf2, buf2_len );
|
|
printf("buf3: %s - %d\n\n", buf3, buf3_len);
|
|
*/
|
|
|
|
ebb_request_parser_execute(&parser, buf1, buf1_len);
|
|
|
|
if( ebb_request_parser_has_error(&parser) ) {
|
|
return FALSE;
|
|
}
|
|
|
|
ebb_request_parser_execute(&parser, buf2, buf2_len);
|
|
|
|
if( ebb_request_parser_has_error(&parser) ) {
|
|
return FALSE;
|
|
}
|
|
|
|
ebb_request_parser_execute(&parser, buf3, buf3_len);
|
|
|
|
if( ebb_request_parser_has_error(&parser))
|
|
return FALSE;
|
|
if(!ebb_request_parser_is_finished(&parser))
|
|
return FALSE;
|
|
|
|
if(3 != num_requests) {
|
|
printf("scan error: only got %d requests in iteration %d\n", num_requests, i);
|
|
return FALSE;
|
|
}
|
|
|
|
if(!request_eq(0, r1)) {
|
|
printf("not maching r1\n");
|
|
return FALSE;
|
|
}
|
|
if(!request_eq(1, r2)) {
|
|
printf("not maching r2\n");
|
|
return FALSE;
|
|
}
|
|
if(!request_eq(2, r3)) {
|
|
printf("not maching r3\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
|
|
assert(test_error("hello world"));
|
|
assert(test_error("GET / HTP/1.1\r\n\r\n"));
|
|
|
|
assert(test_request(&curl_get));
|
|
assert(test_request(&firefox_get));
|
|
|
|
// Zed's header tests
|
|
|
|
assert(test_request(&dumbfuck));
|
|
|
|
const char *dumbfuck2 = "GET / HTTP/1.1\r\nX-SSL-Bullshit: -----BEGIN CERTIFICATE-----\r\n\tMIIFbTCCBFWgAwIBAgICH4cwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVUsx\r\n\tETAPBgNVBAoTCGVTY2llbmNlMRIwEAYDVQQLEwlBdXRob3JpdHkxCzAJBgNVBAMT\r\n\tAkNBMS0wKwYJKoZIhvcNAQkBFh5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMu\r\n\tdWswHhcNMDYwNzI3MTQxMzI4WhcNMDcwNzI3MTQxMzI4WjBbMQswCQYDVQQGEwJV\r\n\tSzERMA8GA1UEChMIZVNjaWVuY2UxEzARBgNVBAsTCk1hbmNoZXN0ZXIxCzAJBgNV\r\n\tBAcTmrsogriqMWLAk1DMRcwFQYDVQQDEw5taWNoYWVsIHBhcmQYJKoZIhvcNAQEB\r\n\tBQADggEPADCCAQoCggEBANPEQBgl1IaKdSS1TbhF3hEXSl72G9J+WC/1R64fAcEF\r\n\tW51rEyFYiIeZGx/BVzwXbeBoNUK41OK65sxGuflMo5gLflbwJtHBRIEKAfVVp3YR\r\n\tgW7cMA/s/XKgL1GEC7rQw8lIZT8RApukCGqOVHSi/F1SiFlPDxuDfmdiNzL31+sL\r\n\t0iwHDdNkGjy5pyBSB8Y79dsSJtCW/iaLB0/n8Sj7HgvvZJ7x0fr+RQjYOUUfrePP\r\n\tu2MSpFyf+9BbC/aXgaZuiCvSR+8Snv3xApQY+fULK/xY8h8Ua51iXoQ5jrgu2SqR\r\n\twgA7BUi3G8LFzMBl8FRCDYGUDy7M6QaHXx1ZWIPWNKsCAwEAAaOCAiQwggIgMAwG\r\n\tA1UdEwEB/wQCMAAwEQYJYIZIAYb4QgEBBAQDAgWgMA4GA1UdDwEB/wQEAwID6DAs\r\n\tBglghkgBhvhCAQ0EHxYdVUsgZS1TY2llbmNlIFVzZXIgQ2VydGlmaWNhdGUwHQYD\r\n\tVR0OBBYEFDTt/sf9PeMaZDHkUIldrDYMNTBZMIGaBgNVHSMEgZIwgY+AFAI4qxGj\r\n\tloCLDdMVKwiljjDastqooXSkcjBwMQswCQYDVQQGEwJVSzERMA8GA1UEChMIZVNj\r\n\taWVuY2UxEjAQBgNVBAsTCUF1dGhvcml0eTELMAkGA1UEAxMCQ0ExLTArBgkqhkiG\r\n\t9w0BCQEWHmNhLW9wZXJhdG9yQGdyaWQtc3VwcG9ydC5hYy51a4IBADApBgNVHRIE\r\n\tIjAggR5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMudWswGQYDVR0gBBIwEDAO\r\n\tBgwrBgEEAdkvAQEBAQYwPQYJYIZIAYb4QgEEBDAWLmh0dHA6Ly9jYS5ncmlkLXN1\r\n\tcHBvcnQuYWMudmT4sopwqlBWsvcHViL2NybC9jYWNybC5jcmwwPQYJYIZIAYb4QgEDBDAWLmh0\r\n\tdHA6Ly9jYS5ncmlkLXN1cHBvcnQuYWMudWsvcHViL2NybC9jYWNybC5jcmwwPwYD\r\n\tVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NhLmdyaWQt5hYy51ay9wdWIv\r\n\tY3JsL2NhY3JsLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAS/U4iiooBENGW/Hwmmd3\r\n\tXCy6Zrt08YjKCzGNjorT98g8uGsqYjSxv/hmi0qlnlHs+k/3Iobc3LjS5AMYr5L8\r\n\tUO7OSkgFFlLHQyC9JzPfmLCAugvzEbyv4Olnsr8hbxF1MbKZoQxUZtMVu29wjfXk\r\n\thTeApBv7eaKCWpSp7MCbvgzm74izKhu3vlDk9w6qVrxePfGgpKPqfHiOoGhFnbTK\r\n\twTC6o2xq5y0qZ03JonF7OJspEd3I5zKY3E+ov7/ZhW6DqT8UFvsAdjvQbXyhV8Eu\r\n\tYhixw1aKEPzNjNowuIseVogKOLXxWI5vAi5HgXdS0/ES5gDGsABo4fqovUKlgop3\r\n\tRA==\r\n\t-----END CERTIFICATE-----\r\n\r\n";
|
|
assert(test_error(dumbfuck2));
|
|
|
|
assert(test_request(&fragment_in_uri));
|
|
|
|
/* TODO sending junk and large headers gets rejected */
|
|
|
|
|
|
/* check to make sure our predefined requests are okay */
|
|
|
|
assert(test_request(&get_no_headers_no_body));
|
|
assert(test_request(&get_one_header_no_body));
|
|
assert(test_request(&get_no_headers_no_body));
|
|
|
|
// no content-length
|
|
const char *bad_get_no_headers_no_body = "GET /bad_get_no_headers_no_body/world HTTP/1.1\r\nAccept: */*\r\nHELLO\r\n";
|
|
assert(test_error(bad_get_no_headers_no_body)); // error if there is a body without content length
|
|
|
|
assert(test_request(&get_funky_content_length_body_hello));
|
|
assert(test_request(&post_identity_body_world));
|
|
assert(test_request(&post_chunked_all_your_base));
|
|
assert(test_request(&two_chunks_mult_zero_end));
|
|
assert(test_request(&chunked_w_trailing_headers));
|
|
|
|
assert(test_request(&chunked_w_bullshit_after_length));
|
|
assert(1 == requests[0].request.version_major);
|
|
assert(1 == requests[0].request.version_minor);
|
|
|
|
// three requests - no bodies
|
|
assert( test_multiple3( &get_no_headers_no_body
|
|
, &get_one_header_no_body
|
|
, &get_no_headers_no_body
|
|
));
|
|
|
|
// three requests - one body
|
|
assert( test_multiple3(&get_no_headers_no_body, &get_funky_content_length_body_hello, &get_no_headers_no_body));
|
|
|
|
// three requests with bodies -- last is chunked
|
|
assert( test_multiple3(&get_funky_content_length_body_hello, &post_identity_body_world, &post_chunked_all_your_base));
|
|
|
|
// three chunked requests
|
|
assert( test_multiple3(&two_chunks_mult_zero_end, &post_chunked_all_your_base, &chunked_w_trailing_headers));
|
|
|
|
|
|
assert(test_scan2(&get_no_headers_no_body, &get_one_header_no_body, &get_no_headers_no_body));
|
|
assert(test_scan2(&get_funky_content_length_body_hello, &post_identity_body_world, &post_chunked_all_your_base));
|
|
assert(test_scan2(&two_chunks_mult_zero_end, &chunked_w_trailing_headers, &chunked_w_bullshit_after_length));
|
|
|
|
assert(test_scan3(&get_no_headers_no_body, &get_one_header_no_body, &get_no_headers_no_body));
|
|
assert(test_scan3(&get_funky_content_length_body_hello, &post_identity_body_world, &post_chunked_all_your_base));
|
|
assert(test_scan3(&two_chunks_mult_zero_end, &chunked_w_trailing_headers, &chunked_w_bullshit_after_length));
|
|
|
|
|
|
printf("okay\n");
|
|
return 0;
|
|
}
|
|
|
|
|