llhttpclient_tut.cpp

Go to the documentation of this file.
00001 
00038 #include <tut/tut.h>
00039 #include "linden_common.h"
00040 
00041 // These are too slow on Windows to actually include in the build. JC
00042 #if !LL_WINDOWS
00043 
00044 #include "lltut.h"
00045 #include "llhttpclient.h"
00046 #include "llformat.h"
00047 #include "llpipeutil.h"
00048 #include "llpumpio.h"
00049 
00050 #include "llsdhttpserver.h"
00051 #include "lliohttpserver.h"
00052 #include "lliosocket.h"
00053 
00054 namespace tut
00055 {
00056         LLSD storage;
00057         
00058         class LLSDStorageNode : public LLHTTPNode
00059         {
00060         public:
00061                 LLSD get() const                                        { return storage; }
00062                 LLSD put(const LLSD& value) const       { storage = value; return LLSD(); }
00063         };
00064 
00065         class ErrorNode : public LLHTTPNode
00066         {
00067         public:
00068                 void get(ResponsePtr r, const LLSD& context) const
00069                         { r->status(599, "Intentional error"); }
00070                 void post(ResponsePtr r, const LLSD& context, const LLSD& input) const
00071                         { r->status(input["status"], input["reason"]); }
00072         };
00073 
00074         class TimeOutNode : public LLHTTPNode
00075         {
00076         public:
00077                 void get(ResponsePtr r, const LLSD& context) const
00078                 {
00079             /* do nothing, the request will eventually time out */ 
00080                 }
00081         };
00082 
00083         LLHTTPRegistration<LLSDStorageNode> gStorageNode("/test/storage");
00084         LLHTTPRegistration<ErrorNode>           gErrorNode("/test/error");
00085         LLHTTPRegistration<TimeOutNode>         gTimeOutNode("/test/timeout");
00086 
00087         struct HTTPClientTestData
00088         {
00089         public:
00090                 HTTPClientTestData()
00091                 {
00092                         apr_pool_create(&mPool, NULL);
00093                         mServerPump = new LLPumpIO(mPool);
00094                         mClientPump = new LLPumpIO(mPool);
00095                         
00096                         LLHTTPClient::setPump(*mClientPump);
00097                 }
00098                 
00099                 ~HTTPClientTestData()
00100                 {
00101                         delete mServerPump;
00102                         delete mClientPump;
00103                         apr_pool_destroy(mPool);
00104                 }
00105 
00106                 void setupTheServer()
00107                 {
00108                         LLHTTPNode& root = LLIOHTTPServer::create(mPool, *mServerPump, 8888);
00109 
00110                         LLHTTPStandardServices::useServices();
00111                         LLHTTPRegistrar::buildAllServices(root);
00112                 }
00113                 
00114                 void runThePump(float timeout = 100.0f)
00115                 {
00116                         LLTimer timer;
00117                         timer.setTimerExpirySec(timeout);
00118 
00119                         while(!mSawCompleted && !timer.hasExpired())
00120                         {
00121                                 if (mServerPump)
00122                                 {
00123                                         mServerPump->pump();
00124                                         mServerPump->callback();
00125                                 }
00126                                 if (mClientPump)
00127                                 {
00128                                         mClientPump->pump();
00129                                         mClientPump->callback();
00130                                 }
00131                         }
00132                 }
00133 
00134                 void killServer()
00135                 {
00136                         delete mServerPump;
00137                         mServerPump = NULL;
00138                 }
00139         
00140         private:
00141                 apr_pool_t* mPool;
00142                 LLPumpIO* mServerPump;
00143                 LLPumpIO* mClientPump;
00144 
00145                 
00146         protected:
00147                 void ensureStatusOK()
00148                 {
00149                         if (mSawError)
00150                         {
00151                                 std::string msg =
00152                                         llformat("error() called when not expected, status %d",
00153                                                 mStatus); 
00154                                 fail(msg);
00155                         }
00156                 }
00157         
00158                 void ensureStatusError()
00159                 {
00160                         if (!mSawError)
00161                         {
00162                                 fail("error() wasn't called");
00163                         }
00164                 }
00165                 
00166                 LLSD getResult()
00167                 {
00168                         return mResult;
00169                 }
00170         
00171         protected:
00172                 bool mSawError;
00173                 U32 mStatus;
00174                 std::string mReason;
00175                 bool mSawCompleted;
00176                 LLSD mResult;
00177                 bool mResultDeleted;
00178 
00179                 class Result : public LLHTTPClient::Responder
00180                 {
00181                 protected:
00182                         Result(HTTPClientTestData& client)
00183                                 : mClient(client)
00184                         {
00185                         }
00186                 
00187                 public:
00188                         static boost::intrusive_ptr<Result> build(HTTPClientTestData& client)
00189                         {
00190                                 return boost::intrusive_ptr<Result>(new Result(client));
00191                         }
00192                         
00193                         ~Result()
00194                         {
00195                                 mClient.mResultDeleted = true;
00196                         }
00197                         
00198                         virtual void error(U32 status, const std::string& reason)
00199                         {
00200                                 mClient.mSawError = true;
00201                                 mClient.mStatus = status;
00202                                 mClient.mReason = reason;
00203                         }
00204 
00205                         virtual void result(const LLSD& content)
00206                         {
00207                                 mClient.mResult = content;
00208                         }
00209 
00210                         virtual void completed(
00211                                                         U32 status, const std::string& reason,
00212                                                         const LLSD& content)
00213                         {
00214                                 LLHTTPClient::Responder::completed(status, reason, content);
00215                                 
00216                                 mClient.mSawCompleted = true;
00217                         }
00218 
00219                 private:
00220                         HTTPClientTestData& mClient;
00221                 };
00222 
00223                 friend class Result;
00224 
00225         protected:
00226                 LLHTTPClient::ResponderPtr newResult()
00227                 {
00228                         mSawError = false;
00229                         mStatus = 0;
00230                         mSawCompleted = false;
00231                         mResult.clear();
00232                         mResultDeleted = false;
00233                         
00234                         return Result::build(*this);
00235                 }
00236         };
00237         
00238         
00239         typedef test_group<HTTPClientTestData>  HTTPClientTestGroup;
00240         typedef HTTPClientTestGroup::object             HTTPClientTestObject;
00241         HTTPClientTestGroup httpClientTestGroup("http_client");
00242 
00243         template<> template<>
00244         void HTTPClientTestObject::test<1>()
00245         {
00246                 LLHTTPClient::get("http://www.secondlife.com/", newResult());
00247                 runThePump();
00248                 ensureStatusOK();
00249                 ensure("result object wasn't destroyed", mResultDeleted);
00250         }
00251 
00252         template<> template<>
00253         void HTTPClientTestObject::test<2>()
00254         {
00255                 LLHTTPClient::get("http://www.invalid", newResult());
00256                 runThePump();
00257                 ensureStatusError();
00258         }
00259 
00260         template<> template<>
00261                 void HTTPClientTestObject::test<3>()
00262         {
00263                 LLSD sd;
00264 
00265                 sd["list"][0]["one"] = 1;
00266                 sd["list"][0]["two"] = 2;
00267                 sd["list"][1]["three"] = 3;
00268                 sd["list"][1]["four"] = 4;
00269                 
00270                 setupTheServer();
00271 
00272                 LLHTTPClient::post("http://localhost:8888/web/echo", sd, newResult());
00273                 runThePump();
00274                 ensureStatusOK();
00275                 ensure_equals("echoed result matches", getResult(), sd);
00276         }
00277 
00278         template<> template<>
00279                 void HTTPClientTestObject::test<4>()
00280         {
00281                 LLSD sd;
00282 
00283                 sd["message"] = "This is my test message.";
00284 
00285                 setupTheServer();
00286                 LLHTTPClient::put("http://localhost:8888/test/storage", sd, newResult());
00287                 runThePump();
00288                 ensureStatusOK();
00289 
00290                 LLHTTPClient::get("http://localhost:8888/test/storage", newResult());
00291                 runThePump();
00292                 ensureStatusOK();
00293                 ensure_equals("echoed result matches", getResult(), sd);
00294         
00295         }
00296 
00297         template<> template<>
00298                 void HTTPClientTestObject::test<5>()
00299         {
00300                 LLSD sd;
00301                 sd["status"] = 543;
00302                 sd["reason"] = "error for testing";
00303 
00304                 setupTheServer();
00305 
00306                 LLHTTPClient::post("http://localhost:8888/test/error", sd, newResult());
00307                 runThePump();
00308                 ensureStatusError();
00309                 ensure_contains("reason", mReason, sd["reason"]);
00310         }
00311 
00312         template<> template<>
00313                 void HTTPClientTestObject::test<6>()
00314         {
00315                 setupTheServer();
00316 
00317                 LLHTTPClient::get("http://localhost:8888/test/timeout", newResult());
00318                 runThePump(1.0f);
00319                 killServer();
00320                 runThePump();
00321                 ensureStatusError();
00322                 ensure_equals("reason", mReason, "STATUS_ERROR");
00323         }
00324 
00325         template<> template<>
00326                 void HTTPClientTestObject::test<7>()
00327         {
00328                 // Can not use the little mini server.  The blocking request won't ever let it run.
00329                 // Instead get from a known LLSD source and compare results with the non-blocking get
00330                 // which is tested against the mini server earlier.
00331                 LLSD expected;
00332 
00333                 LLHTTPClient::get("http://secondlife.com/xmlhttp/homepage.php", newResult());
00334                 runThePump();
00335                 ensureStatusOK();
00336                 expected = getResult();
00337 
00338                 LLSD result;
00339                 result = LLHTTPClient::blockingGet("http://secondlife.com/xmlhttp/homepage.php");
00340                 LLSD body = result["body"];
00341                 ensure_equals("echoed result matches", body.size(), expected.size());
00342         }
00343 
00344 }
00345 
00346 #endif  // !LL_WINDOWS

Generated on Thu Jul 1 06:08:42 2010 for Second Life Viewer by  doxygen 1.4.7