/** * @file mock_http_client.cpp * @brief Framework for testing HTTP requests * * $LicenseInfo:firstyear=2007&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 "llsdhttpserver.h" #include "lliohttpserver.h" #include "llhttpclient.h" #include "llformat.h" #include "llpipeutil.h" #include "llpumpio.h" namespace tut { struct MockHttpClient { public: MockHttpClient() { apr_pool_create(&mPool, NULL); mServerPump = new LLPumpIO(mPool); mClientPump = new LLPumpIO(mPool); LLHTTPClient::setPump(*mClientPump); } ~MockHttpClient() { delete mServerPump; delete mClientPump; apr_pool_destroy(mPool); } void setupTheServer() { LLHTTPNode& root = LLIOHTTPServer::create(mPool, *mServerPump, 8888); LLHTTPStandardServices::useServices(); LLHTTPRegistrar::buildAllServices(root); } void runThePump(float timeout = 100.0f) { LLTimer timer; timer.setTimerExpirySec(timeout); while(!mSawCompleted && !timer.hasExpired()) { if (mServerPump) { mServerPump->pump(); mServerPump->callback(); } if (mClientPump) { mClientPump->pump(); mClientPump->callback(); } } } void killServer() { delete mServerPump; mServerPump = NULL; } private: apr_pool_t* mPool; LLPumpIO* mServerPump; LLPumpIO* mClientPump; protected: void ensureStatusOK() { if (mSawError) { std::string msg = llformat("error() called when not expected, status %d", mStatus); fail(msg); } } void ensureStatusError() { if (!mSawError) { fail("error() wasn't called"); } } LLSD getResult() { return mResult; } protected: bool mSawError; U32 mStatus; std::string mReason; bool mSawCompleted; LLSD mResult; bool mResultDeleted; class Result : public LLHTTPClient::Responder { protected: Result(MockHttpClient& client) : mClient(client) { } public: static boost::intrusive_ptr<Result> build(MockHttpClient& client) { return boost::intrusive_ptr<Result>(new Result(client)); } ~Result() { mClient.mResultDeleted = true; } virtual void error(U32 status, const std::string& reason) { mClient.mSawError = true; mClient.mStatus = status; mClient.mReason = reason; } virtual void result(const LLSD& content) { mClient.mResult = content; } virtual void completed( U32 status, const std::string& reason, const LLSD& content) { LLHTTPClient::Responder::completed(status, reason, content); mClient.mSawCompleted = true; } private: MockHttpClient& mClient; }; friend class Result; protected: void reset() { mSawError = false; mStatus = 0; mSawCompleted = false; mResult.clear(); mResultDeleted = false; } LLHTTPClient::ResponderPtr newResult() { reset(); return Result::build(*this); } }; }