gecko/services/sync/tests/unit/test_errorhandler.js

1303 lines
40 KiB
JavaScript

/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://services-sync/engines/clients.js");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/policies.js");
Cu.import("resource://services-sync/status.js");
Svc.DefaultPrefs.set("registerEngines", "");
Cu.import("resource://services-sync/service.js");
const logsdir = FileUtils.getDir("ProfD", ["weave", "logs"], true);
const LOG_PREFIX_SUCCESS = "success-";
const LOG_PREFIX_ERROR = "error-";
const PROLONGED_ERROR_DURATION =
(Svc.Prefs.get('errorhandler.networkFailureReportTimeout') * 2) * 1000;
const NON_PROLONGED_ERROR_DURATION =
(Svc.Prefs.get('errorhandler.networkFailureReportTimeout') / 2) * 1000;
function setLastSync(lastSyncValue) {
Svc.Prefs.set("lastSync", (new Date(Date.now() -
lastSyncValue)).toString());
}
function CatapultEngine() {
SyncEngine.call(this, "Catapult");
}
CatapultEngine.prototype = {
__proto__: SyncEngine.prototype,
exception: null, // tests fill this in
_sync: function _sync() {
throw this.exception;
}
};
Engines.register(CatapultEngine);
function run_test() {
initTestLogging("Trace");
Log4Moz.repository.getLogger("Sync.Service").level = Log4Moz.Level.Trace;
Log4Moz.repository.getLogger("Sync.SyncScheduler").level = Log4Moz.Level.Trace;
Log4Moz.repository.getLogger("Sync.ErrorHandler").level = Log4Moz.Level.Trace;
run_next_test();
}
function generateCredentialsChangedFailure() {
// Make sync fail due to changed credentials. We simply re-encrypt
// the keys with a different Sync Key, without changing the local one.
let newSyncKeyBundle = new SyncKeyBundle(PWDMGR_PASSPHRASE_REALM, Service.username);
newSyncKeyBundle.keyStr = "23456234562345623456234562";
let keys = CollectionKeys.asWBO();
keys.encrypt(newSyncKeyBundle);
keys.upload(Service.cryptoKeysURL);
}
function service_unavailable(request, response) {
let body = "Service Unavailable";
response.setStatusLine(request.httpVersion, 503, "Service Unavailable");
response.setHeader("Retry-After", "42");
response.bodyOutputStream.write(body, body.length);
}
function sync_httpd_setup() {
let global = new ServerWBO("global", {
syncID: Service.syncID,
storageVersion: STORAGE_VERSION,
engines: {clients: {version: Clients.version,
syncID: Clients.syncID}}
});
let clientsColl = new ServerCollection({}, true);
// Tracking info/collections.
let collectionsHelper = track_collections_helper();
let upd = collectionsHelper.with_updated_collection;
let handler_401 = httpd_handler(401, "Unauthorized");
return httpd_setup({
"/1.1/johndoe/storage/meta/global": upd("meta", global.handler()),
"/1.1/johndoe/info/collections": collectionsHelper.handler,
"/1.1/johndoe/storage/crypto/keys":
upd("crypto", (new ServerWBO("keys")).handler()),
"/1.1/johndoe/storage/clients": upd("clients", clientsColl.handler()),
"/1.1/janedoe/storage/meta/global": handler_401,
"/1.1/janedoe/info/collections": handler_401,
"/maintenance/1.1/johnsmith/info/collections": service_unavailable,
"/maintenance/1.1/janesmith/storage/meta/global": service_unavailable,
"/maintenance/1.1/janesmith/info/collections": collectionsHelper.handler,
"/maintenance/1.1/foo/storage/meta/global": upd("meta", global.handler()),
"/maintenance/1.1/foo/info/collections": collectionsHelper.handler,
"/maintenance/1.1/foo/storage/crypto/keys": service_unavailable,
});
}
function setUp() {
Service.username = "johndoe";
Service.password = "ilovejane";
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
Service.clusterURL = "http://localhost:8080/";
generateNewKeys();
let serverKeys = CollectionKeys.asWBO("crypto", "keys");
serverKeys.encrypt(Service.syncKeyBundle);
return serverKeys.upload(Service.cryptoKeysURL).success;
}
function clean() {
Service.startOver();
Status.resetSync();
Status.resetBackoff();
}
add_test(function test_401_logout() {
let server = sync_httpd_setup();
setUp();
// By calling sync, we ensure we're logged in.
Service.sync();
do_check_eq(Status.sync, SYNC_SUCCEEDED);
do_check_true(Service.isLoggedIn);
// Make sync fail due to login rejected.
Service.username = "janedoe";
Service.sync();
do_check_eq(Status.login, LOGIN_FAILED_LOGIN_REJECTED);
do_check_false(Service.isLoggedIn);
// Clean up.
Service.startOver();
server.stop(run_next_test);
});
add_test(function test_credentials_changed_logout() {
let server = sync_httpd_setup();
setUp();
// By calling sync, we ensure we're logged in.
Service.sync();
do_check_eq(Status.sync, SYNC_SUCCEEDED);
do_check_true(Service.isLoggedIn);
generateCredentialsChangedFailure();
Service.sync();
do_check_eq(Status.sync, CREDENTIALS_CHANGED);
do_check_false(Service.isLoggedIn);
// Clean up.
Service.startOver();
server.stop(run_next_test);
});
add_test(function test_no_lastSync_pref() {
// Test reported error.
Status.resetSync();
ErrorHandler.dontIgnoreErrors = true;
Status.sync = CREDENTIALS_CHANGED;
do_check_true(ErrorHandler.shouldReportError());
// Test unreported error.
Status.resetSync();
ErrorHandler.dontIgnoreErrors = true;
Status.login = LOGIN_FAILED_NETWORK_ERROR;
do_check_true(ErrorHandler.shouldReportError());
run_next_test();
});
add_test(function test_shouldReportError() {
Status.login = MASTER_PASSWORD_LOCKED;
do_check_false(ErrorHandler.shouldReportError());
// Test dontIgnoreErrors, non-network, non-prolonged, login error reported
Status.resetSync();
setLastSync(NON_PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = true;
Status.login = LOGIN_FAILED_NO_PASSWORD;
do_check_true(ErrorHandler.shouldReportError());
// Test dontIgnoreErrors, non-network, non-prolonged, sync error reported
Status.resetSync();
setLastSync(NON_PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = true;
Status.sync = CREDENTIALS_CHANGED;
do_check_true(ErrorHandler.shouldReportError());
// Test dontIgnoreErrors, non-network, prolonged, login error reported
Status.resetSync();
setLastSync(PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = true;
Status.login = LOGIN_FAILED_NO_PASSWORD;
do_check_true(ErrorHandler.shouldReportError());
// Test dontIgnoreErrors, non-network, prolonged, sync error reported
Status.resetSync();
setLastSync(PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = true;
Status.sync = CREDENTIALS_CHANGED;
do_check_true(ErrorHandler.shouldReportError());
// Test dontIgnoreErrors, network, non-prolonged, login error reported
Status.resetSync();
setLastSync(NON_PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = true;
Status.login = LOGIN_FAILED_NETWORK_ERROR;
do_check_true(ErrorHandler.shouldReportError());
// Test dontIgnoreErrors, network, non-prolonged, sync error reported
Status.resetSync();
setLastSync(NON_PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = true;
Status.sync = LOGIN_FAILED_NETWORK_ERROR;
do_check_true(ErrorHandler.shouldReportError());
// Test dontIgnoreErrors, network, prolonged, login error reported
Status.resetSync();
setLastSync(PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = true;
Status.login = LOGIN_FAILED_NETWORK_ERROR;
do_check_true(ErrorHandler.shouldReportError());
// Test dontIgnoreErrors, network, prolonged, sync error reported
Status.resetSync();
setLastSync(PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = true;
Status.sync = LOGIN_FAILED_NETWORK_ERROR;
do_check_true(ErrorHandler.shouldReportError());
// Test non-network, prolonged, login error reported
Status.resetSync();
setLastSync(PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = false;
Status.login = LOGIN_FAILED_NO_PASSWORD;
do_check_true(ErrorHandler.shouldReportError());
// Test non-network, prolonged, sync error reported
Status.resetSync();
setLastSync(PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = false;
Status.sync = CREDENTIALS_CHANGED;
do_check_true(ErrorHandler.shouldReportError());
// Test network, prolonged, login error reported
Status.resetSync();
setLastSync(PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = false;
Status.login = LOGIN_FAILED_NETWORK_ERROR;
do_check_true(ErrorHandler.shouldReportError());
// Test network, prolonged, sync error reported
Status.resetSync();
setLastSync(PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = false;
Status.sync = LOGIN_FAILED_NETWORK_ERROR;
do_check_true(ErrorHandler.shouldReportError());
// Test non-network, non-prolonged, login error reported
Status.resetSync();
setLastSync(NON_PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = false;
Status.login = LOGIN_FAILED_NO_PASSWORD;
do_check_true(ErrorHandler.shouldReportError());
// Test non-network, non-prolonged, sync error reported
Status.resetSync();
setLastSync(NON_PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = false;
Status.sync = CREDENTIALS_CHANGED;
do_check_true(ErrorHandler.shouldReportError());
// Test network, non-prolonged, login error reported
Status.resetSync();
setLastSync(NON_PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = false;
Status.login = LOGIN_FAILED_NETWORK_ERROR;
do_check_false(ErrorHandler.shouldReportError());
// Test network, non-prolonged, sync error reported
Status.resetSync();
setLastSync(NON_PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = false;
Status.sync = LOGIN_FAILED_NETWORK_ERROR;
do_check_false(ErrorHandler.shouldReportError());
// Test server maintenance, sync errors are not reported
Status.resetSync();
setLastSync(NON_PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = false;
Status.sync = SERVER_MAINTENANCE;
do_check_false(ErrorHandler.shouldReportError());
// Test server maintenance, login errors are not reported
Status.resetSync();
setLastSync(NON_PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = false;
Status.login = SERVER_MAINTENANCE;
do_check_false(ErrorHandler.shouldReportError());
// Test prolonged, server maintenance, sync errors are reported
Status.resetSync();
setLastSync(PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = false;
Status.sync = SERVER_MAINTENANCE;
do_check_true(ErrorHandler.shouldReportError());
// Test prolonged, server maintenance, login errors are reported
Status.resetSync();
setLastSync(PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = false;
Status.login = SERVER_MAINTENANCE;
do_check_true(ErrorHandler.shouldReportError());
// Test dontIgnoreErrors, server maintenance, sync errors are reported
Status.resetSync();
setLastSync(NON_PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = true;
Status.sync = SERVER_MAINTENANCE;
do_check_true(ErrorHandler.shouldReportError());
// Test dontIgnoreErrors, server maintenance, login errors are reported
Status.resetSync();
setLastSync(NON_PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = true;
Status.login = SERVER_MAINTENANCE;
do_check_true(ErrorHandler.shouldReportError());
// Test dontIgnoreErrors, prolonged, server maintenance,
// sync errors are reported
Status.resetSync();
setLastSync(PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = true;
Status.sync = SERVER_MAINTENANCE;
do_check_true(ErrorHandler.shouldReportError());
// Test dontIgnoreErrors, prolonged, server maintenance,
// login errors are reported
Status.resetSync();
setLastSync(PROLONGED_ERROR_DURATION);
ErrorHandler.dontIgnoreErrors = true;
Status.login = SERVER_MAINTENANCE;
do_check_true(ErrorHandler.shouldReportError());
run_next_test();
});
add_test(function test_shouldReportError_master_password() {
_("Test error ignored due to locked master password");
let server = sync_httpd_setup();
setUp();
// Monkey patch Service.verifyLogin to imitate
// master password being locked.
Service._verifyLogin = Service.verifyLogin;
Service.verifyLogin = function () {
Status.login = MASTER_PASSWORD_LOCKED;
return false;
};
setLastSync(NON_PROLONGED_ERROR_DURATION);
Service.sync();
do_check_false(ErrorHandler.shouldReportError());
// Clean up.
Service.verifyLogin = Service._verifyLogin;
clean();
server.stop(run_next_test);
});
add_test(function test_login_syncAndReportErrors_non_network_error() {
// Test non-network errors are reported
// when calling syncAndReportErrors
let server = sync_httpd_setup();
setUp();
Service.password = "";
Svc.Obs.add("weave:ui:login:error", function onSyncError() {
Svc.Obs.remove("weave:ui:login:error", onSyncError);
do_check_eq(Status.login, LOGIN_FAILED_NO_PASSWORD);
clean();
server.stop(run_next_test);
});
setLastSync(NON_PROLONGED_ERROR_DURATION);
ErrorHandler.syncAndReportErrors();
});
add_test(function test_sync_syncAndReportErrors_non_network_error() {
// Test non-network errors are reported
// when calling syncAndReportErrors
let server = sync_httpd_setup();
setUp();
// By calling sync, we ensure we're logged in.
Service.sync();
do_check_eq(Status.sync, SYNC_SUCCEEDED);
do_check_true(Service.isLoggedIn);
generateCredentialsChangedFailure();
Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
Svc.Obs.remove("weave:ui:sync:error", onSyncError);
do_check_eq(Status.sync, CREDENTIALS_CHANGED);
clean();
server.stop(run_next_test);
});
setLastSync(NON_PROLONGED_ERROR_DURATION);
ErrorHandler.syncAndReportErrors();
});
add_test(function test_login_syncAndReportErrors_prolonged_non_network_error() {
// Test prolonged, non-network errors are
// reported when calling syncAndReportErrors.
let server = sync_httpd_setup();
setUp();
Service.password = "";
Svc.Obs.add("weave:ui:login:error", function onSyncError() {
Svc.Obs.remove("weave:ui:login:error", onSyncError);
do_check_eq(Status.login, LOGIN_FAILED_NO_PASSWORD);
clean();
server.stop(run_next_test);
});
setLastSync(PROLONGED_ERROR_DURATION);
ErrorHandler.syncAndReportErrors();
});
add_test(function test_sync_syncAndReportErrors_prolonged_non_network_error() {
// Test prolonged, non-network errors are
// reported when calling syncAndReportErrors.
let server = sync_httpd_setup();
setUp();
// By calling sync, we ensure we're logged in.
Service.sync();
do_check_eq(Status.sync, SYNC_SUCCEEDED);
do_check_true(Service.isLoggedIn);
generateCredentialsChangedFailure();
Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
Svc.Obs.remove("weave:ui:sync:error", onSyncError);
do_check_eq(Status.sync, CREDENTIALS_CHANGED);
clean();
server.stop(run_next_test);
});
setLastSync(PROLONGED_ERROR_DURATION);
ErrorHandler.syncAndReportErrors();
});
add_test(function test_login_syncAndReportErrors_network_error() {
// Test network errors are reported when calling syncAndReportErrors.
Service.username = "johndoe";
Service.password = "ilovejane";
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
Service.clusterURL = "http://localhost:8080/";
Svc.Obs.add("weave:ui:login:error", function onSyncError() {
Svc.Obs.remove("weave:ui:login:error", onSyncError);
do_check_eq(Status.login, LOGIN_FAILED_NETWORK_ERROR);
clean();
run_next_test();
});
setLastSync(NON_PROLONGED_ERROR_DURATION);
ErrorHandler.syncAndReportErrors();
});
add_test(function test_sync_syncAndReportErrors_network_error() {
// Test network errors are reported when calling syncAndReportErrors.
Services.io.offline = true;
Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
Svc.Obs.remove("weave:ui:sync:error", onSyncError);
do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
Services.io.offline = false;
clean();
run_next_test();
});
setLastSync(NON_PROLONGED_ERROR_DURATION);
ErrorHandler.syncAndReportErrors();
});
add_test(function test_login_syncAndReportErrors_prolonged_network_error() {
// Test prolonged, network errors are reported
// when calling syncAndReportErrors.
Service.username = "johndoe";
Service.password = "ilovejane";
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
Service.clusterURL = "http://localhost:8080/";
Svc.Obs.add("weave:ui:login:error", function onSyncError() {
Svc.Obs.remove("weave:ui:login:error", onSyncError);
do_check_eq(Status.login, LOGIN_FAILED_NETWORK_ERROR);
clean();
run_next_test();
});
setLastSync(PROLONGED_ERROR_DURATION);
ErrorHandler.syncAndReportErrors();
});
add_test(function test_sync_syncAndReportErrors_prolonged_network_error() {
// Test prolonged, network errors are reported
// when calling syncAndReportErrors.
Services.io.offline = true;
Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
Svc.Obs.remove("weave:ui:sync:error", onSyncError);
do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
Services.io.offline = false;
clean();
run_next_test();
});
setLastSync(PROLONGED_ERROR_DURATION);
ErrorHandler.syncAndReportErrors();
});
add_test(function test_login_prolonged_non_network_error() {
// Test prolonged, non-network errors are reported
let server = sync_httpd_setup();
setUp();
Service.password = "";
Svc.Obs.add("weave:ui:login:error", function onSyncError() {
Svc.Obs.remove("weave:ui:login:error", onSyncError);
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
clean();
server.stop(run_next_test);
});
setLastSync(PROLONGED_ERROR_DURATION);
Service.sync();
});
add_test(function test_sync_prolonged_non_network_error() {
// Test prolonged, non-network errors are reported
let server = sync_httpd_setup();
setUp();
// By calling sync, we ensure we're logged in.
Service.sync();
do_check_eq(Status.sync, SYNC_SUCCEEDED);
do_check_true(Service.isLoggedIn);
generateCredentialsChangedFailure();
Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
Svc.Obs.remove("weave:ui:sync:error", onSyncError);
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
clean();
server.stop(run_next_test);
});
setLastSync(PROLONGED_ERROR_DURATION);
Service.sync();
});
add_test(function test_login_prolonged_network_error() {
// Test prolonged, network errors are reported
Service.username = "johndoe";
Service.password = "ilovejane";
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
Service.clusterURL = "http://localhost:8080/";
Svc.Obs.add("weave:ui:login:error", function onSyncError() {
Svc.Obs.remove("weave:ui:login:error", onSyncError);
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
clean();
run_next_test();
});
setLastSync(PROLONGED_ERROR_DURATION);
Service.sync();
});
add_test(function test_sync_prolonged_network_error() {
// Test prolonged, network errors are reported
Services.io.offline = true;
Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
Svc.Obs.remove("weave:ui:sync:error", onSyncError);
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
Services.io.offline = false;
clean();
run_next_test();
});
setLastSync(PROLONGED_ERROR_DURATION);
Service.sync();
});
add_test(function test_login_non_network_error() {
// Test non-network errors are reported
let server = sync_httpd_setup();
setUp();
Service.password = "";
Svc.Obs.add("weave:ui:login:error", function onSyncError() {
Svc.Obs.remove("weave:ui:login:error", onSyncError);
do_check_eq(Status.login, LOGIN_FAILED_NO_PASSWORD);
clean();
server.stop(run_next_test);
});
setLastSync(NON_PROLONGED_ERROR_DURATION);
Service.sync();
});
add_test(function test_sync_non_network_error() {
// Test non-network errors are reported
let server = sync_httpd_setup();
setUp();
// By calling sync, we ensure we're logged in.
Service.sync();
do_check_eq(Status.sync, SYNC_SUCCEEDED);
do_check_true(Service.isLoggedIn);
generateCredentialsChangedFailure();
Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
Svc.Obs.remove("weave:ui:sync:error", onSyncError);
do_check_eq(Status.sync, CREDENTIALS_CHANGED);
clean();
server.stop(run_next_test);
});
setLastSync(NON_PROLONGED_ERROR_DURATION);
Service.sync();
});
add_test(function test_login_network_error() {
Service.username = "johndoe";
Service.password = "ilovejane";
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
Service.clusterURL = "http://localhost:8080/";
// Test network errors are not reported.
Svc.Obs.add("weave:ui:clear-error", function onClearError() {
Svc.Obs.remove("weave:ui:clear-error", onClearError);
do_check_eq(Status.login, LOGIN_FAILED_NETWORK_ERROR);
Services.io.offline = false;
clean();
run_next_test();
});
setLastSync(NON_PROLONGED_ERROR_DURATION);
Service.sync();
});
add_test(function test_sync_network_error() {
// Test network errors are not reported.
Services.io.offline = true;
Svc.Obs.add("weave:ui:sync:finish", function onUIUpdate() {
Svc.Obs.remove("weave:ui:sync:finish", onUIUpdate);
do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
Services.io.offline = false;
clean();
run_next_test();
});
setLastSync(NON_PROLONGED_ERROR_DURATION);
Service.sync();
});
add_test(function test_sync_server_maintenance_error() {
// Test server maintenance errors are not reported.
let server = sync_httpd_setup();
setUp();
const BACKOFF = 42;
let engine = Engines.get("catapult");
engine.enabled = true;
engine.exception = {status: 503,
headers: {"retry-after": BACKOFF}};
function onSyncError() {
do_throw("Shouldn't get here!");
}
Svc.Obs.add("weave:ui:sync:error", onSyncError);
do_check_eq(Status.service, STATUS_OK);
Svc.Obs.add("weave:ui:sync:finish", function onSyncFinish() {
Svc.Obs.remove("weave:ui:sync:finish", onSyncFinish);
do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
do_check_eq(Status.sync, SERVER_MAINTENANCE);
Svc.Obs.remove("weave:ui:sync:error", onSyncError);
clean();
server.stop(run_next_test);
});
setLastSync(NON_PROLONGED_ERROR_DURATION);
Service.sync();
});
add_test(function test_info_collections_login_server_maintenance_error() {
// Test info/collections server maintenance errors are not reported.
let server = sync_httpd_setup();
setUp();
Service.clusterURL = "http://localhost:8080/maintenance/";
Service.username = "johnsmith";
let backoffInterval;
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
Svc.Obs.remove("weave:service:backoff:interval", observe);
backoffInterval = subject;
});
function onUIUpdate() {
do_throw("Shouldn't get here!");
}
Svc.Obs.add("weave:ui:login:error", onUIUpdate);
do_check_false(Status.enforceBackoff);
do_check_eq(Status.service, STATUS_OK);
Svc.Obs.add("weave:ui:clear-error", function onLoginFinish() {
Svc.Obs.remove("weave:ui:clear-error", onLoginFinish);
do_check_true(Status.enforceBackoff);
do_check_eq(backoffInterval, 42);
do_check_eq(Status.service, LOGIN_FAILED);
do_check_eq(Status.login, SERVER_MAINTENANCE);
Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
clean();
server.stop(run_next_test);
});
setLastSync(NON_PROLONGED_ERROR_DURATION);
Service.sync();
});
add_test(function test_meta_global_login_server_maintenance_error() {
// Test meta/global server maintenance errors are not reported.
let server = sync_httpd_setup();
setUp();
Service.clusterURL = "http://localhost:8080/maintenance/";
Service.username = "janesmith";
let backoffInterval;
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
Svc.Obs.remove("weave:service:backoff:interval", observe);
backoffInterval = subject;
});
function onUIUpdate() {
do_throw("Shouldn't get here!");
}
Svc.Obs.add("weave:ui:login:error", onUIUpdate);
do_check_false(Status.enforceBackoff);
do_check_eq(Status.service, STATUS_OK);
Svc.Obs.add("weave:ui:clear-error", function onLoginFinish() {
Svc.Obs.remove("weave:ui:clear-error", onLoginFinish);
do_check_true(Status.enforceBackoff);
do_check_eq(backoffInterval, 42);
do_check_eq(Status.service, LOGIN_FAILED);
do_check_eq(Status.login, SERVER_MAINTENANCE);
Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
clean();
server.stop(run_next_test);
});
setLastSync(NON_PROLONGED_ERROR_DURATION);
Service.sync();
});
add_test(function test_crypto_keys_login_server_maintenance_error() {
// Test crypto/keys server maintenance errors are not reported.
let server = sync_httpd_setup();
setUp();
Service.clusterURL = "http://localhost:8080/maintenance/";
Service.username = "foo";
// Force re-download of keys
CollectionKeys.clear();
let backoffInterval;
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
Svc.Obs.remove("weave:service:backoff:interval", observe);
backoffInterval = subject;
});
function onUIUpdate() {
do_throw("Shouldn't get here!");
}
Svc.Obs.add("weave:ui:login:error", onUIUpdate);
do_check_false(Status.enforceBackoff);
do_check_eq(Status.service, STATUS_OK);
Svc.Obs.add("weave:ui:clear-error", function onLoginFinish() {
Svc.Obs.remove("weave:ui:clear-error", onLoginFinish);
do_check_true(Status.enforceBackoff);
do_check_eq(backoffInterval, 42);
do_check_eq(Status.service, LOGIN_FAILED);
do_check_eq(Status.login, SERVER_MAINTENANCE);
Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
clean();
server.stop(run_next_test);
});
setLastSync(NON_PROLONGED_ERROR_DURATION);
Service.sync();
});
add_test(function test_sync_prolonged_server_maintenance_error() {
// Test prolonged server maintenance errors are reported.
let server = sync_httpd_setup();
setUp();
const BACKOFF = 42;
let engine = Engines.get("catapult");
engine.enabled = true;
engine.exception = {status: 503,
headers: {"retry-after": BACKOFF}};
Svc.Obs.add("weave:ui:sync:error", function onUIUpdate() {
Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
do_check_eq(Status.service, SYNC_FAILED);
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
clean();
server.stop(run_next_test);
});
do_check_eq(Status.service, STATUS_OK);
setLastSync(PROLONGED_ERROR_DURATION);
Service.sync();
});
add_test(function test_info_collections_login_prolonged_server_maintenance_error(){
// Test info/collections prolonged server maintenance errors are reported.
let server = sync_httpd_setup();
setUp();
Service.clusterURL = "http://localhost:8080/maintenance/";
Service.username = "johnsmith";
let backoffInterval;
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
Svc.Obs.remove("weave:service:backoff:interval", observe);
backoffInterval = subject;
});
Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
do_check_true(Status.enforceBackoff);
do_check_eq(backoffInterval, 42);
do_check_eq(Status.service, SYNC_FAILED);
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
clean();
server.stop(run_next_test);
});
do_check_false(Status.enforceBackoff);
do_check_eq(Status.service, STATUS_OK);
setLastSync(PROLONGED_ERROR_DURATION);
Service.sync();
});
add_test(function test_meta_global_login_prolonged_server_maintenance_error(){
// Test meta/global prolonged server maintenance errors are reported.
let server = sync_httpd_setup();
setUp();
Service.clusterURL = "http://localhost:8080/maintenance/";
Service.username = "janesmith";
let backoffInterval;
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
Svc.Obs.remove("weave:service:backoff:interval", observe);
backoffInterval = subject;
});
Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
do_check_true(Status.enforceBackoff);
do_check_eq(backoffInterval, 42);
do_check_eq(Status.service, SYNC_FAILED);
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
clean();
server.stop(run_next_test);
});
do_check_false(Status.enforceBackoff);
do_check_eq(Status.service, STATUS_OK);
setLastSync(PROLONGED_ERROR_DURATION);
Service.sync();
});
add_test(function test_crypto_keys_login_prolonged_server_maintenance_error(){
// Test crypto/keys prolonged server maintenance errors are reported.
let server = sync_httpd_setup();
setUp();
Service.clusterURL = "http://localhost:8080/maintenance/";
Service.username = "foo";
// Force re-download of keys
CollectionKeys.clear();
let backoffInterval;
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
Svc.Obs.remove("weave:service:backoff:interval", observe);
backoffInterval = subject;
});
Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
do_check_true(Status.enforceBackoff);
do_check_eq(backoffInterval, 42);
do_check_eq(Status.service, SYNC_FAILED);
do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
clean();
server.stop(run_next_test);
});
do_check_false(Status.enforceBackoff);
do_check_eq(Status.service, STATUS_OK);
setLastSync(PROLONGED_ERROR_DURATION);
Service.sync();
});
add_test(function test_sync_syncAndReportErrors_server_maintenance_error() {
// Test server maintenance errors are reported
// when calling syncAndReportErrors.
let server = sync_httpd_setup();
setUp();
const BACKOFF = 42;
let engine = Engines.get("catapult");
engine.enabled = true;
engine.exception = {status: 503,
headers: {"retry-after": BACKOFF}};
Svc.Obs.add("weave:ui:sync:error", function onUIUpdate() {
Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
do_check_eq(Status.sync, SERVER_MAINTENANCE);
clean();
server.stop(run_next_test);
});
do_check_eq(Status.service, STATUS_OK);
setLastSync(NON_PROLONGED_ERROR_DURATION);
ErrorHandler.syncAndReportErrors();
});
add_test(function test_info_collections_login_syncAndReportErrors_server_maintenance_error() {
// Test info/collections server maintenance errors are reported
// when calling syncAndReportErrors.
let server = sync_httpd_setup();
setUp();
Service.clusterURL = "http://localhost:8080/maintenance/";
Service.username = "johnsmith";
let backoffInterval;
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
Svc.Obs.remove("weave:service:backoff:interval", observe);
backoffInterval = subject;
});
Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
do_check_true(Status.enforceBackoff);
do_check_eq(backoffInterval, 42);
do_check_eq(Status.service, LOGIN_FAILED);
do_check_eq(Status.login, SERVER_MAINTENANCE);
clean();
server.stop(run_next_test);
});
do_check_false(Status.enforceBackoff);
do_check_eq(Status.service, STATUS_OK);
setLastSync(NON_PROLONGED_ERROR_DURATION);
ErrorHandler.syncAndReportErrors();
});
add_test(function test_meta_global_login_syncAndReportErrors_server_maintenance_error() {
// Test meta/global server maintenance errors are reported
// when calling syncAndReportErrors.
let server = sync_httpd_setup();
setUp();
Service.clusterURL = "http://localhost:8080/maintenance/";
Service.username = "janesmith";
let backoffInterval;
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
Svc.Obs.remove("weave:service:backoff:interval", observe);
backoffInterval = subject;
});
Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
do_check_true(Status.enforceBackoff);
do_check_eq(backoffInterval, 42);
do_check_eq(Status.service, LOGIN_FAILED);
do_check_eq(Status.login, SERVER_MAINTENANCE);
clean();
server.stop(run_next_test);
});
do_check_false(Status.enforceBackoff);
do_check_eq(Status.service, STATUS_OK);
setLastSync(NON_PROLONGED_ERROR_DURATION);
ErrorHandler.syncAndReportErrors();
});
add_test(function test_crypto_keys_login_syncAndReportErrors_server_maintenance_error() {
// Test crypto/keys server maintenance errors are reported
// when calling syncAndReportErrors.
let server = sync_httpd_setup();
setUp();
Service.clusterURL = "http://localhost:8080/maintenance/";
Service.username = "foo";
// Force re-download of keys
CollectionKeys.clear();
let backoffInterval;
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
Svc.Obs.remove("weave:service:backoff:interval", observe);
backoffInterval = subject;
});
Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
do_check_true(Status.enforceBackoff);
do_check_eq(backoffInterval, 42);
do_check_eq(Status.service, LOGIN_FAILED);
do_check_eq(Status.login, SERVER_MAINTENANCE);
clean();
server.stop(run_next_test);
});
do_check_false(Status.enforceBackoff);
do_check_eq(Status.service, STATUS_OK);
setLastSync(NON_PROLONGED_ERROR_DURATION);
ErrorHandler.syncAndReportErrors();
});
add_test(function test_sync_syncAndReportErrors_prolonged_server_maintenance_error() {
// Test prolonged server maintenance errors are
// reported when calling syncAndReportErrors.
let server = sync_httpd_setup();
setUp();
const BACKOFF = 42;
let engine = Engines.get("catapult");
engine.enabled = true;
engine.exception = {status: 503,
headers: {"retry-after": BACKOFF}};
Svc.Obs.add("weave:ui:sync:error", function onUIUpdate() {
Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
do_check_eq(Status.sync, SERVER_MAINTENANCE);
clean();
server.stop(run_next_test);
});
do_check_eq(Status.service, STATUS_OK);
setLastSync(PROLONGED_ERROR_DURATION);
ErrorHandler.syncAndReportErrors();
});
add_test(function test_info_collections_login_syncAndReportErrors_prolonged_server_maintenance_error() {
// Test info/collections server maintenance errors are reported
// when calling syncAndReportErrors.
let server = sync_httpd_setup();
setUp();
Service.clusterURL = "http://localhost:8080/maintenance/";
Service.username = "johnsmith";
let backoffInterval;
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
Svc.Obs.remove("weave:service:backoff:interval", observe);
backoffInterval = subject;
});
Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
do_check_true(Status.enforceBackoff);
do_check_eq(backoffInterval, 42);
do_check_eq(Status.service, LOGIN_FAILED);
do_check_eq(Status.login, SERVER_MAINTENANCE);
clean();
server.stop(run_next_test);
});
do_check_false(Status.enforceBackoff);
do_check_eq(Status.service, STATUS_OK);
setLastSync(PROLONGED_ERROR_DURATION);
ErrorHandler.syncAndReportErrors();
});
add_test(function test_meta_global_login_syncAndReportErrors_prolonged_server_maintenance_error() {
// Test meta/global server maintenance errors are reported
// when calling syncAndReportErrors.
let server = sync_httpd_setup();
setUp();
Service.clusterURL = "http://localhost:8080/maintenance/";
Service.username = "janesmith";
let backoffInterval;
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
Svc.Obs.remove("weave:service:backoff:interval", observe);
backoffInterval = subject;
});
Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
do_check_true(Status.enforceBackoff);
do_check_eq(backoffInterval, 42);
do_check_eq(Status.service, LOGIN_FAILED);
do_check_eq(Status.login, SERVER_MAINTENANCE);
clean();
server.stop(run_next_test);
});
do_check_false(Status.enforceBackoff);
do_check_eq(Status.service, STATUS_OK);
setLastSync(PROLONGED_ERROR_DURATION);
ErrorHandler.syncAndReportErrors();
});
add_test(function test_crypto_keys_login_syncAndReportErrors_prolonged_server_maintenance_error() {
// Test crypto/keys server maintenance errors are reported
// when calling syncAndReportErrors.
let server = sync_httpd_setup();
setUp();
Service.clusterURL = "http://localhost:8080/maintenance/";
Service.username = "foo";
// Force re-download of keys
CollectionKeys.clear();
let backoffInterval;
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
Svc.Obs.remove("weave:service:backoff:interval", observe);
backoffInterval = subject;
});
Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
do_check_true(Status.enforceBackoff);
do_check_eq(backoffInterval, 42);
do_check_eq(Status.service, LOGIN_FAILED);
do_check_eq(Status.login, SERVER_MAINTENANCE);
clean();
server.stop(run_next_test);
});
do_check_false(Status.enforceBackoff);
do_check_eq(Status.service, STATUS_OK);
setLastSync(PROLONGED_ERROR_DURATION);
ErrorHandler.syncAndReportErrors();
});
add_test(function test_sync_engine_generic_fail() {
let server = sync_httpd_setup();
let engine = Engines.get("catapult");
engine.enabled = true;
engine.sync = function sync() {
Svc.Obs.notify("weave:engine:sync:error", "", "catapult");
};
let log = Log4Moz.repository.getLogger("Sync.ErrorHandler");
Svc.Prefs.set("log.appender.file.logOnError", true);
Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
// Put these checks here, not after sync(), so that we aren't racing the
// log handler... which resets everything just a few lines below!
_("Status.engines: " + JSON.stringify(Status.engines));
do_check_eq(Status.engines["catapult"], ENGINE_UNKNOWN_FAIL);
do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
// Test Error log was written on SYNC_FAILED_PARTIAL.
let entries = logsdir.directoryEntries;
do_check_true(entries.hasMoreElements());
let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
do_check_eq(logfile.leafName.slice(0, LOG_PREFIX_ERROR.length),
LOG_PREFIX_ERROR);
clean();
server.stop(run_next_test);
});
do_check_eq(Status.engines["catapult"], undefined);
do_check_true(setUp());
Service.sync();
});
// This test should be the last one since it monkeypatches the engine object
// and we should only have one engine object throughout the file (bug 629664).
add_test(function test_engine_applyFailed() {
let server = sync_httpd_setup();
let engine = Engines.get("catapult");
engine.enabled = true;
delete engine.exception;
engine.sync = function sync() {
Svc.Obs.notify("weave:engine:sync:applied", {newFailed:1}, "catapult");
};
let log = Log4Moz.repository.getLogger("Sync.ErrorHandler");
Svc.Prefs.set("log.appender.file.logOnError", true);
Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
do_check_eq(Status.engines["catapult"], ENGINE_APPLY_FAIL);
do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
// Test Error log was written on SYNC_FAILED_PARTIAL.
let entries = logsdir.directoryEntries;
do_check_true(entries.hasMoreElements());
let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
do_check_eq(logfile.leafName.slice(0, LOG_PREFIX_ERROR.length),
LOG_PREFIX_ERROR);
clean();
server.stop(run_next_test);
});
do_check_eq(Status.engines["catapult"], undefined);
do_check_true(setUp());
Service.sync();
});