summaryrefslogtreecommitdiff
path: root/indra/llmessage/tests
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmessage/tests')
-rw-r--r--indra/llmessage/tests/llareslistener_test.cpp200
-rw-r--r--indra/llmessage/tests/llcurl_stub.cpp1
-rw-r--r--indra/llmessage/tests/llmockhttpclient.h61
-rw-r--r--indra/llmessage/tests/llregionpresenceverifier_test.cpp113
-rw-r--r--indra/llmessage/tests/test_llsdmessage_peer.py30
-rw-r--r--indra/llmessage/tests/testrunner.py53
6 files changed, 431 insertions, 27 deletions
diff --git a/indra/llmessage/tests/llareslistener_test.cpp b/indra/llmessage/tests/llareslistener_test.cpp
new file mode 100644
index 0000000000..ac4886ccf4
--- /dev/null
+++ b/indra/llmessage/tests/llareslistener_test.cpp
@@ -0,0 +1,200 @@
+/**
+ * @file llareslistener_test.cpp
+ * @author Mark Palange
+ * @date 2009-02-26
+ * @brief Tests of llareslistener.h.
+ *
+ * $LicenseInfo:firstyear=2009&license=internal$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if LL_WINDOWS
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
+#endif
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "../llareslistener.h"
+// STL headers
+#include <iostream>
+// std headers
+// external library headers
+#include <boost/bind.hpp>
+
+// other Linden headers
+#include "llsd.h"
+#include "llares.h"
+#include "../test/lltut.h"
+#include "llevents.h"
+#include "tests/wrapllerrs.h"
+
+/*****************************************************************************
+* Dummy stuff
+*****************************************************************************/
+LLAres::LLAres():
+ // Simulate this much of the real LLAres constructor: we need an
+ // LLAresListener instance.
+ mListener(new LLAresListener("LLAres", this))
+{}
+LLAres::~LLAres() {}
+void LLAres::rewriteURI(const std::string &uri,
+ LLAres::UriRewriteResponder *resp)
+{
+ // This is the only LLAres method I chose to implement.
+ // The effect is that LLAres returns immediately with
+ // a result that is equal to the input uri.
+ std::vector<std::string> result;
+ result.push_back(uri);
+ resp->rewriteResult(result);
+}
+
+LLAres::QueryResponder::~QueryResponder() {}
+void LLAres::QueryResponder::queryError(int) {}
+void LLAres::QueryResponder::queryResult(char const*, size_t) {}
+LLQueryResponder::LLQueryResponder() {}
+void LLQueryResponder::queryResult(char const*, size_t) {}
+void LLQueryResponder::querySuccess() {}
+void LLAres::UriRewriteResponder::queryError(int) {}
+void LLAres::UriRewriteResponder::querySuccess() {}
+void LLAres::UriRewriteResponder::rewriteResult(const std::vector<std::string>& uris) {}
+
+/*****************************************************************************
+* TUT
+*****************************************************************************/
+namespace tut
+{
+ struct data
+ {
+ LLAres dummyAres;
+ };
+ typedef test_group<data> llareslistener_group;
+ typedef llareslistener_group::object object;
+ llareslistener_group llareslistenergrp("llareslistener");
+
+ struct ResponseCallback
+ {
+ std::vector<std::string> mURIs;
+ bool operator()(const LLSD& response)
+ {
+ mURIs.clear();
+ for (LLSD::array_const_iterator ri(response.beginArray()), rend(response.endArray());
+ ri != rend; ++ri)
+ {
+ mURIs.push_back(*ri);
+ }
+ return false;
+ }
+ };
+
+ template<> template<>
+ void object::test<1>()
+ {
+ set_test_name("test event");
+ // Tests the success and failure cases, since they both use
+ // the same code paths in the LLAres responder.
+ ResponseCallback response;
+ std::string pumpname("trigger");
+ // Since we're asking LLEventPumps to obtain() the pump by the desired
+ // name, it will persist beyond the current scope, so ensure we
+ // disconnect from it when 'response' goes away.
+ LLTempBoundListener temp(
+ LLEventPumps::instance().obtain(pumpname).listen("rewriteURIresponse",
+ boost::bind(&ResponseCallback::operator(), &response, _1)));
+ // Now build an LLSD request that will direct its response events to
+ // that pump.
+ const std::string testURI("login.bar.com");
+ LLSD request;
+ request["op"] = "rewriteURI";
+ request["uri"] = testURI;
+ request["reply"] = pumpname;
+ LLEventPumps::instance().obtain("LLAres").post(request);
+ ensure_equals(response.mURIs.size(), 1);
+ ensure_equals(response.mURIs.front(), testURI);
+ }
+
+ template<> template<>
+ void object::test<2>()
+ {
+ set_test_name("bad op");
+ WrapLL_ERRS capture;
+ LLSD request;
+ request["op"] = "foo";
+ std::string threw;
+ try
+ {
+ LLEventPumps::instance().obtain("LLAres").post(request);
+ }
+ catch (const WrapLL_ERRS::FatalException& e)
+ {
+ threw = e.what();
+ }
+ ensure_contains("LLAresListener bad op", threw, "bad");
+ }
+
+ template<> template<>
+ void object::test<3>()
+ {
+ set_test_name("bad rewriteURI request");
+ WrapLL_ERRS capture;
+ LLSD request;
+ request["op"] = "rewriteURI";
+ std::string threw;
+ try
+ {
+ LLEventPumps::instance().obtain("LLAres").post(request);
+ }
+ catch (const WrapLL_ERRS::FatalException& e)
+ {
+ threw = e.what();
+ }
+ ensure_contains("LLAresListener bad req", threw, "missing");
+ ensure_contains("LLAresListener bad req", threw, "reply");
+ ensure_contains("LLAresListener bad req", threw, "uri");
+ }
+
+ template<> template<>
+ void object::test<4>()
+ {
+ set_test_name("bad rewriteURI request");
+ WrapLL_ERRS capture;
+ LLSD request;
+ request["op"] = "rewriteURI";
+ request["reply"] = "nonexistent";
+ std::string threw;
+ try
+ {
+ LLEventPumps::instance().obtain("LLAres").post(request);
+ }
+ catch (const WrapLL_ERRS::FatalException& e)
+ {
+ threw = e.what();
+ }
+ ensure_contains("LLAresListener bad req", threw, "missing");
+ ensure_contains("LLAresListener bad req", threw, "uri");
+ ensure_does_not_contain("LLAresListener bad req", threw, "reply");
+ }
+
+ template<> template<>
+ void object::test<5>()
+ {
+ set_test_name("bad rewriteURI request");
+ WrapLL_ERRS capture;
+ LLSD request;
+ request["op"] = "rewriteURI";
+ request["uri"] = "foo.bar.com";
+ std::string threw;
+ try
+ {
+ LLEventPumps::instance().obtain("LLAres").post(request);
+ }
+ catch (const WrapLL_ERRS::FatalException& e)
+ {
+ threw = e.what();
+ }
+ ensure_contains("LLAresListener bad req", threw, "missing");
+ ensure_contains("LLAresListener bad req", threw, "reply");
+ ensure_does_not_contain("LLAresListener bad req", threw, "uri");
+ }
+}
diff --git a/indra/llmessage/tests/llcurl_stub.cpp b/indra/llmessage/tests/llcurl_stub.cpp
index 5dc5932fde..e6a5ad9946 100644
--- a/indra/llmessage/tests/llcurl_stub.cpp
+++ b/indra/llmessage/tests/llcurl_stub.cpp
@@ -22,6 +22,7 @@
#include "linden_common.h"
LLCurl::Responder::Responder()
+ : mReferenceCount(0)
{
}
diff --git a/indra/llmessage/tests/llmockhttpclient.h b/indra/llmessage/tests/llmockhttpclient.h
new file mode 100644
index 0000000000..2f55e97fcc
--- /dev/null
+++ b/indra/llmessage/tests/llmockhttpclient.h
@@ -0,0 +1,61 @@
+/**
+ * @file
+ * @brief
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
+ * this source code is governed by the Linden Lab Source Code Disclosure
+ * Agreement ("Agreement") previously entered between you and Linden
+ * Lab. By accessing, using, copying, modifying or distributing this
+ * software, you acknowledge that you have been informed of your
+ * obligations under the Agreement and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+/* Macro Definitions */
+#ifndef LL_LLMOCKHTTPCLIENT_H
+#define LL_LLMOCKHTTPCLIENT_H
+
+#include "linden_common.h"
+#include "llhttpclientinterface.h"
+
+#include <gmock/gmock.h>
+
+class LLMockHTTPClient : public LLHTTPClientInterface
+{
+public:
+ MOCK_METHOD2(get, void(const std::string& url, LLCurl::ResponderPtr responder));
+ MOCK_METHOD3(get, void(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers));
+ MOCK_METHOD3(put, void(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder));
+};
+
+// A helper to match responder types
+template<typename T>
+struct ResponderType
+{
+ bool operator()(LLCurl::ResponderPtr ptr) const
+ {
+ T* p = dynamic_cast<T*>(ptr.get());
+ return p != NULL;
+ }
+};
+
+inline bool operator==(const LLSD& l, const LLSD& r)
+{
+ std::ostringstream ls, rs;
+ ls << l;
+ rs << r;
+ return ls.str() == rs.str();
+
+}
+
+
+#endif //LL_LLMOCKHTTPCLIENT_H
+
diff --git a/indra/llmessage/tests/llregionpresenceverifier_test.cpp b/indra/llmessage/tests/llregionpresenceverifier_test.cpp
new file mode 100644
index 0000000000..c86126406e
--- /dev/null
+++ b/indra/llmessage/tests/llregionpresenceverifier_test.cpp
@@ -0,0 +1,113 @@
+/**
+ * @file
+ * @brief
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2001-2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/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 test");
+}
+
+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/test_llsdmessage_peer.py b/indra/llmessage/tests/test_llsdmessage_peer.py
index e62f20912b..86d5761b1b 100644
--- a/indra/llmessage/tests/test_llsdmessage_peer.py
+++ b/indra/llmessage/tests/test_llsdmessage_peer.py
@@ -16,16 +16,12 @@ import os
import sys
from threading import Thread
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
+
mydir = os.path.dirname(__file__) # expected to be .../indra/llmessage/tests/
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
-
-def debug(*args):
- sys.stdout.writelines(args)
- sys.stdout.flush()
-# comment out the line below to enable debug output
-debug = lambda *args: None
+from testrunner import run, debug
class TestHTTPRequestHandler(BaseHTTPRequestHandler):
"""This subclass of BaseHTTPRequestHandler is to receive and echo
@@ -106,25 +102,5 @@ class TestHTTPServer(Thread):
debug("Starting HTTP server...\n")
httpd.serve_forever()
-def main(*args):
- # Start HTTP server thread. Note that this and all other comm server
- # threads should be daemon threads: we'll let them run "forever,"
- # confident that the whole process will terminate when the main thread
- # terminates, which will be when the test executable child process
- # terminates.
- httpThread = TestHTTPServer(name="httpd")
- httpThread.setDaemon(True)
- httpThread.start()
- # choice of os.spawnv():
- # - [v vs. l] pass a list of args vs. individual arguments,
- # - [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()
- rc = os.spawnv(os.P_WAIT, args[0], args)
- debug("%s returned %s\n" % (args[0], rc))
- return rc
-
if __name__ == "__main__":
- sys.exit(main(*sys.argv[1:]))
+ sys.exit(run(server=TestHTTPServer(name="httpd"), *sys.argv[1:]))
diff --git a/indra/llmessage/tests/testrunner.py b/indra/llmessage/tests/testrunner.py
new file mode 100644
index 0000000000..3b9c3a7a19
--- /dev/null
+++ b/indra/llmessage/tests/testrunner.py
@@ -0,0 +1,53 @@
+#!/usr/bin/python
+"""\
+@file testrunner.py
+@author Nat Goodspeed
+@date 2009-03-20
+@brief Utilities for writing wrapper scripts for ADD_COMM_BUILD_TEST unit tests
+
+$LicenseInfo:firstyear=2009&license=viewergpl$
+Copyright (c) 2009, Linden Research, Inc.
+$/LicenseInfo$
+"""
+
+import os
+import sys
+
+def debug(*args):
+ sys.stdout.writelines(args)
+ sys.stdout.flush()
+# comment out the line below to enable debug output
+debug = lambda *args: None
+
+def run(*args, **kwds):
+ """All positional arguments collectively form a command line, executed as
+ a synchronous child process.
+ In addition, pass server=new_thread_instance as an explicit keyword (to
+ differentiate it from an additional command-line argument).
+ new_thread_instance should be an instantiated but not yet started Thread
+ subclass instance, e.g.:
+ run("python", "-c", 'print "Hello, world!"', server=TestHTTPServer(name="httpd"))
+ """
+ # If there's no server= keyword arg, don't start a server thread: simply
+ # run a child process.
+ try:
+ thread = kwds.pop("server")
+ except KeyError:
+ pass
+ else:
+ # Start server thread. Note that this and all other comm server
+ # threads should be daemon threads: we'll let them run "forever,"
+ # confident that the whole process will terminate when the main thread
+ # terminates, which will be when the child process terminates.
+ thread.setDaemon(True)
+ thread.start()
+ # choice of os.spawnv():
+ # - [v vs. l] pass a list of args vs. individual arguments,
+ # - [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()
+ rc = os.spawnv(os.P_WAIT, args[0], args)
+ debug("%s returned %s\n" % (args[0], rc))
+ return rc