Added unit test for parsing HTTP request.
This commit is contained in:
parent
fea556ca1b
commit
1d05fc95ae
4
.gitattributes
vendored
Normal file
4
.gitattributes
vendored
Normal 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
|
@ -263,6 +263,7 @@ if (MSVC)
|
|||||||
if (${SELF_TEST})
|
if (${SELF_TEST})
|
||||||
set_target_properties(
|
set_target_properties(
|
||||||
Network
|
Network
|
||||||
|
HTTP
|
||||||
PROPERTIES FOLDER Lib
|
PROPERTIES FOLDER Lib
|
||||||
)
|
)
|
||||||
set_target_properties(
|
set_target_properties(
|
||||||
@ -274,6 +275,7 @@ if (MSVC)
|
|||||||
creatable-exe
|
creatable-exe
|
||||||
EchoServer
|
EchoServer
|
||||||
Google-exe
|
Google-exe
|
||||||
|
HTTPResponseParser_file-exe
|
||||||
LoadablePieces
|
LoadablePieces
|
||||||
NameLookup
|
NameLookup
|
||||||
PROPERTIES FOLDER Tests
|
PROPERTIES FOLDER Tests
|
||||||
|
@ -9,5 +9,6 @@ endif()
|
|||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
add_subdirectory(ChunkData)
|
add_subdirectory(ChunkData)
|
||||||
|
add_subdirectory(HTTP)
|
||||||
add_subdirectory(Network)
|
add_subdirectory(Network)
|
||||||
add_subdirectory(LoadablePieces)
|
add_subdirectory(LoadablePieces)
|
||||||
|
46
tests/HTTP/CMakeLists.txt
Normal file
46
tests/HTTP/CMakeLists.txt
Normal 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)
|
9
tests/HTTP/HTTPResponse1.data
Normal file
9
tests/HTTP/HTTPResponse1.data
Normal 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
|
15
tests/HTTP/HTTPResponse2.data
Normal file
15
tests/HTTP/HTTPResponse2.data
Normal 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
|
||||||
|
|
153
tests/HTTP/HTTPResponseParser_file.cpp
Normal file
153
tests/HTTP/HTTPResponseParser_file.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user