services/sync/tests/unit/test_errorhandler_sync_checkServerError.js

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

mercurial