Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: test/synchronizer.js

Issue 29355872: Issue 4223 - Adapt synchronizer tests to work in adblockpluscore repository (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore
Patch Set: Converted former loops into separate tests Created Oct. 5, 2016, 9:24 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « test/stub-modules/utils.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 (function() 1 /*
2 { 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 let testRunner = null; 3 * Copyright (C) 2006-2016 Eyeo GmbH
4 let requestHandlers = null; 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 "use strict";
19
20 let {createSandbox} = require("./_common");
21
22 const MILLIS_IN_SECOND = 1000;
23 const MILLIS_IN_MINUTE = 60 * MILLIS_IN_SECOND;
24 const MILLIS_IN_HOUR = 60 * MILLIS_IN_MINUTE;
25 const MILLIS_IN_DAY = 24 * MILLIS_IN_HOUR;
26
27 const Cr = {
28 NS_OK: 0,
29 NS_BINDING_ABORTED: 0x804B0002,
30 NS_ERROR_FAILURE: 0x80004005
31 }
32
33 let Filter = null;
34 let FilterStorage = null;
35 let Prefs = null;
36 let Subscription = null;
37 let Synchronizer = null;
38
39 exports.setUp = function(callback)
40 {
41 let currentTime = 100000 * MILLIS_IN_HOUR;
42 let startTime = currentTime;
43
44 let fakeTimer = {
45 callback: null,
46 delay: -1,
47 nextExecution: 0,
48
49 initWithCallback: function(callback, delay, type)
50 {
51 if (this.callback)
52 throw new Error("Only one timer instance supported");
53 if (type != 1)
54 throw new Error("Only TYPE_REPEATING_SLACK timers supported");
55
56 this.callback = callback;
57 this.delay = delay;
58 this.nextExecution = currentTime + delay;
59 },
60
61 trigger: function()
62 {
63 if (currentTime < this.nextExecution)
64 currentTime = this.nextExecution;
65 try
66 {
67 this.callback();
68 }
69 finally
70 {
71 this.nextExecution = currentTime + this.delay;
72 }
73 },
74
75 cancel: function()
76 {
77 this.nextExecution = -1;
78 }
79 };
80
81 let requests = [];
82 function XMLHttpRequest()
kzar 2016/10/05 11:36:51 Seems kind of wasteful to define XMLHttpRequest an
Wladimir Palant 2016/10/05 12:12:51 Not really - we want a clean environment for every
kzar 2016/10/05 12:18:16 Fair enough.
83 {
84 this._host = "http://example.com";
85 this._loadHandlers = [];
86 this._errorHandlers = [];
87 };
88 XMLHttpRequest.prototype =
89 {
90 _path: null,
91 _data: null,
92 _queryString: null,
93 _loadHandlers: null,
94 _errorHandlers: null,
95 status: 0,
96 readyState: 0,
97 responseText: null,
98
99 addEventListener: function(eventName, handler, capture)
100 {
101 let list;
102 if (eventName == "load")
103 list = this._loadHandlers;
104 else if (eventName == "error")
105 list = this._errorHandlers;
106 else
107 throw new Error("Event type " + eventName + " not supported");
108
109 if (list.indexOf(handler) < 0)
110 list.push(handler);
111 },
112
113 removeEventListener: function(eventName, handler, capture)
114 {
115 let list;
116 if (eventName == "load")
117 list = this._loadHandlers;
118 else if (eventName == "error")
119 list = this._errorHandlers;
120 else
121 throw new Error("Event type " + eventName + " not supported");
122
123 let index = list.indexOf(handler);
124 if (index >= 0)
125 list.splice(index, 1);
126 },
127
128 open: function(method, url, async, user, password)
129 {
130 if (method != "GET")
131 throw new Error("Only GET requests are supported");
132 if (typeof async != "undefined" && !async)
133 throw new Error("Sync requests are not supported");
134 if (typeof user != "undefined" || typeof password != "undefined")
135 throw new Error("User authentification is not supported");
136
137 let match = /^data:[^,]+,/.exec(url);
138 if (match)
139 {
140 this._data = decodeURIComponent(url.substr(match[0].length));
141 return;
142 }
143
144 if (url.substr(0, this._host.length + 1) != this._host + "/")
145 throw new Error("Unexpected URL: " + url + " (URL starting with " + this ._host + "expected)");
146
147 this._path = url.substr(this._host.length);
148
149 let queryIndex = this._path.indexOf("?");
150 this._queryString = "";
151 if (queryIndex >= 0)
152 {
153 this._queryString = this._path.substr(queryIndex + 1);
154 this._path = this._path.substr(0, queryIndex);
155 }
156 },
157
158 send: function(data)
159 {
160 if (!this._data && !this._path)
161 throw new Error("No request path set");
162 if (typeof data != "undefined" && data)
163 throw new Error("Sending data to server is not supported");
164
165 requests.push(Promise.resolve().then(() =>
166 {
167 let result = [Cr.NS_OK, 404, ""];
168 if (this._data)
169 result = [Cr.NS_OK, 0, this._data];
170 else if (this._path in XMLHttpRequest.requestHandlers)
171 {
172 result = XMLHttpRequest.requestHandlers[this._path]({
173 method: "GET",
174 path: this._path,
175 queryString: this._queryString
176 });
177 }
178
179 [this.channel.status, this.channel.responseStatus, this.responseText] = result;
180 this.status = this.channel.responseStatus;
181
182 let eventName = (this.channel.status == Cr.NS_OK ? "load" : "error");
183 let event = {type: eventName};
184 for (let handler of this["_" + eventName + "Handlers"])
185 handler.call(this, event);
186 }));
187 },
188
189 overrideMimeType: function(mime)
190 {
191 },
192
193 channel:
194 {
195 status: -1,
196 responseStatus: 0,
197 loadFlags: 0,
198 INHIBIT_CACHING: 0,
199 VALIDATE_ALWAYS: 0,
200 QueryInterface: () => this
201 }
202 };
203
204 XMLHttpRequest.requestHandlers = {};
205 this.registerHandler = (path, handler) =>
206 {
207 XMLHttpRequest.requestHandlers[path] = handler;
208 };
209
210 function waitForRequests()
211 {
212 if (requests.length)
213 {
214 let result = Promise.all(requests);
215 requests = [];
216 return result.catch(e =>
217 {
218 console.error(e);
219 }).then(() => waitForRequests());
220 }
221 else
222 return Promise.resolve();
223 }
224
225 function runScheduledTasks(maxMillis)
226 {
227 let endTime = currentTime + maxMillis;
228 if (fakeTimer.nextExecution < 0 || fakeTimer.nextExecution > endTime)
229 {
230 currentTime = endTime;
231 return Promise.resolve();
232 }
233 else
234 {
235 fakeTimer.trigger();
236 return waitForRequests().then(() => runScheduledTasks(endTime - currentTim e));
237 }
238
239 currentTime = endTime;
240 }
241
242 this.runScheduledTasks = (maxHours, initial, skip) =>
243 {
244 if (typeof maxHours != "number")
245 throw new Error("Numerical parameter expected");
246 if (typeof initial != "number")
247 initial = 0;
248 if (typeof skip != "number")
249 skip = 0;
250
251 startTime = currentTime;
252 return Promise.resolve().then(() =>
253 {
254 if (initial >= 0)
255 {
256 maxHours -= initial;
257 return runScheduledTasks(initial * MILLIS_IN_HOUR);
258 }
259 }).then(() =>
260 {
261 if (skip >= 0)
262 {
263 maxHours -= skip;
264 currentTime += skip * MILLIS_IN_HOUR;
265 }
266 return runScheduledTasks(maxHours * MILLIS_IN_HOUR);
267 });
268 };
269
270 this.getTimeOffset = () => (currentTime - startTime) / MILLIS_IN_HOUR;
271 Object.defineProperty(this, "currentTime", {
272 get: () => currentTime
273 });
274
5 let randomResult = 0.5; 275 let randomResult = 0.5;
6 276 Object.defineProperty(this, "randomResult", {
7 module("Synchronizer", { 277 get: () => randomResult,
8 setup: function() 278 set: value => randomResult = value
9 { 279 });
10 testRunner = this; 280
11 281 let sandboxedRequire = createSandbox({
12 prepareFilterComponents.call(this); 282 globals: {
13 preparePrefs.call(this); 283 Cc: {
14 284 "@mozilla.org/timer;1": {
15 Synchronizer.init(); 285 createInstance: () => fakeTimer
16 286 }
17 setupVirtualTime.call(this, function(wrapTimer) 287 },
18 { 288 Ci: {
19 let SynchronizerModule = getModuleGlobal("synchronizer"); 289 nsITimer:
20 SynchronizerModule.downloader._timer = wrapTimer(SynchronizerModule.down loader._timer); 290 {
21 }, "synchronizer", "downloader"); 291 TYPE_ONE_SHOT: 0,
22 setupVirtualXMLHttp.call(this, "synchronizer", "downloader"); 292 TYPE_REPEATING_SLACK: 1,
23 293 TYPE_REPEATING_PRECISE: 2
24 // Replace Math.random() function 294 },
25 let DownloaderGlobal = Cu.getGlobalForObject(getModuleGlobal("downloader") ); 295 nsIHttpChannel: () => null,
26 this._origRandom = DownloaderGlobal.Math.random; 296 },
27 DownloaderGlobal.Math.random = () => randomResult; 297 Cr: Cr,
28 randomResult = 0.5; 298 XMLHttpRequest: XMLHttpRequest,
29 }, 299 Date: {
30 300 now: () => currentTime
31 teardown: function() 301 },
32 { 302 Math: {
33 restoreFilterComponents.call(this); 303 random: () => randomResult,
34 restorePrefs.call(this); 304 min: Math.min,
35 restoreVirtualTime.call(this); 305 max: Math.max,
36 restoreVirtualXMLHttp.call(this); 306 round: Math.round
37 307 },
38 if (this._origRandom) 308 URL: function(urlString)
39 { 309 {
40 let DownloaderGlobal = Cu.getGlobalForObject(getModuleGlobal("downloader ")); 310 return require("url").parse(urlString);
41 DownloaderGlobal.Math.random = this._origRandom;
42 delete this._origRandom;
43 } 311 }
44
45 Synchronizer.init();
46 } 312 }
47 }); 313 });
48 314
49 function resetSubscription(subscription) 315 (
50 { 316 {Filter} = sandboxedRequire("../lib/filterClasses"),
51 FilterStorage.updateSubscriptionFilters(subscription, []); 317 {FilterStorage} = sandboxedRequire("../lib/filterStorage"),
52 subscription.lastCheck = subscription.lastDownload = 318 {Prefs} = sandboxedRequire("./stub-modules/prefs"),
53 subscription.version = subscription.lastSuccess = 319 {Subscription} = sandboxedRequire("../lib/subscriptionClasses"),
54 subscription.expires = subscription.softExpiration = 0; 320 {Synchronizer} = sandboxedRequire("../lib/synchronizer")
55 subscription.title = ""; 321 );
56 subscription.homepage = null; 322
57 subscription.errors = 0; 323 callback();
58 subscription.downloadStatus = null; 324 };
59 subscription.requiredVersion = null; 325
60 } 326 function unexpectedError(error)
61 327 {
62 let initialDelay = 1 / 60; 328 console.error(error);
63 329 this.ok(false, "Unexpected error: " + error);
64 test("Downloads of one subscription", function() 330 }
65 { 331
66 let subscription = Subscription.fromURL("http://example.com/subscription"); 332 function resetSubscription(subscription)
67 FilterStorage.addSubscription(subscription); 333 {
68 334 FilterStorage.updateSubscriptionFilters(subscription, []);
69 let requests = []; 335 subscription.lastCheck = subscription.lastDownload =
70 testRunner.registerHandler("/subscription", function(metadata) 336 subscription.version = subscription.lastSuccess =
71 { 337 subscription.expires = subscription.softExpiration = 0;
72 requests.push([testRunner.getTimeOffset(), metadata.method, metadata.path] ); 338 subscription.title = "";
73 return [Cr.NS_OK, 200, "[Adblock]\n! ExPiREs: 1day\nfoo\nbar"]; 339 subscription.homepage = null;
74 }); 340 subscription.errors = 0;
75 341 subscription.downloadStatus = null;
76 testRunner.runScheduledTasks(50); 342 subscription.requiredVersion = null;
77 deepEqual(requests, [ 343 }
344
345 let initialDelay = 1 / 60;
346
347 exports.testOneSubscriptionDownloads = function(test)
348 {
349 let subscription = Subscription.fromURL("http://example.com/subscription");
350 FilterStorage.addSubscription(subscription);
351
352 let requests = [];
353 this.registerHandler("/subscription", metadata =>
kzar 2016/10/05 11:36:51 I guess we could avoid declaring all the module va
Wladimir Palant 2016/10/05 12:12:51 Not during the initial migration - the fewer chang
354 {
355 requests.push([this.getTimeOffset(), metadata.method, metadata.path]);
356 return [Cr.NS_OK, 200, "[Adblock]\n! ExPiREs: 1day\nfoo\nbar"];
357 });
358
359 this.runScheduledTasks(50).then(() =>
360 {
361 test.deepEqual(requests, [
78 [0 + initialDelay, "GET", "/subscription"], 362 [0 + initialDelay, "GET", "/subscription"],
79 [24 + initialDelay, "GET", "/subscription"], 363 [24 + initialDelay, "GET", "/subscription"],
80 [48 + initialDelay, "GET", "/subscription"], 364 [48 + initialDelay, "GET", "/subscription"],
81 ], "Requests after 50 hours"); 365 ], "Requests after 50 hours");
82 }); 366 }).catch(unexpectedError.bind(test)).then(() => test.done());
83 367 };
84 test("Downloads of two subscriptions", function() 368
85 { 369 exports.testTwoSubscriptionsDownloads = function(test)
86 let subscription1 = Subscription.fromURL("http://example.com/subscription1") ; 370 {
87 FilterStorage.addSubscription(subscription1); 371 let subscription1 = Subscription.fromURL("http://example.com/subscription1");
88 372 FilterStorage.addSubscription(subscription1);
89 let subscription2 = Subscription.fromURL("http://example.com/subscription2") ; 373
90 subscription2.expires = 374 let subscription2 = Subscription.fromURL("http://example.com/subscription2");
91 subscription2.softExpiration = 375 subscription2.expires =
92 (testRunner.currentTime + 2 * MILLIS_IN_HOUR) / MILLIS_IN_SECOND; 376 subscription2.softExpiration =
93 FilterStorage.addSubscription(subscription2); 377 (this.currentTime + 2 * MILLIS_IN_HOUR) / MILLIS_IN_SECOND;
94 378 FilterStorage.addSubscription(subscription2);
95 let requests = []; 379
96 function handler(metadata) 380 let requests = [];
97 { 381 let handler = metadata =>
98 requests.push([testRunner.getTimeOffset(), metadata.method, metadata.path] ); 382 {
99 return [Cr.NS_OK, 200, "[Adblock]\n! ExPiREs: 1day\nfoo\nbar"]; 383 requests.push([this.getTimeOffset(), metadata.method, metadata.path]);
100 } 384 return [Cr.NS_OK, 200, "[Adblock]\n! ExPiREs: 1day\nfoo\nbar"];
101 385 };
102 testRunner.registerHandler("/subscription1", handler); 386
103 testRunner.registerHandler("/subscription2", handler); 387 this.registerHandler("/subscription1", handler);
104 388 this.registerHandler("/subscription2", handler);
105 testRunner.runScheduledTasks(55); 389
106 deepEqual(requests, [ 390 this.runScheduledTasks(55).then(() =>
391 {
392 test.deepEqual(requests, [
107 [0 + initialDelay, "GET", "/subscription1"], 393 [0 + initialDelay, "GET", "/subscription1"],
108 [2 + initialDelay, "GET", "/subscription2"], 394 [2 + initialDelay, "GET", "/subscription2"],
109 [24 + initialDelay, "GET", "/subscription1"], 395 [24 + initialDelay, "GET", "/subscription1"],
110 [26 + initialDelay, "GET", "/subscription2"], 396 [26 + initialDelay, "GET", "/subscription2"],
111 [48 + initialDelay, "GET", "/subscription1"], 397 [48 + initialDelay, "GET", "/subscription1"],
112 [50 + initialDelay, "GET", "/subscription2"], 398 [50 + initialDelay, "GET", "/subscription2"],
113 ], "Requests after 55 hours"); 399 ], "Requests after 55 hours");
114 }); 400 }).catch(unexpectedError.bind(test)).then(() => test.done());
115 401 };
116 test("Download result, various subscription headers", function() 402
117 { 403 exports.testSubscriptionHeaders = {};
118 let test; 404
405 for (let currentTest of [
406 {header: "[Adblock]", downloadStatus: "synchronize_ok", requiredVersion: null} ,
407 {header: "[Adblock Plus]", downloadStatus: "synchronize_ok", requiredVersion: null},
408 {header: "(something)[Adblock]", downloadStatus: "synchronize_ok", requiredVer sion: null},
409 {header: "[Adblock Plus 0.0.1]", downloadStatus: "synchronize_ok", requiredVer sion: "0.0.1"},
410 {header: "[Adblock Plus 99.9]", downloadStatus: "synchronize_ok", requiredVers ion: "99.9"},
411 {header: "[Foo]", downloadStatus: "synchronize_invalid_data", requiredVersion: null}
412 ])
413 {
414 exports.testSubscriptionHeaders[currentTest.header] = function(test)
415 {
119 let subscription = Subscription.fromURL("http://example.com/subscription"); 416 let subscription = Subscription.fromURL("http://example.com/subscription");
120 FilterStorage.addSubscription(subscription); 417 FilterStorage.addSubscription(subscription);
121 418
122 testRunner.registerHandler("/subscription", function(metadata) 419 this.registerHandler("/subscription", metadata =>
123 { 420 {
124 return [Cr.NS_OK, 200, test.header + "\n!Expires: 8 hours\nfoo\n!bar\n\n@@ bas\n#bam"]; 421 return [Cr.NS_OK, 200, currentTest.header + "\n!Expires: 8 hours\nfoo\n!ba r\n\n@@bas\n#bam"];
125 }); 422 });
126 423
127 let tests = [ 424 this.runScheduledTasks(2).then(() =>
128 {header: "[Adblock]", downloadStatus: "synchronize_ok", requiredVersion: n ull}, 425 {
129 {header: "[Adblock Plus]", downloadStatus: "synchronize_ok", requiredVersi on: null}, 426 test.equal(subscription.downloadStatus, currentTest.downloadStatus, "Downl oad status");
130 {header: "(something)[Adblock]", downloadStatus: "synchronize_ok", require dVersion: null}, 427 test.equal(subscription.requiredVersion, currentTest.requiredVersion, "Req uired version");
131 {header: "[Adblock Plus 0.0.1]", downloadStatus: "synchronize_ok", require dVersion: "0.0.1"}, 428
132 {header: "[Adblock Plus 99.9]", downloadStatus: "synchronize_ok", required Version: "99.9"}, 429 if (currentTest.downloadStatus == "synchronize_ok")
133 {header: "[Foo]", downloadStatus: "synchronize_invalid_data", requiredVers ion: null} 430 {
134 ]; 431 test.deepEqual(subscription.filters, [
135 for (test of tests)
136 {
137 resetSubscription(subscription)
138 testRunner.runScheduledTasks(2);
139
140 equal(subscription.downloadStatus, test.downloadStatus, "Download status f or " + test.header)
141 equal(subscription.requiredVersion, test.requiredVersion, "Required versio n for " + test.header)
142
143 if (test.downloadStatus == "synchronize_ok")
144 {
145 deepEqual(subscription.filters, [
146 Filter.fromText("foo"), 432 Filter.fromText("foo"),
147 Filter.fromText("!bar"), 433 Filter.fromText("!bar"),
148 Filter.fromText("@@bas"), 434 Filter.fromText("@@bas"),
149 Filter.fromText("#bam"), 435 Filter.fromText("#bam"),
150 ], "Resulting subscription filters for " + test.header); 436 ], "Resulting subscription filters");
151 } 437 }
152 else 438 else
153 { 439 {
154 deepEqual(subscription.filters, [ 440 test.deepEqual(subscription.filters, [
155 ], "Resulting subscription filters for " + test.header); 441 ], "Resulting subscription filters");
156 } 442 }
157 } 443 }).catch(unexpectedError.bind(test)).then(() => test.done());
158 }) 444 };
159 445 }
160 test("Automatic updates disabled", function() 446
161 { 447 exports.testsDisabledUpdates = function(test)
162 Prefs.subscriptions_autoupdate = false; 448 {
163 449 Prefs.subscriptions_autoupdate = false;
450
451 let subscription = Subscription.fromURL("http://example.com/subscription");
452 FilterStorage.addSubscription(subscription);
453
454 let requests = 0;
455 this.registerHandler("/subscription", metadata =>
456 {
457 requests++;
458 throw new Error("Unexpected request");
459 });
460
461 this.runScheduledTasks(50).then(() =>
462 {
463 test.equal(requests, 0, "Request count");
464 }).catch(unexpectedError.bind(test)).then(() => test.done());
465 };
466
467 exports.testExpirationTime = {};
468
469 for (let currentTest of [
470 {
471 expiration: "default",
472 randomResult: 0.5,
473 requests: [0 + initialDelay, 5 * 24 + initialDelay]
474 },
475 {
476 expiration: "1 hours", // Minimal expiration interval
477 randomResult: 0.5,
478 requests: [0 + initialDelay, 1 + initialDelay, 2 + initialDelay, 3 + initial Delay]
479 },
480 {
481 expiration: "26 hours",
482 randomResult: 0.5,
483 requests: [0 + initialDelay, 26 + initialDelay]
484 },
485 {
486 expiration: "2 days",
487 randomResult: 0.5,
488 requests: [0 + initialDelay, 48 + initialDelay]
489 },
490 {
491 expiration: "20 days", // Too large, will be corrected
492 randomResult: 0.5,
493 requests: [0 + initialDelay, 14 * 24 + initialDelay]
494 },
495 {
496 expiration: "35 hours",
497 randomResult: 0, // Changes interval by factor 0.8
498 requests: [0 + initialDelay, 28 + initialDelay]
499 },
500 {
501 expiration: "35 hours",
502 randomResult: 1, // Changes interval by factor 1.2
503 requests: [0 + initialDelay, 42 + initialDelay]
504 },
505 {
506 expiration: "35 hours",
507 randomResult: 0.25, // Changes interval by factor 0.9
508 requests: [0 + initialDelay, 32 + initialDelay]
509 },
510 {
511 expiration: "40 hours",
512 randomResult: 0.5,
513 skipAfter: 5 + initialDelay,
514 skip: 10, // Short break should not increase soft expiration
515 requests: [0 + initialDelay, 40 + initialDelay]
516 },
517 {
518 expiration: "40 hours",
519 randomResult: 0.5,
520 skipAfter: 5 + initialDelay,
521 skip: 30, // Long break should increase soft expiration
522 requests: [0 + initialDelay, 70 + initialDelay]
523 },
524 {
525 expiration: "40 hours",
526 randomResult: 0.5,
527 skipAfter: 5 + initialDelay,
528 skip: 80, // Hitting hard expiration, immediate download
529 requests: [0 + initialDelay, 85 + initialDelay]
530 }
531 ])
532 {
533 let testId = `"${currentTest.expiration}"`;
534 if (currentTest.randomResult != 0.5)
535 testId += " with Math.random() returning " + currentTest.randomResult;
536 if (currentTest.skip)
537 testId += " skipping " + currentTest.skip + " hours after " + currentTest.sk ipAfter + " hours";
538 exports.testExpirationTime[testId] = function(test)
539 {
164 let subscription = Subscription.fromURL("http://example.com/subscription"); 540 let subscription = Subscription.fromURL("http://example.com/subscription");
165 FilterStorage.addSubscription(subscription); 541 FilterStorage.addSubscription(subscription);
166 542
167 let requests = 0; 543 let requests = [];
168 testRunner.registerHandler("/subscription", function(metadata) 544 this.registerHandler("/subscription", metadata =>
169 { 545 {
170 requests++; 546 requests.push(this.getTimeOffset());
171 throw new Error("Unexpected request"); 547 return [Cr.NS_OK, 200, "[Adblock]\nfoo\n!Expires: " + currentTest.expirati on + "\nbar"];
172 }); 548 });
173 549
174 testRunner.runScheduledTasks(50); 550 this.randomResult = currentTest.randomResult;
175 equal(requests, 0, "Request count"); 551
176 }); 552 let maxHours = Math.round(Math.max.apply(null, currentTest.requests)) + 1;
177 553 this.runScheduledTasks(maxHours, currentTest.skipAfter, currentTest.skip).th en(() =>
178 test("Expiration time", function() 554 {
555 test.deepEqual(requests, currentTest.requests, "Requests");
556 }).catch(unexpectedError.bind(test)).then(() => test.done());
557 };
558 }
559
560 exports.testChecksumVerification = {};
561
562 for (let [testName, subscriptionBody, expectedResult] of [
563 ["Correct checksum", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\nfoo\nbar\ n", true],
564 ["Wrong checksum", "[Adblock]\n! Checksum: wrongggny6Fn24b7JHsq/A\nfoo\nbar\n" , false],
565 ["Empty lines ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\n\nfoo\ n\nbar\n\n", true],
566 ["CR LF line breaks treated like LR", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7 JHsq/A\nfoo\r\nbar\r\n", true],
567 ["CR line breaks treated like LR", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHs q/A\nfoo\rbar\r", true],
568 ["Trailing line break not ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JH sq/A\nfoo\nbar", false],
569 ["Line breaks between lines not ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn 24b7JHsq/A\nfoobar", false],
570 ["Lines with spaces not ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq /A\n \nfoo\n\nbar\n", false],
571 ["Extra content in checksum line is part of the checksum", "[Adblock]\n! Check sum: e/JCmqXny6Fn24b7JHsq/A foobar\nfoo\nbar\n", false],
572 ["= symbols after checksum are ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn2 4b7JHsq/A===\nfoo\nbar\n", true],
573 ["Header line is part of the checksum", "[Adblock Plus]\n! Checksum: e/JCmqXny 6Fn24b7JHsq/A\nfoo\nbar\n", false],
574 ["Special comments are part of the checksum", "[Adblock]\n! Checksum: e/JCmqXn y6Fn24b7JHsq/A\n! Expires: 1\nfoo\nbar\n", false],
575 ])
576 {
577 exports.testChecksumVerification[testName] = function(test)
179 { 578 {
180 let subscription = Subscription.fromURL("http://example.com/subscription"); 579 let subscription = Subscription.fromURL("http://example.com/subscription");
181 FilterStorage.addSubscription(subscription); 580 FilterStorage.addSubscription(subscription);
182 581
183 let test; 582 this.registerHandler("/subscription", metadata =>
184 let requests = []; 583 {
185 testRunner.registerHandler("/subscription", function(metadata) 584 return [Cr.NS_OK, 200, subscriptionBody];
186 { 585 });
187 requests.push(testRunner.getTimeOffset()); 586
188 return [Cr.NS_OK, 200, "[Adblock]\nfoo\n!Expires: " + test.expiration + "\ nbar"]; 587 this.runScheduledTasks(2).then(() =>
189 }); 588 {
190 589 test.equal(subscription.downloadStatus, expectedResult ? "synchronize_ok" : "synchronize_checksum_mismatch");
191 let tests = [ 590 }).catch(unexpectedError.bind(test)).then(() => test.done());
192 { 591 };
193 expiration: "default", 592 }
194 randomResult: 0.5, 593
195 requests: [0 + initialDelay, 5 * 24 + initialDelay] 594 exports.testSpecialComments = {};
196 }, 595
197 { 596 for (let [comment, check] of [
198 expiration: "1 hours", // Minimal expiration interval 597 ["! Homepage: http://example.com/", (test, subscription) =>
199 randomResult: 0.5, 598 {
200 requests: [0 + initialDelay, 1 + initialDelay, 2 + initialDelay, 3 + ini tialDelay] 599 test.equal(subscription.homepage, "http://example.com/", "Valid homepage com ment");
201 }, 600 }],
202 { 601 ["! Homepage: ssh://example.com/", (test, subscription) =>
203 expiration: "26 hours", 602 {
204 randomResult: 0.5, 603 test.equal(subscription.homepage, null, "Invalid homepage comment");
205 requests: [0 + initialDelay, 26 + initialDelay] 604 }],
206 }, 605 ["! Title: foo", (test, subscription) =>
207 { 606 {
208 expiration: "2 days", 607 test.equal(subscription.title, "foo", "Title comment");
209 randomResult: 0.5, 608 test.equal(subscription.fixedTitle, true, "Fixed title");
210 requests: [0 + initialDelay, 48 + initialDelay] 609 }],
211 }, 610 ["! Version: 1234", (test, subscription) =>
212 { 611 {
213 expiration: "20 days", // Too large, will be corrected 612 test.equal(subscription.version, 1234, "Version comment");
214 randomResult: 0.5, 613 }]
215 requests: [0 + initialDelay, 14 * 24 + initialDelay] 614 ])
216 }, 615 {
217 { 616 exports.testSpecialComments[comment] = function(test)
218 expiration: "35 hours",
219 randomResult: 0, // Changes interval by factor 0.8
220 requests: [0 + initialDelay, 28 + initialDelay]
221 },
222 {
223 expiration: "35 hours",
224 randomResult: 1, // Changes interval by factor 1.2
225 requests: [0 + initialDelay, 42 + initialDelay]
226 },
227 {
228 expiration: "35 hours",
229 randomResult: 0.25, // Changes interval by factor 0.9
230 requests: [0 + initialDelay, 32 + initialDelay]
231 },
232 {
233 expiration: "40 hours",
234 randomResult: 0.5,
235 skipAfter: 5 + initialDelay,
236 skip: 10, // Short break should not increase soft expirati on
237 requests: [0 + initialDelay, 40 + initialDelay]
238 },
239 {
240 expiration: "40 hours",
241 randomResult: 0.5,
242 skipAfter: 5 + initialDelay,
243 skip: 30, // Long break should increase soft expiration
244 requests: [0 + initialDelay, 70 + initialDelay]
245 },
246 {
247 expiration: "40 hours",
248 randomResult: 0.5,
249 skipAfter: 5 + initialDelay,
250 skip: 80, // Hitting hard expiration, immediate download
251 requests: [0 + initialDelay, 85 + initialDelay]
252 }
253 ]
254
255 for (test of tests)
256 {
257 requests = [];
258 randomResult = test.randomResult;
259 resetSubscription(subscription);
260
261 let maxHours = Math.round(Math.max.apply(null, test.requests)) + 1;
262 testRunner.runScheduledTasks(maxHours, test.skipAfter, test.skip);
263
264 let randomAddendum = (randomResult == 0.5 ? "" : " with Math.random() retu rning " + randomResult);
265 let skipAddendum = (typeof test.skip != "number" ? "" : " skipping " + tes t.skip + " hours after " + test.skipAfter + " hours");
266 deepEqual(requests, test.requests, "Requests for \"" + test.expiration + " \"" + randomAddendum + skipAddendum);
267 }
268 });
269
270 test("Checksum verification", function()
271 { 617 {
272 let subscription = Subscription.fromURL("http://example.com/subscription"); 618 let subscription = Subscription.fromURL("http://example.com/subscription");
273 FilterStorage.addSubscription(subscription); 619 FilterStorage.addSubscription(subscription);
274 620
275 let testName, subscriptionBody, expectedResult; 621 this.registerHandler("/subscription", metadata =>
276 let tests = [ 622 {
277 ["Correct checksum", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\nfoo\n bar\n", true], 623 return [Cr.NS_OK, 200, "[Adblock]\n" + comment + "\nfoo\nbar"];
278 ["Wrong checksum", "[Adblock]\n! Checksum: wrongggny6Fn24b7JHsq/A\nfoo\nba r\n", false], 624 });
279 ["Empty lines ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\n\n foo\n\nbar\n\n", true], 625
280 ["CR LF line breaks treated like LR", "[Adblock]\n! Checksum: e/JCmqXny6Fn 24b7JHsq/A\nfoo\r\nbar\r\n", true], 626 this.runScheduledTasks(2).then(() =>
281 ["CR line breaks treated like LR", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b 7JHsq/A\nfoo\rbar\r", true], 627 {
282 ["Trailing line break not ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24 b7JHsq/A\nfoo\nbar", false], 628 check(test, subscription);
283 ["Line breaks between lines not ignored", "[Adblock]\n! Checksum: e/JCmqXn y6Fn24b7JHsq/A\nfoobar", false], 629 test.deepEqual(subscription.filters, [Filter.fromText("foo"), Filter.fromT ext("bar")], "Special comment not added to filters");
284 ["Lines with spaces not ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7 JHsq/A\n \nfoo\n\nbar\n", false], 630 }).catch(unexpectedError.bind(test)).then(() => test.done());
285 ["Extra content in checksum line is part of the checksum", "[Adblock]\n! C hecksum: e/JCmqXny6Fn24b7JHsq/A foobar\nfoo\nbar\n", false], 631 };
286 ["= symbols after checksum are ignored", "[Adblock]\n! Checksum: e/JCmqXny 6Fn24b7JHsq/A===\nfoo\nbar\n", true], 632 }
287 ["Header line is part of the checksum", "[Adblock Plus]\n! Checksum: e/JCm qXny6Fn24b7JHsq/A\nfoo\nbar\n", false], 633
288 ["Special comments are part of the checksum", "[Adblock]\n! Checksum: e/JC mqXny6Fn24b7JHsq/A\n! Expires: 1\nfoo\nbar\n", false], 634 exports.testRedirects = function(test)
289 ]; 635 {
290 636 let subscription = Subscription.fromURL("http://example.com/subscription");
291 testRunner.registerHandler("/subscription", function(metadata) 637 FilterStorage.addSubscription(subscription);
292 { 638
293 return [Cr.NS_OK, 200, subscriptionBody]; 639 this.registerHandler("/subscription", metadata =>
294 }); 640 {
295 641 return [Cr.NS_OK, 200, "[Adblock]\nfoo\n!Redirect: http://example.com/redire cted\nbar"];
296 for ([testName, subscriptionBody, expectedResult] of tests)
297 {
298 resetSubscription(subscription);
299 testRunner.runScheduledTasks(2);
300 equal(subscription.downloadStatus, expectedResult ? "synchronize_ok" : "sy nchronize_checksum_mismatch", testName);
301 }
302 }); 642 });
303 643
304 test("Special comments", function() 644 let requests;
305 { 645
306 let subscription = Subscription.fromURL("http://example.com/subscription"); 646 this.runScheduledTasks(30).then(() =>
307 FilterStorage.addSubscription(subscription); 647 {
308 648 test.equal(FilterStorage.subscriptions[0], subscription, "Invalid redirect i gnored");
309 let comment, check; 649 test.equal(subscription.downloadStatus, "synchronize_connection_error", "Con nection error recorded");
310 let tests = [ 650 test.equal(subscription.errors, 2, "Number of download errors");
311 ["! Homepage: http://example.com/", () => equal(subscription.homepage, "ht tp://example.com/", "Valid homepage comment")], 651
312 ["! Homepage: ssh://example.com/", () => equal(subscription.homepage, null , "Invalid homepage comment")], 652 requests = [];
313 ["! Title: foo", function() 653
314 { 654 this.registerHandler("/redirected", metadata =>
315 equal(subscription.title, "foo", "Title comment"); 655 {
316 equal(subscription.fixedTitle, true, "Fixed title"); 656 requests.push(this.getTimeOffset());
317 }],
318 ["! Version: 1234", () => equal(subscription.version, 1234, "Version comme nt")]
319 ];
320
321 testRunner.registerHandler("/subscription", function(metadata)
322 {
323 return [Cr.NS_OK, 200, "[Adblock]\n" + comment + "\nfoo\nbar"];
324 });
325
326 for ([comment, check] of tests)
327 {
328 resetSubscription(subscription);
329 testRunner.runScheduledTasks(2);
330 check();
331 deepEqual(subscription.filters, [Filter.fromText("foo"), Filter.fromText(" bar")], "Special comment not added to filters");
332 }
333 });
334
335 test("Redirects", function()
336 {
337 let subscription = Subscription.fromURL("http://example.com/subscription");
338 FilterStorage.addSubscription(subscription);
339
340 testRunner.registerHandler("/subscription", function(metadata)
341 {
342 return [Cr.NS_OK, 200, "[Adblock]\nfoo\n!Redirect: http://example.com/redi rected\nbar"];
343 });
344
345 testRunner.runScheduledTasks(30);
346 equal(FilterStorage.subscriptions[0], subscription, "Invalid redirect ignore d");
347 equal(subscription.downloadStatus, "synchronize_connection_error", "Connecti on error recorded");
348 equal(subscription.errors, 2, "Number of download errors");
349
350 let requests = [];
351 testRunner.registerHandler("/redirected", function(metadata)
352 {
353 requests.push(testRunner.getTimeOffset());
354 return [Cr.NS_OK, 200, "[Adblock]\nfoo\n! Expires: 8 hours\nbar"]; 657 return [Cr.NS_OK, 200, "[Adblock]\nfoo\n! Expires: 8 hours\nbar"];
355 }); 658 });
356 659
357 resetSubscription(subscription); 660 resetSubscription(subscription);
358 testRunner.runScheduledTasks(15); 661 return this.runScheduledTasks(15);
359 equal(FilterStorage.subscriptions[0].url, "http://example.com/redirected", " Redirect followed"); 662 }).then(() =>
360 deepEqual(requests, [0 + initialDelay, 8 + initialDelay], "Resulting request s"); 663 {
361 664 test.equal(FilterStorage.subscriptions[0].url, "http://example.com/redirecte d", "Redirect followed");
362 testRunner.registerHandler("/redirected", function(metadata) 665 test.deepEqual(requests, [0 + initialDelay, 8 + initialDelay], "Resulting re quests");
666
667 this.registerHandler("/redirected", metadata =>
363 { 668 {
364 return [Cr.NS_OK, 200, "[Adblock]\nfoo\n!Redirect: http://example.com/subs cription\nbar"]; 669 return [Cr.NS_OK, 200, "[Adblock]\nfoo\n!Redirect: http://example.com/subs cription\nbar"];
365 }) 670 })
366 671
367 subscription = Subscription.fromURL("http://example.com/subscription"); 672 subscription = Subscription.fromURL("http://example.com/subscription");
368 resetSubscription(subscription); 673 resetSubscription(subscription);
369 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]); 674 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]);
370 FilterStorage.addSubscription(subscription); 675 FilterStorage.addSubscription(subscription);
371 676
372 testRunner.runScheduledTasks(2); 677 return this.runScheduledTasks(2);
373 equal(FilterStorage.subscriptions[0], subscription, "Redirect not followed o n redirect loop"); 678 }).then(() =>
374 equal(subscription.downloadStatus, "synchronize_connection_error", "Download status after redirect loop"); 679 {
680 test.equal(FilterStorage.subscriptions[0], subscription, "Redirect not follo wed on redirect loop");
681 test.equal(subscription.downloadStatus, "synchronize_connection_error", "Dow nload status after redirect loop");
682 }).catch(unexpectedError.bind(test)).then(() => test.done());
683 };
684
685 exports.testFallback = function(test)
686 {
687 Prefs.subscriptions_fallbackerrors = 3;
688 Prefs.subscriptions_fallbackurl = "http://example.com/fallback?%SUBSCRIPTION%& %CHANNELSTATUS%&%RESPONSESTATUS%";
689
690 let subscription = Subscription.fromURL("http://example.com/subscription");
691 FilterStorage.addSubscription(subscription);
692
693 // No valid response from fallback
694
695 let requests = [];
696 let fallbackParams;
697 let redirectedRequests;
698 this.registerHandler("/subscription", metadata =>
699 {
700 requests.push(this.getTimeOffset());
701 return [Cr.NS_OK, 404, ""];
375 }); 702 });
376 703
377 test("Fallback", function() 704 this.runScheduledTasks(100).then(() =>
378 { 705 {
379 Prefs.subscriptions_fallbackerrors = 3; 706 test.deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialD elay, 72 + initialDelay, 96 + initialDelay], "Continue trying if the fallback do esn't respond");
380 Prefs.subscriptions_fallbackurl = "http://example.com/fallback?%SUBSCRIPTION %&%CHANNELSTATUS%&%RESPONSESTATUS%";
381
382 let subscription = Subscription.fromURL("http://example.com/subscription");
383 FilterStorage.addSubscription(subscription);
384
385 // No valid response from fallback
386
387 let requests = [];
388 testRunner.registerHandler("/subscription", function(metadata)
389 {
390 requests.push(testRunner.getTimeOffset());
391 return [Cr.NS_OK, 404, ""];
392 });
393
394 testRunner.runScheduledTasks(100);
395 deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialDelay, 72 + initialDelay, 96 + initialDelay], "Continue trying if the fallback doesn't respond");
396 707
397 // Fallback giving "Gone" response 708 // Fallback giving "Gone" response
398 709
399 resetSubscription(subscription); 710 resetSubscription(subscription);
400 requests = []; 711 requests = [];
401 fallbackParams = null; 712 fallbackParams = null;
402 testRunner.registerHandler("/fallback", function(metadata) 713 this.registerHandler("/fallback", metadata =>
403 { 714 {
404 fallbackParams = decodeURIComponent(metadata.queryString); 715 fallbackParams = decodeURIComponent(metadata.queryString);
405 return [Cr.NS_OK, 200, "410 Gone"]; 716 return [Cr.NS_OK, 200, "410 Gone"];
406 }); 717 });
407 718
408 testRunner.runScheduledTasks(100); 719 return this.runScheduledTasks(100);
409 deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialDelay] , "Stop trying if the fallback responds with Gone"); 720 }).then(() =>
410 equal(fallbackParams, "http://example.com/subscription&0&404", "Fallback arg uments"); 721 {
722 test.deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialD elay], "Stop trying if the fallback responds with Gone");
723 test.equal(fallbackParams, "http://example.com/subscription&0&404", "Fallbac k arguments");
411 724
412 // Fallback redirecting to a missing file 725 // Fallback redirecting to a missing file
413 726
414 subscription = Subscription.fromURL("http://example.com/subscription"); 727 subscription = Subscription.fromURL("http://example.com/subscription");
415 resetSubscription(subscription); 728 resetSubscription(subscription);
416 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]); 729 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]);
417 FilterStorage.addSubscription(subscription); 730 FilterStorage.addSubscription(subscription);
418 requests = []; 731 requests = [];
419 732
420 testRunner.registerHandler("/fallback", function(metadata) 733 this.registerHandler("/fallback", metadata =>
421 { 734 {
422 return [Cr.NS_OK, 200, "301 http://example.com/redirected"]; 735 return [Cr.NS_OK, 200, "301 http://example.com/redirected"];
423 }); 736 });
424 testRunner.runScheduledTasks(100); 737 return this.runScheduledTasks(100);
425 equal(FilterStorage.subscriptions[0].url, "http://example.com/subscription", "Ignore invalid redirect from fallback"); 738 }).then(() =>
426 deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialDelay, 72 + initialDelay, 96 + initialDelay], "Requests not affected by invalid redire ct"); 739 {
740 test.equal(FilterStorage.subscriptions[0].url, "http://example.com/subscript ion", "Ignore invalid redirect from fallback");
741 test.deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialD elay, 72 + initialDelay, 96 + initialDelay], "Requests not affected by invalid r edirect");
427 742
428 // Fallback redirecting to an existing file 743 // Fallback redirecting to an existing file
429 744
430 resetSubscription(subscription); 745 resetSubscription(subscription);
431 requests = []; 746 requests = [];
432 let redirectedRequests = []; 747 redirectedRequests = [];
433 testRunner.registerHandler("/redirected", function(metadata) 748 this.registerHandler("/redirected", metadata =>
434 { 749 {
435 redirectedRequests.push(testRunner.getTimeOffset()); 750 redirectedRequests.push(this.getTimeOffset());
436 return [Cr.NS_OK, 200, "[Adblock]\n!Expires: 1day\nfoo\nbar"]; 751 return [Cr.NS_OK, 200, "[Adblock]\n!Expires: 1day\nfoo\nbar"];
437 }); 752 });
438 753
439 testRunner.runScheduledTasks(100); 754 return this.runScheduledTasks(100);
440 equal(FilterStorage.subscriptions[0].url, "http://example.com/redirected", " Valid redirect from fallback is followed"); 755 }).then(() =>
441 deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialDelay] , "Stop polling original URL after a valid redirect from fallback"); 756 {
442 deepEqual(redirectedRequests, [48 + initialDelay, 72 + initialDelay, 96 + in itialDelay], "Request new URL after a valid redirect from fallback"); 757 test.equal(FilterStorage.subscriptions[0].url, "http://example.com/redirecte d", "Valid redirect from fallback is followed");
758 test.deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialD elay], "Stop polling original URL after a valid redirect from fallback");
759 test.deepEqual(redirectedRequests, [48 + initialDelay, 72 + initialDelay, 96 + initialDelay], "Request new URL after a valid redirect from fallback");
443 760
444 // Checksum mismatch 761 // Checksum mismatch
445 762
446 testRunner.registerHandler("/subscription", function(metadata) 763 this.registerHandler("/subscription", metadata =>
447 { 764 {
448 return [Cr.NS_OK, 200, "[Adblock]\n! Checksum: wrong\nfoo\nbar"]; 765 return [Cr.NS_OK, 200, "[Adblock]\n! Checksum: wrong\nfoo\nbar"];
449 }); 766 });
450 767
451 subscription = Subscription.fromURL("http://example.com/subscription"); 768 subscription = Subscription.fromURL("http://example.com/subscription");
452 resetSubscription(subscription); 769 resetSubscription(subscription);
453 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]); 770 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]);
454 FilterStorage.addSubscription(subscription); 771 FilterStorage.addSubscription(subscription);
455 772
456 testRunner.runScheduledTasks(100); 773 return this.runScheduledTasks(100);
457 equal(FilterStorage.subscriptions[0].url, "http://example.com/redirected", " Wrong checksum produces fallback request"); 774 }).then(() =>
775 {
776 test.equal(FilterStorage.subscriptions[0].url, "http://example.com/redirecte d", "Wrong checksum produces fallback request");
458 777
459 // Redirect loop 778 // Redirect loop
460 779
461 testRunner.registerHandler("/subscription", function(metadata) 780 this.registerHandler("/subscription", metadata =>
462 { 781 {
463 return [Cr.NS_OK, 200, "[Adblock]\n! Redirect: http://example.com/subscrip tion2"]; 782 return [Cr.NS_OK, 200, "[Adblock]\n! Redirect: http://example.com/subscrip tion2"];
464 }); 783 });
465 testRunner.registerHandler("/subscription2", function(metadata, response) 784 this.registerHandler("/subscription2", metadata =>
466 { 785 {
467 return [Cr.NS_OK, 200, "[Adblock]\n! Redirect: http://example.com/subscrip tion"]; 786 return [Cr.NS_OK, 200, "[Adblock]\n! Redirect: http://example.com/subscrip tion"];
468 }); 787 });
469 788
470 subscription = Subscription.fromURL("http://example.com/subscription"); 789 subscription = Subscription.fromURL("http://example.com/subscription");
471 resetSubscription(subscription); 790 resetSubscription(subscription);
472 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]); 791 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]);
473 FilterStorage.addSubscription(subscription); 792 FilterStorage.addSubscription(subscription);
474 793
475 testRunner.runScheduledTasks(100); 794 return this.runScheduledTasks(100);
476 equal(FilterStorage.subscriptions[0].url, "http://example.com/redirected", " Fallback can still redirect even after a redirect loop"); 795 }).then(() =>
796 {
797 test.equal(FilterStorage.subscriptions[0].url, "http://example.com/redirecte d", "Fallback can still redirect even after a redirect loop");
798 }).catch(unexpectedError.bind(test)).then(() => test.done());
799 };
800
801 exports.testStateFields = function(test)
802 {
803 let subscription = Subscription.fromURL("http://example.com/subscription");
804 FilterStorage.addSubscription(subscription);
805
806 this.registerHandler("/subscription", metadata =>
807 {
808 return [Cr.NS_OK, 200, "[Adblock]\n! Expires: 2 hours\nfoo\nbar"];
477 }); 809 });
478 810
479 test("State fields", function() 811 let startTime = this.currentTime;
480 { 812 this.runScheduledTasks(2).then(() =>
481 let subscription = Subscription.fromURL("http://example.com/subscription"); 813 {
482 FilterStorage.addSubscription(subscription); 814 test.equal(subscription.downloadStatus, "synchronize_ok", "downloadStatus af ter successful download");
483 815 test.equal(subscription.lastDownload * MILLIS_IN_SECOND, startTime + initia lDelay * MILLIS_IN_HOUR, "lastDownload after successful download");
484 testRunner.registerHandler("/subscription", function(metadata) 816 test.equal(subscription.lastSuccess * MILLIS_IN_SECOND, startTime + initial Delay * MILLIS_IN_HOUR, "lastSuccess after successful download");
485 { 817 test.equal(subscription.lastCheck * MILLIS_IN_SECOND, startTime + (1 + init ialDelay) * MILLIS_IN_HOUR, "lastCheck after successful download");
486 return [Cr.NS_OK, 200, "[Adblock]\n! Expires: 2 hours\nfoo\nbar"]; 818 test.equal(subscription.errors, 0, "errors after successful download");
487 }); 819
488 820 this.registerHandler("/subscription", metadata =>
489 let startTime = testRunner.currentTime;
490 testRunner.runScheduledTasks(2);
491
492 equal(subscription.downloadStatus, "synchronize_ok", "downloadStatus after s uccessful download");
493 equal(subscription.lastDownload * MILLIS_IN_SECOND, startTime + initialDela y * MILLIS_IN_HOUR, "lastDownload after successful download");
494 equal(subscription.lastSuccess * MILLIS_IN_SECOND, startTime + initialDelay * MILLIS_IN_HOUR, "lastSuccess after successful download");
495 equal(subscription.lastCheck * MILLIS_IN_SECOND, startTime + (1 + initialDe lay) * MILLIS_IN_HOUR, "lastCheck after successful download");
496 equal(subscription.errors, 0, "errors after successful download");
497
498 testRunner.registerHandler("/subscription", function(metadata)
499 { 821 {
500 return [Cr.NS_ERROR_FAILURE, 0, ""]; 822 return [Cr.NS_ERROR_FAILURE, 0, ""];
501 }); 823 });
502 824
503 testRunner.runScheduledTasks(2); 825 return this.runScheduledTasks(2);
504 826 }).then(() =>
505 equal(subscription.downloadStatus, "synchronize_connection_error", "download Status after connection error"); 827 {
506 equal(subscription.lastDownload * MILLIS_IN_SECOND, startTime + (2 + initia lDelay) * MILLIS_IN_HOUR, "lastDownload after connection error"); 828 test.equal(subscription.downloadStatus, "synchronize_connection_error", "dow nloadStatus after connection error");
507 equal(subscription.lastSuccess * MILLIS_IN_SECOND, startTime + initialDelay * MILLIS_IN_HOUR, "lastSuccess after connection error"); 829 test.equal(subscription.lastDownload * MILLIS_IN_SECOND, startTime + (2 + i nitialDelay) * MILLIS_IN_HOUR, "lastDownload after connection error");
508 equal(subscription.lastCheck * MILLIS_IN_SECOND, startTime + (3 + initialDel ay) * MILLIS_IN_HOUR, "lastCheck after connection error"); 830 test.equal(subscription.lastSuccess * MILLIS_IN_SECOND, startTime + initialD elay * MILLIS_IN_HOUR, "lastSuccess after connection error");
509 equal(subscription.errors, 1, "errors after connection error"); 831 test.equal(subscription.lastCheck * MILLIS_IN_SECOND, startTime + (3 + initi alDelay) * MILLIS_IN_HOUR, "lastCheck after connection error");
510 832 test.equal(subscription.errors, 1, "errors after connection error");
511 testRunner.registerHandler("/subscription", function(metadata) 833
834 this.registerHandler("/subscription", metadata =>
512 { 835 {
513 return [Cr.NS_OK, 404, ""]; 836 return [Cr.NS_OK, 404, ""];
514 }); 837 });
515 838
516 testRunner.runScheduledTasks(24); 839 return this.runScheduledTasks(24);
517 840 }).then(() =>
518 equal(subscription.downloadStatus, "synchronize_connection_error", "download Status after download error"); 841 {
519 equal(subscription.lastDownload * MILLIS_IN_SECOND, startTime + (26 + initia lDelay) * MILLIS_IN_HOUR, "lastDownload after download error"); 842 test.equal(subscription.downloadStatus, "synchronize_connection_error", "dow nloadStatus after download error");
520 equal(subscription.lastSuccess * MILLIS_IN_SECOND, startTime + initialDelay * MILLIS_IN_HOUR, "lastSuccess after download error"); 843 test.equal(subscription.lastDownload * MILLIS_IN_SECOND, startTime + (26 + i nitialDelay) * MILLIS_IN_HOUR, "lastDownload after download error");
521 equal(subscription.lastCheck * MILLIS_IN_SECOND, startTime + (27 + initialDe lay) * MILLIS_IN_HOUR, "lastCheck after download error"); 844 test.equal(subscription.lastSuccess * MILLIS_IN_SECOND, startTime + initialD elay * MILLIS_IN_HOUR, "lastSuccess after download error");
522 equal(subscription.errors, 2, "errors after download error"); 845 test.equal(subscription.lastCheck * MILLIS_IN_SECOND, startTime + (27 + init ialDelay) * MILLIS_IN_HOUR, "lastCheck after download error");
523 }); 846 test.equal(subscription.errors, 2, "errors after download error");
524 })(); 847 }).catch(unexpectedError.bind(test)).then(() => test.done());
848 };
OLDNEW
« no previous file with comments | « test/stub-modules/utils.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld