From fe71dd340ab396b93bde45df438041af5d85fd47 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Mon, 1 Feb 2010 15:10:19 -0800 Subject: Merge giab-viewer-trunk 2497, general merge of more secapi stuff as well as certificate handling stuff. Grid manager as well --- indra/newview/tests/lllogininstance_test.cpp | 107 +++++- indra/newview/tests/llsechandler_basic_test.cpp | 456 ++++++++++++++++++++++++ indra/newview/tests/llviewernetwork_test.cpp | 446 +++++++++++++++++++++++ 3 files changed, 990 insertions(+), 19 deletions(-) create mode 100644 indra/newview/tests/llsechandler_basic_test.cpp create mode 100644 indra/newview/tests/llviewernetwork_test.cpp (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index 7b28a3b72c..9222882f5f 100644 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -10,7 +10,10 @@ // Precompiled header #include "../llviewerprecompiledheaders.h" // Own header +#include "../llsecapi.h" +#include "../llviewernetwork.h" #include "../lllogininstance.h" + // STL headers // std headers // external library headers @@ -54,17 +57,69 @@ 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; +} + //----------------------------------------------------------------------------- #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& uris) const +LLGridManager::~LLGridManager() +{ +} + +void LLGridManager::addGrid(LLSD& grid_data) +{ +} +LLGridManager::LLGridManager() +{ +} + +void LLGridManager::getLoginURIs(std::vector& uris) { uris.push_back(VIEWERLOGIN_URI); } -std::string LLViewerLogin::getGridLabel() const { return VIEWERLOGIN_GRIDLABEL; } + +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 LLGridManager::getKnownGrids(bool favorite_only) +{ + std::map 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" @@ -197,15 +252,29 @@ namespace tut gSavedSettings.declareString("NextLoginLocation", "", "", FALSE); gSavedSettings.declareBOOL("LoginLastLocation", FALSE, "", FALSE); - credentials["first"] = "testfirst"; - credentials["last"] = "testlast"; - credentials["passwd"] = "testpass"; + 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; - LLSD credentials; + LLPointer agentCredential; + LLPointer accountCredential; MockNotifications notifications; }; @@ -219,7 +288,7 @@ namespace tut set_test_name("Test Simple Success And Disconnect"); // Test default connect. - logininstance->connect(credentials); + logininstance->connect(agentCredential); ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); @@ -260,7 +329,7 @@ namespace tut const std::string test_uri = "testing-uri"; // Test default connect. - logininstance->connect(test_uri, credentials); + logininstance->connect(test_uri, agentCredential); // connect should call LLLogin::connect to init gLoginURI and gLoginCreds. ensure_equals("Default connect uri", gLoginURI, "testing-uri"); @@ -282,7 +351,7 @@ namespace tut ensure("No TOS, failed auth", logininstance->authFailure()); // Start again. - logininstance->connect(test_uri, credentials); + 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); @@ -294,11 +363,11 @@ namespace tut gTestPump.post(response); ensure("TOS auth failure", logininstance->authFailure()); - logininstance->connect(test_uri, credentials); + 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, credentials); + logininstance->connect(test_uri, agentCredential); response["data"]["reason"] = "critical"; // Change response to "critical message" gTestPump.post(response); @@ -312,7 +381,7 @@ namespace tut response["data"]["reason"] = "key"; // bad creds. gTestPump.post(response); ensure("TOS auth failure", logininstance->authFailure()); - logininstance->connect(test_uri, credentials); + logininstance->connect(test_uri, agentCredential); ensure_equals("Default for agree to tos", gLoginCreds["params"]["read_critical"].asBoolean(), false); } @@ -323,7 +392,7 @@ namespace tut // Part 1 - Mandatory Update, with User accepts response. // Test connect with update needed. - logininstance->connect(credentials); + logininstance->connect(agentCredential); ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); @@ -349,7 +418,7 @@ namespace tut set_test_name("Test Mandatory Update User Decline"); // Test connect with update needed. - logininstance->connect(credentials); + logininstance->connect(agentCredential); ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); @@ -375,7 +444,7 @@ namespace tut // Part 3 - Mandatory Update, with bogus response. // Test connect with update needed. - logininstance->connect(credentials); + logininstance->connect(agentCredential); ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); @@ -401,7 +470,7 @@ namespace tut // Part 3 - Mandatory Update, with bogus response. // Test connect with update needed. - logininstance->connect(credentials); + logininstance->connect(agentCredential); ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp new file mode 100644 index 0000000000..a5554d55a5 --- /dev/null +++ b/indra/newview/tests/llsechandler_basic_test.cpp @@ -0,0 +1,456 @@ +/** + * @file llsechandler_basic_test.cpp + * @author Roxie + * @date 2009-02-10 + * @brief Test the 'basic' sec handler functions + * + * $LicenseInfo:firstyear=2005&license=viewergpl$ + * + * Copyright (c) 2005-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "../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 +#include +#include +#include +#include "llxorcipher.h" + +LLControlGroup gSavedSettings; +unsigned char gMACAddress[MAC_ADDRESS_BYTES] = {77,21,46,31,89,2}; + +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- +namespace tut +{ + // Test wrapper declaration : wrapping nothing for the moment + struct sechandler_basic_test + { + std::string mPemTestCert; + std::string mDerFormat; + X509 *mX509TestCert; + LLBasicCertificate* mTestCert; + + sechandler_basic_test() + { + 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" +""; + 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"; + + mTestCert = new LLBasicCertificate(mPemTestCert); + + gSavedSettings.cleanup(); + gSavedSettings.declareString("FirstName", "", "", FALSE); + gSavedSettings.declareString("LastName", "", "", FALSE); + mX509TestCert = 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); + + } + ~sechandler_basic_test() + { + LLFile::remove("test_password.dat"); + LLFile::remove("sechandler_settings.tmp"); + delete mTestCert; + X509_free(mX509TestCert); + } + }; + + // Tut templating thingamagic: test group, object and test instance + typedef test_group sechandler_basic_test_factory; + typedef sechandler_basic_test_factory::object sechandler_basic_test_object; + tut::sechandler_basic_test_factory tut_test("llsechandler_basic"); + + // --------------------------------------------------------------------------------------- + // Test functions + // --------------------------------------------------------------------------------------- + // test cert data retrieval + template<> template<> + void sechandler_basic_test_object::test<1>() + + { + + char buffer[4096]; + + ensure_equals("Resultant pem is correct", + mPemTestCert, mTestCert->getPem()); + std::vector binary_cert = mTestCert->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 = mTestCert->getLLSD(); + std::ostringstream llsd_value; + llsd_value << LLSDOStreamer(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-30T20:58:00Z"); + ensure_equals("valid to", (std::string)llsd_cert["valid_to"], "2011-12-01T07:59:00Z"); + + ensure("x509 is equal", !X509_cmp(mX509TestCert, mTestCert->getOpenSSLX509())); + } + + + // test protected data + template<> template<> + void sechandler_basic_test_object::test<2>() + + { + unsigned char MACAddress[MAC_ADDRESS_BYTES]; + LLUUID::getNodeID(MACAddress); + + std::string protected_data = "sUSh3wj77NG9oAMyt3XIhaej3KLZhLZWFZvI6rIGmwUUOmmelrRg0NI9rkOj8ZDpTPxpwToaBT5u" + "GQhakdaGLJznr9bHr4/6HIC1bouKj4n2rs4TL6j2WSjto114QdlNfLsE8cbbE+ghww58g8SeyLQO" + "nyzXoz+/PBz0HD5SMFDuObccoPW24gmqYySz8YoEWhSwO0pUtEEqOjVRsAJgF5wLAtJZDeuilGsq" + "4ZT9Y4wZ9Rh8nnF3fDUL6IGamHe1ClXM1jgBu10F6UMhZbnH4C3aJ2E9+LiOntU+l3iCb2MpkEpr" + "82r2ZAMwIrpnirL/xoYoyz7MJQYwUuMvBPToZJrxNSsjI+S2Z+I3iEJAELMAAA=="; + + std::vector 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); + LLXORCipher cipher2(MACAddress, MAC_ADDRESS_BYTES); + 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 handler = new LLSecAPIBasicHandler("sechandler_settings.tmp", + "test_password.dat"); + // 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"); + + 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"); + 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"); + 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 handler = new LLSecAPIBasicHandler("sechandler_settings.tmp", "test_password.dat"); + + + 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 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 my_new_cred = handler->loadCredential("my_grid"); + 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 + + gSavedSettings.setString("FirstName", "myfirstname"); + gSavedSettings.setString("LastName", "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 decoded_password(length); + apr_base64_decode(&decoded_password[0], hashed_password.c_str()); + unsigned char MACAddress[MAC_ADDRESS_BYTES]; + LLUUID::getNodeID(MACAddress); + LLXORCipher cipher(gMACAddress, MAC_ADDRESS_BYTES); + cipher.decrypt((U8*)&decoded_password[0], length); + LLXORCipher cipher2(MACAddress, MAC_ADDRESS_BYTES); + 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 store + template<> template<> + void sechandler_basic_test_object::test<4>() + { + // instantiate a cert store from a file + llofstream certstorefile("mycertstore.pem", std::ios::out | std::ios::binary); + + certstorefile << mPemTestCert; + certstorefile.close(); + // LLBasicCertificateStore test_store("mycertstore.pem"); + // X509* test_cert = test_store[0]->getOpenSSLX509(); + + // ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509TestCert)); + } +}; diff --git a/indra/newview/tests/llviewernetwork_test.cpp b/indra/newview/tests/llviewernetwork_test.cpp new file mode 100644 index 0000000000..c7a6b2ad15 --- /dev/null +++ b/indra/newview/tests/llviewernetwork_test.cpp @@ -0,0 +1,446 @@ +/** + * @file llviewernetwork_test.cpp + * @author Roxie + * @date 2009-03-9 + * @brief Test the viewernetwork functionality + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden LregisterSecAPIab + * 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 + * + * 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 + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "../llviewerprecompiledheaders.h" +#include "../llviewernetwork.h" +#include "../test/lltut.h" +#include "../../llxml/llcontrol.h" +#include "llfile.h" + +LLControlGroup gSavedSettings; +const char *gSampleGridFile = "" +"grid1" +" favorite1" +" helper_urihttps://helper1/helpers/" +" labelmylabel" +" login_pageloginpage" +" login_urimyloginuri" +" namegrid1" +" visible1" +" credential_typeagent" +" grid_login_idMyGrid" +"" +"util.agni.lindenlab.com" +" favorite1" +" helper_urihttps://helper1/helpers/" +" labelmylabel" +" login_pageloginpage" +" login_urimyloginuri" +" nameutil.agni.lindenlab.com" +""; +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- +namespace tut +{ + // Test wrapper declaration : wrapping nothing for the moment + struct viewerNetworkTest + { + viewerNetworkTest() + { + gSavedSettings.cleanup(); + gSavedSettings.cleanup(); + gSavedSettings.declareString("CmdLineGridChoice", "", "", FALSE); + gSavedSettings.declareString("CmdLineHelperURI", "", "", FALSE); + gSavedSettings.declareString("LoginPage", "", "", FALSE); + gSavedSettings.declareString("CurrentGrid", "", "", FALSE); + gSavedSettings.declareLLSD("CmdLineLoginURI", LLSD(), "", FALSE); + } + ~viewerNetworkTest() + { + LLFile::remove("grid_test.xml"); + } + }; + + // Tut templating thingamagic: test group, object and test instance + typedef test_group 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("grid_test.xml"); + // validate that some of the defaults are available. + std::map known_grids = manager.getKnownGrids(); +#ifndef LL_RELEASE_FOR_DOWNLOAD + ensure_equals("Known grids is a string-string map of size 18", known_grids.size(), 18); +#else // LL_RELEASE_FOR_DOWNLOAD + ensure_equals("Known grids is a string-string map of size 18", known_grids.size(), 2); +#endif // LL_RELEASE_FOR_DOWNLOAD + + 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 = manager.getGridInfo("util.agni.lindenlab.com"); + ensure("Grid info for agni is a map", grid.isMap()); + ensure_equals("name is correct for agni", + grid[GRID_NAME_VALUE].asString(), std::string("util.agni.lindenlab.com")); +#ifndef LL_RELEASE_FOR_DOWNLOAD + ensure_equals("label is correct for agni", + grid[GRID_LABEL_VALUE].asString(), std::string("Agni")); +#else // LL_RELEASE_FOR_DOWNLOAD + ensure_equals("label is correct for agni", + grid[GRID_LABEL_VALUE].asString(), std::string("Secondlife.com")); +#endif // LL_RELEASE_FOR_DOWNLOAD + 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 not 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 manager("grid_test.xml"); + std::map known_grids = manager.getKnownGrids(); +#ifndef LL_RELEASE_FOR_DOWNLOAD + ensure_equals("adding a grid via a grid file increases known grid size", + known_grids.size(), 19); +#else + ensure_equals("adding a grid via a grid file increases known grid size", + known_grids.size(), 3); +#endif + 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 = manager.getGridInfo("util.agni.lindenlab.com"); +#ifndef LL_RELEASE_FOR_DOWNLOAD + ensure_equals("Agni grid label was not modified by grid file", + grid[GRID_LABEL_VALUE].asString(), std::string("Agni")); +#else \\ LL_RELEASE_FOR_DOWNLOAD + ensure_equals("Agni grid label was not modified by grid file", + grid[GRID_LABEL_VALUE].asString(), std::string("Secondlife.com")); +#endif \\ LL_RELEASE_FOR_DOWNLOAD + + ensure_equals("Agni name wasn't modified by grid file", + grid[GRID_NAME_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 not 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")); + grid = manager.getGridInfo("grid1"); + ensure_equals("grid file grid name is set", + grid[GRID_NAME_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>() + { + LLSD loginURI = std::string("https://my.login.uri/cgi-bin/login.cgi"); + gSavedSettings.setLLSD("CmdLineLoginURI", loginURI); + LLGridManager manager("grid_test.xml"); + + // with single login uri specified. + std::map known_grids = manager.getKnownGrids(); +#ifndef LL_RELEASE_FOR_DOWNLOAD + ensure_equals("adding a command line grid increases known grid size", + known_grids.size(), 19); +#else + ensure_equals("adding a command line grid increases known grid size", + known_grids.size(), 3); +#endif + ensure_equals("Command line grid is added to the list of grids", + known_grids["my.login.uri"], std::string("my.login.uri")); + LLSD grid = manager.getGridInfo("my.login.uri"); + ensure_equals("Command line grid name is set", + grid[GRID_NAME_VALUE].asString(), std::string("my.login.uri")); + ensure_equals("Command line grid label is set", + grid[GRID_LABEL_VALUE].asString(), std::string("my.login.uri")); + ensure("Command line grid login uri is an array", + grid[GRID_LOGIN_URI_VALUE].isArray()); + ensure_equals("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("Command line grid helper uri is set", + grid[GRID_HELPER_URI_VALUE].asString(), + std::string("https://my.login.uri/helpers/")); + ensure_equals("Command line grid login page is set", + grid[GRID_LOGIN_PAGE_VALUE].asString(), + std::string("http://my.login.uri/app/login/")); + ensure("Command line grid favorite is set", + !grid.has(GRID_IS_FAVORITE_VALUE)); + ensure("Command line grid isn't a system grid", + !grid.has(GRID_IS_SYSTEM_GRID_VALUE)); + + // now try a command line with a custom grid identifier + gSavedSettings.setString("CmdLineGridChoice", "mycustomgridchoice"); + manager = LLGridManager("grid_test.xml"); + known_grids = manager.getKnownGrids(); +#ifndef LL_RELEASE_FOR_DOWNLOAD + ensure_equals("adding a command line grid with custom name increases known grid size", + known_grids.size(), 19); +#else + ensure_equals("adding a command line grid with custom name inceases known grid size", + known_grids.size(), 3); +#endif + ensure_equals("Custom Command line grid is added to the list of grids", + known_grids["mycustomgridchoice"], std::string("mycustomgridchoice")); + grid = manager.getGridInfo("mycustomgridchoice"); + ensure_equals("Custom Command line grid name is set", + grid[GRID_NAME_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://my.login.uri/cgi-bin/login.cgi")); + + // add a helperuri + gSavedSettings.setString("CmdLineHelperURI", "myhelperuri"); + manager = LLGridManager("grid_test.xml"); + grid = manager.getGridInfo("mycustomgridchoice"); + ensure_equals("Validate command line helper uri", + grid[GRID_HELPER_URI_VALUE].asString(), std::string("myhelperuri")); + + // add a login page + gSavedSettings.setString("LoginPage", "myloginpage"); + manager = LLGridManager("grid_test.xml"); + grid = manager.getGridInfo("mycustomgridchoice"); + ensure_equals("Validate command line helper uri", + grid[GRID_LOGIN_PAGE_VALUE].asString(), std::string("myloginpage")); + } + + // validate grid selection + template<> template<> + void viewerNetworkTestObject::test<4>() + { + LLSD loginURI = LLSD::emptyArray(); + LLSD grid = LLSD::emptyMap(); + // adding a grid with simply a name will populate the values. + grid[GRID_NAME_VALUE] = "myaddedgrid"; + + loginURI.append(std::string("https://my.login.uri/cgi-bin/login.cgi")); + gSavedSettings.setLLSD("CmdLineLoginURI", loginURI); + LLGridManager manager("grid_test.xml"); + manager.addGrid(grid); + manager.setGridChoice("util.agni.lindenlab.com"); +#ifndef LL_RELEASE_FOR_DOWNLOAD + ensure_equals("getGridLabel", manager.getGridLabel(), std::string("Agni")); +#else // LL_RELEASE_FOR_DOWNLOAD + ensure_equals("getGridLabel", manager.getGridLabel(), std::string("Secondlife.com")); +#endif // LL_RELEASE_FOR_DOWNLOAD + ensure_equals("getGridName", manager.getGridName(), + std::string("util.agni.lindenlab.com")); + ensure_equals("getHelperURI", manager.getHelperURI(), + std::string("https://secondlife.com/helpers/")); + ensure_equals("getLoginPage", manager.getLoginPage(), + std::string("http://secondlife.com/app/login/")); + ensure_equals("getLoginPage2", manager.getLoginPage("util.agni.lindenlab.com"), + std::string("http://secondlife.com/app/login/")); + ensure("Is Agni a production grid", manager.isInProductionGrid()); + std::vector uris; + manager.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")); + manager.setGridChoice("myaddedgrid"); + ensure_equals("getGridLabel", manager.getGridLabel(), std::string("myaddedgrid")); + ensure("Is myaddedgrid a production grid", !manager.isInProductionGrid()); + + manager.setFavorite(); + grid = manager.getGridInfo("myaddedgrid"); + ensure("setting favorite", grid.has(GRID_IS_FAVORITE_VALUE)); + } + + // name based grid population + template<> template<> + void viewerNetworkTestObject::test<5>() + { + LLGridManager manager("grid_test.xml"); + LLSD grid = LLSD::emptyMap(); + // adding a grid with simply a name will populate the values. + grid[GRID_NAME_VALUE] = "myaddedgrid"; + manager.addGrid(grid); + grid = manager.getGridInfo("myaddedgrid"); + + ensure_equals("name based grid has name value", + grid[GRID_NAME_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<6>() + { + // try with initial grid list without a grid file, + // without setting the grid to a saveable favorite. + LLGridManager manager("grid_test.xml"); + LLSD grid = LLSD::emptyMap(); + grid[GRID_NAME_VALUE] = std::string("mynewgridname"); + manager.addGrid(grid); + manager.saveFavorites(); + ensure("Grid file exists after saving", + LLFile::isfile("grid_test.xml")); + manager = LLGridManager("grid_test.xml"); + // should not be there + std::map known_grids = manager.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 + manager.addGrid(grid); + manager.setGridChoice("mynewgridname"); + manager.setFavorite(); + manager.saveFavorites(); + ensure("Grid file exists after saving", + LLFile::isfile("grid_test.xml")); + manager = LLGridManager("grid_test.xml"); + // should not be there + known_grids = manager.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<7>() + { + + llofstream gridfile("grid_test.xml"); + gridfile << gSampleGridFile; + gridfile.close(); + + LLGridManager manager("grid_test.xml"); + LLSD grid = LLSD::emptyMap(); + grid[GRID_NAME_VALUE] = std::string("mynewgridname"); + manager.addGrid(grid); + manager.saveFavorites(); + // validate we didn't lose existing favorites + manager = LLGridManager("grid_test.xml"); + std::map known_grids = manager.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 + manager.addGrid(grid); + manager.setGridChoice("mynewgridname"); + manager.setFavorite(); + manager.saveFavorites(); + known_grids = manager.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 = manager.getKnownGrids(); + ensure("New grid wasn't added to persisted list after being marked a favorite", + known_grids.find(std::string("mynewgridname")) != + known_grids.end()); + } +} -- cgit v1.2.3