#include "httpparser.h"
#include "../daemon/httpparser.h"
#include <cx/string.h>
CX_TEST(test_parse_request_line) {
CX_TEST_DO {
HttpParser parser;
memset(&parser,
0,
sizeof(HttpParser));
parser.start_line = cx_mutstr(
"GET / HTTP/1.1\r\n");
int ret1 = parse_request_line(&parser);
CX_TEST_ASSERT(!ret1);
CX_TEST_ASSERT(!cx_strcmp(parser.method,
"GET"));
CX_TEST_ASSERT(!cx_strcmp(parser.uri,
"/"));
CX_TEST_ASSERT(!cx_strcmp(parser.httpv,
"HTTP/1.1"));
memset(&parser,
0,
sizeof(HttpParser));
parser.start_line = cx_mutstr(
"POST /longer/url/test/path/ HTTP/1.0\r\n");
int ret2 = parse_request_line(&parser);
CX_TEST_ASSERT(!ret2);
CX_TEST_ASSERT(!cx_strcmp(parser.method,
"POST"));
CX_TEST_ASSERT(!cx_strcmp(parser.uri,
"/longer/url/test/path/"));
CX_TEST_ASSERT(!cx_strcmp(parser.httpv,
"HTTP/1.0"));
memset(&parser,
0,
sizeof(HttpParser));
parser.start_line = cx_mutstr(
"G / v\r\n");
int ret3 = parse_request_line(&parser);
CX_TEST_ASSERT(!ret3);
CX_TEST_ASSERT(!cx_strcmp(parser.method,
"G"));
CX_TEST_ASSERT(!cx_strcmp(parser.uri,
"/"));
CX_TEST_ASSERT(!cx_strcmp(parser.httpv,
"v"));
memset(&parser,
0,
sizeof(HttpParser));
parser.start_line = cx_mutstr(
"HEAD /space HTTP/0.9 \r\n");
int ret4 = parse_request_line(&parser);
CX_TEST_ASSERT(!ret4);
CX_TEST_ASSERT(!cx_strcmp(parser.method,
"HEAD"));
CX_TEST_ASSERT(!cx_strcmp(parser.uri,
"/space"));
CX_TEST_ASSERT(!cx_strcmp(parser.httpv,
"HTTP/0.9"));
memset(&parser,
0,
sizeof(HttpParser));
parser.start_line = cx_mutstr(
"PROPFIND /collection/ HTTP/1.1\n");
int uret1 = parse_request_line(&parser);
CX_TEST_ASSERT(!uret1);
CX_TEST_ASSERT(!cx_strcmp(parser.method,
"PROPFIND"));
CX_TEST_ASSERT(!cx_strcmp(parser.uri,
"/collection/"));
CX_TEST_ASSERT(!cx_strcmp(parser.httpv,
"HTTP/1.1"));
parser.start_line = cx_mutstr(
"\r\n");
int nret1 = parse_request_line(&parser);
CX_TEST_ASSERT(nret1);
parser.start_line = cx_mutstr(
"GET\r\n");
int nret2 = parse_request_line(&parser);
CX_TEST_ASSERT(nret2);
parser.start_line = cx_mutstr(
"GET /test\r\n");
int nret3 = parse_request_line(&parser);
CX_TEST_ASSERT(nret3);
parser.start_line = cx_mutstr(
"GET /test \r\n");
int nret4 = parse_request_line(&parser);
CX_TEST_ASSERT(nret4);
parser.start_line = cx_mutstr(
"/test HTTP/1.1\r\n");
int nret5 = parse_request_line(&parser);
CX_TEST_ASSERT(nret5);
parser.start_line = cx_mutstr(
"GET /uri HTTP/1.1 test\r\n");
int nret6 = parse_request_line(&parser);
CX_TEST_ASSERT(nret6);
parser.start_line = cx_mutstr(
" /uri2 HTTP/1.1\r\n");
int nret7 = parse_request_line(&parser);
CX_TEST_ASSERT(nret7);
parser.start_line = cx_mutstr(
"GET HTTP/1.1\r\n");
int nret8 = parse_request_line(&parser);
CX_TEST_ASSERT(nret8);
}
}
CX_TEST(test_parse_response_line) {
CX_TEST_DO {
HttpParser parser;
memset(&parser,
0,
sizeof(HttpParser));
parser.start_line = cx_mutstr(
"HTTP/1.1 200 OK\r\n");
parser.type =
1;
int ret1 = parse_response_line(&parser);
CX_TEST_ASSERT(!ret1);
CX_TEST_ASSERT(!cx_strcmp(parser.httpv,
"HTTP/1.1"));
CX_TEST_ASSERT(!cx_strcmp(parser.msg,
"OK"));
CX_TEST_ASSERT(parser.status ==
200);
memset(&parser,
0,
sizeof(HttpParser));
parser.start_line = cx_mutstr(
"HTTP/1.0 201 Created\r\n");
parser.type =
1;
int ret2 = parse_response_line(&parser);
CX_TEST_ASSERT(!ret2);
CX_TEST_ASSERT(!cx_strcmp(parser.httpv,
"HTTP/1.0"));
CX_TEST_ASSERT(!cx_strcmp(parser.msg,
"Created"));
CX_TEST_ASSERT(parser.status ==
201);
memset(&parser,
0,
sizeof(HttpParser));
parser.start_line = cx_mutstr(
"HTTP/0.9 204 No Content\r\n");
parser.type =
1;
int ret3 = parse_response_line(&parser);
CX_TEST_ASSERT(!ret3);
CX_TEST_ASSERT(!cx_strcmp(parser.httpv,
"HTTP/0.9"));
CX_TEST_ASSERT(!cx_strcmp(parser.msg,
"No Content"));
CX_TEST_ASSERT(parser.status ==
204);
memset(&parser,
0,
sizeof(HttpParser));
parser.start_line = cx_mutstr(
"HTTP/1.1 200\r\n");
parser.type =
1;
int nret1 = parse_response_line(&parser);
CX_TEST_ASSERT(nret1);
memset(&parser,
0,
sizeof(HttpParser));
parser.start_line = cx_mutstr(
"\r\n");
parser.type =
1;
int nret2 = parse_response_line(&parser);
CX_TEST_ASSERT(nret2);
memset(&parser,
0,
sizeof(HttpParser));
parser.start_line = cx_mutstr(
"200\r\n");
parser.type =
1;
int nret3 = parse_response_line(&parser);
CX_TEST_ASSERT(nret3);
memset(&parser,
0,
sizeof(HttpParser));
parser.start_line = cx_mutstr(
"HTTP/1.1 2345 Test Message\r\n");
parser.type =
1;
int nret4 = parse_response_line(&parser);
CX_TEST_ASSERT(nret4);
memset(&parser,
0,
sizeof(HttpParser));
parser.start_line = cx_mutstr(
"HTTP/1.1 xy1 OK\r\n");
parser.type =
1;
int nret5 = parse_response_line(&parser);
CX_TEST_ASSERT(nret5);
memset(&parser,
0,
sizeof(HttpParser));
parser.start_line = cx_mutstr(
" 200 OK\r\n");
parser.type =
1;
int nret6 = parse_response_line(&parser);
CX_TEST_ASSERT(nret6);
}
}
CX_TEST_SUBROUTINE(test_http_parser_process, cxstring request,
int chunksize) {
netbuf buf;
memset(&buf,
0,
sizeof(netbuf));
buf.inbuf = (
unsigned char*)request.ptr;
buf.maxsize = request.length;
HeaderArray *header = header_array_create();
HttpParser *parser = http_parser_new2(
0, &buf, header);
while(buf.cursize < request.length) {
buf.cursize += chunksize;
if(buf.cursize > buf.maxsize) {
buf.cursize = buf.maxsize;
}
int ret = http_parser_process(parser);
if(buf.cursize < buf.maxsize) {
CX_TEST_ASSERT(ret ==
1);
}
else {
CX_TEST_ASSERT(ret ==
0);
}
}
CX_TEST_ASSERT(http_parser_validate(parser));
http_parser_free(parser);
header_array_free(header);
}
#define _CX_STR(s) { s,
sizeof(s)
-1 }
static cxstring req0 =
_CX_STR(
"GET / HTTP/1.1\r\n"
"Host: example.com\r\n"
"\r\n");
static cxstring req1 =
_CX_STR(
"GET /api/data?id=42 HTTP/1.1\r\n"
"Host: api.example.com\r\n"
"User-Agent: TestClient/1.0\r\n"
"Accept: application/json\r\n"
"Accept-Language: en-US,en;q=0.9\r\n"
"Connection: keep-alive\r\n"
"Cache-Control: no-cache\r\n"
"\r\n");
static cxstring req2 =
_CX_STR(
"GET /search?q=network+testing HTTP/1.1\r\n"
"Host: www.example.com\r\n"
"User-Agent: Mozilla/5.0 (X11; Linux x86_64) TestBrowser/99.0\r\n"
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n"
"Accept-Language: en-US,en;q=0.9,de;q=0.8\r\n"
"Accept-Encoding: gzip, deflate, br\r\n"
"Connection: keep-alive\r\n"
"Cache-Control: max-age=0\r\n"
"Upgrade-Insecure-Requests: 1\r\n"
"Pragma: no-cache\r\n"
"DNT: 1\r\n"
"Sec-Fetch-Dest: document\r\n"
"Sec-Fetch-Mode: navigate\r\n"
"Sec-Fetch-Site: none\r\n"
"Sec-Fetch-User: ?1\r\n"
"Referer: https://www.example.com/\r\n"
"X-Forwarded-For: 203.0.113.195\r\n"
"X-Request-ID: 123e4567-e89b-12d3-a456-426614174000\r\n"
"\r\n");
CX_TEST(test_http_parser_process_full) {
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req0, req0.length);
CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req1, req1.length);
CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req2, req2.length);
}
}
CX_TEST(test_http_parser_process_chunk_1b) {
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req0,
1);
CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req1,
1);
CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req2,
1);
}
}
CX_TEST(test_http_parser_process_chunk_2b) {
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req0,
2);
CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req1,
2);
CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req2,
2);
}
}
CX_TEST(test_http_parser_process_chunk_3b) {
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req0,
3);
CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req1,
3);
CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req2,
3);
}
}
CX_TEST(test_http_parser_process_chunk_4b) {
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req0,
4);
CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req1,
4);
CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req2,
4);
}
}