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})
|
||||
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
|
||||
|
@ -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
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