lliohttpserver_tut.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:9k
源码类别:
游戏引擎
开发平台:
C++ Builder
- /**
- * @file lliohttpserver_tut.cpp
- * @date May 2006
- * @brief HTTP server unit tests
- *
- * $LicenseInfo:firstyear=2006&license=viewergpl$
- *
- * Copyright (c) 2006-2010, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #include "linden_common.h"
- #include "lltut.h"
- #include "llbufferstream.h"
- #include "lliohttpserver.h"
- #include "llsdhttpserver.h"
- #include "llsdserialize.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>);
- }
- 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.0rnrn";
- 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.0rn";
- httpRequest << "Content-Length: " << body.size() << "rn";
- httpRequest << "rn";
- 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 OKrn");
- ensure_contains("web/hello content type", result,
- "Content-Type: application/llsd+xmlrn");
- ensure_contains("web/hello content length", result,
- "Content-Length: 36rn");
- ensure_contains("web/hello content", result,
- "rn"
- "<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 Foundrn");
- actual = httpGET("web/echo");
- ensure_starts_with("web/echo 405", actual,
- "HTTP/1.0 405 Method Not Allowedrn");
- }
- 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 OKrn");
- ensure_contains("web/echo content type", result,
- "Content-Type: application/llsd+xmlrn");
- ensure_contains("web/echo content length", result,
- "Content-Length: 35rn");
- ensure_contains("web/hello content", result,
- "rn"
- "<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 OKrn"
- "Content-Length: 34rn"
- "rn"
- "<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 OKrn");
- ensure_contains("delayed/echo content", result,
- "rn"
- "<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] = ' ';
- //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>";
- llinfos << "HTTPServiceTestObject::test<7>"
- << stream.str().length() << llendl;
- std::string result = httpPOST("web/echo", stream.str());
- ensure_starts_with("large echo status", result, "HTTP/1.0 200 OKrn");
- }
- 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.0rnHost: localhostrnrn";
- bool timeout = false;
- std::string result = makeRequest("/", http_request.str(), timeout);
- ensure_starts_with("OPTIONS verb ok", result, "HTTP/1.0 200 OKrn");
- ensure_contains(
- "Doc url header exists",
- result,
- "X-Documentation-URL: http://localhost");
- }
- /* TO DO:
- test generation of not found and method not allowed errors
- */
- }