-
¡Cinder! ㊝ authored¡Cinder! ㊝ authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
lllogininstance_test.cpp 18.42 KiB
/**
* @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
#pragma warning(disable: 4702) // disable 'unreachable code' so we can safely use skip().
#endif
// Constants
const std::string VIEWERLOGIN_URI("viewerlogin_uri");
const std::string VIEWERLOGIN_GRIDLABEL("viewerlogin_grid");
const std::string APPVIEWER_SERIALNUMBER("appviewer_serialno");
const std::string VIEWERLOGIN_CHANNEL("invalid_channel");
const std::string VIEWERLOGIN_VERSION("invalid_version");
// Link seams.
//-----------------------------------------------------------------------------
static LLEventStream gTestPump("test_pump");
#include "../llslurl.h"
#include "../llstartup.h"
LLSLURL LLStartUp::sStartSLURL;
LLSLURL& LLStartUp::getStartSLURL() { return sStartSLURL; }
#include "lllogin.h"
static std::string gLoginURI;
static LLSD gLoginCreds;
static bool gDisconnectCalled = false;
#include "../llviewerwindow.h"
void LLViewerWindow::setShowProgress(BOOL show) {}
LLProgressView * LLViewerWindow::getProgressView(void) const { return 0; }
LLViewerWindow* gViewerWindow;
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()
{
}
bool LLGridManager::addGrid(LLSD& grid_data)
{
return true;
}
LLGridManager::LLGridManager()
:
mPlatform(NOPLATFORM)
{
}
void LLGridManager::getLoginURIs(std::vector<std::string>& uris) const
{
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& password_url,
const std::string& register_url,
const std::string& update_url_base,
const std::string& administrator,
const std::string& platform,
const std::string& login_id)
{
}
std::map<std::string, std::string> LLGridManager::getKnownGrids() const
{
std::map<std::string, std::string> result;
return result;
}
void LLGridManager::setGridChoice(const std::string& grid_name)
{
}
bool LLGridManager::isInSecondlife() const
{
return false;
}
bool LLGridManager::isInOpenSim() const
{
return false;
}
std::string LLGridManager::getSLURLBase(const std::string& grid_name) const
{
return "myslurl";
}
std::string LLGridManager::getAppSLURLBase(const std::string& grid_name) const
{
return "myappslurl";
}
//-----------------------------------------------------------------------------
#include "../llviewercontrol.h"
LLControlGroup gSavedSettings("Global");
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"; }
LLControlVariable* LLControlGroup::declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, LLControlVariable::ePersist persist) { return NULL; }
LLControlVariable* LLControlGroup::declareString(const std::string& name, const std::string &initial_val, const std::string& comment, LLControlVariable::ePersist persist) { return NULL; }
#include "lluicolortable.h"
void LLUIColorTable::saveUserSettings(void)const {}
//-----------------------------------------------------------------------------
#include "../llversioninfo.h"
const std::string &LLVersionInfo::getVersion() { return VIEWERLOGIN_VERSION; }
const std::string &LLVersionInfo::getChannel() { return VIEWERLOGIN_CHANNEL; }
//-----------------------------------------------------------------------------
#include "../llappviewer.h"
void LLAppViewer::forceQuit(void) {}
LLAppViewer * LLAppViewer::sInstance = 0;
//-----------------------------------------------------------------------------
#include "llupdaterservice.h"
std::string const & LLUpdaterService::pumpName(void)
{
static std::string wakka = "wakka wakka wakka";
return wakka;
}
bool LLUpdaterService::updateReadyToInstall(void) { return false; }
void LLUpdaterService::initialize(const std::string& channel,
const std::string& version,
const std::string& platform,
const std::string& platform_version,
const unsigned char uniqueid[MD5HEX_STR_SIZE],
const bool& willing_to_test
) {}
void LLUpdaterService::setCheckPeriod(unsigned int seconds) {}
void LLUpdaterService::startChecking(bool install_if_ready) {}
void LLUpdaterService::stopChecking() {}
bool LLUpdaterService::isChecking() { return false; }
LLUpdaterService::eUpdaterState LLUpdaterService::getState() { return INITIAL; }
std::string LLUpdaterService::updatedVersion() { return ""; }
bool llHashedUniqueID(unsigned char* id)
{
memcpy( id, "66666666666666666666666666666666", MD5HEX_STR_SIZE );
return true;
}
//-----------------------------------------------------------------------------
#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;
}
//----------------------------------------------------------------------------
#include "../llprogressview.h"
void LLProgressView::setText(std::string const &){}
void LLProgressView::setPercent(float){}
void LLProgressView::setMessage(std::string const &){}
//-----------------------------------------------------------------------------
// 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, "", LLControlVariable::PERSIST_NO);
gSavedSettings.declareBOOL("ConnectAsGod", FALSE, "", LLControlVariable::PERSIST_NO);
gSavedSettings.declareBOOL("UseDebugMenus", FALSE, "", LLControlVariable::PERSIST_NO);
gSavedSettings.declareBOOL("ForceMandatoryUpdate", FALSE, "", LLControlVariable::PERSIST_NO);
gSavedSettings.declareString("ClientSettingsFile", "test_settings.xml", "", LLControlVariable::PERSIST_NO);
gSavedSettings.declareString("NextLoginLocation", "", "", LLControlVariable::PERSIST_NO);
gSavedSettings.declareBOOL("LoginLastLocation", FALSE, "", LLControlVariable::PERSIST_NO);
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);
logininstance->setPlatformInfo("win", "1.3.5");
}
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);
}
}