1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/services/sync/tests/unit/test_service_sync_updateEnabledEngines.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,439 @@ 1.4 +/* Any copyright is dedicated to the Public Domain. 1.5 + http://creativecommons.org/publicdomain/zero/1.0/ */ 1.6 + 1.7 +Cu.import("resource://services-sync/constants.js"); 1.8 +Cu.import("resource://services-sync/engines.js"); 1.9 +Cu.import("resource://services-sync/engines/clients.js"); 1.10 +Cu.import("resource://services-sync/record.js"); 1.11 +Cu.import("resource://services-sync/service.js"); 1.12 +Cu.import("resource://services-sync/util.js"); 1.13 +Cu.import("resource://testing-common/services/sync/utils.js"); 1.14 + 1.15 +initTestLogging(); 1.16 +Service.engineManager.clear(); 1.17 + 1.18 +function QuietStore() { 1.19 + Store.call("Quiet"); 1.20 +} 1.21 +QuietStore.prototype = { 1.22 + getAllIDs: function getAllIDs() { 1.23 + return []; 1.24 + } 1.25 +} 1.26 + 1.27 +function SteamEngine() { 1.28 + SyncEngine.call(this, "Steam", Service); 1.29 +} 1.30 +SteamEngine.prototype = { 1.31 + __proto__: SyncEngine.prototype, 1.32 + // We're not interested in engine sync but what the service does. 1.33 + _storeObj: QuietStore, 1.34 + 1.35 + _sync: function _sync() { 1.36 + this._syncStartup(); 1.37 + } 1.38 +}; 1.39 +Service.engineManager.register(SteamEngine); 1.40 + 1.41 +function StirlingEngine() { 1.42 + SyncEngine.call(this, "Stirling", Service); 1.43 +} 1.44 +StirlingEngine.prototype = { 1.45 + __proto__: SteamEngine.prototype, 1.46 + // This engine's enabled state is the same as the SteamEngine's. 1.47 + get prefName() "steam" 1.48 +}; 1.49 +Service.engineManager.register(StirlingEngine); 1.50 + 1.51 +// Tracking info/collections. 1.52 +let collectionsHelper = track_collections_helper(); 1.53 +let upd = collectionsHelper.with_updated_collection; 1.54 + 1.55 +function sync_httpd_setup(handlers) { 1.56 + 1.57 + handlers["/1.1/johndoe/info/collections"] = collectionsHelper.handler; 1.58 + delete collectionsHelper.collections.crypto; 1.59 + delete collectionsHelper.collections.meta; 1.60 + 1.61 + let cr = new ServerWBO("keys"); 1.62 + handlers["/1.1/johndoe/storage/crypto/keys"] = 1.63 + upd("crypto", cr.handler()); 1.64 + 1.65 + let cl = new ServerCollection(); 1.66 + handlers["/1.1/johndoe/storage/clients"] = 1.67 + upd("clients", cl.handler()); 1.68 + 1.69 + return httpd_setup(handlers); 1.70 +} 1.71 + 1.72 +function setUp(server) { 1.73 + new SyncTestingInfrastructure(server, "johndoe", "ilovejane", 1.74 + "abcdeabcdeabcdeabcdeabcdea"); 1.75 + // Ensure that the server has valid keys so that logging in will work and not 1.76 + // result in a server wipe, rendering many of these tests useless. 1.77 + generateNewKeys(Service.collectionKeys); 1.78 + let serverKeys = Service.collectionKeys.asWBO("crypto", "keys"); 1.79 + serverKeys.encrypt(Service.identity.syncKeyBundle); 1.80 + return serverKeys.upload(Service.resource(Service.cryptoKeysURL)).success; 1.81 +} 1.82 + 1.83 +const PAYLOAD = 42; 1.84 + 1.85 + 1.86 +function run_test() { 1.87 + initTestLogging("Trace"); 1.88 + Log.repository.getLogger("Sync.Service").level = Log.Level.Trace; 1.89 + Log.repository.getLogger("Sync.ErrorHandler").level = Log.Level.Trace; 1.90 + 1.91 + run_next_test(); 1.92 +} 1.93 + 1.94 +add_test(function test_newAccount() { 1.95 + _("Test: New account does not disable locally enabled engines."); 1.96 + let engine = Service.engineManager.get("steam"); 1.97 + let server = sync_httpd_setup({ 1.98 + "/1.1/johndoe/storage/meta/global": new ServerWBO("global", {}).handler(), 1.99 + "/1.1/johndoe/storage/steam": new ServerWBO("steam", {}).handler() 1.100 + }); 1.101 + setUp(server); 1.102 + 1.103 + try { 1.104 + _("Engine is enabled from the beginning."); 1.105 + Service._ignorePrefObserver = true; 1.106 + engine.enabled = true; 1.107 + Service._ignorePrefObserver = false; 1.108 + 1.109 + _("Sync."); 1.110 + Service.sync(); 1.111 + 1.112 + _("Engine continues to be enabled."); 1.113 + do_check_true(engine.enabled); 1.114 + } finally { 1.115 + Service.startOver(); 1.116 + server.stop(run_next_test); 1.117 + } 1.118 +}); 1.119 + 1.120 +add_test(function test_enabledLocally() { 1.121 + _("Test: Engine is disabled on remote clients and enabled locally"); 1.122 + Service.syncID = "abcdefghij"; 1.123 + let engine = Service.engineManager.get("steam"); 1.124 + let metaWBO = new ServerWBO("global", {syncID: Service.syncID, 1.125 + storageVersion: STORAGE_VERSION, 1.126 + engines: {}}); 1.127 + let server = sync_httpd_setup({ 1.128 + "/1.1/johndoe/storage/meta/global": metaWBO.handler(), 1.129 + "/1.1/johndoe/storage/steam": new ServerWBO("steam", {}).handler() 1.130 + }); 1.131 + setUp(server); 1.132 + 1.133 + try { 1.134 + _("Enable engine locally."); 1.135 + engine.enabled = true; 1.136 + 1.137 + _("Sync."); 1.138 + Service.sync(); 1.139 + 1.140 + _("Meta record now contains the new engine."); 1.141 + do_check_true(!!metaWBO.data.engines.steam); 1.142 + 1.143 + _("Engine continues to be enabled."); 1.144 + do_check_true(engine.enabled); 1.145 + } finally { 1.146 + Service.startOver(); 1.147 + server.stop(run_next_test); 1.148 + } 1.149 +}); 1.150 + 1.151 +add_test(function test_disabledLocally() { 1.152 + _("Test: Engine is enabled on remote clients and disabled locally"); 1.153 + Service.syncID = "abcdefghij"; 1.154 + let engine = Service.engineManager.get("steam"); 1.155 + let metaWBO = new ServerWBO("global", { 1.156 + syncID: Service.syncID, 1.157 + storageVersion: STORAGE_VERSION, 1.158 + engines: {steam: {syncID: engine.syncID, 1.159 + version: engine.version}} 1.160 + }); 1.161 + let steamCollection = new ServerWBO("steam", PAYLOAD); 1.162 + 1.163 + let server = sync_httpd_setup({ 1.164 + "/1.1/johndoe/storage/meta/global": metaWBO.handler(), 1.165 + "/1.1/johndoe/storage/steam": steamCollection.handler() 1.166 + }); 1.167 + setUp(server); 1.168 + 1.169 + try { 1.170 + _("Disable engine locally."); 1.171 + Service._ignorePrefObserver = true; 1.172 + engine.enabled = true; 1.173 + Service._ignorePrefObserver = false; 1.174 + engine.enabled = false; 1.175 + 1.176 + _("Sync."); 1.177 + Service.sync(); 1.178 + 1.179 + _("Meta record no longer contains engine."); 1.180 + do_check_false(!!metaWBO.data.engines.steam); 1.181 + 1.182 + _("Server records are wiped."); 1.183 + do_check_eq(steamCollection.payload, undefined); 1.184 + 1.185 + _("Engine continues to be disabled."); 1.186 + do_check_false(engine.enabled); 1.187 + } finally { 1.188 + Service.startOver(); 1.189 + server.stop(run_next_test); 1.190 + } 1.191 +}); 1.192 + 1.193 +add_test(function test_disabledLocally_wipe503() { 1.194 + _("Test: Engine is enabled on remote clients and disabled locally"); 1.195 + Service.syncID = "abcdefghij"; 1.196 + let engine = Service.engineManager.get("steam"); 1.197 + let metaWBO = new ServerWBO("global", { 1.198 + syncID: Service.syncID, 1.199 + storageVersion: STORAGE_VERSION, 1.200 + engines: {steam: {syncID: engine.syncID, 1.201 + version: engine.version}} 1.202 + }); 1.203 + let steamCollection = new ServerWBO("steam", PAYLOAD); 1.204 + 1.205 + function service_unavailable(request, response) { 1.206 + let body = "Service Unavailable"; 1.207 + response.setStatusLine(request.httpVersion, 503, "Service Unavailable"); 1.208 + response.setHeader("Retry-After", "23"); 1.209 + response.bodyOutputStream.write(body, body.length); 1.210 + } 1.211 + 1.212 + let server = sync_httpd_setup({ 1.213 + "/1.1/johndoe/storage/meta/global": metaWBO.handler(), 1.214 + "/1.1/johndoe/storage/steam": service_unavailable 1.215 + }); 1.216 + setUp(server); 1.217 + 1.218 + _("Disable engine locally."); 1.219 + Service._ignorePrefObserver = true; 1.220 + engine.enabled = true; 1.221 + Service._ignorePrefObserver = false; 1.222 + engine.enabled = false; 1.223 + 1.224 + Svc.Obs.add("weave:ui:sync:error", function onSyncError() { 1.225 + Svc.Obs.remove("weave:ui:sync:error", onSyncError); 1.226 + 1.227 + do_check_eq(Service.status.sync, SERVER_MAINTENANCE); 1.228 + 1.229 + Service.startOver(); 1.230 + server.stop(run_next_test); 1.231 + }); 1.232 + 1.233 + _("Sync."); 1.234 + Service.errorHandler.syncAndReportErrors(); 1.235 +}); 1.236 + 1.237 +add_test(function test_enabledRemotely() { 1.238 + _("Test: Engine is disabled locally and enabled on a remote client"); 1.239 + Service.syncID = "abcdefghij"; 1.240 + let engine = Service.engineManager.get("steam"); 1.241 + let metaWBO = new ServerWBO("global", { 1.242 + syncID: Service.syncID, 1.243 + storageVersion: STORAGE_VERSION, 1.244 + engines: {steam: {syncID: engine.syncID, 1.245 + version: engine.version}} 1.246 + }); 1.247 + let server = sync_httpd_setup({ 1.248 + "/1.1/johndoe/storage/meta/global": 1.249 + upd("meta", metaWBO.handler()), 1.250 + 1.251 + "/1.1/johndoe/storage/steam": 1.252 + upd("steam", new ServerWBO("steam", {}).handler()) 1.253 + }); 1.254 + setUp(server); 1.255 + 1.256 + // We need to be very careful how we do this, so that we don't trigger a 1.257 + // fresh start! 1.258 + try { 1.259 + _("Upload some keys to avoid a fresh start."); 1.260 + let wbo = Service.collectionKeys.generateNewKeysWBO(); 1.261 + wbo.encrypt(Service.identity.syncKeyBundle); 1.262 + do_check_eq(200, wbo.upload(Service.resource(Service.cryptoKeysURL)).status); 1.263 + 1.264 + _("Engine is disabled."); 1.265 + do_check_false(engine.enabled); 1.266 + 1.267 + _("Sync."); 1.268 + Service.sync(); 1.269 + 1.270 + _("Engine is enabled."); 1.271 + do_check_true(engine.enabled); 1.272 + 1.273 + _("Meta record still present."); 1.274 + do_check_eq(metaWBO.data.engines.steam.syncID, engine.syncID); 1.275 + } finally { 1.276 + Service.startOver(); 1.277 + server.stop(run_next_test); 1.278 + } 1.279 +}); 1.280 + 1.281 +add_test(function test_disabledRemotelyTwoClients() { 1.282 + _("Test: Engine is enabled locally and disabled on a remote client... with two clients."); 1.283 + Service.syncID = "abcdefghij"; 1.284 + let engine = Service.engineManager.get("steam"); 1.285 + let metaWBO = new ServerWBO("global", {syncID: Service.syncID, 1.286 + storageVersion: STORAGE_VERSION, 1.287 + engines: {}}); 1.288 + let server = sync_httpd_setup({ 1.289 + "/1.1/johndoe/storage/meta/global": 1.290 + upd("meta", metaWBO.handler()), 1.291 + 1.292 + "/1.1/johndoe/storage/steam": 1.293 + upd("steam", new ServerWBO("steam", {}).handler()) 1.294 + }); 1.295 + setUp(server); 1.296 + 1.297 + try { 1.298 + _("Enable engine locally."); 1.299 + Service._ignorePrefObserver = true; 1.300 + engine.enabled = true; 1.301 + Service._ignorePrefObserver = false; 1.302 + 1.303 + _("Sync."); 1.304 + Service.sync(); 1.305 + 1.306 + _("Disable engine by deleting from meta/global."); 1.307 + let d = metaWBO.data; 1.308 + delete d.engines["steam"]; 1.309 + metaWBO.payload = JSON.stringify(d); 1.310 + metaWBO.modified = Date.now() / 1000; 1.311 + 1.312 + _("Add a second client and verify that the local pref is changed."); 1.313 + Service.clientsEngine._store._remoteClients["foobar"] = {name: "foobar", type: "desktop"}; 1.314 + Service.sync(); 1.315 + 1.316 + _("Engine is disabled."); 1.317 + do_check_false(engine.enabled); 1.318 + 1.319 + } finally { 1.320 + Service.startOver(); 1.321 + server.stop(run_next_test); 1.322 + } 1.323 +}); 1.324 + 1.325 +add_test(function test_disabledRemotely() { 1.326 + _("Test: Engine is enabled locally and disabled on a remote client"); 1.327 + Service.syncID = "abcdefghij"; 1.328 + let engine = Service.engineManager.get("steam"); 1.329 + let metaWBO = new ServerWBO("global", {syncID: Service.syncID, 1.330 + storageVersion: STORAGE_VERSION, 1.331 + engines: {}}); 1.332 + let server = sync_httpd_setup({ 1.333 + "/1.1/johndoe/storage/meta/global": metaWBO.handler(), 1.334 + "/1.1/johndoe/storage/steam": new ServerWBO("steam", {}).handler() 1.335 + }); 1.336 + setUp(server); 1.337 + 1.338 + try { 1.339 + _("Enable engine locally."); 1.340 + Service._ignorePrefObserver = true; 1.341 + engine.enabled = true; 1.342 + Service._ignorePrefObserver = false; 1.343 + 1.344 + _("Sync."); 1.345 + Service.sync(); 1.346 + 1.347 + _("Engine is not disabled: only one client."); 1.348 + do_check_true(engine.enabled); 1.349 + 1.350 + } finally { 1.351 + Service.startOver(); 1.352 + server.stop(run_next_test); 1.353 + } 1.354 +}); 1.355 + 1.356 +add_test(function test_dependentEnginesEnabledLocally() { 1.357 + _("Test: Engine is disabled on remote clients and enabled locally"); 1.358 + Service.syncID = "abcdefghij"; 1.359 + let steamEngine = Service.engineManager.get("steam"); 1.360 + let stirlingEngine = Service.engineManager.get("stirling"); 1.361 + let metaWBO = new ServerWBO("global", {syncID: Service.syncID, 1.362 + storageVersion: STORAGE_VERSION, 1.363 + engines: {}}); 1.364 + let server = sync_httpd_setup({ 1.365 + "/1.1/johndoe/storage/meta/global": metaWBO.handler(), 1.366 + "/1.1/johndoe/storage/steam": new ServerWBO("steam", {}).handler(), 1.367 + "/1.1/johndoe/storage/stirling": new ServerWBO("stirling", {}).handler() 1.368 + }); 1.369 + setUp(server); 1.370 + 1.371 + try { 1.372 + _("Enable engine locally. Doing it on one is enough."); 1.373 + steamEngine.enabled = true; 1.374 + 1.375 + _("Sync."); 1.376 + Service.sync(); 1.377 + 1.378 + _("Meta record now contains the new engines."); 1.379 + do_check_true(!!metaWBO.data.engines.steam); 1.380 + do_check_true(!!metaWBO.data.engines.stirling); 1.381 + 1.382 + _("Engines continue to be enabled."); 1.383 + do_check_true(steamEngine.enabled); 1.384 + do_check_true(stirlingEngine.enabled); 1.385 + } finally { 1.386 + Service.startOver(); 1.387 + server.stop(run_next_test); 1.388 + } 1.389 +}); 1.390 + 1.391 +add_test(function test_dependentEnginesDisabledLocally() { 1.392 + _("Test: Two dependent engines are enabled on remote clients and disabled locally"); 1.393 + Service.syncID = "abcdefghij"; 1.394 + let steamEngine = Service.engineManager.get("steam"); 1.395 + let stirlingEngine = Service.engineManager.get("stirling"); 1.396 + let metaWBO = new ServerWBO("global", { 1.397 + syncID: Service.syncID, 1.398 + storageVersion: STORAGE_VERSION, 1.399 + engines: {steam: {syncID: steamEngine.syncID, 1.400 + version: steamEngine.version}, 1.401 + stirling: {syncID: stirlingEngine.syncID, 1.402 + version: stirlingEngine.version}} 1.403 + }); 1.404 + 1.405 + let steamCollection = new ServerWBO("steam", PAYLOAD); 1.406 + let stirlingCollection = new ServerWBO("stirling", PAYLOAD); 1.407 + 1.408 + let server = sync_httpd_setup({ 1.409 + "/1.1/johndoe/storage/meta/global": metaWBO.handler(), 1.410 + "/1.1/johndoe/storage/steam": steamCollection.handler(), 1.411 + "/1.1/johndoe/storage/stirling": stirlingCollection.handler() 1.412 + }); 1.413 + setUp(server); 1.414 + 1.415 + try { 1.416 + _("Disable engines locally. Doing it on one is enough."); 1.417 + Service._ignorePrefObserver = true; 1.418 + steamEngine.enabled = true; 1.419 + do_check_true(stirlingEngine.enabled); 1.420 + Service._ignorePrefObserver = false; 1.421 + steamEngine.enabled = false; 1.422 + do_check_false(stirlingEngine.enabled); 1.423 + 1.424 + _("Sync."); 1.425 + Service.sync(); 1.426 + 1.427 + _("Meta record no longer contains engines."); 1.428 + do_check_false(!!metaWBO.data.engines.steam); 1.429 + do_check_false(!!metaWBO.data.engines.stirling); 1.430 + 1.431 + _("Server records are wiped."); 1.432 + do_check_eq(steamCollection.payload, undefined); 1.433 + do_check_eq(stirlingCollection.payload, undefined); 1.434 + 1.435 + _("Engines continue to be disabled."); 1.436 + do_check_false(steamEngine.enabled); 1.437 + do_check_false(stirlingEngine.enabled); 1.438 + } finally { 1.439 + Service.startOver(); 1.440 + server.stop(run_next_test); 1.441 + } 1.442 +});