LEFT | RIGHT |
1 (function() | 1 (function() |
2 { | 2 { |
3 let testRunner = null; | 3 let testRunner = null; |
4 let server = null; | 4 let server = null; |
5 let randomResult = 0.5; | 5 let randomResult = 0.5; |
6 | 6 |
7 const MILLIS_IN_SECOND = 1000; | 7 const MILLIS_IN_SECOND = 1000; |
8 const MILLIS_IN_MINUTE = 60 * MILLIS_IN_SECOND; | 8 const MILLIS_IN_MINUTE = 60 * MILLIS_IN_SECOND; |
9 const MILLIS_IN_HOUR = 60 * MILLIS_IN_MINUTE; | 9 const MILLIS_IN_HOUR = 60 * MILLIS_IN_MINUTE; |
10 const MILLIS_IN_DAY = 24 * MILLIS_IN_HOUR; | 10 const MILLIS_IN_DAY = 24 * MILLIS_IN_HOUR; |
11 | 11 |
12 module("Synchronizer", { | 12 module("Synchronizer", { |
13 QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakRef
erence]), | 13 QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakRef
erence]), |
14 | 14 |
15 setup: function() | 15 setup: function() |
16 { | 16 { |
17 testRunner = this; | 17 testRunner = this; |
18 | 18 |
19 prepareFilterComponents.call(this); | 19 prepareFilterComponents.call(this); |
20 preparePrefs.call(this); | 20 preparePrefs.call(this); |
21 | 21 |
22 let SynchronizerGlobal = Cu.getGlobalForObject(Synchronizer); | 22 let SynchronizerGlobal = Cu.getGlobalForObject(Synchronizer); |
23 let SynchronizerModule = getModuleGlobal("synchronizer"); | 23 let SynchronizerModule = getModuleGlobal("synchronizer"); |
| 24 let DownloaderGlobal = Cu.getGlobalForObject(SynchronizerModule.downloader
); |
24 | 25 |
25 server = new nsHttpServer(); | 26 server = new nsHttpServer(); |
26 server.start(1234); | 27 server.start(1234); |
27 | 28 |
28 let currentTime = 100000 * MILLIS_IN_HOUR; | 29 let currentTime = 100000 * MILLIS_IN_HOUR; |
29 let startTime = currentTime; | 30 let startTime = currentTime; |
30 let scheduledTasks = []; | 31 let scheduledTasks = []; |
31 | 32 |
32 // Replace Date.now() function | 33 // Replace Date.now() function |
33 this._origNow = SynchronizerGlobal.Date.now; | 34 this._origNow = SynchronizerGlobal.Date.now; |
34 SynchronizerGlobal.Date.now = function() currentTime; | 35 SynchronizerGlobal.Date.now = DownloaderGlobal.Date.now = function() curre
ntTime; |
35 | 36 |
36 // Replace Math.random() function | 37 // Replace Math.random() function |
37 this._origRandom = SynchronizerGlobal.Math.random; | 38 this._origRandom = DownloaderGlobal.Math.random; |
38 SynchronizerGlobal.Math.random = function() randomResult; | 39 DownloaderGlobal.Math.random = function() randomResult; |
39 | 40 |
40 // Replace global timer variable | 41 // Replace global timer variable |
41 let timer = {__proto__: SynchronizerModule.timer, delay: 0.1 * MILLIS_IN_H
OUR}; | 42 let timer = {__proto__: SynchronizerModule.downloader._timer, delay: 0.1 *
MILLIS_IN_HOUR}; |
42 let callback = timer.callback; | 43 let callback = timer.callback; |
43 timer.handler = function() { callback.notify(timer); }; | 44 timer.handler = function() { callback.notify(timer); }; |
44 timer.nextExecution = currentTime + timer.delay; | 45 timer.nextExecution = currentTime + timer.delay; |
45 scheduledTasks.push(timer); | 46 scheduledTasks.push(timer); |
46 SynchronizerModule.timer.cancel(); | 47 SynchronizerModule.downloader._timer.cancel(); |
47 SynchronizerModule.timer = timer; | 48 SynchronizerModule.downloader._timer = timer; |
48 | 49 |
49 // Register observer to track outstanding requests | 50 // Register observer to track outstanding requests |
50 this._outstandingRequests = 0; | 51 this._outstandingRequests = 0; |
51 Services.obs.addObserver(this, "http-on-modify-request", true); | 52 Services.obs.addObserver(this, "http-on-modify-request", true); |
52 Services.obs.addObserver(this, "http-on-examine-response", true); | 53 Services.obs.addObserver(this, "http-on-examine-response", true); |
53 | 54 |
54 this.runScheduledTasks = function(maxHours, initial, skip) | 55 this.runScheduledTasks = function(maxHours, initial, skip) |
55 { | 56 { |
56 if (typeof maxHours != "number") | 57 if (typeof maxHours != "number") |
57 throw new Error("Numerical parameter expected"); | 58 throw new Error("Numerical parameter expected"); |
58 if (typeof initial != "number") | 59 if (typeof initial != "number") |
59 initial = 0; | 60 initial = 0; |
60 if (typeof skip != "number") | 61 if (typeof skip != "number") |
61 skip = 0; | 62 skip = 0; |
62 | 63 |
63 startTime = currentTime; | 64 startTime = currentTime; |
64 if (initial >= 0) | 65 if (initial >= 0) |
65 { | 66 { |
66 this._runScheduledTasks(initial); | 67 this._runScheduledTasks(initial); |
67 maxHours -= initial; | 68 maxHours -= initial; |
68 } | 69 } |
69 if (skip) | 70 if (skip) |
70 { | 71 { |
71 this._skipTasks(skip); | 72 this._skipTasks(skip); |
72 maxHours -= initial; | 73 maxHours -= skip; |
73 } | 74 } |
74 this._runScheduledTasks(maxHours); | 75 this._runScheduledTasks(maxHours); |
75 } | 76 } |
76 | 77 |
77 this._runScheduledTasks = function(maxHours) | 78 this._runScheduledTasks = function(maxHours) |
78 { | 79 { |
79 let endTime = currentTime + maxHours * MILLIS_IN_HOUR; | 80 let endTime = currentTime + maxHours * MILLIS_IN_HOUR; |
80 while (true) | 81 while (true) |
81 { | 82 { |
82 let nextTask = null; | 83 let nextTask = null; |
(...skipping 25 matching lines...) Expand all Loading... |
108 else | 109 else |
109 nextTask.nextExecution = currentTime + nextTask.delay; | 110 nextTask.nextExecution = currentTime + nextTask.delay; |
110 } | 111 } |
111 | 112 |
112 currentTime = endTime; | 113 currentTime = endTime; |
113 } | 114 } |
114 | 115 |
115 this._skipTasks = function(hours) | 116 this._skipTasks = function(hours) |
116 { | 117 { |
117 let newTasks = []; | 118 let newTasks = []; |
118 let endTime = currentTime + hours * MILLIS_IN_HOUR; | 119 currentTime += hours * MILLIS_IN_HOUR; |
119 for each (let task in scheduledTasks) | 120 for each (let task in scheduledTasks) |
120 { | 121 { |
121 if (task.nextExecution >= endTime) | 122 if (task.nextExecution >= currentTime) |
122 newTasks.push(task); | 123 newTasks.push(task); |
123 else if (task.type != Components.interfaces.nsITimer.TYPE_ONE_SHOT) | 124 else if (task.type != Components.interfaces.nsITimer.TYPE_ONE_SHOT) |
124 { | 125 { |
125 task.nextExecution = endTime; | 126 task.nextExecution = currentTime; |
126 newTasks.push(task); | 127 newTasks.push(task); |
127 } | 128 } |
128 } | 129 } |
129 scheduledTasks = newTasks; | 130 scheduledTasks = newTasks; |
130 } | 131 } |
131 | 132 |
132 this.getTimeOffset = function() (currentTime - startTime) / MILLIS_IN_HOUR
; | 133 this.getTimeOffset = function() (currentTime - startTime) / MILLIS_IN_HOUR
; |
133 | 134 |
134 this.__defineGetter__("currentTime", function() currentTime); | 135 this.__defineGetter__("currentTime", function() currentTime); |
135 }, | 136 }, |
(...skipping 15 matching lines...) Expand all Loading... |
151 stop(); | 152 stop(); |
152 server.stop(function() | 153 server.stop(function() |
153 { | 154 { |
154 server = null; | 155 server = null; |
155 start(); | 156 start(); |
156 }); | 157 }); |
157 | 158 |
158 if (this._origNow) | 159 if (this._origNow) |
159 { | 160 { |
160 let SynchronizerGlobal = Cu.getGlobalForObject(Synchronizer); | 161 let SynchronizerGlobal = Cu.getGlobalForObject(Synchronizer); |
161 SynchronizerGlobal.Date.now = this._origNow; | 162 let SynchronizerModule = getModuleGlobal("synchronizer"); |
| 163 let DownloaderGlobal = Cu.getGlobalForObject(SynchronizerModule.download
er); |
| 164 SynchronizerGlobal.Date.now = DownloaderGlobal.Date.now = this._origNow; |
162 delete this._origNow; | 165 delete this._origNow; |
163 } | 166 } |
164 | 167 |
165 if (this._origRandom) | 168 if (this._origRandom) |
166 { | 169 { |
167 let SynchronizerGlobal = Cu.getGlobalForObject(Synchronizer); | 170 let SynchronizerModule = getModuleGlobal("synchronizer"); |
168 SynchronizerGlobal.Math.random = this._origRandom; | 171 let DownloaderGlobal = Cu.getGlobalForObject(SynchronizerModule.download
er); |
| 172 DownloaderGlobal.Math.random = this._origRandom; |
169 delete this._origRandom; | 173 delete this._origRandom; |
170 } | 174 } |
171 | 175 |
172 Synchronizer.init(); | 176 Synchronizer.init(); |
173 } | 177 } |
174 }); | 178 }); |
175 | 179 |
176 function resetSubscription(subscription) | 180 function resetSubscription(subscription) |
177 { | 181 { |
178 FilterStorage.updateSubscriptionFilters(subscription, []); | 182 FilterStorage.updateSubscriptionFilters(subscription, []); |
179 subscription.lastCheck = subscription.lastDownload = | 183 subscription.lastCheck = subscription.lastDownload = |
180 subscription.lastSuccess = subscription.expires = | 184 subscription.version = subscription.lastSuccess = |
181 subscription.softExpiration = 0; | 185 subscription.expires = subscription.softExpiration = 0; |
| 186 subscription.title = ""; |
| 187 subscription.homepage = null; |
182 subscription.errors = 0; | 188 subscription.errors = 0; |
183 subscription.downloadStatus = null; | 189 subscription.downloadStatus = null; |
184 subscription.requiredVersion = null; | 190 subscription.requiredVersion = null; |
185 subscription.nextURL = null; | |
186 } | 191 } |
187 | 192 |
188 test("Downloads of one subscription", function() | 193 test("Downloads of one subscription", function() |
189 { | 194 { |
190 // Always use average download interval | 195 // Always use average download interval |
191 randomResult = 0.5; | 196 randomResult = 0.5; |
192 | 197 |
193 let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription"
); | 198 let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription"
); |
194 FilterStorage.addSubscription(subscription); | 199 FilterStorage.addSubscription(subscription); |
195 | 200 |
196 let requests = []; | 201 let requests = []; |
197 function handler(metadata, response) | 202 function handler(metadata, response) |
198 { | 203 { |
199 requests.push([testRunner.getTimeOffset(), metadata.method, metadata.path]
); | 204 requests.push([testRunner.getTimeOffset(), metadata.method, metadata.path]
); |
200 | 205 |
201 response.setStatusLine("1.1", "200", "OK"); | 206 response.setStatusLine("1.1", "200", "OK"); |
202 response.setHeader("Content-Type", "text/plain"); | 207 response.setHeader("Content-Type", "text/plain"); |
203 | 208 |
204 let result = "[Adblock]\nfoo\nbar"; | 209 let result = "[Adblock]\n! ExPiREs: 1day\nfoo\nbar"; |
205 response.bodyOutputStream.write(result, result.length); | 210 response.bodyOutputStream.write(result, result.length); |
206 } | 211 } |
207 | 212 |
208 server.registerPathHandler("/subscription", handler); | 213 server.registerPathHandler("/subscription", handler); |
209 | 214 |
210 testRunner.runScheduledTasks(50); | 215 testRunner.runScheduledTasks(50); |
211 deepEqual(requests, [ | 216 deepEqual(requests, [ |
212 [0.1, "GET", "/subscription"], | 217 [0.1, "GET", "/subscription"], |
213 [24.1, "GET", "/subscription"], | 218 [24.1, "GET", "/subscription"], |
214 [48.1, "GET", "/subscription"], | 219 [48.1, "GET", "/subscription"], |
(...skipping 15 matching lines...) Expand all Loading... |
230 FilterStorage.addSubscription(subscription2); | 235 FilterStorage.addSubscription(subscription2); |
231 | 236 |
232 let requests = []; | 237 let requests = []; |
233 function handler(metadata, response) | 238 function handler(metadata, response) |
234 { | 239 { |
235 requests.push([testRunner.getTimeOffset(), metadata.method, metadata.path]
); | 240 requests.push([testRunner.getTimeOffset(), metadata.method, metadata.path]
); |
236 | 241 |
237 response.setStatusLine("1.1", "200", "OK"); | 242 response.setStatusLine("1.1", "200", "OK"); |
238 response.setHeader("Content-Type", "text/plain"); | 243 response.setHeader("Content-Type", "text/plain"); |
239 | 244 |
240 let result = "[Adblock]\nfoo\nbar"; | 245 let result = "[Adblock]\n! ExPiREs: 1day\nfoo\nbar"; |
241 response.bodyOutputStream.write(result, result.length); | 246 response.bodyOutputStream.write(result, result.length); |
242 } | 247 } |
243 | 248 |
244 server.registerPathHandler("/subscription1", handler); | 249 server.registerPathHandler("/subscription1", handler); |
245 server.registerPathHandler("/subscription2", handler); | 250 server.registerPathHandler("/subscription2", handler); |
246 | 251 |
247 testRunner.runScheduledTasks(55); | 252 testRunner.runScheduledTasks(55); |
248 deepEqual(requests, [ | 253 deepEqual(requests, [ |
249 [0.1, "GET", "/subscription1"], | 254 [0.1, "GET", "/subscription1"], |
250 [2.1, "GET", "/subscription2"], | 255 [2.1, "GET", "/subscription2"], |
(...skipping 13 matching lines...) Expand all Loading... |
264 let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription"
); | 269 let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription"
); |
265 FilterStorage.addSubscription(subscription); | 270 FilterStorage.addSubscription(subscription); |
266 | 271 |
267 function handler(metadata, response) | 272 function handler(metadata, response) |
268 { | 273 { |
269 response.setStatusLine("1.1", "200", "OK"); | 274 response.setStatusLine("1.1", "200", "OK"); |
270 | 275 |
271 // Wrong content type shouldn't matter | 276 // Wrong content type shouldn't matter |
272 response.setHeader("Content-Type", "text/xml"); | 277 response.setHeader("Content-Type", "text/xml"); |
273 | 278 |
274 let result = test.header + "\nfoo\n!bar\n\n@@bas\n#bam"; | 279 let result = test.header + "\n!Expires: 8 hours\nfoo\n!bar\n\n@@bas\n#bam"
; |
275 response.bodyOutputStream.write(result, result.length); | 280 response.bodyOutputStream.write(result, result.length); |
276 } | 281 } |
277 server.registerPathHandler("/subscription", handler); | 282 server.registerPathHandler("/subscription", handler); |
278 | 283 |
279 let tests = [ | 284 let tests = [ |
280 {header: "[Adblock]", downloadStatus: "synchronize_ok", requiredVersion: n
ull}, | 285 {header: "[Adblock]", downloadStatus: "synchronize_ok", requiredVersion: n
ull}, |
281 {header: "[Adblock Plus]", downloadStatus: "synchronize_ok", requiredVersi
on: null}, | 286 {header: "[Adblock Plus]", downloadStatus: "synchronize_ok", requiredVersi
on: null}, |
282 {header: "(something)[Adblock]", downloadStatus: "synchronize_ok", require
dVersion: null}, | 287 {header: "(something)[Adblock]", downloadStatus: "synchronize_ok", require
dVersion: null}, |
283 {header: "[Adblock Plus 0.0.1]", downloadStatus: "synchronize_ok", require
dVersion: "0.0.1"}, | 288 {header: "[Adblock Plus 0.0.1]", downloadStatus: "synchronize_ok", require
dVersion: "0.0.1"}, |
284 {header: "[Adblock Plus 99.9]", downloadStatus: "synchronize_ok", required
Version: "99.9"}, | 289 {header: "[Adblock Plus 99.9]", downloadStatus: "synchronize_ok", required
Version: "99.9"}, |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 response.setStatusLine("1.1", "200", "OK"); | 348 response.setStatusLine("1.1", "200", "OK"); |
344 response.setHeader("Content-Type", "text/plain"); | 349 response.setHeader("Content-Type", "text/plain"); |
345 | 350 |
346 let result = "[Adblock]\nfoo\n!Expires: " + test.expiration + "\nbar"; | 351 let result = "[Adblock]\nfoo\n!Expires: " + test.expiration + "\nbar"; |
347 response.bodyOutputStream.write(result, result.length); | 352 response.bodyOutputStream.write(result, result.length); |
348 } | 353 } |
349 server.registerPathHandler("/subscription", handler); | 354 server.registerPathHandler("/subscription", handler); |
350 | 355 |
351 let tests = [ | 356 let tests = [ |
352 { | 357 { |
353 expiration: "1 hour", // Too small, will be corrected | 358 expiration: "default", |
354 randomResult: 0.5, | 359 randomResult: 0.5, |
355 requests: [0.1, 24.1] | 360 requests: [0.1, 5 * 24 + 0.1] |
| 361 }, |
| 362 { |
| 363 expiration: "1 hours", // Minimal expiration interval |
| 364 randomResult: 0.5, |
| 365 requests: [0.1, 1.1, 2.1, 3.1] |
356 }, | 366 }, |
357 { | 367 { |
358 expiration: "26 hours", | 368 expiration: "26 hours", |
359 randomResult: 0.5, | 369 randomResult: 0.5, |
360 requests: [0.1, 26.1] | 370 requests: [0.1, 26.1] |
361 }, | 371 }, |
362 { | 372 { |
363 expiration: "2 days", | 373 expiration: "2 days", |
364 randomResult: 0.5, | 374 randomResult: 0.5, |
365 requests: [0.1, 48.1] | 375 requests: [0.1, 48.1] |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 requests: [0.1, 85.1] | 416 requests: [0.1, 85.1] |
407 } | 417 } |
408 ] | 418 ] |
409 | 419 |
410 for each (test in tests) | 420 for each (test in tests) |
411 { | 421 { |
412 requests = []; | 422 requests = []; |
413 randomResult = test.randomResult; | 423 randomResult = test.randomResult; |
414 resetSubscription(subscription); | 424 resetSubscription(subscription); |
415 | 425 |
416 let maxHours = Math.round(Math.max.apply(null, test.requests)) + 12; | 426 let maxHours = Math.round(Math.max.apply(null, test.requests)) + 1; |
417 testRunner.runScheduledTasks(maxHours, test.skipAfter, test.skip); | 427 testRunner.runScheduledTasks(maxHours, test.skipAfter, test.skip); |
418 | 428 |
419 let randomAddendum = (randomResult == 0.5 ? "" : " with Math.random() retu
rning " + randomResult); | 429 let randomAddendum = (randomResult == 0.5 ? "" : " with Math.random() retu
rning " + randomResult); |
420 let skipAddendum = (typeof test.skip != "number" ? "" : " skipping " + tes
t.skip + " hours after " + test.skipAfter + " hours"); | 430 let skipAddendum = (typeof test.skip != "number" ? "" : " skipping " + tes
t.skip + " hours after " + test.skipAfter + " hours"); |
421 deepEqual(requests, test.requests, "Requests for \"" + test.expiration + "
\"" + randomAddendum + skipAddendum); | 431 deepEqual(requests, test.requests, "Requests for \"" + test.expiration + "
\"" + randomAddendum + skipAddendum); |
422 | 432 } |
423 if (typeof test.skip == "number") | 433 }); |
424 { | 434 |
425 // Ensure that next time synchronizer triggers at time offset 0.1 again | 435 test("Checksum verification", function() |
426 testRunner.runScheduledTasks(0.1); | 436 { |
427 } | 437 // Always use average download interval |
| 438 randomResult = 0.5; |
| 439 |
| 440 let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription"
); |
| 441 FilterStorage.addSubscription(subscription); |
| 442 |
| 443 let testName, subscriptionBody, expectedResult; |
| 444 let tests = [ |
| 445 ["Correct checksum", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\nfoo\n
bar\n", true], |
| 446 ["Wrong checksum", "[Adblock]\n! Checksum: wrongggny6Fn24b7JHsq/A\nfoo\nba
r\n", false], |
| 447 ["Empty lines ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\n\n
foo\n\nbar\n\n", true], |
| 448 ["CR LF line breaks treated like LR", "[Adblock]\n! Checksum: e/JCmqXny6Fn
24b7JHsq/A\nfoo\r\nbar\r\n", true], |
| 449 ["CR line breaks treated like LR", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b
7JHsq/A\nfoo\rbar\r", true], |
| 450 ["Trailing line break not ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24
b7JHsq/A\nfoo\nbar", false], |
| 451 ["Line breaks between lines not ignored", "[Adblock]\n! Checksum: e/JCmqXn
y6Fn24b7JHsq/A\nfoobar", false], |
| 452 ["Lines with spaces not ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7
JHsq/A\n \nfoo\n\nbar\n", false], |
| 453 ["Extra content in checksum line is part of the checksum", "[Adblock]\n! C
hecksum: e/JCmqXny6Fn24b7JHsq/A foobar\nfoo\nbar\n", false], |
| 454 ["= symbols after checksum are ignored", "[Adblock]\n! Checksum: e/JCmqXny
6Fn24b7JHsq/A===\nfoo\nbar\n", true], |
| 455 ["Header line is part of the checksum", "[Adblock Plus]\n! Checksum: e/JCm
qXny6Fn24b7JHsq/A\nfoo\nbar\n", false], |
| 456 ["Special comments are part of the checksum", "[Adblock]\n! Checksum: e/JC
mqXny6Fn24b7JHsq/A\n! Expires: 1\nfoo\nbar\n", false], |
| 457 ]; |
| 458 |
| 459 function handler(metadata, response) |
| 460 { |
| 461 response.setStatusLine("1.1", "200", "OK"); |
| 462 response.setHeader("Content-Type", "text/plain"); |
| 463 |
| 464 response.bodyOutputStream.write(subscriptionBody, subscriptionBody.length)
; |
| 465 } |
| 466 server.registerPathHandler("/subscription", handler); |
| 467 |
| 468 for each ([testName, subscriptionBody, expectedResult] in tests) |
| 469 { |
| 470 resetSubscription(subscription); |
| 471 testRunner.runScheduledTasks(2); |
| 472 equal(subscription.downloadStatus, expectedResult ? "synchronize_ok" : "sy
nchronize_checksum_mismatch", testName); |
| 473 } |
| 474 }); |
| 475 |
| 476 test("Special comments", function() |
| 477 { |
| 478 // Always use average download interval |
| 479 randomResult = 0.5; |
| 480 |
| 481 let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription"
); |
| 482 FilterStorage.addSubscription(subscription); |
| 483 |
| 484 let comment, check; |
| 485 let tests = [ |
| 486 ["! Homepage: http://example.com/", function() equal(subscription.homepage
, "http://example.com/", "Valid homepage comment")], |
| 487 ["! Homepage: ssh://example.com/", function() equal(subscription.homepage,
null, "Invalid homepage comment")], |
| 488 ["! Title: foo", function() |
| 489 { |
| 490 equal(subscription.title, "foo", "Title comment"); |
| 491 equal(subscription.fixedTitle, true, "Fixed title"); |
| 492 }], |
| 493 ["! Version: 1234", function() equal(subscription.version, 1234, "Version
comment")] |
| 494 ]; |
| 495 |
| 496 function handler(metadata, response) |
| 497 { |
| 498 response.setStatusLine("1.1", "200", "OK"); |
| 499 response.setHeader("Content-Type", "text/plain"); |
| 500 |
| 501 let result = "[Adblock]\n" + comment + "\nfoo\nbar"; |
| 502 response.bodyOutputStream.write(result, result.length); |
| 503 } |
| 504 server.registerPathHandler("/subscription", handler); |
| 505 |
| 506 for each([comment, check] in tests) |
| 507 { |
| 508 resetSubscription(subscription); |
| 509 testRunner.runScheduledTasks(2); |
| 510 check(); |
| 511 deepEqual(subscription.filters, [Filter.fromText("foo"), Filter.fromText("
bar")], "Special comment not added to filters"); |
428 } | 512 } |
429 }); | 513 }); |
430 | 514 |
431 test("Redirects", function() | 515 test("Redirects", function() |
432 { | 516 { |
| 517 // Always use average download interval |
| 518 randomResult = 0.5; |
| 519 |
433 let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription"
); | 520 let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription"
); |
434 FilterStorage.addSubscription(subscription); | 521 FilterStorage.addSubscription(subscription); |
435 | 522 |
436 function redirect_handler(metadata, response) | 523 function redirect_handler(metadata, response) |
437 { | 524 { |
438 response.setStatusLine("1.1", "200", "OK"); | 525 response.setStatusLine("1.1", "200", "OK"); |
439 response.setHeader("Content-Type", "text/plain"); | 526 response.setHeader("Content-Type", "text/plain"); |
440 | 527 |
441 let result = "[Adblock]\nfoo\n!Redirect: http://127.0.0.1:1234/redirected\
nbar"; | 528 let result = "[Adblock]\nfoo\n!Redirect: http://127.0.0.1:1234/redirected\
nbar"; |
442 response.bodyOutputStream.write(result, result.length); | 529 response.bodyOutputStream.write(result, result.length); |
443 } | 530 } |
444 server.registerPathHandler("/subscription", redirect_handler); | 531 server.registerPathHandler("/subscription", redirect_handler); |
445 | 532 |
446 testRunner.runScheduledTasks(50); | 533 testRunner.runScheduledTasks(30); |
447 equal(FilterStorage.subscriptions[0].url, "http://127.0.0.1:1234/subscriptio
n", "Invalid redirect ignored"); | 534 equal(FilterStorage.subscriptions[0], subscription, "Invalid redirect ignore
d"); |
| 535 equal(subscription.downloadStatus, "synchronize_connection_error", "Connecti
on error recorded"); |
| 536 equal(subscription.errors, 2, "Number of download errors"); |
448 | 537 |
449 let requests = []; | 538 let requests = []; |
450 function handler(metadata, response) | 539 function handler(metadata, response) |
451 { | 540 { |
452 requests.push(testRunner.getTimeOffset()); | 541 requests.push(testRunner.getTimeOffset()); |
453 | 542 |
454 response.setStatusLine("1.1", "200", "OK"); | 543 response.setStatusLine("1.1", "200", "OK"); |
455 response.setHeader("Content-Type", "text/plain"); | 544 response.setHeader("Content-Type", "text/plain"); |
456 | 545 |
457 let result = "[Adblock]\nfoo\nbar"; | 546 let result = "[Adblock]\nfoo\n! Expires: 8 hours\nbar"; |
458 response.bodyOutputStream.write(result, result.length); | 547 response.bodyOutputStream.write(result, result.length); |
459 } | 548 } |
460 server.registerPathHandler("/redirected", handler); | 549 server.registerPathHandler("/redirected", handler); |
461 | 550 |
462 resetSubscription(subscription); | 551 resetSubscription(subscription); |
463 testRunner.runScheduledTasks(50); | 552 testRunner.runScheduledTasks(15); |
464 equal(FilterStorage.subscriptions[0].url, "http://127.0.0.1:1234/redirected"
, "Redirect followed"); | 553 equal(FilterStorage.subscriptions[0].url, "http://127.0.0.1:1234/redirected"
, "Redirect followed"); |
465 deepEqual(requests, [24.1, 48.1], "Resulting requests"); | 554 deepEqual(requests, [0.1, 8.1], "Resulting requests"); |
| 555 |
| 556 server.registerPathHandler("/redirected", function(metadata, response) |
| 557 { |
| 558 response.setStatusLine("1.1", "200", "OK"); |
| 559 response.setHeader("Content-Type", "text/plain"); |
| 560 |
| 561 let result = "[Adblock]\nfoo\n!Redirect: http://127.0.0.1:1234/subscriptio
n\nbar"; |
| 562 response.bodyOutputStream.write(result, result.length); |
| 563 }) |
| 564 |
| 565 let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription"
); |
| 566 resetSubscription(subscription); |
| 567 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]); |
| 568 FilterStorage.addSubscription(subscription); |
| 569 |
| 570 testRunner.runScheduledTasks(2); |
| 571 equal(FilterStorage.subscriptions[0], subscription, "Redirect not followed o
n redirect loop"); |
| 572 equal(subscription.downloadStatus, "synchronize_connection_error", "Download
status after redirect loop"); |
466 }); | 573 }); |
467 | 574 |
468 test("Fallback", function() | 575 test("Fallback", function() |
469 { | 576 { |
| 577 // Always use average download interval |
| 578 randomResult = 0.5; |
| 579 |
470 Prefs.subscriptions_fallbackerrors = 3; | 580 Prefs.subscriptions_fallbackerrors = 3; |
471 Prefs.subscriptions_fallbackurl = "http://127.0.0.1:1234/fallback?%URL%&%CHA
NNELSTATUS%&%RESPONSESTATUS%"; | 581 Prefs.subscriptions_fallbackurl = "http://127.0.0.1:1234/fallback?%SUBSCRIPT
ION%&%CHANNELSTATUS%&%RESPONSESTATUS%"; |
472 | 582 |
473 let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription"
); | 583 let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription"
); |
474 FilterStorage.addSubscription(subscription); | 584 FilterStorage.addSubscription(subscription); |
| 585 |
| 586 // No valid response from fallback |
475 | 587 |
476 let requests = []; | 588 let requests = []; |
477 function handler(metadata, response) | 589 function handler(metadata, response) |
478 { | 590 { |
479 requests.push(testRunner.getTimeOffset()); | 591 requests.push(testRunner.getTimeOffset()); |
480 | 592 |
481 response.setStatusLine("1.1", "404", "Not found"); | 593 response.setStatusLine("1.1", "404", "Not found"); |
482 } | 594 } |
483 server.registerPathHandler("/subscription", handler); | 595 server.registerPathHandler("/subscription", handler); |
484 | 596 |
485 testRunner.runScheduledTasks(100); | 597 testRunner.runScheduledTasks(100); |
486 deepEqual(requests, [0.1, 24.1, 48.1, 72.1, 96.1], "Continue trying if the f
allback doesn't respond"); | 598 deepEqual(requests, [0.1, 24.1, 48.1, 72.1, 96.1], "Continue trying if the f
allback doesn't respond"); |
| 599 |
| 600 // Fallback giving "Gone" response |
487 | 601 |
488 resetSubscription(subscription); | 602 resetSubscription(subscription); |
489 requests = []; | 603 requests = []; |
490 fallbackParams = null; | 604 fallbackParams = null; |
491 server.registerPathHandler("/fallback", function(metadata, response) | 605 server.registerPathHandler("/fallback", function(metadata, response) |
492 { | 606 { |
493 response.setStatusLine("1.1", "200", "OK"); | 607 response.setStatusLine("1.1", "200", "OK"); |
494 fallbackParams = decodeURIComponent(metadata.queryString); | 608 fallbackParams = decodeURIComponent(metadata.queryString); |
495 | 609 |
496 let result = "410 Gone"; | 610 let result = "410 Gone"; |
497 response.bodyOutputStream.write(result, result.length); | 611 response.bodyOutputStream.write(result, result.length); |
498 }); | 612 }); |
499 | 613 |
500 testRunner.runScheduledTasks(100); | 614 testRunner.runScheduledTasks(100); |
501 deepEqual(requests, [0.1, 24.1, 48.1], "Stop trying if the fallback responds
with Gone"); | 615 deepEqual(requests, [0.1, 24.1, 48.1], "Stop trying if the fallback responds
with Gone"); |
502 equal(fallbackParams, "http://127.0.0.1:1234/subscription&0&404"); | 616 equal(fallbackParams, "http://127.0.0.1:1234/subscription&0&404", "Fallback
arguments"); |
503 | 617 |
| 618 // Fallback redirecting to a missing file |
| 619 |
| 620 subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription"); |
504 resetSubscription(subscription); | 621 resetSubscription(subscription); |
505 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]); | 622 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]); |
506 FilterStorage.addSubscription(subscription); | 623 FilterStorage.addSubscription(subscription); |
507 requests = []; | 624 requests = []; |
508 | 625 |
509 server.registerPathHandler("/fallback", function(metadata, response) | 626 server.registerPathHandler("/fallback", function(metadata, response) |
510 { | 627 { |
511 response.setStatusLine("1.1", "200", "OK"); | 628 response.setStatusLine("1.1", "200", "OK"); |
512 | 629 |
513 let result = "301 http://127.0.0.1:1234/redirected"; | 630 let result = "301 http://127.0.0.1:1234/redirected"; |
514 response.bodyOutputStream.write(result, result.length); | 631 response.bodyOutputStream.write(result, result.length); |
515 }); | 632 }); |
516 testRunner.runScheduledTasks(100); | 633 testRunner.runScheduledTasks(100); |
517 equal(FilterStorage.subscriptions[0].url, "http://127.0.0.1:1234/subscriptio
n"); | 634 equal(FilterStorage.subscriptions[0].url, "http://127.0.0.1:1234/subscriptio
n", "Ignore invalid redirect from fallback"); |
518 deepEqual(requests, [0.1, 24.1, 48.1, 96.1], "Come back after invalid redire
ct from fallback"); | 635 deepEqual(requests, [0.1, 24.1, 48.1, 72.1, 96.1], "Requests not affected by
invalid redirect"); |
| 636 |
| 637 // Fallback redirecting to an existing file |
519 | 638 |
520 resetSubscription(subscription); | 639 resetSubscription(subscription); |
521 requests = []; | 640 requests = []; |
522 let redirectedRequests = []; | 641 let redirectedRequests = []; |
523 server.registerPathHandler("/redirected", function(metadata, response) | 642 server.registerPathHandler("/redirected", function(metadata, response) |
524 { | 643 { |
525 redirectedRequests.push(testRunner.getTimeOffset()); | 644 redirectedRequests.push(testRunner.getTimeOffset()); |
526 | 645 |
527 response.setStatusLine("1.1", "200", "OK"); | 646 response.setStatusLine("1.1", "200", "OK"); |
528 response.setHeader("Content-Type", "text/plain"); | 647 response.setHeader("Content-Type", "text/plain"); |
529 | 648 |
530 let result = "[Adblock]\nfoo\nbar"; | 649 let result = "[Adblock]\n!Expires: 1day\nfoo\nbar"; |
531 response.bodyOutputStream.write(result, result.length); | 650 response.bodyOutputStream.write(result, result.length); |
532 }); | 651 }); |
533 | 652 |
534 testRunner.runScheduledTasks(100); | 653 testRunner.runScheduledTasks(100); |
535 equal(FilterStorage.subscriptions[0].url, "http://127.0.0.1:1234/redirected"
); | 654 equal(FilterStorage.subscriptions[0].url, "http://127.0.0.1:1234/redirected"
, "Valid redirect from fallback is followed"); |
536 deepEqual(requests, [0.1, 24.1, 48.1], "Stop polling original URL after a va
lid redirect from fallback"); | 655 deepEqual(requests, [0.1, 24.1, 48.1], "Stop polling original URL after a va
lid redirect from fallback"); |
537 deepEqual(redirectedRequests, [72.1, 96.1], "Request new URL after a valid r
edirect from fallback"); | 656 deepEqual(redirectedRequests, [48.1, 72.1, 96.1], "Request new URL after a v
alid redirect from fallback"); |
538 }); | 657 |
539 | 658 // Checksum mismatch |
540 // TODO: Checksum verification | 659 |
| 660 function handler2(metadata, response) |
| 661 { |
| 662 response.setStatusLine("1.1", "200", "OK"); |
| 663 response.setHeader("Content-Type", "text/plain"); |
| 664 |
| 665 let result = "[Adblock]\n! Checksum: wrong\nfoo\nbar"; |
| 666 response.bodyOutputStream.write(result, result.length); |
| 667 } |
| 668 server.registerPathHandler("/subscription", handler2); |
| 669 |
| 670 subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription"); |
| 671 resetSubscription(subscription); |
| 672 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]); |
| 673 FilterStorage.addSubscription(subscription); |
| 674 |
| 675 testRunner.runScheduledTasks(100); |
| 676 equal(FilterStorage.subscriptions[0].url, "http://127.0.0.1:1234/redirected"
, "Wrong checksum produces fallback request"); |
| 677 |
| 678 // Redirect loop |
| 679 |
| 680 server.registerPathHandler("/subscription", function(metadata, response) |
| 681 { |
| 682 response.setStatusLine("1.1", "200", "OK"); |
| 683 response.setHeader("Content-Type", "text/plain"); |
| 684 |
| 685 let result = "[Adblock]\n! Redirect: http://127.0.0.1:1234/subscription2"; |
| 686 response.bodyOutputStream.write(result, result.length); |
| 687 }); |
| 688 server.registerPathHandler("/subscription2", function(metadata, response) |
| 689 { |
| 690 response.setStatusLine("1.1", "200", "OK"); |
| 691 response.setHeader("Content-Type", "text/plain"); |
| 692 |
| 693 let result = "[Adblock]\n! Redirect: http://127.0.0.1:1234/subscription"; |
| 694 response.bodyOutputStream.write(result, result.length); |
| 695 }); |
| 696 |
| 697 subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription"); |
| 698 resetSubscription(subscription); |
| 699 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]); |
| 700 FilterStorage.addSubscription(subscription); |
| 701 |
| 702 testRunner.runScheduledTasks(100); |
| 703 equal(FilterStorage.subscriptions[0].url, "http://127.0.0.1:1234/redirected"
, "Fallback can still redirect even after a redirect loop"); |
| 704 }); |
| 705 |
| 706 test("State fields", function() |
| 707 { |
| 708 // Always use average download interval |
| 709 randomResult = 0.5; |
| 710 |
| 711 let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription"
); |
| 712 FilterStorage.addSubscription(subscription); |
| 713 |
| 714 server.registerPathHandler("/subscription", function successHandler(metadata
, response) |
| 715 { |
| 716 response.setStatusLine("1.1", "200", "OK"); |
| 717 response.setHeader("Content-Type", "text/plain"); |
| 718 |
| 719 let result = "[Adblock]\n! Expires: 2 hours\nfoo\nbar"; |
| 720 response.bodyOutputStream.write(result, result.length); |
| 721 }); |
| 722 |
| 723 let startTime = testRunner.currentTime; |
| 724 testRunner.runScheduledTasks(2); |
| 725 |
| 726 equal(subscription.downloadStatus, "synchronize_ok", "downloadStatus after s
uccessful download"); |
| 727 equal(subscription.lastDownload * MILLIS_IN_SECOND, startTime + 0.1 * MILLIS
_IN_HOUR, "lastDownload after successful download"); |
| 728 equal(subscription.lastSuccess * MILLIS_IN_SECOND, startTime + 0.1 * MILLIS_
IN_HOUR, "lastSuccess after successful download"); |
| 729 equal(subscription.lastCheck * MILLIS_IN_SECOND, startTime + 1.1 * MILLIS_IN
_HOUR, "lastCheck after successful download"); |
| 730 equal(subscription.errors, 0, "errors after successful download"); |
| 731 |
| 732 server.registerPathHandler("/subscription", function errorHandler(metadata,
response) |
| 733 { |
| 734 response.setStatusLine("1.1", "404", "Not Found"); |
| 735 }); |
| 736 |
| 737 testRunner.runScheduledTasks(2); |
| 738 |
| 739 equal(subscription.downloadStatus, "synchronize_connection_error", "download
Status after download error"); |
| 740 equal(subscription.lastDownload * MILLIS_IN_SECOND, startTime + 2.1 * MILLIS
_IN_HOUR, "lastDownload after download error"); |
| 741 equal(subscription.lastSuccess * MILLIS_IN_SECOND, startTime + 0.1 * MILLIS_
IN_HOUR, "lastSuccess after download error"); |
| 742 equal(subscription.lastCheck * MILLIS_IN_SECOND, startTime + 3.1 * MILLIS_IN
_HOUR, "lastCheck after download error"); |
| 743 equal(subscription.errors, 1, "errors after download error"); |
| 744 }); |
541 })(); | 745 })(); |
LEFT | RIGHT |