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

314 lines
8.3 KiB
JavaScript

Cu.import("resource://services-sync/engines.js");
Cu.import("resource://services-sync/status.js");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/util.js");
Svc.DefaultPrefs.set("registerEngines", "");
Cu.import("resource://services-sync/service.js");
Cu.import("resource://services-sync/record.js");
initTestLogging();
function CatapultEngine() {
SyncEngine.call(this, "Catapult");
}
CatapultEngine.prototype = {
__proto__: SyncEngine.prototype,
exception: null, // tests fill this in
sync: function sync() {
throw this.exception;
}
};
function sync_httpd_setup() {
let collectionsHelper = track_collections_helper();
let upd = collectionsHelper.with_updated_collection;
let collections = collectionsHelper.collections;
let catapultEngine = Engines.get("catapult");
let engines = {catapult: {version: catapultEngine.version,
syncID: catapultEngine.syncID}};
// Track these using the collections helper, which keeps modified times
// up-to-date.
let clientsColl = new ServerCollection({}, true);
let keysWBO = new ServerWBO("keys");
let globalWBO = new ServerWBO("global", {storageVersion: STORAGE_VERSION,
syncID: Utils.makeGUID(),
engines: engines});
let handlers = {
"/1.1/johndoe/info/collections": collectionsHelper.handler,
"/1.1/johndoe/storage/meta/global": upd("meta", globalWBO.handler()),
"/1.1/johndoe/storage/clients": upd("clients", clientsColl.handler()),
"/1.1/johndoe/storage/crypto/keys": upd("crypto", keysWBO.handler())
};
return httpd_setup(handlers);
}
function setUp() {
Service.username = "johndoe";
Service.password = "ilovejane";
Service.passphrase = "aabcdeabcdeabcdeabcdeabcde";
Service.clusterURL = "http://localhost:8080/";
new FakeCryptoService();
}
function generateAndUploadKeys() {
generateNewKeys();
let serverKeys = CollectionKeys.asWBO("crypto", "keys");
serverKeys.encrypt(Weave.Service.syncKeyBundle);
return serverKeys.upload("http://localhost:8080/1.1/johndoe/storage/crypto/keys").success;
}
add_test(function test_backoff500() {
_("Test: HTTP 500 sets backoff status.");
setUp();
let server = sync_httpd_setup();
let engine = Engines.get("catapult");
engine.enabled = true;
engine.exception = {status: 500};
try {
do_check_false(Status.enforceBackoff);
// Forcibly create and upload keys here -- otherwise we don't get to the 500!
do_check_true(generateAndUploadKeys());
Service.login();
Service.sync();
do_check_true(Status.enforceBackoff);
} finally {
Status.resetBackoff();
Service.startOver();
}
server.stop(run_next_test);
});
add_test(function test_backoff503() {
_("Test: HTTP 503 with Retry-After header leads to backoff notification and sets backoff status.");
setUp();
let server = sync_httpd_setup();
const BACKOFF = 42;
let engine = Engines.get("catapult");
engine.enabled = true;
engine.exception = {status: 503,
headers: {"retry-after": BACKOFF}};
let backoffInterval;
Svc.Obs.add("weave:service:backoff:interval", function (subject) {
backoffInterval = subject;
});
try {
do_check_false(Status.enforceBackoff);
do_check_true(generateAndUploadKeys());
Service.login();
Service.sync();
do_check_true(Status.enforceBackoff);
do_check_eq(backoffInterval, BACKOFF);
} finally {
Status.resetBackoff();
Service.startOver();
}
server.stop(run_next_test);
});
add_test(function test_overQuota() {
_("Test: HTTP 400 with body error code 14 means over quota.");
setUp();
let server = sync_httpd_setup();
let engine = Engines.get("catapult");
engine.enabled = true;
engine.exception = {status: 400,
toString: function() "14"};
try {
do_check_eq(Status.sync, SYNC_SUCCEEDED);
do_check_true(generateAndUploadKeys());
Service.login();
Service.sync();
do_check_eq(Status.sync, OVER_QUOTA);
} finally {
Status.resetSync();
Service.startOver();
}
server.stop(run_next_test);
});
add_test(function test_service_networkError() {
_("Test: Connection refused error from Service.sync() leads to the right status code.");
setUp();
// Provoke connection refused.
Service.clusterURL = "http://localhost:12345/";
Service._ignorableErrorCount = 0;
try {
do_check_eq(Status.sync, SYNC_SUCCEEDED);
Service._loggedIn = true;
Service.sync();
do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
do_check_eq(Service._ignorableErrorCount, 1);
} finally {
Status.resetSync();
Service.startOver();
}
run_next_test();
});
add_test(function test_service_offline() {
_("Test: Wanting to sync in offline mode leads to the right status code but does not increment the ignorable error count.");
setUp();
Services.io.offline = true;
Service._ignorableErrorCount = 0;
try {
do_check_eq(Status.sync, SYNC_SUCCEEDED);
Service._loggedIn = true;
Service.sync();
do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
do_check_eq(Service._ignorableErrorCount, 0);
} finally {
Status.resetSync();
Service.startOver();
}
Services.io.offline = false;
run_next_test();
});
add_test(function test_service_reset_ignorableErrorCount() {
_("Test: Successful sync resets the ignorable error count.");
setUp();
let server = sync_httpd_setup();
Service._ignorableErrorCount = 10;
// Disable the engine so that sync completes.
let engine = Engines.get("catapult");
engine.enabled = false;
try {
do_check_eq(Status.sync, SYNC_SUCCEEDED);
do_check_true(generateAndUploadKeys());
Service.login();
Service.sync();
do_check_eq(Status.sync, SYNC_SUCCEEDED);
do_check_eq(Service._ignorableErrorCount, 0);
} finally {
Status.resetSync();
Service.startOver();
}
server.stop(run_next_test);
});
add_test(function test_engine_networkError() {
_("Test: Network related exceptions from engine.sync() lead to the right status code.");
setUp();
let server = sync_httpd_setup();
Service._ignorableErrorCount = 0;
let engine = Engines.get("catapult");
engine.enabled = true;
engine.exception = Components.Exception("NS_ERROR_UNKNOWN_HOST",
Cr.NS_ERROR_UNKNOWN_HOST);
try {
do_check_eq(Status.sync, SYNC_SUCCEEDED);
do_check_true(generateAndUploadKeys());
Service.login();
Service.sync();
do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
do_check_eq(Service._ignorableErrorCount, 1);
} finally {
Status.resetSync();
Service.startOver();
}
server.stop(run_next_test);
});
add_test(function test_resource_timeout() {
setUp();
let server = sync_httpd_setup();
let engine = Engines.get("catapult");
engine.enabled = true;
// Resource throws this when it encounters a timeout.
engine.exception = Components.Exception("Aborting due to channel inactivity.",
Cr.NS_ERROR_NET_TIMEOUT);
try {
do_check_eq(Status.sync, SYNC_SUCCEEDED);
do_check_true(generateAndUploadKeys());
Service.login();
Service.sync();
do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
} finally {
Status.resetSync();
Service.startOver();
}
server.stop(run_next_test);
});
// Slightly misplaced test as it doesn't actually test checkServerError,
// but the observer for "weave:engine:sync:apply-failed".
// 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() {
setUp();
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:apply-failed", {}, "steam");
};
try {
do_check_eq(Status.engines["steam"], undefined);
do_check_true(generateAndUploadKeys());
Service.login();
Service.sync();
do_check_eq(Status.engines["steam"], ENGINE_APPLY_FAIL);
} finally {
Status.resetSync();
Service.startOver();
}
server.stop(run_next_test);
});
function run_test() {
if (DISABLE_TESTS_BUG_604565)
return;
Engines.register(CatapultEngine);
run_next_test();
}