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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llhttpclient_tut.cpp
  3.  * @brief Testing the HTTP client classes.
  4.  *
  5.  * $LicenseInfo:firstyear=2006&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2006-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. /**
  33.  *
  34.  * These classes test the HTTP client framework.
  35.  *
  36.  */
  37. #include <tut/tut.hpp>
  38. #include "linden_common.h"
  39. // These are too slow on Windows to actually include in the build. JC
  40. #if !LL_WINDOWS
  41. #include "lltut.h"
  42. #include "llhttpclient.h"
  43. #include "llformat.h"
  44. #include "llpipeutil.h"
  45. #include "llpumpio.h"
  46. #include "llsdhttpserver.h"
  47. #include "lliohttpserver.h"
  48. #include "lliosocket.h"
  49. namespace tut
  50. {
  51. LLSD storage;
  52. class LLSDStorageNode : public LLHTTPNode
  53. {
  54. public:
  55. LLSD simpleGet() const { return storage; }
  56. LLSD simplePut(const LLSD& value) const { storage = value; return LLSD(); }
  57. };
  58. class ErrorNode : public LLHTTPNode
  59. {
  60. public:
  61. void get(ResponsePtr r, const LLSD& context) const
  62. { r->status(599, "Intentional error"); }
  63. void post(ResponsePtr r, const LLSD& context, const LLSD& input) const
  64. { r->status(input["status"], input["reason"]); }
  65. };
  66. class TimeOutNode : public LLHTTPNode
  67. {
  68. public:
  69. void get(ResponsePtr r, const LLSD& context) const
  70. {
  71.             /* do nothing, the request will eventually time out */ 
  72. }
  73. };
  74. LLHTTPRegistration<LLSDStorageNode> gStorageNode("/test/storage");
  75. LLHTTPRegistration<ErrorNode> gErrorNode("/test/error");
  76. LLHTTPRegistration<TimeOutNode> gTimeOutNode("/test/timeout");
  77. struct HTTPClientTestData
  78. {
  79. public:
  80. HTTPClientTestData()
  81. {
  82. apr_pool_create(&mPool, NULL);
  83. mServerPump = new LLPumpIO(mPool);
  84. mClientPump = new LLPumpIO(mPool);
  85. LLHTTPClient::setPump(*mClientPump);
  86. }
  87. ~HTTPClientTestData()
  88. {
  89. delete mServerPump;
  90. delete mClientPump;
  91. apr_pool_destroy(mPool);
  92. }
  93. void setupTheServer()
  94. {
  95. LLHTTPNode& root = LLIOHTTPServer::create(mPool, *mServerPump, 8888);
  96. LLHTTPStandardServices::useServices();
  97. LLHTTPRegistrar::buildAllServices(root);
  98. }
  99. void runThePump(float timeout = 100.0f)
  100. {
  101. LLTimer timer;
  102. timer.setTimerExpirySec(timeout);
  103. while(!mSawCompleted && !mSawCompletedHeader && !timer.hasExpired())
  104. {
  105. if (mServerPump)
  106. {
  107. mServerPump->pump();
  108. mServerPump->callback();
  109. }
  110. if (mClientPump)
  111. {
  112. mClientPump->pump();
  113. mClientPump->callback();
  114. }
  115. }
  116. }
  117. void killServer()
  118. {
  119. delete mServerPump;
  120. mServerPump = NULL;
  121. }
  122. private:
  123. apr_pool_t* mPool;
  124. LLPumpIO* mServerPump;
  125. LLPumpIO* mClientPump;
  126. protected:
  127. void ensureStatusOK()
  128. {
  129. if (mSawError)
  130. {
  131. std::string msg =
  132. llformat("error() called when not expected, status %d",
  133. mStatus); 
  134. fail(msg);
  135. }
  136. }
  137. void ensureStatusError()
  138. {
  139. if (!mSawError)
  140. {
  141. fail("error() wasn't called");
  142. }
  143. }
  144. LLSD getResult()
  145. {
  146. return mResult;
  147. }
  148. LLSD getHeader()
  149. {
  150. return mHeader;
  151. }
  152. protected:
  153. bool mSawError;
  154. U32 mStatus;
  155. std::string mReason;
  156. bool mSawCompleted;
  157. bool mSawCompletedHeader;
  158. LLSD mResult;
  159. LLSD mHeader;
  160. bool mResultDeleted;
  161. class Result : public LLHTTPClient::Responder
  162. {
  163. protected:
  164. Result(HTTPClientTestData& client)
  165. : mClient(client)
  166. {
  167. }
  168. public:
  169. static boost::intrusive_ptr<Result> build(HTTPClientTestData& client)
  170. {
  171. return boost::intrusive_ptr<Result>(new Result(client));
  172. }
  173. ~Result()
  174. {
  175. mClient.mResultDeleted = true;
  176. }
  177. virtual void error(U32 status, const std::string& reason)
  178. {
  179. mClient.mSawError = true;
  180. mClient.mStatus = status;
  181. mClient.mReason = reason;
  182. }
  183. virtual void result(const LLSD& content)
  184. {
  185. mClient.mResult = content;
  186. }
  187. virtual void completed(
  188. U32 status, const std::string& reason,
  189. const LLSD& content)
  190. {
  191. LLHTTPClient::Responder::completed(status, reason, content);
  192. mClient.mSawCompleted = true;
  193. }
  194. virtual void completedHeader(
  195. U32 status, const std::string& reason,
  196. const LLSD& content)
  197. {
  198. mClient.mHeader = content;
  199. mClient.mSawCompletedHeader = true;
  200. }
  201. private:
  202. HTTPClientTestData& mClient;
  203. };
  204. friend class Result;
  205. protected:
  206. LLHTTPClient::ResponderPtr newResult()
  207. {
  208. mSawError = false;
  209. mStatus = 0;
  210. mSawCompleted = false;
  211. mSawCompletedHeader = false;
  212. mResult.clear();
  213. mHeader.clear();
  214. mResultDeleted = false;
  215. return Result::build(*this);
  216. }
  217. };
  218. typedef test_group<HTTPClientTestData> HTTPClientTestGroup;
  219. typedef HTTPClientTestGroup::object HTTPClientTestObject;
  220. HTTPClientTestGroup httpClientTestGroup("http_client");
  221. template<> template<>
  222. void HTTPClientTestObject::test<1>()
  223. {
  224. LLHTTPClient::get("http://www.google.com/", newResult());
  225. runThePump();
  226. ensureStatusOK();
  227. ensure("result object wasn't destroyed", mResultDeleted);
  228. }
  229. template<> template<>
  230. void HTTPClientTestObject::test<2>()
  231. {
  232. skip("error test depends on dev's local ISP not supplying "helpful" search page");
  233. LLHTTPClient::get("http://www.invalid", newResult());
  234. runThePump();
  235. ensureStatusError();
  236. }
  237. template<> template<>
  238. void HTTPClientTestObject::test<3>()
  239. {
  240. LLSD sd;
  241. sd["list"][0]["one"] = 1;
  242. sd["list"][0]["two"] = 2;
  243. sd["list"][1]["three"] = 3;
  244. sd["list"][1]["four"] = 4;
  245. setupTheServer();
  246. LLHTTPClient::post("http://localhost:8888/web/echo", sd, newResult());
  247. runThePump();
  248. ensureStatusOK();
  249. ensure_equals("echoed result matches", getResult(), sd);
  250. }
  251. template<> template<>
  252. void HTTPClientTestObject::test<4>()
  253. {
  254. LLSD sd;
  255. sd["message"] = "This is my test message.";
  256. setupTheServer();
  257. LLHTTPClient::put("http://localhost:8888/test/storage", sd, newResult());
  258. runThePump();
  259. ensureStatusOK();
  260. LLHTTPClient::get("http://localhost:8888/test/storage", newResult());
  261. runThePump();
  262. ensureStatusOK();
  263. ensure_equals("echoed result matches", getResult(), sd);
  264. }
  265. template<> template<>
  266. void HTTPClientTestObject::test<5>()
  267. {
  268. LLSD sd;
  269. sd["status"] = 543;
  270. sd["reason"] = "error for testing";
  271. setupTheServer();
  272. LLHTTPClient::post("http://localhost:8888/test/error", sd, newResult());
  273. runThePump();
  274. ensureStatusError();
  275. ensure_contains("reason", mReason, sd["reason"]);
  276. }
  277. template<> template<>
  278. void HTTPClientTestObject::test<6>()
  279. {
  280. setupTheServer();
  281. LLHTTPClient::get("http://localhost:8888/test/timeout", newResult());
  282. runThePump(1.0f);
  283. killServer();
  284. runThePump();
  285. ensureStatusError();
  286. ensure_equals("reason", mReason, "STATUS_ERROR");
  287. }
  288. template<> template<>
  289. void HTTPClientTestObject::test<7>()
  290. {
  291. // Can not use the little mini server.  The blocking request
  292. // won't ever let it run.  Instead get from a known LLSD
  293. // source and compare results with the non-blocking get which
  294. // is tested against the mini server earlier.
  295. skip("secondlife.com is not reliable enough for unit tests.");
  296. LLSD expected;
  297. LLHTTPClient::get("http://secondlife.com/xmlhttp/homepage.php", newResult());
  298. runThePump();
  299. ensureStatusOK();
  300. expected = getResult();
  301. LLSD result;
  302. result = LLHTTPClient::blockingGet("http://secondlife.com/xmlhttp/homepage.php");
  303. LLSD body = result["body"];
  304. ensure_equals("echoed result matches", body.size(), expected.size());
  305. }
  306. template<> template<>
  307. void HTTPClientTestObject::test<8>()
  308. {
  309. // This is testing for the presence of the Header in the returned results
  310. // from an HTTP::get call.
  311. LLHTTPClient::get("http://www.google.com/", newResult());
  312. runThePump();
  313. ensureStatusOK();
  314. LLSD header = getHeader();
  315. ensure_equals("got a header", header.emptyMap().asBoolean(), FALSE);
  316. }
  317. template<> template<>
  318. void HTTPClientTestObject::test<9>()
  319. {
  320. LLHTTPClient::head("http://www.google.com/", newResult());
  321. runThePump();
  322. ensureStatusOK();
  323. ensure("result object wasn't destroyed", mResultDeleted);
  324. }
  325. }
  326. #endif // !LL_WINDOWS