michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: * http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: Cu.import("resource://services-sync/constants.js"); michael@0: Cu.import("resource://services-sync/identity.js"); michael@0: Cu.import("resource://services-sync/util.js"); michael@0: michael@0: let identity = new IdentityManager(); michael@0: michael@0: function run_test() { michael@0: initTestLogging("Trace"); michael@0: Log.repository.getLogger("Sync.Identity").level = Log.Level.Trace; michael@0: michael@0: run_next_test(); michael@0: } michael@0: michael@0: add_test(function test_username_from_account() { michael@0: _("Ensure usernameFromAccount works properly."); michael@0: michael@0: do_check_eq(identity.usernameFromAccount(null), null); michael@0: do_check_eq(identity.usernameFromAccount("user"), "user"); michael@0: do_check_eq(identity.usernameFromAccount("User"), "user"); michael@0: do_check_eq(identity.usernameFromAccount("john@doe.com"), michael@0: "7wohs32cngzuqt466q3ge7indszva4of"); michael@0: michael@0: run_next_test(); michael@0: }); michael@0: michael@0: add_test(function test_account_username() { michael@0: _("Ensure the account and username attributes work properly."); michael@0: michael@0: _("Verify initial state"); michael@0: do_check_eq(Svc.Prefs.get("account"), undefined); michael@0: do_check_eq(Svc.Prefs.get("username"), undefined); michael@0: do_check_eq(identity.account, null); michael@0: do_check_eq(identity.username, null); michael@0: michael@0: _("The 'username' attribute is normalized to lower case, updates preferences and identities."); michael@0: identity.username = "TarZan"; michael@0: do_check_eq(identity.username, "tarzan"); michael@0: do_check_eq(Svc.Prefs.get("username"), "tarzan"); michael@0: do_check_eq(identity.username, "tarzan"); michael@0: michael@0: _("If not set, the 'account attribute' falls back to the username for backwards compatibility."); michael@0: do_check_eq(identity.account, "tarzan"); michael@0: michael@0: _("Setting 'username' to a non-truthy value resets the pref."); michael@0: identity.username = null; michael@0: do_check_eq(identity.username, null); michael@0: do_check_eq(identity.account, null); michael@0: const default_marker = {}; michael@0: do_check_eq(Svc.Prefs.get("username", default_marker), default_marker); michael@0: do_check_eq(identity.username, null); michael@0: michael@0: _("The 'account' attribute will set the 'username' if it doesn't contain characters that aren't allowed in the username."); michael@0: identity.account = "johndoe"; michael@0: do_check_eq(identity.account, "johndoe"); michael@0: do_check_eq(identity.username, "johndoe"); michael@0: do_check_eq(Svc.Prefs.get("username"), "johndoe"); michael@0: do_check_eq(identity.username, "johndoe"); michael@0: michael@0: _("If 'account' contains disallowed characters such as @, 'username' will the base32 encoded SHA1 hash of 'account'"); michael@0: identity.account = "John@Doe.com"; michael@0: do_check_eq(identity.account, "john@doe.com"); michael@0: do_check_eq(identity.username, "7wohs32cngzuqt466q3ge7indszva4of"); michael@0: michael@0: _("Setting 'account' to a non-truthy value resets the pref."); michael@0: identity.account = null; michael@0: do_check_eq(identity.account, null); michael@0: do_check_eq(Svc.Prefs.get("account", default_marker), default_marker); michael@0: do_check_eq(identity.username, null); michael@0: do_check_eq(Svc.Prefs.get("username", default_marker), default_marker); michael@0: michael@0: Svc.Prefs.resetBranch(""); michael@0: run_next_test(); michael@0: }); michael@0: michael@0: add_test(function test_basic_password() { michael@0: _("Ensure basic password setting works as expected."); michael@0: michael@0: identity.account = null; michael@0: do_check_eq(identity.currentAuthState, LOGIN_FAILED_NO_USERNAME); michael@0: let thrown = false; michael@0: try { michael@0: identity.basicPassword = "foobar"; michael@0: } catch (ex) { michael@0: thrown = true; michael@0: } michael@0: michael@0: do_check_true(thrown); michael@0: thrown = false; michael@0: michael@0: identity.account = "johndoe"; michael@0: do_check_eq(identity.currentAuthState, LOGIN_FAILED_NO_PASSWORD); michael@0: identity.basicPassword = "password"; michael@0: do_check_eq(identity.basicPassword, "password"); michael@0: do_check_eq(identity.currentAuthState, LOGIN_FAILED_NO_PASSPHRASE); michael@0: do_check_true(identity.hasBasicCredentials()); michael@0: michael@0: identity.account = null; michael@0: michael@0: run_next_test(); michael@0: }); michael@0: michael@0: add_test(function test_basic_password_persistence() { michael@0: _("Ensure credentials are saved and restored to the login manager properly."); michael@0: michael@0: // Just in case. michael@0: identity.account = null; michael@0: identity.deleteSyncCredentials(); michael@0: michael@0: identity.account = "janesmith"; michael@0: identity.basicPassword = "ilovejohn"; michael@0: identity.persistCredentials(); michael@0: michael@0: let im1 = new IdentityManager(); michael@0: do_check_eq(im1._basicPassword, null); michael@0: do_check_eq(im1.username, "janesmith"); michael@0: do_check_eq(im1.basicPassword, "ilovejohn"); michael@0: michael@0: let im2 = new IdentityManager(); michael@0: do_check_eq(im2._basicPassword, null); michael@0: michael@0: _("Now remove the password and ensure it is deleted from storage."); michael@0: identity.basicPassword = null; michael@0: identity.persistCredentials(); // This should nuke from storage. michael@0: do_check_eq(im2.basicPassword, null); michael@0: michael@0: _("Ensure that retrieving an unset but unpersisted removal returns null."); michael@0: identity.account = "janesmith"; michael@0: identity.basicPassword = "myotherpassword"; michael@0: identity.persistCredentials(); michael@0: michael@0: identity.basicPassword = null; michael@0: do_check_eq(identity.basicPassword, null); michael@0: michael@0: // Reset for next test. michael@0: identity.account = null; michael@0: identity.persistCredentials(); michael@0: michael@0: run_next_test(); michael@0: }); michael@0: michael@0: add_test(function test_sync_key() { michael@0: _("Ensure Sync Key works as advertised."); michael@0: michael@0: _("Ensure setting a Sync Key before an account throws."); michael@0: let thrown = false; michael@0: try { michael@0: identity.syncKey = "blahblah"; michael@0: } catch (ex) { michael@0: thrown = true; michael@0: } michael@0: do_check_true(thrown); michael@0: thrown = false; michael@0: michael@0: identity.account = "johnsmith"; michael@0: identity.basicPassword = "johnsmithpw"; michael@0: michael@0: do_check_eq(identity.syncKey, null); michael@0: do_check_eq(identity.syncKeyBundle, null); michael@0: michael@0: _("An invalid Sync Key is silently accepted for historical reasons."); michael@0: identity.syncKey = "synckey"; michael@0: do_check_eq(identity.syncKey, "synckey"); michael@0: michael@0: _("But the SyncKeyBundle should not be created from bad keys."); michael@0: do_check_eq(identity.syncKeyBundle, null); michael@0: michael@0: let syncKey = Utils.generatePassphrase(); michael@0: identity.syncKey = syncKey; michael@0: do_check_eq(identity.syncKey, syncKey); michael@0: do_check_neq(identity.syncKeyBundle, null); michael@0: michael@0: let im = new IdentityManager(); michael@0: im.account = "pseudojohn"; michael@0: do_check_eq(im.syncKey, null); michael@0: do_check_eq(im.syncKeyBundle, null); michael@0: michael@0: identity.account = null; michael@0: michael@0: run_next_test(); michael@0: }); michael@0: michael@0: add_test(function test_sync_key_changes() { michael@0: _("Ensure changes to Sync Key have appropriate side-effects."); michael@0: michael@0: let im = new IdentityManager(); michael@0: let sk1 = Utils.generatePassphrase(); michael@0: let sk2 = Utils.generatePassphrase(); michael@0: michael@0: im.account = "johndoe"; michael@0: do_check_eq(im.syncKey, null); michael@0: do_check_eq(im.syncKeyBundle, null); michael@0: michael@0: im.syncKey = sk1; michael@0: do_check_neq(im.syncKeyBundle, null); michael@0: michael@0: let ek1 = im.syncKeyBundle.encryptionKeyB64; michael@0: let hk1 = im.syncKeyBundle.hmacKeyB64; michael@0: michael@0: // Change the Sync Key and ensure the Sync Key Bundle is updated. michael@0: im.syncKey = sk2; michael@0: let ek2 = im.syncKeyBundle.encryptionKeyB64; michael@0: let hk2 = im.syncKeyBundle.hmacKeyB64; michael@0: michael@0: do_check_neq(ek1, ek2); michael@0: do_check_neq(hk1, hk2); michael@0: michael@0: im.account = null; michael@0: michael@0: run_next_test(); michael@0: }); michael@0: michael@0: add_test(function test_current_auth_state() { michael@0: _("Ensure current auth state is reported properly."); michael@0: michael@0: let im = new IdentityManager(); michael@0: do_check_eq(im.currentAuthState, LOGIN_FAILED_NO_USERNAME); michael@0: michael@0: im.account = "johndoe"; michael@0: do_check_eq(im.currentAuthState, LOGIN_FAILED_NO_PASSWORD); michael@0: michael@0: im.basicPassword = "ilovejane"; michael@0: do_check_eq(im.currentAuthState, LOGIN_FAILED_NO_PASSPHRASE); michael@0: michael@0: im.syncKey = "foobar"; michael@0: do_check_eq(im.currentAuthState, LOGIN_FAILED_INVALID_PASSPHRASE); michael@0: michael@0: im.syncKey = null; michael@0: do_check_eq(im.currentAuthState, LOGIN_FAILED_NO_PASSPHRASE); michael@0: michael@0: im.syncKey = Utils.generatePassphrase(); michael@0: do_check_eq(im.currentAuthState, STATUS_OK); michael@0: michael@0: im.account = null; michael@0: michael@0: run_next_test(); michael@0: }); michael@0: michael@0: add_test(function test_sync_key_persistence() { michael@0: _("Ensure Sync Key persistence works as expected."); michael@0: michael@0: identity.account = "pseudojohn"; michael@0: identity.password = "supersecret"; michael@0: michael@0: let syncKey = Utils.generatePassphrase(); michael@0: identity.syncKey = syncKey; michael@0: michael@0: identity.persistCredentials(); michael@0: michael@0: let im = new IdentityManager(); michael@0: im.account = "pseudojohn"; michael@0: do_check_eq(im.syncKey, syncKey); michael@0: do_check_neq(im.syncKeyBundle, null); michael@0: michael@0: let kb1 = identity.syncKeyBundle; michael@0: let kb2 = im.syncKeyBundle; michael@0: michael@0: do_check_eq(kb1.encryptionKeyB64, kb2.encryptionKeyB64); michael@0: do_check_eq(kb1.hmacKeyB64, kb2.hmacKeyB64); michael@0: michael@0: identity.account = null; michael@0: identity.persistCredentials(); michael@0: michael@0: let im2 = new IdentityManager(); michael@0: im2.account = "pseudojohn"; michael@0: do_check_eq(im2.syncKey, null); michael@0: michael@0: im2.account = null; michael@0: michael@0: _("Ensure deleted but not persisted value is retrieved."); michael@0: identity.account = "someoneelse"; michael@0: identity.syncKey = Utils.generatePassphrase(); michael@0: identity.persistCredentials(); michael@0: identity.syncKey = null; michael@0: do_check_eq(identity.syncKey, null); michael@0: michael@0: // Clean up. michael@0: identity.account = null; michael@0: identity.persistCredentials(); michael@0: michael@0: run_next_test(); michael@0: });