summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorMark Palange (Mani) <palange@lindenlab.com>2009-07-24 15:08:16 -0700
committerMark Palange (Mani) <palange@lindenlab.com>2009-07-24 15:08:16 -0700
commit9538328d5f7cf0f0be5dd77b8e27032e09104fff (patch)
tree7592050ae6c8854284f5961558249985e3abec82 /indra
parentdb7f15df68cda2850c3d8a7ffcc59fc136de6f95 (diff)
Adding LLLoginInstance unit test.
- Added LLNotificationsInterface class. - Removed LLLoginInstance use of LLNotifications EventAPI
Diffstat (limited to 'indra')
-rw-r--r--indra/llui/llnotifications.h13
-rw-r--r--indra/llui/llnotificationslistener.cpp8
-rw-r--r--indra/llui/llnotificationslistener.h2
-rw-r--r--indra/newview/lllogininstance.cpp15
-rw-r--r--indra/newview/lllogininstance.h7
-rw-r--r--indra/newview/llstartup.cpp3
-rw-r--r--indra/newview/tests/lllogininstance_test.cpp413
7 files changed, 447 insertions, 14 deletions
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index 93cdcbeefd..c534267fca 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -799,8 +799,19 @@ private:
LLNotificationComparator mComparator;
};
+// An interface class to provide a clean linker seam to the LLNotifications class.
+// Extend this interface as needed for your use of LLNotifications.
+class LLNotificationsInterface
+{
+public:
+ virtual LLNotificationPtr add(const std::string& name,
+ const LLSD& substitutions,
+ const LLSD& payload,
+ LLNotificationFunctorRegistry::ResponseFunctor functor) = 0;
+};
class LLNotifications :
+ public LLNotificationsInterface,
public LLSingleton<LLNotifications>,
public LLNotificationChannelBase
{
@@ -824,7 +835,7 @@ public:
const LLSD& substitutions,
const LLSD& payload,
const std::string& functor_name);
- LLNotificationPtr add(const std::string& name,
+ /* virtual */ LLNotificationPtr add(const std::string& name,
const LLSD& substitutions,
const LLSD& payload,
LLNotificationFunctorRegistry::ResponseFunctor functor);
diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp
index 6ebbee68ac..75f4d6177d 100644
--- a/indra/llui/llnotificationslistener.cpp
+++ b/indra/llui/llnotificationslistener.cpp
@@ -29,7 +29,7 @@ void LLNotificationsListener::requestAdd(const LLSD& event_data) const
mNotifications.add(event_data["name"],
event_data["substitutions"],
event_data["payload"],
- boost::bind(&LLNotificationListener::Responder,
+ boost::bind(&LLNotificationsListener::NotificationResponder,
this,
event_data["reply"].asString(),
_1, _2
@@ -44,12 +44,12 @@ void LLNotificationsListener::requestAdd(const LLSD& event_data) const
}
}
-void LLNotificationsListener::Responder(const std::string& reply_pump,
+void LLNotificationsListener::NotificationResponder(const std::string& reply_pump,
const LLSD& notification,
- const LLSD& response)
+ const LLSD& response) const
{
LLSD reponse_event;
reponse_event["notification"] = notification;
reponse_event["response"] = response;
- mEventPumps.obtain(reply_pump).post(reponse_event);
+ LLEventPumps::getInstance()->obtain(reply_pump).post(reponse_event);
}
diff --git a/indra/llui/llnotificationslistener.h b/indra/llui/llnotificationslistener.h
index d11aed1b52..6f71a7c781 100644
--- a/indra/llui/llnotificationslistener.h
+++ b/indra/llui/llnotificationslistener.h
@@ -27,7 +27,7 @@ public:
private:
void NotificationResponder(const std::string& replypump,
const LLSD& notification,
- const LLSD& response);
+ const LLSD& response) const;
LLNotifications & mNotifications;
};
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
index bf42129fc1..c08cc2baae 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -59,6 +59,7 @@ std::string construct_start_string();
LLLoginInstance::LLLoginInstance() :
mLoginModule(new LLLogin()),
+ mNotifications(NULL),
mLoginState("offline"),
mUserInteraction(true),
mSkipOptionalUpdate(false),
@@ -345,10 +346,13 @@ void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg)
#endif
}
- // *NOTE:Mani - for reference
-// LLNotifications::instance().add(notification_name, args, payload,
-// boost::bind(&LLLoginInstance::updateDialogCallback, this, _1, _2));
+ if(mNotifications)
+ {
+ mNotifications->add(notification_name, args, payload,
+ boost::bind(&LLLoginInstance::updateDialogCallback, this, _1, _2));
+ }
+ /* *NOTE:Mani Experiment with Event API interface.
if(!mUpdateAppResponse)
{
bool make_unique = true;
@@ -368,12 +372,11 @@ void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg)
event["reply"] = mUpdateAppResponse->getName();
LLEventPumps::getInstance()->obtain("LLNotifications").post(event);
+ */
}
-bool LLLoginInstance::updateDialogCallback(const LLSD& event)
+bool LLLoginInstance::updateDialogCallback(const LLSD& notification, const LLSD& response)
{
- LLSD notification = event["notification"];
- LLSD response = event["response"];
S32 option = LLNotification::getSelectedOption(notification, response);
std::string update_exe_path;
bool mandatory = notification["payload"]["mandatory"].asBoolean();
diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h
index afe96acd1e..47d52a6184 100644
--- a/indra/newview/lllogininstance.h
+++ b/indra/newview/lllogininstance.h
@@ -37,6 +37,7 @@
#include <boost/function.hpp>
class LLLogin;
class LLEventStream;
+class LLNotificationsInterface;
// This class hosts the login module and is used to
// negotiate user authentication attempts.
@@ -73,13 +74,15 @@ public:
void setSerialNumber(const std::string& sn) { mSerialNumber = sn; }
void setLastExecEvent(int lee) { mLastExecEvent = lee; }
+ void setNotificationsInterface(LLNotificationsInterface* ni) { mNotifications = ni; }
+
typedef boost::function<void()> UpdaterLauncherCallback;
void setUpdaterLauncher(const UpdaterLauncherCallback& ulc) { mUpdaterLauncher = ulc; }
private:
void constructAuthParams(const LLSD& credentials);
void updateApp(bool mandatory, const std::string& message);
- bool updateDialogCallback(const LLSD& event);
+ bool updateDialogCallback(const LLSD& notification, const LLSD& response);
bool handleLoginEvent(const LLSD& event);
bool handleLoginFailure(const LLSD& event);
@@ -90,6 +93,8 @@ private:
void attemptComplete() { mAttemptComplete = true; } // In the future an event?
boost::scoped_ptr<LLLogin> mLoginModule;
+ LLNotificationsInterface* mNotifications;
+
std::string mLoginState;
LLSD mRequestData;
LLSD mResponseData;
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index dac6f8423a..eb585f8fe3 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -966,6 +966,7 @@ bool idle_startup()
// Setting initial values...
LLLoginInstance* login = LLLoginInstance::getInstance();
+ login->setNotificationsInterface(LLNotifications::getInstance());
if(gNoRender)
{
// HACK, skip optional updates if you're running drones
@@ -975,7 +976,7 @@ bool idle_startup()
login->setUserInteraction(show_connect_box);
login->setSerialNumber(LLAppViewer::instance()->getSerialNumber());
login->setLastExecEvent(gLastExecEvent);
- login->setUpdaterLauncher(boost::bind(LLAppViewer::launchUpdater, LLAppViewer::instance()));
+ login->setUpdaterLauncher(boost::bind(&LLAppViewer::launchUpdater, LLAppViewer::instance()));
// This call to LLLoginInstance::connect() starts the
// authentication process.
diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp
new file mode 100644
index 0000000000..19cf9cd961
--- /dev/null
+++ b/indra/newview/tests/lllogininstance_test.cpp
@@ -0,0 +1,413 @@
+/**
+ * @file lllogininstance_test.cpp
+ * @brief Test for lllogininstance.cpp.
+ *
+ * $LicenseInfo:firstyear=2008&license=internal$
+ * Copyright (c) 2008, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "../llviewerprecompiledheaders.h"
+// Own header
+#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 "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;
+}
+
+//-----------------------------------------------------------------------------
+#include "../llviewernetwork.h"
+unsigned char gMACAddress[MAC_ADDRESS_BYTES] = {'1','2','3','4','5','6'}; /* Flawfinder: ignore */
+
+LLViewerLogin::LLViewerLogin() {}
+LLViewerLogin::~LLViewerLogin() {}
+void LLViewerLogin::getLoginURIs(std::vector<std::string>& uris) const
+{
+ uris.push_back(VIEWERLOGIN_URI);
+}
+std::string LLViewerLogin::getGridLabel() const { return VIEWERLOGIN_GRIDLABEL; }
+
+//-----------------------------------------------------------------------------
+#include "../llviewercontrol.h"
+LLControlGroup gSavedSettings("Global");
+LLControlGroup gSavedSkinSettings("Skinning");
+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; }
+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 "../llurlsimstring.h"
+LLURLSimString LLURLSimString::sInstance;
+bool LLURLSimString::parse() { return true; }
+
+//-----------------------------------------------------------------------------
+#include "../llfloatertos.h"
+static LLFloaterTOS::ETOSType gTOSType;
+static LLFloaterTOS::YesNoCallback gTOSCallback;
+LLFloaterTOS* LLFloaterTOS::show(LLFloaterTOS::ETOSType type,
+ const std::string & message,
+ const YesNoCallback& callback)
+{
+ gTOSType = type;
+ gTOSCallback = callback;
+ 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();
+}
+
+// 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 = -1; // Set to invalid value.
+ gTOSCallback = 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);
+
+ credentials["first"] = "testfirst";
+ credentials["last"] = "testlast";
+ credentials["passwd"] = "testpass";
+
+ logininstance->setNotificationsInterface(&notifications);
+ }
+
+ LLLoginInstance* logininstance;
+ LLSD credentials;
+ 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(credentials);
+
+ ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);
+
+ // Dummy success response.
+ LLSD response;
+ response["state"] = "online";
+ 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["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, credentials);
+
+ // 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["progress"] = 0.0;
+ response["transfer_rate"] = 7;
+ response["data"]["reason"] = "tos";
+ gTestPump.post(response);
+
+ ensure_equals("TOS Dialog type", gTOSType, LLFloaterTOS::TOS_TOS);
+ ensure("TOS callback given", gTOSCallback != 0);
+ gTOSCallback(false); // Call callback denying TOS.
+ ensure("No TOS, failed auth", logininstance->authFailure());
+
+ // Start again.
+ logininstance->connect(test_uri, credentials);
+ gTestPump.post(response); // Fail for tos again.
+ gTOSCallback(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, credentials);
+ ensure_equals("Reset to default for agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), false);
+
+ // Critical Message failure response.
+ logininstance->connect(test_uri, credentials);
+ response["data"]["reason"] = "critical"; // Change response to "critical message"
+ gTestPump.post(response);
+
+ ensure_equals("TOS Dialog type", gTOSType, LLFloaterTOS::TOS_CRITICAL_MESSAGE);
+ ensure("TOS callback given", gTOSCallback != 0);
+ gTOSCallback(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, credentials);
+ 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(credentials);
+
+ ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);
+
+ // Update needed failure response.
+ LLSD response;
+ response["state"] = "offline";
+ 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(credentials);
+
+ ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);
+
+ // Update needed failure response.
+ LLSD response;
+ response["state"] = "offline";
+ 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(credentials);
+
+ ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);
+
+ // Update needed failure response.
+ LLSD response;
+ response["state"] = "offline";
+ 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(credentials);
+
+ ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);
+
+ // Update needed failure response.
+ LLSD response;
+ response["state"] = "offline";
+ 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);
+ }
+}