summaryrefslogtreecommitdiff
path: root/indra/llmessage/tests/lliohttpserver_test.cpp
diff options
context:
space:
mode:
authorRye <rye@alchemyviewer.org>2025-12-09 19:27:14 -0500
committerAndrey Kleshchev <117672381+akleshchev@users.noreply.github.com>2025-12-11 21:37:03 +0200
commit3b88739957d8b0d5072646e571d27b743e68fe2e (patch)
treee9cdd325e282735c1f3e7021bef7e8d0e983083b /indra/llmessage/tests/lliohttpserver_test.cpp
parent0e70989f6804f71a5efb2ff7e1352fb556321446 (diff)
Rework legacy lltest executable into individual integration tests and restore some disabled tests
Removes dead llprimlinkinfo and related test Remove dead llassetuploadqueue llhttpclient lltimestampcache lltranscode tests Remove dead mock_http_client Remove duplicate hex_dump.h Fix crash in LLDataPacker test
Diffstat (limited to 'indra/llmessage/tests/lliohttpserver_test.cpp')
-rw-r--r--indra/llmessage/tests/lliohttpserver_test.cpp350
1 files changed, 350 insertions, 0 deletions
diff --git a/indra/llmessage/tests/lliohttpserver_test.cpp b/indra/llmessage/tests/lliohttpserver_test.cpp
new file mode 100644
index 0000000000..7034f4a063
--- /dev/null
+++ b/indra/llmessage/tests/lliohttpserver_test.cpp
@@ -0,0 +1,350 @@
+/**
+ * @file lliohttpserver_tut.cpp
+ * @date May 2006
+ * @brief HTTP server unit tests
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "lltut.h"
+#include "llbufferstream.h"
+#include "lliohttpserver.h"
+#include "llsdhttpserver.h"
+#include "llsdserialize.h"
+#include "llcommon.h"
+
+#include "llpipeutil.h"
+
+
+namespace tut
+{
+ class HTTPServiceTestData
+ {
+ public:
+ class DelayedEcho : public LLHTTPNode
+ {
+ HTTPServiceTestData* mTester;
+
+ public:
+ DelayedEcho(HTTPServiceTestData* tester) : mTester(tester) { }
+
+ void post(ResponsePtr response, const LLSD& context, const LLSD& input) const
+ {
+ ensure("response already set", mTester->mResponse == ResponsePtr(NULL));
+ mTester->mResponse = response;
+ mTester->mResult = input;
+ }
+ };
+
+ class WireHello : public LLIOPipe
+ {
+ protected:
+ virtual EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
+ {
+ if(!eos) return STATUS_BREAK;
+ LLSD sd = "yo!";
+ LLBufferStream ostr(channels, buffer.get());
+ ostr << LLSDXMLStreamer(sd);
+ return STATUS_DONE;
+ }
+ };
+
+ HTTPServiceTestData()
+ : mResponse(NULL)
+ {
+ LLHTTPStandardServices::useServices();
+ LLHTTPRegistrar::buildAllServices(mRoot);
+ mRoot.addNode("/delayed/echo", new DelayedEcho(this));
+ mRoot.addNode("/wire/hello", new LLHTTPNodeForPipe<WireHello>);
+ }
+
+ ~HTTPServiceTestData()
+ {
+ }
+
+ LLHTTPNode mRoot;
+ LLHTTPNode::ResponsePtr mResponse;
+ LLSD mResult;
+
+ void pumpPipe(LLPumpIO* pump, S32 iterations)
+ {
+ while(iterations > 0)
+ {
+ pump->pump();
+ pump->callback();
+ --iterations;
+ }
+ }
+
+ std::string makeRequest(
+ const std::string& name,
+ const std::string& httpRequest,
+ bool timeout = false)
+ {
+ LLPipeStringInjector* injector = new LLPipeStringInjector(httpRequest);
+ LLPipeStringExtractor* extractor = new LLPipeStringExtractor();
+
+ apr_pool_t* pool;
+ apr_pool_create(&pool, NULL);
+
+ LLPumpIO* pump;
+ pump = new LLPumpIO(pool);
+
+ LLPumpIO::chain_t chain;
+ LLSD context;
+
+ chain.push_back(LLIOPipe::ptr_t(injector));
+ LLIOHTTPServer::createPipe(chain, mRoot, LLSD());
+ chain.push_back(LLIOPipe::ptr_t(extractor));
+
+ pump->addChain(chain, DEFAULT_CHAIN_EXPIRY_SECS);
+
+ pumpPipe(pump, 10);
+ if(mResponse.notNull() && (! timeout))
+ {
+ mResponse->result(mResult);
+ mResponse = NULL;
+ }
+ pumpPipe(pump, 10);
+
+ std::string httpResult = extractor->string();
+
+ chain.clear();
+ delete pump;
+ apr_pool_destroy(pool);
+
+ if(mResponse.notNull() && timeout)
+ {
+ mResponse->result(mResult);
+ mResponse = NULL;
+ }
+
+ return httpResult;
+ }
+
+ std::string httpGET(const std::string& uri,
+ bool timeout = false)
+ {
+ std::string httpRequest = "GET " + uri + " HTTP/1.0\r\n\r\n";
+ return makeRequest(uri, httpRequest, timeout);
+ }
+
+ std::string httpPOST(const std::string& uri,
+ const std::string& body,
+ bool timeout,
+ const std::string& evilExtra = "")
+ {
+ std::ostringstream httpRequest;
+ httpRequest << "POST " + uri + " HTTP/1.0\r\n";
+ httpRequest << "Content-Length: " << body.size() << "\r\n";
+ httpRequest << "\r\n";
+ httpRequest << body;
+ httpRequest << evilExtra;
+
+ return makeRequest(uri, httpRequest.str(), timeout);
+ }
+
+ std::string httpPOST(const std::string& uri,
+ const std::string& body,
+ const std::string& evilExtra = "")
+ {
+ bool timeout = false;
+ return httpPOST(uri, body, timeout, evilExtra);
+ }
+ };
+
+ typedef test_group<HTTPServiceTestData> HTTPServiceTestGroup;
+ typedef HTTPServiceTestGroup::object HTTPServiceTestObject;
+ HTTPServiceTestGroup httpServiceTestGroup("http service");
+
+ template<> template<>
+ void HTTPServiceTestObject::test<1>()
+ {
+ std::string result = httpGET("web/hello");
+
+ ensure_starts_with("web/hello status", result,
+ "HTTP/1.0 200 OK\r\n");
+
+ ensure_contains("web/hello content type", result,
+ "Content-Type: application/llsd+xml\r\n");
+
+ ensure_contains("web/hello content length", result,
+ "Content-Length: 36\r\n");
+
+ ensure_contains("web/hello content", result,
+ "\r\n"
+ "<llsd><string>hello</string></llsd>"
+ );
+ }
+
+ template<> template<>
+ void HTTPServiceTestObject::test<2>()
+ {
+ // test various HTTP errors
+
+ std::string actual;
+
+ actual = httpGET("web/missing");
+ ensure_starts_with("web/missing 404", actual,
+ "HTTP/1.0 404 Not Found\r\n");
+
+ actual = httpGET("web/echo");
+ ensure_starts_with("web/echo 405", actual,
+ "HTTP/1.0 405 Method Not Allowed\r\n");
+ }
+
+ template<> template<>
+ void HTTPServiceTestObject::test<3>()
+ {
+ // test POST & content-length handling
+
+ std::string result;
+
+ result = httpPOST("web/echo",
+ "<llsd><integer>42</integer></llsd>");
+
+ ensure_starts_with("web/echo status", result,
+ "HTTP/1.0 200 OK\r\n");
+
+ ensure_contains("web/echo content type", result,
+ "Content-Type: application/llsd+xml\r\n");
+
+ ensure_contains("web/echo content length", result,
+ "Content-Length: 35\r\n");
+
+ ensure_contains("web/hello content", result,
+ "\r\n"
+ "<llsd><integer>42</integer></llsd>"
+ );
+
+/* TO DO: this test doesn't pass!!
+
+ result = httpPOST("web/echo",
+ "<llsd><string>evil</string></llsd>",
+ "really! evil!!!");
+
+ ensure_equals("web/echo evil result", result,
+ "HTTP/1.0 200 OK\r\n"
+ "Content-Length: 34\r\n"
+ "\r\n"
+ "<llsd><string>evil</string></llsd>"
+ );
+*/
+ }
+
+ template<> template<>
+ void HTTPServiceTestObject::test<4>()
+ {
+ // test calling things based on pipes
+
+ std::string result;
+
+ result = httpGET("wire/hello");
+
+ ensure_contains("wire/hello", result, "yo!");
+ }
+
+ template<> template<>
+ void HTTPServiceTestObject::test<5>()
+ {
+ // test timeout before async response
+ std::string result;
+
+ bool timeout = true;
+ result = httpPOST("delayed/echo",
+ "<llsd><string>agent99</string></llsd>", timeout);
+
+ ensure_equals("timeout delayed/echo status", result, std::string(""));
+ }
+
+ template<> template<>
+ void HTTPServiceTestObject::test<6>()
+ {
+ // test delayed service
+ std::string result;
+
+ result = httpPOST("delayed/echo",
+ "<llsd><string>agent99</string></llsd>");
+
+ ensure_starts_with("delayed/echo status", result,
+ "HTTP/1.0 200 OK\r\n");
+
+ ensure_contains("delayed/echo content", result,
+ "\r\n"
+ "<llsd><string>agent99</string></llsd>"
+ );
+ }
+
+ template<> template<>
+ void HTTPServiceTestObject::test<7>()
+ {
+ // test large request
+ std::stringstream stream;
+
+ //U32 size = 36 * 1024 * 1024;
+ //U32 size = 36 * 1024;
+ //std::vector<char> data(size);
+ //memset(&(data[0]), '1', size);
+ //data[size - 1] = '\0';
+
+
+ //std::string result = httpPOST("web/echo", &(data[0]));
+
+ stream << "<llsd><array>";
+ for(U32 i = 0; i < 1000000; ++i)
+ {
+ stream << "<integer>42</integer>";
+ }
+ stream << "</array></llsd>";
+ LL_INFOS() << "HTTPServiceTestObject::test<7>"
+ << stream.str().length() << LL_ENDL;
+ std::string result = httpPOST("web/echo", stream.str());
+ ensure_starts_with("large echo status", result, "HTTP/1.0 200 OK\r\n");
+ }
+
+ template<> template<>
+ void HTTPServiceTestObject::test<8>()
+ {
+ // test the OPTIONS http method -- the default implementation
+ // should return the X-Documentation-URL
+ std::ostringstream http_request;
+ http_request << "OPTIONS / HTTP/1.0\r\nHost: localhost\r\n\r\n";
+ bool timeout = false;
+ std::string result = makeRequest("/", http_request.str(), timeout);
+ ensure_starts_with("OPTIONS verb ok", result, "HTTP/1.0 200 OK\r\n");
+ ensure_contains(
+ "Doc url header exists",
+ result,
+ "X-Documentation-URL: http://localhost");
+ }
+
+
+ /* TO DO:
+ test generation of not found and method not allowed errors
+ */
+}