diff options
Diffstat (limited to 'indra/llmessage/tests')
24 files changed, 1010 insertions, 843 deletions
diff --git a/indra/llmessage/tests/commtest.h b/indra/llmessage/tests/commtest.h index 32035783e2..0d149b5258 100644..100755 --- a/indra/llmessage/tests/commtest.h +++ b/indra/llmessage/tests/commtest.h @@ -34,7 +34,67 @@ #include "llsd.h" #include "llhost.h" #include "stringize.h" +#include <map> #include <string> +#include <stdexcept> +#include <boost/lexical_cast.hpp> + +struct CommtestError: public std::runtime_error +{ + CommtestError(const std::string& what): std::runtime_error(what) {} +}; + +static bool query_verbose() +{ + const char* cbose = getenv("INTEGRATION_TEST_VERBOSE"); + if (! cbose) + { + cbose = "1"; + } + std::string strbose(cbose); + return (! (strbose == "0" || strbose == "off" || + strbose == "false" || strbose == "quiet")); +} + +bool verbose() +{ + // This should only be initialized once. + static bool vflag = query_verbose(); + return vflag; +} + +static int query_port(const std::string& var) +{ + const char* cport = getenv(var.c_str()); + if (! cport) + { + throw CommtestError(STRINGIZE("missing environment variable" << var)); + } + // This will throw, too, if the value of PORT isn't numeric. + int port(boost::lexical_cast<int>(cport)); + if (verbose()) + { + std::cout << "getport('" << var << "') = " << port << std::endl; + } + return port; +} + +static int getport(const std::string& var) +{ + typedef std::map<std::string, int> portsmap; + static portsmap ports; + // We can do this with a single map lookup with map::insert(). Either it + // returns an existing entry and 'false' (not newly inserted), or it + // inserts the specified value and 'true'. + std::pair<portsmap::iterator, bool> inserted(ports.insert(portsmap::value_type(var, 0))); + if (inserted.second) + { + // We haven't yet seen this var. Remember its value. + inserted.first->second = query_port(var); + } + // Return the (existing or new) iterator's value. + return inserted.first->second; +} /** * This struct is shared by a couple of standalone comm tests (ADD_COMM_BUILD_TEST). @@ -55,13 +115,21 @@ struct commtest_data replyPump("reply"), errorPump("error"), success(false), - host("127.0.0.1", 8000), + host("127.0.0.1", getport("PORT")), server(STRINGIZE("http://" << host.getString() << "/")) { replyPump.listen("self", boost::bind(&commtest_data::outcome, this, _1, true)); errorPump.listen("self", boost::bind(&commtest_data::outcome, this, _1, false)); } + static int getport(const std::string& var) + { + // We have a couple consumers of commtest_data::getport(). But we've + // since moved it out to the global namespace. So this is just a + // facade. + return ::getport(var); + } + bool outcome(const LLSD& _result, bool _success) { // std::cout << "commtest_data::outcome(" << _result << ", " << _success << ")\n"; diff --git a/indra/llmessage/tests/llareslistener_test.cpp b/indra/llmessage/tests/llareslistener_test.cpp index 60c91e12cf..c04696c86b 100644..100755 --- a/indra/llmessage/tests/llareslistener_test.cpp +++ b/indra/llmessage/tests/llareslistener_test.cpp @@ -135,7 +135,7 @@ namespace tut void object::test<2>() { set_test_name("bad op"); - WrapLL_ERRS capture; + WrapLLErrs capture; LLSD request; request["op"] = "foo"; std::string threw; @@ -143,7 +143,7 @@ namespace tut { LLEventPumps::instance().obtain("LLAres").post(request); } - catch (const WrapLL_ERRS::FatalException& e) + catch (const WrapLLErrs::FatalException& e) { threw = e.what(); } @@ -154,7 +154,7 @@ namespace tut void object::test<3>() { set_test_name("bad rewriteURI request"); - WrapLL_ERRS capture; + WrapLLErrs capture; LLSD request; request["op"] = "rewriteURI"; std::string threw; @@ -162,7 +162,7 @@ namespace tut { LLEventPumps::instance().obtain("LLAres").post(request); } - catch (const WrapLL_ERRS::FatalException& e) + catch (const WrapLLErrs::FatalException& e) { threw = e.what(); } @@ -175,7 +175,7 @@ namespace tut void object::test<4>() { set_test_name("bad rewriteURI request"); - WrapLL_ERRS capture; + WrapLLErrs capture; LLSD request; request["op"] = "rewriteURI"; request["reply"] = "nonexistent"; @@ -184,7 +184,7 @@ namespace tut { LLEventPumps::instance().obtain("LLAres").post(request); } - catch (const WrapLL_ERRS::FatalException& e) + catch (const WrapLLErrs::FatalException& e) { threw = e.what(); } @@ -197,7 +197,7 @@ namespace tut void object::test<5>() { set_test_name("bad rewriteURI request"); - WrapLL_ERRS capture; + WrapLLErrs capture; LLSD request; request["op"] = "rewriteURI"; request["uri"] = "foo.bar.com"; @@ -206,7 +206,7 @@ namespace tut { LLEventPumps::instance().obtain("LLAres").post(request); } - catch (const WrapLL_ERRS::FatalException& e) + catch (const WrapLLErrs::FatalException& e) { threw = e.what(); } diff --git a/indra/llmessage/tests/llavatarnamecache_test.cpp b/indra/llmessage/tests/llavatarnamecache_test.cpp index ec6b65d483..ec6b65d483 100644..100755 --- a/indra/llmessage/tests/llavatarnamecache_test.cpp +++ b/indra/llmessage/tests/llavatarnamecache_test.cpp diff --git a/indra/llmessage/tests/llcurl_stub.cpp b/indra/llmessage/tests/llcurl_stub.cpp index d84fe0a49f..b7fdf4f437 100644..100755 --- a/indra/llmessage/tests/llcurl_stub.cpp +++ b/indra/llmessage/tests/llcurl_stub.cpp @@ -24,72 +24,76 @@ * $/LicenseInfo$ */ +#ifndef LL_CURL_STUB_CPP +#define LL_CURL_STUB_CPP + + #include "linden_common.h" #include "llcurl.h" +#include "llhttpconstants.cpp" LLCurl::Responder::Responder() - : mReferenceCount(0) { } -void LLCurl::Responder::completed(U32 status, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const &reason, - LLSD const& mContent) +void LLCurl::Responder::httpCompleted() { - if (isGoodStatus(status)) + if (isGoodStatus()) { - result(mContent); + httpSuccess(); } else { - errorWithContent(status, reason, mContent); + httpFailure(); } } -void LLCurl::Responder::completedHeader(unsigned, - std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, - LLSD const&) +void LLCurl::Responder::completedRaw(LLChannelDescriptors const&, + boost::shared_ptr<LLBufferArray> const&) { } -void LLCurl::Responder::completedRaw(unsigned, - std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, - LLChannelDescriptors const&, - boost::shared_ptr<LLBufferArray> const&) +void LLCurl::Responder::httpFailure() { } -void LLCurl::Responder::errorWithContent(unsigned, - std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, - LLSD const&) +LLCurl::Responder::~Responder () { } -LLCurl::Responder::~Responder () +void LLCurl::Responder::httpSuccess() { } -void LLCurl::Responder::error(unsigned, - std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) +std::string LLCurl::Responder::dumpResponse() const { + return "dumpResponse()"; } -void LLCurl::Responder::result(LLSD const&) +void LLCurl::Responder::successResult(const LLSD& content) { + setResult(HTTP_OK, "", content); + httpSuccess(); } -namespace boost +void LLCurl::Responder::failureResult(S32 status, const std::string& reason, const LLSD& content) { - void intrusive_ptr_add_ref(LLCurl::Responder* p) - { - ++p->mReferenceCount; - } + setResult(status, reason, content); + httpFailure(); +} - void intrusive_ptr_release(LLCurl::Responder* p) - { - if(p && 0 == --p->mReferenceCount) - { - delete p; - } - } -}; +void LLCurl::Responder::completeResult(S32 status, const std::string& reason, const LLSD& content) +{ + setResult(status, reason, content); + httpCompleted(); +} + +void LLCurl::Responder::setResult(S32 status, const std::string& reason, const LLSD& content /* = LLSD() */) +{ + mStatus = status; + mReason = reason; + mContent = content; +} + +#endif diff --git a/indra/llmessage/tests/llhost_test.cpp b/indra/llmessage/tests/llhost_test.cpp index b20bceae1d..efca1bbfca 100644..100755 --- a/indra/llmessage/tests/llhost_test.cpp +++ b/indra/llmessage/tests/llhost_test.cpp @@ -151,10 +151,31 @@ namespace tut template<> template<> void host_object::test<9>() { + skip("this test is irreparably flaky"); // skip("setHostByName(\"google.com\"); getHostName() -> (e.g.) \"yx-in-f100.1e100.net\""); - std::string hostStr = "linux.org"; + // nat: is it reasonable to expect LLHost::getHostName() to echo + // back something resembling the string passed to setHostByName()? + // + // If that's not even reasonable, would a round trip in the /other/ + // direction make more sense? (Call getHostName() for something with + // known IP address; call setHostByName(); verify IP address) + // + // Failing that... is there a plausible way to test getHostName() and + // setHostByName()? Hopefully without putting up a dummy local DNS + // server? + + // monty: If you don't control the DNS server or the DNS configuration + // for the test point then, no, none of these will necessarily be + // reliable and may start to fail at any time. Forward translation + // is subject to CNAME records and round-robin address assignment. + // Reverse lookup is 1-to-many and is more and more likely to have + // nothing to do with the forward translation. + // + // So the test is increasingly meaningless on a real network. + + std::string hostStr = "lindenlab.com"; LLHost host; - host.setHostByName(hostStr); + host.setHostByName(hostStr); // reverse DNS will likely result in appending of some // sub-domain to the main hostname. so look for @@ -176,9 +197,9 @@ namespace tut template<> template<> void host_object::test<10>() { - std::string hostStr = "64.233.167.99"; + std::string hostStr = "64.233.167.99"; LLHost host; - host.setHostByName(hostStr); + host.setHostByName(hostStr); ensure("SetHostByName for dotted IP Address failed", host.getAddress() == ip_string_to_u32(hostStr.c_str())); } diff --git a/indra/llmessage/tests/llhttpclient_test.cpp b/indra/llmessage/tests/llhttpclient_test.cpp new file mode 100755 index 0000000000..a32bfa59ce --- /dev/null +++ b/indra/llmessage/tests/llhttpclient_test.cpp @@ -0,0 +1,309 @@ +/** + * @file llhttpclient_test.cpp + * @brief Testing the HTTP client classes. + * + * $LicenseInfo:firstyear=2006&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$ + */ + +/** + * + * These classes test the HTTP client framework. + * + */ + +#include <tut/tut.hpp> +#include "linden_common.h" + +#include "lltut.h" +#include "llhttpclient.h" +#include "llformat.h" +#include "llpipeutil.h" +#include "llproxy.h" +#include "llpumpio.h" + +#include "lliosocket.h" +#include "stringize.h" + +namespace tut +{ + struct HTTPClientTestData + { + public: + HTTPClientTestData(): + PORT(getenv("PORT")), + // Turning NULL PORT into empty string doesn't make things work; + // that's just to keep this initializer from blowing up. We test + // PORT separately in the constructor body. + local_server(STRINGIZE("http://127.0.0.1:" << (PORT? PORT : "") << "/")) + { + ensure("Set environment variable PORT to local test server port", PORT); + apr_pool_create(&mPool, NULL); + LLCurl::initClass(false); + mClientPump = new LLPumpIO(mPool); + + LLHTTPClient::setPump(*mClientPump); + } + + ~HTTPClientTestData() + { + delete mClientPump; + LLProxy::cleanupClass(); + apr_pool_destroy(mPool); + } + + void runThePump(float timeout = 100.0f) + { + LLTimer timer; + timer.setTimerExpirySec(timeout); + + while(!mSawCompleted && !mSawCompletedHeader && !timer.hasExpired()) + { + LLFrameTimer::updateFrameTime(); + if (mClientPump) + { + mClientPump->pump(); + mClientPump->callback(); + } + } + } + + const char* const PORT; + const std::string local_server; + + private: + apr_pool_t* mPool; + LLPumpIO* mClientPump; + + protected: + void ensureStatusOK() + { + if (mSawError) + { + std::string msg = + llformat("httpFailure() called when not expected, status %d", + mStatus); + fail(msg); + } + } + + void ensureStatusError() + { + if (!mSawError) + { + fail("httpFailure() wasn't called"); + } + } + + LLSD getResult() + { + return mResult; + } + LLSD getHeader() + { + return mHeader; + } + + protected: + bool mSawError; + U32 mStatus; + std::string mReason; + bool mSawCompleted; + bool mSawCompletedHeader; + LLSD mResult; + LLSD mHeader; + bool mResultDeleted; + + class Result : public LLHTTPClient::Responder + { + protected: + Result(HTTPClientTestData& client) + : mClient(client) + { + } + + public: + static Result* build(HTTPClientTestData& client) + { + return new Result(client); + } + + ~Result() + { + mClient.mResultDeleted = true; + } + + protected: + virtual void httpFailure() + { + mClient.mSawError = true; + mClient.mStatus = getStatus(); + mClient.mReason = getReason(); + } + + virtual void httpSuccess() + { + mClient.mResult = getContent(); + } + + virtual void httpCompleted() + { + LLHTTPClient::Responder::httpCompleted(); + + mClient.mSawCompleted = true; + mClient.mSawCompletedHeader = true; + mClient.mHeader = getResponseHeaders(); + } + + private: + HTTPClientTestData& mClient; + }; + + friend class Result; + + protected: + LLHTTPClient::ResponderPtr newResult() + { + mSawError = false; + mStatus = 0; + mSawCompleted = false; + mSawCompletedHeader = false; + mResult.clear(); + mHeader.clear(); + mResultDeleted = false; + + return Result::build(*this); + } + }; + + + typedef test_group<HTTPClientTestData> HTTPClientTestGroup; + typedef HTTPClientTestGroup::object HTTPClientTestObject; + HTTPClientTestGroup httpClientTestGroup("http_client"); + + template<> template<> + void HTTPClientTestObject::test<1>() + { + LLHTTPClient::get(local_server, newResult()); + runThePump(); + ensureStatusOK(); + ensure("result object wasn't destroyed", mResultDeleted); + } + + template<> template<> + void HTTPClientTestObject::test<2>() + { + // Please nobody listen on this particular port... + LLHTTPClient::get("http://127.0.0.1:7950", newResult()); + runThePump(); + ensureStatusError(); + } + + template<> template<> + void HTTPClientTestObject::test<3>() + { + LLSD sd; + + sd["list"][0]["one"] = 1; + sd["list"][0]["two"] = 2; + sd["list"][1]["three"] = 3; + sd["list"][1]["four"] = 4; + + LLHTTPClient::post(local_server + "web/echo", sd, newResult()); + runThePump(); + ensureStatusOK(); + ensure_equals("echoed result matches", getResult(), sd); + } + + template<> template<> + void HTTPClientTestObject::test<4>() + { + LLSD sd; + + sd["message"] = "This is my test message."; + + LLHTTPClient::put(local_server + "test/storage", sd, newResult()); + runThePump(); + ensureStatusOK(); + + LLHTTPClient::get(local_server + "test/storage", newResult()); + runThePump(); + ensureStatusOK(); + ensure_equals("echoed result matches", getResult(), sd); + + } + + template<> template<> + void HTTPClientTestObject::test<5>() + { + LLSD sd; + sd["status"] = 543; + sd["reason"] = "error for testing"; + + LLHTTPClient::post(local_server + "test/error", sd, newResult()); + runThePump(); + ensureStatusError(); + ensure_contains("reason", mReason, sd["reason"]); + } + + template<> template<> + void HTTPClientTestObject::test<6>() + { + const F32 timeout = 1.0f; + LLHTTPClient::get(local_server + "test/timeout", newResult(), LLSD(), timeout); + runThePump(timeout * 5.0f); + ensureStatusError(); + ensure_equals("reason", mReason, "STATUS_EXPIRED"); + } + + template<> template<> + void HTTPClientTestObject::test<7>() + { + LLHTTPClient::get(local_server, newResult()); + runThePump(); + ensureStatusOK(); + LLSD expected = getResult(); + + LLSD result; + result = LLHTTPClient::blockingGet(local_server); + LLSD body = result["body"]; + ensure_equals("echoed result matches", body.size(), expected.size()); + } + template<> template<> + void HTTPClientTestObject::test<8>() + { + // This is testing for the presence of the Header in the returned results + // from an HTTP::get call. + LLHTTPClient::get(local_server, newResult()); + runThePump(); + ensureStatusOK(); + LLSD header = getHeader(); + ensure("got a header", ! header.emptyMap().asBoolean()); + } + template<> template<> + void HTTPClientTestObject::test<9>() + { + LLHTTPClient::head(local_server, newResult()); + runThePump(); + ensureStatusOK(); + ensure("result object wasn't destroyed", mResultDeleted); + } +} diff --git a/indra/llmessage/tests/llhttpclientadapter_test.cpp b/indra/llmessage/tests/llhttpclientadapter_test.cpp index 13ce0a0edd..e9ce116bb3 100644..100755 --- a/indra/llmessage/tests/llhttpclientadapter_test.cpp +++ b/indra/llmessage/tests/llhttpclientadapter_test.cpp @@ -1,6 +1,6 @@ /** - * @file - * @brief + * @file llhttpclientadapter_test.cpp + * @brief Tests for LLHTTPClientAdapter * * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code @@ -33,8 +33,8 @@ float const HTTP_REQUEST_EXPIRY_SECS = 1.0F; std::vector<std::string> get_urls; -std::vector<boost::intrusive_ptr<LLCurl::Responder> > get_responders; -void LLHTTPClient::get(const std::string& url, boost::intrusive_ptr<LLCurl::Responder> responder, const LLSD& headers, const F32 timeout) +std::vector< LLCurl::ResponderPtr > get_responders; +void LLHTTPClient::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers, const F32 timeout, bool follow_redirects) { get_urls.push_back(url); get_responders.push_back(responder); @@ -42,16 +42,30 @@ void LLHTTPClient::get(const std::string& url, boost::intrusive_ptr<LLCurl::Resp std::vector<std::string> put_urls; std::vector<LLSD> put_body; -std::vector<boost::intrusive_ptr<LLCurl::Responder> > put_responders; +std::vector<LLSD> put_headers; +std::vector<LLCurl::ResponderPtr> put_responders; -void LLHTTPClient::put(const std::string& url, const LLSD& body, boost::intrusive_ptr<LLCurl::Responder> responder, const LLSD& headers, const F32 timeout) +void LLHTTPClient::put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder, const LLSD& headers, const F32 timeout) { put_urls.push_back(url); put_responders.push_back(responder); put_body.push_back(body); + put_headers.push_back(headers); } +std::vector<std::string> delete_urls; +std::vector<LLCurl::ResponderPtr> delete_responders; + +void LLHTTPClient::del( + const std::string& url, + LLCurl::ResponderPtr responder, + const LLSD& headers, + const F32 timeout) +{ + delete_urls.push_back(url); + delete_responders.push_back(responder); +} namespace tut { @@ -64,6 +78,9 @@ namespace tut put_urls.clear(); put_responders.clear(); put_body.clear(); + put_headers.clear(); + delete_urls.clear(); + delete_responders.clear(); } }; @@ -73,7 +90,7 @@ namespace tut namespace { - tut::factory tf("LLHTTPClientAdapterData test"); + tut::factory tf("LLHTTPClientAdapterData"); } namespace tut @@ -91,7 +108,7 @@ namespace tut { LLHTTPClientAdapter adapter; - boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder(); + LLCurl::ResponderPtr responder = new LLCurl::Responder(); adapter.get("Made up URL", responder); ensure_equals(get_urls.size(), 1); @@ -103,7 +120,7 @@ namespace tut void object::test<3>() { LLHTTPClientAdapter adapter; - boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder(); + LLCurl::ResponderPtr responder = new LLCurl::Responder(); adapter.get("Made up URL", responder); @@ -117,7 +134,7 @@ namespace tut { LLHTTPClientAdapter adapter; - boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder(); + LLCurl::ResponderPtr responder = new LLCurl::Responder(); LLSD body; body["TestBody"] = "Foobar"; @@ -133,7 +150,7 @@ namespace tut { LLHTTPClientAdapter adapter; - boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder(); + LLCurl::ResponderPtr responder = new LLCurl::Responder(); LLSD body; body["TestBody"] = "Foobar"; @@ -150,7 +167,7 @@ namespace tut { LLHTTPClientAdapter adapter; - boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder(); + LLCurl::ResponderPtr responder = new LLCurl::Responder(); LLSD body; body["TestBody"] = "Foobar"; @@ -160,5 +177,45 @@ namespace tut ensure_equals(put_body.size(), 1); ensure_equals(put_body[0]["TestBody"].asString(), "Foobar"); } + + // Ensure that headers are passed through put properly + template<> template<> + void object::test<7>() + { + LLHTTPClientAdapter adapter; + + LLCurl::ResponderPtr responder = new LLCurl::Responder(); + + LLSD body = LLSD::emptyMap(); + body["TestBody"] = "Foobar"; + + LLSD headers = LLSD::emptyMap(); + headers["booger"] = "omg"; + + adapter.put("Made up URL", body, responder, headers); + + ensure_equals("Header count", put_headers.size(), 1); + ensure_equals( + "First header", + put_headers[0]["booger"].asString(), + "omg"); + } + + // Ensure that del() passes appropriate arguments to the LLHTTPClient + template<> template<> + void object::test<8>() + { + LLHTTPClientAdapter adapter; + + LLCurl::ResponderPtr responder = new LLCurl::Responder(); + + adapter.del("Made up URL", responder); + + ensure_equals("URL count", delete_urls.size(), 1); + ensure_equals("Received URL", delete_urls[0], "Made up URL"); + + ensure_equals("Responder count", delete_responders.size(), 1); + //ensure_equals("Responder", delete_responders[0], responder); + } } diff --git a/indra/llmessage/tests/llhttpnode_stub.cpp b/indra/llmessage/tests/llhttpnode_stub.cpp new file mode 100755 index 0000000000..479a256bdd --- /dev/null +++ b/indra/llmessage/tests/llhttpnode_stub.cpp @@ -0,0 +1,107 @@ +/** + * @file llhttpnode_stub.cpp + * @brief STUB Implementation of classes for generic HTTP/LSL/REST handling. + * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ + * + * Second Life Viewer Source Code + * Copyright (c) 2006-2009, 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 "linden_common.h" +#include "llhttpnode.h" + +const std::string CONTEXT_VERB("verb"); +const std::string CONTEXT_REQUEST("request"); +const std::string CONTEXT_WILDCARD("wildcard"); +const std::string CONTEXT_PATH("path"); +const std::string CONTEXT_QUERY_STRING("query-string"); +const std::string CONTEXT_REMOTE_HOST("remote-host"); +const std::string CONTEXT_REMOTE_PORT("remote-port"); +const std::string CONTEXT_HEADERS("headers"); +const std::string CONTEXT_RESPONSE("response"); + +/** + * LLHTTPNode + */ +class LLHTTPNode::Impl +{ + // dummy +}; + +LLHTTPNode::LLHTTPNode(): impl(*new Impl) {} +LLHTTPNode::~LLHTTPNode() {} +LLSD LLHTTPNode::simpleGet() const { return LLSD(); } +LLSD LLHTTPNode::simplePut(const LLSD& input) const { return LLSD(); } +LLSD LLHTTPNode::simplePost(const LLSD& input) const { return LLSD(); } +LLSD LLHTTPNode::simpleDel(const LLSD&) const { return LLSD(); } +void LLHTTPNode::get(LLHTTPNode::ResponsePtr response, const LLSD& context) const {} +void LLHTTPNode::put(LLHTTPNode::ResponsePtr response, const LLSD& context, const LLSD& input) const {} +void LLHTTPNode::post(LLHTTPNode::ResponsePtr response, const LLSD& context, const LLSD& input) const {} +void LLHTTPNode::del(LLHTTPNode::ResponsePtr response, const LLSD& context) const {} +void LLHTTPNode::options(ResponsePtr response, const LLSD& context) const {} +LLHTTPNode* LLHTTPNode::getChild(const std::string& name, LLSD& context) const { return NULL; } +bool LLHTTPNode::handles(const LLSD& remainder, LLSD& context) const { return false; } +bool LLHTTPNode::validate(const std::string& name, LLSD& context) const { return false; } +const LLHTTPNode* LLHTTPNode::traverse(const std::string& path, LLSD& context) const { return NULL; } +void LLHTTPNode::addNode(const std::string& path, LLHTTPNode* nodeToAdd) { } +LLSD LLHTTPNode::allNodePaths() const { return LLSD(); } +const LLHTTPNode* LLHTTPNode::rootNode() const { return NULL; } +const LLHTTPNode* LLHTTPNode::findNode(const std::string& name) const { return NULL; } + +LLHTTPNode::Response::~Response(){} +void LLHTTPNode::Response::notFound(const std::string& message) +{ + status(404, message); +} +void LLHTTPNode::Response::notFound() +{ + status(404, "Not Found"); +} +void LLHTTPNode::Response::methodNotAllowed() +{ + status(405, "Method Not Allowed"); +} +void LLHTTPNode::Response::statusUnknownError(S32 code) +{ + status(code, "Unknown Error"); +} + +void LLHTTPNode::Response::status(S32 code, const std::string& message) +{ +} + +void LLHTTPNode::Response::addHeader(const std::string& name,const std::string& value) +{ + mHeaders[name] = value; +} +void LLHTTPNode::describe(Description& desc) const { } + + +const LLChainIOFactory* LLHTTPNode::getProtocolHandler() const { return NULL; } + + +LLHTTPRegistrar::NodeFactory::~NodeFactory() { } + +void LLHTTPRegistrar::registerFactory( + const std::string& path, NodeFactory& factory) {} +void LLHTTPRegistrar::buildAllServices(LLHTTPNode& root) {} + + diff --git a/indra/llmessage/tests/llmime_test.cpp b/indra/llmessage/tests/llmime_test.cpp deleted file mode 100644 index aed5c4589c..0000000000 --- a/indra/llmessage/tests/llmime_test.cpp +++ /dev/null @@ -1,445 +0,0 @@ -/** - * @file llmime_test.cpp - * @author Phoenix - * @date 2006-12-24 - * @brief BRIEF_DESC of llmime_test.cpp - * - * $LicenseInfo:firstyear=2006&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 "linden_common.h" - -#include "llsdserialize.h" - -#include "../llmime.h" - -#include "../test/lltut.h" - -namespace tut -{ - struct mime_index - { - }; - typedef test_group<mime_index> mime_index_t; - typedef mime_index_t::object mime_index_object_t; - tut::mime_index_t tut_mime_index("LLMime"); - - template<> template<> - void mime_index_object_t::test<1>() - { - LLMimeIndex mime; - ensure("no headers", mime.headers().isUndefined()); - ensure_equals("invalid offset", mime.offset(), -1); - ensure_equals("invalid content length", mime.contentLength(), -1); - ensure("no content type", mime.contentType().empty()); - ensure("not multipart", !mime.isMultipart()); - ensure_equals("no attachments", mime.subPartCount(), 0); - } - - template<> template<> - void mime_index_object_t::test<2>() - { - const S32 CONTENT_LENGTH = 6000; - const S32 CONTENT_OFFSET = 100; - const std::string CONTENT_TYPE = std::string("image/j2c"); - LLSD headers; - headers["Content-Length"] = CONTENT_LENGTH; - headers["Content-Type"] = CONTENT_TYPE; - LLMimeIndex mime(headers, CONTENT_OFFSET); - ensure("headers are map", mime.headers().isMap()); - ensure_equals("offset", mime.offset(), CONTENT_OFFSET); - ensure_equals("content length", mime.contentLength(), CONTENT_LENGTH); - ensure_equals("type is image/j2c", mime.contentType(), CONTENT_TYPE); - ensure("not multipart", !mime.isMultipart()); - ensure_equals("no attachments", mime.subPartCount(), 0); - } - - template<> template<> - void mime_index_object_t::test<3>() - { - const S32 MULTI_CONTENT_LENGTH = 8000; - const S32 MULTI_CONTENT_OFFSET = 100; - const std::string MULTI_CONTENT_TYPE = std::string("multipart/mixed"); - LLSD headers; - headers["Content-Length"] = MULTI_CONTENT_LENGTH; - headers["Content-Type"] = MULTI_CONTENT_TYPE; - LLMimeIndex mime(headers, MULTI_CONTENT_OFFSET); - llinfos << "headers: " << LLSDOStreamer<LLSDNotationFormatter>(headers) - << llendl; - - - const S32 META_CONTENT_LENGTH = 700; - const S32 META_CONTENT_OFFSET = 69; - const std::string META_CONTENT_TYPE = std::string( - "text/llsd+xml"); - headers = LLSD::emptyMap(); - headers["Content-Length"] = META_CONTENT_LENGTH; - headers["Content-Type"] = META_CONTENT_TYPE; - LLMimeIndex meta(headers, META_CONTENT_OFFSET); - mime.attachSubPart(meta); - - const S32 IMAGE_CONTENT_LENGTH = 6000; - const S32 IMAGE_CONTENT_OFFSET = 200; - const std::string IMAGE_CONTENT_TYPE = std::string("image/j2c"); - headers = LLSD::emptyMap(); - headers["Content-Length"] = IMAGE_CONTENT_LENGTH; - headers["Content-Type"] = IMAGE_CONTENT_TYPE; - LLMimeIndex image(headers, IMAGE_CONTENT_OFFSET); - mime.attachSubPart(image); - - // make sure we have a valid multi-part - ensure("is multipart", mime.isMultipart()); - ensure_equals("multi offset", mime.offset(), MULTI_CONTENT_OFFSET); - ensure_equals( - "multi content length", - mime.contentLength(), - MULTI_CONTENT_LENGTH); - ensure_equals("two attachments", mime.subPartCount(), 2); - - // make sure ranged gets do the right thing with out of bounds - // sub-parts. - LLMimeIndex invalid_child(mime.subPart(-1)); - ensure("no headers", invalid_child.headers().isUndefined()); - ensure_equals("invalid offset", invalid_child.offset(), -1); - ensure_equals( - "invalid content length", invalid_child.contentLength(), -1); - ensure("no content type", invalid_child.contentType().empty()); - ensure("not multipart", !invalid_child.isMultipart()); - ensure_equals("no attachments", invalid_child.subPartCount(), 0); - - invalid_child = mime.subPart(2); - ensure("no headers", invalid_child.headers().isUndefined()); - ensure_equals("invalid offset", invalid_child.offset(), -1); - ensure_equals( - "invalid content length", invalid_child.contentLength(), -1); - ensure("no content type", invalid_child.contentType().empty()); - ensure("not multipart", !invalid_child.isMultipart()); - ensure_equals("no attachments", invalid_child.subPartCount(), 0); - } - - template<> template<> - void mime_index_object_t::test<4>() - { - const S32 MULTI_CONTENT_LENGTH = 8000; - const S32 MULTI_CONTENT_OFFSET = 100; - const std::string MULTI_CONTENT_TYPE = std::string("multipart/mixed"); - LLSD headers; - headers["Content-Length"] = MULTI_CONTENT_LENGTH; - headers["Content-Type"] = MULTI_CONTENT_TYPE; - LLMimeIndex mime(headers, MULTI_CONTENT_OFFSET); - - const S32 META_CONTENT_LENGTH = 700; - const S32 META_CONTENT_OFFSET = 69; - const std::string META_CONTENT_TYPE = std::string( - "application/llsd+xml"); - headers = LLSD::emptyMap(); - headers["Content-Length"] = META_CONTENT_LENGTH; - headers["Content-Type"] = META_CONTENT_TYPE; - LLMimeIndex meta(headers, META_CONTENT_OFFSET); - mime.attachSubPart(meta); - - const S32 IMAGE_CONTENT_LENGTH = 6000; - const S32 IMAGE_CONTENT_OFFSET = 200; - const std::string IMAGE_CONTENT_TYPE = std::string("image/j2c"); - headers = LLSD::emptyMap(); - headers["Content-Length"] = IMAGE_CONTENT_LENGTH; - headers["Content-Type"] = IMAGE_CONTENT_TYPE; - LLMimeIndex image(headers, IMAGE_CONTENT_OFFSET); - mime.attachSubPart(image); - - // check what we have - ensure("is multipart", mime.isMultipart()); - ensure_equals("multi offset", mime.offset(), MULTI_CONTENT_OFFSET); - ensure_equals( - "multi content length", - mime.contentLength(), - MULTI_CONTENT_LENGTH); - ensure_equals("two attachments", mime.subPartCount(), 2); - - LLMimeIndex actual_meta = mime.subPart(0); - ensure_equals( - "meta type", actual_meta.contentType(), META_CONTENT_TYPE); - ensure_equals( - "meta offset", actual_meta.offset(), META_CONTENT_OFFSET); - ensure_equals( - "meta content length", - actual_meta.contentLength(), - META_CONTENT_LENGTH); - - LLMimeIndex actual_image = mime.subPart(1); - ensure_equals( - "image type", actual_image.contentType(), IMAGE_CONTENT_TYPE); - ensure_equals( - "image offset", actual_image.offset(), IMAGE_CONTENT_OFFSET); - ensure_equals( - "image content length", - actual_image.contentLength(), - IMAGE_CONTENT_LENGTH); - } - -/* - template<> template<> - void mime_index_object_t::test<5>() - { - } - template<> template<> - void mime_index_object_t::test<6>() - { - } - template<> template<> - void mime_index_object_t::test<7>() - { - } - template<> template<> - void mime_index_object_t::test<8>() - { - } - template<> template<> - void mime_index_object_t::test<>() - { - } -*/ -} - - -namespace tut -{ - struct mime_parse - { - }; - typedef test_group<mime_parse> mime_parse_t; - typedef mime_parse_t::object mime_parse_object_t; - tut::mime_parse_t tut_mime_parse("LLMimeParse"); - - template<> template<> - void mime_parse_object_t::test<1>() - { - // parse one mime object - const std::string SERIALIZED_MIME("Content-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n"); - std::stringstream istr; - istr.str(SERIALIZED_MIME); - LLMimeIndex mime; - LLMimeParser parser; - bool ok = parser.parseIndex(istr, mime); - ensure("Parse successful.", ok); - ensure_equals("content type", mime.contentType(), "text/plain"); - ensure_equals("content length", mime.contentLength(), 200); - ensure_equals("offset", mime.offset(), 49); - } - - template<> template<> - void mime_parse_object_t::test<2>() - { - // make sure we only parse one. - const std::string SERIALIZED_MIME("Content-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n\r\nContent-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n\r\n"); - std::stringstream istr; - istr.str(SERIALIZED_MIME); - LLMimeIndex mime; - LLMimeParser parser; - bool ok = parser.parseIndex(istr, mime); - ensure("Parse successful.", ok); - ensure("not multipart.", !mime.isMultipart()); - ensure_equals("content type", mime.contentType(), "text/plain"); - ensure_equals("content length", mime.contentLength(), 200); - ensure_equals("offset", mime.offset(), 49); - } - - template<> template<> - void mime_parse_object_t::test<3>() - { - // test multi-part and lack of content length for some of it. - /* -Content-Type: multipart/mixed; boundary="segment"rnContent-Length: 148rnrn--segmentrnContent-Type: text/plainrnrnsome datarnrn--segmentrnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrn<llsd><undef /></llsd>rnrn - */ - const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=\"segment\"\r\nContent-Length: 150\r\n\r\n--segment\r\nContent-Type: text/plain\r\n\r\nsome data\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n"); - std::stringstream istr; - istr.str(SERIALIZED_MIME); - LLMimeIndex mime; - LLMimeParser parser; - bool ok = parser.parseIndex(istr, mime); - ensure("Parse successful.", ok); - ensure("is multipart.", mime.isMultipart()); - ensure_equals("sub-part count", mime.subPartCount(), 2); - ensure_equals("content length", mime.contentLength(), 150); - ensure_equals("data offset for multipart", mime.offset(), 74); - - LLMimeIndex mime_plain(mime.subPart(0)); - ensure_equals( - "first part type", - mime_plain.contentType(), - "text/plain"); - ensure_equals( - "first part content length not known.", - mime_plain.contentLength(), - -1); - ensure_equals("first part offset", mime_plain.offset(), 113); - - LLMimeIndex mime_xml(mime.subPart(1)); - ensure_equals( - "second part type", - mime_xml.contentType(), - "text/xml; charset=UTF-8"); - ensure_equals( - "second part content length", - mime_xml.contentLength(), - 22); - ensure_equals("second part offset", mime_xml.offset(), 198); - } - - template<> template<> - void mime_parse_object_t::test<4>() - { - // test multi-part, unquoted separator, and premature eof conditions - /* -Content-Type: multipart/mixed; boundary=segmentrnContent-Length: 220rnrn--segmentrnContent-Type: text/plainrnContent-Length: 55rnrnhow are you today?rnI do not know. I guess I am:n'fine'rnrn--segmentrnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrn<llsd><undef /></llsd>rnrn */ - const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=segment\r\nContent-Length: 220\r\n\r\n--segment\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n"); - std::stringstream istr; - istr.str(SERIALIZED_MIME); - LLMimeIndex mime; - LLMimeParser parser; - bool ok = parser.parseIndex(istr, mime); - ensure("Parse successful.", ok); - ensure("is multipart.", mime.isMultipart()); - ensure_equals("sub-part count", mime.subPartCount(), 2); - ensure_equals("content length", mime.contentLength(), 220); - ensure_equals("data offset for multipart", mime.offset(), 72); - - LLMimeIndex mime_plain(mime.subPart(0)); - ensure_equals( - "first part type", - mime_plain.contentType(), - "text/plain"); - ensure_equals( - "first part content length", - mime_plain.contentLength(), - 55); - ensure_equals("first part offset", mime_plain.offset(), 131); - - LLMimeIndex mime_xml(mime.subPart(1)); - ensure_equals( - "second part type", - mime_xml.contentType(), - "text/xml; charset=UTF-8"); - ensure_equals( - "second part content length", - mime_xml.contentLength(), - 22); - ensure_equals("second part offset", mime_xml.offset(), 262); - } - - template<> template<> - void mime_parse_object_t::test<5>() - { - // test multi-part with multiple params - const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=segment; comment=\"testing multiple params.\"\r\nContent-Length: 220\r\n\r\n--segment\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n"); - std::stringstream istr; - istr.str(SERIALIZED_MIME); - LLMimeIndex mime; - LLMimeParser parser; - bool ok = parser.parseIndex(istr, mime); - ensure("Parse successful.", ok); - ensure("is multipart.", mime.isMultipart()); - ensure_equals("sub-part count", mime.subPartCount(), 2); - ensure_equals("content length", mime.contentLength(), 220); - - LLMimeIndex mime_plain(mime.subPart(0)); - ensure_equals( - "first part type", - mime_plain.contentType(), - "text/plain"); - ensure_equals( - "first part content length", - mime_plain.contentLength(), - 55); - - LLMimeIndex mime_xml(mime.subPart(1)); - ensure_equals( - "second part type", - mime_xml.contentType(), - "text/xml; charset=UTF-8"); - ensure_equals( - "second part content length", - mime_xml.contentLength(), - 22); - } - - template<> template<> - void mime_parse_object_t::test<6>() - { - // test multi-part with no specified boundary and eof -/* -Content-Type: multipart/relatedrnContent-Length: 220rnrn--rnContent-Type: text/plainrnContent-Length: 55rnrnhow are you today?rnI do not know. I guess I am:n'fine'rnrn--rnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrn<llsd><undef /></llsd>rnrn -*/ - const std::string SERIALIZED_MIME("Content-Type: multipart/related\r\nContent-Length: 500\r\n\r\n--\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n"); - std::stringstream istr; - istr.str(SERIALIZED_MIME); - LLMimeIndex mime; - LLMimeParser parser; - bool ok = parser.parseIndex(istr, mime); - ensure("Parse successful.", ok); - ensure("is multipart.", mime.isMultipart()); - ensure_equals("sub-part count", mime.subPartCount(), 2); - ensure_equals("content length", mime.contentLength(), 500); - ensure_equals("data offset for multipart", mime.offset(), 56); - - LLMimeIndex mime_plain(mime.subPart(0)); - ensure_equals( - "first part type", - mime_plain.contentType(), - "text/plain"); - ensure_equals( - "first part content length", - mime_plain.contentLength(), - 55); - ensure_equals("first part offset", mime_plain.offset(), 108); - - LLMimeIndex mime_xml(mime.subPart(1)); - ensure_equals( - "second part type", - mime_xml.contentType(), - "text/xml; charset=UTF-8"); - ensure_equals( - "second part content length", - mime_xml.contentLength(), - 22); - ensure_equals("second part offset", mime_xml.offset(), 232); - } - -/* - template<> template<> - void mime_parse_object_t::test<>() - { - } - template<> template<> - void mime_parse_object_t::test<>() - { - } - template<> template<> - void mime_parse_object_t::test<>() - { - } - template<> template<> - void mime_parse_object_t::test<>() - { - } -*/ -} diff --git a/indra/llmessage/tests/llmockhttpclient.h b/indra/llmessage/tests/llmockhttpclient.h index af26bf8803..af26bf8803 100644..100755 --- a/indra/llmessage/tests/llmockhttpclient.h +++ b/indra/llmessage/tests/llmockhttpclient.h diff --git a/indra/llmessage/tests/llnamevalue_test.cpp b/indra/llmessage/tests/llnamevalue_test.cpp index 8902fdd2e8..8902fdd2e8 100644..100755 --- a/indra/llmessage/tests/llnamevalue_test.cpp +++ b/indra/llmessage/tests/llnamevalue_test.cpp diff --git a/indra/llmessage/tests/llpartdata_test.cpp b/indra/llmessage/tests/llpartdata_test.cpp index 9123bd06c7..de81e0bbb2 100644..100755 --- a/indra/llmessage/tests/llpartdata_test.cpp +++ b/indra/llmessage/tests/llpartdata_test.cpp @@ -38,10 +38,34 @@ namespace tut { + + //bunch of sniffed data that *should* be a valid particle system + static U8 msg[] = { + 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x80, 0x00, 0x80, + 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x5e, 0x12, 0x0b, 0xa1, 0x58, 0x05, 0xdc, 0x57, 0x66, + 0xb7, 0xf5, 0xac, 0x4b, 0xd1, 0x8f, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x05, 0x02, 0x00, 0x00, 0x0a, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7e, 0xc6, 0x81, 0xdc, 0x7e, 0xc6, 0x81, 0xdc, 0x77, 0xcf, 0xef, 0xd4, 0xce, 0x64, 0x1a, 0x7e, + 0x26, 0x87, 0x55, 0x7f, 0xdd, 0x65, 0x22, 0x7f, 0xdd, 0x65, 0x22, 0x7f, 0x77, 0xcf, 0x98, 0xa3, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xf2, + 0xf1, 0x65, 0x32, 0x1b, 0xef, 0x18, 0x70, 0x66, 0xba, 0x30, 0xa0, 0x11, 0xaa, 0x2f, 0xb0, 0xab, 0xd0, + 0x30, 0x7d, 0xbd, 0x01, 0x00, 0xf8, 0x0d, 0xb8, 0x30, 0x01, 0x00, 0x00, 0x00, 0xce, 0xc6, 0x81, 0xdc, + 0xce, 0xc6, 0x81, 0xdc, 0xc7, 0xcf, 0xef, 0xd4, 0x75, 0x65, 0x1a, 0x7f, 0x62, 0x6f, 0x55, 0x7f, 0x6d, + 0x65, 0x22, 0x7f, 0x6d, 0x65, 0x22, 0x7f, 0xc7, 0xcf, 0x98, 0xa3, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xf2, 0xf1, 0x62, 0x12, 0x1b, 0xef, + 0x18, 0x7e, 0xbd, 0x01, 0x00, 0x16, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0xac, 0x28, 0x03, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, + 0xe0, 0xb9, 0x30, 0x03, 0xe1, 0xb9, 0x30, 0xbb, 0x00, 0x00, 0x00, 0x48, 0xe0, 0xb9, 0x30, 0x36, 0xd9, + 0x81, 0xdc, 0x36, 0xd9, 0x81, 0xdc, 0x3f, 0xd0, 0xef, 0xd4, 0xa5, 0x7a, 0x72, 0x7f, 0x26, 0x30, 0x55, + 0x7f, 0x95, 0x7a, 0x22, 0x7f, 0x95, 0x7a, 0x22, 0x7f, 0x3f, 0xd0, 0x98, 0xa3, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00 }; struct partdata_test { }; + typedef test_group<partdata_test> partdata_test_t; typedef partdata_test_t::object partdata_test_object_t; tut::partdata_test_t tut_partdata_test("LLPartData"); @@ -49,168 +73,82 @@ namespace tut template<> template<> void partdata_test_object_t::test<1>() { - LLPartData llpdata,llpdata1; - U8 pkbuf[128]; - - llpdata.setFlags(LLPartData::LL_PART_INTERP_COLOR_MASK | LLPartData::LL_PART_INTERP_SCALE_MASK | - LLPartData::LL_PART_BOUNCE_MASK | LLPartData::LL_PART_WIND_MASK | LLPartData::LL_PART_FOLLOW_SRC_MASK | - LLPartData::LL_PART_FOLLOW_VELOCITY_MASK | LLPartData::LL_PART_TARGET_POS_MASK | LLPartData::LL_PART_TARGET_LINEAR_MASK | - LLPartData::LL_PART_EMISSIVE_MASK | LLPartData::LL_PART_BEAM_MASK | LLPartData::LL_PART_DEAD_MASK); - - llpdata.setMaxAge(29.3f); - - LLVector3 llvec1(1.0f, .5f, .25f); - llpdata.setStartColor(llvec1); - llpdata.setStartAlpha(.7f); - - LLVector3 llvec2(.2f, .3f, 1.0f); - llpdata.setEndColor(llvec2); - llpdata.setEndAlpha(1.0f); + LLPartSysData llpsysdata; + LLDataPackerBinaryBuffer dp1(msg, sizeof(msg)); - llpdata.setStartScale(3.23f, 4.0f); - llpdata.setEndScale(2.4678f, 1.0f); + ensure("LLPartSysData::unpack failed.", llpsysdata.unpack(dp1)); - LLDataPackerBinaryBuffer dp((U8*)pkbuf, 128); - llpdata.pack(dp); - S32 cur_size = dp.getCurrentSize(); - - LLDataPackerBinaryBuffer dp1((U8*)pkbuf, cur_size); - llpdata1.unpack(dp1); - - ensure("1.mFlags values are different after unpacking", llpdata1.mFlags == llpdata.mFlags); - ensure_approximately_equals("2.mMaxAge values are different after unpacking", llpdata1.mMaxAge, llpdata.mMaxAge, 8); - - ensure_approximately_equals("3.mStartColor[0] values are different after unpacking", llpdata1.mStartColor.mV[0], llpdata.mStartColor.mV[0], 8); - ensure_approximately_equals("4.mStartColor[1] values are different after unpacking", llpdata1.mStartColor.mV[1], llpdata.mStartColor.mV[1], 8); - ensure_approximately_equals("5.mStartColor[2] values are different after unpacking", llpdata1.mStartColor.mV[2], llpdata.mStartColor.mV[2], 8); - ensure_approximately_equals("6.mStartColor[3] values are different after unpacking", llpdata1.mStartColor.mV[3], llpdata.mStartColor.mV[3], 8); - - ensure_approximately_equals("7.mEndColor[0] values are different after unpacking", llpdata1.mEndColor.mV[0], llpdata.mEndColor.mV[0], 8); - ensure_approximately_equals("8.mEndColor[1] values are different after unpacking", llpdata1.mEndColor.mV[1], llpdata.mEndColor.mV[1], 8); - ensure_approximately_equals("9.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[2], llpdata.mEndColor.mV[2], 8); - ensure_approximately_equals("10.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[3], llpdata.mEndColor.mV[3], 8); - - ensure_approximately_equals("11.mStartScale[0] values are different after unpacking", llpdata1.mStartScale.mV[0], llpdata.mStartScale.mV[0], 5); - ensure_approximately_equals("12.mStartScale[1] values are different after unpacking", llpdata1.mStartScale.mV[1], llpdata.mStartScale.mV[1], 5); - - ensure_approximately_equals("13.mEndScale[0] values are different after unpacking", llpdata1.mEndScale.mV[0], llpdata.mEndScale.mV[0], 5); - ensure_approximately_equals("14.mEndScale[1] values are different after unpacking", llpdata1.mEndScale.mV[1], llpdata.mEndScale.mV[1], 5); - } - - - template<> template<> - void partdata_test_object_t::test<2>() - { - LLPartData llpdata,llpdata1; - - llpdata.setFlags(LLPartData::LL_PART_INTERP_COLOR_MASK | LLPartData::LL_PART_INTERP_SCALE_MASK | - LLPartData::LL_PART_BOUNCE_MASK | LLPartData::LL_PART_WIND_MASK | LLPartData::LL_PART_FOLLOW_SRC_MASK | - LLPartData::LL_PART_FOLLOW_VELOCITY_MASK | LLPartData::LL_PART_TARGET_POS_MASK | LLPartData::LL_PART_TARGET_LINEAR_MASK | - LLPartData::LL_PART_EMISSIVE_MASK | LLPartData::LL_PART_BEAM_MASK | LLPartData::LL_PART_DEAD_MASK); - - llpdata.setMaxAge(29.3f); - - LLVector3 llvec1(1.0f, .5f, .25f); - llpdata.setStartColor(llvec1); - llpdata.setStartAlpha(.7f); - - LLVector3 llvec2(.2f, .3f, 1.0f); - llpdata.setEndColor(llvec2); - llpdata.setEndAlpha(1.0f); - - llpdata.setStartScale(3.23f, 4.0f); - llpdata.setEndScale(2.4678f, 1.0f); - - LLSD llsd = llpdata.asLLSD(); - - llpdata1.fromLLSD(llsd); - - ensure("1.mFlags values are different after unpacking", llpdata1.mFlags == llpdata.mFlags); - ensure_approximately_equals("2.mMaxAge values are different after unpacking", llpdata1.mMaxAge, llpdata.mMaxAge, 8); - - ensure_approximately_equals("3.mStartColor[0] values are different after unpacking", llpdata1.mStartColor.mV[0], llpdata.mStartColor.mV[0], 8); - ensure_approximately_equals("4.mStartColor[1] values are different after unpacking", llpdata1.mStartColor.mV[1], llpdata.mStartColor.mV[1], 8); - ensure_approximately_equals("5.mStartColor[2] values are different after unpacking", llpdata1.mStartColor.mV[2], llpdata.mStartColor.mV[2], 8); - ensure_approximately_equals("6.mStartColor[3] values are different after unpacking", llpdata1.mStartColor.mV[3], llpdata.mStartColor.mV[3], 8); - - ensure_approximately_equals("7.mEndColor[0] values are different after unpacking", llpdata1.mEndColor.mV[0], llpdata.mEndColor.mV[0], 8); - ensure_approximately_equals("8.mEndColor[1] values are different after unpacking", llpdata1.mEndColor.mV[1], llpdata.mEndColor.mV[1], 8); - ensure_approximately_equals("9.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[2], llpdata.mEndColor.mV[2], 8); - ensure_approximately_equals("10.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[3], llpdata.mEndColor.mV[3], 8); - - ensure_approximately_equals("11.mStartScale[0] values are different after unpacking", llpdata1.mStartScale.mV[0], llpdata.mStartScale.mV[0], 5); - ensure_approximately_equals("12.mStartScale[1] values are different after unpacking", llpdata1.mStartScale.mV[1], llpdata.mStartScale.mV[1], 5); - - ensure_approximately_equals("13.mEndScale[0] values are different after unpacking", llpdata1.mEndScale.mV[0], llpdata.mEndScale.mV[0], 5); - ensure_approximately_equals("14.mEndScale[1] values are different after unpacking", llpdata1.mEndScale.mV[1], llpdata.mEndScale.mV[1], 5); - } - - -//*********llpartsysdata*********** - - template<> template<> - void partdata_test_object_t::test<3>() - { - LLPartSysData llpsysdata, llpsysdata1; - U8 pkbuf[256]; - llpsysdata.setBurstSpeedMin(33.33f); - ensure("1.mBurstSpeedMin coudnt be set", 33.33f == llpsysdata.mBurstSpeedMin); - - llpsysdata.setBurstSpeedMax(44.44f); - ensure("2.mBurstSpeedMax coudnt be set", 44.44f == llpsysdata.mBurstSpeedMax); - - llpsysdata.setBurstRadius(45.55f); - ensure("3.mBurstRadius coudnt be set", 45.55f == llpsysdata.mBurstRadius); - - LLVector3 llvec(44.44f, 111.11f, -40.4f); - llpsysdata.setPartAccel(llvec); - - llpsysdata.mCRC = 0xFFFFFFFF; - llpsysdata.mFlags = 0x20; - - llpsysdata.mPattern = LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE_EMPTY; - - llpsysdata.mMaxAge = 99.99f; - llpsysdata.mStartAge = 18.5f; - llpsysdata.mInnerAngle = 4.234f; - llpsysdata.mOuterAngle = 7.123f; - llpsysdata.mBurstRate = 245.53f; - llpsysdata.mBurstPartCount = 0xFF; - llpsysdata.mAngularVelocity = llvec; - - llpsysdata.mPartImageID.generate(); - llpsysdata.mTargetUUID.generate(); + //mCRC 1 unsigned int + ensure("mCRC different after unpacking", llpsysdata.mCRC == (U32) 1); + //mFlags 0 unsigned int + ensure ("mFlags different after unpacking", llpsysdata.mFlags == (U32) 0); + //mPattern 1 '' unsigned char + ensure ("mPattern different after unpacking", llpsysdata.mPattern == (U8) 1); + //mInnerAngle 0.00000000 float + ensure_approximately_equals("mInnerAngle different after unpacking", llpsysdata.mInnerAngle, 0.f, 8); + //mOuterAngle 0.00000000 float + ensure_approximately_equals("mOuterAngle different after unpacking", llpsysdata.mOuterAngle, 0.f, 8); + //mAngularVelocity 0,0,0 + ensure_approximately_equals("mAngularVelocity.mV[0] different after unpacking", llpsysdata.mAngularVelocity.mV[0], 0.f, 8); + ensure_approximately_equals("mAngularVelocity.mV[0] different after unpacking", llpsysdata.mAngularVelocity.mV[1], 0.f, 8); + ensure_approximately_equals("mAngularVelocity.mV[0] different after unpacking", llpsysdata.mAngularVelocity.mV[2], 0.f, 8); + //mBurstRate 0.097656250 float + ensure_approximately_equals("mBurstRate different after unpacking", llpsysdata.mBurstRate, 0.097656250f, 8); + //mBurstPartCount 1 '' unsigned char + ensure("mBurstPartCount different after unpacking", llpsysdata.mBurstPartCount == (U8) 1); + //mBurstRadius 0.00000000 float + ensure_approximately_equals("mBurstRadius different after unpacking", llpsysdata.mBurstRadius, 0.f, 8); + //mBurstSpeedMin 1.0000000 float + ensure_approximately_equals("mBurstSpeedMin different after unpacking", llpsysdata.mBurstSpeedMin, 1.f, 8); + //mBurstSpeedMax 1.0000000 float + ensure_approximately_equals("mBurstSpeedMax different after unpacking", llpsysdata.mBurstSpeedMax, 1.f, 8); + //mMaxAge 0.00000000 float + ensure_approximately_equals("mMaxAge different after unpacking", llpsysdata.mMaxAge, 0.f, 8); + //mStartAge 0.00000000 float + ensure_approximately_equals("mStartAge different after unpacking", llpsysdata.mStartAge, 0.f, 8); + //mPartAccel <0,0,0> + ensure_approximately_equals("mPartAccel.mV[0] different after unpacking", llpsysdata.mPartAccel.mV[0], 0.f, 7); + ensure_approximately_equals("mPartAccel.mV[1] different after unpacking", llpsysdata.mPartAccel.mV[1], 0.f, 7); + ensure_approximately_equals("mPartAccel.mV[2] different after unpacking", llpsysdata.mPartAccel.mV[2], 0.f, 7); + + //mPartData + LLPartData& data = llpsysdata.mPartData; + + //mFlags 132354 unsigned int + ensure ("mPartData.mFlags different after unpacking", data.mFlags == (U32) 132354); + //mMaxAge 10.000000 float + ensure_approximately_equals("mPartData.mMaxAge different after unpacking", data.mMaxAge, 10.f, 8); + //mStartColor <1,1,1,1> + ensure_approximately_equals("mPartData.mStartColor.mV[0] different after unpacking", data.mStartColor.mV[0], 1.f, 8); + ensure_approximately_equals("mPartData.mStartColor.mV[1] different after unpacking", data.mStartColor.mV[1], 1.f, 8); + ensure_approximately_equals("mPartData.mStartColor.mV[2] different after unpacking", data.mStartColor.mV[2], 1.f, 8); + ensure_approximately_equals("mPartData.mStartColor.mV[3] different after unpacking", data.mStartColor.mV[3], 1.f, 8); + //mEndColor <1,1,0,0> + ensure_approximately_equals("mPartData.mEndColor.mV[0] different after unpacking", data.mEndColor.mV[0], 1.f, 8); + ensure_approximately_equals("mPartData.mEndColor.mV[1] different after unpacking", data.mEndColor.mV[1], 1.f, 8); + ensure_approximately_equals("mPartData.mEndColor.mV[2] different after unpacking", data.mEndColor.mV[2], 0.f, 8); + ensure_approximately_equals("mPartData.mEndColor.mV[3] different after unpacking", data.mEndColor.mV[3], 0.f, 8); + //mStartScale <1,1> + ensure_approximately_equals("mPartData.mStartScale.mV[0] different after unpacking", data.mStartScale.mV[0], 1.f, 8); + ensure_approximately_equals("mPartData.mStartScale.mV[1] different after unpacking", data.mStartScale.mV[1], 1.f, 8); + //mEndScale <0,0> + ensure_approximately_equals("mPartData.mEndScale.mV[0] different after unpacking", data.mEndScale.mV[0], 0.f, 8); + ensure_approximately_equals("mPartData.mEndScale.mV[1] different after unpacking", data.mEndScale.mV[1], 0.f, 8); + //mPosOffset <0,0,0> + ensure_approximately_equals("mPartData.mPosOffset.mV[0] different after unpacking", data.mPosOffset.mV[0], 0.f, 8); + ensure_approximately_equals("mPartData.mPosOffset.mV[1] different after unpacking", data.mPosOffset.mV[1], 0.f, 8); + ensure_approximately_equals("mPartData.mPosOffset.mV[2] different after unpacking", data.mPosOffset.mV[2], 0.f, 8); + //mParameter 0.00000000 float + ensure_approximately_equals("mPartData.mParameter different after unpacking", data.mParameter, 0.f, 8); - LLDataPackerBinaryBuffer dp((U8*)pkbuf, 256); - llpsysdata.pack(dp); - S32 cur_size = dp.getCurrentSize(); - LLDataPackerBinaryBuffer dp1((U8*)pkbuf, cur_size); - llpsysdata1.unpack(dp1); - - ensure("1.mCRC's not equal", llpsysdata.mCRC == llpsysdata1.mCRC); - ensure("2.mFlags's not equal", llpsysdata.mFlags == llpsysdata1.mFlags); - ensure("3.mPattern's not equal", llpsysdata.mPattern == llpsysdata1.mPattern); - ensure_approximately_equals("4.mMaxAge's not equal", llpsysdata.mMaxAge , llpsysdata1.mMaxAge, 8); - ensure_approximately_equals("5.mStartAge's not equal", llpsysdata.mStartAge, llpsysdata1.mStartAge, 8); - ensure_approximately_equals("6.mOuterAngle's not equal", llpsysdata.mOuterAngle, llpsysdata1.mOuterAngle, 5); - ensure_approximately_equals("7.mInnerAngles's not equal", llpsysdata.mInnerAngle, llpsysdata1.mInnerAngle, 5); - ensure_approximately_equals("8.mBurstRate's not equal", llpsysdata.mBurstRate, llpsysdata1.mBurstRate, 8); - ensure("9.mBurstPartCount's not equal", llpsysdata.mBurstPartCount == llpsysdata1.mBurstPartCount); - - ensure_approximately_equals("10.mBurstSpeedMin's not equal", llpsysdata.mBurstSpeedMin, llpsysdata1.mBurstSpeedMin, 8); - ensure_approximately_equals("11.mBurstSpeedMax's not equal", llpsysdata.mBurstSpeedMax, llpsysdata1.mBurstSpeedMax, 8); - - ensure_approximately_equals("12.mAngularVelocity's not equal", llpsysdata.mAngularVelocity.mV[0], llpsysdata1.mAngularVelocity.mV[0], 7); - ensure_approximately_equals("13.mAngularVelocity's not equal", llpsysdata.mAngularVelocity.mV[1], llpsysdata1.mAngularVelocity.mV[1], 7); - ensure_approximately_equals("14.mAngularVelocity's not equal", llpsysdata.mAngularVelocity.mV[2], llpsysdata1.mAngularVelocity.mV[2], 7); - - ensure_approximately_equals("15.mPartAccel's not equal", llpsysdata.mPartAccel.mV[0], llpsysdata1.mPartAccel.mV[0], 7); - ensure_approximately_equals("16.mPartAccel's not equal", llpsysdata.mPartAccel.mV[1], llpsysdata1.mPartAccel.mV[1], 7); - ensure_approximately_equals("17.mPartAccel's not equal", llpsysdata.mPartAccel.mV[2], llpsysdata1.mPartAccel.mV[2], 7); - - ensure("18.mPartImageID's not equal", llpsysdata.mPartImageID == llpsysdata1.mPartImageID); - ensure("19.mTargetUUID's not equal", llpsysdata.mTargetUUID == llpsysdata1.mTargetUUID); - ensure_approximately_equals("20.mBurstRadius's not equal", llpsysdata.mBurstRadius, llpsysdata1.mBurstRadius, 8); + //mStartGlow 0.00000000 float + ensure_approximately_equals("mPartData.mStartGlow different after unpacking", data.mStartGlow, 0.f, 8); + //mEndGlow 0.00000000 float + ensure_approximately_equals("mPartData.mEndGlow different after unpacking", data.mEndGlow, 0.f, 8); + //mBlendFuncSource 2 '' unsigned char + ensure("mPartData.mBlendFuncSource different after unpacking", data.mBlendFuncSource == (U8) 2); + //mBlendFuncDest 1 '' unsigned char + ensure("mPartData.mBlendFuncDest different after unpacking", data.mBlendFuncDest == (U8) 1); } } diff --git a/indra/llmessage/tests/llregionpresenceverifier_test.cpp b/indra/llmessage/tests/llregionpresenceverifier_test.cpp deleted file mode 100644 index 5b89f2a8c6..0000000000 --- a/indra/llmessage/tests/llregionpresenceverifier_test.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @file - * @brief - * - * $LicenseInfo:firstyear=2008&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 "linden_common.h" - -#include "../test/lltut.h" -#include "llregionpresenceverifier.h" -#include "llcurl_stub.cpp" -#include "llhost.cpp" -#include "net.cpp" -#include "lltesthttpclientadapter.cpp" - -class LLTestResponse : public LLRegionPresenceVerifier::Response -{ -public: - - virtual bool checkValidity(const LLSD& content) const - { - return true; - } - - virtual void onRegionVerified(const LLSD& region_details) - { - } - - virtual void onRegionVerificationFailed() - { - } - - virtual LLHTTPClientInterface& getHttpClient() - { - return mHttpInterface; - } - - LLTestHTTPClientAdapter mHttpInterface; -}; - -namespace tut -{ - struct LLRegionPresenceVerifierData - { - LLRegionPresenceVerifierData() : - mResponse(new LLTestResponse()), - mResponder("", LLRegionPresenceVerifier::ResponsePtr(mResponse), - LLSD(), 3) - { - } - - LLTestResponse* mResponse; - LLRegionPresenceVerifier::VerifiedDestinationResponder mResponder; - }; - - typedef test_group<LLRegionPresenceVerifierData> factory; - typedef factory::object object; -} - -namespace -{ - tut::factory tf("LLRegionPresenceVerifier"); -} - -namespace tut -{ - // Test that VerifiedDestinationResponder does retry - // on error when shouldRetry returns true. - template<> template<> - void object::test<1>() - { - mResponder.error(500, "Internal server error"); - ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 1); - } - - // Test that VerifiedDestinationResponder only retries - // on error until shouldRetry returns false. - template<> template<> - void object::test<2>() - { - mResponder.error(500, "Internal server error"); - mResponder.error(500, "Internal server error"); - mResponder.error(500, "Internal server error"); - mResponder.error(500, "Internal server error"); - ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 3); - } -} - diff --git a/indra/llmessage/tests/llsdmessage_test.cpp b/indra/llmessage/tests/llsdmessage_test.cpp index 9998a1b8bb..44b024a83f 100644..100755 --- a/indra/llmessage/tests/llsdmessage_test.cpp +++ b/indra/llmessage/tests/llsdmessage_test.cpp @@ -42,6 +42,7 @@ // external library headers // other Linden headers #include "../test/lltut.h" +#include "../test/catch_and_store_what_in.h" #include "llsdserialize.h" #include "llevents.h" #include "stringize.h" @@ -61,6 +62,7 @@ namespace tut llsdmessage_data(): httpPump(pumps.obtain("LLHTTPClient")) { + LLCurl::initClass(); LLSDMessage::link(); } }; @@ -71,43 +73,14 @@ namespace tut template<> template<> void llsdmessage_object::test<1>() { - bool threw = false; + std::string threw; // This should fail... try { LLSDMessage localListener; } - catch (const LLEventPump::DupPumpName&) - { - threw = true; - } - catch (const std::runtime_error& ex) - { - // This clause is because on Linux, on the viewer side, for this - // one test program (though not others!), the - // LLEventPump::DupPumpName exception isn't caught by the clause - // above. Warn the user... - std::cerr << "Failed to catch " << typeid(ex).name() << std::endl; - // But if the expected exception was thrown, allow the test to - // succeed anyway. Not sure how else to handle this odd case. - if (std::string(typeid(ex).name()) == typeid(LLEventPump::DupPumpName).name()) - { - threw = true; - } - else - { - // We don't even recognize this exception. Let it propagate - // out to TUT to fail the test. - throw; - } - } - catch (...) - { - std::cerr << "Utterly failed to catch expected exception!" << std::endl; - // This case is full of fail. We HAVE to address it. - throw; - } - ensure("second LLSDMessage should throw", threw); + CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::DupPumpName) + ensure("second LLSDMessage should throw", ! threw.empty()); } template<> template<> @@ -142,7 +115,7 @@ namespace tut httpPump.post(request); ensure("got response", netio.pump()); ensure("success response", success); - ensure_equals(result.asString(), "success"); + ensure_equals(result["reply"].asString(), "success"); body["status"] = 499; body["reason"] = "custom error message"; diff --git a/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp index 3b04530c1a..3b04530c1a 100644..100755 --- a/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp +++ b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp diff --git a/indra/llmessage/tests/lltesthttpclientadapter.cpp b/indra/llmessage/tests/lltesthttpclientadapter.cpp index 4539e4a540..4539e4a540 100644..100755 --- a/indra/llmessage/tests/lltesthttpclientadapter.cpp +++ b/indra/llmessage/tests/lltesthttpclientadapter.cpp diff --git a/indra/llmessage/tests/lltesthttpclientadapter.h b/indra/llmessage/tests/lltesthttpclientadapter.h index c29cbb3a2a..c29cbb3a2a 100644..100755 --- a/indra/llmessage/tests/lltesthttpclientadapter.h +++ b/indra/llmessage/tests/lltesthttpclientadapter.h diff --git a/indra/llmessage/tests/lltestmessagesender.cpp b/indra/llmessage/tests/lltestmessagesender.cpp index ee40e0249e..ee40e0249e 100644..100755 --- a/indra/llmessage/tests/lltestmessagesender.cpp +++ b/indra/llmessage/tests/lltestmessagesender.cpp diff --git a/indra/llmessage/tests/lltestmessagesender.h b/indra/llmessage/tests/lltestmessagesender.h index bb89289585..bb89289585 100644..100755 --- a/indra/llmessage/tests/lltestmessagesender.h +++ b/indra/llmessage/tests/lltestmessagesender.h diff --git a/indra/llmessage/tests/lltrustedmessageservice_test.cpp b/indra/llmessage/tests/lltrustedmessageservice_test.cpp index b287a29841..55748ad27e 100644..100755 --- a/indra/llmessage/tests/lltrustedmessageservice_test.cpp +++ b/indra/llmessage/tests/lltrustedmessageservice_test.cpp @@ -32,6 +32,7 @@ #include "message.h" #include "llmessageconfig.h" +#include "llhttpnode_stub.cpp" LLMessageSystem* gMessageSystem = NULL; diff --git a/indra/llmessage/tests/llxfer_file_test.cpp b/indra/llmessage/tests/llxfer_file_test.cpp index a8c1adf9b4..a8c1adf9b4 100644..100755 --- a/indra/llmessage/tests/llxfer_file_test.cpp +++ b/indra/llmessage/tests/llxfer_file_test.cpp diff --git a/indra/llmessage/tests/networkio.h b/indra/llmessage/tests/networkio.h index 2aff90ca1e..2aff90ca1e 100644..100755 --- a/indra/llmessage/tests/networkio.h +++ b/indra/llmessage/tests/networkio.h diff --git a/indra/llmessage/tests/test_llsdmessage_peer.py b/indra/llmessage/tests/test_llsdmessage_peer.py index 7eb198bb34..e45249b1cb 100644..100755 --- a/indra/llmessage/tests/test_llsdmessage_peer.py +++ b/indra/llmessage/tests/test_llsdmessage_peer.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python """\ @file test_llsdmessage_peer.py @author Nat Goodspeed @@ -38,7 +38,10 @@ mydir = os.path.dirname(__file__) # expected to be .../indra/llmessage/tes sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python")) from indra.util.fastest_elementtree import parse as xml_parse from indra.base import llsd -from testrunner import run, debug +from testrunner import freeport, run, debug, VERBOSE +import time + +_storage=None class TestHTTPRequestHandler(BaseHTTPRequestHandler): """This subclass of BaseHTTPRequestHandler is to receive and echo @@ -72,52 +75,99 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler): ## # assuming that the underlying XML parser reads its input file ## # incrementally. Unfortunately I haven't been able to make it work. ## tree = xml_parse(self.rfile) -## debug("Finished raw parse\n") -## debug("parsed XML tree %s\n" % tree) -## debug("parsed root node %s\n" % tree.getroot()) -## debug("root node tag %s\n" % tree.getroot().tag) +## debug("Finished raw parse") +## debug("parsed XML tree %s", tree) +## debug("parsed root node %s", tree.getroot()) +## debug("root node tag %s", tree.getroot().tag) ## return llsd.to_python(tree.getroot()) - def do_GET(self): + def do_HEAD(self): + self.do_GET(withdata=False) + + def do_GET(self, withdata=True): # Of course, don't attempt to read data. - self.answer(dict(reply="success", status=500, - reason="Your GET operation requested failure")) + data = dict(reply="success", body="avatar", random=17) + self.answer(data, withdata=withdata) def do_POST(self): # Read the provided POST data. self.answer(self.read_xml()) - def answer(self, data): - if "fail" not in self.path: - response = llsd.format_xml(data.get("reply", llsd.LLSD("success"))) - self.send_response(200) - self.send_header("Content-type", "application/llsd+xml") - self.send_header("Content-Length", str(len(response))) - self.end_headers() - self.wfile.write(response) - else: # fail requested + def do_PUT(self): + # Read the provided PUT data. + self.answer(self.read_xml()) + + def answer(self, data, withdata=True): + global _storage + debug("%s.answer(%s): self.path = %r", self.__class__.__name__, data, self.path) + if "fail" in self.path or "test/error" in self.path: # fail requested status = data.get("status", 500) + # self.responses maps an int status to a (short, long) pair of + # strings. We want the longer string. That's why we pass a string + # pair to get(): the [1] will select the second string, whether it + # came from self.responses or from our default pair. reason = data.get("reason", self.responses.get(status, ("fail requested", "Your request specified failure status %s " "without providing a reason" % status))[1]) + debug("fail requested: %s: %r", status, reason) self.send_error(status, reason) + else: + if "web/echo" in self.path: + pass + elif "test/timeout" in self.path: + time.sleep(5.0) + return + elif "test/storage" in self.path: + if "GET" == self.command: + data = _storage + else: + _storage = data + data = "ok" + else: + data = data.copy() # we're going to modify + # Ensure there's a "reply" key in data, even if there wasn't before + data["reply"] = data.get("reply", llsd.LLSD("success")) + response = llsd.format_xml(data) + debug("success: %s", response) + self.send_response(200) + self.send_header("Content-type", "application/llsd+xml") + self.send_header("Content-Length", str(len(response))) + self.end_headers() + if withdata: + self.wfile.write(response) + + if not VERBOSE: + # When VERBOSE is set, skip both these overrides because they exist to + # suppress output. - def log_request(self, code, size=None): - # For present purposes, we don't want the request splattered onto - # stderr, as it would upset devs watching the test run - pass + def log_request(self, code, size=None): + # For present purposes, we don't want the request splattered onto + # stderr, as it would upset devs watching the test run + pass - def log_error(self, format, *args): - # Suppress error output as well - pass + def log_error(self, format, *args): + # Suppress error output as well + pass -class TestHTTPServer(Thread): - def run(self): - httpd = HTTPServer(('127.0.0.1', 8000), TestHTTPRequestHandler) - debug("Starting HTTP server...\n") - httpd.serve_forever() +class Server(HTTPServer): + # This pernicious flag is on by default in HTTPServer. But proper + # operation of freeport() absolutely depends on it being off. + allow_reuse_address = False if __name__ == "__main__": - sys.exit(run(server=TestHTTPServer(name="httpd"), *sys.argv[1:])) + # Instantiate a Server(TestHTTPRequestHandler) on the first free port + # in the specified port range. Doing this inline is better than in a + # daemon thread: if it blows up here, we'll get a traceback. If it blew up + # in some other thread, the traceback would get eaten and we'd run the + # subject test program anyway. + httpd, port = freeport(xrange(8000, 8020), + lambda port: Server(('127.0.0.1', port), TestHTTPRequestHandler)) + # Pass the selected port number to the subject test program via the + # environment. We don't want to impose requirements on the test program's + # command-line parsing -- and anyway, for C++ integration tests, that's + # performed in TUT code rather than our own. + os.environ["PORT"] = str(port) + debug("$PORT = %s", port) + sys.exit(run(server=Thread(name="httpd", target=httpd.serve_forever), *sys.argv[1:])) diff --git a/indra/llmessage/tests/testrunner.py b/indra/llmessage/tests/testrunner.py index 4d58ef7130..5b9beb359b 100644..100755 --- a/indra/llmessage/tests/testrunner.py +++ b/indra/llmessage/tests/testrunner.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python """\ @file testrunner.py @author Nat Goodspeed @@ -27,14 +27,118 @@ Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA $/LicenseInfo$ """ +from __future__ import with_statement + import os import sys +import re +import errno +import socket + +VERBOSE = os.environ.get("INTEGRATION_TEST_VERBOSE", "0") # default to quiet +# Support usage such as INTEGRATION_TEST_VERBOSE=off -- distressing to user if +# that construct actually turns on verbosity... +VERBOSE = not re.match(r"(0|off|false|quiet)$", VERBOSE, re.IGNORECASE) + +if VERBOSE: + def debug(fmt, *args): + print fmt % args + sys.stdout.flush() +else: + debug = lambda *args: None + +def freeport(portlist, expr): + """ + Find a free server port to use. Specifically, evaluate 'expr' (a + callable(port)) until it stops raising EADDRINUSE exception. + + Pass: + + portlist: an iterable (e.g. xrange()) of ports to try. If you exhaust the + range, freeport() lets the socket.error exception propagate. If you want + unbounded, you could pass itertools.count(baseport), though of course in + practice the ceiling is 2^16-1 anyway. But it seems prudent to constrain + the range much more sharply: if we're iterating an absurd number of times, + probably something else is wrong. + + expr: a callable accepting a port number, specifically one of the items + from portlist. If calling that callable raises socket.error with + EADDRINUSE, freeport() retrieves the next item from portlist and retries. + + Returns: (expr(port), port) + + port: the value from portlist for which expr(port) succeeded + + Raises: + + Any exception raised by expr(port) other than EADDRINUSE. + + socket.error if, for every item from portlist, expr(port) raises + socket.error. The exception you see is the one from the last item in + portlist. + + StopIteration if portlist is completely empty. + + Example: + + class Server(HTTPServer): + # If you use BaseHTTPServer.HTTPServer, turning off this flag is + # essential for proper operation of freeport()! + allow_reuse_address = False + # ... + server, port = freeport(xrange(8000, 8010), + lambda port: Server(("localhost", port), + MyRequestHandler)) + # pass 'port' to client code + # call server.serve_forever() + """ + try: + # If portlist is completely empty, let StopIteration propagate: that's an + # error because we can't return meaningful values. We have no 'port', + # therefore no 'expr(port)'. + portiter = iter(portlist) + port = portiter.next() + + while True: + try: + # If this value of port works, return as promised. + value = expr(port) + + except socket.error, err: + # Anything other than 'Address already in use', propagate + if err.args[0] != errno.EADDRINUSE: + raise + + # Here we want the next port from portiter. But on StopIteration, + # we want to raise the original exception rather than + # StopIteration. So save the original exc_info(). + type, value, tb = sys.exc_info() + try: + try: + port = portiter.next() + except StopIteration: + raise type, value, tb + finally: + # Clean up local traceback, see docs for sys.exc_info() + del tb + + else: + debug("freeport() returning %s on port %s", value, port) + return value, port -def debug(*args): - sys.stdout.writelines(args) - sys.stdout.flush() -# comment out the line below to enable debug output -debug = lambda *args: None + # Recap of the control flow above: + # If expr(port) doesn't raise, return as promised. + # If expr(port) raises anything but EADDRINUSE, propagate that + # exception. + # If portiter.next() raises StopIteration -- that is, if the port + # value we just passed to expr(port) was the last available -- reraise + # the EADDRINUSE exception. + # If we've actually arrived at this point, portiter.next() delivered a + # new port value. Loop back to pass that to expr(port). + + except Exception, err: + debug("*** freeport() raising %s: %s", err.__class__.__name__, err) + raise def run(*args, **kwds): """All positional arguments collectively form a command line, executed as @@ -63,8 +167,96 @@ def run(*args, **kwds): # - [no p] don't use the PATH because we specifically want to invoke the # executable passed as our first arg, # - [no e] child should inherit this process's environment. - debug("Running %s...\n" % (" ".join(args))) - sys.stdout.flush() + debug("Running %s...", " ".join(args)) rc = os.spawnv(os.P_WAIT, args[0], args) - debug("%s returned %s\n" % (args[0], rc)) + debug("%s returned %s", args[0], rc) return rc + +# **************************************************************************** +# test code -- manual at this point, see SWAT-564 +# **************************************************************************** +def test_freeport(): + # ------------------------------- Helpers -------------------------------- + from contextlib import contextmanager + # helper Context Manager for expecting an exception + # with exc(SomeError): + # raise SomeError() + # raises AssertionError otherwise. + @contextmanager + def exc(exception_class, *args): + try: + yield + except exception_class, err: + for i, expected_arg in enumerate(args): + assert expected_arg == err.args[i], \ + "Raised %s, but args[%s] is %r instead of %r" % \ + (err.__class__.__name__, i, err.args[i], expected_arg) + print "Caught expected exception %s(%s)" % \ + (err.__class__.__name__, ', '.join(repr(arg) for arg in err.args)) + else: + assert False, "Failed to raise " + exception_class.__class__.__name__ + + # helper to raise specified exception + def raiser(exception): + raise exception + + # the usual + def assert_equals(a, b): + assert a == b, "%r != %r" % (a, b) + + # ------------------------ Sanity check the above ------------------------ + class SomeError(Exception): pass + # Without extra args, accept any err.args value + with exc(SomeError): + raiser(SomeError("abc")) + # With extra args, accept only the specified value + with exc(SomeError, "abc"): + raiser(SomeError("abc")) + with exc(AssertionError): + with exc(SomeError, "abc"): + raiser(SomeError("def")) + with exc(AssertionError): + with exc(socket.error, errno.EADDRINUSE): + raiser(socket.error(errno.ECONNREFUSED, 'Connection refused')) + + # ----------- freeport() without engaging socket functionality ----------- + # If portlist is empty, freeport() raises StopIteration. + with exc(StopIteration): + freeport([], None) + + assert_equals(freeport([17], str), ("17", 17)) + + # This is the magic exception that should prompt us to retry + inuse = socket.error(errno.EADDRINUSE, 'Address already in use') + # Get the iterator to our ports list so we can check later if we've used all + ports = iter(xrange(5)) + with exc(socket.error, errno.EADDRINUSE): + freeport(ports, lambda port: raiser(inuse)) + # did we entirely exhaust 'ports'? + with exc(StopIteration): + ports.next() + + ports = iter(xrange(2)) + # Any exception but EADDRINUSE should quit immediately + with exc(SomeError): + freeport(ports, lambda port: raiser(SomeError())) + assert_equals(ports.next(), 1) + + # ----------- freeport() with platform-dependent socket stuff ------------ + # This is what we should've had unit tests to begin with (see CHOP-661). + def newbind(port): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.bind(('127.0.0.1', port)) + return sock + + bound0, port0 = freeport(xrange(7777, 7780), newbind) + assert_equals(port0, 7777) + bound1, port1 = freeport(xrange(7777, 7780), newbind) + assert_equals(port1, 7778) + bound2, port2 = freeport(xrange(7777, 7780), newbind) + assert_equals(port2, 7779) + with exc(socket.error, errno.EADDRINUSE): + bound3, port3 = freeport(xrange(7777, 7780), newbind) + +if __name__ == "__main__": + test_freeport() |