Wed, 31 Dec 2014 07:53:36 +0100
Correct small whitespace inconsistency, lost while renaming variables.
michael@0 | 1 | /* Any copyright is dedicated to the Public Domain. |
michael@0 | 2 | http://creativecommons.org/publicdomain/zero/1.0/ */ |
michael@0 | 3 | |
michael@0 | 4 | Cu.import("resource://gre/modules/Log.jsm"); |
michael@0 | 5 | Cu.import("resource://services-sync/constants.js"); |
michael@0 | 6 | Cu.import("resource://services-sync/service.js"); |
michael@0 | 7 | Cu.import("resource://services-sync/policies.js"); |
michael@0 | 8 | Cu.import("resource://services-sync/util.js"); |
michael@0 | 9 | Cu.import("resource://testing-common/services/sync/utils.js"); |
michael@0 | 10 | |
michael@0 | 11 | function login_handling(handler) { |
michael@0 | 12 | return function (request, response) { |
michael@0 | 13 | if (basic_auth_matches(request, "johndoe", "ilovejane") || |
michael@0 | 14 | basic_auth_matches(request, "janedoe", "ilovejohn")) { |
michael@0 | 15 | handler(request, response); |
michael@0 | 16 | } else { |
michael@0 | 17 | let body = "Unauthorized"; |
michael@0 | 18 | response.setStatusLine(request.httpVersion, 401, "Unauthorized"); |
michael@0 | 19 | response.setHeader("Content-Type", "text/plain"); |
michael@0 | 20 | response.bodyOutputStream.write(body, body.length); |
michael@0 | 21 | } |
michael@0 | 22 | }; |
michael@0 | 23 | } |
michael@0 | 24 | |
michael@0 | 25 | function run_test() { |
michael@0 | 26 | let logger = Log.repository.rootLogger; |
michael@0 | 27 | Log.repository.rootLogger.addAppender(new Log.DumpAppender()); |
michael@0 | 28 | |
michael@0 | 29 | run_next_test(); |
michael@0 | 30 | } |
michael@0 | 31 | |
michael@0 | 32 | add_test(function test_offline() { |
michael@0 | 33 | try { |
michael@0 | 34 | _("The right bits are set when we're offline."); |
michael@0 | 35 | Services.io.offline = true; |
michael@0 | 36 | do_check_false(!!Service.login()); |
michael@0 | 37 | do_check_eq(Service.status.login, LOGIN_FAILED_NETWORK_ERROR); |
michael@0 | 38 | Services.io.offline = false; |
michael@0 | 39 | } finally { |
michael@0 | 40 | Svc.Prefs.resetBranch(""); |
michael@0 | 41 | run_next_test(); |
michael@0 | 42 | } |
michael@0 | 43 | }); |
michael@0 | 44 | |
michael@0 | 45 | function setup() { |
michael@0 | 46 | let janeHelper = track_collections_helper(); |
michael@0 | 47 | let janeU = janeHelper.with_updated_collection; |
michael@0 | 48 | let janeColls = janeHelper.collections; |
michael@0 | 49 | let johnHelper = track_collections_helper(); |
michael@0 | 50 | let johnU = johnHelper.with_updated_collection; |
michael@0 | 51 | let johnColls = johnHelper.collections; |
michael@0 | 52 | |
michael@0 | 53 | let server = httpd_setup({ |
michael@0 | 54 | "/1.1/johndoe/info/collections": login_handling(johnHelper.handler), |
michael@0 | 55 | "/1.1/janedoe/info/collections": login_handling(janeHelper.handler), |
michael@0 | 56 | |
michael@0 | 57 | // We need these handlers because we test login, and login |
michael@0 | 58 | // is where keys are generated or fetched. |
michael@0 | 59 | // TODO: have Jane fetch her keys, not generate them... |
michael@0 | 60 | "/1.1/johndoe/storage/crypto/keys": johnU("crypto", new ServerWBO("keys").handler()), |
michael@0 | 61 | "/1.1/johndoe/storage/meta/global": johnU("meta", new ServerWBO("global").handler()), |
michael@0 | 62 | "/1.1/janedoe/storage/crypto/keys": janeU("crypto", new ServerWBO("keys").handler()), |
michael@0 | 63 | "/1.1/janedoe/storage/meta/global": janeU("meta", new ServerWBO("global").handler()) |
michael@0 | 64 | }); |
michael@0 | 65 | |
michael@0 | 66 | Service.serverURL = server.baseURI; |
michael@0 | 67 | return server; |
michael@0 | 68 | } |
michael@0 | 69 | |
michael@0 | 70 | add_test(function test_login_logout() { |
michael@0 | 71 | let server = setup(); |
michael@0 | 72 | |
michael@0 | 73 | try { |
michael@0 | 74 | _("Force the initial state."); |
michael@0 | 75 | ensureLegacyIdentityManager(); |
michael@0 | 76 | Service.status.service = STATUS_OK; |
michael@0 | 77 | do_check_eq(Service.status.service, STATUS_OK); |
michael@0 | 78 | |
michael@0 | 79 | _("Try logging in. It won't work because we're not configured yet."); |
michael@0 | 80 | Service.login(); |
michael@0 | 81 | do_check_eq(Service.status.service, CLIENT_NOT_CONFIGURED); |
michael@0 | 82 | do_check_eq(Service.status.login, LOGIN_FAILED_NO_USERNAME); |
michael@0 | 83 | do_check_false(Service.isLoggedIn); |
michael@0 | 84 | |
michael@0 | 85 | _("Try again with username and password set."); |
michael@0 | 86 | Service.identity.account = "johndoe"; |
michael@0 | 87 | Service.identity.basicPassword = "ilovejane"; |
michael@0 | 88 | Service.login(); |
michael@0 | 89 | do_check_eq(Service.status.service, CLIENT_NOT_CONFIGURED); |
michael@0 | 90 | do_check_eq(Service.status.login, LOGIN_FAILED_NO_PASSPHRASE); |
michael@0 | 91 | do_check_false(Service.isLoggedIn); |
michael@0 | 92 | |
michael@0 | 93 | _("Success if passphrase is set."); |
michael@0 | 94 | Service.identity.syncKey = "foo"; |
michael@0 | 95 | Service.login(); |
michael@0 | 96 | do_check_eq(Service.status.service, STATUS_OK); |
michael@0 | 97 | do_check_eq(Service.status.login, LOGIN_SUCCEEDED); |
michael@0 | 98 | do_check_true(Service.isLoggedIn); |
michael@0 | 99 | |
michael@0 | 100 | _("We can also pass username, password and passphrase to login()."); |
michael@0 | 101 | Service.login("janedoe", "incorrectpassword", "bar"); |
michael@0 | 102 | setBasicCredentials("janedoe", "incorrectpassword", "bar"); |
michael@0 | 103 | do_check_eq(Service.status.service, LOGIN_FAILED); |
michael@0 | 104 | do_check_eq(Service.status.login, LOGIN_FAILED_LOGIN_REJECTED); |
michael@0 | 105 | do_check_false(Service.isLoggedIn); |
michael@0 | 106 | |
michael@0 | 107 | _("Try again with correct password."); |
michael@0 | 108 | Service.login("janedoe", "ilovejohn"); |
michael@0 | 109 | do_check_eq(Service.status.service, STATUS_OK); |
michael@0 | 110 | do_check_eq(Service.status.login, LOGIN_SUCCEEDED); |
michael@0 | 111 | do_check_true(Service.isLoggedIn); |
michael@0 | 112 | |
michael@0 | 113 | _("Calling login() with parameters when the client is unconfigured sends notification."); |
michael@0 | 114 | let notified = false; |
michael@0 | 115 | Svc.Obs.add("weave:service:setup-complete", function() { |
michael@0 | 116 | notified = true; |
michael@0 | 117 | }); |
michael@0 | 118 | setBasicCredentials(null, null, null); |
michael@0 | 119 | Service.login("janedoe", "ilovejohn", "bar"); |
michael@0 | 120 | do_check_true(notified); |
michael@0 | 121 | do_check_eq(Service.status.service, STATUS_OK); |
michael@0 | 122 | do_check_eq(Service.status.login, LOGIN_SUCCEEDED); |
michael@0 | 123 | do_check_true(Service.isLoggedIn); |
michael@0 | 124 | |
michael@0 | 125 | _("Logout."); |
michael@0 | 126 | Service.logout(); |
michael@0 | 127 | do_check_false(Service.isLoggedIn); |
michael@0 | 128 | |
michael@0 | 129 | _("Logging out again won't do any harm."); |
michael@0 | 130 | Service.logout(); |
michael@0 | 131 | do_check_false(Service.isLoggedIn); |
michael@0 | 132 | |
michael@0 | 133 | } finally { |
michael@0 | 134 | Svc.Prefs.resetBranch(""); |
michael@0 | 135 | server.stop(run_next_test); |
michael@0 | 136 | } |
michael@0 | 137 | }); |
michael@0 | 138 | |
michael@0 | 139 | add_test(function test_login_on_sync() { |
michael@0 | 140 | let server = setup(); |
michael@0 | 141 | setBasicCredentials("johndoe", "ilovejane", "bar"); |
michael@0 | 142 | |
michael@0 | 143 | try { |
michael@0 | 144 | _("Sync calls login."); |
michael@0 | 145 | let oldLogin = Service.login; |
michael@0 | 146 | let loginCalled = false; |
michael@0 | 147 | Service.login = function() { |
michael@0 | 148 | loginCalled = true; |
michael@0 | 149 | Service.status.login = LOGIN_SUCCEEDED; |
michael@0 | 150 | this._loggedIn = false; // So that sync aborts. |
michael@0 | 151 | return true; |
michael@0 | 152 | }; |
michael@0 | 153 | |
michael@0 | 154 | Service.sync(); |
michael@0 | 155 | |
michael@0 | 156 | do_check_true(loginCalled); |
michael@0 | 157 | Service.login = oldLogin; |
michael@0 | 158 | |
michael@0 | 159 | // Stub mpLocked. |
michael@0 | 160 | let mpLockedF = Utils.mpLocked; |
michael@0 | 161 | let mpLocked = true; |
michael@0 | 162 | Utils.mpLocked = function() mpLocked; |
michael@0 | 163 | |
michael@0 | 164 | // Stub scheduleNextSync. This gets called within checkSyncStatus if we're |
michael@0 | 165 | // ready to sync, so use it as an indicator. |
michael@0 | 166 | let scheduleNextSyncF = Service.scheduler.scheduleNextSync; |
michael@0 | 167 | let scheduleCalled = false; |
michael@0 | 168 | Service.scheduler.scheduleNextSync = function(wait) { |
michael@0 | 169 | scheduleCalled = true; |
michael@0 | 170 | scheduleNextSyncF.call(this, wait); |
michael@0 | 171 | }; |
michael@0 | 172 | |
michael@0 | 173 | // Autoconnect still tries to connect in the background (useful behavior: |
michael@0 | 174 | // for non-MP users and unlocked MPs, this will detect version expiry |
michael@0 | 175 | // earlier). |
michael@0 | 176 | // |
michael@0 | 177 | // Consequently, non-MP users will be logged in as in the pre-Bug 543784 world, |
michael@0 | 178 | // and checkSyncStatus reflects that by waiting for login. |
michael@0 | 179 | // |
michael@0 | 180 | // This process doesn't apply if your MP is still locked, so we make |
michael@0 | 181 | // checkSyncStatus accept a locked MP in place of being logged in. |
michael@0 | 182 | // |
michael@0 | 183 | // This test exercises these two branches. |
michael@0 | 184 | |
michael@0 | 185 | _("We're ready to sync if locked."); |
michael@0 | 186 | Service.enabled = true; |
michael@0 | 187 | Services.io.offline = false; |
michael@0 | 188 | Service.scheduler.checkSyncStatus(); |
michael@0 | 189 | do_check_true(scheduleCalled); |
michael@0 | 190 | |
michael@0 | 191 | _("... and also if we're not locked."); |
michael@0 | 192 | scheduleCalled = false; |
michael@0 | 193 | mpLocked = false; |
michael@0 | 194 | Service.scheduler.checkSyncStatus(); |
michael@0 | 195 | do_check_true(scheduleCalled); |
michael@0 | 196 | Service.scheduler.scheduleNextSync = scheduleNextSyncF; |
michael@0 | 197 | |
michael@0 | 198 | // TODO: need better tests around master password prompting. See Bug 620583. |
michael@0 | 199 | |
michael@0 | 200 | mpLocked = true; |
michael@0 | 201 | |
michael@0 | 202 | // Testing exception handling if master password dialog is canceled. |
michael@0 | 203 | // Do this by monkeypatching. |
michael@0 | 204 | let oldGetter = Service.identity.__lookupGetter__("syncKey"); |
michael@0 | 205 | let oldSetter = Service.identity.__lookupSetter__("syncKey"); |
michael@0 | 206 | _("Old passphrase function is " + oldGetter); |
michael@0 | 207 | Service.identity.__defineGetter__("syncKey", |
michael@0 | 208 | function() { |
michael@0 | 209 | throw "User canceled Master Password entry"; |
michael@0 | 210 | }); |
michael@0 | 211 | |
michael@0 | 212 | let oldClearSyncTriggers = Service.scheduler.clearSyncTriggers; |
michael@0 | 213 | let oldLockedSync = Service._lockedSync; |
michael@0 | 214 | |
michael@0 | 215 | let cSTCalled = false; |
michael@0 | 216 | let lockedSyncCalled = false; |
michael@0 | 217 | |
michael@0 | 218 | Service.scheduler.clearSyncTriggers = function() { cSTCalled = true; }; |
michael@0 | 219 | Service._lockedSync = function() { lockedSyncCalled = true; }; |
michael@0 | 220 | |
michael@0 | 221 | _("If master password is canceled, login fails and we report lockage."); |
michael@0 | 222 | do_check_false(!!Service.login()); |
michael@0 | 223 | do_check_eq(Service.status.login, MASTER_PASSWORD_LOCKED); |
michael@0 | 224 | do_check_eq(Service.status.service, LOGIN_FAILED); |
michael@0 | 225 | _("Locked? " + Utils.mpLocked()); |
michael@0 | 226 | _("checkSync reports the correct term."); |
michael@0 | 227 | do_check_eq(Service._checkSync(), kSyncMasterPasswordLocked); |
michael@0 | 228 | |
michael@0 | 229 | _("Sync doesn't proceed and clears triggers if MP is still locked."); |
michael@0 | 230 | Service.sync(); |
michael@0 | 231 | |
michael@0 | 232 | do_check_true(cSTCalled); |
michael@0 | 233 | do_check_false(lockedSyncCalled); |
michael@0 | 234 | |
michael@0 | 235 | Service.identity.__defineGetter__("syncKey", oldGetter); |
michael@0 | 236 | Service.identity.__defineSetter__("syncKey", oldSetter); |
michael@0 | 237 | |
michael@0 | 238 | // N.B., a bunch of methods are stubbed at this point. Be careful putting |
michael@0 | 239 | // new tests after this point! |
michael@0 | 240 | |
michael@0 | 241 | } finally { |
michael@0 | 242 | Svc.Prefs.resetBranch(""); |
michael@0 | 243 | server.stop(run_next_test); |
michael@0 | 244 | } |
michael@0 | 245 | }); |