summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitattributes4
-rw-r--r--CMakeLists.txt2
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/HTTP/CMakeLists.txt46
-rw-r--r--tests/HTTP/HTTPResponse1.data9
-rw-r--r--tests/HTTP/HTTPResponse2.data15
-rw-r--r--tests/HTTP/HTTPResponseParser_file.cpp153
7 files changed, 230 insertions, 0 deletions
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 000000000..6470a6393
--- /dev/null
+++ b/.gitattributes
@@ -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
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3234e93d7..f84a81062 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index bdab4bc58..63eb8ae3a 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -9,5 +9,6 @@ endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
add_subdirectory(ChunkData)
+add_subdirectory(HTTP)
add_subdirectory(Network)
add_subdirectory(LoadablePieces)
diff --git a/tests/HTTP/CMakeLists.txt b/tests/HTTP/CMakeLists.txt
new file mode 100644
index 000000000..f6989d831
--- /dev/null
+++ b/tests/HTTP/CMakeLists.txt
@@ -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)
diff --git a/tests/HTTP/HTTPResponse1.data b/tests/HTTP/HTTPResponse1.data
new file mode 100644
index 000000000..b97e58afd
--- /dev/null
+++ b/tests/HTTP/HTTPResponse1.data
@@ -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
diff --git a/tests/HTTP/HTTPResponse2.data b/tests/HTTP/HTTPResponse2.data
new file mode 100644
index 000000000..d708c4758
--- /dev/null
+++ b/tests/HTTP/HTTPResponse2.data
@@ -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
+
diff --git a/tests/HTTP/HTTPResponseParser_file.cpp b/tests/HTTP/HTTPResponseParser_file.cpp
new file mode 100644
index 000000000..48ff928bc
--- /dev/null
+++ b/tests/HTTP/HTTPResponseParser_file.cpp
@@ -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;
+}
+
+
+
+