diff options
| author | Steve Bennetts <steve@lindenlab.com> | 2009-10-20 10:52:53 -0700 | 
|---|---|---|
| committer | Steve Bennetts <steve@lindenlab.com> | 2009-10-20 10:52:53 -0700 | 
| commit | afcccc3b36d96ababe61ca04dc6c9e02f4b20d81 (patch) | |
| tree | f351783fb94e36ba6229bf4a9531eb4e42a4272f /indra/llmessage/tests | |
| parent | 91fe3e7c790317420619aff1aae9ae14d38fa606 (diff) | |
| parent | aa75245a1aee3b64aeed31744e58fe96afa1ce7e (diff) | |
merge
Diffstat (limited to 'indra/llmessage/tests')
| -rw-r--r-- | indra/llmessage/tests/llareslistener_test.cpp | 200 | ||||
| -rw-r--r-- | indra/llmessage/tests/llcurl_stub.cpp | 1 | ||||
| -rw-r--r-- | indra/llmessage/tests/llhost_test.cpp | 16 | ||||
| -rw-r--r-- | indra/llmessage/tests/llmockhttpclient.h | 61 | ||||
| -rw-r--r-- | indra/llmessage/tests/llregionpresenceverifier_test.cpp | 113 | ||||
| -rw-r--r-- | indra/llmessage/tests/test_llsdmessage_peer.py | 30 | ||||
| -rw-r--r-- | indra/llmessage/tests/testrunner.py | 53 | 
7 files changed, 446 insertions, 28 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/llhost_test.cpp b/indra/llmessage/tests/llhost_test.cpp index 6dbdcb86e7..4c9e75456a 100644 --- a/indra/llmessage/tests/llhost_test.cpp +++ b/indra/llmessage/tests/llhost_test.cpp @@ -166,7 +166,21 @@ namespace tut  		// the main domain name and not do the exact compare  		std::string hostname = host.getHostName(); -		ensure("getHostName failed", hostname.find(hostStr) != std::string::npos); +/*==========================================================================*| +		// nat 2009-10-20: not sure this ensure() is such a good idea, at +		// least with "google.com". The logic below is failing for me with: +		// set 'google.com'; reported 'yx-in-f100.1e100.net' +		// Disabling test until we can replace it with something more robust. +		try +		{ +			ensure("getHostName failed", hostname.find(hostStr) != std::string::npos); +		} +		catch (const std::exception&) +		{ +			std::cerr << "set '" << hostStr << "'; reported '" << hostname << "'" << std::endl; +			throw; +		} +|*==========================================================================*/  	}  //	setHostByName for dotted IP 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 | 
