diff options
Diffstat (limited to 'lib/libUPnP/Platinum/Source/Tests/Http')
-rw-r--r-- | lib/libUPnP/Platinum/Source/Tests/Http/HttpTest.cpp | 526 |
1 files changed, 526 insertions, 0 deletions
diff --git a/lib/libUPnP/Platinum/Source/Tests/Http/HttpTest.cpp b/lib/libUPnP/Platinum/Source/Tests/Http/HttpTest.cpp new file mode 100644 index 0000000..00b1f52 --- /dev/null +++ b/lib/libUPnP/Platinum/Source/Tests/Http/HttpTest.cpp @@ -0,0 +1,526 @@ +/***************************************************************** +| +| Platinum - HTTP tests +| +| Copyright (c) 2004-2010, Plutinosoft, LLC. +| All rights reserved. +| http://www.plutinosoft.com +| +| This program is free software; you can redistribute it and/or +| modify it under the terms of the GNU General Public License +| as published by the Free Software Foundation; either version 2 +| of the License, or (at your option) any later version. +| +| OEMs, ISVs, VARs and other distributors that combine and +| distribute commercially licensed software with Platinum software +| and do not wish to distribute the source code for the commercially +| licensed software under version 2, or (at your option) any later +| version, of the GNU General Public License (the "GPL") must enter +| into a commercial license agreement with Plutinosoft, LLC. +| licensing@plutinosoft.com +| +| This program is distributed in the hope that it will be useful, +| but WITHOUT ANY WARRANTY; without even the implied warranty of +| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +| GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License +| along with this program; see the file LICENSE.txt. If not, write to +| the Free Software Foundation, Inc., +| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +| http://www.gnu.org/licenses/gpl-2.0.html +| +****************************************************************/ + +/*---------------------------------------------------------------------- +| includes ++---------------------------------------------------------------------*/ +#include "Neptune.h" +#include "PltTaskManager.h" +#include "PltHttpServer.h" +#include "PltDownloader.h" +#include "PltRingBufferStream.h" + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +NPT_SET_LOCAL_LOGGER("platinum.core.http.test") + +//#define TEST1 +//#define TEST2 +//#define TEST3 +//#define TEST4 +#define TEST5 + +/*---------------------------------------------------------------------- +| globals ++---------------------------------------------------------------------*/ +struct Options { + NPT_UInt32 port; + NPT_String path; +} Options; + +/*---------------------------------------------------------------------- +| PLT_HttpCustomRequestHandler ++---------------------------------------------------------------------*/ +class PLT_HttpCustomRequestHandler : public NPT_HttpRequestHandler +{ +public: + // constructors + PLT_HttpCustomRequestHandler(NPT_InputStreamReference& body, + const char* mime_type, + bool update_content_length = false) : + m_Body(body), + m_MimeType(mime_type), + m_UpdateContentLength(update_content_length) {} + + // NPT_HttpRequetsHandler methods + virtual NPT_Result SetupResponse(NPT_HttpRequest& request, + const NPT_HttpRequestContext& context, + NPT_HttpResponse& response) { + NPT_COMPILER_UNUSED(request); + NPT_COMPILER_UNUSED(context); + + NPT_HttpEntity* entity = response.GetEntity(); + if (entity == NULL) return NPT_ERROR_INVALID_STATE; + + entity->SetContentType(m_MimeType); + entity->SetInputStream(m_Body, m_UpdateContentLength); + + return NPT_SUCCESS; + } + +private: + NPT_InputStreamReference m_Body; + NPT_String m_MimeType; + bool m_UpdateContentLength; +}; + + +#ifdef TEST1 +/*---------------------------------------------------------------------- +| Test1 ++---------------------------------------------------------------------*/ +static bool +Test1(PLT_TaskManager* task_manager, NPT_HttpUrl url, NPT_Size& size) +{ + NPT_LOG_INFO("########### TEST 1 ######################"); + + NPT_MemoryStreamReference memory_stream(new NPT_MemoryStream()); + NPT_OutputStreamReference output_stream(memory_stream); + PLT_Downloader downloader(task_manager, url, output_stream); + downloader.Start(); + + while (1) { + switch(downloader.GetState()) { + case PLT_DOWNLOADER_SUCCESS: { + size = memory_stream->GetDataSize(); + return true; + } + + case PLT_DOWNLOADER_ERROR: + return false; + + default: + NPT_System::Sleep(NPT_TimeInterval(.1f)); + break; + } + }; + + return false; +} +#endif + +#ifdef TEST2 +/*---------------------------------------------------------------------- +| DumpBody ++---------------------------------------------------------------------*/ +static NPT_Result +ReadBody(PLT_Downloader& downloader, NPT_InputStreamReference& stream, NPT_Size& size) +{ + NPT_LargeSize avail; + char buffer[2048]; + NPT_Result ret = NPT_ERROR_WOULD_BLOCK; + + /* reset output param first */ + size = 0; + + /* + we test for availability first to avoid + getting stuck in Read forever in case blocking is true + and the download is done writing to the stream + */ + NPT_CHECK(stream->GetAvailable(avail)); + + if (avail) { + ret = stream->Read(buffer, 2048, &size); + NPT_LOG_FINER_2("Read %d bytes (result = %d)\n", size, ret); + return ret; + } else { + Plt_DowloaderState state = downloader.GetState(); + switch (state) { + case PLT_DOWNLOADER_ERROR: + return NPT_FAILURE; + + case PLT_DOWNLOADER_SUCCESS: + /* no more data expected */ + return NPT_ERROR_EOS; + + default: + NPT_System::Sleep(NPT_TimeInterval(.1f)); + break; + } + } + + return NPT_SUCCESS; +} + +/*---------------------------------------------------------------------- +| Test2 ++---------------------------------------------------------------------*/ +static bool +Test2(PLT_TaskManager* task_manager, NPT_HttpUrl url, NPT_Size& size) +{ + NPT_LOG_INFO("########### TEST 2 ######################"); + + /* reset output param first */ + size = 0; + + PLT_RingBufferStreamReference ringbuffer_stream(new PLT_RingBufferStream()); + NPT_OutputStreamReference output_stream(ringbuffer_stream); + NPT_InputStreamReference input_stream(ringbuffer_stream); + PLT_Downloader downloader(task_manager, url, output_stream); + downloader.Start(); + + while (1) { + switch(downloader.GetState()) { + case PLT_DOWNLOADER_SUCCESS: + ringbuffer_stream->SetEOS(); + /* fallthrough */ + + case PLT_DOWNLOADER_DOWNLOADING: { + NPT_Size bytes_read; + NPT_Result res = ReadBody(downloader, input_stream, bytes_read); + if (NPT_FAILED(res)) { + return (res==NPT_ERROR_EOS)?true:false; + } + size += bytes_read; + } + break; + + case PLT_DOWNLOADER_ERROR: + return false; + + default: + NPT_System::Sleep(NPT_TimeInterval(.1f)); + break; + } + }; + + return false; +} +#endif + + +#ifdef TEST3 +class RingBufferWriterTask : public PLT_ThreadTask +{ +public: + RingBufferWriterTask(PLT_RingBufferStreamReference& ringbuffer_stream) + : m_RingBufferStream(ringbuffer_stream) {} + + // PLT_ThreadTask methods + virtual void DoRun() { + char buffer[32768]; + m_RingBufferStream->WriteFully(buffer, 32768); + + /* mark as done */ + m_RingBufferStream->SetEOS(); + } + +private: + PLT_RingBufferStreamReference m_RingBufferStream; +}; + +/*---------------------------------------------------------------------- +| Test3 ++---------------------------------------------------------------------*/ +static bool +Test3(PLT_TaskManager* task_manager, NPT_HttpUrl url, PLT_RingBufferStreamReference& ringbuffer_stream, NPT_Size& size) +{ + NPT_LOG_INFO("########### TEST 3 ######################"); + + /* reset output param first */ + size = 0; + + NPT_MemoryStreamReference memory_stream(new NPT_MemoryStream()); + NPT_OutputStreamReference output_stream(memory_stream); + PLT_Downloader downloader(task_manager, url, output_stream); + downloader.Start(); + + /* asynchronously write onto ring buffer stream */ + task_manager->StartTask(new RingBufferWriterTask(ringbuffer_stream)); + + /* start pulling data */ + while (1) { + switch(downloader.GetState()) { + case PLT_DOWNLOADER_SUCCESS: + size = memory_stream->GetDataSize(); + return true; + + case PLT_DOWNLOADER_ERROR: + return false; + + default: + NPT_System::Sleep(NPT_TimeInterval(.1f)); + break; + } + }; + + return false; +} +#endif + +#ifdef TEST4 +class ClientStuckTask : public PLT_ThreadTask +{ +public: + ClientStuckTask(NPT_HttpUrl& url, NPT_HttpClient& client) + : m_Url(url), m_Client(client) {} + + // PLT_ThreadTask methods + virtual void DoRun() { + NPT_HttpRequest request(m_Url, NPT_HTTP_METHOD_GET); + NPT_HttpResponse* response = NULL; + m_Client.SendRequest(request, response); + } + + virtual void DoAbort() { + m_Client.Abort(); + } + +private: + NPT_HttpUrl m_Url; + NPT_HttpClient& m_Client; + bool m_Aborted; +}; +/*---------------------------------------------------------------------- +| Test4 ++---------------------------------------------------------------------*/ +static bool +Test4(PLT_TaskManager* task_manager, NPT_HttpUrl url, NPT_TimeInterval wait_before_kill) +{ + NPT_LOG_INFO("########### TEST 4 ######################"); + + NPT_HttpClient client; + + /* start task to asynchronously fetch url */ + ClientStuckTask* task = new ClientStuckTask(url, client); + task_manager->StartTask(task, NULL, false); + + /* wait a bit and abort client */ + NPT_System::Sleep(wait_before_kill); + + task->Kill(); + return true; +} +#endif + +#ifdef TEST5 +/*---------------------------------------------------------------------- +| Test5 ++---------------------------------------------------------------------*/ +static bool +Test5(NPT_HttpUrl url) +{ + NPT_LOG_INFO("########### TEST 5 ######################"); + + NPT_HttpClient client; + + // first request + NPT_HttpRequest request(url, NPT_HTTP_METHOD_POST, NPT_HTTP_PROTOCOL_1_1); + NPT_HttpEntity* request_entity = new NPT_HttpEntity(); + request_entity->SetInputStream("Testing"); + request.SetEntity(request_entity); + + NPT_HttpResponse* response = NULL; + client.SendRequest(request, response); + NPT_HttpEntity* entity = NULL; + if (response && (entity = response->GetEntity())) { + NPT_DataBuffer buffer; + if (NPT_FAILED(entity->Load(buffer))) return false; + } + + // try again + delete response; + response = NULL; + request_entity = new NPT_HttpEntity(); + request_entity->SetInputStream("Testing2"); + request.SetEntity(request_entity); + client.SendRequest(request, response); + entity = NULL; + if (response && (entity = response->GetEntity())) { + NPT_DataBuffer buffer; + if (NPT_FAILED(entity->Load(buffer))) return false; + } + + return true; +} +#endif + +/*---------------------------------------------------------------------- +| PrintUsageAndExit ++---------------------------------------------------------------------*/ +static void +PrintUsageAndExit(char** args) +{ + fprintf(stderr, "usage: %s [-p <port>] [-f <filepath>]\n", args[0]); + fprintf(stderr, "-p : optional server port\n"); + fprintf(stderr, "-f : optional local filepath to serve\n"); + exit(1); +} + +/*---------------------------------------------------------------------- +| ParseCommandLine ++---------------------------------------------------------------------*/ +static void +ParseCommandLine(char** args) +{ + const char* arg; + char** tmp = args+1; + + /* default values */ + Options.port = 0; + Options.path = ""; + + while ((arg = *tmp++)) { + if (Options.port == 0 && !strcmp(arg, "-p")) { + NPT_UInt32 port; + if (NPT_FAILED(NPT_ParseInteger32(*tmp++, port, false))) { + fprintf(stderr, "ERROR: invalid port\n"); + exit(1); + } + Options.port = port; + } else if (Options.path.IsEmpty() && !strcmp(arg, "-f")) { + Options.path = *tmp++; + } else { + fprintf(stderr, "ERROR: too many arguments\n"); + PrintUsageAndExit(args); + } + } +} + +/*---------------------------------------------------------------------- +| main ++---------------------------------------------------------------------*/ +int +main(int argc, char** argv) +{ + NPT_COMPILER_UNUSED(argc); + + NPT_HttpRequestHandler* handler; + NPT_Reference<NPT_DataBuffer> buffer; + bool result; + + /* parse command line */ + ParseCommandLine(argv); + + /* create http server */ + PLT_HttpServer http_server(Options.port?Options.port:8089); + NPT_String url; + + if (!Options.path.IsEmpty()) { + /* extract folder path */ + int index1 = Options.path.ReverseFind('\\'); + int index2 = Options.path.ReverseFind('/'); + if (index1 <= 0 && index2 <=0) { + fprintf(stderr, "ERROR: invalid path\n"); + exit(1); + } + + NPT_FileInfo info; + NPT_CHECK_SEVERE(NPT_File::GetInfo(Options.path, &info)); + + /* add file request handler */ + handler = new NPT_HttpFileRequestHandler( + Options.path.Left(index1>index2?index1:index2), + "/"); + http_server.AddRequestHandler(handler, "/", true); + + /* build url */ + url = "/" + Options.path.SubString((index1>index2?index1:index2)+1); + } else { + /* create random garbage data */ + buffer = new NPT_DataBuffer(32768); + buffer->SetDataSize(32768); + + /* add static handler */ + handler = new NPT_HttpStaticRequestHandler(buffer->GetData(), + buffer->GetDataSize(), + "application/octet-stream"); + http_server.AddRequestHandler(handler, "/test"); + + /* build url */ + url = "/test"; + } + + /* add custom handler */ + PLT_RingBufferStreamReference ringbuffer_stream(new PLT_RingBufferStream()); + NPT_InputStreamReference stream(ringbuffer_stream); + NPT_HttpRequestHandler* custom_handler = new PLT_HttpCustomRequestHandler(stream, "text/xml"); + http_server.AddRequestHandler(custom_handler, "/custom"); + + /* start server */ + NPT_CHECK_SEVERE(http_server.Start()); + + /* a task manager for the tests downloader */ + PLT_TaskManager task_manager; + + /* small delay to let the server start */ + NPT_System::Sleep(NPT_TimeInterval(1.f)); + + /* execute tests */ + NPT_Size size; + NPT_COMPILER_UNUSED(size); + +#ifdef TEST1 + result = Test1(&task_manager, NPT_HttpUrl("127.0.0.1", http_server.GetPort(), url), size); + if (!result) return -1; +#endif + +#ifdef TEST2 + result = Test2(&task_manager, NPT_HttpUrl("127.0.0.1", http_server.GetPort(), url), size); + if (!result) return -1; +#endif + +#ifdef TEST3 + result = Test3(&task_manager, NPT_HttpUrl("127.0.0.1", http_server.GetPort(), "/custom"), ringbuffer_stream, size); + if (!result) return -1; +#endif + +#ifdef TEST4 + result = Test4(&task_manager, NPT_HttpUrl("127.0.0.1", http_server.GetPort(), "/custom"), NPT_TimeInterval(.1f)); + if (!result) return -1; + + result = Test4(&task_manager, NPT_HttpUrl("127.0.0.1", http_server.GetPort(), "/custom"), NPT_TimeInterval(1.f)); + if (!result) return -1; + + result = Test4(&task_manager, NPT_HttpUrl("127.0.0.1", http_server.GetPort(), "/custom"), NPT_TimeInterval(2.f)); + if (!result) return -1; +#endif + +#ifdef TEST5 + result = Test5(NPT_HttpUrl("127.0.0.1", http_server.GetPort(), "/test")); + if (!result) return -1; +#endif + + NPT_System::Sleep(NPT_TimeInterval(1.f)); + + // abort server tasks that are waiting on ring buffer stream + ringbuffer_stream->Abort(); + + http_server.Stop(); + + return 0; +} |