diff options
Diffstat (limited to 'indra/newview/tests')
| -rw-r--r-- | indra/newview/tests/llagentaccess_test.cpp | 40 | ||||
| -rw-r--r-- | indra/newview/tests/llcapabilitylistener_test.cpp | 58 | ||||
| -rw-r--r-- | indra/newview/tests/lldateutil_test.cpp | 186 | ||||
| -rw-r--r-- | indra/newview/tests/lllogininstance_test.cpp | 527 | ||||
| -rw-r--r-- | indra/newview/tests/llmediadataclient_test.cpp | 969 | ||||
| -rw-r--r-- | indra/newview/tests/llsecapi_test.cpp | 122 | ||||
| -rw-r--r-- | indra/newview/tests/llsechandler_basic_test.cpp | 1065 | ||||
| -rw-r--r-- | indra/newview/tests/llslurl_test.cpp | 260 | ||||
| -rw-r--r-- | indra/newview/tests/lltextureinfo_test.cpp | 278 | ||||
| -rw-r--r-- | indra/newview/tests/lltextureinfodetails_test.cpp | 92 | ||||
| -rw-r--r-- | indra/newview/tests/lltexturestatsuploader_test.cpp | 150 | ||||
| -rw-r--r-- | indra/newview/tests/llviewerhelputil_test.cpp | 165 | ||||
| -rw-r--r-- | indra/newview/tests/llviewernetwork_test.cpp | 581 | ||||
| -rw-r--r-- | indra/newview/tests/llworldmap_test.cpp | 517 | ||||
| -rw-r--r-- | indra/newview/tests/llworldmipmap_test.cpp | 170 | ||||
| -rw-r--r-- | indra/newview/tests/llxmlrpclistener_test.cpp | 247 | ||||
| -rw-r--r-- | indra/newview/tests/test_llxmlrpc_peer.py | 76 | 
17 files changed, 5450 insertions, 53 deletions
diff --git a/indra/newview/tests/llagentaccess_test.cpp b/indra/newview/tests/llagentaccess_test.cpp index 42872d85fb..c970d79975 100644 --- a/indra/newview/tests/llagentaccess_test.cpp +++ b/indra/newview/tests/llagentaccess_test.cpp @@ -2,33 +2,29 @@   * @file llagentaccess_test.cpp   * @brief LLAgentAccess tests   * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - *  - * Copyright (c) 2001-2009, Linden Research, Inc. - *  + * $LicenseInfo:firstyear=2001&license=viewerlgpl$   * 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://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc.   *  - * 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://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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.   *  - * 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. + * 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.   *  - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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 "../llagentaccess.h" @@ -78,7 +74,7 @@ namespace tut  	typedef test_group<agentaccess> agentaccess_t;  	typedef agentaccess_t::object agentaccess_object_t; -	tut::agentaccess_t tut_agentaccess("agentaccess"); +	tut::agentaccess_t tut_agentaccess("LLAgentAccess");  	template<> template<>  	void agentaccess_object_t::test<1>() diff --git a/indra/newview/tests/llcapabilitylistener_test.cpp b/indra/newview/tests/llcapabilitylistener_test.cpp index f66ae9404f..9da851ffc4 100644 --- a/indra/newview/tests/llcapabilitylistener_test.cpp +++ b/indra/newview/tests/llcapabilitylistener_test.cpp @@ -4,8 +4,25 @@   * @date   2008-12-31   * @brief  Test for llcapabilitylistener.cpp.   *  - * $LicenseInfo:firstyear=2008&license=viewergpl$ - * Copyright (c) 2008, Linden Research, Inc. + * $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$   */ @@ -24,9 +41,10 @@  #include "../test/lltut.h"  #include "../llcapabilityprovider.h"  #include "lluuid.h" -#include "llerrorcontrol.h"  #include "tests/networkio.h"  #include "tests/commtest.h" +#include "tests/wrapllerrs.h" +#include "message.h"  #include "stringize.h"  #if defined(LL_WINDOWS) @@ -104,28 +122,6 @@ namespace tut      typedef llcapears_group::object llcapears_object;      llcapears_group llsdmgr("llcapabilitylistener"); -    struct CaptureError: public LLError::OverrideFatalFunction -    { -        CaptureError(): -            LLError::OverrideFatalFunction(boost::bind(&CaptureError::operator(), this, _1)) -        { -            LLError::setPrintLocation(false); -        } - -        struct FatalException: public std::runtime_error -        { -            FatalException(const std::string& what): std::runtime_error(what) {} -        }; - -        void operator()(const std::string& message) -        { -            error = message; -            throw FatalException(message); -        } - -        std::string error; -    }; -      template<> template<>      void llcapears_object::test<1>()      { @@ -137,10 +133,10 @@ namespace tut          std::string threw;          try          { -            CaptureError capture; +            WrapLL_ERRS capture;              regionPump.post(request);          } -        catch (const CaptureError::FatalException& e) +        catch (const WrapLL_ERRS::FatalException& e)          {              threw = e.what();          } @@ -184,10 +180,10 @@ namespace tut          std::string threw;          try          { -            CaptureError capture; +            WrapLL_ERRS capture;              regionPump.post(request);          } -        catch (const CaptureError::FatalException& e) +        catch (const WrapLL_ERRS::FatalException& e)          {              threw = e.what();          } @@ -246,10 +242,10 @@ namespace tut          std::string threw;          try          { -            CaptureError capture; +            WrapLL_ERRS capture;              regionPump.post(request);          } -        catch (const CaptureError::FatalException& e) +        catch (const WrapLL_ERRS::FatalException& e)          {              threw = e.what();          } diff --git a/indra/newview/tests/lldateutil_test.cpp b/indra/newview/tests/lldateutil_test.cpp new file mode 100644 index 0000000000..99b346cff8 --- /dev/null +++ b/indra/newview/tests/lldateutil_test.cpp @@ -0,0 +1,186 @@ +/**  + * @file lldateutil_test.cpp + * + * $LicenseInfo:firstyear=2001&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 "../lldateutil.h" + +#include "lldate.h" +#include "llstring.h"	// LLStringUtil::format() +#include "lltrans.h" +#include "llui.h" + +#include <map> + + +// Baked-in return values for getString() +std::map< std::string, std::string > gString; + +// Baked-in return values for getCountString() +// map of pairs of input xml_desc and integer count +typedef std::pair< std::string, int > count_string_t; +std::map< count_string_t, std::string > gCountString; + +std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args) +{ +	std::string text = gString[xml_desc]; +	LLStringUtil::format(text, args); +	return text; +} + +std::string LLTrans::getCountString(const std::string& language, const std::string& xml_desc, S32 count) +{ +	count_string_t key(xml_desc, count); +	if (gCountString.find(key) == gCountString.end()) +	{ +		return std::string("Couldn't find ") + xml_desc; +	} +	return gCountString[ count_string_t(xml_desc, count) ]; +} + +std::string LLUI::getLanguage() +{ +	return "en"; +} + +namespace tut +{ +    struct dateutil +    { +		// Hard-code a "now" date so unit test doesn't change with +		// current time.  Because server strings are in Pacific time +		// roll this forward 8 hours to compensate.  This represents +		// 2009-12-31T00:00:00Z UTC. +		dateutil() +			:	mNow(std::string("2009-12-31T08:00:00Z")) +		{ +			// copied from strings.xml +			gString["YearsMonthsOld"] = "[AGEYEARS] [AGEMONTHS] old"; +			gString["YearsOld"] = "[AGEYEARS] old"; +			gString["MonthsOld"] = "[AGEMONTHS] old"; +			gString["WeeksOld"] = "[AGEWEEKS] old"; +			gString["DaysOld"] = "[AGEDAYS] old"; +			gString["TodayOld"] = "Joined today"; + +			gCountString[ count_string_t("AgeYears", 1) ]  = "1 year"; +			gCountString[ count_string_t("AgeYears", 2) ]  = "2 years"; +			gCountString[ count_string_t("AgeMonths", 1) ] = "1 month"; +			gCountString[ count_string_t("AgeMonths", 2) ] = "2 months"; +			gCountString[ count_string_t("AgeMonths", 11) ]= "11 months"; +			gCountString[ count_string_t("AgeWeeks", 1) ]  = "1 week"; +			gCountString[ count_string_t("AgeWeeks", 2) ]  = "2 weeks"; +			gCountString[ count_string_t("AgeWeeks", 3) ]  = "3 weeks"; +			gCountString[ count_string_t("AgeWeeks", 4) ]  = "4 weeks"; +			gCountString[ count_string_t("AgeDays", 1) ]   = "1 day"; +			gCountString[ count_string_t("AgeDays", 2) ]   = "2 days"; +		} +		LLDate mNow; +    }; +     +	typedef test_group<dateutil> dateutil_t; +	typedef dateutil_t::object dateutil_object_t; +	tut::dateutil_t tut_dateutil("LLDateUtil"); + +	template<> template<> +	void dateutil_object_t::test<1>() +	{ +		set_test_name("Years"); +		ensure_equals("years + months", +			LLDateUtil::ageFromDate("10/30/2007", mNow), +			"2 years 2 months old" ); +		ensure_equals("years", +			LLDateUtil::ageFromDate("12/31/2007", mNow), +			"2 years old" ); +		ensure_equals("years", +			LLDateUtil::ageFromDate("1/1/2008", mNow), +			"1 year 11 months old" ); +		ensure_equals("single year + one month", +			LLDateUtil::ageFromDate("11/30/2008", mNow), +			"1 year 1 month old" ); +		ensure_equals("single year + a bit", +			LLDateUtil::ageFromDate("12/12/2008", mNow), +			"1 year old" ); +		ensure_equals("single year", +			LLDateUtil::ageFromDate("12/31/2008", mNow), +			"1 year old" ); +    } + +	template<> template<> +	void dateutil_object_t::test<2>() +	{ +		set_test_name("Months"); +		ensure_equals("months", +			LLDateUtil::ageFromDate("10/30/2009", mNow), +			"2 months old" ); +		ensure_equals("months 2", +			LLDateUtil::ageFromDate("10/31/2009", mNow), +			"2 months old" ); +		ensure_equals("single month", +			LLDateUtil::ageFromDate("11/30/2009", mNow), +			"1 month old" ); +	} + +	template<> template<> +	void dateutil_object_t::test<3>() +	{ +		set_test_name("Weeks"); +		ensure_equals("4 weeks", +			LLDateUtil::ageFromDate("12/1/2009", mNow), +			"4 weeks old" ); +		ensure_equals("weeks", +			LLDateUtil::ageFromDate("12/17/2009", mNow), +			"2 weeks old" ); +		ensure_equals("single week", +			LLDateUtil::ageFromDate("12/24/2009", mNow), +			"1 week old" ); +	} + +	template<> template<> +	void dateutil_object_t::test<4>() +	{ +		set_test_name("Days"); +		ensure_equals("days", +			LLDateUtil::ageFromDate("12/29/2009", mNow), +			"2 days old" ); +		ensure_equals("single day", +			LLDateUtil::ageFromDate("12/30/2009", mNow), +			"1 day old" ); +		ensure_equals("today", +			LLDateUtil::ageFromDate("12/31/2009", mNow), +			"Joined today" ); +	} + +	template<> template<> +	void dateutil_object_t::test<5>() +	{ +		set_test_name("2010 rollover"); +		LLDate now(std::string("2010-01-04T12:00:00Z")); +		ensure_equals("days", +			LLDateUtil::ageFromDate("12/13/2009", now), +			"3 weeks old" ); +	} +} diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp new file mode 100644 index 0000000000..55823fc386 --- /dev/null +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -0,0 +1,527 @@ +/** + * @file   lllogininstance_test.cpp + * @brief  Test for lllogininstance.cpp. + *  + * $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$ + */ + +// Precompiled header +#include "../llviewerprecompiledheaders.h" +// Own header +#include "../llsecapi.h" +#include "../llviewernetwork.h" +#include "../lllogininstance.h" + +// STL headers +// std headers +// external library headers +// other Linden headers +#include "../test/lltut.h" +#include "llevents.h" + +#if defined(LL_WINDOWS) +#pragma warning(disable: 4355)      // using 'this' in base-class ctor initializer expr +#endif + +// Constants +const std::string VIEWERLOGIN_URI("viewerlogin_uri"); +const std::string VIEWERLOGIN_GRIDLABEL("viewerlogin_grid"); + +const std::string APPVIEWER_SERIALNUMBER("appviewer_serialno"); + +// Link seams. + +//----------------------------------------------------------------------------- +static LLEventStream gTestPump("test_pump"); + +#include "../llslurl.h" +#include "../llstartup.h" +LLSLURL LLStartUp::sStartSLURL; + +#include "lllogin.h" + +static std::string gLoginURI; +static LLSD gLoginCreds; +static bool gDisconnectCalled = false; +class LLLogin::Impl +{ +}; +LLLogin::LLLogin() {} +LLLogin::~LLLogin() {} +LLEventPump& LLLogin::getEventPump() { return gTestPump; } +void LLLogin::connect(const std::string& uri, const LLSD& credentials)  +{ +	gLoginURI = uri; +	gLoginCreds = credentials; +} + +void LLLogin::disconnect()  +{ +	gDisconnectCalled = true; +} + +LLSD LLCredential::getLoginParams() +{ +	LLSD result = LLSD::emptyMap(); + +	// legacy credential +	result["passwd"] = "$1$testpasssd"; +	result["first"] = "myfirst"; +	result["last"] ="mylast"; +	return result; +} +void LLCredential::identifierType(std::string &idType) +{ +} + +void LLCredential::authenticatorType(std::string &idType) +{ +} + +//----------------------------------------------------------------------------- +#include "../llviewernetwork.h" +LLGridManager::~LLGridManager() +{ +} + +void LLGridManager::addGrid(LLSD& grid_data) +{ +} +LLGridManager::LLGridManager() +{	 +} + +void LLGridManager::getLoginURIs(std::vector<std::string>& uris) +{ +	uris.push_back(VIEWERLOGIN_URI); +} + +void LLGridManager::addSystemGrid(const std::string& label,  +								  const std::string& name,  +								  const std::string& login,  +								  const std::string& helper, +								  const std::string& login_page, +								  const std::string& login_id) +{ +} +std::map<std::string, std::string> LLGridManager::getKnownGrids(bool favorite_only) +{ +	std::map<std::string, std::string> result; +	return result; +} + +void LLGridManager::setGridChoice(const std::string& grid_name) +{ +} + +bool LLGridManager::isInProductionGrid() +{ +	return false; +} + +void LLGridManager::saveFavorites() +{} +std::string LLGridManager::getSLURLBase(const std::string& grid_name) +{ +	return "myslurl"; +} +std::string LLGridManager::getAppSLURLBase(const std::string& grid_name) +{ +	return "myappslurl"; +} + +//----------------------------------------------------------------------------- +#include "../llviewercontrol.h" +LLControlGroup gSavedSettings("Global"); +std::string gCurrentVersion = "invalid_version"; + +LLControlGroup::LLControlGroup(const std::string& name) : +	LLInstanceTracker<LLControlGroup, std::string>(name){} +LLControlGroup::~LLControlGroup() {} +void LLControlGroup::setBOOL(const std::string& name, BOOL val) {} +BOOL LLControlGroup::getBOOL(const std::string& name) { return FALSE; } +F32 LLControlGroup::getF32(const std::string& name) { return 0.0f; } +U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only) { return 1; } +void LLControlGroup::setString(const std::string& name, const std::string& val) {} +std::string LLControlGroup::getString(const std::string& name) { return "test_string"; } +BOOL LLControlGroup::declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, BOOL persist) { return TRUE; } +BOOL LLControlGroup::declareString(const std::string& name, const std::string &initial_val, const std::string& comment, BOOL persist) { return TRUE; } + +#include "lluicolortable.h" +void LLUIColorTable::saveUserSettings(void)const {} + + +//----------------------------------------------------------------------------- +#include "llnotifications.h" +#include "llfloaterreg.h" +static std::string gTOSType; +static LLEventPump * gTOSReplyPump = NULL; + +//static +LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key, BOOL focus) +{ +	gTOSType = name; +	gTOSReplyPump = &LLEventPumps::instance().obtain(key["reply_pump"]); +	return NULL; +} + +//----------------------------------------------------------------------------- +// LLNotifications +class MockNotifications : public LLNotificationsInterface +{ +	boost::function<void (const LLSD&, const LLSD&)> mResponder; +	int mAddedCount; + +public:  +	MockNotifications() : +		mResponder(0), +		mAddedCount(0) +	{ +	} + +	virtual ~MockNotifications() {} + +	/* virtual */ LLNotificationPtr add( +					const std::string& name, +					const LLSD& substitutions, +					const LLSD& payload,  +					LLNotificationFunctorRegistry::ResponseFunctor functor) +	{ +		mResponder = functor; +		mAddedCount++; +		return LLNotificationPtr((LLNotification*)NULL); +	} + +	void sendYesResponse() +	{ +		LLSD notification; +		LLSD response; +		response = 1; +		mResponder(notification, response); +	} + +	void sendNoResponse() +	{ +		LLSD notification; +		LLSD response; +		response = 2; +		mResponder(notification, response); +	} + +	void sendBogusResponse() +	{ +		LLSD notification; +		LLSD response; +		response = 666; +		mResponder(notification, response); +	} + +	int addedCount() { return mAddedCount; } +}; + +S32 LLNotification::getSelectedOption(const LLSD& notification, const LLSD& response) +{ +	return response.asInteger(); +} + +//----------------------------------------------------------------------------- +#include "../llmachineid.h" +unsigned char gMACAddress[MAC_ADDRESS_BYTES] = {77,21,46,31,89,2}; + +S32 LLMachineID::getUniqueID(unsigned char *unique_id, size_t len) +{ +	memcpy(unique_id, gMACAddress, len); +	return 1; +} +//----------------------------------------------------------------------------- +// misc +std::string xml_escape_string(const std::string& in) +{ +	return in; +} + +/***************************************************************************** +*   TUT +*****************************************************************************/ +namespace tut +{ +    struct lllogininstance_data +    { +		lllogininstance_data() : logininstance(LLLoginInstance::getInstance()) +		{ +			// Global initialization +			gLoginURI.clear(); +			gLoginCreds.clear(); +			gDisconnectCalled = false; + +			gTOSType = ""; // Set to invalid value. +			gTOSReplyPump = 0; // clear the callback. + + +			gSavedSettings.declareBOOL("NoInventoryLibrary", FALSE, "", FALSE); +			gSavedSettings.declareBOOL("ConnectAsGod", FALSE, "", FALSE); +			gSavedSettings.declareBOOL("UseDebugMenus", FALSE, "", FALSE); +			gSavedSettings.declareBOOL("ForceMandatoryUpdate", FALSE, "", FALSE); +			gSavedSettings.declareString("ClientSettingsFile", "test_settings.xml", "", FALSE); +			gSavedSettings.declareString("VersionChannelName", "test_version_string", "", FALSE); +			gSavedSettings.declareString("NextLoginLocation", "", "", FALSE); +			gSavedSettings.declareBOOL("LoginLastLocation", FALSE, "", FALSE); + +			LLSD authenticator = LLSD::emptyMap(); +			LLSD identifier = LLSD::emptyMap(); +			identifier["type"] = "agent"; +			identifier["first_name"] = "testfirst"; +			identifier["last_name"] = "testlast"; +			authenticator["passwd"] = "testpass"; +			agentCredential = new LLCredential(); +			agentCredential->setCredentialData(identifier, authenticator); +			 +			authenticator = LLSD::emptyMap(); +			identifier = LLSD::emptyMap(); +			identifier["type"] = "account"; +			identifier["username"] = "testuser"; +			authenticator["secret"] = "testsecret"; +			accountCredential = new LLCredential(); +			accountCredential->setCredentialData(identifier, authenticator);			 + +			logininstance->setNotificationsInterface(¬ifications); +		} + +		LLLoginInstance* logininstance; +		LLPointer<LLCredential> agentCredential; +		LLPointer<LLCredential> accountCredential; +		MockNotifications notifications; +    }; + +    typedef test_group<lllogininstance_data> lllogininstance_group; +    typedef lllogininstance_group::object lllogininstance_object; +    lllogininstance_group llsdmgr("LLLoginInstance"); + +    template<> template<> +    void lllogininstance_object::test<1>() +    { +		set_test_name("Test Simple Success And Disconnect"); + +		// Test default connect. +		logininstance->connect(agentCredential); + +		ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);  + +		// Dummy success response. +		LLSD response; +		response["state"] = "online"; +		response["change"] = "connect"; +		response["progress"] = 1.0; +		response["transfer_rate"] = 7; +		response["data"] = "test_data"; + +		gTestPump.post(response); + +		ensure("Success response", logininstance->authSuccess()); +		ensure_equals("Test Response Data", logininstance->getResponse().asString(), "test_data"); + +		logininstance->disconnect(); + +		ensure_equals("Called Login Module Disconnect", gDisconnectCalled, true); + +		response.clear(); +		response["state"] = "offline"; +		response["change"] = "disconnect"; +		response["progress"] = 0.0; +		response["transfer_rate"] = 0; +		response["data"] = "test_data"; + +		gTestPump.post(response); + +		ensure("Disconnected", !(logininstance->authSuccess())); +    } + +    template<> template<> +    void lllogininstance_object::test<2>() +    { +		set_test_name("Test User TOS/Critical message Interaction"); + +		const std::string test_uri = "testing-uri"; + +		// Test default connect. +		logininstance->connect(test_uri, agentCredential); + +		// connect should call LLLogin::connect to init gLoginURI and gLoginCreds. +		ensure_equals("Default connect uri", gLoginURI, "testing-uri");  +		ensure_equals("Default for agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), false); +		ensure_equals("Default for read critical", gLoginCreds["params"]["read_critical"].asBoolean(), false); + +		// TOS failure response. +		LLSD response; +		response["state"] = "offline"; +		response["change"] = "fail.login"; +		response["progress"] = 0.0; +		response["transfer_rate"] = 7; +		response["data"]["reason"] = "tos"; +		gTestPump.post(response); + +		ensure_equals("TOS Dialog type", gTOSType, "message_tos"); +		ensure("TOS callback given", gTOSReplyPump != 0); +		gTOSReplyPump->post(false); // Call callback denying TOS. +		ensure("No TOS, failed auth", logininstance->authFailure()); + +		// Start again. +		logininstance->connect(test_uri, agentCredential); +		gTestPump.post(response); // Fail for tos again. +		gTOSReplyPump->post(true); // Accept tos, should reconnect w/ agree_to_tos. +		ensure_equals("Accepted agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), true); +		ensure("Incomplete login status", !logininstance->authFailure() && !logininstance->authSuccess()); +	 +		// Fail connection, attempt connect again. +		// The new request should have reset agree to tos to default. +		response["data"]["reason"] = "key"; // bad creds. +		gTestPump.post(response); +		ensure("TOS auth failure", logininstance->authFailure()); + +		logininstance->connect(test_uri, agentCredential); +		ensure_equals("Reset to default for agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), false); + +		// Critical Message failure response. +		logininstance->connect(test_uri, agentCredential); +		response["data"]["reason"] = "critical"; // Change response to "critical message" +		gTestPump.post(response); + +		ensure_equals("TOS Dialog type", gTOSType, "message_critical"); +		ensure("TOS callback given", gTOSReplyPump != 0); +		gTOSReplyPump->post(true);  +		ensure_equals("Accepted read critical message", gLoginCreds["params"]["read_critical"].asBoolean(), true); +		ensure("Incomplete login status", !logininstance->authFailure() && !logininstance->authSuccess()); + +		// Fail then attempt new connection +		response["data"]["reason"] = "key"; // bad creds. +		gTestPump.post(response); +		ensure("TOS auth failure", logininstance->authFailure()); +		logininstance->connect(test_uri, agentCredential); +		ensure_equals("Default for agree to tos", gLoginCreds["params"]["read_critical"].asBoolean(), false); +	} + +    template<> template<> +    void lllogininstance_object::test<3>() +    { +		set_test_name("Test Mandatory Update User Accepts"); + +		// Part 1 - Mandatory Update, with User accepts response. +		// Test connect with update needed. +		logininstance->connect(agentCredential); + +		ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);  + +		// Update needed failure response. +		LLSD response; +		response["state"] = "offline"; +		response["change"] = "fail.login"; +		response["progress"] = 0.0; +		response["transfer_rate"] = 7; +		response["data"]["reason"] = "update"; +		gTestPump.post(response); + +		ensure_equals("Notification added", notifications.addedCount(), 1); + +		notifications.sendYesResponse(); + +		ensure("Disconnected", !(logininstance->authSuccess())); +	} + +	template<> template<> +    void lllogininstance_object::test<4>() +    { +		set_test_name("Test Mandatory Update User Decline"); + +		// Test connect with update needed. +		logininstance->connect(agentCredential); + +		ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);  + +		// Update needed failure response. +		LLSD response; +		response["state"] = "offline"; +		response["change"] = "fail.login"; +		response["progress"] = 0.0; +		response["transfer_rate"] = 7; +		response["data"]["reason"] = "update"; +		gTestPump.post(response); + +		ensure_equals("Notification added", notifications.addedCount(), 1); +		notifications.sendNoResponse(); + +		ensure("Disconnected", !(logininstance->authSuccess())); +	} + +	template<> template<> +    void lllogininstance_object::test<6>() +    { +		set_test_name("Test Optional Update User Accept"); + +		// Part 3 - Mandatory Update, with bogus response. +		// Test connect with update needed. +		logininstance->connect(agentCredential); + +		ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);  + +		// Update needed failure response. +		LLSD response; +		response["state"] = "offline"; +		response["change"] = "fail.login"; +		response["progress"] = 0.0; +		response["transfer_rate"] = 7; +		response["data"]["reason"] = "optional"; +		gTestPump.post(response); + +		ensure_equals("Notification added", notifications.addedCount(), 1); +		notifications.sendYesResponse(); + +		ensure("Disconnected", !(logininstance->authSuccess())); +	} + +	template<> template<> +    void lllogininstance_object::test<7>() +    { +		set_test_name("Test Optional Update User Denies"); + +		// Part 3 - Mandatory Update, with bogus response. +		// Test connect with update needed. +		logininstance->connect(agentCredential); + +		ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);  + +		// Update needed failure response. +		LLSD response; +		response["state"] = "offline"; +		response["change"] = "fail.login"; +		response["progress"] = 0.0; +		response["transfer_rate"] = 7; +		response["data"]["reason"] = "optional"; +		gTestPump.post(response); + +		ensure_equals("Notification added", notifications.addedCount(), 1); +		notifications.sendNoResponse(); + +		// User skips, should be reconnecting. +		ensure_equals("reconnect uri", gLoginURI, VIEWERLOGIN_URI);  +		ensure_equals("skipping optional update", gLoginCreds["params"]["skipoptional"].asBoolean(), true);  +	} +} diff --git a/indra/newview/tests/llmediadataclient_test.cpp b/indra/newview/tests/llmediadataclient_test.cpp new file mode 100644 index 0000000000..0254c5881f --- /dev/null +++ b/indra/newview/tests/llmediadataclient_test.cpp @@ -0,0 +1,969 @@ +/**  + * @file llmediadataclient_test.cpp + * @brief LLMediaDatClient tests + * + * $LicenseInfo:firstyear=2001&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 "../llviewerprecompiledheaders.h" +  +#include <iostream> +#include "../test/lltut.h" + +#include "llsdserialize.h" +#include "llsdutil.h" +#include "llerrorcontrol.h" +#include "llhttpstatuscodes.h" + +#include "../llmediadataclient.h" +#include "../llvovolume.h" + +#include "../../llprimitive/llmediaentry.cpp" +#include "../../llprimitive/lltextureentry.cpp" +#include "../../llmessage/tests/llcurl_stub.cpp" + +#if LL_WINDOWS +#pragma warning (push) +#pragma warning (disable : 4702) // boost::lexical_cast generates this warning +#endif +#include <boost/lexical_cast.hpp> +#if LL_WINDOWS +#pragma warning (pop) +#endif + +#define VALID_OBJECT_ID   "3607d5c4-644b-4a8a-871a-8b78471af2a2" +#define VALID_OBJECT_ID_1 "11111111-1111-1111-1111-111111111111" +#define VALID_OBJECT_ID_2 "22222222-2222-2222-2222-222222222222" +#define VALID_OBJECT_ID_3 "33333333-3333-3333-3333-333333333333" +#define VALID_OBJECT_ID_4 "44444444-4444-4444-4444-444444444444" + +#define FAKE_OBJECT_MEDIA_CAP_URL "foo_ObjectMedia" +#define FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL "foo_ObjectMediaNavigate" +#define FAKE_OBJECT_MEDIA_CAP_URL_503 "foo_ObjectMedia_503" +#define FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR "foo_ObjectMediaNavigate_ERROR" + +#define MEDIA_DATA "\ +<array>														\ +<string>http://foo.example.com</string>										\ +<string>http://bar.example.com</string>										\ +<string>baz</string>										\ +</array>" + +#define _DATA_URLS(ID,INTEREST,NEW,URL1,URL2) "					\ +<llsd>											\ +  <map>											\ +    <key>uuid</key>								\ +    <string>" ID "</string>						\ +    <key>interest</key>											\ +    <real>" INTEREST "</real>											\ +    <key>cap_urls</key>											\ +    <map>														\ +      <key>ObjectMedia</key>									\ +      <string>" URL1 "</string>			\ +      <key>ObjectMediaNavigate</key>							\ +      <string>" URL2 "</string>	\ +    </map>														\ +    <key>media_data</key>                                       \ +	" MEDIA_DATA "												\ +    <key>is_dead</key>											\ +	<boolean>false</boolean>									\ +	<key>is_new</key>											\ +	<boolean>" NEW "</boolean>									\ +  </map>														\ +</llsd>" + +#define _DATA(ID,INTEREST,NEW) _DATA_URLS(ID,INTEREST,NEW,FAKE_OBJECT_MEDIA_CAP_URL,FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL) + +const char *DATA = _DATA(VALID_OBJECT_ID,"1.0","true"); +	 +#define STR(I) boost::lexical_cast<std::string>(I) + +#define LOG_TEST(N) LL_DEBUGS("LLMediaDataClient") << "\n" <<			\ +"================================================================================\n" << \ +"==================================== TEST " #N " ===================================\n" << \ +"================================================================================\n" << LL_ENDL; + +LLSD *gPostRecords = NULL; +F64   gMinimumInterestLevel = (F64)0.0; + +// stubs: +void LLHTTPClient::post( +		const std::string& url, +		const LLSD& body, +		LLHTTPClient::ResponderPtr responder, +		const LLSD& headers, +		const F32 timeout) +{ +	LLSD record; +	record["url"] = url; +	record["body"] = body; +	record["headers"] = headers; +	record["timeout"] = timeout; +	gPostRecords->append(record); +	 +	// Magic URL that triggers a 503: +	LLSD result; +	result[LLTextureEntry::OBJECT_ID_KEY] = body[LLTextureEntry::OBJECT_ID_KEY]; +	if ( url == FAKE_OBJECT_MEDIA_CAP_URL_503 ) +	{ +		responder->error(HTTP_SERVICE_UNAVAILABLE, "fake reason"); +		return; +	} +	else if (url == FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR)  +	{ +		LLSD error; +		error["code"] = LLObjectMediaNavigateClient::ERROR_PERMISSION_DENIED_CODE; +		result["error"] = error; +	}	 +	responder->result(result); +} + +const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f; + +class LLMediaDataClientObjectTest : public LLMediaDataClientObject +{ +public: +	LLMediaDataClientObjectTest(const char *data)  +		{ +			std::istringstream d(data); +			LLSDSerialize::fromXML(mRep, d); +			mNumBounceBacks = 0; +             +           // std::cout << ll_pretty_print_sd(mRep) << std::endl; +           // std::cout << "ID: " << getID() << std::endl; +		} +	LLMediaDataClientObjectTest(const LLSD &rep)  +		: mRep(rep), mNumBounceBacks(0) {} +	~LLMediaDataClientObjectTest() +		{ LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClientObjectTest" << LL_ENDL; } +	 +	virtual U8 getMediaDataCount() const  +		{ return mRep["media_data"].size(); } +	virtual LLSD getMediaDataLLSD(U8 index) const +		{ return mRep["media_data"][(LLSD::Integer)index]; } +	virtual bool isCurrentMediaUrl(U8 index, const std::string &url) const +		{ return (mRep["media_data"][(LLSD::Integer)index].asString() == url); } +	virtual LLUUID getID() const  +		{ return mRep["uuid"]; } +	virtual void mediaNavigateBounceBack(U8 index) +		{ mNumBounceBacks++; }	 +	 +	virtual bool hasMedia() const +		{ return mRep.has("media_data"); } +	 +	virtual void updateObjectMediaData(LLSD const &media_data_array, const std::string &media_version) +		{ mRep["media_data"] = media_data_array; mRep["media_version"] = media_version; } +		 +	virtual F64 getMediaInterest() const +		{ return (LLSD::Real)mRep["interest"]; } +	 +	virtual bool isInterestingEnough() const +		{ return getMediaInterest() > gMinimumInterestLevel; } +	 +	virtual std::string getCapabilityUrl(const std::string &name) const  +		{ return mRep["cap_urls"][name]; } + +	virtual bool isDead() const +		{ return mRep["is_dead"]; } +	 +	virtual U32 getMediaVersion() const +		{ return (LLSD::Integer)mRep["media_version"]; } +	 +	virtual bool isNew() const +		{ return mRep["is_new"]; } +	 +	void setMediaInterest(F64 val) +		{ mRep["interest"] = val; } + +	int getNumBounceBacks() const +		{ return mNumBounceBacks; } +	 +	void markDead() +		{ mRep["is_dead"] = true; } +	 +	void markOld() +		{ mRep["is_new"] = false; } +	 +private: +	LLSD mRep; +	int mNumBounceBacks; +}; + +// This special timer delay should ensure that the timer will fire on the very +// next pump, no matter what (though this does make an assumption about the +// implementation of LLEventTimer::updateClass()): +const F32 NO_PERIOD = -1000.0f; + +static void pump_timers() +{ +	LLEventTimer::updateClass(); +} + +namespace tut +{ +    struct mediadataclient +    { +		mediadataclient() { +			gPostRecords = &mLLSD; +			gMinimumInterestLevel = (F64)0.0; +			 +// 			LLError::setDefaultLevel(LLError::LEVEL_DEBUG); +// 			LLError::setClassLevel("LLMediaDataClient", LLError::LEVEL_DEBUG); +//			LLError::setTagLevel("MediaOnAPrim", LLError::LEVEL_DEBUG); +		} +		LLSD mLLSD; +    }; +     +	typedef test_group<mediadataclient> mediadataclient_t; +	typedef mediadataclient_t::object mediadataclient_object_t; +	tut::mediadataclient_t tut_mediadataclient("LLMediaDataClient"); +     +    void ensure(const std::string &msg, int value, int expected) +    { +        std::string m = msg; +        m += " value: " + STR(value); +        m += ", expected: " + STR(expected); +        ensure(m, value == expected); +    } +     +    void ensure(const std::string &msg, const std::string & value, const std::string & expected) +    { +        std::string m = msg; +        m += " value: " + value; +        m += ", expected: " + expected; +        ensure(m, value == expected); +    } +     +    void ensure(const std::string &msg, const LLUUID & value, const LLUUID & expected) +    { +        std::string m = msg; +        m += " value: " + value.asString(); +        m += ", expected: " + expected.asString(); +        ensure(m, value == expected); +    } +     +    void ensure_llsd(const std::string &msg, const LLSD & value, const char *expected) +    { +        LLSD expected_llsd; +        std::istringstream e(expected); +        LLSDSerialize::fromXML(expected_llsd, e); +    +        std::string value_str = ll_pretty_print_sd(value); +        std::string expected_str = ll_pretty_print_sd(expected_llsd); +        std::string m = msg; +        m += " value: " + value_str; +        m += ", expected: " + expected_str; +        ensure(m, value_str == expected_str); +    } + +	////////////////////////////////////////////////////////////////////////////////////////// +	 +	template<> template<> +	void mediadataclient_object_t::test<1>() +	{ +		// +		// Test fetchMedia() +		// +		LOG_TEST(1); +		 +		LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA); +		int num_refs_start = o->getNumRefs(); +		{ +			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); +			mdc->fetchMedia(o); + +			// Make sure no posts happened yet... +			ensure("post records", gPostRecords->size(), 0); + +			::pump_timers(); +		 +			ensure("post records", gPostRecords->size(), 1); +			ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_CAP_URL); +			ensure("post GET", (*gPostRecords)[0]["body"]["verb"], "GET"); +			ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID)); +			ensure("queue empty", mdc->isEmpty()); +		} +		 +		// Make sure everyone's destroyed properly +		ensure("REF COUNT", o->getNumRefs(), num_refs_start); +    } + +	////////////////////////////////////////////////////////////////////////////////////////// + +	template<> template<> +	void mediadataclient_object_t::test<2>() +	{ +		// +		// Test updateMedia() +		// +		LOG_TEST(2); + +		LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA); +		{ +			// queue time w/ no delay ensures that ::pump_timers() will hit the tick() +			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);   +			mdc->updateMedia(o); +			ensure("post records", gPostRecords->size(), 0); +			::pump_timers(); +		 +			ensure("post records", gPostRecords->size(), 1); +			ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_CAP_URL); +			ensure("post UPDATE", (*gPostRecords)[0]["body"]["verb"], "UPDATE"); +			ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID)); +			ensure_llsd("post data llsd", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_MEDIA_DATA_KEY],  +						"<llsd>" MEDIA_DATA "</llsd>"); +			ensure("queue empty", mdc->isEmpty()); +		} + +		ensure("REF COUNT", o->getNumRefs(), 1); +	} + +	////////////////////////////////////////////////////////////////////////////////////////// + +    template<> template<> +    void mediadataclient_object_t::test<3>() +    { +		// +		// Test navigate() +		// +		LOG_TEST(3); + +		LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA); +		{		 +			LLPointer<LLObjectMediaNavigateClient> mdc = new LLObjectMediaNavigateClient(NO_PERIOD,NO_PERIOD); +			const char *TEST_URL = "http://example.com"; +			mdc->navigate(o, 0, TEST_URL); +			ensure("post records", gPostRecords->size(), 0); +			::pump_timers(); + +			// ensure no bounce back +			ensure("bounce back", dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o))->getNumBounceBacks(), 0); +		 +			ensure("post records", gPostRecords->size(), 1); +			ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL); +			ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID)); +			ensure("post data", (*gPostRecords)[0]["body"][LLTextureEntry::TEXTURE_INDEX_KEY], 0); +			ensure("post data", (*gPostRecords)[0]["body"][LLMediaEntry::CURRENT_URL_KEY], TEST_URL); +			ensure("queue empty", mdc->isEmpty()); +		} +		ensure("REF COUNT", o->getNumRefs(), 1); +    } +	 +	////////////////////////////////////////////////////////////////////////////////////////// + +    template<> template<> +    void mediadataclient_object_t::test<4>() +    { +		// +		// Test queue ordering +		// +		LOG_TEST(4); + +		LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest( +			_DATA(VALID_OBJECT_ID_1,"1.0","true")); +		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest( +			_DATA(VALID_OBJECT_ID_2,"3.0","true")); +		LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest( +			_DATA(VALID_OBJECT_ID_3,"2.0","true")); +		{ +			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);   +			const char *ORDERED_OBJECT_IDS[] = { VALID_OBJECT_ID_2, VALID_OBJECT_ID_3, VALID_OBJECT_ID_1 }; +			mdc->fetchMedia(o1); +			mdc->fetchMedia(o2); +			mdc->fetchMedia(o3); + +			// Make sure no posts happened yet... +			ensure("post records", gPostRecords->size(), 0); + +			// tick 3 times... +			::pump_timers(); +			ensure("post records", gPostRecords->size(), 1); +			::pump_timers(); +			ensure("post records", gPostRecords->size(), 2); +			::pump_timers(); +			ensure("post records", gPostRecords->size(), 3); +		 +			for( int i=0; i < 3; i++ ) +			{ +				ensure("[" + STR(i) + "] post url", (*gPostRecords)[i]["url"], FAKE_OBJECT_MEDIA_CAP_URL); +				ensure("[" + STR(i) + "] post GET", (*gPostRecords)[i]["body"]["verb"], "GET"); +				ensure("[" + STR(i) + "] post object id", (*gPostRecords)[i]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(),  +					   LLUUID(ORDERED_OBJECT_IDS[i])); +			} + +			ensure("queue empty", mdc->isEmpty()); +		} +		ensure("refcount of o1", o1->getNumRefs(), 1); +		ensure("refcount of o2", o2->getNumRefs(), 1); +		ensure("refcount of o3", o3->getNumRefs(), 1); +    } + +	////////////////////////////////////////////////////////////////////////////////////////// + +	template<> template<> +	void mediadataclient_object_t::test<5>() +	{ +		// +		// Test fetchMedia() getting a 503 error +		// +		LOG_TEST(5); +		 +		LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest( +			_DATA_URLS(VALID_OBJECT_ID, +					   "1.0","true", +					   FAKE_OBJECT_MEDIA_CAP_URL_503, +					   FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL)); +		int num_refs_start = o->getNumRefs(); +		{ +			const int NUM_RETRIES = 5; +			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD,NUM_RETRIES); + +			// This should generate a retry +			mdc->fetchMedia(o); + +			// Make sure no posts happened yet... +			ensure("post records before", gPostRecords->size(), 0); + +			// Once, causes retry +			// Second, fires retry timer +			// Third, fires queue timer again +			for (int i=0; i<NUM_RETRIES; ++i) +			{ +				::pump_timers();  // Should pump (fire) the queue timer, causing a retry timer to be scheduled +				// XXX This ensure is not guaranteed, because scheduling a timer might actually get it pumped in the same loop +				//ensure("post records " + STR(i), gPostRecords->size(), i+1); +				::pump_timers();  // Should pump (fire) the retry timer, scheduling the queue timer +			} + +			// Do some extra pumps to make sure no other timer work occurs. +			::pump_timers(); +			::pump_timers(); +			::pump_timers(); +			 +			// Make sure there were 2 posts +			ensure("post records after", gPostRecords->size(), NUM_RETRIES); +			for (int i=0; i<NUM_RETRIES; ++i) +			{ +				ensure("[" + STR(i) + "] post url", (*gPostRecords)[i]["url"], FAKE_OBJECT_MEDIA_CAP_URL_503); +				ensure("[" + STR(i) + "] post GET", (*gPostRecords)[i]["body"]["verb"], "GET"); +				ensure("[" + STR(i) + "] post object id", (*gPostRecords)[i]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID)); +			} +			ensure("queue empty", mdc->isEmpty()); +		} +		 +		// Make sure everyone's destroyed properly +		ensure("REF COUNT", o->getNumRefs(), num_refs_start); +    } + +    template<> template<> +    void mediadataclient_object_t::test<6>() +    { +		// +		// Test navigate() with a bounce back +		// +		LOG_TEST(6); + +		LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest( +			_DATA_URLS(VALID_OBJECT_ID, +					   "1.0","true", +					   FAKE_OBJECT_MEDIA_CAP_URL, +					   FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR)); +		{		 +			LLPointer<LLObjectMediaNavigateClient> mdc = new LLObjectMediaNavigateClient(NO_PERIOD,NO_PERIOD); +			const char *TEST_URL = "http://example.com"; +			mdc->navigate(o, 0, TEST_URL); +			ensure("post records", gPostRecords->size(), 0); +			::pump_timers(); + +			// ensure bounce back +			ensure("bounce back",  +				   dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o))->getNumBounceBacks(), +				   1); +			 +			ensure("post records", gPostRecords->size(), 1); +			ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR); +			ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID)); +			ensure("post data", (*gPostRecords)[0]["body"][LLTextureEntry::TEXTURE_INDEX_KEY], 0); +			ensure("post data", (*gPostRecords)[0]["body"][LLMediaEntry::CURRENT_URL_KEY], TEST_URL); +			ensure("queue empty", mdc->isEmpty()); +		} +		ensure("REF COUNT", o->getNumRefs(), 1); +    } + +	template<> template<> +    void mediadataclient_object_t::test<7>() +    { +		// Test LLMediaDataClient::isInQueue() +		LOG_TEST(7); +		 +		LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest( +			_DATA(VALID_OBJECT_ID_1,"3.0","true")); +		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest( +			_DATA(VALID_OBJECT_ID_2,"1.0","true")); +		int num_refs_start = o1->getNumRefs(); +		{ +			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); +			 +			ensure("not in queue yet 1", ! mdc->isInQueue(o1)); +			ensure("not in queue yet 2", ! mdc->isInQueue(o2)); +			 +			mdc->fetchMedia(o1); +			 +			ensure("is in queue", mdc->isInQueue(o1)); +			ensure("is not in queue", ! mdc->isInQueue(o2)); +			 +			::pump_timers(); +			 +			ensure("not in queue anymore", ! mdc->isInQueue(o1)); +			ensure("still is not in queue", ! mdc->isInQueue(o2)); +			 +			ensure("queue empty", mdc->isEmpty()); +		} +		 +		// Make sure everyone's destroyed properly +		ensure("REF COUNT", o1->getNumRefs(), num_refs_start); +		 +	} + +	template<> template<> +    void mediadataclient_object_t::test<8>() +    { +		// Test queue handling of objects that are marked dead. +		LOG_TEST(8); +		 +		LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"4.0","true")); +		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"3.0","true")); +		LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"2.0","true")); +		LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"1.0","true")); +		{ +			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); +			 +			// queue up all 4 objects +			mdc->fetchMedia(o1); +			mdc->fetchMedia(o2); +			mdc->fetchMedia(o3); +			mdc->fetchMedia(o4); + +			ensure("is in queue 1", mdc->isInQueue(o1)); +			ensure("is in queue 2", mdc->isInQueue(o2)); +			ensure("is in queue 3", mdc->isInQueue(o3)); +			ensure("is in queue 4", mdc->isInQueue(o4)); +			ensure("post records", gPostRecords->size(), 0); +			 +			// and mark the second and fourth ones dead.  Call removeFromQueue when marking dead, since this is what LLVOVolume will do. +			dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o2))->markDead(); +			mdc->removeFromQueue(o2); +			dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o4))->markDead(); +			mdc->removeFromQueue(o4); + +			// The removeFromQueue calls should remove the second and fourth ones +			ensure("is in queue 1", mdc->isInQueue(o1)); +			ensure("is not in queue 2", !mdc->isInQueue(o2)); +			ensure("is in queue 3", mdc->isInQueue(o3)); +			ensure("is not in queue 4", !mdc->isInQueue(o4)); +			ensure("post records", gPostRecords->size(), 0); +			 +			::pump_timers(); +			 +			// The first tick should process the first item +			ensure("is not in queue 1", !mdc->isInQueue(o1)); +			ensure("is not in queue 2", !mdc->isInQueue(o2)); +			ensure("is in queue 3", mdc->isInQueue(o3)); +			ensure("is not in queue 4", !mdc->isInQueue(o4)); +			ensure("post records", gPostRecords->size(), 1); +			 +			::pump_timers(); +			 +			// The second tick should process the third, emptying the queue +			ensure("is not in queue 3", !mdc->isInQueue(o3)); +			ensure("post records", gPostRecords->size(), 2); + +			ensure("queue empty", mdc->isEmpty()); +		} +		ensure("refcount of o1", o1->getNumRefs(), 1); +		ensure("refcount of o2", o2->getNumRefs(), 1); +		ensure("refcount of o3", o3->getNumRefs(), 1); +		ensure("refcount of o4", o4->getNumRefs(), 1); + +	} +	 +	////////////////////////////////////////////////////////////////////////////////////////// + +    template<> template<> +    void mediadataclient_object_t::test<9>() +    { +		// +		// Test queue re-ordering +		// +		LOG_TEST(9); +		 +		LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"40.0","true")); +		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"30.0","true")); +		LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"20.0","true")); +		LLMediaDataClientObjectTest *object4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"10.0","true")); +		LLMediaDataClientObject::ptr_t o4 = object4; +		{ +			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); +			 +			// queue up all 4 objects.  They should now be in the queue in +			// order 1 through 4, with 4 being at the front of the queue +			mdc->fetchMedia(o1); +			mdc->fetchMedia(o2); +			mdc->fetchMedia(o3); +			mdc->fetchMedia(o4); +			 +			int tick_num = 0; +			 +			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0); +			 +			::pump_timers(); +			++tick_num; +			 +			// The first tick should remove the first one  +			ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1); +			 +			// Now, pretend that object 4 moved relative to the avatar such +			// that it is now closest +			object4->setMediaInterest(50.0); +			 +			::pump_timers(); +			++tick_num; +			 +			// The second tick should still pick off item 2, but then re-sort +			// have picked off object 4 +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2); + +			::pump_timers(); +			++tick_num; +			 +			// The third tick should pick off object 2 +			ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3); + +			// The fourth tick should pick off object 3 +			::pump_timers(); +			++tick_num; + +			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4); + +			ensure("queue empty", mdc->isEmpty()); +		} +		ensure("refcount of o1", o1->getNumRefs(), 1); +		ensure("refcount of o2", o2->getNumRefs(), 1); +		ensure("refcount of o3", o3->getNumRefs(), 1); +		ensure("refcount of o4", o4->getNumRefs(), 1); +    } +	 +	 +	template<> template<> +    void mediadataclient_object_t::test<10>() +    { +		// +		// Test using the "round-robin" queue +		// +		LOG_TEST(10); +		 +		LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","true")); +		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"2.0","true")); +		LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"3.0","false")); +		LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"4.0","false")); +		{ +			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); +			 +			// queue up all 4 objects.  The first two should be in the sorted +			// queue [2 1], the second in the round-robin queue.  The queues +			// are serviced interleaved, so we should expect: +			// 2, 3, 1, 4 +			mdc->fetchMedia(o1); +			mdc->fetchMedia(o2); +			mdc->fetchMedia(o3); +			mdc->fetchMedia(o4); +			 +			int tick_num = 0; +			 +			// 0 +			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0); +			 +			::pump_timers(); +			++tick_num; +			 +			// 1 The first tick should remove object 2 +			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1); +			ensure(STR(tick_num) + ". post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_2)); +			 +			::pump_timers(); +			++tick_num; +			 +			// 2 The second tick should send object 3 +			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2); +			ensure(STR(tick_num) + ". post object id", (*gPostRecords)[1]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_3)); +			 +			::pump_timers(); +			++tick_num; +			 +			// 3 The third tick should remove object 1 +			ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3); +			ensure(STR(tick_num) + ". post object id", (*gPostRecords)[2]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_1)); +			 +			::pump_timers(); +			++tick_num; +			 +			// 4 The fourth tick should send object 4 +			ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4); +			ensure(STR(tick_num) + ". post object id", (*gPostRecords)[3]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_4)); +			 +			::pump_timers(); +			++tick_num; +						 +			// 5 The fifth tick should not change the state of anything. +			ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4); +			 +			::pump_timers(); +			 +			// Whew....better be empty +			ensure("queue empty", mdc->isEmpty()); +		} +		ensure("refcount of o1", o1->getNumRefs(), 1); +		ensure("refcount of o2", o2->getNumRefs(), 1); +		ensure("refcount of o3", o3->getNumRefs(), 1); +		ensure("refcount of o4", o4->getNumRefs(), 1);		 +	} +	 +	 +	template<> template<> +	void mediadataclient_object_t::test<11>() +	{ +		// +		// Test LLMediaDataClient's destructor +		// +		LOG_TEST(11); +		 +		LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA); +		int num_refs_start = o->getNumRefs(); +		{ +			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); +			mdc->fetchMedia(o); +			// must tick enough times to clear refcount of mdc +			::pump_timers(); +		}		 +		// Make sure everyone's destroyed properly +		ensure("REF COUNT", o->getNumRefs(), num_refs_start); +	} +	 +	template<> template<> +    void mediadataclient_object_t::test<12>() +    { +		// +		// Test the "not interesting enough" call +		// +		LOG_TEST(12); +		 +		LLMediaDataClientObjectTest *object1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","true")); +		LLMediaDataClientObject::ptr_t o1 = object1; +		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"2.0","true")); +		LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"3.0","true")); +		LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"4.0","true")); +		{ +			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); +			 +			// queue up all 4 objects.  The first two are "interesting enough". +			// Firing the timer 4 times should therefore leave them. +			// Note that they should be sorted 4,3,2,1 +			// Then, we'll make one "interesting enough", fire the timer a few  +			// times, and make sure only it gets pulled off the queue +			gMinimumInterestLevel = 2.5; +			mdc->fetchMedia(o1); +			mdc->fetchMedia(o2); +			mdc->fetchMedia(o3); +			mdc->fetchMedia(o4); +			 +			int tick_num = 0; +			 +			// 0 +			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0); +			 +			::pump_timers(); +			++tick_num; +			 +			// 1 The first tick should remove object 4 +			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1); +			ensure(STR(tick_num) + ". post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_4)); +			 +			::pump_timers(); +			++tick_num; +			 +			// 2 The second tick should send object 3 +			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2); +			ensure(STR(tick_num) + ". post object id", (*gPostRecords)[1]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_3)); +			 +			::pump_timers(); +			++tick_num; +			 +			// 3 The third tick should not pull off anything +			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2); + +			::pump_timers(); +			++tick_num; +			 +			// 4 The fourth tick (for good measure) should not pull off anything +			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2); +			 +			// Okay, now futz with object 1's interest, such that it is now  +			// "interesting enough" +			object1->setMediaInterest((F64)5.0); +			 +			// This should sort so that the queue is now [1 2]  +			::pump_timers(); +			++tick_num; +			 +			// 5 The fifth tick should now identify objects 3 and 4 as no longer +			// needing "updating", and remove them from the queue +			ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3); +			ensure(STR(tick_num) + ". post object id", (*gPostRecords)[2]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_1)); +			 +			::pump_timers(); +			++tick_num; +			 +			// 6 The sixth tick should not pull off anything +			ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); +			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); +			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); +			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); +			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3); +			 +			::pump_timers(); +			++tick_num; +		 +			// Whew....better NOT be empty ... o2 should still be there +			ensure("queue not empty", !mdc->isEmpty()); +			 +			// But, we need to clear the queue, or else we won't destroy MDC... +			// this is a strange interplay between the queue timer and the MDC +			mdc->removeFromQueue(o2); +			// tick +			::pump_timers(); +		} +		ensure("refcount of o1", o1->getNumRefs(), 1); +		ensure("refcount of o2", o2->getNumRefs(), 1); +		ensure("refcount of o3", o3->getNumRefs(), 1); +		ensure("refcount of o4", o4->getNumRefs(), 1);		 +	} + +	template<> template<> +	void mediadataclient_object_t::test<13>() +	{ +		// +		// Test supression of redundant navigates. +		// +		LOG_TEST(13); +		 +		LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","true")); +		{ +			LLPointer<LLObjectMediaNavigateClient> mdc = new LLObjectMediaNavigateClient(NO_PERIOD,NO_PERIOD); +			const char *TEST_URL = "http://foo.example.com"; +			const char *TEST_URL_2 = "http://example.com"; +			mdc->navigate(o1, 0, TEST_URL); +			mdc->navigate(o1, 1, TEST_URL); +			mdc->navigate(o1, 0, TEST_URL_2); +			mdc->navigate(o1, 1, TEST_URL_2); +			 +			// This should add two requests to the queue, one for face 0 of the object and one for face 1. +			 +			ensure("before pump: 1 is in queue", mdc->isInQueue(o1)); + +			::pump_timers(); + +			ensure("after first pump: 1 is in queue", mdc->isInQueue(o1)); + +			::pump_timers(); + +			ensure("after second pump: 1 is not in queue", !mdc->isInQueue(o1)); + +			ensure("first post has correct url", (*gPostRecords)[0]["body"][LLMediaEntry::CURRENT_URL_KEY].asString(), std::string(TEST_URL_2)); +			ensure("second post has correct url", (*gPostRecords)[1]["body"][LLMediaEntry::CURRENT_URL_KEY].asString(), std::string(TEST_URL_2)); + +		}		 +	} +	 +} diff --git a/indra/newview/tests/llsecapi_test.cpp b/indra/newview/tests/llsecapi_test.cpp new file mode 100644 index 0000000000..703603e2db --- /dev/null +++ b/indra/newview/tests/llsecapi_test.cpp @@ -0,0 +1,122 @@ +/**  + * @file llsecapi_test.cpp + * @author Roxie + * @date 2009-02-10 + * @brief Test the sec api functionality + * + * $LicenseInfo:firstyear=2009&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 "../llviewerprecompiledheaders.h" +#include "../llviewernetwork.h" +#include "../test/lltut.h" +#include "../llsecapi.h" +#include "../llsechandler_basic.h" +#include "../../llxml/llcontrol.h" + + +//----------------------------------------------------------------------------                +// Mock objects for the dependencies of the code we're testing                                + +LLControlGroup::LLControlGroup(const std::string& name) +: LLInstanceTracker<LLControlGroup, std::string>(name) {} +LLControlGroup::~LLControlGroup() {} +BOOL LLControlGroup::declareString(const std::string& name, +                                   const std::string& initial_val, +                                   const std::string& comment, +                                   BOOL persist) {return TRUE;} +void LLControlGroup::setString(const std::string& name, const std::string& val){} +std::string LLControlGroup::getString(const std::string& name) +{ +	return ""; +} + + +LLControlGroup gSavedSettings("test"); + +LLSecAPIBasicHandler::LLSecAPIBasicHandler() {} +void LLSecAPIBasicHandler::init() {} +LLSecAPIBasicHandler::~LLSecAPIBasicHandler() {} +LLPointer<LLCertificate> LLSecAPIBasicHandler::getCertificate(const std::string& pem_cert) { return NULL; } +LLPointer<LLCertificate> LLSecAPIBasicHandler::getCertificate(X509* openssl_cert) { return NULL; } +LLPointer<LLCertificateChain> LLSecAPIBasicHandler::getCertificateChain(const X509_STORE_CTX* chain) { return NULL; } +LLPointer<LLCertificateStore> LLSecAPIBasicHandler::getCertificateStore(const std::string& store_id) { return NULL; } +void LLSecAPIBasicHandler::setProtectedData(const std::string& data_type, const std::string& data_id, const LLSD& data) {} +LLSD LLSecAPIBasicHandler::getProtectedData(const std::string& data_type, const std::string& data_id) { return LLSD(); } +void LLSecAPIBasicHandler::deleteProtectedData(const std::string& data_type, const std::string& data_id) {} +LLPointer<LLCredential> LLSecAPIBasicHandler::createCredential(const std::string& grid, const LLSD& identifier, const LLSD& authenticator) { return NULL; } +LLPointer<LLCredential> LLSecAPIBasicHandler::loadCredential(const std::string& grid) { return NULL; } +void LLSecAPIBasicHandler::saveCredential(LLPointer<LLCredential> cred, bool save_authenticator) {} +void LLSecAPIBasicHandler::deleteCredential(LLPointer<LLCredential> cred) {} + +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- +namespace tut +{ +	// Test wrapper declaration : wrapping nothing for the moment +	struct secapiTest +	{ +		 +		secapiTest() +		{ +		} +		~secapiTest() +		{ +		} +	}; +	 +	// Tut templating thingamagic: test group, object and test instance +	typedef test_group<secapiTest> secapiTestFactory; +	typedef secapiTestFactory::object secapiTestObject; +	tut::secapiTestFactory tut_test("LLSecAPI"); +	 +	// --------------------------------------------------------------------------------------- +	// Test functions  +	// --------------------------------------------------------------------------------------- +	// registration +	template<> template<> +	void secapiTestObject::test<1>() +	{ +		// retrieve an unknown handler + +		ensure("'Unknown' handler should be NULL", !(BOOL)getSecHandler("unknown")); +		LLPointer<LLSecAPIHandler> test1_handler =  new LLSecAPIBasicHandler(); +		registerSecHandler("sectest1", test1_handler); +		ensure("'Unknown' handler should be NULL", !(BOOL)getSecHandler("unknown")); +		LLPointer<LLSecAPIHandler> retrieved_test1_handler = getSecHandler("sectest1"); +		ensure("Retrieved sectest1 handler should be the same",  +			   retrieved_test1_handler == test1_handler); +		 +		// insert a second handler +		LLPointer<LLSecAPIHandler> test2_handler =  new LLSecAPIBasicHandler(); +		registerSecHandler("sectest2", test2_handler); +		ensure("'Unknown' handler should be NULL", !(BOOL)getSecHandler("unknown")); +		retrieved_test1_handler = getSecHandler("sectest1"); +		ensure("Retrieved sectest1 handler should be the same",  +			   retrieved_test1_handler == test1_handler); + +		LLPointer<LLSecAPIHandler> retrieved_test2_handler = getSecHandler("sectest2"); +		ensure("Retrieved sectest1 handler should be the same",  +			   retrieved_test2_handler == test2_handler); +		 +	} +} diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp new file mode 100644 index 0000000000..daa10819fc --- /dev/null +++ b/indra/newview/tests/llsechandler_basic_test.cpp @@ -0,0 +1,1065 @@ +/**  + * @file llsechandler_basic_test.cpp + * @author Roxie + * @date 2009-02-10 + * @brief Test the 'basic' sec handler functions + * + * $LicenseInfo:firstyear=2005&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 "../llviewerprecompiledheaders.h" +#include "../test/lltut.h" +#include "../llsecapi.h" +#include "../llsechandler_basic.h" +#include "../../llxml/llcontrol.h" +#include "../llviewernetwork.h" +#include "lluuid.h" +#include "llxorcipher.h" +#include "apr_base64.h" +#include <vector> +#include <ios> +#include <llsdserialize.h> +#include <openssl/pem.h> +#include <openssl/err.h> +#include <openssl/evp.h> +#include "llxorcipher.h" +#include <openssl/ossl_typ.h> +#include <openssl/x509.h> +#include <openssl/x509v3.h> +#include <openssl/pem.h> +#include <openssl/asn1.h> +#include <openssl/rand.h> +#include <openssl/err.h> +#include "../llmachineid.h" + +#define ensure_throws(str, exc_type, cert, func, ...) \ +try \ +{ \ +func(__VA_ARGS__); \ +fail("throws, " str); \ +} \ +catch(exc_type& except) \ +{ \ +ensure("Exception cert is incorrect for " str, except.getCert() == cert); \ +} + +extern bool _cert_hostname_wildcard_match(const std::string& hostname, const std::string& wildcard_string); + +//----------------------------------------------------------------------------                +// Mock objects for the dependencies of the code we're testing                                + +std::string gFirstName; +std::string gLastName; +LLControlGroup::LLControlGroup(const std::string& name) +: LLInstanceTracker<LLControlGroup, std::string>(name) {} +LLControlGroup::~LLControlGroup() {} +BOOL LLControlGroup::declareString(const std::string& name, +                                   const std::string& initial_val, +                                   const std::string& comment, +                                   BOOL persist) {return TRUE;} +void LLControlGroup::setString(const std::string& name, const std::string& val){} +std::string LLControlGroup::getString(const std::string& name) +{ + +	if (name == "FirstName") +		return gFirstName; +	else if (name == "LastName") +		return gLastName; +	return ""; +} + +LLSD LLCredential::getLoginParams() +{ +	LLSD result = LLSD::emptyMap(); +	 +	// legacy credential +	result["passwd"] = "$1$testpasssd"; +	result["first"] = "myfirst"; +	result["last"] ="mylast"; +	return result; +} + +void LLCredential::identifierType(std::string &idType) +{ +} + +void LLCredential::authenticatorType(std::string &idType) +{ +} + + +LLControlGroup gSavedSettings("test"); +unsigned char gMACAddress[MAC_ADDRESS_BYTES] = {77,21,46,31,89,2}; + + +S32 LLMachineID::getUniqueID(unsigned char *unique_id, size_t len) +{ +	memcpy(unique_id, gMACAddress, len); +	return 1; +} +S32 LLMachineID::init() { return 1; } +	 + +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- +namespace tut +{ +	// Test wrapper declaration : wrapping nothing for the moment +	struct sechandler_basic_test +	{ +		std::string mPemTestCert, mPemRootCert, mPemIntermediateCert, mPemChildCert, mSha1RSATestCert, mSha1RSATestCA; +		std::string mDerFormat; +		X509 *mX509TestCert, *mX509RootCert, *mX509IntermediateCert, *mX509ChildCert; + +		sechandler_basic_test() +		{ +            LLMachineID::init(); +			OpenSSL_add_all_algorithms(); +			OpenSSL_add_all_ciphers(); +			OpenSSL_add_all_digests();	 +			ERR_load_crypto_strings(); +			gFirstName = ""; +			gLastName = ""; +			LLFile::remove("test_password.dat"); +			LLFile::remove("sechandler_settings.tmp");			 +			mPemTestCert = "-----BEGIN CERTIFICATE-----\n" +				"MIIEuDCCA6CgAwIBAgIBBDANBgkqhkiG9w0BAQUFADCBtDELMAkGA1UEBhMCQlIx\n" +				"EzARBgNVBAoTCklDUC1CcmFzaWwxPTA7BgNVBAsTNEluc3RpdHV0byBOYWNpb25h\n" +				"bCBkZSBUZWNub2xvZ2lhIGRhIEluZm9ybWFjYW8gLSBJVEkxETAPBgNVBAcTCEJy\n" +				"YXNpbGlhMQswCQYDVQQIEwJERjExMC8GA1UEAxMoQXV0b3JpZGFkZSBDZXJ0aWZp\n" +				"Y2Fkb3JhIFJhaXogQnJhc2lsZWlyYTAeFw0wMTExMzAxMjU4MDBaFw0xMTExMzAy\n" +				"MzU5MDBaMIG0MQswCQYDVQQGEwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDE9MDsG\n" +				"A1UECxM0SW5zdGl0dXRvIE5hY2lvbmFsIGRlIFRlY25vbG9naWEgZGEgSW5mb3Jt\n" +				"YWNhbyAtIElUSTERMA8GA1UEBxMIQnJhc2lsaWExCzAJBgNVBAgTAkRGMTEwLwYD\n" +				"VQQDEyhBdXRvcmlkYWRlIENlcnRpZmljYWRvcmEgUmFpeiBCcmFzaWxlaXJhMIIB\n" +				"IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwPMudwX/hvm+Uh2b/lQAcHVA\n" +				"isamaLkWdkwP9/S/tOKIgRrL6Oy+ZIGlOUdd6uYtk9Ma/3pUpgcfNAj0vYm5gsyj\n" +				"Qo9emsc+x6m4VWwk9iqMZSCK5EQkAq/Ut4n7KuLE1+gdftwdIgxfUsPt4CyNrY50\n" +				"QV57KM2UT8x5rrmzEjr7TICGpSUAl2gVqe6xaii+bmYR1QrmWaBSAG59LrkrjrYt\n" +				"bRhFboUDe1DK+6T8s5L6k8c8okpbHpa9veMztDVC9sPJ60MWXh6anVKo1UcLcbUR\n" +				"yEeNvZneVRKAAU6ouwdjDvwlsaKydFKwed0ToQ47bmUKgcm+wV3eTRk36UOnTwID\n" +				"AQABo4HSMIHPME4GA1UdIARHMEUwQwYFYEwBAQAwOjA4BggrBgEFBQcCARYsaHR0\n" +				"cDovL2FjcmFpei5pY3BicmFzaWwuZ292LmJyL0RQQ2FjcmFpei5wZGYwPQYDVR0f\n" +				"BDYwNDAyoDCgLoYsaHR0cDovL2FjcmFpei5pY3BicmFzaWwuZ292LmJyL0xDUmFj\n" +				"cmFpei5jcmwwHQYDVR0OBBYEFIr68VeEERM1kEL6V0lUaQ2kxPA3MA8GA1UdEwEB\n" +				"/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAZA5c1\n" +				"U/hgIh6OcgLAfiJgFWpvmDZWqlV30/bHFpj8iBobJSm5uDpt7TirYh1Uxe3fQaGl\n" +				"YjJe+9zd+izPRbBqXPVQA34EXcwk4qpWuf1hHriWfdrx8AcqSqr6CuQFwSr75Fos\n" +				"SzlwDADa70mT7wZjAmQhnZx2xJ6wfWlT9VQfS//JYeIc7Fue2JNLd00UOSMMaiK/\n" +				"t79enKNHEA2fupH3vEigf5Eh4bVAN5VohrTm6MY53x7XQZZr1ME7a55lFEnSeT0u\n" +				"mlOAjR2mAbvSM5X5oSZNrmetdzyTj2flCM8CC7MLab0kkdngRIlUBGHF1/S5nmPb\n" +				"K+9A46sd33oqK8n8\n" +				"-----END CERTIFICATE-----\n"; + +			mPemRootCert = "-----BEGIN CERTIFICATE-----\n" +			"MIIB0TCCATqgAwIBAgIJANaTqrzEvHaRMA0GCSqGSIb3DQEBBAUAMBsxGTAXBgNV\n" +			"BAMTEFJveGllcyB0ZXN0IHJvb3QwHhcNMDkwNDE1MjEwNzQ3WhcNMTAwNDE1MjEw\n" +			"NzQ3WjAbMRkwFwYDVQQDExBSb3hpZXMgdGVzdCByb290MIGfMA0GCSqGSIb3DQEB\n" +			"AQUAA4GNADCBiQKBgQCpo5nDW6RNz9IHUVZd7Tw2XAQiBniDF4xH0N1w7sUYTiFq\n" +			"21mABsnOPJD3ra+MtOsXPHcaljm661JjTD8L40v5sfEbqDUPcOw76ClrPqnuAeyT\n" +			"38qk8DHku/mT8YdprevGZdVcUXQg3vosVzOL93HOOHK+u61mEEoM9W5xoNVEdQID\n" +			"AQABox0wGzAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjANBgkqhkiG9w0BAQQF\n" +			"AAOBgQAzn0aW/+zWPmcTbvxonyiYYUr9b4SOB/quhAkT8KT4ir1dcZAXRR59+kEn\n" +			"HSTu1FAodV0gvESqyobftF5hZ1XMxdJqGu//xP+YCwlv244G/0pp7KLI8ihNO2+N\n" +			"lPBUJgbo++ZkhiE1jotZi9Ay0Oedh3s/AfbMZPyfpJ23ll6+BA==\n" +			"-----END CERTIFICATE-----\n"; +			 +			 +			 +			mPemIntermediateCert = "-----BEGIN CERTIFICATE-----\n" +			"MIIBzzCCATigAwIBAgIBATANBgkqhkiG9w0BAQQFADAbMRkwFwYDVQQDExBSb3hp\n" +			"ZXMgdGVzdCByb290MB4XDTA5MDQxNTIxMzE1NloXDTEwMDQxNTIxMzE1NlowITEf\n" +			"MB0GA1UEAxMWUm94aWVzIGludGVybWVkaWF0ZSBDQTCBnzANBgkqhkiG9w0BAQEF\n" +			"AAOBjQAwgYkCgYEA15MM0W1R37rx/24Q2Qkb5bSiQZxTUcQAhJ2pA8mwUucXuCVt\n" +			"6ayI2TuN32nkjmsCgUkiT/bdXWp0OJo7/MXRIFeUNMCRxrpeFnxuigYEqbIXAdN6\n" +			"qu/vdG2X4PRv/v9Ijrju4cBEiKIldIgOurWEIfXEsVSFP2XmFQHesF04qDcCAwEA\n" +			"AaMdMBswDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEEBQAD\n" +			"gYEAYljikYgak3W1jSo0vYthNHUy3lBVAKzDhpM96lY5OuXFslpCRX42zNL8X3kN\n" +			"U/4IaJUVtZqx8WsUXl1eXHzBCaXCftapV4Ir6cENLIsXCdXs8paFYzN5nPJA5GYU\n" +			"zWgkSEl1MEhNIc+bJW34vwi29EjrAShAhsIZ84Mt/lvD3Pc=\n" +			"-----END CERTIFICATE-----\n"; +			 +			mPemChildCert = "-----BEGIN CERTIFICATE-----\n" +			"MIIB5DCCAU0CBEnm9eUwDQYJKoZIhvcNAQEEBQAwITEfMB0GA1UEAxMWUm94aWVz\n" +			"IGludGVybWVkaWF0ZSBDQTAeFw0wOTA0MTYwMDAzNDlaFw0xMDA0MTYwMDAzNDla\n" +			"MCAxHjAcBgNVBAMTFWVuaWFjNjMubGluZGVubGFiLmNvbTCBnzANBgkqhkiG9w0B\n" +			"AQEFAAOBjQAwgYkCgYEAp9I5rofEzbjNht+9QejfnsIlEPqSxskoWKCG255TesWR\n" +			"RTmw9wafHQQkJk/VIsaU4RMBYHkknGbHX2dGvMHmKZoWUPSQ/8FZz09o0Qx3TNUZ\n" +			"l7KlGOD2d1c7ZxXDPqlLC6QW8DrE1/8zfwJ5cbYBXc8e7OKdSZeRrnwHyw4Q8r8C\n" +			"AwEAAaMvMC0wEwYDVR0lBAwwCgYIKwYBBQUHAwEwCQYDVR0TBAIwADALBgNVHQ8E\n" +			"BAMCBaAwDQYJKoZIhvcNAQEEBQADgYEAIG0M5tqYlXyMiGKPZfXy/R3M3ZZOapDk\n" +			"W0dsXJYXAc35ftwtn0VYu9CNnZCcli17/d+AKhkK8a/oGPazqudjFF6WLJLTXaY9\n" +			"NmhkJcOPADXkbyQPUPXzLe4YRrkEQeGhzMb4rKDQ1TKAcXfs0Y068pTpsixNSxja\n" +			"NhAUUcve5Is=\n" +			"-----END CERTIFICATE-----\n"; +			 +			mDerFormat = "MIIEuDCCA6CgAwIBAgIBBDANBgkqhkiG9w0BAQUFADCBtDELMAkGA1UEBhMCQlIxEzARBgNVBAoT" +"CklDUC1CcmFzaWwxPTA7BgNVBAsTNEluc3RpdHV0byBOYWNpb25hbCBkZSBUZWNub2xvZ2lhIGRh" +"IEluZm9ybWFjYW8gLSBJVEkxETAPBgNVBAcTCEJyYXNpbGlhMQswCQYDVQQIEwJERjExMC8GA1UE" +"AxMoQXV0b3JpZGFkZSBDZXJ0aWZpY2Fkb3JhIFJhaXogQnJhc2lsZWlyYTAeFw0wMTExMzAxMjU4" +"MDBaFw0xMTExMzAyMzU5MDBaMIG0MQswCQYDVQQGEwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDE9" +"MDsGA1UECxM0SW5zdGl0dXRvIE5hY2lvbmFsIGRlIFRlY25vbG9naWEgZGEgSW5mb3JtYWNhbyAt" +"IElUSTERMA8GA1UEBxMIQnJhc2lsaWExCzAJBgNVBAgTAkRGMTEwLwYDVQQDEyhBdXRvcmlkYWRl" +"IENlcnRpZmljYWRvcmEgUmFpeiBCcmFzaWxlaXJhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB" +"CgKCAQEAwPMudwX/hvm+Uh2b/lQAcHVAisamaLkWdkwP9/S/tOKIgRrL6Oy+ZIGlOUdd6uYtk9Ma" +"/3pUpgcfNAj0vYm5gsyjQo9emsc+x6m4VWwk9iqMZSCK5EQkAq/Ut4n7KuLE1+gdftwdIgxfUsPt" +"4CyNrY50QV57KM2UT8x5rrmzEjr7TICGpSUAl2gVqe6xaii+bmYR1QrmWaBSAG59LrkrjrYtbRhF" +"boUDe1DK+6T8s5L6k8c8okpbHpa9veMztDVC9sPJ60MWXh6anVKo1UcLcbURyEeNvZneVRKAAU6o" +"uwdjDvwlsaKydFKwed0ToQ47bmUKgcm+wV3eTRk36UOnTwIDAQABo4HSMIHPME4GA1UdIARHMEUw" +"QwYFYEwBAQAwOjA4BggrBgEFBQcCARYsaHR0cDovL2FjcmFpei5pY3BicmFzaWwuZ292LmJyL0RQ" +"Q2FjcmFpei5wZGYwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2FjcmFpei5pY3BicmFzaWwuZ292" +"LmJyL0xDUmFjcmFpei5jcmwwHQYDVR0OBBYEFIr68VeEERM1kEL6V0lUaQ2kxPA3MA8GA1UdEwEB" +"/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAZA5c1U/hgIh6OcgLA" +"fiJgFWpvmDZWqlV30/bHFpj8iBobJSm5uDpt7TirYh1Uxe3fQaGlYjJe+9zd+izPRbBqXPVQA34E" +"Xcwk4qpWuf1hHriWfdrx8AcqSqr6CuQFwSr75FosSzlwDADa70mT7wZjAmQhnZx2xJ6wfWlT9VQf" +"S//JYeIc7Fue2JNLd00UOSMMaiK/t79enKNHEA2fupH3vEigf5Eh4bVAN5VohrTm6MY53x7XQZZr" +"1ME7a55lFEnSeT0umlOAjR2mAbvSM5X5oSZNrmetdzyTj2flCM8CC7MLab0kkdngRIlUBGHF1/S5" +"nmPbK+9A46sd33oqK8n8"; +			 +			mSha1RSATestCert = "-----BEGIN CERTIFICATE-----\n" +			"MIIDFDCCAn2gAwIBAgIDDqqYMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT\n" +			"MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0\n" +			"aWZpY2F0ZSBBdXRob3JpdHkwHhcNMTAwMTA1MDAzNjMwWhcNMTEwMTA3MjAyMTE0\n" +			"WjCBnjEpMCcGA1UEBRMgQmNmc0RBRkl1U0YwdFpWVm5vOFJKbjVUbW9hNGR2Wkgx\n" +			"CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4g\n" +			"RnJhbmNpc2NvMR0wGwYDVQQKExRMaW5kZW4gUmVzZWFyY2ggSW5jLjEYMBYGA1UE\n" +			"AxQPKi5saW5kZW5sYWIuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD2\n" +			"14Jdko8v6GB33hHbW+lNQyloFQtc2h4ykjf+fYPJ27dw6tQO2if7N3k/5XDkwC1N\n" +			"krGgE9vt3iecCPgasue6k67Zyfj9HbEP2D+j38eROudrsxLaRFDQx50BvZ5YMNl3\n" +			"4zQCj8/gCMsuq8cvaP9/rbJTUpgYWFGLsm8yAYOgWwIDAQABo4GuMIGrMA4GA1Ud\n" +			"DwEB/wQEAwIE8DAdBgNVHQ4EFgQUIBK/JB9AyqquSEbkzt2Zux6v9sYwOgYDVR0f\n" +			"BDMwMTAvoC2gK4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9zZWN1cmVj\n" +			"YS5jcmwwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gjIBBPM5iQn9QwHQYDVR0lBBYw\n" +			"FAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBBQUAA4GBAKKR84+hvLuB\n" +			"pop9VG7HQPIyEKtZq3Nnk+UlJGfjGY3csLWSFmxU727r5DzdEP1W1PwF3rxuoKcZ\n" +			"4nJJpKdzoGVujgBMP2U/J0PJvU7D8U3Zqu7nrXAjOHj7iVnvJ3EKJ1bvwXaisgPN\n" +			"wt21kKfGnA4OlhJtJ6VQvUkcF12I3pTP\n" +			"-----END CERTIFICATE-----\n"; +			 +			mSha1RSATestCA = "-----BEGIN CERTIFICATE-----\n" +			"MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV\n" +			"UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy\n" +			"dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1\n" +			"MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx\n" +			"dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B\n" +			"AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f\n" +			"BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A\n" +			"cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC\n" +			"AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ\n" +			"MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm\n" +			"aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw\n" +			"ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj\n" +			"IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF\n" +			"MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA\n" +			"A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y\n" +			"7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh\n" +			"1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4\n" +			"-----END CERTIFICATE-----\n"; + +			 +			 +			 +			mX509TestCert = NULL; +			mX509RootCert = NULL; +			mX509IntermediateCert = NULL; +			mX509ChildCert = NULL; +			 +			BIO * validation_bio = BIO_new_mem_buf((void*)mPemTestCert.c_str(), mPemTestCert.length());			 +			PEM_read_bio_X509(validation_bio, &mX509TestCert, 0, NULL); +			BIO_free(validation_bio); +			validation_bio = BIO_new_mem_buf((void*)mPemRootCert.c_str(), mPemRootCert.length()); +			PEM_read_bio_X509(validation_bio, &mX509RootCert, 0, NULL); +			BIO_free(validation_bio); +			validation_bio = BIO_new_mem_buf((void*)mPemIntermediateCert.c_str(), mPemIntermediateCert.length()); +			PEM_read_bio_X509(validation_bio, &mX509IntermediateCert, 0, NULL); +			BIO_free(validation_bio);	 +			validation_bio = BIO_new_mem_buf((void*)mPemChildCert.c_str(), mPemChildCert.length()); +			PEM_read_bio_X509(validation_bio, &mX509ChildCert, 0, NULL); +			BIO_free(validation_bio);				 +		} +		~sechandler_basic_test() +		{ +			LLFile::remove("test_password.dat"); +			LLFile::remove("sechandler_settings.tmp"); +			LLFile::remove("mycertstore.pem"); +			X509_free(mX509TestCert); +			X509_free(mX509RootCert); +			X509_free(mX509IntermediateCert); +			X509_free(mX509ChildCert); +		} +	}; +	 +	// Tut templating thingamagic: test group, object and test instance +	typedef test_group<sechandler_basic_test> sechandler_basic_test_factory; +	typedef sechandler_basic_test_factory::object sechandler_basic_test_object; +	tut::sechandler_basic_test_factory tut_test("LLSecHandler"); +	 +	// --------------------------------------------------------------------------------------- +	// Test functions  +	// --------------------------------------------------------------------------------------- +	// test cert data retrieval +	template<> template<> +	void sechandler_basic_test_object::test<1>() +	 +	{ +		char buffer[4096]; +		LLPointer<LLCertificate> test_cert = new LLBasicCertificate(mPemTestCert); +		 +		ensure_equals("Resultant pem is correct", +			   mPemTestCert, test_cert->getPem()); +		std::vector<U8> binary_cert = test_cert->getBinary(); + +		apr_base64_encode(buffer, (const char *)&binary_cert[0], binary_cert.size()); +		 +		ensure_equals("Der Format is correct", memcmp(buffer, mDerFormat.c_str(), mDerFormat.length()), 0); +		 +		LLSD llsd_cert; +		test_cert->getLLSD(llsd_cert); +		std::ostringstream llsd_value; +		llsd_value << LLSDOStreamer<LLSDNotationFormatter>(llsd_cert) << std::endl; +		std::string llsd_cert_str = llsd_value.str(); +		ensure_equals("Issuer Name/commonName",  +			   (std::string)llsd_cert["issuer_name"]["commonName"], "Autoridade Certificadora Raiz Brasileira"); +		ensure_equals("Issure Name/countryName", (std::string)llsd_cert["issuer_name"]["countryName"], "BR"); +		ensure_equals("Issuer Name/localityName", (std::string)llsd_cert["issuer_name"]["localityName"], "Brasilia"); +		ensure_equals("Issuer Name/org name", (std::string)llsd_cert["issuer_name"]["organizationName"], "ICP-Brasil"); +		ensure_equals("IssuerName/org unit",  +			   (std::string)llsd_cert["issuer_name"]["organizationalUnitName"], "Instituto Nacional de Tecnologia da Informacao - ITI"); +		ensure_equals("IssuerName/state", (std::string)llsd_cert["issuer_name"]["stateOrProvinceName"], "DF"); +		ensure_equals("Issuer name string",  +			   (std::string)llsd_cert["issuer_name_string"], "CN=Autoridade Certificadora Raiz Brasileira,ST=DF," +															   "L=Brasilia,OU=Instituto Nacional de Tecnologia da Informacao - ITI,O=ICP-Brasil,C=BR"); +		ensure_equals("subject Name/commonName",  +			   (std::string)llsd_cert["subject_name"]["commonName"], "Autoridade Certificadora Raiz Brasileira"); +		ensure_equals("subject Name/countryName", (std::string)llsd_cert["subject_name"]["countryName"], "BR"); +		ensure_equals("subject Name/localityName", (std::string)llsd_cert["subject_name"]["localityName"], "Brasilia"); +		ensure_equals("subject Name/org name", (std::string)llsd_cert["subject_name"]["organizationName"], "ICP-Brasil"); +		ensure_equals("subjectName/org unit",  +			   (std::string)llsd_cert["subject_name"]["organizationalUnitName"], "Instituto Nacional de Tecnologia da Informacao - ITI"); +		ensure_equals("subjectName/state", (std::string)llsd_cert["subject_name"]["stateOrProvinceName"], "DF"); +		ensure_equals("subject name string",  +			   (std::string)llsd_cert["subject_name_string"], "CN=Autoridade Certificadora Raiz Brasileira,ST=DF," +			                                                    "L=Brasilia,OU=Instituto Nacional de Tecnologia da Informacao - ITI,O=ICP-Brasil,C=BR"); +		 +		ensure_equals("md5 digest", (std::string)llsd_cert["md5_digest"], "96:89:7d:61:d1:55:2b:27:e2:5a:39:b4:2a:6c:44:6f"); +		ensure_equals("serial number", (std::string)llsd_cert["serial_number"], "04"); +		// sha1 digest is giving a weird value, and I've no idea why...feh +		//ensure_equals("sha1 digest", (std::string)llsd_cert["sha1_digest"], "8e:fd:ca:bc:93:e6:1e:92:5d:4d:1d:ed:18:1a:43:20:a4:67:a1:39"); +		ensure_equals("valid from", (std::string)llsd_cert["valid_from"], "2001-11-30T12:58:00Z"); +		ensure_equals("valid to", (std::string)llsd_cert["valid_to"], "2011-11-30T23:59:00Z"); +		LLSD expectedKeyUsage = LLSD::emptyArray(); +		expectedKeyUsage.append(LLSD((std::string)"certSigning")); +		expectedKeyUsage.append(LLSD((std::string)"crlSigning")); +		ensure("key usage", valueCompareLLSD(llsd_cert["keyUsage"], expectedKeyUsage)); +		ensure("basic constraints", (bool)llsd_cert["basicConstraints"]["CA"]); +		 +		ensure("x509 is equal", !X509_cmp(mX509TestCert, test_cert->getOpenSSLX509())); +	} + +	 +	// test protected data +	template<> template<> +	void sechandler_basic_test_object::test<2>() + +	{ +		 +		std::string protected_data = "sUSh3wj77NG9oAMyt3XIhaej3KLZhLZWFZvI6rIGmwUUOmmelrRg0NI9rkOj8ZDpTPxpwToaBT5u" +		"GQhakdaGLJznr9bHr4/6HIC1bouKj4n2rs4TL6j2WSjto114QdlNfLsE8cbbE+ghww58g8SeyLQO" +		"nyzXoz+/PBz0HD5SMFDuObccoPW24gmqYySz8YoEWhSwO0pUtEEqOjVRsAJgF5wLAtJZDeuilGsq" +		"4ZT9Y4wZ9Rh8nnF3fDUL6IGamHe1ClXM1jgBu10F6UMhZbnH4C3aJ2E9+LiOntU+l3iCb2MpkEpr" +		"82r2ZAMwIrpnirL/xoYoyz7MJQYwUuMvBPToZJrxNSsjI+S2Z+I3iEJAELMAAA=="; +		 +		std::vector<U8> binary_data(apr_base64_decode_len(protected_data.c_str())); +		apr_base64_decode_binary(&binary_data[0], protected_data.c_str()); + +		LLXORCipher cipher(gMACAddress, MAC_ADDRESS_BYTES); +		cipher.decrypt(&binary_data[0], 16); +		unsigned char unique_id[MAC_ADDRESS_BYTES]; +        LLMachineID::getUniqueID(unique_id, sizeof(unique_id)); +		LLXORCipher cipher2(unique_id, sizeof(unique_id)); +		cipher2.encrypt(&binary_data[0], 16); +		std::ofstream temp_file("sechandler_settings.tmp", std::ofstream::binary); +		temp_file.write((const char *)&binary_data[0], binary_data.size()); +		temp_file.close(); + +		LLPointer<LLSecAPIBasicHandler> handler = new LLSecAPIBasicHandler("sechandler_settings.tmp", +																		   "test_password.dat"); +		handler->init();																		 +		// data retrieval for existing data +		LLSD data = handler->getProtectedData("test_data_type", "test_data_id"); + + +		ensure_equals("retrieve existing data1", (std::string)data["data1"], "test_data_1"); +		ensure_equals("retrieve existing data2", (std::string)data["data2"], "test_data_2"); +		ensure_equals("retrieve existing data3", (std::string)data["data3"]["elem1"], "test element1"); +		 +		// data storage +		LLSD store_data = LLSD::emptyMap(); +		store_data["store_data1"] = "test_store_data1"; +		store_data["store_data2"] = 27; +		store_data["store_data3"] = LLSD::emptyMap(); +		store_data["store_data3"]["subelem1"] = "test_subelem1"; +		 +		handler->setProtectedData("test_data_type", "test_data_id1", store_data); +		data = handler->getProtectedData("test_data_type", "test_data_id"); +		 +		data = handler->getProtectedData("test_data_type", "test_data_id"); +		// verify no overwrite of existing data +		ensure_equals("verify no overwrite 1", (std::string)data["data1"], "test_data_1"); +		ensure_equals("verify no overwrite 2", (std::string)data["data2"], "test_data_2"); +		ensure_equals("verify no overwrite 3", (std::string)data["data3"]["elem1"], "test element1"); +		 +		// verify written data is good +		data = handler->getProtectedData("test_data_type", "test_data_id1"); +		ensure_equals("verify stored data1", (std::string)data["store_data1"], "test_store_data1"); +		ensure_equals("verify stored data2", (int)data["store_data2"], 27); +		ensure_equals("verify stored data3", (std::string)data["store_data3"]["subelem1"], "test_subelem1"); +		 +		// verify overwrite works +		handler->setProtectedData("test_data_type", "test_data_id", store_data);	 +		data = handler->getProtectedData("test_data_type", "test_data_id"); +		ensure_equals("verify overwrite stored data1", (std::string)data["store_data1"], "test_store_data1"); +		ensure_equals("verify overwrite stored data2", (int)data["store_data2"], 27); +		ensure_equals("verify overwrite stored data3", (std::string)data["store_data3"]["subelem1"], "test_subelem1"); +		 +		// verify other datatype doesn't conflict +		store_data["store_data3"] = "test_store_data3"; +		store_data["store_data4"] = 28; +		store_data["store_data5"] = LLSD::emptyMap(); +		store_data["store_data5"]["subelem2"] = "test_subelem2"; +		 +		handler->setProtectedData("test_data_type1", "test_data_id", store_data);	 +		data = handler->getProtectedData("test_data_type1", "test_data_id"); +		ensure_equals("verify datatype stored data3", (std::string)data["store_data3"], "test_store_data3"); +		ensure_equals("verify datatype stored data4", (int)data["store_data4"], 28); +		ensure_equals("verify datatype stored data5", (std::string)data["store_data5"]["subelem2"], "test_subelem2");	 +		 +		// test data not found + +		data = handler->getProtectedData("test_data_type1", "test_data_not_found"); +		ensure("not found", data.isUndefined()); + +		// cause a 'write' by using 'LLPointer' to delete then instantiate a handler +		handler = NULL; +		handler = new LLSecAPIBasicHandler("sechandler_settings.tmp", "test_password.dat"); +		handler->init(); + +		data = handler->getProtectedData("test_data_type1", "test_data_id"); +		ensure_equals("verify datatype stored data3a", (std::string)data["store_data3"], "test_store_data3"); +		ensure_equals("verify datatype stored data4a", (int)data["store_data4"], 28); +		ensure_equals("verify datatype stored data5a", (std::string)data["store_data5"]["subelem2"], "test_subelem2");	 +		 +		// rewrite the initial file to verify reloads +		handler = NULL; +		std::ofstream temp_file2("sechandler_settings.tmp", std::ofstream::binary); +		temp_file2.write((const char *)&binary_data[0], binary_data.size()); +		temp_file2.close(); +		 +		// cause a 'write' +		handler = new LLSecAPIBasicHandler("sechandler_settings.tmp", "test_password.dat"); +		handler->init();		 +		data = handler->getProtectedData("test_data_type1", "test_data_id"); +		ensure("not found", data.isUndefined()); +		 +		handler->deleteProtectedData("test_data_type", "test_data_id"); +		ensure("Deleted data not found", handler->getProtectedData("test_data_type", "test_data_id").isUndefined()); +		 +		LLFile::remove("sechandler_settings.tmp"); +		handler = new LLSecAPIBasicHandler("sechandler_settings.tmp", "test_password.dat"); +		handler->init();		 +		data = handler->getProtectedData("test_data_type1", "test_data_id"); +		ensure("not found", data.isUndefined()); +		handler = NULL; +		 +		ensure(LLFile::isfile("sechandler_settings.tmp")); +	} +	 +	// test credenitals +	template<> template<> +	void sechandler_basic_test_object::test<3>() +	{ +		LLPointer<LLSecAPIBasicHandler> handler = new LLSecAPIBasicHandler("sechandler_settings.tmp", "test_password.dat"); +		handler->init(); + +		LLSD my_id = LLSD::emptyMap(); +		LLSD my_authenticator = LLSD::emptyMap(); +		my_id["type"] = "test_type"; +		my_id["username"] = "testuser@lindenlab.com"; +		my_authenticator["type"] = "test_auth"; +		my_authenticator["creds"] = "12345"; + +		// test creation of credentials		 +		LLPointer<LLCredential> my_cred = handler->createCredential("my_grid", my_id, my_authenticator); + +		// test retrieval of credential components +		ensure_equals("basic credential creation: identifier", my_id, my_cred->getIdentifier()); +		ensure_equals("basic credential creation: authenticator", my_authenticator, my_cred->getAuthenticator()); +		ensure_equals("basic credential creation: grid", "my_grid", my_cred->getGrid()); +		 +		// test setting/overwriting of credential components +		my_id["first_name"] = "firstname"; +		my_id.erase("username"); +		my_authenticator.erase("creds"); +		my_authenticator["hash"] = "6563245"; +		 +		my_cred->setCredentialData(my_id, my_authenticator); +		ensure_equals("set credential data: identifier", my_id, my_cred->getIdentifier()); +		ensure_equals("set credential data: authenticator", my_authenticator, my_cred->getAuthenticator()); +		ensure_equals("set credential data: grid", "my_grid", my_cred->getGrid());		 +			 +		// test loading of a credential, that hasn't been saved, without +		// any legacy saved credential data +		LLPointer<LLCredential> my_new_cred = handler->loadCredential("my_grid2"); +		ensure("unknown credential load test", my_new_cred->getIdentifier().isMap()); +		ensure("unknown credential load test", !my_new_cred->getIdentifier().has("type"));		 +		ensure("unknown credential load test", my_new_cred->getAuthenticator().isMap()); +		ensure("unknown credential load test", !my_new_cred->getAuthenticator().has("type"));	 +		// test saving of a credential +		handler->saveCredential(my_cred, true); + +		// test loading of a known credential +		my_new_cred = handler->loadCredential("my_grid"); +		ensure_equals("load a known credential: identifier", my_id, my_new_cred->getIdentifier()); +		ensure_equals("load a known credential: authenticator",my_authenticator, my_new_cred->getAuthenticator()); +		ensure_equals("load a known credential: grid", "my_grid", my_cred->getGrid()); +	 +		// test deletion of a credential +		handler->deleteCredential(my_new_cred); + +		ensure("delete credential: identifier", my_new_cred->getIdentifier().isUndefined()); +		ensure("delete credentialt: authenticator", my_new_cred->getIdentifier().isUndefined()); +		ensure_equals("delete credential: grid", "my_grid", my_cred->getGrid());		 +		// load unknown cred +		 +		my_new_cred = handler->loadCredential("my_grid"); +		ensure("deleted credential load test", my_new_cred->getIdentifier().isMap()); +		ensure("deleted credential load test", !my_new_cred->getIdentifier().has("type"));		 +		ensure("deleted credential load test", my_new_cred->getAuthenticator().isMap()); +		ensure("deleted credential load test", !my_new_cred->getAuthenticator().has("type")); +		 +		// test loading of an unknown credential with legacy saved username, but without +		// saved password +		gFirstName = "myfirstname"; +		gLastName = "mylastname"; +		my_new_cred = handler->loadCredential("my_legacy_grid"); +		ensure_equals("legacy credential with no password: type",  +					  (const std::string)my_new_cred->getIdentifier()["type"], "agent"); +		ensure_equals("legacy credential with no password: first_name",  +					  (const std::string)my_new_cred->getIdentifier()["first_name"], "myfirstname"); +		ensure_equals("legacy credential with no password: last_name", +					  (const std::string)my_new_cred->getIdentifier()["last_name"], "mylastname"); +		 +		ensure("legacy credential with no password: no authenticator", my_new_cred->getAuthenticator().isUndefined()); +		 +		// test loading of an unknown credential with legacy saved password and username + +		std::string hashed_password = "fSQcLG03eyIWJmkzfyYaKm81dSweLmsxeSAYKGE7fSQ=";		 +		int length = apr_base64_decode_len(hashed_password.c_str()); +		std::vector<char> decoded_password(length); +		apr_base64_decode(&decoded_password[0], hashed_password.c_str()); +		LLXORCipher cipher(gMACAddress, MAC_ADDRESS_BYTES); +		cipher.decrypt((U8*)&decoded_password[0], length); +		unsigned char unique_id[MAC_ADDRESS_BYTES]; +		LLMachineID::getUniqueID(unique_id, sizeof(unique_id)); +		LLXORCipher cipher2(unique_id, sizeof(unique_id)); +		cipher2.encrypt((U8*)&decoded_password[0], length); +		llofstream password_file("test_password.dat", std::ofstream::binary); +		password_file.write(&decoded_password[0], length);  +		password_file.close(); +		 +		my_new_cred = handler->loadCredential("my_legacy_grid2");		 +		ensure_equals("legacy credential with password: type",  +					  (const std::string)my_new_cred->getIdentifier()["type"], "agent"); +		ensure_equals("legacy credential with password: first_name",  +					  (const std::string)my_new_cred->getIdentifier()["first_name"], "myfirstname"); +		ensure_equals("legacy credential with password: last_name", +					  (const std::string)my_new_cred->getIdentifier()["last_name"], "mylastname"); +		 +		LLSD legacy_authenticator = my_new_cred->getAuthenticator(); +		ensure_equals("legacy credential with password: type",  +					  (std::string)legacy_authenticator["type"],  +					  "hash"); +		ensure_equals("legacy credential with password: algorithm",  +					  (std::string)legacy_authenticator["algorithm"],  +					  "md5");	 +		ensure_equals("legacy credential with password: algorithm",  +					  (std::string)legacy_authenticator["secret"],  +					  "01234567890123456789012345678901"); +		 +		// test creation of credentials		 +		my_cred = handler->createCredential("mysavedgrid", my_id, my_authenticator); +		// test save without saving authenticator. 		 +		handler->saveCredential(my_cred, FALSE); +		my_new_cred = handler->loadCredential("mysavedgrid");	 +		ensure_equals("saved credential without auth",  +					  (const std::string)my_new_cred->getIdentifier()["type"], "test_type"); +		ensure("no authenticator values were saved", my_new_cred->getAuthenticator().isUndefined()); +	} + +	// test cert vector +	template<> template<> +	void sechandler_basic_test_object::test<4>() +	{ +		 +		// validate create from empty vector +		LLPointer<LLBasicCertificateVector> test_vector = new LLBasicCertificateVector(); +		ensure_equals("when loading with nothing, we should result in no certs in vector", test_vector->size(), 0); +		 +		test_vector->add(new LLBasicCertificate(mPemTestCert)); +		ensure_equals("one element in vector", test_vector->size(), 1); +		test_vector->add(new LLBasicCertificate(mPemChildCert)); +		ensure_equals("two elements in vector after add", test_vector->size(), 2); +		 +		test_vector->add(new LLBasicCertificate(mPemChildCert)); +		ensure_equals("two elements in vector after re-add", test_vector->size(), 2); +		// validate order +		X509* test_cert = (*test_vector)[0]->getOpenSSLX509();		 +		ensure("first cert added remains first cert", !X509_cmp(test_cert, mX509TestCert)); +		X509_free(test_cert); +		 +		test_cert = (*test_vector)[1]->getOpenSSLX509();	 +		ensure("adding a duplicate cert", !X509_cmp(test_cert, mX509ChildCert)); +		X509_free(test_cert);		 +		 +		// +		// validate iterator +		// +		LLBasicCertificateVector::iterator current_cert = test_vector->begin(); +		LLBasicCertificateVector::iterator copy_current_cert = current_cert; +		// operator++(int) +		ensure("validate iterator++ element in vector is expected cert", *current_cert++ == (*test_vector)[0]); +		ensure("validate 2nd iterator++ element in vector is expected cert", *current_cert++ == (*test_vector)[1]); +		ensure("validate end iterator++", current_cert == test_vector->end()); +		 +		// copy  +		ensure("validate copy iterator element in vector is expected cert", *copy_current_cert == (*test_vector)[0]);		 +		 +		// operator--(int) +		current_cert--; +		ensure("validate iterator-- element in vector is expected cert", *current_cert-- == (*test_vector)[1]);		 +		ensure("validate iterator-- element in vector is expected cert", *current_cert == (*test_vector)[0]); +		 +		ensure("begin iterator is equal", current_cert == test_vector->begin()); +		 +		// operator++ +		ensure("validate ++iterator element in vector is expected cert", *++current_cert == (*test_vector)[1]);				 +		ensure("end of cert vector after ++iterator", ++current_cert == test_vector->end()); +		// operator-- +		ensure("validate --iterator element in vector is expected cert", *--current_cert == (*test_vector)[1]);		 +		ensure("validate 2nd --iterator element in vector is expected cert", *--current_cert == (*test_vector)[0]);		 +		 +		// validate remove +		// validate create from empty vector +		test_vector = new LLBasicCertificateVector(); +		test_vector->add(new LLBasicCertificate(mPemTestCert)); +		test_vector->add(new LLBasicCertificate(mPemChildCert)); +		test_vector->erase(test_vector->begin()); +		ensure_equals("one element in store after remove", test_vector->size(), 1); +		test_cert = (*test_vector)[0]->getOpenSSLX509(); +		ensure("validate cert was removed", !X509_cmp(test_cert, mX509ChildCert)); +		X509_free(test_cert); +		 +		// validate insert +		test_vector->insert(test_vector->begin(), new LLBasicCertificate(mPemChildCert)); +		test_cert = (*test_vector)[0]->getOpenSSLX509(); +		 +		ensure("validate cert was inserted", !X509_cmp(test_cert, mX509ChildCert)); +		X509_free(test_cert);	 + +		//validate find +		LLSD find_info = LLSD::emptyMap(); +		test_vector->insert(test_vector->begin(), new LLBasicCertificate(mPemRootCert)); +		find_info["issuer_name"] = LLSD::emptyMap(); +		find_info["issuer_name"]["commonName"] = "Roxies intermediate CA"; +		find_info["md5_digest"] = "97:24:c7:4c:d4:ba:2d:0e:9c:a1:18:8e:3a:c6:1f:c3"; +		current_cert = test_vector->find(find_info); +		ensure("found", current_cert != test_vector->end()); +		ensure("found cert", (*current_cert).get() == (*test_vector)[1].get()); +		find_info["sha1_digest"] = "bad value"; +		current_cert =test_vector->find(find_info); +		ensure("didn't find cert", current_cert == test_vector->end());		 +	}	 +	 +	// test cert store +	template<> template<> +	void sechandler_basic_test_object::test<5>() +	{ +		// validate load with nothing +		LLFile::remove("mycertstore.pem"); +		LLPointer<LLBasicCertificateStore> test_store = new LLBasicCertificateStore("mycertstore.pem"); +		ensure_equals("when loading with nothing, we should result in no certs in store", test_store->size(), 0); +		 +		// validate load with empty file +		test_store->save(); +		test_store = NULL; +		test_store = new LLBasicCertificateStore("mycertstore.pem"); +		ensure_equals("when loading with nothing, we should result in no certs in store", test_store->size(), 0); +		test_store=NULL; +		 +		// instantiate a cert store from a file +		llofstream certstorefile("mycertstore.pem", std::ios::out); +		certstorefile << mPemChildCert << std::endl << mPemTestCert << std::endl; +		certstorefile.close(); +		// validate loaded certs +		test_store = new LLBasicCertificateStore("mycertstore.pem"); +		ensure_equals("two elements in store", test_store->size(), 2); +		 +		// operator[] +		X509* test_cert = (*test_store)[0]->getOpenSSLX509(); + +		ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert)); +		X509_free(test_cert); +		test_cert = (*test_store)[1]->getOpenSSLX509(); +		ensure("validate second element in store is expected cert", !X509_cmp(test_cert, mX509TestCert));	 +		X509_free(test_cert); + + +		// validate save +		LLFile::remove("mycertstore.pem"); +		test_store->save(); +		test_store = NULL; +		test_store = new LLBasicCertificateStore("mycertstore.pem"); +		ensure_equals("two elements in store after save", test_store->size(), 2);				 +		LLCertificateStore::iterator current_cert = test_store->begin();		 +		test_cert = (*current_cert)->getOpenSSLX509(); +		ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert)); +		current_cert++; +		X509_free(test_cert); +		test_cert = (*current_cert)->getOpenSSLX509(); +		ensure("validate second element in store is expected cert", !X509_cmp(test_cert, mX509TestCert));	 +		X509_free(test_cert); +		current_cert++; +		ensure("end of cert store", current_cert == test_store->end()); +		 +	} +	 +	// cert name wildcard matching +	template<> template<> +	void sechandler_basic_test_object::test<6>() +	{ +		ensure("simple name match",  +			   _cert_hostname_wildcard_match("foo", "foo")); + +		ensure("simple name match, with end period",  +			   _cert_hostname_wildcard_match("foo.", "foo.")); +		 +		ensure("simple name match, with begin period",  +			   _cert_hostname_wildcard_match(".foo", ".foo"));		 + +		ensure("simple name match, with mismatched period cn",  +			   _cert_hostname_wildcard_match("foo.", "foo"));	 +		 +		ensure("simple name match, with mismatched period hostname",  +			   _cert_hostname_wildcard_match("foo", "foo."));	 +		 +		ensure("simple name match, with subdomain",  +			   _cert_hostname_wildcard_match("foo.bar", "foo.bar"));	 +		 +		ensure("stutter name match",  +			   _cert_hostname_wildcard_match("foobbbbfoo", "foo*bbbfoo"));			 +		 +		ensure("simple name match, with beginning wildcard",  +			   _cert_hostname_wildcard_match("foobar", "*bar"));	 +		 +		ensure("simple name match, with ending wildcard",  +			   _cert_hostname_wildcard_match("foobar", "foo*")); +		 +		ensure("simple name match, with beginning null wildcard",  +			   _cert_hostname_wildcard_match("foobar", "*foobar"));			 + +		ensure("simple name match, with ending null wildcard",  +			   _cert_hostname_wildcard_match("foobar", "foobar*")); +		 +		ensure("simple name match, with embedded wildcard",  +			   _cert_hostname_wildcard_match("foobar", "f*r"));		 +		 +		ensure("simple name match, with embedded null wildcard",  +			   _cert_hostname_wildcard_match("foobar", "foo*bar")); + +		ensure("simple name match, with dual embedded wildcard",  +			   _cert_hostname_wildcard_match("foobar", "f*o*ar"));		 + +		ensure("simple name mismatch",  +			   !_cert_hostname_wildcard_match("bar", "foo")); +		 +		ensure("simple name mismatch, with end period",  +			   !_cert_hostname_wildcard_match("foobar.", "foo.")); +		 +		ensure("simple name mismatch, with begin period",  +			   !_cert_hostname_wildcard_match(".foobar", ".foo"));		 +		 +		ensure("simple name mismatch, with subdomain",  +			   !_cert_hostname_wildcard_match("foobar.bar", "foo.bar"));	 +		 +		ensure("simple name mismatch, with beginning wildcard",  +			   !_cert_hostname_wildcard_match("foobara", "*bar"));	 +		 +		ensure("simple name mismatch, with ending wildcard",  +			   !_cert_hostname_wildcard_match("oobar", "foo*")); +		 +		ensure("simple name mismatch, with embedded wildcard",  +			   !_cert_hostname_wildcard_match("oobar", "f*r"));		 +		 +		ensure("simple name mismatch, with dual embedded wildcard",  +			   !_cert_hostname_wildcard_match("foobar", "f*d*ar")); +		 +		ensure("simple wildcard",  +			   _cert_hostname_wildcard_match("foobar", "*")); +		 +		ensure("long domain",  +			   _cert_hostname_wildcard_match("foo.bar.com", "foo.bar.com")); +		 +		ensure("long domain with multiple wildcards",  +			   _cert_hostname_wildcard_match("foo.bar.com", "*.b*r.com"));	 + +		ensure("end periods",  +			   _cert_hostname_wildcard_match("foo.bar.com.", "*.b*r.com."));	 +		 +		ensure("match end period",  +			   _cert_hostname_wildcard_match("foo.bar.com.", "*.b*r.com")); +		 +		ensure("match end period2",  +			   _cert_hostname_wildcard_match("foo.bar.com", "*.b*r.com.")); +		 +		ensure("wildcard mismatch",  +			   !_cert_hostname_wildcard_match("bar.com", "*.bar.com"));	 +		 +		ensure("wildcard match",  +			   _cert_hostname_wildcard_match("foo.bar.com", "*.bar.com"));	 + +		ensure("wildcard match",  +			   _cert_hostname_wildcard_match("foo.foo.bar.com", "*.bar.com"));	 +		 +		ensure("wildcard match",  +			   _cert_hostname_wildcard_match("foo.foo.bar.com", "*.*.com")); +		 +		ensure("wildcard mismatch",  +			   !_cert_hostname_wildcard_match("foo.foo.bar.com", "*.foo.com"));			 +	} +	 +	// test cert chain +	template<> template<> +	void sechandler_basic_test_object::test<7>() +	{ +		// validate create from empty chain +		LLPointer<LLBasicCertificateChain> test_chain = new LLBasicCertificateChain(NULL); +		ensure_equals("when loading with nothing, we should result in no certs in chain", test_chain->size(), 0); + +		// Single cert in the chain. +		X509_STORE_CTX *test_store = X509_STORE_CTX_new(); +		test_store->cert = mX509ChildCert;		 +		test_store->untrusted = NULL; +		test_chain = new LLBasicCertificateChain(test_store); +		X509_STORE_CTX_free(test_store); +		ensure_equals("two elements in store", test_chain->size(), 1);		 +		X509* test_cert = (*test_chain)[0]->getOpenSSLX509(); +		ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert)); +		X509_free(test_cert);		 +		 +		// cert + CA +		 +		test_store = X509_STORE_CTX_new(); +		test_store->cert = mX509ChildCert; +		test_store->untrusted = sk_X509_new_null(); +		sk_X509_push(test_store->untrusted, mX509IntermediateCert); +		test_chain = new LLBasicCertificateChain(test_store); +		X509_STORE_CTX_free(test_store); +		ensure_equals("two elements in store", test_chain->size(), 2);	 +		test_cert = (*test_chain)[0]->getOpenSSLX509(); +		ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert)); +		X509_free(test_cert); +		test_cert = (*test_chain)[1]->getOpenSSLX509(); +		ensure("validate second element in store is expected cert", !X509_cmp(test_cert, mX509IntermediateCert));	 +		X509_free(test_cert); + +		// cert + nonrelated +		 +		test_store = X509_STORE_CTX_new(); +		test_store->cert = mX509ChildCert; +		test_store->untrusted = sk_X509_new_null(); +		sk_X509_push(test_store->untrusted, mX509TestCert); +		test_chain = new LLBasicCertificateChain(test_store); +		X509_STORE_CTX_free(test_store); +		ensure_equals("two elements in store", test_chain->size(), 1);	 +		test_cert = (*test_chain)[0]->getOpenSSLX509(); +		ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert)); +		X509_free(test_cert); +		 +		// cert + CA + nonrelated +		test_store = X509_STORE_CTX_new(); +		test_store->cert = mX509ChildCert; +		test_store->untrusted = sk_X509_new_null(); +		sk_X509_push(test_store->untrusted, mX509IntermediateCert); +		sk_X509_push(test_store->untrusted, mX509TestCert); +		test_chain = new LLBasicCertificateChain(test_store); +		X509_STORE_CTX_free(test_store); +		ensure_equals("two elements in store", test_chain->size(), 2);	 +		test_cert = (*test_chain)[0]->getOpenSSLX509(); +		ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert)); +		X509_free(test_cert); +		test_cert = (*test_chain)[1]->getOpenSSLX509(); +		ensure("validate second element in store is expected cert", !X509_cmp(test_cert, mX509IntermediateCert));	 +		X509_free(test_cert); + +		// cert + intermediate + CA  +		test_store = X509_STORE_CTX_new(); +		test_store->cert = mX509ChildCert; +		test_store->untrusted = sk_X509_new_null(); +		sk_X509_push(test_store->untrusted, mX509IntermediateCert); +		sk_X509_push(test_store->untrusted, mX509RootCert); +		test_chain = new LLBasicCertificateChain(test_store); +		X509_STORE_CTX_free(test_store); +		ensure_equals("three elements in store", test_chain->size(), 3);	 +		test_cert = (*test_chain)[0]->getOpenSSLX509(); +		ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert)); +		X509_free(test_cert); +		test_cert = (*test_chain)[1]->getOpenSSLX509(); +		ensure("validate second element in store is expected cert", !X509_cmp(test_cert, mX509IntermediateCert));	 +		X509_free(test_cert); + +		test_cert = (*test_chain)[2]->getOpenSSLX509(); +		ensure("validate second element in store is expected cert", !X509_cmp(test_cert, mX509RootCert));	 +		X509_free(test_cert);		 +	} +	// test cert validation +	template<> template<> +	void sechandler_basic_test_object::test<8>() +	{ +		// start with a trusted store with our known root cert +		LLFile::remove("mycertstore.pem"); +		LLPointer<LLBasicCertificateStore> test_store = new LLBasicCertificateStore("mycertstore.pem"); +		test_store->add(new LLBasicCertificate(mX509RootCert)); +		LLSD validation_params; +		 +		// validate basic trust for a chain containing only the intermediate cert.  (1 deep) +		LLPointer<LLBasicCertificateChain> test_chain = new LLBasicCertificateChain(NULL); + +		test_chain->add(new LLBasicCertificate(mX509IntermediateCert)); + +		test_store->validate(0, test_chain, validation_params); + +		// add the root certificate to the chain and revalidate +		test_chain->add(new LLBasicCertificate(mX509RootCert));	 +		test_store->validate(0, test_chain, validation_params); + +		// add the child cert at the head of the chain, and revalidate (3 deep chain) +		test_chain->insert(test_chain->begin(), new LLBasicCertificate(mX509ChildCert)); +		test_store->validate(0, test_chain, validation_params); + +		// basic failure cases +		test_chain = new LLBasicCertificateChain(NULL); +		//validate with only the child cert in chain, but child cert was previously +		// trusted +		test_chain->add(new LLBasicCertificate(mX509ChildCert)); +		 +		// validate without the trust flag. +		test_store->validate(VALIDATION_POLICY_TRUSTED, test_chain, validation_params);	 +		 +		// Validate with child cert but no parent, and no parent in CA store +		test_store = new LLBasicCertificateStore("mycertstore.pem"); +		ensure_throws("no CA, with only a child cert",  +					  LLCertValidationTrustException,  +					  (*test_chain)[0], +					  test_store->validate,  +					  VALIDATION_POLICY_TRUSTED,  +					  test_chain,  +					  validation_params); + + +		// validate without the trust flag. +		test_store->validate(0, test_chain, validation_params);		 + +		// clear out the store +		test_store = new LLBasicCertificateStore("mycertstore.pem"); +		// append the intermediate cert +		test_chain->add(new LLBasicCertificate(mX509IntermediateCert));		 +		ensure_throws("no CA, with child and intermediate certs",  +					  LLCertValidationTrustException,  +					  (*test_chain)[1], +					  test_store->validate,  +					  VALIDATION_POLICY_TRUSTED,  +					  test_chain,  +					  validation_params); +		// validate without the trust flag +		test_store->validate(0, test_chain, validation_params); + +		// Test time validity +		LLSD child_info; +		((*test_chain)[0])->getLLSD(child_info); +		validation_params = LLSD::emptyMap(); +		validation_params[CERT_VALIDATION_DATE] = LLDate(child_info[CERT_VALID_FROM].asDate().secondsSinceEpoch() + 1.0);   +		test_store->validate(VALIDATION_POLICY_TIME, test_chain, validation_params); + +		validation_params = LLSD::emptyMap();		 +		validation_params[CERT_VALIDATION_DATE] = child_info[CERT_VALID_FROM].asDate(); +		 +		validation_params[CERT_VALIDATION_DATE] = LLDate(child_info[CERT_VALID_FROM].asDate().secondsSinceEpoch() - 1.0); + 		 +		// test not yet valid +		ensure_throws("Child cert not yet valid" ,  +					  LLCertValidationExpirationException,  +					  (*test_chain)[0], +					  test_store->validate,  +					  VALIDATION_POLICY_TIME,  +					  test_chain,  +					  validation_params);	 +		validation_params = LLSD::emptyMap();		 +		validation_params[CERT_VALIDATION_DATE] = LLDate(child_info[CERT_VALID_TO].asDate().secondsSinceEpoch() + 1.0); + 		 +		// test cert expired +		ensure_throws("Child cert expired",  +					  LLCertValidationExpirationException,  +					  (*test_chain)[0], +					  test_store->validate,  +					  VALIDATION_POLICY_TIME,  +					  test_chain,  +					  validation_params); + +		// test SSL KU +		// validate basic trust for a chain containing child and intermediate. +		test_chain = new LLBasicCertificateChain(NULL); +		test_chain->add(new LLBasicCertificate(mX509ChildCert)); +		test_chain->add(new LLBasicCertificate(mX509IntermediateCert)); +		test_store->validate(VALIDATION_POLICY_SSL_KU, test_chain, validation_params);	 + +		test_chain = new LLBasicCertificateChain(NULL); +		test_chain->add(new LLBasicCertificate(mX509TestCert)); + +		test_store = new LLBasicCertificateStore("mycertstore.pem");		 +		ensure_throws("Cert doesn't have ku",  +					  LLCertKeyUsageValidationException,  +					  (*test_chain)[0], +					  test_store->validate,  +					  VALIDATION_POLICY_SSL_KU,  +					  test_chain,  +					  validation_params); +		 +		// test sha1RSA validation +		test_chain = new LLBasicCertificateChain(NULL); +		test_chain->add(new LLBasicCertificate(mSha1RSATestCert));	 +		test_chain->add(new LLBasicCertificate(mSha1RSATestCA)); + +		test_store->validate(0, test_chain, validation_params);	 +	} +	 +}; + diff --git a/indra/newview/tests/llslurl_test.cpp b/indra/newview/tests/llslurl_test.cpp new file mode 100644 index 0000000000..f96f79006a --- /dev/null +++ b/indra/newview/tests/llslurl_test.cpp @@ -0,0 +1,260 @@ +/**  + * @file llsecapi_test.cpp + * @author Roxie + * @date 2009-02-10 + * @brief Test the sec api functionality + * + * $LicenseInfo:firstyear=2009&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 "../llviewerprecompiledheaders.h" +#include "../llviewernetwork.h" +#include "../test/lltut.h" +#include "../llslurl.h" +#include "../../llxml/llcontrol.h" +#include "llsdserialize.h" +//----------------------------------------------------------------------------                +// Mock objects for the dependencies of the code we're testing                                + +LLControlGroup::LLControlGroup(const std::string& name) +: LLInstanceTracker<LLControlGroup, std::string>(name) {} +LLControlGroup::~LLControlGroup() {} +BOOL LLControlGroup::declareString(const std::string& name, +                                   const std::string& initial_val, +                                   const std::string& comment, +                                   BOOL persist) {return TRUE;} +void LLControlGroup::setString(const std::string& name, const std::string& val){} + +std::string gCmdLineLoginURI; +std::string gCmdLineGridChoice; +std::string gCmdLineHelperURI; +std::string gLoginPage; +std::string gCurrentGrid; +std::string LLControlGroup::getString(const std::string& name) +{ +	if (name == "CmdLineGridChoice") +		return gCmdLineGridChoice; +	else if (name == "CmdLineHelperURI") +		return gCmdLineHelperURI; +	else if (name == "LoginPage") +		return gLoginPage; +	else if (name == "CurrentGrid") +		return gCurrentGrid; +	return ""; +} + +LLSD LLControlGroup::getLLSD(const std::string& name) +{ +	if (name == "CmdLineLoginURI") +	{ +		if(!gCmdLineLoginURI.empty()) +		{ +			return LLSD(gCmdLineLoginURI); +		} +	} +	return LLSD(); +} + +LLPointer<LLControlVariable> LLControlGroup::getControl(const std::string& name) +{ +	ctrl_name_table_t::iterator iter = mNameTable.find(name); +	return iter == mNameTable.end() ? LLPointer<LLControlVariable>() : iter->second; +} + +LLControlGroup gSavedSettings("test"); + +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- +namespace tut +{ +	// Test wrapper declaration : wrapping nothing for the moment +	struct slurlTest +	{ +		slurlTest() +		{	 +			LLGridManager::getInstance()->initialize(std::string("")); +		} +		~slurlTest() +		{ +		} +	}; +	 +	// Tut templating thingamagic: test group, object and test instance +	typedef test_group<slurlTest> slurlTestFactory; +	typedef slurlTestFactory::object slurlTestObject; +	tut::slurlTestFactory tut_test("LLSlurl"); +	 +	// --------------------------------------------------------------------------------------- +	// Test functions  +	// --------------------------------------------------------------------------------------- +	// construction from slurl string +	template<> template<> +	void slurlTestObject::test<1>() +	{ +		LLGridManager::getInstance()->setGridChoice("util.agni.lindenlab.com"); +		 +		LLSLURL slurl = LLSLURL(""); +		ensure_equals("null slurl", (int)slurl.getType(), LLSLURL::LAST_LOCATION); +		 +		slurl = LLSLURL("http://slurl.com/secondlife/myregion"); +		ensure_equals("slurl.com slurl, region only - type", slurl.getType(), LLSLURL::LOCATION); +		ensure_equals("slurl.com slurl, region only", slurl.getSLURLString(),  +					  "http://maps.secondlife.com/secondlife/myregion/128/128/0"); +		 +		slurl = LLSLURL("http://maps.secondlife.com/secondlife/myregion/1/2/3"); +		ensure_equals("maps.secondlife.com slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); +		ensure_equals("maps.secondlife.com slurl, region + coords", slurl.getSLURLString(),  +					  "http://maps.secondlife.com/secondlife/myregion/1/2/3"); + +		slurl = LLSLURL("secondlife://myregion"); +		ensure_equals("secondlife: slurl, region only - type", slurl.getType(), LLSLURL::LOCATION); +		ensure_equals("secondlife: slurl, region only", slurl.getSLURLString(),  +					  "http://maps.secondlife.com/secondlife/myregion/128/128/0"); +		 +		slurl = LLSLURL("secondlife://myregion/1/2/3"); +		ensure_equals("secondlife: slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); +		ensure_equals("secondlife slurl, region + coords", slurl.getSLURLString(),  +					  "http://maps.secondlife.com/secondlife/myregion/1/2/3"); +		 +		slurl = LLSLURL("/myregion"); +		ensure_equals("/region slurl, region- type", slurl.getType(), LLSLURL::LOCATION); +		ensure_equals("/region slurl, region ", slurl.getSLURLString(),  +					  "http://maps.secondlife.com/secondlife/myregion/128/128/0"); +		 +		slurl = LLSLURL("/myregion/1/2/3"); +		ensure_equals("/: slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); +		ensure_equals("/ slurl, region + coords", slurl.getSLURLString(),  +					  "http://maps.secondlife.com/secondlife/myregion/1/2/3");	 +		 +		slurl = LLSLURL("my region/1/2/3"); +		ensure_equals(" slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); +		ensure_equals(" slurl, region + coords", slurl.getSLURLString(),  +					  "http://maps.secondlife.com/secondlife/my%20region/1/2/3");	 +		 +		LLGridManager::getInstance()->setGridChoice("my.grid.com");		 +		slurl = LLSLURL("https://my.grid.com/region/my%20region/1/2/3"); +		ensure_equals("grid slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); +		ensure_equals("grid slurl, region + coords", slurl.getSLURLString(),  +					  "https://my.grid.com/region/my%20region/1/2/3");	 +		 +		slurl = LLSLURL("https://my.grid.com/region/my region"); +		ensure_equals("grid slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); +		ensure_equals("grid slurl, region + coords", slurl.getSLURLString(),  +					  "https://my.grid.com/region/my%20region/128/128/0"); +		 +		LLGridManager::getInstance()->setGridChoice("foo.bar.com");		 +		slurl = LLSLURL("/myregion/1/2/3"); +		ensure_equals("/: slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); +		ensure_equals("/ slurl, region + coords", slurl.getSLURLString(),  +					  "https://foo.bar.com/region/myregion/1/2/3");		 +		 +		slurl = LLSLURL("myregion/1/2/3"); +		ensure_equals(": slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); +		ensure_equals(" slurl, region + coords", slurl.getSLURLString(),  +					  "https://foo.bar.com/region/myregion/1/2/3");		 +		 +		slurl = LLSLURL(LLSLURL::SIM_LOCATION_HOME); +		ensure_equals("home", slurl.getType(), LLSLURL::HOME_LOCATION); + +		slurl = LLSLURL(LLSLURL::SIM_LOCATION_LAST); +		ensure_equals("last", slurl.getType(), LLSLURL::LAST_LOCATION); +		 +		slurl = LLSLURL("secondlife:///app/foo/bar?12345"); +		ensure_equals("app", slurl.getType(), LLSLURL::APP);		 +		ensure_equals("appcmd", slurl.getAppCmd(), "foo"); +		ensure_equals("apppath", slurl.getAppPath().size(), 1); +		ensure_equals("apppath2", slurl.getAppPath()[0].asString(), "bar"); +		ensure_equals("appquery", slurl.getAppQuery(), "12345"); +		ensure_equals("grid1", "foo.bar.com", slurl.getGrid()); +	 +		slurl = LLSLURL("secondlife://Aditi/app/foo/bar?12345"); +		ensure_equals("app", slurl.getType(), LLSLURL::APP);		 +		ensure_equals("appcmd", slurl.getAppCmd(), "foo"); +		ensure_equals("apppath", slurl.getAppPath().size(), 1); +		ensure_equals("apppath2", slurl.getAppPath()[0].asString(), "bar"); +		ensure_equals("appquery", slurl.getAppQuery(), "12345"); +		ensure_equals("grid2", "util.aditi.lindenlab.com", slurl.getGrid());		 + +		LLGridManager::getInstance()->setGridChoice("foo.bar.com");			 +		slurl = LLSLURL("secondlife:///secondlife/myregion/1/2/3"); +		ensure_equals("/: slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); +		ensure_equals("location", slurl.getType(), LLSLURL::LOCATION); +		ensure_equals("region" , "myregion", slurl.getRegion()); +		ensure_equals("grid3", "util.agni.lindenlab.com", slurl.getGrid()); +				 +		slurl = LLSLURL("secondlife://Aditi/secondlife/myregion/1/2/3"); +		ensure_equals("/: slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); +		ensure_equals("location", slurl.getType(), LLSLURL::LOCATION); +		ensure_equals("region" , "myregion", slurl.getRegion()); +		ensure_equals("grid4", "util.aditi.lindenlab.com", slurl.getGrid());		 +		 +		LLGridManager::getInstance()->setGridChoice("my.grid.com"); +		slurl = LLSLURL("https://my.grid.com/app/foo/bar?12345"); +		ensure_equals("app", slurl.getType(), LLSLURL::APP);		 +		ensure_equals("appcmd", slurl.getAppCmd(), "foo"); +		ensure_equals("apppath", slurl.getAppPath().size(), 1); +		ensure_equals("apppath2", slurl.getAppPath()[0].asString(), "bar"); +		ensure_equals("appquery", slurl.getAppQuery(), "12345");	 +		 +	} +	 +	// construction from grid/region/vector combos +	template<> template<> +	void slurlTestObject::test<2>() +	{ +		LLSLURL slurl = LLSLURL("mygrid.com", "my region"); +		ensure_equals("grid/region - type", slurl.getType(), LLSLURL::LOCATION); +		ensure_equals("grid/region", slurl.getSLURLString(),  +					  "https://mygrid.com/region/my%20region/128/128/0");	 +		 +		slurl = LLSLURL("mygrid.com", "my region", LLVector3(1,2,3)); +		ensure_equals("grid/region/vector - type", slurl.getType(), LLSLURL::LOCATION); +		ensure_equals(" grid/region/vector", slurl.getSLURLString(),  +					  "https://mygrid.com/region/my%20region/1/2/3");			 + +		LLGridManager::getInstance()->setGridChoice("foo.bar.com.bar");			 +		slurl = LLSLURL("my region", LLVector3(1,2,3)); +		ensure_equals("grid/region/vector - type", slurl.getType(), LLSLURL::LOCATION); +		ensure_equals(" grid/region/vector", slurl.getSLURLString(),  +					  "https://foo.bar.com.bar/region/my%20region/1/2/3");	 +		 +		LLGridManager::getInstance()->setGridChoice("util.agni.lindenlab.com");	 +		slurl = LLSLURL("my region", LLVector3(1,2,3)); +		ensure_equals("default grid/region/vector - type", slurl.getType(), LLSLURL::LOCATION); +		ensure_equals(" default grid/region/vector", slurl.getSLURLString(),  +					  "http://maps.secondlife.com/secondlife/my%20region/1/2/3");	 +		 +	} +	// Accessors +	template<> template<> +	void slurlTestObject::test<3>() +	{ +		LLGridManager::getInstance()->setGridChoice("my.grid.com");		 +		LLSLURL slurl = LLSLURL("https://my.grid.com/region/my%20region/1/2/3"); +		ensure_equals("login string", slurl.getLoginString(), "uri:my region&1&2&3"); +		ensure_equals("location string", slurl.getLocationString(), "my region/1/2/3"); +		ensure_equals("grid", slurl.getGrid(), "my.grid.com"); +		ensure_equals("region", slurl.getRegion(), "my region"); +		ensure_equals("position", slurl.getPosition(), LLVector3(1, 2, 3)); +		 +	} +} diff --git a/indra/newview/tests/lltextureinfo_test.cpp b/indra/newview/tests/lltextureinfo_test.cpp new file mode 100644 index 0000000000..73ace1de37 --- /dev/null +++ b/indra/newview/tests/lltextureinfo_test.cpp @@ -0,0 +1,278 @@ +/**  + * @file llwtextureinfo_test.cpp + * @author Si & Gabriel + * @date 2009-03-30 + * + * $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$ + */ + +// Precompiled header: almost always required for newview cpp files +#include "../llviewerprecompiledheaders.h" +// Class to test +#include "../lltextureinfo.h" +// Dependencies +#include "../lltextureinfodetails.cpp" + +// Tut header +#include "../test/lltut.h" + +// ------------------------------------------------------------------------------------------- +// Stubbing: Declarations required to link and run the class being tested +// Notes:  +// * Add here stubbed implementation of the few classes and methods used in the class to be tested +// * Add as little as possible (let the link errors guide you) +// * Do not make any assumption as to how those classes or methods work (i.e. don't copy/paste code) +// * A simulator for a class can be implemented here. Please comment and document thoroughly. + + +// End Stubbing +// ------------------------------------------------------------------------------------------- + +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- + +namespace tut +{ +	// Test wrapper declarations +	struct textureinfo_test +	{ +		// Constructor and destructor of the test wrapper +		textureinfo_test() +		{ +		} +		~textureinfo_test() +		{ +		} +	}; + +	// Tut templating thingamagic: test group, object and test instance +	typedef test_group<textureinfo_test> textureinfo_t; +	typedef textureinfo_t::object textureinfo_object_t; +	tut::textureinfo_t tut_textureinfo("LLTectureInfo"); + +	 +	// --------------------------------------------------------------------------------------- +	// Test functions +	// Notes: +	// * Test as many as you possibly can without requiring a full blown simulation of everything +	// * The tests are executed in sequence so the test instance state may change between calls +	// * Remember that you cannot test private methods with tut +	// --------------------------------------------------------------------------------------- + +	// --------------------------------------------------------------------------------------- +	// Test the LLTextureInfo +	// --------------------------------------------------------------------------------------- + + +	// Test instantiation +	template<> template<> +	void textureinfo_object_t::test<1>() +	{ +		LLTextureInfo tex_info; +		tex_info.setUpLogging(true, true); +		ensure("have we crashed?", true); +	} + +	// Check lltextureinfo does not contain UUIDs we haven't added +	template<> template<> +	void textureinfo_object_t::test<2>() +	{ +		LLTextureInfo tex_info; +		tex_info.setUpLogging(true, true); + +		LLUUID nonExistant("3a0efa3b-84dc-4e17-9b8c-79ea028850c1"); +		ensure(!tex_info.has(nonExistant)); +	} + +	// Check we can add a request time for a texture +	template<> template<> +	void textureinfo_object_t::test<3>() +	{ +		LLTextureInfo tex_info; +		tex_info.setUpLogging(true, true); + +		LLUUID id("10e65d70-46fd-429f-841a-bf698e9424d3"); +		tex_info.setRequestStartTime(id, 200); + +		ensure_equals(tex_info.getRequestStartTime(id), 200); +	} + +	// Check time for non-existant texture +	template<> template<> +	void textureinfo_object_t::test<4>() +	{ +		LLTextureInfo tex_info; +		tex_info.setUpLogging(true, true); + +		LLUUID nonExistant("3a0efa3b-84dc-4e17-9b8c-79ea028850c1"); +		ensure_equals(tex_info.getRequestStartTime(nonExistant), 0); +	} + +	// Check download complete time for non existant texture +	template<> template<> +	void textureinfo_object_t::test<5>() +	{ +		LLTextureInfo tex_info; +		tex_info.setUpLogging(true, true); + +		LLUUID nonExistant("3a0efa3b-84dc-4e17-9b8c-79ea028850c1"); +		ensure_equals(tex_info.getRequestCompleteTime(nonExistant), 0); +	} + +	// requested size is passed in correctly +	template<> template<> +	void textureinfo_object_t::test<6>() +	{ +		LLTextureInfo tex_info; +		tex_info.setUpLogging(true, true); + +		LLUUID id("10e65d70-46fd-429f-841a-bf698e9424d3"); +		tex_info.setRequestSize(id, 600); + +		ensure_equals(tex_info.getRequestSize(id), 600); +	} + +	// transport type is recorded correctly (http) +	template<> template<> +	void textureinfo_object_t::test<7>() +	{ +		LLTextureInfo tex_info; +		tex_info.setUpLogging(true, true); + +		LLUUID id("10e65d70-46fd-429f-841a-bf698e9424d3"); +		tex_info.setRequestType(id, LLTextureInfoDetails::REQUEST_TYPE_HTTP); + +		ensure_equals(tex_info.getRequestType(id), LLTextureInfoDetails::REQUEST_TYPE_HTTP); +	} + +	// transport type is recorded correctly (udp) +	template<> template<> +	void textureinfo_object_t::test<8>() +	{ +		LLTextureInfo tex_info; +		tex_info.setUpLogging(true, true); + +		LLUUID id("10e65d70-46fd-429f-841a-bf698e9424d3"); +		tex_info.setRequestType(id, LLTextureInfoDetails::REQUEST_TYPE_UDP); + +		ensure_equals(tex_info.getRequestType(id), LLTextureInfoDetails::REQUEST_TYPE_UDP); +	} + +	// request offset is recorded correctly +	template<> template<> +	void textureinfo_object_t::test<9>() +	{ +		LLTextureInfo tex_info; +		tex_info.setUpLogging(true, true); + +		LLUUID id("10e65d70-46fd-429f-841a-bf698e9424d3"); +		tex_info.setRequestOffset(id, 1234); + +		ensure_equals(tex_info.getRequestOffset(id), 1234); +	} + +	// ask for averages gives us correct figure +	template<> template<> +	void textureinfo_object_t::test<10>() +	{ +		LLTextureInfo tex_info; +		tex_info.setUpLogging(true, true); + +		S32 requestStartTimeOne = 200; +		S32 requestEndTimeOne = 400; +		S32 requestSizeOne = 1024; +		S32 requestSizeOneBits = requestSizeOne * 8; +		LLUUID id1("10e65d70-46fd-429f-841a-bf698e9424d3"); +		tex_info.setRequestStartTime(id1, requestStartTimeOne); +		tex_info.setRequestSize(id1, requestSizeOne); +		tex_info.setRequestType(id1, LLTextureInfoDetails::REQUEST_TYPE_HTTP); +		tex_info.setRequestCompleteTimeAndLog(id1, requestEndTimeOne); + +		U32 requestStartTimeTwo = 100; +		U32 requestEndTimeTwo = 500; +		U32 requestSizeTwo = 2048; +		S32 requestSizeTwoBits = requestSizeTwo * 8; +		LLUUID id2("10e65d70-46fd-429f-841a-bf698e9424d4"); +		tex_info.setRequestStartTime(id2, requestStartTimeTwo); +		tex_info.setRequestSize(id2, requestSizeTwo); +		tex_info.setRequestType(id2, LLTextureInfoDetails::REQUEST_TYPE_HTTP); +		tex_info.setRequestCompleteTimeAndLog(id2, requestEndTimeTwo); + +		S32 averageBitRate = ((requestSizeOneBits/(requestEndTimeOne - requestStartTimeOne)) + +							(requestSizeTwoBits/(requestEndTimeTwo - requestStartTimeTwo))) / 2; + +		S32 totalBytes = requestSizeOne + requestSizeTwo; + +		LLSD results = tex_info.getAverages(); +		ensure_equals("is average bits per second correct", results["bits_per_second"].asInteger(), averageBitRate); +		ensure_equals("is total bytes is correct", results["bytes_downloaded"].asInteger(), totalBytes); +		ensure_equals("is transport correct", results["transport"].asString(), std::string("HTTP")); +	} + +	// make sure averages cleared when reset is called +	template<> template<> +	void textureinfo_object_t::test<11>() +	{ +		LLTextureInfo tex_info; +		tex_info.setUpLogging(true, true); + +		S32 requestStartTimeOne = 200; +		S32 requestEndTimeOne = 400; +		S32 requestSizeOne = 1024; +		LLUUID id1("10e65d70-46fd-429f-841a-bf698e9424d3"); +		tex_info.setRequestStartTime(id1, requestStartTimeOne); +		tex_info.setRequestSize(id1, requestSizeOne); +		tex_info.setRequestType(id1, LLTextureInfoDetails::REQUEST_TYPE_HTTP); +		tex_info.setRequestCompleteTimeAndLog(id1, requestEndTimeOne); + +		tex_info.getAverages(); +		tex_info.reset(); +		LLSD results = tex_info.getAverages(); +		ensure_equals("is average bits per second correct", results["bits_per_second"].asInteger(), 0); +		ensure_equals("is total bytes is correct", results["bytes_downloaded"].asInteger(), 0); +		ensure_equals("is transport correct", results["transport"].asString(), std::string("NONE")); +	} + +	// make sure map item removed when expired +	template<> template<> +	void textureinfo_object_t::test<12>() +	{ +		LLTextureInfo tex_info; +		tex_info.setUpLogging(true, true); + +		S32 requestStartTimeOne = 200; +		S32 requestEndTimeOne = 400; +		S32 requestSizeOne = 1024; +		LLUUID id1("10e65d70-46fd-429f-841a-bf698e9424d3"); +		tex_info.setRequestStartTime(id1, requestStartTimeOne); +		tex_info.setRequestSize(id1, requestSizeOne); +		tex_info.setRequestType(id1, LLTextureInfoDetails::REQUEST_TYPE_HTTP); + +		ensure_equals("map item created", tex_info.getTextureInfoMapSize(), 1); + +		tex_info.setRequestCompleteTimeAndLog(id1, requestEndTimeOne); + +		ensure_equals("map item removed when consumed", tex_info.getTextureInfoMapSize(), 0); +	} +} + diff --git a/indra/newview/tests/lltextureinfodetails_test.cpp b/indra/newview/tests/lltextureinfodetails_test.cpp new file mode 100644 index 0000000000..31ec5f9d4e --- /dev/null +++ b/indra/newview/tests/lltextureinfodetails_test.cpp @@ -0,0 +1,92 @@ +/**  + * @file llwtextureinfodetails_test.cpp + * @author Si & Gabriel + * @date 2009-03-30 + * + * $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$ + */ + +// Precompiled header: almost always required for newview cpp files +#include "../llviewerprecompiledheaders.h" +// Class to test +#include "../lltextureinfodetails.h" +// Dependencies + +// Tut header +#include "../test/lltut.h" + +// ------------------------------------------------------------------------------------------- +// Stubbing: Declarations required to link and run the class being tested +// Notes:  +// * Add here stubbed implementation of the few classes and methods used in the class to be tested +// * Add as little as possible (let the link errors guide you) +// * Do not make any assumption as to how those classes or methods work (i.e. don't copy/paste code) +// * A simulator for a class can be implemented here. Please comment and document thoroughly. + + +// End Stubbing +// ------------------------------------------------------------------------------------------- + +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- + +namespace tut +{ +	// Test wrapper declarations +	struct textureinfodetails_test +	{ +		// Constructor and destructor of the test wrapper +		textureinfodetails_test() +		{ +		} +		~textureinfodetails_test() +		{ +		} +	}; + +	// Tut templating thingamagic: test group, object and test instance +	typedef test_group<textureinfodetails_test> textureinfodetails_t; +	typedef textureinfodetails_t::object textureinfodetails_object_t; +	tut::textureinfodetails_t tut_textureinfodetails("LLTextureInfoDetails"); + +	 +	// --------------------------------------------------------------------------------------- +	// Test functions +	// Notes: +	// * Test as many as you possibly can without requiring a full blown simulation of everything +	// * The tests are executed in sequence so the test instance state may change between calls +	// * Remember that you cannot test private methods with tut +	// --------------------------------------------------------------------------------------- + +	// --------------------------------------------------------------------------------------- +	// Test the LLTextureInfo +	// --------------------------------------------------------------------------------------- + + +	// Test instantiation +	template<> template<> +	void textureinfodetails_object_t::test<1>() +	{ +		ensure("have we crashed?", true); +	} +} diff --git a/indra/newview/tests/lltexturestatsuploader_test.cpp b/indra/newview/tests/lltexturestatsuploader_test.cpp new file mode 100644 index 0000000000..cfb2c267cc --- /dev/null +++ b/indra/newview/tests/lltexturestatsuploader_test.cpp @@ -0,0 +1,150 @@ +/**  + * @file lltexturestatsuploader_test.cpp + * @author Si + * @date 2009-05-27 + * + * $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$ + */ + +// Precompiled header: almost always required for newview cpp files +#include "../llviewerprecompiledheaders.h" +// Class to test +#include "../lltexturestatsuploader.h" +// Dependencies + +// Tut header +#include "../test/lltut.h" + +// ------------------------------------------------------------------------------------------- +// Stubbing: Declarations required to link and run the class being tested +// Notes:  +// * Add here stubbed implementation of the few classes and methods used in the class to be tested +// * Add as little as possible (let the link errors guide you) +// * Do not make any assumption as to how those classes or methods work (i.e. don't copy/paste code) +// * A simulator for a class can be implemented here. Please comment and document thoroughly. + +#include "boost/intrusive_ptr.hpp" +void boost::intrusive_ptr_add_ref(LLCurl::Responder*){} +void boost::intrusive_ptr_release(LLCurl::Responder* p){} +const F32 HTTP_REQUEST_EXPIRY_SECS = 0.0f; + +static std::string most_recent_url; +static LLSD most_recent_body; + +void LLHTTPClient::post( +		const std::string& url, +		const LLSD& body, +		ResponderPtr, +		const LLSD& headers, +		const F32 timeout) +{ +	// set some sensor code +	most_recent_url = url; +	most_recent_body = body; +	return; +} + +// End Stubbing +// ------------------------------------------------------------------------------------------- + +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- + +namespace tut +{ +	// Test wrapper declarations +	struct texturestatsuploader_test +	{ +		// Constructor and destructor of the test wrapper +		texturestatsuploader_test() +		{ +			most_recent_url = "some sort of default text that should never match anything the tests are expecting!"; +			LLSD blank_llsd; +			most_recent_body = blank_llsd; +		} +		~texturestatsuploader_test() +		{ +		} +	}; + +	// Tut templating thingamagic: test group, object and test instance +	typedef test_group<texturestatsuploader_test> texturestatsuploader_t; +	typedef texturestatsuploader_t::object texturestatsuploader_object_t; +	tut::texturestatsuploader_t tut_texturestatsuploader("LLTextureStatsUploader"); + +	 +	// --------------------------------------------------------------------------------------- +	// Test functions +	// Notes: +	// * Test as many as you possibly can without requiring a full blown simulation of everything +	// * The tests are executed in sequence so the test instance state may change between calls +	// * Remember that you cannot test private methods with tut +	// --------------------------------------------------------------------------------------- + +	// --------------------------------------------------------------------------------------- +	// Test the LLTextureInfo +	// --------------------------------------------------------------------------------------- + + +	// Test instantiation +	template<> template<> +	void texturestatsuploader_object_t::test<1>() +	{ +		LLTextureStatsUploader tsu; +		llinfos << &tsu << llendl; +		ensure("have we crashed?", true); +	} + +	// does it call out to the provided url if we ask it to? +	template<> template<> +	void texturestatsuploader_object_t::test<2>() +	{	 +		LLTextureStatsUploader tsu; +		std::string url = "http://blahblahblah"; +		LLSD texture_stats; +		tsu.uploadStatsToSimulator(url, texture_stats); +		ensure_equals("did the right url get called?", most_recent_url, url); +		ensure_equals("did the right body get sent?", most_recent_body, texture_stats); +	} + +	// does it not call out to the provided url if we send it an ungranted cap? +	template<> template<> +	void texturestatsuploader_object_t::test<3>() +	{	 +		LLTextureStatsUploader tsu; + +		// this url left intentionally blank to mirror +		// not getting a cap in the caller. +		std::string url_for_ungranted_cap = "";  +							   +		LLSD texture_stats; +		std::string most_recent_url_before_test = most_recent_url; +		tsu.uploadStatsToSimulator(url_for_ungranted_cap, texture_stats); + +		ensure_equals("hopefully no url got called!", most_recent_url, most_recent_url_before_test); +	} + +	// does it call out if the data is empty? +	// should it even do that? +} + diff --git a/indra/newview/tests/llviewerhelputil_test.cpp b/indra/newview/tests/llviewerhelputil_test.cpp new file mode 100644 index 0000000000..a0f1d1c3c3 --- /dev/null +++ b/indra/newview/tests/llviewerhelputil_test.cpp @@ -0,0 +1,165 @@ +/**  + * @file llviewerhelputil_test.cpp + * @brief LLViewerHelpUtil tests + * @author Tofu Linden + * + * $LicenseInfo:firstyear=2001&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$ + */ +// Precompiled header +#include "../llviewerprecompiledheaders.h" + +#include "../test/lltut.h" + +#include "../llviewerhelputil.h" +#include "../llweb.h" +#include "llcontrol.h" + +#include <iostream> + +// values for all of the supported substitutions parameters +static std::string gHelpURL; +static std::string gVersion; +static std::string gChannel; +static std::string gLanguage; +static std::string gGrid; +static std::string gOS; + +//---------------------------------------------------------------------------- +// Mock objects for the dependencies of the code we're testing + +LLControlGroup::LLControlGroup(const std::string& name) +	: LLInstanceTracker<LLControlGroup, std::string>(name) {} +LLControlGroup::~LLControlGroup() {} +BOOL LLControlGroup::declareString(const std::string& name, +				   const std::string& initial_val, +				   const std::string& comment, +				   BOOL persist) {return TRUE;} +void LLControlGroup::setString(const std::string& name, const std::string& val){} +std::string LLControlGroup::getString(const std::string& name) +{ +	if (name == "HelpURLFormat") +		return gHelpURL; +	return ""; +} +LLControlGroup gSavedSettings("test"); + +static void substitute_string(std::string &input, const std::string &search, const std::string &replace) +{ +	size_t pos = input.find(search); +	while (pos != std::string::npos) +	{ +		input = input.replace(pos, search.size(), replace); +		pos = input.find(search); +	} +} + +class LLAgent +{ +public: +	LLAgent() {} +	~LLAgent() {} +#ifdef __GNUC__ +	__attribute__ ((noinline)) +#endif +	bool isGodlike() const { return FALSE; } +}; +LLAgent gAgent; + +std::string LLWeb::expandURLSubstitutions(const std::string &url, +										  const LLSD &default_subs) +{ +	(void)gAgent.isGodlike(); // ref symbol to stop compiler from stripping it +	std::string new_url = url; +	substitute_string(new_url, "[TOPIC]", default_subs["TOPIC"].asString()); +	substitute_string(new_url, "[VERSION]", gVersion); +	substitute_string(new_url, "[CHANNEL]", gChannel); +	substitute_string(new_url, "[LANGUAGE]", gLanguage); +	substitute_string(new_url, "[GRID]", gGrid); +	substitute_string(new_url, "[OS]", gOS); +	return new_url; +} + + +//---------------------------------------------------------------------------- +	 +namespace tut +{ +    struct viewerhelputil +    { +    }; +     +	typedef test_group<viewerhelputil> viewerhelputil_t; +	typedef viewerhelputil_t::object viewerhelputil_object_t; +	tut::viewerhelputil_t tut_viewerhelputil("LLViewerHelpUtil"); + +	template<> template<> +	void viewerhelputil_object_t::test<1>() +	{ +		std::string topic("test_topic"); +		std::string subresult; + +		gHelpURL = "fooformat"; +		subresult = LLViewerHelpUtil::buildHelpURL(topic); +		ensure_equals("no substitution tags", subresult, "fooformat"); + +		gHelpURL = ""; +		subresult = LLViewerHelpUtil::buildHelpURL(topic); +		ensure_equals("blank substitution format", subresult, ""); + +		gHelpURL = "[TOPIC]"; +		subresult = LLViewerHelpUtil::buildHelpURL(topic); +		ensure_equals("topic name", subresult, "test_topic"); + +		gHelpURL = "[LANGUAGE]"; +		gLanguage = ""; +		subresult = LLViewerHelpUtil::buildHelpURL(topic); +		ensure_equals("simple substitution with blank", subresult, ""); + +		gHelpURL = "[LANGUAGE]"; +		gLanguage = "Esperanto"; +		subresult = LLViewerHelpUtil::buildHelpURL(topic); +		ensure_equals("simple substitution", subresult, "Esperanto"); + +		gHelpURL = "http://secondlife.com/[LANGUAGE]"; +		gLanguage = "Gaelic"; +		subresult = LLViewerHelpUtil::buildHelpURL(topic); +		ensure_equals("simple substitution with url", subresult, "http://secondlife.com/Gaelic"); + +		gHelpURL = "[XXX]"; +		subresult = LLViewerHelpUtil::buildHelpURL(topic); +		ensure_equals("unknown substitution", subresult, "[XXX]"); + +		gHelpURL = "[LANGUAGE]/[LANGUAGE]"; +		gLanguage = "Esperanto"; +		subresult = LLViewerHelpUtil::buildHelpURL(topic); +		ensure_equals("multiple substitution", subresult, "Esperanto/Esperanto"); + +		gHelpURL = "http://[CHANNEL]/[VERSION]/[LANGUAGE]/[OS]/[GRID]/[XXX]"; +		gChannel = "Second Life Test"; +		gVersion = "2.0"; +		gLanguage = "gaelic"; +		gOS = "AmigaOS 2.1"; +		gGrid = "mysim"; +		subresult = LLViewerHelpUtil::buildHelpURL(topic); +		ensure_equals("complex substitution", subresult, "http://Second Life Test/2.0/gaelic/AmigaOS 2.1/mysim/[XXX]"); +	} +} diff --git a/indra/newview/tests/llviewernetwork_test.cpp b/indra/newview/tests/llviewernetwork_test.cpp new file mode 100644 index 0000000000..dd7761475e --- /dev/null +++ b/indra/newview/tests/llviewernetwork_test.cpp @@ -0,0 +1,581 @@ +/**  + * @file llviewernetwork_test.cpp + * @author Roxie + * @date 2009-03-9 + * @brief Test the viewernetwork functionality + * + * $LicenseInfo:firstyear=2009&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 "../llviewerprecompiledheaders.h" +#include "../llviewernetwork.h" +#include "../test/lltut.h" +#include "../../llxml/llcontrol.h" +#include "llfile.h" + +//----------------------------------------------------------------------------                +// Mock objects for the dependencies of the code we're testing                                + +LLControlGroup::LLControlGroup(const std::string& name) +: LLInstanceTracker<LLControlGroup, std::string>(name) {} +LLControlGroup::~LLControlGroup() {} +BOOL LLControlGroup::declareString(const std::string& name, +                                   const std::string& initial_val, +                                   const std::string& comment, +                                   BOOL persist) {return TRUE;} +void LLControlGroup::setString(const std::string& name, const std::string& val){} + +std::string gCmdLineLoginURI; +std::string gCmdLineGridChoice; +std::string gCmdLineHelperURI; +std::string gLoginPage; +std::string gCurrentGrid; +std::string LLControlGroup::getString(const std::string& name) +{ +	if (name == "CmdLineGridChoice") +		return gCmdLineGridChoice; +	else if (name == "CmdLineHelperURI") +		return gCmdLineHelperURI; +	else if (name == "LoginPage") +		return gLoginPage; +	else if (name == "CurrentGrid") +		return gCurrentGrid; +	return ""; +} + +LLSD LLControlGroup::getLLSD(const std::string& name) +{ +	if (name == "CmdLineLoginURI") +	{ +		if(!gCmdLineLoginURI.empty()) +		{ +			return LLSD(gCmdLineLoginURI); +		} +	} +	return LLSD(); +} + +LLPointer<LLControlVariable> LLControlGroup::getControl(const std::string& name) +{ +	ctrl_name_table_t::iterator iter = mNameTable.find(name); +	return iter == mNameTable.end() ? LLPointer<LLControlVariable>() : iter->second; +} + +LLControlGroup gSavedSettings("test"); + +const char *gSampleGridFile = "<llsd><map>" +"<key>grid1</key><map>" +"  <key>favorite</key><integer>1</integer>" +"  <key>helper_uri</key><string>https://helper1/helpers/</string>" +"  <key>label</key><string>mylabel</string>" +"  <key>login_page</key><string>loginpage</string>" +"  <key>login_uri</key><array><string>myloginuri</string></array>" +"  <key>name</key><string>grid1</string>" +"  <key>visible</key><integer>1</integer>" +"  <key>credential_type</key><string>agent</string>" +"  <key>grid_login_id</key><string>MyGrid</string>" +"</map>" +"<key>util.agni.lindenlab.com</key><map>" +"  <key>favorite</key><integer>1</integer>" +"  <key>helper_uri</key><string>https://helper1/helpers/</string>" +"  <key>label</key><string>mylabel</string>" +"  <key>login_page</key><string>loginpage</string>" +"  <key>login_uri</key><array><string>myloginuri</string></array>" +"  <key>name</key><string>util.agni.lindenlab.com</string>" +"</map></map></llsd>"; +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- +namespace tut +{ +  // Test wrapper declaration : wrapping nothing for the moment +  struct viewerNetworkTest +	{ +		viewerNetworkTest() +		{ +			LLFile::remove("grid_test.xml"); +			gCmdLineLoginURI.clear(); +			gCmdLineGridChoice.clear(); +			gCmdLineHelperURI.clear(); +			gLoginPage.clear(); +			gCurrentGrid.clear();			 +		} +		~viewerNetworkTest() +		{ +			LLFile::remove("grid_test.xml"); +		} +	}; +	 +	// Tut templating thingamagic: test group, object and test instance +	typedef test_group<viewerNetworkTest> viewerNetworkTestFactory; +	typedef viewerNetworkTestFactory::object viewerNetworkTestObject; +	tut::viewerNetworkTestFactory tut_test("LLViewerNetwork"); +	 +	// --------------------------------------------------------------------------------------- +	// Test functions  +	// --------------------------------------------------------------------------------------- +	// initialization without a grid file +	template<> template<> +	void viewerNetworkTestObject::test<1>() +	{ + +		LLGridManager *manager = LLGridManager::getInstance(); +		// grid file doesn't exist +		manager->initialize("grid_test.xml"); +		// validate that some of the defaults are available. +		std::map<std::string, std::string> known_grids = manager->getKnownGrids(); +		ensure_equals("Known grids is a string-string map of size 23", known_grids.size(), 23); +		ensure_equals("Agni has the right name and label",  +					  known_grids[std::string("util.agni.lindenlab.com")], std::string("Agni")); +		ensure_equals("None exists", known_grids[""], "None"); +		 +		LLSD grid; +		LLGridManager::getInstance()->getGridInfo("util.agni.lindenlab.com", grid); +		ensure("Grid info for agni is a map", grid.isMap()); +		ensure_equals("name is correct for agni",  +					  grid[GRID_VALUE].asString(), std::string("util.agni.lindenlab.com")); +		ensure_equals("label is correct for agni",  +					  grid[GRID_LABEL_VALUE].asString(), std::string("Agni")); +		ensure("Login URI is an array",  +			   grid[GRID_LOGIN_URI_VALUE].isArray()); +		ensure_equals("Agni login uri is correct",  +					  grid[GRID_LOGIN_URI_VALUE][0].asString(),  +					  std::string("https://login.agni.lindenlab.com/cgi-bin/login.cgi")); +		ensure_equals("Agni helper uri is correct", +					  grid[GRID_HELPER_URI_VALUE].asString(),  +					  std::string("https://secondlife.com/helpers/")); +		ensure_equals("Agni login page is correct", +					  grid[GRID_LOGIN_PAGE_VALUE].asString(),  +					  std::string("http://secondlife.com/app/login/")); +		ensure("Agni is a favorite", +			   grid.has(GRID_IS_FAVORITE_VALUE)); +		ensure("Agni is a system grid",  +			   grid.has(GRID_IS_SYSTEM_GRID_VALUE)); +		ensure("Grid file wasn't greated as it wasn't saved",  +			   !LLFile::isfile("grid_test.xml")); +	} +	 +	// initialization with a grid file +	template<> template<> +	void viewerNetworkTestObject::test<2>() +	{ +		llofstream gridfile("grid_test.xml"); +		gridfile << gSampleGridFile; +		gridfile.close(); +		 +		LLGridManager::getInstance()->initialize("grid_test.xml"); +		std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids(); +		ensure_equals("adding a grid via a grid file increases known grid size",  +					  known_grids.size(), 24); +		ensure_equals("Agni is still there after we've added a grid via a grid file",  +					  known_grids["util.agni.lindenlab.com"], std::string("Agni")); +	 +		 +		// assure Agni doesn't get overwritten +		LLSD grid; +		LLGridManager::getInstance()->getGridInfo("util.agni.lindenlab.com", grid); + +		ensure_equals("Agni grid label was not modified by grid file",  +					  grid[GRID_LABEL_VALUE].asString(), std::string("Agni")); +		 +		ensure_equals("Agni name wasn't modified by grid file", +					  grid[GRID_VALUE].asString(), std::string("util.agni.lindenlab.com")); +		ensure("Agni grid URI is still an array after grid file",  +			   grid[GRID_LOGIN_URI_VALUE].isArray()); +		ensure_equals("Agni login uri still the same after grid file",  +					  grid[GRID_LOGIN_URI_VALUE][0].asString(),   +					  std::string("https://login.agni.lindenlab.com/cgi-bin/login.cgi")); +		ensure_equals("Agni helper uri still the same after grid file",  +					  grid[GRID_HELPER_URI_VALUE].asString(),  +					  std::string("https://secondlife.com/helpers/")); +		ensure_equals("Agni login page the same after grid file",  +					  grid[GRID_LOGIN_PAGE_VALUE].asString(),  +					  std::string("http://secondlife.com/app/login/")); +		ensure("Agni still a favorite after grid file",  +			   grid.has(GRID_IS_FAVORITE_VALUE)); +		ensure("Agni system grid still set after grid file",  +			   grid.has(GRID_IS_SYSTEM_GRID_VALUE)); +		 +		ensure_equals("Grid file adds to name<->label map",  +					  known_grids["grid1"], std::string("mylabel")); +		LLGridManager::getInstance()->getGridInfo("grid1", grid); +		ensure_equals("grid file grid name is set", +					  grid[GRID_VALUE].asString(), std::string("grid1")); +		ensure_equals("grid file label is set",  +					  grid[GRID_LABEL_VALUE].asString(), std::string("mylabel")); +		ensure("grid file login uri is an array", +			   grid[GRID_LOGIN_URI_VALUE].isArray()); +		ensure_equals("grid file login uri is set", +					  grid[GRID_LOGIN_URI_VALUE][0].asString(),  +					  std::string("myloginuri")); +		ensure_equals("grid file helper uri is set", +					  grid[GRID_HELPER_URI_VALUE].asString(),  +					  std::string("https://helper1/helpers/")); +		ensure_equals("grid file login page is set", +					  grid[GRID_LOGIN_PAGE_VALUE].asString(),  +					  std::string("loginpage")); +		ensure("grid file favorite is set", +			   grid.has(GRID_IS_FAVORITE_VALUE)); +		ensure("grid file isn't a system grid", +			   !grid.has(GRID_IS_SYSTEM_GRID_VALUE));		 +		ensure("Grid file still exists after loading",  +			   LLFile::isfile("grid_test.xml")); +	} +	 +	// Initialize via command line +	 +	template<> template<> +	void viewerNetworkTestObject::test<3>() +	{	 +		// USE --grid command line +		// initialize with a known grid +		LLSD grid; +		gCmdLineGridChoice = "Aditi"; +		LLGridManager::getInstance()->initialize("grid_test.xml"); +		// with single login uri specified. +		std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids(); +		ensure_equals("Using a known grid via command line doesn't increase number of known grids",  +					  known_grids.size(), 23); +		ensure_equals("getGridLabel", LLGridManager::getInstance()->getGridLabel(), std::string("Aditi")); +		// initialize with a known grid in lowercase +		gCmdLineGridChoice = "agni"; +		LLGridManager::getInstance()->initialize("grid_test.xml"); +		ensure_equals("getGridLabel", LLGridManager::getInstance()->getGridLabel(), std::string("Agni"));		 +		 +		// now try a command line with a custom grid identifier +		gCmdLineGridChoice = "mycustomgridchoice";		 +		LLGridManager::getInstance()->initialize("grid_test.xml"); +		known_grids = LLGridManager::getInstance()->getKnownGrids(); +		ensure_equals("adding a command line grid with custom name increases known grid size",  +					  known_grids.size(), 24); +		ensure_equals("Custom Command line grid is added to the list of grids",  +					  known_grids["mycustomgridchoice"], std::string("mycustomgridchoice")); +		LLGridManager::getInstance()->getGridInfo("mycustomgridchoice", grid); +		ensure_equals("Custom Command line grid name is set", +					  grid[GRID_VALUE].asString(), std::string("mycustomgridchoice")); +		ensure_equals("Custom Command line grid label is set",  +					  grid[GRID_LABEL_VALUE].asString(), std::string("mycustomgridchoice"));		 +		ensure("Custom Command line grid login uri is an array", +			   grid[GRID_LOGIN_URI_VALUE].isArray()); +		ensure_equals("Custom Command line grid login uri is set", +					  grid[GRID_LOGIN_URI_VALUE][0].asString(),  +					  std::string("https://mycustomgridchoice/cgi-bin/login.cgi")); +		ensure_equals("Custom Command line grid helper uri is set", +					  grid[GRID_HELPER_URI_VALUE].asString(),  +					  std::string("https://mycustomgridchoice/helpers/")); +		ensure_equals("Custom Command line grid login page is set", +					  grid[GRID_LOGIN_PAGE_VALUE].asString(),  +					  std::string("http://mycustomgridchoice/app/login/")); +	} +	 +	// validate override of login uri with cmd line +	template<> template<> +	void viewerNetworkTestObject::test<4>() +	{			 +		// Override with loginuri +		// override known grid +		LLSD grid; +		gCmdLineGridChoice = "Aditi"; +		gCmdLineLoginURI = "https://my.login.uri/cgi-bin/login.cgi";		 +		LLGridManager::getInstance()->initialize("grid_test.xml");		 +		std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids();		 +		ensure_equals("Override known grid login uri: No grids are added",  +					  known_grids.size(), 23); +		LLGridManager::getInstance()->getGridInfo(grid); +		ensure("Override known grid login uri: login uri is an array", +			   grid[GRID_LOGIN_URI_VALUE].isArray()); +		ensure_equals("Override known grid login uri: Command line grid login uri is set", +					  grid[GRID_LOGIN_URI_VALUE][0].asString(),  +					  std::string("https://my.login.uri/cgi-bin/login.cgi")); +		ensure_equals("Override known grid login uri: helper uri is not changed", +					  grid[GRID_HELPER_URI_VALUE].asString(),  +					  std::string("http://aditi-secondlife.webdev.lindenlab.com/helpers/")); +		ensure_equals("Override known grid login uri: login page is not set", +					  grid[GRID_LOGIN_PAGE_VALUE].asString(),  +					  std::string("http://secondlife.com/app/login/"));		 +		 +		// Override with loginuri +		// override custom grid +		gCmdLineGridChoice = "mycustomgridchoice"; +		gCmdLineLoginURI = "https://my.login.uri/cgi-bin/login.cgi";		 +		LLGridManager::getInstance()->initialize("grid_test.xml");		 +		known_grids = LLGridManager::getInstance()->getKnownGrids(); +		LLGridManager::getInstance()->getGridInfo(grid); +		ensure_equals("Override custom grid login uri: Grid is added",  +					  known_grids.size(), 24);		 +		ensure("Override custom grid login uri: login uri is an array", +			   grid[GRID_LOGIN_URI_VALUE].isArray()); +		ensure_equals("Override custom grid login uri: login uri is set", +					  grid[GRID_LOGIN_URI_VALUE][0].asString(),  +					  std::string("https://my.login.uri/cgi-bin/login.cgi")); +		ensure_equals("Override custom grid login uri: Helper uri is not set", +					  grid[GRID_HELPER_URI_VALUE].asString(),  +					  std::string("https://mycustomgridchoice/helpers/")); +		ensure_equals("Override custom grid login uri: Login page is not set", +					  grid[GRID_LOGIN_PAGE_VALUE].asString(),  +					  std::string("http://mycustomgridchoice/app/login/")); +	} +	 +	// validate override of helper uri with cmd line +	template<> template<> +	void viewerNetworkTestObject::test<5>() +	{	 +		// Override with helperuri +		// override known grid +		LLSD grid; +		gCmdLineGridChoice = "Aditi"; +		gCmdLineLoginURI = ""; +		gCmdLineHelperURI = "https://my.helper.uri/mycustomhelpers";		 +		LLGridManager::getInstance()->initialize("grid_test.xml");		 +		std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids();		 +		ensure_equals("Override known grid helper uri: No grids are added",  +					  known_grids.size(), 23); +		LLGridManager::getInstance()->getGridInfo(grid); +		ensure("Override known known helper uri: login uri is an array", +			   grid[GRID_LOGIN_URI_VALUE].isArray()); +		ensure_equals("Override known grid helper uri: login uri is not changed", +					  grid[GRID_LOGIN_URI_VALUE][0].asString(),  +					  std::string("https://login.aditi.lindenlab.com/cgi-bin/login.cgi")); +		ensure_equals("Override known grid helper uri: helper uri is changed", +					  grid[GRID_HELPER_URI_VALUE].asString(),  +					  std::string("https://my.helper.uri/mycustomhelpers")); +		ensure_equals("Override known grid helper uri: login page is not changed", +					  grid[GRID_LOGIN_PAGE_VALUE].asString(),  +					  std::string("http://secondlife.com/app/login/"));		 +		 +		// Override with helperuri +		// override custom grid +		gCmdLineGridChoice = "mycustomgridchoice"; +		gCmdLineHelperURI = "https://my.helper.uri/mycustomhelpers";		 +		LLGridManager::getInstance()->initialize("grid_test.xml");	 +		known_grids = LLGridManager::getInstance()->getKnownGrids(); +		ensure_equals("Override custom grid helper uri: grids is added",  +					  known_grids.size(), 24); +		LLGridManager::getInstance()->getGridInfo(grid); +		ensure("Override custom helper uri: login uri is an array", +			   grid[GRID_LOGIN_URI_VALUE].isArray()); +		ensure_equals("Override custom grid helper uri: login uri is not changed", +					  grid[GRID_LOGIN_URI_VALUE][0].asString(),  +					  std::string("https://mycustomgridchoice/cgi-bin/login.cgi")); +		ensure_equals("Override custom grid helper uri: helper uri is changed", +					  grid[GRID_HELPER_URI_VALUE].asString(),  +					  std::string("https://my.helper.uri/mycustomhelpers")); +		ensure_equals("Override custom grid helper uri: login page is not changed", +					  grid[GRID_LOGIN_PAGE_VALUE].asString(),  +					  std::string("http://mycustomgridchoice/app/login/")); +	} +	 +	// validate overriding of login page via cmd line +	template<> template<> +	void viewerNetworkTestObject::test<6>() +	{	 +		// Override with login page +		// override known grid +		LLSD grid; +		gCmdLineGridChoice = "Aditi"; +		gCmdLineHelperURI = ""; +		gLoginPage = "myloginpage";		 +		LLGridManager::getInstance()->initialize("grid_test.xml");		 +		std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids();				 +		ensure_equals("Override known grid login page: No grids are added",  +					  known_grids.size(), 23); +		LLGridManager::getInstance()->getGridInfo(grid); +		ensure("Override known grid login page: Command line grid login uri is an array", +			   grid[GRID_LOGIN_URI_VALUE].isArray()); +		ensure_equals("Override known grid login page: login uri is not changed", +					  grid[GRID_LOGIN_URI_VALUE][0].asString(),  +					  std::string("https://login.aditi.lindenlab.com/cgi-bin/login.cgi")); +		ensure_equals("Override known grid login page: helper uri is not changed", +					  grid[GRID_HELPER_URI_VALUE].asString(),  +					  std::string("http://aditi-secondlife.webdev.lindenlab.com/helpers/")); +		ensure_equals("Override known grid login page: login page is changed", +					  grid[GRID_LOGIN_PAGE_VALUE].asString(),  +					  std::string("myloginpage"));		 +		 +		// Override with login page +		// override custom grid +		gCmdLineGridChoice = "mycustomgridchoice"; +		gLoginPage = "myloginpage"; +		LLGridManager::getInstance()->initialize("grid_test.xml");		 +		known_grids = LLGridManager::getInstance()->getKnownGrids(); +		ensure_equals("Override custom grid login page: grids are added",  +					  known_grids.size(), 24); +		LLGridManager::getInstance()->getGridInfo(grid); +		ensure("Override custom grid login page: Command line grid login uri is an array", +			   grid[GRID_LOGIN_URI_VALUE].isArray()); +		ensure_equals("Override custom grid login page: login uri is not changed", +					  grid[GRID_LOGIN_URI_VALUE][0].asString(),  +					  std::string("https://mycustomgridchoice/cgi-bin/login.cgi")); +		ensure_equals("Override custom grid login page: helper uri is not changed", +					  grid[GRID_HELPER_URI_VALUE].asString(),  +					  std::string("https://mycustomgridchoice/helpers/")); +		ensure_equals("Override custom grid login page: login page is changed", +					  grid[GRID_LOGIN_PAGE_VALUE].asString(),  +					  std::string("myloginpage"));	 +		 +	} +	 +	// validate grid selection +	template<> template<> +	void viewerNetworkTestObject::test<7>() +	{	 +		LLSD loginURI = LLSD::emptyArray(); +		LLSD grid = LLSD::emptyMap(); +		// adding a grid with simply a name will populate the values. +		grid[GRID_VALUE] = "myaddedgrid"; + +		LLGridManager::getInstance()->initialize("grid_test.xml"); +		LLGridManager::getInstance()->addGrid(grid); +		LLGridManager::getInstance()->setGridChoice("util.agni.lindenlab.com");	 +		ensure_equals("getGridLabel", LLGridManager::getInstance()->getGridLabel(), std::string("Agni")); +		ensure_equals("getGrid", LLGridManager::getInstance()->getGrid(),  +					  std::string("util.agni.lindenlab.com")); +		ensure_equals("getHelperURI", LLGridManager::getInstance()->getHelperURI(),  +					  std::string("https://secondlife.com/helpers/")); +		ensure_equals("getLoginPage", LLGridManager::getInstance()->getLoginPage(),  +					  std::string("http://secondlife.com/app/login/")); +		ensure_equals("getLoginPage2", LLGridManager::getInstance()->getLoginPage("util.agni.lindenlab.com"),  +					  std::string("http://secondlife.com/app/login/")); +		ensure("Is Agni a production grid", LLGridManager::getInstance()->isInProductionGrid());		 +		std::vector<std::string> uris; +		LLGridManager::getInstance()->getLoginURIs(uris); +		ensure_equals("getLoginURIs size", uris.size(), 1); +		ensure_equals("getLoginURIs", uris[0],  +					  std::string("https://login.agni.lindenlab.com/cgi-bin/login.cgi")); +		LLGridManager::getInstance()->setGridChoice("myaddedgrid"); +		ensure_equals("getGridLabel", LLGridManager::getInstance()->getGridLabel(), std::string("myaddedgrid"));		 +		ensure("Is myaddedgrid a production grid", !LLGridManager::getInstance()->isInProductionGrid()); +		 +		LLGridManager::getInstance()->setFavorite(); +		LLGridManager::getInstance()->getGridInfo("myaddedgrid", grid); +		ensure("setting favorite", grid.has(GRID_IS_FAVORITE_VALUE)); +	} +	 +	// name based grid population +	template<> template<> +	void viewerNetworkTestObject::test<8>() +	{ +		LLGridManager::getInstance()->initialize("grid_test.xml"); +		LLSD grid = LLSD::emptyMap(); +		// adding a grid with simply a name will populate the values. +		grid[GRID_VALUE] = "myaddedgrid"; +		LLGridManager::getInstance()->addGrid(grid); +		LLGridManager::getInstance()->getGridInfo("myaddedgrid", grid); +		 +		ensure_equals("name based grid has name value",  +					  grid[GRID_VALUE].asString(), +					  std::string("myaddedgrid")); +		ensure_equals("name based grid has label value",  +					  grid[GRID_LABEL_VALUE].asString(), +					  std::string("myaddedgrid")); +		ensure_equals("name based grid has name value",  +					  grid[GRID_HELPER_URI_VALUE].asString(), +					  std::string("https://myaddedgrid/helpers/")); +		ensure_equals("name based grid has name value",  +					  grid[GRID_LOGIN_PAGE_VALUE].asString(), +					  std::string("http://myaddedgrid/app/login/")); +		ensure("name based grid has array loginuri",  +			   grid[GRID_LOGIN_URI_VALUE].isArray()); +		ensure_equals("name based grid has single login uri value", +			   grid[GRID_LOGIN_URI_VALUE].size(), 1); +		ensure_equals("Name based grid login uri is correct", +					  grid[GRID_LOGIN_URI_VALUE][0].asString(), +					  std::string("https://myaddedgrid/cgi-bin/login.cgi")); +		ensure("name based grid is not a favorite yet",  +			   !grid.has(GRID_IS_FAVORITE_VALUE)); +		ensure("name based grid does not have system setting", +			   !grid.has(GRID_IS_SYSTEM_GRID_VALUE)); +		 +		llofstream gridfile("grid_test.xml"); +		gridfile << gSampleGridFile; +		gridfile.close(); +	} +	 +	// persistence of the grid list with an empty gridfile. +	template<> template<> +	void viewerNetworkTestObject::test<9>() +	{ +		// try with initial grid list without a grid file, +		// without setting the grid to a saveable favorite. +		LLGridManager::getInstance()->initialize("grid_test.xml"); +		LLSD grid = LLSD::emptyMap(); +		grid[GRID_VALUE] = std::string("mynewgridname"); +		LLGridManager::getInstance()->addGrid(grid); +		LLGridManager::getInstance()->saveFavorites(); +		ensure("Grid file exists after saving",  +			   LLFile::isfile("grid_test.xml")); +		LLGridManager::getInstance()->initialize("grid_test.xml"); +		// should not be there +		std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids(); +		ensure("New grid wasn't added to persisted list without being marked a favorite", +					  known_grids.find(std::string("mynewgridname")) == known_grids.end()); +		 +		// mark a grid a favorite to make sure it's persisted +		LLGridManager::getInstance()->addGrid(grid); +		LLGridManager::getInstance()->setGridChoice("mynewgridname"); +		LLGridManager::getInstance()->setFavorite(); +		LLGridManager::getInstance()->saveFavorites(); +		ensure("Grid file exists after saving",  +			   LLFile::isfile("grid_test.xml")); +		LLGridManager::getInstance()->initialize("grid_test.xml"); +		// should not be there +		known_grids = LLGridManager::getInstance()->getKnownGrids(); +		ensure("New grid wasn't added to persisted list after being marked a favorite", +					  known_grids.find(std::string("mynewgridname")) != +					  known_grids.end()); +	} +	 +	// persistence of the grid file with existing gridfile +	template<> template<> +	void viewerNetworkTestObject::test<10>() +	{ +		 +		llofstream gridfile("grid_test.xml"); +		gridfile << gSampleGridFile; +		gridfile.close(); +		 +		LLGridManager::getInstance()->initialize("grid_test.xml"); +		LLSD grid = LLSD::emptyMap(); +		grid[GRID_VALUE] = std::string("mynewgridname"); +		LLGridManager::getInstance()->addGrid(grid); +		LLGridManager::getInstance()->saveFavorites(); +		// validate we didn't lose existing favorites +		LLGridManager::getInstance()->initialize("grid_test.xml"); +		std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids(); +		ensure("New grid wasn't added to persisted list after being marked a favorite", +			   known_grids.find(std::string("grid1")) != +			   known_grids.end()); +		 +		// add a grid +		LLGridManager::getInstance()->addGrid(grid); +		LLGridManager::getInstance()->setGridChoice("mynewgridname"); +		LLGridManager::getInstance()->setFavorite(); +		LLGridManager::getInstance()->saveFavorites(); +		known_grids = LLGridManager::getInstance()->getKnownGrids(); +		ensure("New grid wasn't added to persisted list after being marked a favorite", +			   known_grids.find(std::string("grid1")) != +			   known_grids.end()); +		known_grids = LLGridManager::getInstance()->getKnownGrids(); +		ensure("New grid wasn't added to persisted list after being marked a favorite", +			   known_grids.find(std::string("mynewgridname")) != +			   known_grids.end()); +	} +} diff --git a/indra/newview/tests/llworldmap_test.cpp b/indra/newview/tests/llworldmap_test.cpp new file mode 100644 index 0000000000..b976ac5ea9 --- /dev/null +++ b/indra/newview/tests/llworldmap_test.cpp @@ -0,0 +1,517 @@ +/**  + * @file llworldmap_test.cpp + * @author Merov Linden + * @date 2009-03-09 + * + * $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$ + */ + +// Precompiled header: almost always required for newview cpp files +#include "../llviewerprecompiledheaders.h" +// Class to test +#include "../llworldmap.h" +// Dependencies +#include "../llviewerimagelist.h" +#include "../llworldmapmessage.h" +// Tut header +#include "../test/lltut.h" + +// ------------------------------------------------------------------------------------------- +// Stubbing: Declarations required to link and run the class being tested +// Notes:  +// * Add here stubbed implementation of the few classes and methods used in the class to be tested +// * Add as little as possible (let the link errors guide you) +// * Do not make any assumption as to how those classes or methods work (i.e. don't copy/paste code) +// * A simulator for a class can be implemented here. Please comment and document thoroughly. + +// Stub image calls +LLViewerImageList::LLViewerImageList() { } +LLViewerImageList::~LLViewerImageList() { } +LLViewerImageList gImageList; +LLViewerImage* LLViewerImageList::getImage(const LLUUID &image_id, +												   BOOL usemipmaps, +												   BOOL level_immediate, +												   LLGLint internal_format, +												   LLGLenum primary_format, +												   LLHost request_from_host) +{ return NULL; } +void LLViewerImage::setBoostLevel(S32 level) { } +void LLImageGL::setAddressMode(LLTexUnit::eTextureAddressMode mode) { } + +// Stub related map calls +LLWorldMapMessage::LLWorldMapMessage() { } +LLWorldMapMessage::~LLWorldMapMessage() { } +void LLWorldMapMessage::sendItemRequest(U32 type, U64 handle) { } +void LLWorldMapMessage::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent) { } +LLWorldMipmap::LLWorldMipmap() { } +LLWorldMipmap::~LLWorldMipmap() { } +void LLWorldMipmap::reset() { } +void LLWorldMipmap::dropBoostLevels() { } +void LLWorldMipmap::equalizeBoostLevels() { } +LLPointer<LLViewerImage> LLWorldMipmap::getObjectsTile(U32 grid_x, U32 grid_y, S32 level, bool load) +{ return NULL; } + +// Stub other stuff +BOOL gPacificDaylightTime; + +// End Stubbing +// ------------------------------------------------------------------------------------------- + +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- + +const F32 X_WORLD_TEST = 1000.0f * REGION_WIDTH_METERS; +const F32 Y_WORLD_TEST = 2000.0f * REGION_WIDTH_METERS; +const F32 Z_WORLD_TEST = 240.0f; +const std::string ITEM_NAME_TEST = "Item Foo"; +const std::string TOOLTIP_TEST = "Tooltip Foo"; + +const std::string SIM_NAME_TEST = "Sim Foo"; + +namespace tut +{ +	// Test wrapper declarations +	struct iteminfo_test +	{ +		// Instance to be tested +		LLItemInfo* mItem; + +		// Constructor and destructor of the test wrapper +		iteminfo_test() +		{ +			LLUUID id; +			mItem = new LLItemInfo(X_WORLD_TEST, Y_WORLD_TEST, ITEM_NAME_TEST, id); +		} +		~iteminfo_test() +		{ +			delete mItem; +		} +	}; + +	struct siminfo_test +	{ +		// Instance to be tested +		LLSimInfo* mSim; + +		// Constructor and destructor of the test wrapper +		siminfo_test() +		{ +			U64 handle = to_region_handle_global(X_WORLD_TEST, Y_WORLD_TEST); +			mSim = new LLSimInfo(handle); +		} +		~siminfo_test() +		{ +			delete mSim; +		} +	}; + +	struct worldmap_test +	{ +		// Instance to be tested +		LLWorldMap* mWorld; + +		// Constructor and destructor of the test wrapper +		worldmap_test() +		{ +			mWorld = LLWorldMap::getInstance(); +		} +		~worldmap_test() +		{ +			mWorld = NULL; +		} +	}; + +	// Tut templating thingamagic: test group, object and test instance +	typedef test_group<iteminfo_test> iteminfo_t; +	typedef iteminfo_t::object iteminfo_object_t; +	tut::iteminfo_t tut_iteminfo("LLItemInfo"); + +	typedef test_group<siminfo_test> siminfo_t; +	typedef siminfo_t::object siminfo_object_t; +	tut::siminfo_t tut_siminfo("LLSimInfo"); + +	typedef test_group<worldmap_test> worldmap_t; +	typedef worldmap_t::object worldmap_object_t; +	tut::worldmap_t tut_worldmap("LLWorldMap"); + +	// --------------------------------------------------------------------------------------- +	// Test functions +	// Notes: +	// * Test as many as you possibly can without requiring a full blown simulation of everything +	// * The tests are executed in sequence so the test instance state may change between calls +	// * Remember that you cannot test private methods with tut +	// --------------------------------------------------------------------------------------- + +	// --------------------------------------------------------------------------------------- +	// Test the LLItemInfo interface +	// --------------------------------------------------------------------------------------- +	template<> template<> +	void iteminfo_object_t::test<1>() +	{ +		// Test 1 : setCount() / getCount() +		mItem->setCount(10); +		ensure("LLItemInfo::setCount() test failed", mItem->getCount() == 10); +		// Test 2 : setTooltip() / getToolTip() +		std::string tooltip = TOOLTIP_TEST; +		mItem->setTooltip(tooltip); +		ensure("LLItemInfo::setTooltip() test failed", mItem->getToolTip() == TOOLTIP_TEST); +		// Test 3 : setElevation() / getGlobalPosition() +		mItem->setElevation(Z_WORLD_TEST); +		LLVector3d pos = mItem->getGlobalPosition(); +		LLVector3d ref(X_WORLD_TEST, Y_WORLD_TEST, Z_WORLD_TEST); +		ensure("LLItemInfo::getGlobalPosition() test failed", pos == ref); +		// Test 4 : getName() +		std::string name = mItem->getName(); +		ensure("LLItemInfo::getName() test failed", name == ITEM_NAME_TEST); +		// Test 5 : isName() +		ensure("LLItemInfo::isName() test failed", mItem->isName(name)); +		// Test 6 : getUUID() +		LLUUID id; +		ensure("LLItemInfo::getUUID() test failed", mItem->getUUID() == id); +		// Test 7 : getRegionHandle() +		U64 handle = to_region_handle_global(X_WORLD_TEST, Y_WORLD_TEST); +		ensure("LLItemInfo::getRegionHandle() test failed", mItem->getRegionHandle() == handle); +	} +	// --------------------------------------------------------------------------------------- +	// Test the LLSimInfo interface +	// --------------------------------------------------------------------------------------- +	// Test Setters and Accessors methods +	template<> template<> +	void siminfo_object_t::test<1>() +	{ +		// Test 1 : setName() / getName() +		std::string name = SIM_NAME_TEST; +		mSim->setName(name); +		ensure("LLSimInfo::setName() test failed", mSim->getName() == SIM_NAME_TEST); +		// Test 2 : isName() +		ensure("LLSimInfo::isName() test failed", mSim->isName(name)); +		// Test 3 : getGlobalPos() +		LLVector3 local; +		LLVector3d ref(X_WORLD_TEST, Y_WORLD_TEST, 0.0f); +		LLVector3d pos = mSim->getGlobalPos(local); +		ensure("LLSimInfo::getGlobalPos() test failed", pos == ref); +		// Test 4 : getGlobalOrigin() +		pos = mSim->getGlobalOrigin(); +		ensure("LLSimInfo::getGlobalOrigin() test failed", pos == ref); +		// Test 5 : clearImage() +		try { +			mSim->clearImage(); +		} catch (...) { +			fail("LLSimInfo::clearImage() test failed"); +		} +		// Test 6 : dropImagePriority() +		try { +			mSim->dropImagePriority(); +		} catch (...) { +			fail("LLSimInfo::dropImagePriority() test failed"); +		} +		// Test 7 : updateAgentCount() +		try { +			mSim->updateAgentCount(0.0f); +		} catch (...) { +			fail("LLSimInfo::updateAgentCount() test failed"); +		} +		// Test 8 : getAgentCount() +		S32 agents = mSim->getAgentCount(); +		ensure("LLSimInfo::getAgentCount() test failed", agents == 0); +		// Test 9 : setLandForSaleImage() / getLandForSaleImage() +		LLUUID id; +		mSim->setLandForSaleImage(id); +		LLPointer<LLViewerImage> image = mSim->getLandForSaleImage(); +		ensure("LLSimInfo::getLandForSaleImage() test failed", image.isNull()); +		// Test 10 : isPG() +		mSim->setAccess(SIM_ACCESS_PG); +		ensure("LLSimInfo::isPG() test failed", mSim->isPG()); +		// Test 11 : isDown() +		mSim->setAccess(SIM_ACCESS_DOWN); +		ensure("LLSimInfo::isDown() test failed", mSim->isDown()); +		// Test 12 : Access strings can't be accessed from unit test... +		//ensure("LLSimInfo::getAccessString() test failed", mSim->getAccessString() == "Offline"); +		// Test 13 : Region strings can't be accessed from unit test... +		//mSim->setRegionFlags(REGION_FLAGS_SANDBOX); +		//ensure("LLSimInfo::setRegionFlags() test failed", mSim->getFlagsString() == "Sandbox"); +	} +	// Test management of LLInfoItem lists +	template<> template<> +	void siminfo_object_t::test<2>() +	{ +		// Test 14 : clearItems() +		try { +			mSim->clearItems(); +		} catch (...) { +			fail("LLSimInfo::clearItems() at init test failed"); +		} + +		// Test 15 : Verify that all the lists are empty +		LLSimInfo::item_info_list_t list; +		list = mSim->getTeleHub(); +		ensure("LLSimInfo::getTeleHub() empty at init test failed", list.empty()); +		list = mSim->getInfoHub(); +		ensure("LLSimInfo::getInfoHub() empty at init test failed", list.empty()); +		list = mSim->getPGEvent(); +		ensure("LLSimInfo::getPGEvent() empty at init test failed", list.empty()); +		list = mSim->getMatureEvent(); +		ensure("LLSimInfo::getMatureEvent() empty at init test failed", list.empty()); +		list = mSim->getLandForSale(); +		ensure("LLSimInfo::getLandForSale() empty at init test failed", list.empty()); +		list = mSim->getAgentLocation(); +		ensure("LLSimInfo::getAgentLocation() empty at init test failed", list.empty()); + +		// Create an item to be inserted +		LLUUID id; +		LLItemInfo item(X_WORLD_TEST, Y_WORLD_TEST, ITEM_NAME_TEST, id); + +		// Insert the item in each list +		mSim->insertTeleHub(item); +		mSim->insertInfoHub(item); +		mSim->insertPGEvent(item); +		mSim->insertMatureEvent(item); +		mSim->insertLandForSale(item); +		mSim->insertAgentLocation(item); + +		// Test 16 : Verify that the lists contain 1 item each +		list = mSim->getTeleHub(); +		ensure("LLSimInfo::insertTeleHub() test failed", list.size() == 1); +		list = mSim->getInfoHub(); +		ensure("LLSimInfo::insertInfoHub() test failed", list.size() == 1); +		list = mSim->getPGEvent(); +		ensure("LLSimInfo::insertPGEvent() test failed", list.size() == 1); +		list = mSim->getMatureEvent(); +		ensure("LLSimInfo::insertMatureEvent() test failed", list.size() == 1); +		list = mSim->getLandForSale(); +		ensure("LLSimInfo::insertLandForSale() test failed", list.size() == 1); +		list = mSim->getAgentLocation(); +		ensure("LLSimInfo::insertAgentLocation() test failed", list.size() == 1); + +		// Test 17 : clearItems() +		try { +			mSim->clearItems(); +		} catch (...) { +			fail("LLSimInfo::clearItems() at end test failed"); +		} + +		// Test 18 : Verify that all the lists are empty again... *except* agent which is persisted!! (on purpose) +		list = mSim->getTeleHub(); +		ensure("LLSimInfo::getTeleHub() empty after clear test failed", list.empty()); +		list = mSim->getInfoHub(); +		ensure("LLSimInfo::getInfoHub() empty after clear test failed", list.empty()); +		list = mSim->getPGEvent(); +		ensure("LLSimInfo::getPGEvent() empty after clear test failed", list.empty()); +		list = mSim->getMatureEvent(); +		ensure("LLSimInfo::getMatureEvent() empty after clear test failed", list.empty()); +		list = mSim->getLandForSale(); +		ensure("LLSimInfo::getLandForSale() empty after clear test failed", list.empty()); +		list = mSim->getAgentLocation(); +		ensure("LLSimInfo::getAgentLocation() empty after clear test failed", list.size() == 1); +	} + +	// --------------------------------------------------------------------------------------- +	// Test the LLWorldMap interface +	// --------------------------------------------------------------------------------------- +	// Test Setters and Accessors methods +	template<> template<> +	void worldmap_object_t::test<1>() +	{ +		// Test 1 : reset() +		try { +			mWorld->reset(); +		} catch (...) { +			fail("LLWorldMap::reset() at init test failed"); +		} +		// Test 2 : clearImageRefs() +		try { +			mWorld->clearImageRefs(); +		} catch (...) { +			fail("LLWorldMap::clearImageRefs() test failed"); +		} +		// Test 3 : dropImagePriorities() +		try { +			mWorld->dropImagePriorities(); +		} catch (...) { +			fail("LLWorldMap::dropImagePriorities() test failed"); +		} +		// Test 4 : reloadItems() +		try { +			mWorld->reloadItems(true); +		} catch (...) { +			fail("LLWorldMap::reloadItems() test failed"); +		} +		// Test 5 : updateRegions() +		try { +			mWorld->updateRegions(1000, 1000, 1004, 1004); +		} catch (...) { +			fail("LLWorldMap::updateRegions() test failed"); +		} +		// Test 6 : equalizeBoostLevels() + 		try { + 			mWorld->equalizeBoostLevels(); + 		} catch (...) { + 			fail("LLWorldMap::equalizeBoostLevels() test failed"); + 		} +		// Test 7 : getObjectsTile() +		try { +			LLPointer<LLViewerImage> image = mWorld->getObjectsTile((U32)(X_WORLD_TEST/REGION_WIDTH_METERS), (U32)(Y_WORLD_TEST/REGION_WIDTH_METERS), 1); +			ensure("LLWorldMap::getObjectsTile() failed", image.isNull()); +		} catch (...) { +			fail("LLWorldMap::getObjectsTile() test failed with exception"); +		} +	} +	// Test management of LLSimInfo lists +	template<> template<> +	void worldmap_object_t::test<2>() +	{ +		// Test 8 : reset() +		try { +			mWorld->reset(); +		} catch (...) { +			fail("LLWorldMap::reset() at init test failed"); +		} + +		// Test 9 : Verify that all the region list is empty +		LLWorldMap::sim_info_map_t list; +		list = mWorld->getRegionMap(); +		ensure("LLWorldMap::getRegionMap() empty at init test failed", list.empty()); + +		// Test 10 : Insert a region +		bool success; +		LLUUID id; +		std::string name_sim = SIM_NAME_TEST; +		success = mWorld->insertRegion(	U32(X_WORLD_TEST),  +						U32(Y_WORLD_TEST),  +										name_sim, +										id, +										SIM_ACCESS_PG, +										REGION_FLAGS_SANDBOX); +		list = mWorld->getRegionMap(); +		ensure("LLWorldMap::insertRegion() failed", success && (list.size() == 1)); + +		// Test 11 : Insert an item in the same region -> number of regions doesn't increase +		std::string name_item = ITEM_NAME_TEST; +		success = mWorld->insertItem(	U32(X_WORLD_TEST + REGION_WIDTH_METERS/2), +						U32(Y_WORLD_TEST + REGION_WIDTH_METERS/2),  +										name_item, +										id, +										MAP_ITEM_LAND_FOR_SALE, +										0, 0); +		list = mWorld->getRegionMap(); +		ensure("LLWorldMap::insertItem() in existing region failed", success && (list.size() == 1)); + +		// Test 12 : Insert an item in another region -> number of regions increases +		success = mWorld->insertItem(	U32(X_WORLD_TEST + REGION_WIDTH_METERS*2),  +						U32(Y_WORLD_TEST + REGION_WIDTH_METERS*2),  +										name_item, +										id, +										MAP_ITEM_LAND_FOR_SALE, +										0, 0); +		list = mWorld->getRegionMap(); +		ensure("LLWorldMap::insertItem() in unexisting region failed", success && (list.size() == 2)); + +		// Test 13 : simInfoFromPosGlobal() in region +		LLVector3d pos1(	X_WORLD_TEST + REGION_WIDTH_METERS*2 + REGION_WIDTH_METERS/2,  +							Y_WORLD_TEST + REGION_WIDTH_METERS*2 + REGION_WIDTH_METERS/2,  +							0.0f); +		LLSimInfo* sim; +		sim = mWorld->simInfoFromPosGlobal(pos1); +		ensure("LLWorldMap::simInfoFromPosGlobal() test on existing region failed", sim != NULL); + +		// Test 14 : simInfoFromPosGlobal() outside region +		LLVector3d pos2(	X_WORLD_TEST + REGION_WIDTH_METERS*4 + REGION_WIDTH_METERS/2,  +							Y_WORLD_TEST + REGION_WIDTH_METERS*4 + REGION_WIDTH_METERS/2,  +							0.0f); +		sim = mWorld->simInfoFromPosGlobal(pos2); +		ensure("LLWorldMap::simInfoFromPosGlobal() test outside region failed", sim == NULL); + +		// Test 15 : simInfoFromName() +		sim = mWorld->simInfoFromName(name_sim); +		ensure("LLWorldMap::simInfoFromName() test on existing region failed", sim != NULL); + +		// Test 16 : simInfoFromHandle() +		U64 handle = to_region_handle_global(X_WORLD_TEST, Y_WORLD_TEST); +		sim = mWorld->simInfoFromHandle(handle); +		ensure("LLWorldMap::simInfoFromHandle() test on existing region failed", sim != NULL); + +		// Test 17 : simNameFromPosGlobal() +		LLVector3d pos3(	X_WORLD_TEST + REGION_WIDTH_METERS/2,  +							Y_WORLD_TEST + REGION_WIDTH_METERS/2,  +							0.0f); +		success = mWorld->simNameFromPosGlobal(pos3, name_sim); +		ensure("LLWorldMap::simNameFromPosGlobal() test on existing region failed", success && (name_sim == SIM_NAME_TEST)); +		 +		// Test 18 : reset() +		try { +			mWorld->reset(); +		} catch (...) { +			fail("LLWorldMap::reset() at end test failed"); +		} + +		// Test 19 : Verify that all the region list is empty +		list = mWorld->getRegionMap(); +		ensure("LLWorldMap::getRegionMap() empty at end test failed", list.empty()); +	} +	// Test tracking +	template<> template<> +	void worldmap_object_t::test<3>() +	{ +		// Point to track +		LLVector3d pos( X_WORLD_TEST + REGION_WIDTH_METERS/2, Y_WORLD_TEST + REGION_WIDTH_METERS/2, Z_WORLD_TEST); + +		// Test 20 : no tracking +		mWorld->cancelTracking(); +		ensure("LLWorldMap::cancelTracking() at begin test failed", mWorld->isTracking() == false); + +		// Test 21 : set tracking +		mWorld->setTracking(pos); +		ensure("LLWorldMap::setTracking() failed", mWorld->isTracking() && !mWorld->isTrackingValidLocation()); + +		// Test 22 : set click and commit flags +		mWorld->setTrackingDoubleClick(); +		ensure("LLWorldMap::setTrackingDoubleClick() failed", mWorld->isTrackingDoubleClick()); +		mWorld->setTrackingCommit(); +		ensure("LLWorldMap::setTrackingCommit() failed", mWorld->isTrackingCommit()); + +		// Test 23 : in rectangle test +		bool inRect = mWorld->isTrackingInRectangle(	X_WORLD_TEST, Y_WORLD_TEST,   +														X_WORLD_TEST + REGION_WIDTH_METERS,  +														Y_WORLD_TEST + REGION_WIDTH_METERS); +		ensure("LLWorldMap::isTrackingInRectangle() in rectangle failed", inRect); +		inRect = mWorld->isTrackingInRectangle(			X_WORLD_TEST + REGION_WIDTH_METERS,  +														Y_WORLD_TEST + REGION_WIDTH_METERS,   +														X_WORLD_TEST + 2 * REGION_WIDTH_METERS,  +														Y_WORLD_TEST + 2 * REGION_WIDTH_METERS); +		ensure("LLWorldMap::isTrackingInRectangle() outside rectangle failed", !inRect); + +		// Test 24 : set tracking to valid and invalid +		mWorld->setTrackingValid(); +		ensure("LLWorldMap::setTrackingValid() failed", mWorld->isTrackingValidLocation() && !mWorld->isTrackingInvalidLocation()); +		mWorld->setTrackingInvalid(); +		ensure("LLWorldMap::setTrackingInvalid() failed", !mWorld->isTrackingValidLocation() && mWorld->isTrackingInvalidLocation()); + +		// Test 25 : getTrackedPositionGlobal() +		LLVector3d res = mWorld->getTrackedPositionGlobal(); +		ensure("LLWorldMap::getTrackedPositionGlobal() failed", res == pos); + +		// Test 26 : reset tracking +		mWorld->cancelTracking(); +		ensure("LLWorldMap::cancelTracking() at end test failed", mWorld->isTracking() == false); +	} +} diff --git a/indra/newview/tests/llworldmipmap_test.cpp b/indra/newview/tests/llworldmipmap_test.cpp new file mode 100644 index 0000000000..54887ae219 --- /dev/null +++ b/indra/newview/tests/llworldmipmap_test.cpp @@ -0,0 +1,170 @@ +/**  + * @file llworldmipmap_test.cpp + * @author Merov Linden + * @date 2009-02-03 + * + * $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$ + */ + +// Precompiled header: almost always required for newview cpp files +#include "../llviewerprecompiledheaders.h" +// Class to test +#include "../llworldmipmap.h" +// Dependencies +#include "../llviewerimagelist.h" +// Tut header +#include "../test/lltut.h" + +// ------------------------------------------------------------------------------------------- +// Stubbing: Declarations required to link and run the class being tested +// Notes:  +// * Add here stubbed implementation of the few classes and methods used in the class to be tested +// * Add as little as possible (let the link errors guide you) +// * Do not make any assumption as to how those classes or methods work (i.e. don't copy/paste code) +// * A simulator for a class can be implemented here. Please comment and document thoroughly. + +LLViewerImageList::LLViewerImageList() { } +LLViewerImageList::~LLViewerImageList() { } + +LLViewerImageList gImageList; + +LLViewerImage* LLViewerImageList::getImageFromUrl(const std::string& url, +												   BOOL usemipmaps, +												   BOOL level_immediate, +												   LLGLint internal_format, +												   LLGLenum primary_format,  +												   const LLUUID& force_id) +{ return NULL; } +void LLViewerImage::setBoostLevel(S32 level) { } + +// End Stubbing +// ------------------------------------------------------------------------------------------- + +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- +namespace tut +{ +	// Test wrapper declaration +	struct worldmipmap_test +	{ +		// Derived test class +		class LLTestWorldMipmap : public LLWorldMipmap +		{ +			// Put here stubbs of virtual methods we shouldn't call all the way down +		}; +		// Instance to be tested +		LLTestWorldMipmap* mMap; + +		// Constructor and destructor of the test wrapper +		worldmipmap_test() +		{ +			mMap = new LLTestWorldMipmap; +		} +		~worldmipmap_test() +		{ +			delete mMap; +		} +	}; + +	// Tut templating thingamagic: test group, object and test instance +	typedef test_group<worldmipmap_test> worldmipmap_t; +	typedef worldmipmap_t::object worldmipmap_object_t; +	tut::worldmipmap_t tut_worldmipmap("LLWorldMipmap"); + +	// --------------------------------------------------------------------------------------- +	// Test functions +	// Notes: +	// * Test as many as you possibly can without requiring a full blown simulation of everything +	// * The tests are executed in sequence so the test instance state may change between calls +	// * Remember that you cannot test private methods with tut +	// --------------------------------------------------------------------------------------- +	// Test static methods +	// Test 1 : scaleToLevel() +	template<> template<> +	void worldmipmap_object_t::test<1>() +	{ +		S32 level = mMap->scaleToLevel(0.0); +		ensure("scaleToLevel() test 1 failed", level == LLWorldMipmap::MAP_LEVELS); +		level = mMap->scaleToLevel(LLWorldMipmap::MAP_TILE_SIZE); +		ensure("scaleToLevel() test 2 failed", level == 1); +		level = mMap->scaleToLevel(10 * LLWorldMipmap::MAP_TILE_SIZE); +		ensure("scaleToLevel() test 3 failed", level == 1); +	} +	// Test 2 : globalToMipmap() +	template<> template<> +	void worldmipmap_object_t::test<2>() +	{ +		U32 grid_x, grid_y; +		mMap->globalToMipmap(1000.f*REGION_WIDTH_METERS, 1000.f*REGION_WIDTH_METERS, 1, &grid_x, &grid_y); +		ensure("globalToMipmap() test 1 failed", (grid_x == 1000) && (grid_y == 1000)); +		mMap->globalToMipmap(0.0, 0.0, LLWorldMipmap::MAP_LEVELS, &grid_x, &grid_y); +		ensure("globalToMipmap() test 2 failed", (grid_x == 0) && (grid_y == 0)); +	} +	// Test 3 : getObjectsTile() +	template<> template<> +	void worldmipmap_object_t::test<3>() +	{ +		// Depends on some inline methods in LLViewerImage... Thinking about how to make this work +		// LLPointer<LLViewerImage> img = mMap->getObjectsTile(0, 0, 1); +		// ensure("getObjectsTile() test failed", img.isNull()); +	} +	// Test 4 : equalizeBoostLevels() +	template<> template<> +	void worldmipmap_object_t::test<4>() +	{ +		try +		{ +			mMap->equalizeBoostLevels(); +		}  +		catch (...) +		{ +			fail("equalizeBoostLevels() test failed"); +		} +	} +	// Test 5 : dropBoostLevels() +	template<> template<> +	void worldmipmap_object_t::test<5>() +	{ +		try +		{ +			mMap->dropBoostLevels(); +		}  +		catch (...) +		{ +			fail("dropBoostLevels() test failed"); +		} +	} +	// Test 6 : reset() +	template<> template<> +	void worldmipmap_object_t::test<6>() +	{ +		try +		{ +			mMap->reset(); +		}  +		catch (...) +		{ +			fail("reset() test failed"); +		} +	} +} diff --git a/indra/newview/tests/llxmlrpclistener_test.cpp b/indra/newview/tests/llxmlrpclistener_test.cpp new file mode 100644 index 0000000000..4d5df1043e --- /dev/null +++ b/indra/newview/tests/llxmlrpclistener_test.cpp @@ -0,0 +1,247 @@ +/* + * @file   llxmlrpclistener_test.cpp + * @author Nat Goodspeed + * @date   2009-03-20 + * @brief  Test for llxmlrpclistener. + *  + * $LicenseInfo:firstyear=2009&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$ + */ + +// Precompiled header +#include "../llviewerprecompiledheaders.h" +// associated header +#include "../llxmlrpclistener.h" +// STL headers +#include <iomanip> +// std headers +// external library headers +// other Linden headers +#include "../test/lltut.h" +#include "../llxmlrpctransaction.h" +#include "llevents.h" +#include "lleventfilter.h" +#include "llsd.h" +#include "llcontrol.h" +#include "tests/wrapllerrs.h" + +LLControlGroup gSavedSettings("Global"); + +/***************************************************************************** +*   TUT +*****************************************************************************/ +namespace tut +{ +    struct data +    { +        data(): +            pumps(LLEventPumps::instance()), +            uri("http://127.0.0.1:8000") +        { +            // These variables are required by machinery used by +            // LLXMLRPCTransaction. The values reflect reality for this test +            // executable; hopefully these values are correct. +            gSavedSettings.declareBOOL("BrowserProxyEnabled", FALSE, "", FALSE); // don't persist +            gSavedSettings.declareBOOL("NoVerifySSLCert", TRUE, "", FALSE); // don't persist +        } + +        // LLEventPump listener signature +        bool captureReply(const LLSD& r) +        { +            reply = r; +            return false; +        } + +        LLSD reply; +        LLEventPumps& pumps; +        std::string uri; +    }; +    typedef test_group<data> llxmlrpclistener_group; +    typedef llxmlrpclistener_group::object object; +    llxmlrpclistener_group llxmlrpclistenergrp("llxmlrpclistener"); + +    template<> template<> +    void object::test<1>() +    { +        set_test_name("request validation"); +        WrapLL_ERRS capture; +        LLSD request; +        request["uri"] = uri; +        std::string threw; +        try +        { +            pumps.obtain("LLXMLRPCTransaction").post(request); +        } +        catch (const WrapLL_ERRS::FatalException& e) +        { +            threw = e.what(); +        } +        ensure_contains("threw exception", threw, "missing params"); +        ensure_contains("identified missing", threw, "method"); +        ensure_contains("identified missing", threw, "reply"); +    } + +    template<> template<> +    void object::test<2>() +    { +        set_test_name("param types validation"); +        WrapLL_ERRS capture; +        LLSD request; +        request["uri"] = uri; +        request["method"] = "hello"; +        request["reply"] = "reply"; +        LLSD& params(request["params"]); +        params["who"]["specifically"] = "world"; // LLXMLRPCListener only handles scalar params +        std::string threw; +        try +        { +            pumps.obtain("LLXMLRPCTransaction").post(request); +        } +        catch (const WrapLL_ERRS::FatalException& e) +        { +            threw = e.what(); +        } +        ensure_contains("threw exception", threw, "unknown type"); +    } + +    template<> template<> +    void object::test<3>() +    { +        set_test_name("success case"); +        LLSD request; +        request["uri"] = uri; +        request["method"] = "hello"; +        request["reply"] = "reply"; +        LLSD& params(request["params"]); +        params["who"] = "world"; +        // Set up a timeout filter so we don't spin forever waiting. +        LLEventTimeout watchdog; +        // Connect the timeout filter to the reply pump. +        LLTempBoundListener temp( +            pumps.obtain("reply"). +            listen("watchdog", boost::bind(&LLEventTimeout::post, boost::ref(watchdog), _1))); +        // Now connect our target listener to the timeout filter. +        watchdog.listen("captureReply", boost::bind(&data::captureReply, this, _1)); +        // Kick off the request... +        reply.clear(); +        pumps.obtain("LLXMLRPCTransaction").post(request); +        // Set the timer +        F32 timeout(10); +        watchdog.eventAfter(timeout, LLSD().insert("timeout", 0)); +        // and pump "mainloop" until we get something, whether from +        // LLXMLRPCListener or from the watchdog filter. +        LLTimer timer; +        F32 start = timer.getElapsedTimeF32(); +        LLEventPump& mainloop(pumps.obtain("mainloop")); +        while (reply.isUndefined()) +        { +            mainloop.post(LLSD()); +        } +        ensure("timeout works", (timer.getElapsedTimeF32() - start) < (timeout + 1)); +        ensure_equals(reply["responses"]["hi_there"].asString(), "Hello, world!"); +    } + +    template<> template<> +    void object::test<4>() +    { +        set_test_name("bogus method"); +        LLSD request; +        request["uri"] = uri; +        request["method"] = "goodbye"; +        request["reply"] = "reply"; +        LLSD& params(request["params"]); +        params["who"] = "world"; +        // Set up a timeout filter so we don't spin forever waiting. +        LLEventTimeout watchdog; +        // Connect the timeout filter to the reply pump. +        LLTempBoundListener temp( +            pumps.obtain("reply"). +            listen("watchdog", boost::bind(&LLEventTimeout::post, boost::ref(watchdog), _1))); +        // Now connect our target listener to the timeout filter. +        watchdog.listen("captureReply", boost::bind(&data::captureReply, this, _1)); +        // Kick off the request... +        reply.clear(); +        pumps.obtain("LLXMLRPCTransaction").post(request); +        // Set the timer +        F32 timeout(10); +        watchdog.eventAfter(timeout, LLSD().insert("timeout", 0)); +        // and pump "mainloop" until we get something, whether from +        // LLXMLRPCListener or from the watchdog filter. +        LLTimer timer; +        F32 start = timer.getElapsedTimeF32(); +        LLEventPump& mainloop(pumps.obtain("mainloop")); +        while (reply.isUndefined()) +        { +            mainloop.post(LLSD()); +        } +        ensure("timeout works", (timer.getElapsedTimeF32() - start) < (timeout + 1)); +        ensure_equals("XMLRPC error", reply["status"].asString(), "XMLRPCError"); +    } + +    template<> template<> +    void object::test<5>() +    { +        set_test_name("bad type"); +        LLSD request; +        request["uri"] = uri; +        request["method"] = "getdict"; +        request["reply"] = "reply"; +        (void)request["params"]; +        // Set up a timeout filter so we don't spin forever waiting. +        LLEventTimeout watchdog; +        // Connect the timeout filter to the reply pump. +        LLTempBoundListener temp( +            pumps.obtain("reply"). +            listen("watchdog", boost::bind(&LLEventTimeout::post, boost::ref(watchdog), _1))); +        // Now connect our target listener to the timeout filter. +        watchdog.listen("captureReply", boost::bind(&data::captureReply, this, _1)); +        // Kick off the request... +        reply.clear(); +        pumps.obtain("LLXMLRPCTransaction").post(request); +        // Set the timer +        F32 timeout(10); +        watchdog.eventAfter(timeout, LLSD().insert("timeout", 0)); +        // and pump "mainloop" until we get something, whether from +        // LLXMLRPCListener or from the watchdog filter. +        LLTimer timer; +        F32 start = timer.getElapsedTimeF32(); +        LLEventPump& mainloop(pumps.obtain("mainloop")); +        while (reply.isUndefined()) +        { +            mainloop.post(LLSD()); +        } +        ensure("timeout works", (timer.getElapsedTimeF32() - start) < (timeout + 1)); +        ensure_equals(reply["status"].asString(), "BadType"); +        ensure_contains("bad type", reply["responses"]["nested_dict"].asString(), "bad XMLRPC type"); +    } +} // namespace tut + +/***************************************************************************** +*   Resolve link errors: use real machinery here, since we intend to exchange +*   actual XML with a peer process. +*****************************************************************************/ +// Including llxmlrpctransaction.cpp drags in the static LLXMLRPCListener +// instantiated there. That's why it works to post requests to the LLEventPump +// named "LLXMLRPCTransaction". +#include "../llxmlrpctransaction.cpp" +#include "llcontrol.cpp" +#include "llxmltree.cpp" +#include "llxmlparser.cpp" diff --git a/indra/newview/tests/test_llxmlrpc_peer.py b/indra/newview/tests/test_llxmlrpc_peer.py new file mode 100644 index 0000000000..aeebb0cfd1 --- /dev/null +++ b/indra/newview/tests/test_llxmlrpc_peer.py @@ -0,0 +1,76 @@ +#!/usr/bin/python +"""\ +@file   test_llxmlrpc_peer.py +@author Nat Goodspeed +@date   2008-10-09 +@brief  This script asynchronously runs the executable (with args) specified on +        the command line, returning its result code. While that executable is +        running, we provide dummy local services for use by C++ tests. + +$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$ +""" + +import os +import sys +from threading import Thread +from SimpleXMLRPCServer import SimpleXMLRPCServer + +mydir = os.path.dirname(__file__)       # expected to be .../indra/newview/tests/ +sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python")) +sys.path.insert(1, os.path.join(mydir, os.pardir, os.pardir, "llmessage", "tests")) +from testrunner import run, debug + +class TestServer(SimpleXMLRPCServer): +    def _dispatch(self, method, params): +        try: +            func = getattr(self, method) +        except AttributeError: +            raise Exception('method "%s" is not supported' % method) +        else: +            # LLXMLRPCListener constructs XMLRPC parameters that arrive as a +            # 1-tuple containing a dict. +            return func(**(params[0])) + +    def hello(self, who): +        # LLXMLRPCListener expects a dict return. +        return {"hi_there": "Hello, %s!" % who} + +    def getdict(self): +        return dict(nested_dict=dict(a=17, b=5)) + +    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 + +class ServerRunner(Thread): +    def run(self): +        server = TestServer(('127.0.0.1', 8000)) +        debug("Starting XMLRPC server...\n") +        server.serve_forever() + +if __name__ == "__main__": +    sys.exit(run(server=ServerRunner(name="xmlrpc"), *sys.argv[1:]))  | 
