Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* Any copyright is dedicated to the Public Domain.
2 http://creativecommons.org/publicdomain/zero/1.0/ */
4 Cu.import("resource://services-sync/engines/clients.js");
5 Cu.import("resource://services-sync/constants.js");
6 Cu.import("resource://services-sync/engines.js");
7 Cu.import("resource://services-sync/keys.js");
8 Cu.import("resource://services-sync/policies.js");
9 Cu.import("resource://services-sync/service.js");
10 Cu.import("resource://services-sync/status.js");
11 Cu.import("resource://services-sync/util.js");
12 Cu.import("resource://testing-common/services/sync/utils.js");
13 Cu.import("resource://gre/modules/FileUtils.jsm");
15 const FAKE_SERVER_URL = "http://dummy:9000/";
16 const logsdir = FileUtils.getDir("ProfD", ["weave", "logs"], true);
17 const LOG_PREFIX_SUCCESS = "success-";
18 const LOG_PREFIX_ERROR = "error-";
20 const PROLONGED_ERROR_DURATION =
21 (Svc.Prefs.get('errorhandler.networkFailureReportTimeout') * 2) * 1000;
23 const NON_PROLONGED_ERROR_DURATION =
24 (Svc.Prefs.get('errorhandler.networkFailureReportTimeout') / 2) * 1000;
26 Service.engineManager.clear();
28 function setLastSync(lastSyncValue) {
29 Svc.Prefs.set("lastSync", (new Date(Date.now() - lastSyncValue)).toString());
30 }
32 function CatapultEngine() {
33 SyncEngine.call(this, "Catapult", Service);
34 }
35 CatapultEngine.prototype = {
36 __proto__: SyncEngine.prototype,
37 exception: null, // tests fill this in
38 _sync: function _sync() {
39 if (this.exception) {
40 throw this.exception;
41 }
42 }
43 };
45 let engineManager = Service.engineManager;
46 engineManager.register(CatapultEngine);
48 // This relies on Service/ErrorHandler being a singleton. Fixing this will take
49 // a lot of work.
50 let errorHandler = Service.errorHandler;
52 function run_test() {
53 initTestLogging("Trace");
55 Log.repository.getLogger("Sync.Service").level = Log.Level.Trace;
56 Log.repository.getLogger("Sync.SyncScheduler").level = Log.Level.Trace;
57 Log.repository.getLogger("Sync.ErrorHandler").level = Log.Level.Trace;
59 ensureLegacyIdentityManager();
61 run_next_test();
62 }
64 function generateCredentialsChangedFailure() {
65 // Make sync fail due to changed credentials. We simply re-encrypt
66 // the keys with a different Sync Key, without changing the local one.
67 let newSyncKeyBundle = new SyncKeyBundle("johndoe", "23456234562345623456234562");
68 let keys = Service.collectionKeys.asWBO();
69 keys.encrypt(newSyncKeyBundle);
70 keys.upload(Service.resource(Service.cryptoKeysURL));
71 }
73 function service_unavailable(request, response) {
74 let body = "Service Unavailable";
75 response.setStatusLine(request.httpVersion, 503, "Service Unavailable");
76 response.setHeader("Retry-After", "42");
77 response.bodyOutputStream.write(body, body.length);
78 }
80 function sync_httpd_setup() {
81 let global = new ServerWBO("global", {
82 syncID: Service.syncID,
83 storageVersion: STORAGE_VERSION,
84 engines: {clients: {version: Service.clientsEngine.version,
85 syncID: Service.clientsEngine.syncID},
86 catapult: {version: engineManager.get("catapult").version,
87 syncID: engineManager.get("catapult").syncID}}
88 });
89 let clientsColl = new ServerCollection({}, true);
91 // Tracking info/collections.
92 let collectionsHelper = track_collections_helper();
93 let upd = collectionsHelper.with_updated_collection;
95 let handler_401 = httpd_handler(401, "Unauthorized");
96 return httpd_setup({
97 // Normal server behaviour.
98 "/1.1/johndoe/storage/meta/global": upd("meta", global.handler()),
99 "/1.1/johndoe/info/collections": collectionsHelper.handler,
100 "/1.1/johndoe/storage/crypto/keys":
101 upd("crypto", (new ServerWBO("keys")).handler()),
102 "/1.1/johndoe/storage/clients": upd("clients", clientsColl.handler()),
104 // Credentials are wrong or node reallocated.
105 "/1.1/janedoe/storage/meta/global": handler_401,
106 "/1.1/janedoe/info/collections": handler_401,
108 // Maintenance or overloaded (503 + Retry-After) at info/collections.
109 "/maintenance/1.1/broken.info/info/collections": service_unavailable,
111 // Maintenance or overloaded (503 + Retry-After) at meta/global.
112 "/maintenance/1.1/broken.meta/storage/meta/global": service_unavailable,
113 "/maintenance/1.1/broken.meta/info/collections": collectionsHelper.handler,
115 // Maintenance or overloaded (503 + Retry-After) at crypto/keys.
116 "/maintenance/1.1/broken.keys/storage/meta/global": upd("meta", global.handler()),
117 "/maintenance/1.1/broken.keys/info/collections": collectionsHelper.handler,
118 "/maintenance/1.1/broken.keys/storage/crypto/keys": service_unavailable,
120 // Maintenance or overloaded (503 + Retry-After) at wiping collection.
121 "/maintenance/1.1/broken.wipe/info/collections": collectionsHelper.handler,
122 "/maintenance/1.1/broken.wipe/storage/meta/global": upd("meta", global.handler()),
123 "/maintenance/1.1/broken.wipe/storage/crypto/keys":
124 upd("crypto", (new ServerWBO("keys")).handler()),
125 "/maintenance/1.1/broken.wipe/storage": service_unavailable,
126 "/maintenance/1.1/broken.wipe/storage/clients": upd("clients", clientsColl.handler()),
127 "/maintenance/1.1/broken.wipe/storage/catapult": service_unavailable
128 });
129 }
131 function setUp(server) {
132 return configureIdentity({username: "johndoe"}).then(
133 () => {
134 Service.serverURL = server.baseURI + "/";
135 Service.clusterURL = server.baseURI + "/";
136 }
137 ).then(
138 () => generateAndUploadKeys()
139 );
140 }
142 function generateAndUploadKeys() {
143 generateNewKeys(Service.collectionKeys);
144 let serverKeys = Service.collectionKeys.asWBO("crypto", "keys");
145 serverKeys.encrypt(Service.identity.syncKeyBundle);
146 return serverKeys.upload(Service.resource(Service.cryptoKeysURL)).success;
147 }
149 function clean() {
150 Service.startOver();
151 Status.resetSync();
152 Status.resetBackoff();
153 errorHandler.didReportProlongedError = false;
154 }
156 add_identity_test(this, function test_401_logout() {
157 let server = sync_httpd_setup();
158 yield setUp(server);
160 // By calling sync, we ensure we're logged in.
161 Service.sync();
162 do_check_eq(Status.sync, SYNC_SUCCEEDED);
163 do_check_true(Service.isLoggedIn);
165 let deferred = Promise.defer();
166 Svc.Obs.add("weave:service:sync:error", onSyncError);
167 function onSyncError() {
168 _("Got weave:service:sync:error in first sync.");
169 Svc.Obs.remove("weave:service:sync:error", onSyncError);
171 // Wait for the automatic next sync.
172 function onLoginError() {
173 _("Got weave:service:login:error in second sync.");
174 Svc.Obs.remove("weave:service:login:error", onLoginError);
176 do_check_eq(Status.login, LOGIN_FAILED_LOGIN_REJECTED);
177 do_check_false(Service.isLoggedIn);
179 // Clean up.
180 Utils.nextTick(function () {
181 Service.startOver();
182 server.stop(deferred.resolve);
183 });
184 }
185 Svc.Obs.add("weave:service:login:error", onLoginError);
186 }
188 // Make sync fail due to login rejected.
189 yield configureIdentity({username: "janedoe"});
190 Service._updateCachedURLs();
192 _("Starting first sync.");
193 Service.sync();
194 _("First sync done.");
195 yield deferred.promise;
196 });
198 add_identity_test(this, function test_credentials_changed_logout() {
199 let server = sync_httpd_setup();
200 yield setUp(server);
202 // By calling sync, we ensure we're logged in.
203 Service.sync();
204 do_check_eq(Status.sync, SYNC_SUCCEEDED);
205 do_check_true(Service.isLoggedIn);
207 generateCredentialsChangedFailure();
208 Service.sync();
210 do_check_eq(Status.sync, CREDENTIALS_CHANGED);
211 do_check_false(Service.isLoggedIn);
213 // Clean up.
214 Service.startOver();
215 let deferred = Promise.defer();
216 server.stop(deferred.resolve);
217 yield deferred.promise;
218 });
220 add_identity_test(this, function test_no_lastSync_pref() {
221 // Test reported error.
222 Status.resetSync();
223 errorHandler.dontIgnoreErrors = true;
224 Status.sync = CREDENTIALS_CHANGED;
225 do_check_true(errorHandler.shouldReportError());
227 // Test unreported error.
228 Status.resetSync();
229 errorHandler.dontIgnoreErrors = true;
230 Status.login = LOGIN_FAILED_NETWORK_ERROR;
231 do_check_true(errorHandler.shouldReportError());
233 });
235 add_identity_test(this, function test_shouldReportError() {
236 Status.login = MASTER_PASSWORD_LOCKED;
237 do_check_false(errorHandler.shouldReportError());
239 // Give ourselves a clusterURL so that the temporary 401 no-error situation
240 // doesn't come into play.
241 Service.serverURL = FAKE_SERVER_URL;
242 Service.clusterURL = FAKE_SERVER_URL;
244 // Test dontIgnoreErrors, non-network, non-prolonged, login error reported
245 Status.resetSync();
246 setLastSync(NON_PROLONGED_ERROR_DURATION);
247 errorHandler.dontIgnoreErrors = true;
248 Status.login = LOGIN_FAILED_NO_PASSWORD;
249 do_check_true(errorHandler.shouldReportError());
251 // Test dontIgnoreErrors, non-network, non-prolonged, sync error reported
252 Status.resetSync();
253 setLastSync(NON_PROLONGED_ERROR_DURATION);
254 errorHandler.dontIgnoreErrors = true;
255 Status.sync = CREDENTIALS_CHANGED;
256 do_check_true(errorHandler.shouldReportError());
258 // Test dontIgnoreErrors, non-network, prolonged, login error reported
259 Status.resetSync();
260 setLastSync(PROLONGED_ERROR_DURATION);
261 errorHandler.dontIgnoreErrors = true;
262 Status.login = LOGIN_FAILED_NO_PASSWORD;
263 do_check_true(errorHandler.shouldReportError());
265 // Test dontIgnoreErrors, non-network, prolonged, sync error reported
266 Status.resetSync();
267 setLastSync(PROLONGED_ERROR_DURATION);
268 errorHandler.dontIgnoreErrors = true;
269 Status.sync = CREDENTIALS_CHANGED;
270 do_check_true(errorHandler.shouldReportError());
272 // Test dontIgnoreErrors, network, non-prolonged, login error reported
273 Status.resetSync();
274 setLastSync(NON_PROLONGED_ERROR_DURATION);
275 errorHandler.dontIgnoreErrors = true;
276 Status.login = LOGIN_FAILED_NETWORK_ERROR;
277 do_check_true(errorHandler.shouldReportError());
279 // Test dontIgnoreErrors, network, non-prolonged, sync error reported
280 Status.resetSync();
281 setLastSync(NON_PROLONGED_ERROR_DURATION);
282 errorHandler.dontIgnoreErrors = true;
283 Status.sync = LOGIN_FAILED_NETWORK_ERROR;
284 do_check_true(errorHandler.shouldReportError());
286 // Test dontIgnoreErrors, network, prolonged, login error reported
287 Status.resetSync();
288 setLastSync(PROLONGED_ERROR_DURATION);
289 errorHandler.dontIgnoreErrors = true;
290 Status.login = LOGIN_FAILED_NETWORK_ERROR;
291 do_check_true(errorHandler.shouldReportError());
293 // Test dontIgnoreErrors, network, prolonged, sync error reported
294 Status.resetSync();
295 setLastSync(PROLONGED_ERROR_DURATION);
296 errorHandler.dontIgnoreErrors = true;
297 Status.sync = LOGIN_FAILED_NETWORK_ERROR;
298 do_check_true(errorHandler.shouldReportError());
300 // Test non-network, prolonged, login error reported
301 do_check_false(errorHandler.didReportProlongedError);
302 Status.resetSync();
303 setLastSync(PROLONGED_ERROR_DURATION);
304 errorHandler.dontIgnoreErrors = false;
305 Status.login = LOGIN_FAILED_NO_PASSWORD;
306 do_check_true(errorHandler.shouldReportError());
307 do_check_true(errorHandler.didReportProlongedError);
309 // Second time with prolonged error and without resetting
310 // didReportProlongedError, sync error should not be reported.
311 Status.resetSync();
312 setLastSync(PROLONGED_ERROR_DURATION);
313 errorHandler.dontIgnoreErrors = false;
314 Status.login = LOGIN_FAILED_NO_PASSWORD;
315 do_check_false(errorHandler.shouldReportError());
316 do_check_true(errorHandler.didReportProlongedError);
318 // Test non-network, prolonged, sync error reported
319 Status.resetSync();
320 setLastSync(PROLONGED_ERROR_DURATION);
321 errorHandler.dontIgnoreErrors = false;
322 errorHandler.didReportProlongedError = false;
323 Status.sync = CREDENTIALS_CHANGED;
324 do_check_true(errorHandler.shouldReportError());
325 do_check_true(errorHandler.didReportProlongedError);
326 errorHandler.didReportProlongedError = false;
328 // Test network, prolonged, login error reported
329 Status.resetSync();
330 setLastSync(PROLONGED_ERROR_DURATION);
331 errorHandler.dontIgnoreErrors = false;
332 Status.login = LOGIN_FAILED_NETWORK_ERROR;
333 do_check_true(errorHandler.shouldReportError());
334 do_check_true(errorHandler.didReportProlongedError);
335 errorHandler.didReportProlongedError = false;
337 // Test network, prolonged, sync error reported
338 Status.resetSync();
339 setLastSync(PROLONGED_ERROR_DURATION);
340 errorHandler.dontIgnoreErrors = false;
341 Status.sync = LOGIN_FAILED_NETWORK_ERROR;
342 do_check_true(errorHandler.shouldReportError());
343 do_check_true(errorHandler.didReportProlongedError);
344 errorHandler.didReportProlongedError = false;
346 // Test non-network, non-prolonged, login error reported
347 Status.resetSync();
348 setLastSync(NON_PROLONGED_ERROR_DURATION);
349 errorHandler.dontIgnoreErrors = false;
350 Status.login = LOGIN_FAILED_NO_PASSWORD;
351 do_check_true(errorHandler.shouldReportError());
352 do_check_false(errorHandler.didReportProlongedError);
354 // Test non-network, non-prolonged, sync error reported
355 Status.resetSync();
356 setLastSync(NON_PROLONGED_ERROR_DURATION);
357 errorHandler.dontIgnoreErrors = false;
358 Status.sync = CREDENTIALS_CHANGED;
359 do_check_true(errorHandler.shouldReportError());
360 do_check_false(errorHandler.didReportProlongedError);
362 // Test network, non-prolonged, login error reported
363 Status.resetSync();
364 setLastSync(NON_PROLONGED_ERROR_DURATION);
365 errorHandler.dontIgnoreErrors = false;
366 Status.login = LOGIN_FAILED_NETWORK_ERROR;
367 do_check_false(errorHandler.shouldReportError());
368 do_check_false(errorHandler.didReportProlongedError);
370 // Test network, non-prolonged, sync error reported
371 Status.resetSync();
372 setLastSync(NON_PROLONGED_ERROR_DURATION);
373 errorHandler.dontIgnoreErrors = false;
374 Status.sync = LOGIN_FAILED_NETWORK_ERROR;
375 do_check_false(errorHandler.shouldReportError());
376 do_check_false(errorHandler.didReportProlongedError);
378 // Test server maintenance, sync errors are not reported
379 Status.resetSync();
380 setLastSync(NON_PROLONGED_ERROR_DURATION);
381 errorHandler.dontIgnoreErrors = false;
382 Status.sync = SERVER_MAINTENANCE;
383 do_check_false(errorHandler.shouldReportError());
384 do_check_false(errorHandler.didReportProlongedError);
386 // Test server maintenance, login errors are not reported
387 Status.resetSync();
388 setLastSync(NON_PROLONGED_ERROR_DURATION);
389 errorHandler.dontIgnoreErrors = false;
390 Status.login = SERVER_MAINTENANCE;
391 do_check_false(errorHandler.shouldReportError());
392 do_check_false(errorHandler.didReportProlongedError);
394 // Test prolonged, server maintenance, sync errors are reported
395 Status.resetSync();
396 setLastSync(PROLONGED_ERROR_DURATION);
397 errorHandler.dontIgnoreErrors = false;
398 Status.sync = SERVER_MAINTENANCE;
399 do_check_true(errorHandler.shouldReportError());
400 do_check_true(errorHandler.didReportProlongedError);
401 errorHandler.didReportProlongedError = false;
403 // Test prolonged, server maintenance, login errors are reported
404 Status.resetSync();
405 setLastSync(PROLONGED_ERROR_DURATION);
406 errorHandler.dontIgnoreErrors = false;
407 Status.login = SERVER_MAINTENANCE;
408 do_check_true(errorHandler.shouldReportError());
409 do_check_true(errorHandler.didReportProlongedError);
410 errorHandler.didReportProlongedError = false;
412 // Test dontIgnoreErrors, server maintenance, sync errors are reported
413 Status.resetSync();
414 setLastSync(NON_PROLONGED_ERROR_DURATION);
415 errorHandler.dontIgnoreErrors = true;
416 Status.sync = SERVER_MAINTENANCE;
417 do_check_true(errorHandler.shouldReportError());
418 // dontIgnoreErrors means we don't set didReportProlongedError
419 do_check_false(errorHandler.didReportProlongedError);
421 // Test dontIgnoreErrors, server maintenance, login errors are reported
422 Status.resetSync();
423 setLastSync(NON_PROLONGED_ERROR_DURATION);
424 errorHandler.dontIgnoreErrors = true;
425 Status.login = SERVER_MAINTENANCE;
426 do_check_true(errorHandler.shouldReportError());
427 do_check_false(errorHandler.didReportProlongedError);
429 // Test dontIgnoreErrors, prolonged, server maintenance,
430 // sync errors are reported
431 Status.resetSync();
432 setLastSync(PROLONGED_ERROR_DURATION);
433 errorHandler.dontIgnoreErrors = true;
434 Status.sync = SERVER_MAINTENANCE;
435 do_check_true(errorHandler.shouldReportError());
436 do_check_false(errorHandler.didReportProlongedError);
438 // Test dontIgnoreErrors, prolonged, server maintenance,
439 // login errors are reported
440 Status.resetSync();
441 setLastSync(PROLONGED_ERROR_DURATION);
442 errorHandler.dontIgnoreErrors = true;
443 Status.login = SERVER_MAINTENANCE;
444 do_check_true(errorHandler.shouldReportError());
445 do_check_false(errorHandler.didReportProlongedError);
446 });
448 add_identity_test(this, function test_shouldReportError_master_password() {
449 _("Test error ignored due to locked master password");
450 let server = sync_httpd_setup();
451 yield setUp(server);
453 // Monkey patch Service.verifyLogin to imitate
454 // master password being locked.
455 Service._verifyLogin = Service.verifyLogin;
456 Service.verifyLogin = function () {
457 Status.login = MASTER_PASSWORD_LOCKED;
458 return false;
459 };
461 setLastSync(NON_PROLONGED_ERROR_DURATION);
462 Service.sync();
463 do_check_false(errorHandler.shouldReportError());
465 // Clean up.
466 Service.verifyLogin = Service._verifyLogin;
467 clean();
468 let deferred = Promise.defer();
469 server.stop(deferred.resolve);
470 yield deferred.promise;
471 });
473 // XXX - how to arrange for 'Service.identity.basicPassword = null;' in
474 // an fxaccounts environment?
475 add_task(function test_login_syncAndReportErrors_non_network_error() {
476 // Test non-network errors are reported
477 // when calling syncAndReportErrors
478 let server = sync_httpd_setup();
479 yield setUp(server);
480 Service.identity.basicPassword = null;
482 let deferred = Promise.defer();
483 Svc.Obs.add("weave:ui:login:error", function onSyncError() {
484 Svc.Obs.remove("weave:ui:login:error", onSyncError);
485 do_check_eq(Status.login, LOGIN_FAILED_NO_PASSWORD);
487 clean();
488 server.stop(deferred.resolve);
489 });
491 setLastSync(NON_PROLONGED_ERROR_DURATION);
492 errorHandler.syncAndReportErrors();
493 yield deferred.promise;
494 });
496 add_identity_test(this, function test_sync_syncAndReportErrors_non_network_error() {
497 // Test non-network errors are reported
498 // when calling syncAndReportErrors
499 let server = sync_httpd_setup();
500 yield setUp(server);
502 // By calling sync, we ensure we're logged in.
503 Service.sync();
504 do_check_eq(Status.sync, SYNC_SUCCEEDED);
505 do_check_true(Service.isLoggedIn);
507 generateCredentialsChangedFailure();
509 let deferred = Promise.defer();
510 Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
511 Svc.Obs.remove("weave:ui:sync:error", onSyncError);
512 do_check_eq(Status.sync, CREDENTIALS_CHANGED);
514 clean();
515 server.stop(deferred.resolve);
516 });
518 setLastSync(NON_PROLONGED_ERROR_DURATION);
519 errorHandler.syncAndReportErrors();
520 yield deferred.promise;
521 });
523 // XXX - how to arrange for 'Service.identity.basicPassword = null;' in
524 // an fxaccounts environment?
525 add_task(function test_login_syncAndReportErrors_prolonged_non_network_error() {
526 // Test prolonged, non-network errors are
527 // reported when calling syncAndReportErrors.
528 let server = sync_httpd_setup();
529 yield setUp(server);
530 Service.identity.basicPassword = null;
532 let deferred = Promise.defer();
533 Svc.Obs.add("weave:ui:login:error", function onSyncError() {
534 Svc.Obs.remove("weave:ui:login:error", onSyncError);
535 do_check_eq(Status.login, LOGIN_FAILED_NO_PASSWORD);
537 clean();
538 server.stop(deferred.resolve);
539 });
541 setLastSync(PROLONGED_ERROR_DURATION);
542 errorHandler.syncAndReportErrors();
543 yield deferred.promise;
544 });
546 add_identity_test(this, function test_sync_syncAndReportErrors_prolonged_non_network_error() {
547 // Test prolonged, non-network errors are
548 // reported when calling syncAndReportErrors.
549 let server = sync_httpd_setup();
550 yield setUp(server);
552 // By calling sync, we ensure we're logged in.
553 Service.sync();
554 do_check_eq(Status.sync, SYNC_SUCCEEDED);
555 do_check_true(Service.isLoggedIn);
557 generateCredentialsChangedFailure();
559 let deferred = Promise.defer();
560 Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
561 Svc.Obs.remove("weave:ui:sync:error", onSyncError);
562 do_check_eq(Status.sync, CREDENTIALS_CHANGED);
564 clean();
565 server.stop(deferred.resolve);
566 });
568 setLastSync(PROLONGED_ERROR_DURATION);
569 errorHandler.syncAndReportErrors();
570 yield deferred.promise;
571 });
573 add_identity_test(this, function test_login_syncAndReportErrors_network_error() {
574 // Test network errors are reported when calling syncAndReportErrors.
575 yield configureIdentity({username: "broken.wipe"});
576 Service.serverURL = FAKE_SERVER_URL;
577 Service.clusterURL = FAKE_SERVER_URL;
579 let deferred = Promise.defer();
580 Svc.Obs.add("weave:ui:login:error", function onSyncError() {
581 Svc.Obs.remove("weave:ui:login:error", onSyncError);
582 do_check_eq(Status.login, LOGIN_FAILED_NETWORK_ERROR);
584 clean();
585 deferred.resolve();
586 });
588 setLastSync(NON_PROLONGED_ERROR_DURATION);
589 errorHandler.syncAndReportErrors();
590 yield deferred.promise;
591 });
594 add_test(function test_sync_syncAndReportErrors_network_error() {
595 // Test network errors are reported when calling syncAndReportErrors.
596 Services.io.offline = true;
598 Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
599 Svc.Obs.remove("weave:ui:sync:error", onSyncError);
600 do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
602 Services.io.offline = false;
603 clean();
604 run_next_test();
605 });
607 setLastSync(NON_PROLONGED_ERROR_DURATION);
608 errorHandler.syncAndReportErrors();
609 });
611 add_identity_test(this, function test_login_syncAndReportErrors_prolonged_network_error() {
612 // Test prolonged, network errors are reported
613 // when calling syncAndReportErrors.
614 yield configureIdentity({username: "johndoe"});
616 Service.serverURL = FAKE_SERVER_URL;
617 Service.clusterURL = FAKE_SERVER_URL;
619 let deferred = Promise.defer();
620 Svc.Obs.add("weave:ui:login:error", function onSyncError() {
621 Svc.Obs.remove("weave:ui:login:error", onSyncError);
622 do_check_eq(Status.login, LOGIN_FAILED_NETWORK_ERROR);
624 clean();
625 deferred.resolve();
626 });
628 setLastSync(PROLONGED_ERROR_DURATION);
629 errorHandler.syncAndReportErrors();
630 yield deferred.promise;
631 });
633 add_test(function test_sync_syncAndReportErrors_prolonged_network_error() {
634 // Test prolonged, network errors are reported
635 // when calling syncAndReportErrors.
636 Services.io.offline = true;
638 Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
639 Svc.Obs.remove("weave:ui:sync:error", onSyncError);
640 do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
642 Services.io.offline = false;
643 clean();
644 run_next_test();
645 });
647 setLastSync(PROLONGED_ERROR_DURATION);
648 errorHandler.syncAndReportErrors();
649 });
651 add_task(function test_login_prolonged_non_network_error() {
652 // Test prolonged, non-network errors are reported
653 let server = sync_httpd_setup();
654 yield setUp(server);
655 Service.identity.basicPassword = null;
657 let deferred = Promise.defer();
658 Svc.Obs.add("weave:ui:login:error", function onSyncError() {
659 Svc.Obs.remove("weave:ui:login:error", onSyncError);
660 do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
661 do_check_true(errorHandler.didReportProlongedError);
663 clean();
664 server.stop(deferred.resolve);
665 });
667 setLastSync(PROLONGED_ERROR_DURATION);
668 Service.sync();
669 yield deferred.promise;
670 });
672 add_task(function test_sync_prolonged_non_network_error() {
673 // Test prolonged, non-network errors are reported
674 let server = sync_httpd_setup();
675 yield setUp(server);
677 // By calling sync, we ensure we're logged in.
678 Service.sync();
679 do_check_eq(Status.sync, SYNC_SUCCEEDED);
680 do_check_true(Service.isLoggedIn);
682 generateCredentialsChangedFailure();
684 let deferred = Promise.defer();
685 Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
686 Svc.Obs.remove("weave:ui:sync:error", onSyncError);
687 do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
688 do_check_true(errorHandler.didReportProlongedError);
690 clean();
691 server.stop(deferred.resolve);
692 });
694 setLastSync(PROLONGED_ERROR_DURATION);
695 Service.sync();
696 yield deferred.promise;
697 });
699 add_identity_test(this, function test_login_prolonged_network_error() {
700 // Test prolonged, network errors are reported
701 yield configureIdentity({username: "johndoe"});
702 Service.serverURL = FAKE_SERVER_URL;
703 Service.clusterURL = FAKE_SERVER_URL;
705 let deferred = Promise.defer();
706 Svc.Obs.add("weave:ui:login:error", function onSyncError() {
707 Svc.Obs.remove("weave:ui:login:error", onSyncError);
708 do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
709 do_check_true(errorHandler.didReportProlongedError);
711 clean();
712 deferred.resolve();
713 });
715 setLastSync(PROLONGED_ERROR_DURATION);
716 Service.sync();
717 yield deferred.promise;
718 });
720 add_test(function test_sync_prolonged_network_error() {
721 // Test prolonged, network errors are reported
722 Services.io.offline = true;
724 Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
725 Svc.Obs.remove("weave:ui:sync:error", onSyncError);
726 do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
727 do_check_true(errorHandler.didReportProlongedError);
729 Services.io.offline = false;
730 clean();
731 run_next_test();
732 });
734 setLastSync(PROLONGED_ERROR_DURATION);
735 Service.sync();
736 });
738 add_task(function test_login_non_network_error() {
739 // Test non-network errors are reported
740 let server = sync_httpd_setup();
741 yield setUp(server);
742 Service.identity.basicPassword = null;
744 let deferred = Promise.defer();
745 Svc.Obs.add("weave:ui:login:error", function onSyncError() {
746 Svc.Obs.remove("weave:ui:login:error", onSyncError);
747 do_check_eq(Status.login, LOGIN_FAILED_NO_PASSWORD);
748 do_check_false(errorHandler.didReportProlongedError);
750 clean();
751 server.stop(deferred.resolve);
752 });
754 setLastSync(NON_PROLONGED_ERROR_DURATION);
755 Service.sync();
756 yield deferred.promise;
757 });
759 add_task(function test_sync_non_network_error() {
760 // Test non-network errors are reported
761 let server = sync_httpd_setup();
762 yield setUp(server);
764 // By calling sync, we ensure we're logged in.
765 Service.sync();
766 do_check_eq(Status.sync, SYNC_SUCCEEDED);
767 do_check_true(Service.isLoggedIn);
769 generateCredentialsChangedFailure();
771 let deferred = Promise.defer();
772 Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
773 Svc.Obs.remove("weave:ui:sync:error", onSyncError);
774 do_check_eq(Status.sync, CREDENTIALS_CHANGED);
775 do_check_false(errorHandler.didReportProlongedError);
777 clean();
778 server.stop(deferred.resolve);
779 });
781 setLastSync(NON_PROLONGED_ERROR_DURATION);
782 Service.sync();
783 yield deferred.promise;
784 });
786 add_identity_test(this, function test_login_network_error() {
787 yield configureIdentity({username: "johndoe"});
788 Service.serverURL = FAKE_SERVER_URL;
789 Service.clusterURL = FAKE_SERVER_URL;
791 let deferred = Promise.defer();
792 // Test network errors are not reported.
793 Svc.Obs.add("weave:ui:clear-error", function onClearError() {
794 Svc.Obs.remove("weave:ui:clear-error", onClearError);
796 do_check_eq(Status.login, LOGIN_FAILED_NETWORK_ERROR);
797 do_check_false(errorHandler.didReportProlongedError);
799 Services.io.offline = false;
800 clean();
801 deferred.resolve()
802 });
804 setLastSync(NON_PROLONGED_ERROR_DURATION);
805 Service.sync();
806 yield deferred.promise;
807 });
809 add_test(function test_sync_network_error() {
810 // Test network errors are not reported.
811 Services.io.offline = true;
813 Svc.Obs.add("weave:ui:sync:finish", function onUIUpdate() {
814 Svc.Obs.remove("weave:ui:sync:finish", onUIUpdate);
815 do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
816 do_check_false(errorHandler.didReportProlongedError);
818 Services.io.offline = false;
819 clean();
820 run_next_test();
821 });
823 setLastSync(NON_PROLONGED_ERROR_DURATION);
824 Service.sync();
825 });
827 add_identity_test(this, function test_sync_server_maintenance_error() {
828 // Test server maintenance errors are not reported.
829 let server = sync_httpd_setup();
830 yield setUp(server);
832 const BACKOFF = 42;
833 let engine = engineManager.get("catapult");
834 engine.enabled = true;
835 engine.exception = {status: 503,
836 headers: {"retry-after": BACKOFF}};
838 function onSyncError() {
839 do_throw("Shouldn't get here!");
840 }
841 Svc.Obs.add("weave:ui:sync:error", onSyncError);
843 do_check_eq(Status.service, STATUS_OK);
845 let deferred = Promise.defer();
846 Svc.Obs.add("weave:ui:sync:finish", function onSyncFinish() {
847 Svc.Obs.remove("weave:ui:sync:finish", onSyncFinish);
849 do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
850 do_check_eq(Status.sync, SERVER_MAINTENANCE);
851 do_check_false(errorHandler.didReportProlongedError);
853 Svc.Obs.remove("weave:ui:sync:error", onSyncError);
854 clean();
855 server.stop(deferred.resolve);
856 });
858 setLastSync(NON_PROLONGED_ERROR_DURATION);
859 Service.sync();
860 yield deferred.promise;
861 });
863 add_identity_test(this, function test_info_collections_login_server_maintenance_error() {
864 // Test info/collections server maintenance errors are not reported.
865 let server = sync_httpd_setup();
866 yield setUp(server);
868 Service.username = "broken.info";
869 yield configureIdentity({username: "broken.info"});
870 Service.serverURL = server.baseURI + "/maintenance/";
871 Service.clusterURL = server.baseURI + "/maintenance/";
873 let backoffInterval;
874 Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
875 Svc.Obs.remove("weave:service:backoff:interval", observe);
876 backoffInterval = subject;
877 });
879 function onUIUpdate() {
880 do_throw("Shouldn't experience UI update!");
881 }
882 Svc.Obs.add("weave:ui:login:error", onUIUpdate);
884 do_check_false(Status.enforceBackoff);
885 do_check_eq(Status.service, STATUS_OK);
887 let deferred = Promise.defer();
888 Svc.Obs.add("weave:ui:clear-error", function onLoginFinish() {
889 Svc.Obs.remove("weave:ui:clear-error", onLoginFinish);
891 do_check_true(Status.enforceBackoff);
892 do_check_eq(backoffInterval, 42);
893 do_check_eq(Status.service, LOGIN_FAILED);
894 do_check_eq(Status.login, SERVER_MAINTENANCE);
895 do_check_false(errorHandler.didReportProlongedError);
897 Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
898 clean();
899 server.stop(deferred.resolve);
900 });
902 setLastSync(NON_PROLONGED_ERROR_DURATION);
903 Service.sync();
904 yield deferred.promise;
905 });
907 add_identity_test(this, function test_meta_global_login_server_maintenance_error() {
908 // Test meta/global server maintenance errors are not reported.
909 let server = sync_httpd_setup();
910 yield setUp(server);
912 yield configureIdentity({username: "broken.meta"});
913 Service.serverURL = server.baseURI + "/maintenance/";
914 Service.clusterURL = server.baseURI + "/maintenance/";
916 let backoffInterval;
917 Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
918 Svc.Obs.remove("weave:service:backoff:interval", observe);
919 backoffInterval = subject;
920 });
922 function onUIUpdate() {
923 do_throw("Shouldn't get here!");
924 }
925 Svc.Obs.add("weave:ui:login:error", onUIUpdate);
927 do_check_false(Status.enforceBackoff);
928 do_check_eq(Status.service, STATUS_OK);
930 let deferred = Promise.defer();
931 Svc.Obs.add("weave:ui:clear-error", function onLoginFinish() {
932 Svc.Obs.remove("weave:ui:clear-error", onLoginFinish);
934 do_check_true(Status.enforceBackoff);
935 do_check_eq(backoffInterval, 42);
936 do_check_eq(Status.service, LOGIN_FAILED);
937 do_check_eq(Status.login, SERVER_MAINTENANCE);
938 do_check_false(errorHandler.didReportProlongedError);
940 Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
941 clean();
942 server.stop(deferred.resolve);
943 });
945 setLastSync(NON_PROLONGED_ERROR_DURATION);
946 Service.sync();
947 yield deferred.promise;
948 });
950 add_identity_test(this, function test_crypto_keys_login_server_maintenance_error() {
951 // Test crypto/keys server maintenance errors are not reported.
952 let server = sync_httpd_setup();
953 yield setUp(server);
955 yield configureIdentity({username: "broken.keys"});
956 Service.serverURL = server.baseURI + "/maintenance/";
957 Service.clusterURL = server.baseURI + "/maintenance/";
959 // Force re-download of keys
960 Service.collectionKeys.clear();
962 let backoffInterval;
963 Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
964 Svc.Obs.remove("weave:service:backoff:interval", observe);
965 backoffInterval = subject;
966 });
968 function onUIUpdate() {
969 do_throw("Shouldn't get here!");
970 }
971 Svc.Obs.add("weave:ui:login:error", onUIUpdate);
973 do_check_false(Status.enforceBackoff);
974 do_check_eq(Status.service, STATUS_OK);
976 let deferred = Promise.defer();
977 Svc.Obs.add("weave:ui:clear-error", function onLoginFinish() {
978 Svc.Obs.remove("weave:ui:clear-error", onLoginFinish);
980 do_check_true(Status.enforceBackoff);
981 do_check_eq(backoffInterval, 42);
982 do_check_eq(Status.service, LOGIN_FAILED);
983 do_check_eq(Status.login, SERVER_MAINTENANCE);
984 do_check_false(errorHandler.didReportProlongedError);
986 Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
987 clean();
988 server.stop(deferred.resolve);
989 });
991 setLastSync(NON_PROLONGED_ERROR_DURATION);
992 Service.sync();
993 yield deferred.promise;
994 });
996 add_task(function test_sync_prolonged_server_maintenance_error() {
997 // Test prolonged server maintenance errors are reported.
998 let server = sync_httpd_setup();
999 yield setUp(server);
1001 const BACKOFF = 42;
1002 let engine = engineManager.get("catapult");
1003 engine.enabled = true;
1004 engine.exception = {status: 503,
1005 headers: {"retry-after": BACKOFF}};
1007 let deferred = Promise.defer();
1008 Svc.Obs.add("weave:ui:sync:error", function onUIUpdate() {
1009 Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
1010 do_check_eq(Status.service, SYNC_FAILED);
1011 do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
1012 do_check_true(errorHandler.didReportProlongedError);
1014 clean();
1015 server.stop(deferred.resolve);
1016 });
1018 do_check_eq(Status.service, STATUS_OK);
1020 setLastSync(PROLONGED_ERROR_DURATION);
1021 Service.sync();
1022 yield deferred.promise;
1023 });
1025 add_identity_test(this, function test_info_collections_login_prolonged_server_maintenance_error(){
1026 // Test info/collections prolonged server maintenance errors are reported.
1027 let server = sync_httpd_setup();
1028 yield setUp(server);
1030 yield configureIdentity({username: "broken.info"});
1031 Service.serverURL = server.baseURI + "/maintenance/";
1032 Service.clusterURL = server.baseURI + "/maintenance/";
1034 let backoffInterval;
1035 Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
1036 Svc.Obs.remove("weave:service:backoff:interval", observe);
1037 backoffInterval = subject;
1038 });
1040 let deferred = Promise.defer();
1041 Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
1042 Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
1043 do_check_true(Status.enforceBackoff);
1044 do_check_eq(backoffInterval, 42);
1045 do_check_eq(Status.service, SYNC_FAILED);
1046 do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
1047 do_check_true(errorHandler.didReportProlongedError);
1049 clean();
1050 server.stop(deferred.resolve);
1051 });
1053 do_check_false(Status.enforceBackoff);
1054 do_check_eq(Status.service, STATUS_OK);
1056 setLastSync(PROLONGED_ERROR_DURATION);
1057 Service.sync();
1058 yield deferred.promise;
1059 });
1061 add_identity_test(this, function test_meta_global_login_prolonged_server_maintenance_error(){
1062 // Test meta/global prolonged server maintenance errors are reported.
1063 let server = sync_httpd_setup();
1064 yield setUp(server);
1066 yield configureIdentity({username: "broken.meta"});
1067 Service.serverURL = server.baseURI + "/maintenance/";
1068 Service.clusterURL = server.baseURI + "/maintenance/";
1070 let backoffInterval;
1071 Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
1072 Svc.Obs.remove("weave:service:backoff:interval", observe);
1073 backoffInterval = subject;
1074 });
1076 let deferred = Promise.defer();
1077 Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
1078 Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
1079 do_check_true(Status.enforceBackoff);
1080 do_check_eq(backoffInterval, 42);
1081 do_check_eq(Status.service, SYNC_FAILED);
1082 do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
1083 do_check_true(errorHandler.didReportProlongedError);
1085 clean();
1086 server.stop(deferred.resolve);
1087 });
1089 do_check_false(Status.enforceBackoff);
1090 do_check_eq(Status.service, STATUS_OK);
1092 setLastSync(PROLONGED_ERROR_DURATION);
1093 Service.sync();
1094 yield deferred.promise;
1095 });
1097 add_identity_test(this, function test_download_crypto_keys_login_prolonged_server_maintenance_error(){
1098 // Test crypto/keys prolonged server maintenance errors are reported.
1099 let server = sync_httpd_setup();
1100 yield setUp(server);
1102 yield configureIdentity({username: "broken.keys"});
1103 Service.serverURL = server.baseURI + "/maintenance/";
1104 Service.clusterURL = server.baseURI + "/maintenance/";
1105 // Force re-download of keys
1106 Service.collectionKeys.clear();
1108 let backoffInterval;
1109 Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
1110 Svc.Obs.remove("weave:service:backoff:interval", observe);
1111 backoffInterval = subject;
1112 });
1114 let deferred = Promise.defer();
1115 Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
1116 Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
1117 do_check_true(Status.enforceBackoff);
1118 do_check_eq(backoffInterval, 42);
1119 do_check_eq(Status.service, SYNC_FAILED);
1120 do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
1121 do_check_true(errorHandler.didReportProlongedError);
1123 clean();
1124 server.stop(deferred.resolve);
1125 });
1127 do_check_false(Status.enforceBackoff);
1128 do_check_eq(Status.service, STATUS_OK);
1130 setLastSync(PROLONGED_ERROR_DURATION);
1131 Service.sync();
1132 yield deferred.promise;
1133 });
1135 add_identity_test(this, function test_upload_crypto_keys_login_prolonged_server_maintenance_error(){
1136 // Test crypto/keys prolonged server maintenance errors are reported.
1137 let server = sync_httpd_setup();
1139 // Start off with an empty account, do not upload a key.
1140 yield configureIdentity({username: "broken.keys"});
1141 Service.serverURL = server.baseURI + "/maintenance/";
1142 Service.clusterURL = server.baseURI + "/maintenance/";
1144 let backoffInterval;
1145 Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
1146 Svc.Obs.remove("weave:service:backoff:interval", observe);
1147 backoffInterval = subject;
1148 });
1150 let deferred = Promise.defer();
1151 Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
1152 Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
1153 do_check_true(Status.enforceBackoff);
1154 do_check_eq(backoffInterval, 42);
1155 do_check_eq(Status.service, SYNC_FAILED);
1156 do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
1157 do_check_true(errorHandler.didReportProlongedError);
1159 clean();
1160 server.stop(deferred.resolve);
1161 });
1163 do_check_false(Status.enforceBackoff);
1164 do_check_eq(Status.service, STATUS_OK);
1166 setLastSync(PROLONGED_ERROR_DURATION);
1167 Service.sync();
1168 yield deferred.promise;
1169 });
1171 add_identity_test(this, function test_wipeServer_login_prolonged_server_maintenance_error(){
1172 // Test that we report prolonged server maintenance errors that occur whilst
1173 // wiping the server.
1174 let server = sync_httpd_setup();
1176 // Start off with an empty account, do not upload a key.
1177 yield configureIdentity({username: "broken.wipe"});
1178 Service.serverURL = server.baseURI + "/maintenance/";
1179 Service.clusterURL = server.baseURI + "/maintenance/";
1181 let backoffInterval;
1182 Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
1183 Svc.Obs.remove("weave:service:backoff:interval", observe);
1184 backoffInterval = subject;
1185 });
1187 let deferred = Promise.defer();
1188 Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
1189 Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
1190 do_check_true(Status.enforceBackoff);
1191 do_check_eq(backoffInterval, 42);
1192 do_check_eq(Status.service, SYNC_FAILED);
1193 do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
1194 do_check_true(errorHandler.didReportProlongedError);
1196 clean();
1197 server.stop(deferred.resolve);
1198 });
1200 do_check_false(Status.enforceBackoff);
1201 do_check_eq(Status.service, STATUS_OK);
1203 setLastSync(PROLONGED_ERROR_DURATION);
1204 Service.sync();
1205 yield deferred.promise;
1206 });
1208 add_identity_test(this, function test_wipeRemote_prolonged_server_maintenance_error(){
1209 // Test that we report prolonged server maintenance errors that occur whilst
1210 // wiping all remote devices.
1211 let server = sync_httpd_setup();
1213 server.registerPathHandler("/1.1/broken.wipe/storage/catapult", service_unavailable);
1214 yield configureIdentity({username: "broken.wipe"});
1215 Service.serverURL = server.baseURI + "/maintenance/";
1216 Service.clusterURL = server.baseURI + "/maintenance/";
1217 generateAndUploadKeys();
1219 let engine = engineManager.get("catapult");
1220 engine.exception = null;
1221 engine.enabled = true;
1223 let backoffInterval;
1224 Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
1225 Svc.Obs.remove("weave:service:backoff:interval", observe);
1226 backoffInterval = subject;
1227 });
1229 let deferred = Promise.defer();
1230 Svc.Obs.add("weave:ui:sync:error", function onUIUpdate() {
1231 Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
1232 do_check_true(Status.enforceBackoff);
1233 do_check_eq(backoffInterval, 42);
1234 do_check_eq(Status.service, SYNC_FAILED);
1235 do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
1236 do_check_eq(Svc.Prefs.get("firstSync"), "wipeRemote");
1237 do_check_true(errorHandler.didReportProlongedError);
1239 clean();
1240 server.stop(deferred.resolve);
1241 });
1243 do_check_false(Status.enforceBackoff);
1244 do_check_eq(Status.service, STATUS_OK);
1246 Svc.Prefs.set("firstSync", "wipeRemote");
1247 setLastSync(PROLONGED_ERROR_DURATION);
1248 Service.sync();
1249 yield deferred.promise;
1250 });
1252 add_task(function test_sync_syncAndReportErrors_server_maintenance_error() {
1253 // Test server maintenance errors are reported
1254 // when calling syncAndReportErrors.
1255 let server = sync_httpd_setup();
1256 yield setUp(server);
1258 const BACKOFF = 42;
1259 let engine = engineManager.get("catapult");
1260 engine.enabled = true;
1261 engine.exception = {status: 503,
1262 headers: {"retry-after": BACKOFF}};
1264 let deferred = Promise.defer();
1265 Svc.Obs.add("weave:ui:sync:error", function onUIUpdate() {
1266 Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
1267 do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
1268 do_check_eq(Status.sync, SERVER_MAINTENANCE);
1269 do_check_false(errorHandler.didReportProlongedError);
1271 clean();
1272 server.stop(deferred.resolve);
1273 });
1275 do_check_eq(Status.service, STATUS_OK);
1277 setLastSync(NON_PROLONGED_ERROR_DURATION);
1278 errorHandler.syncAndReportErrors();
1279 yield deferred.promise;
1280 });
1282 add_identity_test(this, function test_info_collections_login_syncAndReportErrors_server_maintenance_error() {
1283 // Test info/collections server maintenance errors are reported
1284 // when calling syncAndReportErrors.
1285 let server = sync_httpd_setup();
1286 yield setUp(server);
1288 yield configureIdentity({username: "broken.info"});
1289 Service.serverURL = server.baseURI + "/maintenance/";
1290 Service.clusterURL = server.baseURI + "/maintenance/";
1292 let backoffInterval;
1293 Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
1294 Svc.Obs.remove("weave:service:backoff:interval", observe);
1295 backoffInterval = subject;
1296 });
1298 let deferred = Promise.defer();
1299 Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
1300 Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
1301 do_check_true(Status.enforceBackoff);
1302 do_check_eq(backoffInterval, 42);
1303 do_check_eq(Status.service, LOGIN_FAILED);
1304 do_check_eq(Status.login, SERVER_MAINTENANCE);
1305 do_check_false(errorHandler.didReportProlongedError);
1307 clean();
1308 server.stop(deferred.resolve);
1309 });
1311 do_check_false(Status.enforceBackoff);
1312 do_check_eq(Status.service, STATUS_OK);
1314 setLastSync(NON_PROLONGED_ERROR_DURATION);
1315 errorHandler.syncAndReportErrors();
1316 yield deferred.promise;
1317 });
1319 add_identity_test(this, function test_meta_global_login_syncAndReportErrors_server_maintenance_error() {
1320 // Test meta/global server maintenance errors are reported
1321 // when calling syncAndReportErrors.
1322 let server = sync_httpd_setup();
1323 yield setUp(server);
1325 yield configureIdentity({username: "broken.meta"});
1326 Service.serverURL = server.baseURI + "/maintenance/";
1327 Service.clusterURL = server.baseURI + "/maintenance/";
1329 let backoffInterval;
1330 Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
1331 Svc.Obs.remove("weave:service:backoff:interval", observe);
1332 backoffInterval = subject;
1333 });
1335 let deferred = Promise.defer();
1336 Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
1337 Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
1338 do_check_true(Status.enforceBackoff);
1339 do_check_eq(backoffInterval, 42);
1340 do_check_eq(Status.service, LOGIN_FAILED);
1341 do_check_eq(Status.login, SERVER_MAINTENANCE);
1342 do_check_false(errorHandler.didReportProlongedError);
1344 clean();
1345 server.stop(deferred.resolve);
1346 });
1348 do_check_false(Status.enforceBackoff);
1349 do_check_eq(Status.service, STATUS_OK);
1351 setLastSync(NON_PROLONGED_ERROR_DURATION);
1352 errorHandler.syncAndReportErrors();
1353 yield deferred.promise;
1354 });
1356 add_identity_test(this, function test_download_crypto_keys_login_syncAndReportErrors_server_maintenance_error() {
1357 // Test crypto/keys server maintenance errors are reported
1358 // when calling syncAndReportErrors.
1359 let server = sync_httpd_setup();
1360 yield setUp(server);
1362 yield configureIdentity({username: "broken.keys"});
1363 Service.serverURL = server.baseURI + "/maintenance/";
1364 Service.clusterURL = server.baseURI + "/maintenance/";
1365 // Force re-download of keys
1366 Service.collectionKeys.clear();
1368 let backoffInterval;
1369 Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
1370 Svc.Obs.remove("weave:service:backoff:interval", observe);
1371 backoffInterval = subject;
1372 });
1374 let deferred = Promise.defer();
1375 Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
1376 Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
1377 do_check_true(Status.enforceBackoff);
1378 do_check_eq(backoffInterval, 42);
1379 do_check_eq(Status.service, LOGIN_FAILED);
1380 do_check_eq(Status.login, SERVER_MAINTENANCE);
1381 do_check_false(errorHandler.didReportProlongedError);
1383 clean();
1384 server.stop(deferred.resolve);
1385 });
1387 do_check_false(Status.enforceBackoff);
1388 do_check_eq(Status.service, STATUS_OK);
1390 setLastSync(NON_PROLONGED_ERROR_DURATION);
1391 errorHandler.syncAndReportErrors();
1392 yield deferred.promise;
1393 });
1395 add_identity_test(this, function test_upload_crypto_keys_login_syncAndReportErrors_server_maintenance_error() {
1396 // Test crypto/keys server maintenance errors are reported
1397 // when calling syncAndReportErrors.
1398 let server = sync_httpd_setup();
1400 // Start off with an empty account, do not upload a key.
1401 yield configureIdentity({username: "broken.keys"});
1402 Service.serverURL = server.baseURI + "/maintenance/";
1403 Service.clusterURL = server.baseURI + "/maintenance/";
1405 let backoffInterval;
1406 Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
1407 Svc.Obs.remove("weave:service:backoff:interval", observe);
1408 backoffInterval = subject;
1409 });
1411 let deferred = Promise.defer();
1412 Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
1413 Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
1414 do_check_true(Status.enforceBackoff);
1415 do_check_eq(backoffInterval, 42);
1416 do_check_eq(Status.service, LOGIN_FAILED);
1417 do_check_eq(Status.login, SERVER_MAINTENANCE);
1418 do_check_false(errorHandler.didReportProlongedError);
1420 clean();
1421 server.stop(deferred.resolve);
1422 });
1424 do_check_false(Status.enforceBackoff);
1425 do_check_eq(Status.service, STATUS_OK);
1427 setLastSync(NON_PROLONGED_ERROR_DURATION);
1428 errorHandler.syncAndReportErrors();
1429 yield deferred.promise;
1430 });
1432 add_identity_test(this, function test_wipeServer_login_syncAndReportErrors_server_maintenance_error() {
1433 // Test crypto/keys server maintenance errors are reported
1434 // when calling syncAndReportErrors.
1435 let server = sync_httpd_setup();
1437 // Start off with an empty account, do not upload a key.
1438 yield configureIdentity({username: "broken.wipe"});
1439 Service.serverURL = server.baseURI + "/maintenance/";
1440 Service.clusterURL = server.baseURI + "/maintenance/";
1442 let backoffInterval;
1443 Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
1444 Svc.Obs.remove("weave:service:backoff:interval", observe);
1445 backoffInterval = subject;
1446 });
1448 let deferred = Promise.defer();
1449 Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
1450 Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
1451 do_check_true(Status.enforceBackoff);
1452 do_check_eq(backoffInterval, 42);
1453 do_check_eq(Status.service, LOGIN_FAILED);
1454 do_check_eq(Status.login, SERVER_MAINTENANCE);
1455 do_check_false(errorHandler.didReportProlongedError);
1457 clean();
1458 server.stop(deferred.resolve);
1459 });
1461 do_check_false(Status.enforceBackoff);
1462 do_check_eq(Status.service, STATUS_OK);
1464 setLastSync(NON_PROLONGED_ERROR_DURATION);
1465 errorHandler.syncAndReportErrors();
1466 yield deferred.promise;
1467 });
1469 add_identity_test(this, function test_wipeRemote_syncAndReportErrors_server_maintenance_error(){
1470 // Test that we report prolonged server maintenance errors that occur whilst
1471 // wiping all remote devices.
1472 let server = sync_httpd_setup();
1474 yield configureIdentity({username: "broken.wipe"});
1475 Service.serverURL = server.baseURI + "/maintenance/";
1476 Service.clusterURL = server.baseURI + "/maintenance/";
1477 generateAndUploadKeys();
1479 let engine = engineManager.get("catapult");
1480 engine.exception = null;
1481 engine.enabled = true;
1483 let backoffInterval;
1484 Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
1485 Svc.Obs.remove("weave:service:backoff:interval", observe);
1486 backoffInterval = subject;
1487 });
1489 let deferred = Promise.defer();
1490 Svc.Obs.add("weave:ui:sync:error", function onUIUpdate() {
1491 Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
1492 do_check_true(Status.enforceBackoff);
1493 do_check_eq(backoffInterval, 42);
1494 do_check_eq(Status.service, SYNC_FAILED);
1495 do_check_eq(Status.sync, SERVER_MAINTENANCE);
1496 do_check_eq(Svc.Prefs.get("firstSync"), "wipeRemote");
1497 do_check_false(errorHandler.didReportProlongedError);
1499 clean();
1500 server.stop(deferred.resolve);
1501 });
1503 do_check_false(Status.enforceBackoff);
1504 do_check_eq(Status.service, STATUS_OK);
1506 Svc.Prefs.set("firstSync", "wipeRemote");
1507 setLastSync(NON_PROLONGED_ERROR_DURATION);
1508 errorHandler.syncAndReportErrors();
1509 yield deferred.promise;
1510 });
1512 add_task(function test_sync_syncAndReportErrors_prolonged_server_maintenance_error() {
1513 // Test prolonged server maintenance errors are
1514 // reported when calling syncAndReportErrors.
1515 let server = sync_httpd_setup();
1516 yield setUp(server);
1518 const BACKOFF = 42;
1519 let engine = engineManager.get("catapult");
1520 engine.enabled = true;
1521 engine.exception = {status: 503,
1522 headers: {"retry-after": BACKOFF}};
1524 let deferred = Promise.defer();
1525 Svc.Obs.add("weave:ui:sync:error", function onUIUpdate() {
1526 Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
1527 do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
1528 do_check_eq(Status.sync, SERVER_MAINTENANCE);
1529 // syncAndReportErrors means dontIgnoreErrors, which means
1530 // didReportProlongedError not touched.
1531 do_check_false(errorHandler.didReportProlongedError);
1533 clean();
1534 server.stop(deferred.resolve);
1535 });
1537 do_check_eq(Status.service, STATUS_OK);
1539 setLastSync(PROLONGED_ERROR_DURATION);
1540 errorHandler.syncAndReportErrors();
1541 yield deferred.promise;
1542 });
1544 add_identity_test(this, function test_info_collections_login_syncAndReportErrors_prolonged_server_maintenance_error() {
1545 // Test info/collections server maintenance errors are reported
1546 // when calling syncAndReportErrors.
1547 let server = sync_httpd_setup();
1548 yield setUp(server);
1550 yield configureIdentity({username: "broken.info"});
1551 Service.serverURL = server.baseURI + "/maintenance/";
1552 Service.clusterURL = server.baseURI + "/maintenance/";
1554 let backoffInterval;
1555 Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
1556 Svc.Obs.remove("weave:service:backoff:interval", observe);
1557 backoffInterval = subject;
1558 });
1560 let deferred = Promise.defer();
1561 Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
1562 Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
1563 do_check_true(Status.enforceBackoff);
1564 do_check_eq(backoffInterval, 42);
1565 do_check_eq(Status.service, LOGIN_FAILED);
1566 do_check_eq(Status.login, SERVER_MAINTENANCE);
1567 // syncAndReportErrors means dontIgnoreErrors, which means
1568 // didReportProlongedError not touched.
1569 do_check_false(errorHandler.didReportProlongedError);
1571 clean();
1572 server.stop(deferred.resolve);
1573 });
1575 do_check_false(Status.enforceBackoff);
1576 do_check_eq(Status.service, STATUS_OK);
1578 setLastSync(PROLONGED_ERROR_DURATION);
1579 errorHandler.syncAndReportErrors();
1580 yield deferred.promise;
1581 });
1583 add_identity_test(this, function test_meta_global_login_syncAndReportErrors_prolonged_server_maintenance_error() {
1584 // Test meta/global server maintenance errors are reported
1585 // when calling syncAndReportErrors.
1586 let server = sync_httpd_setup();
1587 yield setUp(server);
1589 yield configureIdentity({username: "broken.meta"});
1590 Service.serverURL = server.baseURI + "/maintenance/";
1591 Service.clusterURL = server.baseURI + "/maintenance/";
1593 let backoffInterval;
1594 Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
1595 Svc.Obs.remove("weave:service:backoff:interval", observe);
1596 backoffInterval = subject;
1597 });
1599 let deferred = Promise.defer();
1600 Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
1601 Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
1602 do_check_true(Status.enforceBackoff);
1603 do_check_eq(backoffInterval, 42);
1604 do_check_eq(Status.service, LOGIN_FAILED);
1605 do_check_eq(Status.login, SERVER_MAINTENANCE);
1606 // syncAndReportErrors means dontIgnoreErrors, which means
1607 // didReportProlongedError not touched.
1608 do_check_false(errorHandler.didReportProlongedError);
1610 clean();
1611 server.stop(deferred.resolve);
1612 });
1614 do_check_false(Status.enforceBackoff);
1615 do_check_eq(Status.service, STATUS_OK);
1617 setLastSync(PROLONGED_ERROR_DURATION);
1618 errorHandler.syncAndReportErrors();
1619 yield deferred.promise;
1620 });
1622 add_identity_test(this, function test_download_crypto_keys_login_syncAndReportErrors_prolonged_server_maintenance_error() {
1623 // Test crypto/keys server maintenance errors are reported
1624 // when calling syncAndReportErrors.
1625 let server = sync_httpd_setup();
1626 yield setUp(server);
1628 yield configureIdentity({username: "broken.keys"});
1629 Service.serverURL = server.baseURI + "/maintenance/";
1630 Service.clusterURL = server.baseURI + "/maintenance/";
1631 // Force re-download of keys
1632 Service.collectionKeys.clear();
1634 let backoffInterval;
1635 Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
1636 Svc.Obs.remove("weave:service:backoff:interval", observe);
1637 backoffInterval = subject;
1638 });
1640 let deferred = Promise.defer();
1641 Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
1642 Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
1643 do_check_true(Status.enforceBackoff);
1644 do_check_eq(backoffInterval, 42);
1645 do_check_eq(Status.service, LOGIN_FAILED);
1646 do_check_eq(Status.login, SERVER_MAINTENANCE);
1647 // syncAndReportErrors means dontIgnoreErrors, which means
1648 // didReportProlongedError not touched.
1649 do_check_false(errorHandler.didReportProlongedError);
1651 clean();
1652 server.stop(deferred.resolve);
1653 });
1655 do_check_false(Status.enforceBackoff);
1656 do_check_eq(Status.service, STATUS_OK);
1658 setLastSync(PROLONGED_ERROR_DURATION);
1659 errorHandler.syncAndReportErrors();
1660 yield deferred.promise;
1661 });
1663 add_identity_test(this, function test_upload_crypto_keys_login_syncAndReportErrors_prolonged_server_maintenance_error() {
1664 // Test crypto/keys server maintenance errors are reported
1665 // when calling syncAndReportErrors.
1666 let server = sync_httpd_setup();
1668 // Start off with an empty account, do not upload a key.
1669 yield configureIdentity({username: "broken.keys"});
1670 Service.serverURL = server.baseURI + "/maintenance/";
1671 Service.clusterURL = server.baseURI + "/maintenance/";
1673 let backoffInterval;
1674 Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
1675 Svc.Obs.remove("weave:service:backoff:interval", observe);
1676 backoffInterval = subject;
1677 });
1679 let deferred = Promise.defer();
1680 Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
1681 Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
1682 do_check_true(Status.enforceBackoff);
1683 do_check_eq(backoffInterval, 42);
1684 do_check_eq(Status.service, LOGIN_FAILED);
1685 do_check_eq(Status.login, SERVER_MAINTENANCE);
1686 // syncAndReportErrors means dontIgnoreErrors, which means
1687 // didReportProlongedError not touched.
1688 do_check_false(errorHandler.didReportProlongedError);
1690 clean();
1691 server.stop(deferred.resolve);
1692 });
1694 do_check_false(Status.enforceBackoff);
1695 do_check_eq(Status.service, STATUS_OK);
1697 setLastSync(PROLONGED_ERROR_DURATION);
1698 errorHandler.syncAndReportErrors();
1699 yield deferred.promise;
1700 });
1702 add_identity_test(this, function test_wipeServer_login_syncAndReportErrors_prolonged_server_maintenance_error() {
1703 // Test crypto/keys server maintenance errors are reported
1704 // when calling syncAndReportErrors.
1705 let server = sync_httpd_setup();
1707 // Start off with an empty account, do not upload a key.
1708 yield configureIdentity({username: "broken.wipe"});
1709 Service.serverURL = server.baseURI + "/maintenance/";
1710 Service.clusterURL = server.baseURI + "/maintenance/";
1712 let backoffInterval;
1713 Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
1714 Svc.Obs.remove("weave:service:backoff:interval", observe);
1715 backoffInterval = subject;
1716 });
1718 let deferred = Promise.defer();
1719 Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
1720 Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
1721 do_check_true(Status.enforceBackoff);
1722 do_check_eq(backoffInterval, 42);
1723 do_check_eq(Status.service, LOGIN_FAILED);
1724 do_check_eq(Status.login, SERVER_MAINTENANCE);
1725 // syncAndReportErrors means dontIgnoreErrors, which means
1726 // didReportProlongedError not touched.
1727 do_check_false(errorHandler.didReportProlongedError);
1729 clean();
1730 server.stop(deferred.resolve);
1731 });
1733 do_check_false(Status.enforceBackoff);
1734 do_check_eq(Status.service, STATUS_OK);
1736 setLastSync(PROLONGED_ERROR_DURATION);
1737 errorHandler.syncAndReportErrors();
1738 yield deferred.promise;
1739 });
1741 add_task(function test_sync_engine_generic_fail() {
1742 let server = sync_httpd_setup();
1744 let engine = engineManager.get("catapult");
1745 engine.enabled = true;
1746 engine.sync = function sync() {
1747 Svc.Obs.notify("weave:engine:sync:error", "", "catapult");
1748 };
1750 let log = Log.repository.getLogger("Sync.ErrorHandler");
1751 Svc.Prefs.set("log.appender.file.logOnError", true);
1753 do_check_eq(Status.engines["catapult"], undefined);
1755 let deferred = Promise.defer();
1756 // Don't wait for reset-file-log until the sync is underway.
1757 // This avoids us catching a delayed notification from an earlier test.
1758 Svc.Obs.add("weave:engine:sync:finish", function onEngineFinish() {
1759 Svc.Obs.remove("weave:engine:sync:finish", onEngineFinish);
1761 log.info("Adding reset-file-log observer.");
1762 Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
1763 Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
1765 // Put these checks here, not after sync(), so that we aren't racing the
1766 // log handler... which resets everything just a few lines below!
1767 _("Status.engines: " + JSON.stringify(Status.engines));
1768 do_check_eq(Status.engines["catapult"], ENGINE_UNKNOWN_FAIL);
1769 do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
1771 // Test Error log was written on SYNC_FAILED_PARTIAL.
1772 let entries = logsdir.directoryEntries;
1773 do_check_true(entries.hasMoreElements());
1774 let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
1775 do_check_eq(logfile.leafName.slice(0, LOG_PREFIX_ERROR.length),
1776 LOG_PREFIX_ERROR);
1778 clean();
1779 server.stop(deferred.resolve);
1780 });
1781 });
1783 do_check_true(yield setUp(server));
1784 Service.sync();
1785 yield deferred.promise;
1786 });
1788 add_test(function test_logs_on_sync_error_despite_shouldReportError() {
1789 _("Ensure that an error is still logged when weave:service:sync:error " +
1790 "is notified, despite shouldReportError returning false.");
1792 let log = Log.repository.getLogger("Sync.ErrorHandler");
1793 Svc.Prefs.set("log.appender.file.logOnError", true);
1794 log.info("TESTING");
1796 // Ensure that we report no error.
1797 Status.login = MASTER_PASSWORD_LOCKED;
1798 do_check_false(errorHandler.shouldReportError());
1800 Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
1801 Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
1803 // Test that error log was written.
1804 let entries = logsdir.directoryEntries;
1805 do_check_true(entries.hasMoreElements());
1806 let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
1807 do_check_eq(logfile.leafName.slice(0, LOG_PREFIX_ERROR.length),
1808 LOG_PREFIX_ERROR);
1810 clean();
1811 run_next_test();
1812 });
1813 Svc.Obs.notify("weave:service:sync:error", {});
1814 });
1816 add_test(function test_logs_on_login_error_despite_shouldReportError() {
1817 _("Ensure that an error is still logged when weave:service:login:error " +
1818 "is notified, despite shouldReportError returning false.");
1820 let log = Log.repository.getLogger("Sync.ErrorHandler");
1821 Svc.Prefs.set("log.appender.file.logOnError", true);
1822 log.info("TESTING");
1824 // Ensure that we report no error.
1825 Status.login = MASTER_PASSWORD_LOCKED;
1826 do_check_false(errorHandler.shouldReportError());
1828 Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
1829 Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
1831 // Test that error log was written.
1832 let entries = logsdir.directoryEntries;
1833 do_check_true(entries.hasMoreElements());
1834 let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
1835 do_check_eq(logfile.leafName.slice(0, LOG_PREFIX_ERROR.length),
1836 LOG_PREFIX_ERROR);
1838 clean();
1839 run_next_test();
1840 });
1841 Svc.Obs.notify("weave:service:login:error", {});
1842 });
1844 // This test should be the last one since it monkeypatches the engine object
1845 // and we should only have one engine object throughout the file (bug 629664).
1846 add_task(function test_engine_applyFailed() {
1847 let server = sync_httpd_setup();
1849 let engine = engineManager.get("catapult");
1850 engine.enabled = true;
1851 delete engine.exception;
1852 engine.sync = function sync() {
1853 Svc.Obs.notify("weave:engine:sync:applied", {newFailed:1}, "catapult");
1854 };
1856 let log = Log.repository.getLogger("Sync.ErrorHandler");
1857 Svc.Prefs.set("log.appender.file.logOnError", true);
1859 let deferred = Promise.defer();
1860 Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
1861 Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
1863 do_check_eq(Status.engines["catapult"], ENGINE_APPLY_FAIL);
1864 do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
1866 // Test Error log was written on SYNC_FAILED_PARTIAL.
1867 let entries = logsdir.directoryEntries;
1868 do_check_true(entries.hasMoreElements());
1869 let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
1870 do_check_eq(logfile.leafName.slice(0, LOG_PREFIX_ERROR.length),
1871 LOG_PREFIX_ERROR);
1873 clean();
1874 server.stop(deferred.resolve);
1875 });
1877 do_check_eq(Status.engines["catapult"], undefined);
1878 do_check_true(yield setUp(server));
1879 Service.sync();
1880 yield deferred.promise;
1881 });