1
0
Fork 0

Added unit test for parsing HTTP request.

This commit is contained in:
Mattes D 2016-01-03 16:07:53 +01:00
parent fea556ca1b
commit 1d05fc95ae
7 changed files with 230 additions and 0 deletions

4
.gitattributes vendored Normal file
View File

@ -0,0 +1,4 @@
# Set the *.data files to be checked out as binary files.
# Used for the HTTP test data files, they need to have the CRLF line endings
# even on Linux, because they're HTTP protocol dumps.
*.data binary

View File

@ -263,6 +263,7 @@ if (MSVC)
if (${SELF_TEST})
set_target_properties(
Network
HTTP
PROPERTIES FOLDER Lib
)
set_target_properties(
@ -274,6 +275,7 @@ if (MSVC)
creatable-exe
EchoServer
Google-exe
HTTPResponseParser_file-exe
LoadablePieces
NameLookup
PROPERTIES FOLDER Tests

View File

@ -9,5 +9,6 @@ endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
add_subdirectory(ChunkData)
add_subdirectory(HTTP)
add_subdirectory(Network)
add_subdirectory(LoadablePieces)

46
tests/HTTP/CMakeLists.txt Normal file
View File

@ -0,0 +1,46 @@
cmake_minimum_required (VERSION 2.6)
enable_testing()
include_directories(${CMAKE_SOURCE_DIR}/src/)
include_directories(${CMAKE_SOURCE_DIR}/lib/libevent/include)
add_definitions(-DTEST_GLOBALS=1)
# Create a single HTTP library that contains all the HTTP code:
set (HTTP_SRCS
${CMAKE_SOURCE_DIR}/src/HTTP/EnvelopeParser.cpp
${CMAKE_SOURCE_DIR}/src/HTTP/HTTPMessage.cpp
${CMAKE_SOURCE_DIR}/src/HTTP/HTTPResponseParser.cpp
${CMAKE_SOURCE_DIR}/src/HTTP/TransferEncodingParser.cpp
${CMAKE_SOURCE_DIR}/src/StringUtils.cpp
)
set (HTTP_HDRS
${CMAKE_SOURCE_DIR}/src/HTTP/EnvelopeParser.h
${CMAKE_SOURCE_DIR}/src/HTTP/HTTPMessage.h
${CMAKE_SOURCE_DIR}/src/HTTP/HTTPResponseParser.h
${CMAKE_SOURCE_DIR}/src/HTTP/TransferEncodingParser.h
${CMAKE_SOURCE_DIR}/src/StringUtils.h
)
add_library(HTTP
${HTTP_SRCS}
${HTTP_HDRS}
)
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_flags_cxx("-Wno-error=conversion -Wno-error=old-style-cast")
endif()
# Define individual tests:
# HTTPResponseParser_file: Feed file contents into a cHTTPResponseParser and print the callbacks as they're called:
add_executable(HTTPResponseParser_file-exe HTTPResponseParser_file.cpp)
target_link_libraries(HTTPResponseParser_file-exe HTTP)
add_test(NAME HTTPResponseParser_file-test1 COMMAND HTTPResponseParser_file-exe HTTPResponse1.data)
add_test(NAME HTTPResponseParser_file-test2 COMMAND HTTPResponseParser_file-exe HTTPResponse2.data)

View File

@ -0,0 +1,9 @@
HTTP/1.0 200 OK
Note: This is a test of a regular response with Content-Length set
(identity transfer encoding)
Note2: The above header also tests multi-line header lines
Header1: Value1
Header2: Value2
Content-Length: 3
bla

View File

@ -0,0 +1,15 @@
HTTP/1.0 200 OK
Note: This is a Chunked transfer encoding test
Header2: Value2
Transfer-Encoding: chunked
4
Wiki
5
pedia
e
in
chunks.
0

View File

@ -0,0 +1,153 @@
// HTTPResponseParser_file.cpp
// Implements a test that feeds file contents into a cHTTPResponseParser instance and prints all callbacks
#include "Globals.h"
#include "HTTP/HTTPResponseParser.h"
/** Maximum size of the input buffer, through which the file is read */
static const size_t MAX_BUF = 4096;
class cCallbacks:
public cHTTPResponseParser::cCallbacks
{
typedef cHTTPResponseParser::cCallbacks Super;
public:
cCallbacks(void)
{
printf("cCallbacks created\n");
}
// cHTTPResponseParser::cCallbacks overrides:
virtual void OnError(const AString & a_ErrorDescription) override
{
printf("Error: \"%s\"\n", a_ErrorDescription.c_str());
}
/** Called when the status line is fully parsed. */
virtual void OnStatusLine(const AString & a_StatusLine) override
{
printf("Status line: \"%s\"\n", a_StatusLine.c_str());
}
/** Called when a single header line is parsed. */
virtual void OnHeaderLine(const AString & a_Key, const AString & a_Value) override
{
printf("Header line: \"%s\": \"%s\"\n", a_Key.c_str(), a_Value.c_str());
}
/** Called when all the headers have been parsed. */
virtual void OnHeadersFinished(void) override
{
printf("Headers finished\n");
}
/** Called for each chunk of the incoming body data. */
virtual void OnBodyData(const void * a_Data, size_t a_Size) override
{
AString hexDump;
CreateHexDump(hexDump, a_Data, a_Size, 16);
printf("Body data: %u bytes\n%s", static_cast<unsigned>(a_Size), hexDump.c_str());
}
virtual void OnBodyFinished(void) override
{
printf("Body finished\n");
}
};
int main(int argc, char * argv[])
{
printf("HTTPResponseParser_file beginning\n");
// Open the input file:
if (argc <= 1)
{
printf("Usage: %s <filename> [<buffersize>]\n", argv[0]);
return 1;
}
FILE * f;
if (strcmp(argv[1], "-") == 0)
{
f = stdin;
}
else
{
f = fopen(argv[1], "rb");
if (f == nullptr)
{
printf("Cannot open file \"%s\". Aborting.\n", argv[1]);
return 2;
}
}
// If a third param is present, use it as the buffer size
size_t bufSize = MAX_BUF;
if (argc >= 3)
{
if (!StringToInteger(argv[2], bufSize) || (bufSize == 0))
{
bufSize = MAX_BUF;
printf("\"%s\" is not a valid buffer size, using the default of %u instead.\n", argv[2], static_cast<unsigned>(bufSize));
}
if (bufSize > MAX_BUF)
{
bufSize = MAX_BUF;
printf("\"%s\" is too large, maximum buffer size is %u. Using the size %u instead.\n", argv[2], static_cast<unsigned>(bufSize), static_cast<unsigned>(bufSize));
}
}
// Feed the file contents into the parser:
cCallbacks callbacks;
cHTTPResponseParser parser(callbacks);
while (!feof(f))
{
char buf[MAX_BUF];
auto numBytes = fread(buf, 1, bufSize, f);
if (numBytes == 0)
{
printf("Read 0 bytes from file (EOF?), terminating\n");
break;
}
auto numLeft = parser.Parse(buf, numBytes);
if (numLeft == AString::npos)
{
printf("Parser indicates there was an error, terminating parsing.\n");
break;
}
ASSERT(numLeft <= numBytes);
if (numLeft > 0)
{
printf("Parser indicates stream end, but there's more data (at least %u bytes) in the file.\n", static_cast<unsigned>(numLeft));
}
}
if (!parser.IsFinished())
{
printf("Parser indicates an incomplete stream.\n");
}
// Close the input file:
if (f != stdin)
{
fclose(f);
}
return 0;
}