Left: | ||
Right: |
OLD | NEW |
---|---|
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 }; | |
OLD | NEW |