services/sync/tests/unit/test_errorhandler_sync_checkServerError.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* Any copyright is dedicated to the Public Domain.
michael@0 2 http://creativecommons.org/publicdomain/zero/1.0/ */
michael@0 3
michael@0 4 Cu.import("resource://services-sync/constants.js");
michael@0 5 Cu.import("resource://services-sync/engines.js");
michael@0 6 Cu.import("resource://services-sync/policies.js");
michael@0 7 Cu.import("resource://services-sync/record.js");
michael@0 8 Cu.import("resource://services-sync/service.js");
michael@0 9 Cu.import("resource://services-sync/status.js");
michael@0 10 Cu.import("resource://services-sync/util.js");
michael@0 11 Cu.import("resource://testing-common/services/sync/fakeservices.js");
michael@0 12 Cu.import("resource://testing-common/services/sync/utils.js");
michael@0 13
michael@0 14 initTestLogging("Trace");
michael@0 15
michael@0 16 let engineManager = Service.engineManager;
michael@0 17 engineManager.clear();
michael@0 18
michael@0 19 function promiseStopServer(server) {
michael@0 20 let deferred = Promise.defer();
michael@0 21 server.stop(deferred.resolve);
michael@0 22 return deferred.promise;
michael@0 23 }
michael@0 24
michael@0 25 function CatapultEngine() {
michael@0 26 SyncEngine.call(this, "Catapult", Service);
michael@0 27 }
michael@0 28 CatapultEngine.prototype = {
michael@0 29 __proto__: SyncEngine.prototype,
michael@0 30 exception: null, // tests fill this in
michael@0 31 _sync: function _sync() {
michael@0 32 throw this.exception;
michael@0 33 }
michael@0 34 };
michael@0 35
michael@0 36 function sync_httpd_setup() {
michael@0 37 let collectionsHelper = track_collections_helper();
michael@0 38 let upd = collectionsHelper.with_updated_collection;
michael@0 39 let collections = collectionsHelper.collections;
michael@0 40
michael@0 41 let catapultEngine = engineManager.get("catapult");
michael@0 42 let engines = {catapult: {version: catapultEngine.version,
michael@0 43 syncID: catapultEngine.syncID}};
michael@0 44
michael@0 45 // Track these using the collections helper, which keeps modified times
michael@0 46 // up-to-date.
michael@0 47 let clientsColl = new ServerCollection({}, true);
michael@0 48 let keysWBO = new ServerWBO("keys");
michael@0 49 let globalWBO = new ServerWBO("global", {storageVersion: STORAGE_VERSION,
michael@0 50 syncID: Utils.makeGUID(),
michael@0 51 engines: engines});
michael@0 52
michael@0 53 let handlers = {
michael@0 54 "/1.1/johndoe/info/collections": collectionsHelper.handler,
michael@0 55 "/1.1/johndoe/storage/meta/global": upd("meta", globalWBO.handler()),
michael@0 56 "/1.1/johndoe/storage/clients": upd("clients", clientsColl.handler()),
michael@0 57 "/1.1/johndoe/storage/crypto/keys": upd("crypto", keysWBO.handler())
michael@0 58 };
michael@0 59 return httpd_setup(handlers);
michael@0 60 }
michael@0 61
michael@0 62 function setUp(server) {
michael@0 63 yield configureIdentity({username: "johndoe"});
michael@0 64 Service.serverURL = server.baseURI + "/";
michael@0 65 Service.clusterURL = server.baseURI + "/";
michael@0 66 new FakeCryptoService();
michael@0 67 }
michael@0 68
michael@0 69 function generateAndUploadKeys(server) {
michael@0 70 generateNewKeys(Service.collectionKeys);
michael@0 71 let serverKeys = Service.collectionKeys.asWBO("crypto", "keys");
michael@0 72 serverKeys.encrypt(Service.identity.syncKeyBundle);
michael@0 73 let res = Service.resource(server.baseURI + "/1.1/johndoe/storage/crypto/keys");
michael@0 74 return serverKeys.upload(res).success;
michael@0 75 }
michael@0 76
michael@0 77
michael@0 78 add_identity_test(this, function test_backoff500() {
michael@0 79 _("Test: HTTP 500 sets backoff status.");
michael@0 80 let server = sync_httpd_setup();
michael@0 81 yield setUp(server);
michael@0 82
michael@0 83 let engine = engineManager.get("catapult");
michael@0 84 engine.enabled = true;
michael@0 85 engine.exception = {status: 500};
michael@0 86
michael@0 87 try {
michael@0 88 do_check_false(Status.enforceBackoff);
michael@0 89
michael@0 90 // Forcibly create and upload keys here -- otherwise we don't get to the 500!
michael@0 91 do_check_true(generateAndUploadKeys(server));
michael@0 92
michael@0 93 Service.login();
michael@0 94 Service.sync();
michael@0 95 do_check_true(Status.enforceBackoff);
michael@0 96 do_check_eq(Status.sync, SYNC_SUCCEEDED);
michael@0 97 do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
michael@0 98 } finally {
michael@0 99 Status.resetBackoff();
michael@0 100 Service.startOver();
michael@0 101 }
michael@0 102 yield promiseStopServer(server);
michael@0 103 });
michael@0 104
michael@0 105 add_identity_test(this, function test_backoff503() {
michael@0 106 _("Test: HTTP 503 with Retry-After header leads to backoff notification and sets backoff status.");
michael@0 107 let server = sync_httpd_setup();
michael@0 108 yield setUp(server);
michael@0 109
michael@0 110 const BACKOFF = 42;
michael@0 111 let engine = engineManager.get("catapult");
michael@0 112 engine.enabled = true;
michael@0 113 engine.exception = {status: 503,
michael@0 114 headers: {"retry-after": BACKOFF}};
michael@0 115
michael@0 116 let backoffInterval;
michael@0 117 Svc.Obs.add("weave:service:backoff:interval", function (subject) {
michael@0 118 backoffInterval = subject;
michael@0 119 });
michael@0 120
michael@0 121 try {
michael@0 122 do_check_false(Status.enforceBackoff);
michael@0 123
michael@0 124 do_check_true(generateAndUploadKeys(server));
michael@0 125
michael@0 126 Service.login();
michael@0 127 Service.sync();
michael@0 128
michael@0 129 do_check_true(Status.enforceBackoff);
michael@0 130 do_check_eq(backoffInterval, BACKOFF);
michael@0 131 do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
michael@0 132 do_check_eq(Status.sync, SERVER_MAINTENANCE);
michael@0 133 } finally {
michael@0 134 Status.resetBackoff();
michael@0 135 Status.resetSync();
michael@0 136 Service.startOver();
michael@0 137 }
michael@0 138 yield promiseStopServer(server);
michael@0 139 });
michael@0 140
michael@0 141 add_identity_test(this, function test_overQuota() {
michael@0 142 _("Test: HTTP 400 with body error code 14 means over quota.");
michael@0 143 let server = sync_httpd_setup();
michael@0 144 yield setUp(server);
michael@0 145
michael@0 146 let engine = engineManager.get("catapult");
michael@0 147 engine.enabled = true;
michael@0 148 engine.exception = {status: 400,
michael@0 149 toString: function() "14"};
michael@0 150
michael@0 151 try {
michael@0 152 do_check_eq(Status.sync, SYNC_SUCCEEDED);
michael@0 153
michael@0 154 do_check_true(generateAndUploadKeys(server));
michael@0 155
michael@0 156 Service.login();
michael@0 157 Service.sync();
michael@0 158
michael@0 159 do_check_eq(Status.sync, OVER_QUOTA);
michael@0 160 do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
michael@0 161 } finally {
michael@0 162 Status.resetSync();
michael@0 163 Service.startOver();
michael@0 164 }
michael@0 165 yield promiseStopServer(server);
michael@0 166 });
michael@0 167
michael@0 168 add_identity_test(this, function test_service_networkError() {
michael@0 169 _("Test: Connection refused error from Service.sync() leads to the right status code.");
michael@0 170 let server = sync_httpd_setup();
michael@0 171 yield setUp(server);
michael@0 172 let deferred = Promise.defer();
michael@0 173 server.stop(() => {
michael@0 174 // Provoke connection refused.
michael@0 175 Service.clusterURL = "http://localhost:12345/";
michael@0 176
michael@0 177 try {
michael@0 178 do_check_eq(Status.sync, SYNC_SUCCEEDED);
michael@0 179
michael@0 180 Service._loggedIn = true;
michael@0 181 Service.sync();
michael@0 182
michael@0 183 do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
michael@0 184 do_check_eq(Status.service, SYNC_FAILED);
michael@0 185 } finally {
michael@0 186 Status.resetSync();
michael@0 187 Service.startOver();
michael@0 188 }
michael@0 189 deferred.resolve();
michael@0 190 });
michael@0 191 yield deferred.promise;
michael@0 192 });
michael@0 193
michael@0 194 add_identity_test(this, function test_service_offline() {
michael@0 195 _("Test: Wanting to sync in offline mode leads to the right status code but does not increment the ignorable error count.");
michael@0 196 let server = sync_httpd_setup();
michael@0 197 yield setUp(server);
michael@0 198 let deferred = Promise.defer();
michael@0 199 server.stop(() => {
michael@0 200 Services.io.offline = true;
michael@0 201
michael@0 202 try {
michael@0 203 do_check_eq(Status.sync, SYNC_SUCCEEDED);
michael@0 204
michael@0 205 Service._loggedIn = true;
michael@0 206 Service.sync();
michael@0 207
michael@0 208 do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
michael@0 209 do_check_eq(Status.service, SYNC_FAILED);
michael@0 210 } finally {
michael@0 211 Status.resetSync();
michael@0 212 Service.startOver();
michael@0 213 }
michael@0 214 Services.io.offline = false;
michael@0 215 deferred.resolve();
michael@0 216 });
michael@0 217 yield deferred.promise;
michael@0 218 });
michael@0 219
michael@0 220 add_identity_test(this, function test_engine_networkError() {
michael@0 221 _("Test: Network related exceptions from engine.sync() lead to the right status code.");
michael@0 222 let server = sync_httpd_setup();
michael@0 223 yield setUp(server);
michael@0 224
michael@0 225 let engine = engineManager.get("catapult");
michael@0 226 engine.enabled = true;
michael@0 227 engine.exception = Components.Exception("NS_ERROR_UNKNOWN_HOST",
michael@0 228 Cr.NS_ERROR_UNKNOWN_HOST);
michael@0 229
michael@0 230 try {
michael@0 231 do_check_eq(Status.sync, SYNC_SUCCEEDED);
michael@0 232
michael@0 233 do_check_true(generateAndUploadKeys(server));
michael@0 234
michael@0 235 Service.login();
michael@0 236 Service.sync();
michael@0 237
michael@0 238 do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
michael@0 239 do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
michael@0 240 } finally {
michael@0 241 Status.resetSync();
michael@0 242 Service.startOver();
michael@0 243 }
michael@0 244 yield promiseStopServer(server);
michael@0 245 });
michael@0 246
michael@0 247 add_identity_test(this, function test_resource_timeout() {
michael@0 248 let server = sync_httpd_setup();
michael@0 249 yield setUp(server);
michael@0 250
michael@0 251 let engine = engineManager.get("catapult");
michael@0 252 engine.enabled = true;
michael@0 253 // Resource throws this when it encounters a timeout.
michael@0 254 engine.exception = Components.Exception("Aborting due to channel inactivity.",
michael@0 255 Cr.NS_ERROR_NET_TIMEOUT);
michael@0 256
michael@0 257 try {
michael@0 258 do_check_eq(Status.sync, SYNC_SUCCEEDED);
michael@0 259
michael@0 260 do_check_true(generateAndUploadKeys(server));
michael@0 261
michael@0 262 Service.login();
michael@0 263 Service.sync();
michael@0 264
michael@0 265 do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
michael@0 266 do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
michael@0 267 } finally {
michael@0 268 Status.resetSync();
michael@0 269 Service.startOver();
michael@0 270 }
michael@0 271 yield promiseStopServer(server);
michael@0 272 });
michael@0 273
michael@0 274 function run_test() {
michael@0 275 engineManager.register(CatapultEngine);
michael@0 276 run_next_test();
michael@0 277 }

mercurial