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() |
| 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 => |
| 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 = function(test) |
118 let test; | 404 { |
119 let subscription = Subscription.fromURL("http://example.com/subscription"); | 405 let currentTest; |
120 FilterStorage.addSubscription(subscription); | 406 let subscription = Subscription.fromURL("http://example.com/subscription"); |
121 | 407 FilterStorage.addSubscription(subscription); |
122 testRunner.registerHandler("/subscription", function(metadata) | 408 |
123 { | 409 this.registerHandler("/subscription", metadata => |
124 return [Cr.NS_OK, 200, test.header + "\n!Expires: 8 hours\nfoo\n!bar\n\n@@
bas\n#bam"]; | 410 { |
125 }); | 411 return [Cr.NS_OK, 200, currentTest.header + "\n!Expires: 8 hours\nfoo\n!bar\
n\n@@bas\n#bam"]; |
126 | 412 }); |
127 let tests = [ | 413 |
128 {header: "[Adblock]", downloadStatus: "synchronize_ok", requiredVersion: n
ull}, | 414 let tests = [ |
129 {header: "[Adblock Plus]", downloadStatus: "synchronize_ok", requiredVersi
on: null}, | 415 {header: "[Adblock]", downloadStatus: "synchronize_ok", requiredVersion: nul
l}, |
130 {header: "(something)[Adblock]", downloadStatus: "synchronize_ok", require
dVersion: null}, | 416 {header: "[Adblock Plus]", downloadStatus: "synchronize_ok", requiredVersion
: null}, |
131 {header: "[Adblock Plus 0.0.1]", downloadStatus: "synchronize_ok", require
dVersion: "0.0.1"}, | 417 {header: "(something)[Adblock]", downloadStatus: "synchronize_ok", requiredV
ersion: null}, |
132 {header: "[Adblock Plus 99.9]", downloadStatus: "synchronize_ok", required
Version: "99.9"}, | 418 {header: "[Adblock Plus 0.0.1]", downloadStatus: "synchronize_ok", requiredV
ersion: "0.0.1"}, |
133 {header: "[Foo]", downloadStatus: "synchronize_invalid_data", requiredVers
ion: null} | 419 {header: "[Adblock Plus 99.9]", downloadStatus: "synchronize_ok", requiredVe
rsion: "99.9"}, |
134 ]; | 420 {header: "[Foo]", downloadStatus: "synchronize_invalid_data", requiredVersio
n: null} |
135 for (test of tests) | 421 ]; |
136 { | 422 |
137 resetSubscription(subscription) | 423 let runTest = () => |
138 testRunner.runScheduledTasks(2); | 424 { |
139 | 425 if (!tests.length) |
140 equal(subscription.downloadStatus, test.downloadStatus, "Download status f
or " + test.header) | 426 return; |
141 equal(subscription.requiredVersion, test.requiredVersion, "Required versio
n for " + test.header) | 427 |
142 | 428 currentTest = tests.shift(); |
143 if (test.downloadStatus == "synchronize_ok") | 429 |
144 { | 430 resetSubscription(subscription) |
145 deepEqual(subscription.filters, [ | 431 return this.runScheduledTasks(2).then(() => |
| 432 { |
| 433 test.equal(subscription.downloadStatus, currentTest.downloadStatus, "Downl
oad status for " + currentTest.header); |
| 434 test.equal(subscription.requiredVersion, currentTest.requiredVersion, "Req
uired version for " + currentTest.header); |
| 435 |
| 436 if (currentTest.downloadStatus == "synchronize_ok") |
| 437 { |
| 438 test.deepEqual(subscription.filters, [ |
146 Filter.fromText("foo"), | 439 Filter.fromText("foo"), |
147 Filter.fromText("!bar"), | 440 Filter.fromText("!bar"), |
148 Filter.fromText("@@bas"), | 441 Filter.fromText("@@bas"), |
149 Filter.fromText("#bam"), | 442 Filter.fromText("#bam"), |
150 ], "Resulting subscription filters for " + test.header); | 443 ], "Resulting subscription filters for " + currentTest.header); |
151 } | 444 } |
152 else | 445 else |
153 { | 446 { |
154 deepEqual(subscription.filters, [ | 447 test.deepEqual(subscription.filters, [ |
155 ], "Resulting subscription filters for " + test.header); | 448 ], "Resulting subscription filters for " + currentTest.header); |
156 } | 449 } |
| 450 }).then(runTest); |
| 451 }; |
| 452 |
| 453 runTest().catch(unexpectedError.bind(test)).then(() => test.done()); |
| 454 }; |
| 455 |
| 456 exports.testsDisabledUpdates = function(test) |
| 457 { |
| 458 Prefs.subscriptions_autoupdate = false; |
| 459 |
| 460 let subscription = Subscription.fromURL("http://example.com/subscription"); |
| 461 FilterStorage.addSubscription(subscription); |
| 462 |
| 463 let requests = 0; |
| 464 this.registerHandler("/subscription", metadata => |
| 465 { |
| 466 requests++; |
| 467 throw new Error("Unexpected request"); |
| 468 }); |
| 469 |
| 470 this.runScheduledTasks(50).then(() => |
| 471 { |
| 472 test.equal(requests, 0, "Request count"); |
| 473 }).catch(unexpectedError.bind(test)).then(() => test.done()); |
| 474 }; |
| 475 |
| 476 exports.testExpirationTime = function(test) |
| 477 { |
| 478 let subscription = Subscription.fromURL("http://example.com/subscription"); |
| 479 FilterStorage.addSubscription(subscription); |
| 480 |
| 481 let currentTest; |
| 482 let requests = []; |
| 483 this.registerHandler("/subscription", metadata => |
| 484 { |
| 485 requests.push(this.getTimeOffset()); |
| 486 return [Cr.NS_OK, 200, "[Adblock]\nfoo\n!Expires: " + currentTest.expiration
+ "\nbar"]; |
| 487 }); |
| 488 |
| 489 let tests = [ |
| 490 { |
| 491 expiration: "default", |
| 492 randomResult: 0.5, |
| 493 requests: [0 + initialDelay, 5 * 24 + initialDelay] |
| 494 }, |
| 495 { |
| 496 expiration: "1 hours", // Minimal expiration interval |
| 497 randomResult: 0.5, |
| 498 requests: [0 + initialDelay, 1 + initialDelay, 2 + initialDelay, 3 + initi
alDelay] |
| 499 }, |
| 500 { |
| 501 expiration: "26 hours", |
| 502 randomResult: 0.5, |
| 503 requests: [0 + initialDelay, 26 + initialDelay] |
| 504 }, |
| 505 { |
| 506 expiration: "2 days", |
| 507 randomResult: 0.5, |
| 508 requests: [0 + initialDelay, 48 + initialDelay] |
| 509 }, |
| 510 { |
| 511 expiration: "20 days", // Too large, will be corrected |
| 512 randomResult: 0.5, |
| 513 requests: [0 + initialDelay, 14 * 24 + initialDelay] |
| 514 }, |
| 515 { |
| 516 expiration: "35 hours", |
| 517 randomResult: 0, // Changes interval by factor 0.8 |
| 518 requests: [0 + initialDelay, 28 + initialDelay] |
| 519 }, |
| 520 { |
| 521 expiration: "35 hours", |
| 522 randomResult: 1, // Changes interval by factor 1.2 |
| 523 requests: [0 + initialDelay, 42 + initialDelay] |
| 524 }, |
| 525 { |
| 526 expiration: "35 hours", |
| 527 randomResult: 0.25, // Changes interval by factor 0.9 |
| 528 requests: [0 + initialDelay, 32 + initialDelay] |
| 529 }, |
| 530 { |
| 531 expiration: "40 hours", |
| 532 randomResult: 0.5, |
| 533 skipAfter: 5 + initialDelay, |
| 534 skip: 10, // Short break should not increase soft expiration |
| 535 requests: [0 + initialDelay, 40 + initialDelay] |
| 536 }, |
| 537 { |
| 538 expiration: "40 hours", |
| 539 randomResult: 0.5, |
| 540 skipAfter: 5 + initialDelay, |
| 541 skip: 30, // Long break should increase soft expiration |
| 542 requests: [0 + initialDelay, 70 + initialDelay] |
| 543 }, |
| 544 { |
| 545 expiration: "40 hours", |
| 546 randomResult: 0.5, |
| 547 skipAfter: 5 + initialDelay, |
| 548 skip: 80, // Hitting hard expiration, immediate download |
| 549 requests: [0 + initialDelay, 85 + initialDelay] |
157 } | 550 } |
158 }) | 551 ] |
159 | 552 |
160 test("Automatic updates disabled", function() | 553 let runTest = () => |
161 { | 554 { |
162 Prefs.subscriptions_autoupdate = false; | 555 if (!tests.length) |
163 | 556 return; |
164 let subscription = Subscription.fromURL("http://example.com/subscription"); | 557 |
165 FilterStorage.addSubscription(subscription); | 558 currentTest = tests.shift(); |
166 | 559 |
167 let requests = 0; | 560 requests = []; |
168 testRunner.registerHandler("/subscription", function(metadata) | 561 this.randomResult = currentTest.randomResult; |
169 { | 562 resetSubscription(subscription); |
170 requests++; | 563 |
171 throw new Error("Unexpected request"); | 564 let maxHours = Math.round(Math.max.apply(null, currentTest.requests)) + 1; |
172 }); | 565 return this.runScheduledTasks(maxHours, currentTest.skipAfter, currentTest.s
kip).then(() => |
173 | 566 { |
174 testRunner.runScheduledTasks(50); | 567 let randomAddendum = (this.randomResult == 0.5 ? "" : " with Math.random()
returning " + this.randomResult); |
175 equal(requests, 0, "Request count"); | 568 let skipAddendum = (typeof currentTest.skip != "number" ? "" : " skipping
" + currentTest.skip + " hours after " + currentTest.skipAfter + " hours"); |
176 }); | 569 test.deepEqual(requests, currentTest.requests, "Requests for \"" + current
Test.expiration + "\"" + randomAddendum + skipAddendum); |
177 | 570 }).then(runTest); |
178 test("Expiration time", function() | 571 }; |
179 { | 572 |
180 let subscription = Subscription.fromURL("http://example.com/subscription"); | 573 runTest().catch(unexpectedError.bind(test)).then(() => test.done()); |
181 FilterStorage.addSubscription(subscription); | 574 }; |
182 | 575 |
183 let test; | 576 exports.testChecksumVerification = function(test) |
184 let requests = []; | 577 { |
185 testRunner.registerHandler("/subscription", function(metadata) | 578 let subscription = Subscription.fromURL("http://example.com/subscription"); |
186 { | 579 FilterStorage.addSubscription(subscription); |
187 requests.push(testRunner.getTimeOffset()); | 580 |
188 return [Cr.NS_OK, 200, "[Adblock]\nfoo\n!Expires: " + test.expiration + "\
nbar"]; | 581 let testName, subscriptionBody, expectedResult; |
189 }); | 582 let tests = [ |
190 | 583 ["Correct checksum", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\nfoo\nba
r\n", true], |
191 let tests = [ | 584 ["Wrong checksum", "[Adblock]\n! Checksum: wrongggny6Fn24b7JHsq/A\nfoo\nbar\
n", false], |
192 { | 585 ["Empty lines ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\n\nfo
o\n\nbar\n\n", true], |
193 expiration: "default", | 586 ["CR LF line breaks treated like LR", "[Adblock]\n! Checksum: e/JCmqXny6Fn24
b7JHsq/A\nfoo\r\nbar\r\n", true], |
194 randomResult: 0.5, | 587 ["CR line breaks treated like LR", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7J
Hsq/A\nfoo\rbar\r", true], |
195 requests: [0 + initialDelay, 5 * 24 + initialDelay] | 588 ["Trailing line break not ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7
JHsq/A\nfoo\nbar", false], |
196 }, | 589 ["Line breaks between lines not ignored", "[Adblock]\n! Checksum: e/JCmqXny6
Fn24b7JHsq/A\nfoobar", false], |
197 { | 590 ["Lines with spaces not ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JH
sq/A\n \nfoo\n\nbar\n", false], |
198 expiration: "1 hours", // Minimal expiration interval | 591 ["Extra content in checksum line is part of the checksum", "[Adblock]\n! Che
cksum: e/JCmqXny6Fn24b7JHsq/A foobar\nfoo\nbar\n", false], |
199 randomResult: 0.5, | 592 ["= symbols after checksum are ignored", "[Adblock]\n! Checksum: e/JCmqXny6F
n24b7JHsq/A===\nfoo\nbar\n", true], |
200 requests: [0 + initialDelay, 1 + initialDelay, 2 + initialDelay, 3 + ini
tialDelay] | 593 ["Header line is part of the checksum", "[Adblock Plus]\n! Checksum: e/JCmqX
ny6Fn24b7JHsq/A\nfoo\nbar\n", false], |
201 }, | 594 ["Special comments are part of the checksum", "[Adblock]\n! Checksum: e/JCmq
Xny6Fn24b7JHsq/A\n! Expires: 1\nfoo\nbar\n", false], |
202 { | 595 ]; |
203 expiration: "26 hours", | 596 |
204 randomResult: 0.5, | 597 this.registerHandler("/subscription", metadata => |
205 requests: [0 + initialDelay, 26 + initialDelay] | 598 { |
206 }, | 599 return [Cr.NS_OK, 200, subscriptionBody]; |
207 { | 600 }); |
208 expiration: "2 days", | 601 |
209 randomResult: 0.5, | 602 let runTest = () => |
210 requests: [0 + initialDelay, 48 + initialDelay] | 603 { |
211 }, | 604 if (!tests.length) |
212 { | 605 return; |
213 expiration: "20 days", // Too large, will be corrected | 606 |
214 randomResult: 0.5, | 607 [testName, subscriptionBody, expectedResult] = tests.shift(); |
215 requests: [0 + initialDelay, 14 * 24 + initialDelay] | 608 |
216 }, | 609 resetSubscription(subscription); |
217 { | 610 return this.runScheduledTasks(2).then(() => |
218 expiration: "35 hours", | 611 { |
219 randomResult: 0, // Changes interval by factor 0.8 | 612 test.equal(subscription.downloadStatus, expectedResult ? "synchronize_ok"
: "synchronize_checksum_mismatch", testName); |
220 requests: [0 + initialDelay, 28 + initialDelay] | 613 }).then(runTest); |
221 }, | 614 }; |
222 { | 615 |
223 expiration: "35 hours", | 616 runTest().catch(unexpectedError.bind(test)).then(() => test.done()); |
224 randomResult: 1, // Changes interval by factor 1.2 | 617 }; |
225 requests: [0 + initialDelay, 42 + initialDelay] | 618 |
226 }, | 619 exports.testSpecialComments = function(test) |
227 { | 620 { |
228 expiration: "35 hours", | 621 let subscription = Subscription.fromURL("http://example.com/subscription"); |
229 randomResult: 0.25, // Changes interval by factor 0.9 | 622 FilterStorage.addSubscription(subscription); |
230 requests: [0 + initialDelay, 32 + initialDelay] | 623 |
231 }, | 624 let comment, check; |
232 { | 625 let tests = [ |
233 expiration: "40 hours", | 626 ["! Homepage: http://example.com/", () => test.equal(subscription.homepage,
"http://example.com/", "Valid homepage comment")], |
234 randomResult: 0.5, | 627 ["! Homepage: ssh://example.com/", () => test.equal(subscription.homepage, n
ull, "Invalid homepage comment")], |
235 skipAfter: 5 + initialDelay, | 628 ["! Title: foo", function() |
236 skip: 10, // Short break should not increase soft expirati
on | 629 { |
237 requests: [0 + initialDelay, 40 + initialDelay] | 630 test.equal(subscription.title, "foo", "Title comment"); |
238 }, | 631 test.equal(subscription.fixedTitle, true, "Fixed title"); |
239 { | 632 }], |
240 expiration: "40 hours", | 633 ["! Version: 1234", () => test.equal(subscription.version, 1234, "Version co
mment")] |
241 randomResult: 0.5, | 634 ]; |
242 skipAfter: 5 + initialDelay, | 635 |
243 skip: 30, // Long break should increase soft expiration | 636 this.registerHandler("/subscription", metadata => |
244 requests: [0 + initialDelay, 70 + initialDelay] | 637 { |
245 }, | 638 return [Cr.NS_OK, 200, "[Adblock]\n" + comment + "\nfoo\nbar"]; |
246 { | 639 }); |
247 expiration: "40 hours", | 640 |
248 randomResult: 0.5, | 641 let runTest = () => |
249 skipAfter: 5 + initialDelay, | 642 { |
250 skip: 80, // Hitting hard expiration, immediate download | 643 if (!tests.length) |
251 requests: [0 + initialDelay, 85 + initialDelay] | 644 return; |
252 } | 645 |
253 ] | 646 [comment, check] = tests.shift(); |
254 | 647 |
255 for (test of tests) | 648 resetSubscription(subscription); |
256 { | 649 return this.runScheduledTasks(2).then(() => |
257 requests = []; | 650 { |
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 { | |
272 let subscription = Subscription.fromURL("http://example.com/subscription"); | |
273 FilterStorage.addSubscription(subscription); | |
274 | |
275 let testName, subscriptionBody, expectedResult; | |
276 let tests = [ | |
277 ["Correct checksum", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\nfoo\n
bar\n", true], | |
278 ["Wrong checksum", "[Adblock]\n! Checksum: wrongggny6Fn24b7JHsq/A\nfoo\nba
r\n", false], | |
279 ["Empty lines ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\n\n
foo\n\nbar\n\n", true], | |
280 ["CR LF line breaks treated like LR", "[Adblock]\n! Checksum: e/JCmqXny6Fn
24b7JHsq/A\nfoo\r\nbar\r\n", true], | |
281 ["CR line breaks treated like LR", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b
7JHsq/A\nfoo\rbar\r", true], | |
282 ["Trailing line break not ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24
b7JHsq/A\nfoo\nbar", false], | |
283 ["Line breaks between lines not ignored", "[Adblock]\n! Checksum: e/JCmqXn
y6Fn24b7JHsq/A\nfoobar", false], | |
284 ["Lines with spaces not ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7
JHsq/A\n \nfoo\n\nbar\n", false], | |
285 ["Extra content in checksum line is part of the checksum", "[Adblock]\n! C
hecksum: e/JCmqXny6Fn24b7JHsq/A foobar\nfoo\nbar\n", false], | |
286 ["= symbols after checksum are ignored", "[Adblock]\n! Checksum: e/JCmqXny
6Fn24b7JHsq/A===\nfoo\nbar\n", true], | |
287 ["Header line is part of the checksum", "[Adblock Plus]\n! Checksum: e/JCm
qXny6Fn24b7JHsq/A\nfoo\nbar\n", false], | |
288 ["Special comments are part of the checksum", "[Adblock]\n! Checksum: e/JC
mqXny6Fn24b7JHsq/A\n! Expires: 1\nfoo\nbar\n", false], | |
289 ]; | |
290 | |
291 testRunner.registerHandler("/subscription", function(metadata) | |
292 { | |
293 return [Cr.NS_OK, 200, subscriptionBody]; | |
294 }); | |
295 | |
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 }); | |
303 | |
304 test("Special comments", function() | |
305 { | |
306 let subscription = Subscription.fromURL("http://example.com/subscription"); | |
307 FilterStorage.addSubscription(subscription); | |
308 | |
309 let comment, check; | |
310 let tests = [ | |
311 ["! Homepage: http://example.com/", () => equal(subscription.homepage, "ht
tp://example.com/", "Valid homepage comment")], | |
312 ["! Homepage: ssh://example.com/", () => equal(subscription.homepage, null
, "Invalid homepage comment")], | |
313 ["! Title: foo", function() | |
314 { | |
315 equal(subscription.title, "foo", "Title comment"); | |
316 equal(subscription.fixedTitle, true, "Fixed title"); | |
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(); | 651 check(); |
331 deepEqual(subscription.filters, [Filter.fromText("foo"), Filter.fromText("
bar")], "Special comment not added to filters"); | 652 test.deepEqual(subscription.filters, [Filter.fromText("foo"), Filter.fromT
ext("bar")], "Special comment not added to filters"); |
332 } | 653 }).then(runTest); |
333 }); | 654 }; |
334 | 655 |
335 test("Redirects", function() | 656 runTest().catch(unexpectedError.bind(test)).then(() => test.done()); |
336 { | 657 }; |
337 let subscription = Subscription.fromURL("http://example.com/subscription"); | 658 |
338 FilterStorage.addSubscription(subscription); | 659 exports.testRedirects = function(test) |
339 | 660 { |
340 testRunner.registerHandler("/subscription", function(metadata) | 661 let subscription = Subscription.fromURL("http://example.com/subscription"); |
341 { | 662 FilterStorage.addSubscription(subscription); |
342 return [Cr.NS_OK, 200, "[Adblock]\nfoo\n!Redirect: http://example.com/redi
rected\nbar"]; | 663 |
343 }); | 664 this.registerHandler("/subscription", metadata => |
344 | 665 { |
345 testRunner.runScheduledTasks(30); | 666 return [Cr.NS_OK, 200, "[Adblock]\nfoo\n!Redirect: http://example.com/redire
cted\nbar"]; |
346 equal(FilterStorage.subscriptions[0], subscription, "Invalid redirect ignore
d"); | 667 }); |
347 equal(subscription.downloadStatus, "synchronize_connection_error", "Connecti
on error recorded"); | 668 |
348 equal(subscription.errors, 2, "Number of download errors"); | 669 let requests; |
349 | 670 |
350 let requests = []; | 671 this.runScheduledTasks(30).then(() => |
351 testRunner.registerHandler("/redirected", function(metadata) | 672 { |
352 { | 673 test.equal(FilterStorage.subscriptions[0], subscription, "Invalid redirect i
gnored"); |
353 requests.push(testRunner.getTimeOffset()); | 674 test.equal(subscription.downloadStatus, "synchronize_connection_error", "Con
nection error recorded"); |
| 675 test.equal(subscription.errors, 2, "Number of download errors"); |
| 676 |
| 677 requests = []; |
| 678 |
| 679 this.registerHandler("/redirected", metadata => |
| 680 { |
| 681 requests.push(this.getTimeOffset()); |
354 return [Cr.NS_OK, 200, "[Adblock]\nfoo\n! Expires: 8 hours\nbar"]; | 682 return [Cr.NS_OK, 200, "[Adblock]\nfoo\n! Expires: 8 hours\nbar"]; |
355 }); | 683 }); |
356 | 684 |
357 resetSubscription(subscription); | 685 resetSubscription(subscription); |
358 testRunner.runScheduledTasks(15); | 686 return this.runScheduledTasks(15); |
359 equal(FilterStorage.subscriptions[0].url, "http://example.com/redirected", "
Redirect followed"); | 687 }).then(() => |
360 deepEqual(requests, [0 + initialDelay, 8 + initialDelay], "Resulting request
s"); | 688 { |
361 | 689 test.equal(FilterStorage.subscriptions[0].url, "http://example.com/redirecte
d", "Redirect followed"); |
362 testRunner.registerHandler("/redirected", function(metadata) | 690 test.deepEqual(requests, [0 + initialDelay, 8 + initialDelay], "Resulting re
quests"); |
| 691 |
| 692 this.registerHandler("/redirected", metadata => |
363 { | 693 { |
364 return [Cr.NS_OK, 200, "[Adblock]\nfoo\n!Redirect: http://example.com/subs
cription\nbar"]; | 694 return [Cr.NS_OK, 200, "[Adblock]\nfoo\n!Redirect: http://example.com/subs
cription\nbar"]; |
365 }) | 695 }) |
366 | 696 |
367 subscription = Subscription.fromURL("http://example.com/subscription"); | 697 subscription = Subscription.fromURL("http://example.com/subscription"); |
368 resetSubscription(subscription); | 698 resetSubscription(subscription); |
369 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]); | 699 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]); |
370 FilterStorage.addSubscription(subscription); | 700 FilterStorage.addSubscription(subscription); |
371 | 701 |
372 testRunner.runScheduledTasks(2); | 702 return this.runScheduledTasks(2); |
373 equal(FilterStorage.subscriptions[0], subscription, "Redirect not followed o
n redirect loop"); | 703 }).then(() => |
374 equal(subscription.downloadStatus, "synchronize_connection_error", "Download
status after redirect loop"); | 704 { |
375 }); | 705 test.equal(FilterStorage.subscriptions[0], subscription, "Redirect not follo
wed on redirect loop"); |
376 | 706 test.equal(subscription.downloadStatus, "synchronize_connection_error", "Dow
nload status after redirect loop"); |
377 test("Fallback", function() | 707 }).catch(unexpectedError.bind(test)).then(() => test.done()); |
378 { | 708 }; |
379 Prefs.subscriptions_fallbackerrors = 3; | 709 |
380 Prefs.subscriptions_fallbackurl = "http://example.com/fallback?%SUBSCRIPTION
%&%CHANNELSTATUS%&%RESPONSESTATUS%"; | 710 exports.testFallback = function(test) |
381 | 711 { |
382 let subscription = Subscription.fromURL("http://example.com/subscription"); | 712 Prefs.subscriptions_fallbackerrors = 3; |
383 FilterStorage.addSubscription(subscription); | 713 Prefs.subscriptions_fallbackurl = "http://example.com/fallback?%SUBSCRIPTION%&
%CHANNELSTATUS%&%RESPONSESTATUS%"; |
384 | 714 |
385 // No valid response from fallback | 715 let subscription = Subscription.fromURL("http://example.com/subscription"); |
386 | 716 FilterStorage.addSubscription(subscription); |
387 let requests = []; | 717 |
388 testRunner.registerHandler("/subscription", function(metadata) | 718 // No valid response from fallback |
389 { | 719 |
390 requests.push(testRunner.getTimeOffset()); | 720 let requests = []; |
391 return [Cr.NS_OK, 404, ""]; | 721 let fallbackParams; |
392 }); | 722 let redirectedRequests; |
393 | 723 this.registerHandler("/subscription", metadata => |
394 testRunner.runScheduledTasks(100); | 724 { |
395 deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialDelay,
72 + initialDelay, 96 + initialDelay], "Continue trying if the fallback doesn't
respond"); | 725 requests.push(this.getTimeOffset()); |
| 726 return [Cr.NS_OK, 404, ""]; |
| 727 }); |
| 728 |
| 729 this.runScheduledTasks(100).then(() => |
| 730 { |
| 731 test.deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialD
elay, 72 + initialDelay, 96 + initialDelay], "Continue trying if the fallback do
esn't respond"); |
396 | 732 |
397 // Fallback giving "Gone" response | 733 // Fallback giving "Gone" response |
398 | 734 |
399 resetSubscription(subscription); | 735 resetSubscription(subscription); |
400 requests = []; | 736 requests = []; |
401 fallbackParams = null; | 737 fallbackParams = null; |
402 testRunner.registerHandler("/fallback", function(metadata) | 738 this.registerHandler("/fallback", metadata => |
403 { | 739 { |
404 fallbackParams = decodeURIComponent(metadata.queryString); | 740 fallbackParams = decodeURIComponent(metadata.queryString); |
405 return [Cr.NS_OK, 200, "410 Gone"]; | 741 return [Cr.NS_OK, 200, "410 Gone"]; |
406 }); | 742 }); |
407 | 743 |
408 testRunner.runScheduledTasks(100); | 744 return this.runScheduledTasks(100); |
409 deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialDelay]
, "Stop trying if the fallback responds with Gone"); | 745 }).then(() => |
410 equal(fallbackParams, "http://example.com/subscription&0&404", "Fallback arg
uments"); | 746 { |
| 747 test.deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialD
elay], "Stop trying if the fallback responds with Gone"); |
| 748 test.equal(fallbackParams, "http://example.com/subscription&0&404", "Fallbac
k arguments"); |
411 | 749 |
412 // Fallback redirecting to a missing file | 750 // Fallback redirecting to a missing file |
413 | 751 |
414 subscription = Subscription.fromURL("http://example.com/subscription"); | 752 subscription = Subscription.fromURL("http://example.com/subscription"); |
415 resetSubscription(subscription); | 753 resetSubscription(subscription); |
416 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]); | 754 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]); |
417 FilterStorage.addSubscription(subscription); | 755 FilterStorage.addSubscription(subscription); |
418 requests = []; | 756 requests = []; |
419 | 757 |
420 testRunner.registerHandler("/fallback", function(metadata) | 758 this.registerHandler("/fallback", metadata => |
421 { | 759 { |
422 return [Cr.NS_OK, 200, "301 http://example.com/redirected"]; | 760 return [Cr.NS_OK, 200, "301 http://example.com/redirected"]; |
423 }); | 761 }); |
424 testRunner.runScheduledTasks(100); | 762 return this.runScheduledTasks(100); |
425 equal(FilterStorage.subscriptions[0].url, "http://example.com/subscription",
"Ignore invalid redirect from fallback"); | 763 }).then(() => |
426 deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialDelay,
72 + initialDelay, 96 + initialDelay], "Requests not affected by invalid redire
ct"); | 764 { |
| 765 test.equal(FilterStorage.subscriptions[0].url, "http://example.com/subscript
ion", "Ignore invalid redirect from fallback"); |
| 766 test.deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialD
elay, 72 + initialDelay, 96 + initialDelay], "Requests not affected by invalid r
edirect"); |
427 | 767 |
428 // Fallback redirecting to an existing file | 768 // Fallback redirecting to an existing file |
429 | 769 |
430 resetSubscription(subscription); | 770 resetSubscription(subscription); |
431 requests = []; | 771 requests = []; |
432 let redirectedRequests = []; | 772 redirectedRequests = []; |
433 testRunner.registerHandler("/redirected", function(metadata) | 773 this.registerHandler("/redirected", metadata => |
434 { | 774 { |
435 redirectedRequests.push(testRunner.getTimeOffset()); | 775 redirectedRequests.push(this.getTimeOffset()); |
436 return [Cr.NS_OK, 200, "[Adblock]\n!Expires: 1day\nfoo\nbar"]; | 776 return [Cr.NS_OK, 200, "[Adblock]\n!Expires: 1day\nfoo\nbar"]; |
437 }); | 777 }); |
438 | 778 |
439 testRunner.runScheduledTasks(100); | 779 return this.runScheduledTasks(100); |
440 equal(FilterStorage.subscriptions[0].url, "http://example.com/redirected", "
Valid redirect from fallback is followed"); | 780 }).then(() => |
441 deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialDelay]
, "Stop polling original URL after a valid redirect from fallback"); | 781 { |
442 deepEqual(redirectedRequests, [48 + initialDelay, 72 + initialDelay, 96 + in
itialDelay], "Request new URL after a valid redirect from fallback"); | 782 test.equal(FilterStorage.subscriptions[0].url, "http://example.com/redirecte
d", "Valid redirect from fallback is followed"); |
| 783 test.deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialD
elay], "Stop polling original URL after a valid redirect from fallback"); |
| 784 test.deepEqual(redirectedRequests, [48 + initialDelay, 72 + initialDelay, 96
+ initialDelay], "Request new URL after a valid redirect from fallback"); |
443 | 785 |
444 // Checksum mismatch | 786 // Checksum mismatch |
445 | 787 |
446 testRunner.registerHandler("/subscription", function(metadata) | 788 this.registerHandler("/subscription", metadata => |
447 { | 789 { |
448 return [Cr.NS_OK, 200, "[Adblock]\n! Checksum: wrong\nfoo\nbar"]; | 790 return [Cr.NS_OK, 200, "[Adblock]\n! Checksum: wrong\nfoo\nbar"]; |
449 }); | 791 }); |
450 | 792 |
451 subscription = Subscription.fromURL("http://example.com/subscription"); | 793 subscription = Subscription.fromURL("http://example.com/subscription"); |
452 resetSubscription(subscription); | 794 resetSubscription(subscription); |
453 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]); | 795 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]); |
454 FilterStorage.addSubscription(subscription); | 796 FilterStorage.addSubscription(subscription); |
455 | 797 |
456 testRunner.runScheduledTasks(100); | 798 return this.runScheduledTasks(100); |
457 equal(FilterStorage.subscriptions[0].url, "http://example.com/redirected", "
Wrong checksum produces fallback request"); | 799 }).then(() => |
| 800 { |
| 801 test.equal(FilterStorage.subscriptions[0].url, "http://example.com/redirecte
d", "Wrong checksum produces fallback request"); |
458 | 802 |
459 // Redirect loop | 803 // Redirect loop |
460 | 804 |
461 testRunner.registerHandler("/subscription", function(metadata) | 805 this.registerHandler("/subscription", metadata => |
462 { | 806 { |
463 return [Cr.NS_OK, 200, "[Adblock]\n! Redirect: http://example.com/subscrip
tion2"]; | 807 return [Cr.NS_OK, 200, "[Adblock]\n! Redirect: http://example.com/subscrip
tion2"]; |
464 }); | 808 }); |
465 testRunner.registerHandler("/subscription2", function(metadata, response) | 809 this.registerHandler("/subscription2", metadata => |
466 { | 810 { |
467 return [Cr.NS_OK, 200, "[Adblock]\n! Redirect: http://example.com/subscrip
tion"]; | 811 return [Cr.NS_OK, 200, "[Adblock]\n! Redirect: http://example.com/subscrip
tion"]; |
468 }); | 812 }); |
469 | 813 |
470 subscription = Subscription.fromURL("http://example.com/subscription"); | 814 subscription = Subscription.fromURL("http://example.com/subscription"); |
471 resetSubscription(subscription); | 815 resetSubscription(subscription); |
472 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]); | 816 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]); |
473 FilterStorage.addSubscription(subscription); | 817 FilterStorage.addSubscription(subscription); |
474 | 818 |
475 testRunner.runScheduledTasks(100); | 819 return this.runScheduledTasks(100); |
476 equal(FilterStorage.subscriptions[0].url, "http://example.com/redirected", "
Fallback can still redirect even after a redirect loop"); | 820 }).then(() => |
477 }); | 821 { |
478 | 822 test.equal(FilterStorage.subscriptions[0].url, "http://example.com/redirecte
d", "Fallback can still redirect even after a redirect loop"); |
479 test("State fields", function() | 823 }).catch(unexpectedError.bind(test)).then(() => test.done()); |
480 { | 824 }; |
481 let subscription = Subscription.fromURL("http://example.com/subscription"); | 825 |
482 FilterStorage.addSubscription(subscription); | 826 exports.testStateFields = function(test) |
483 | 827 { |
484 testRunner.registerHandler("/subscription", function(metadata) | 828 let subscription = Subscription.fromURL("http://example.com/subscription"); |
485 { | 829 FilterStorage.addSubscription(subscription); |
486 return [Cr.NS_OK, 200, "[Adblock]\n! Expires: 2 hours\nfoo\nbar"]; | 830 |
487 }); | 831 this.registerHandler("/subscription", metadata => |
488 | 832 { |
489 let startTime = testRunner.currentTime; | 833 return [Cr.NS_OK, 200, "[Adblock]\n! Expires: 2 hours\nfoo\nbar"]; |
490 testRunner.runScheduledTasks(2); | 834 }); |
491 | 835 |
492 equal(subscription.downloadStatus, "synchronize_ok", "downloadStatus after s
uccessful download"); | 836 let startTime = this.currentTime; |
493 equal(subscription.lastDownload * MILLIS_IN_SECOND, startTime + initialDela
y * MILLIS_IN_HOUR, "lastDownload after successful download"); | 837 this.runScheduledTasks(2).then(() => |
494 equal(subscription.lastSuccess * MILLIS_IN_SECOND, startTime + initialDelay
* MILLIS_IN_HOUR, "lastSuccess after successful download"); | 838 { |
495 equal(subscription.lastCheck * MILLIS_IN_SECOND, startTime + (1 + initialDe
lay) * MILLIS_IN_HOUR, "lastCheck after successful download"); | 839 test.equal(subscription.downloadStatus, "synchronize_ok", "downloadStatus af
ter successful download"); |
496 equal(subscription.errors, 0, "errors after successful download"); | 840 test.equal(subscription.lastDownload * MILLIS_IN_SECOND, startTime + initia
lDelay * MILLIS_IN_HOUR, "lastDownload after successful download"); |
497 | 841 test.equal(subscription.lastSuccess * MILLIS_IN_SECOND, startTime + initial
Delay * MILLIS_IN_HOUR, "lastSuccess after successful download"); |
498 testRunner.registerHandler("/subscription", function(metadata) | 842 test.equal(subscription.lastCheck * MILLIS_IN_SECOND, startTime + (1 + init
ialDelay) * MILLIS_IN_HOUR, "lastCheck after successful download"); |
| 843 test.equal(subscription.errors, 0, "errors after successful download"); |
| 844 |
| 845 this.registerHandler("/subscription", metadata => |
499 { | 846 { |
500 return [Cr.NS_ERROR_FAILURE, 0, ""]; | 847 return [Cr.NS_ERROR_FAILURE, 0, ""]; |
501 }); | 848 }); |
502 | 849 |
503 testRunner.runScheduledTasks(2); | 850 return this.runScheduledTasks(2); |
504 | 851 }).then(() => |
505 equal(subscription.downloadStatus, "synchronize_connection_error", "download
Status after connection error"); | 852 { |
506 equal(subscription.lastDownload * MILLIS_IN_SECOND, startTime + (2 + initia
lDelay) * MILLIS_IN_HOUR, "lastDownload after connection error"); | 853 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"); | 854 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"); | 855 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"); | 856 test.equal(subscription.lastCheck * MILLIS_IN_SECOND, startTime + (3 + initi
alDelay) * MILLIS_IN_HOUR, "lastCheck after connection error"); |
510 | 857 test.equal(subscription.errors, 1, "errors after connection error"); |
511 testRunner.registerHandler("/subscription", function(metadata) | 858 |
| 859 this.registerHandler("/subscription", metadata => |
512 { | 860 { |
513 return [Cr.NS_OK, 404, ""]; | 861 return [Cr.NS_OK, 404, ""]; |
514 }); | 862 }); |
515 | 863 |
516 testRunner.runScheduledTasks(24); | 864 return this.runScheduledTasks(24); |
517 | 865 }).then(() => |
518 equal(subscription.downloadStatus, "synchronize_connection_error", "download
Status after download error"); | 866 { |
519 equal(subscription.lastDownload * MILLIS_IN_SECOND, startTime + (26 + initia
lDelay) * MILLIS_IN_HOUR, "lastDownload after download error"); | 867 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"); | 868 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"); | 869 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"); | 870 test.equal(subscription.lastCheck * MILLIS_IN_SECOND, startTime + (27 + init
ialDelay) * MILLIS_IN_HOUR, "lastCheck after download error"); |
523 }); | 871 test.equal(subscription.errors, 2, "errors after download error"); |
524 })(); | 872 }).catch(unexpectedError.bind(test)).then(() => test.done()); |
| 873 }; |
OLD | NEW |