lliohttpserver_tut.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:9k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file lliohttpserver_tut.cpp
  3.  * @date   May 2006
  4.  * @brief HTTP server unit tests
  5.  *
  6.  * $LicenseInfo:firstyear=2006&license=viewergpl$
  7.  * 
  8.  * Copyright (c) 2006-2010, Linden Research, Inc.
  9.  * 
  10.  * Second Life Viewer Source Code
  11.  * The source code in this file ("Source Code") is provided by Linden Lab
  12.  * to you under the terms of the GNU General Public License, version 2.0
  13.  * ("GPL"), unless you have obtained a separate licensing agreement
  14.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  15.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  16.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  17.  * 
  18.  * There are special exceptions to the terms and conditions of the GPL as
  19.  * it is applied to this Source Code. View the full text of the exception
  20.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  21.  * online at
  22.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  23.  * 
  24.  * By copying, modifying or distributing this software, you acknowledge
  25.  * that you have read and understood your obligations described above,
  26.  * and agree to abide by those obligations.
  27.  * 
  28.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  29.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  30.  * COMPLETENESS OR PERFORMANCE.
  31.  * $/LicenseInfo$
  32.  */
  33. #include "linden_common.h"
  34. #include "lltut.h"
  35. #include "llbufferstream.h"
  36. #include "lliohttpserver.h"
  37. #include "llsdhttpserver.h"
  38. #include "llsdserialize.h"
  39. #include "llpipeutil.h"
  40. namespace tut
  41. {
  42. class HTTPServiceTestData
  43. {
  44. public:
  45. class DelayedEcho : public LLHTTPNode
  46. {
  47. HTTPServiceTestData* mTester;
  48. public:
  49. DelayedEcho(HTTPServiceTestData* tester) : mTester(tester) { }
  50. void post(ResponsePtr response, const LLSD& context, const LLSD& input) const
  51. {
  52. ensure("response already set", mTester->mResponse == ResponsePtr(NULL));
  53. mTester->mResponse = response;
  54. mTester->mResult = input;
  55. }
  56. };
  57. class WireHello : public LLIOPipe
  58. {
  59. protected:
  60. virtual EStatus process_impl(
  61. const LLChannelDescriptors& channels,
  62. buffer_ptr_t& buffer,
  63. bool& eos,
  64. LLSD& context,
  65. LLPumpIO* pump)
  66. {
  67. if(!eos) return STATUS_BREAK;
  68. LLSD sd = "yo!";
  69. LLBufferStream ostr(channels, buffer.get());
  70. ostr << LLSDXMLStreamer(sd);
  71. return STATUS_DONE;
  72. }
  73. };
  74. HTTPServiceTestData()
  75. : mResponse(NULL)
  76. {
  77. LLHTTPStandardServices::useServices();
  78. LLHTTPRegistrar::buildAllServices(mRoot);
  79. mRoot.addNode("/delayed/echo", new DelayedEcho(this));
  80. mRoot.addNode("/wire/hello", new LLHTTPNodeForPipe<WireHello>);
  81. }
  82. LLHTTPNode mRoot;
  83. LLHTTPNode::ResponsePtr mResponse;
  84. LLSD mResult;
  85. void pumpPipe(LLPumpIO* pump, S32 iterations)
  86. {
  87. while(iterations > 0)
  88. {
  89. pump->pump();
  90. pump->callback();
  91. --iterations;
  92. }
  93. }
  94. std::string makeRequest(
  95. const std::string& name,
  96. const std::string& httpRequest,
  97. bool timeout = false)
  98. {
  99. LLPipeStringInjector* injector = new LLPipeStringInjector(httpRequest);
  100. LLPipeStringExtractor* extractor = new LLPipeStringExtractor();
  101. apr_pool_t* pool;
  102. apr_pool_create(&pool, NULL);
  103. LLPumpIO* pump;
  104. pump = new LLPumpIO(pool);
  105. LLPumpIO::chain_t chain;
  106. LLSD context;
  107. chain.push_back(LLIOPipe::ptr_t(injector));
  108. LLIOHTTPServer::createPipe(chain, mRoot, LLSD());
  109. chain.push_back(LLIOPipe::ptr_t(extractor));
  110. pump->addChain(chain, DEFAULT_CHAIN_EXPIRY_SECS);
  111. pumpPipe(pump, 10);
  112. if(mResponse.notNull() && (! timeout)) 
  113. {
  114. mResponse->result(mResult);
  115. mResponse = NULL;
  116. }
  117. pumpPipe(pump, 10);
  118. std::string httpResult = extractor->string();
  119. chain.clear();
  120. delete pump;
  121. apr_pool_destroy(pool);
  122. if(mResponse.notNull() && timeout)
  123. {
  124. mResponse->result(mResult);
  125. mResponse = NULL;
  126. }
  127. return httpResult;
  128. }
  129. std::string httpGET(const std::string& uri, 
  130. bool timeout = false)
  131. {
  132. std::string httpRequest = "GET " + uri + " HTTP/1.0rnrn";
  133. return makeRequest(uri, httpRequest, timeout);
  134. }
  135. std::string httpPOST(const std::string& uri,
  136. const std::string& body,
  137. bool timeout,
  138. const std::string& evilExtra = "")
  139. {
  140. std::ostringstream httpRequest;
  141. httpRequest << "POST " + uri + " HTTP/1.0rn";
  142. httpRequest << "Content-Length: " << body.size() << "rn";
  143. httpRequest << "rn";
  144. httpRequest << body;
  145. httpRequest << evilExtra;
  146. return makeRequest(uri, httpRequest.str(), timeout);
  147. }
  148. std::string httpPOST(const std::string& uri,
  149. const std::string& body,
  150. const std::string& evilExtra = "")
  151. {
  152. bool timeout = false;
  153. return httpPOST(uri, body, timeout, evilExtra);
  154. }
  155. };
  156. typedef test_group<HTTPServiceTestData> HTTPServiceTestGroup;
  157. typedef HTTPServiceTestGroup::object HTTPServiceTestObject;
  158. HTTPServiceTestGroup httpServiceTestGroup("http service");
  159. template<> template<>
  160. void HTTPServiceTestObject::test<1>()
  161. {
  162. std::string result = httpGET("web/hello");
  163. ensure_starts_with("web/hello status", result,
  164. "HTTP/1.0 200 OKrn");
  165. ensure_contains("web/hello content type", result,
  166. "Content-Type: application/llsd+xmlrn");
  167. ensure_contains("web/hello content length", result,
  168. "Content-Length: 36rn");
  169. ensure_contains("web/hello content", result,
  170. "rn"
  171. "<llsd><string>hello</string></llsd>"
  172. );
  173. }
  174. template<> template<>
  175. void HTTPServiceTestObject::test<2>()
  176. {
  177. // test various HTTP errors
  178. std::string actual;
  179. actual = httpGET("web/missing");
  180. ensure_starts_with("web/missing 404", actual,
  181. "HTTP/1.0 404 Not Foundrn");
  182. actual = httpGET("web/echo");
  183. ensure_starts_with("web/echo 405", actual,
  184. "HTTP/1.0 405 Method Not Allowedrn");
  185. }
  186. template<> template<>
  187. void HTTPServiceTestObject::test<3>()
  188. {
  189. // test POST & content-length handling
  190. std::string result;
  191. result = httpPOST("web/echo",
  192. "<llsd><integer>42</integer></llsd>");
  193. ensure_starts_with("web/echo status", result,
  194. "HTTP/1.0 200 OKrn");
  195. ensure_contains("web/echo content type", result,
  196. "Content-Type: application/llsd+xmlrn");
  197. ensure_contains("web/echo content length", result,
  198. "Content-Length: 35rn");
  199. ensure_contains("web/hello content", result,
  200. "rn"
  201. "<llsd><integer>42</integer></llsd>"
  202. );
  203. /* TO DO: this test doesn't pass!!
  204. result = httpPOST("web/echo",
  205. "<llsd><string>evil</string></llsd>",
  206. "really!  evil!!!");
  207. ensure_equals("web/echo evil result", result,
  208. "HTTP/1.0 200 OKrn"
  209. "Content-Length: 34rn"
  210. "rn"
  211. "<llsd><string>evil</string></llsd>"
  212. );
  213. */
  214. }
  215. template<> template<>
  216. void HTTPServiceTestObject::test<4>()
  217. {
  218. // test calling things based on pipes
  219. std::string result;
  220. result = httpGET("wire/hello");
  221. ensure_contains("wire/hello", result, "yo!");
  222. }
  223.     template<> template<>
  224. void HTTPServiceTestObject::test<5>()
  225.     {
  226. // test timeout before async response
  227. std::string result;
  228. bool timeout = true;
  229. result = httpPOST("delayed/echo",
  230. "<llsd><string>agent99</string></llsd>", timeout);
  231. ensure_equals("timeout delayed/echo status", result, std::string(""));
  232. }
  233. template<> template<>
  234. void HTTPServiceTestObject::test<6>()
  235. {
  236. // test delayed service
  237. std::string result;
  238. result = httpPOST("delayed/echo",
  239. "<llsd><string>agent99</string></llsd>");
  240. ensure_starts_with("delayed/echo status", result,
  241. "HTTP/1.0 200 OKrn");
  242. ensure_contains("delayed/echo content", result,
  243. "rn"
  244. "<llsd><string>agent99</string></llsd>"
  245. );
  246. }
  247. template<> template<>
  248. void HTTPServiceTestObject::test<7>()
  249. {
  250. // test large request
  251. std::stringstream stream;
  252. //U32 size = 36 * 1024 * 1024;
  253. //U32 size = 36 * 1024;
  254. //std::vector<char> data(size);
  255. //memset(&(data[0]), '1', size);
  256. //data[size - 1] = '';
  257. //std::string result = httpPOST("web/echo", &(data[0]));
  258. stream << "<llsd><array>";
  259. for(U32 i = 0; i < 1000000; ++i)
  260. {
  261. stream << "<integer>42</integer>";
  262. }
  263. stream << "</array></llsd>";
  264. llinfos << "HTTPServiceTestObject::test<7>"
  265. << stream.str().length() << llendl;
  266. std::string result = httpPOST("web/echo", stream.str());
  267. ensure_starts_with("large echo status", result, "HTTP/1.0 200 OKrn");
  268. }
  269. template<> template<>
  270. void HTTPServiceTestObject::test<8>()
  271. {
  272. // test the OPTIONS http method -- the default implementation
  273. // should return the X-Documentation-URL
  274. std::ostringstream http_request;
  275. http_request << "OPTIONS /  HTTP/1.0rnHost: localhostrnrn";
  276. bool timeout = false;
  277. std::string result = makeRequest("/", http_request.str(), timeout);
  278. ensure_starts_with("OPTIONS verb ok", result, "HTTP/1.0 200 OKrn");
  279. ensure_contains(
  280. "Doc url header exists",
  281. result,
  282. "X-Documentation-URL: http://localhost");
  283. }
  284. /* TO DO:
  285. test generation of not found and method not allowed errors
  286. */
  287. }