LEFT | RIGHT |
(no file at all) | |
| 1 /* |
| 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
| 3 * Copyright (C) 2006-present eyeo GmbH |
| 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 { |
| 21 createSandbox, setupTimerAndXMLHttp, setupRandomResult, unexpectedError, Cr, |
| 22 MILLIS_IN_SECOND, MILLIS_IN_HOUR |
| 23 } = require("./_common"); |
| 24 |
| 25 let Filter = null; |
| 26 let FilterStorage = null; |
| 27 let Prefs = null; |
| 28 let Subscription = null; |
| 29 |
| 30 exports.setUp = function(callback) |
| 31 { |
| 32 let globals = Object.assign({}, setupTimerAndXMLHttp.call(this), |
| 33 setupRandomResult.call(this)); |
| 34 |
| 35 let sandboxedRequire = createSandbox({globals}); |
| 36 ( |
| 37 {Filter} = sandboxedRequire("../lib/filterClasses"), |
| 38 {FilterStorage} = sandboxedRequire("../lib/filterStorage"), |
| 39 {Prefs} = sandboxedRequire("./stub-modules/prefs"), |
| 40 {Subscription} = sandboxedRequire("../lib/subscriptionClasses"), |
| 41 sandboxedRequire("../lib/synchronizer") |
| 42 ); |
| 43 |
| 44 callback(); |
| 45 }; |
| 46 |
| 47 function resetSubscription(subscription) |
| 48 { |
| 49 FilterStorage.clearSubscriptionFilters(subscription); |
| 50 subscription.lastCheck = subscription.lastDownload = |
| 51 subscription.version = subscription.lastSuccess = |
| 52 subscription.expires = subscription.softExpiration = 0; |
| 53 subscription.title = ""; |
| 54 subscription.homepage = null; |
| 55 subscription.errors = 0; |
| 56 subscription.downloadStatus = null; |
| 57 subscription.requiredVersion = null; |
| 58 } |
| 59 |
| 60 function testFiltersEqual(test, subscription, expected, message) |
| 61 { |
| 62 test.deepEqual( |
| 63 Array.from(subscription.filters, filter => filter.text), |
| 64 expected.map(filter => filter.text)); |
| 65 } |
| 66 |
| 67 function testSubscriptionEqual(test, sub1, sub2, message) |
| 68 { |
| 69 test.equal(sub1.fixedTitle, sub2.fixedTitle, message); |
| 70 test.equal(sub1.homepage, sub2.homepage, message); |
| 71 } |
| 72 |
| 73 let initialDelay = 1 / 60; |
| 74 |
| 75 exports.testOneSubscriptionDownloads = function(test) |
| 76 { |
| 77 let subscription = Subscription.fromURL("http://example.com/subscription"); |
| 78 FilterStorage.addSubscription(subscription); |
| 79 |
| 80 let requests = []; |
| 81 this.registerHandler("/subscription", metadata => |
| 82 { |
| 83 requests.push([this.getTimeOffset(), metadata.method, metadata.path]); |
| 84 return [Cr.NS_OK, 200, "[Adblock]\n! ExPiREs: 1day\nfoo\nbar"]; |
| 85 }); |
| 86 |
| 87 this.runScheduledTasks(50).then(() => |
| 88 { |
| 89 test.deepEqual(requests, [ |
| 90 [0 + initialDelay, "GET", "/subscription"], |
| 91 [24 + initialDelay, "GET", "/subscription"], |
| 92 [48 + initialDelay, "GET", "/subscription"] |
| 93 ], "Requests after 50 hours"); |
| 94 }).catch(unexpectedError.bind(test)).then(() => test.done()); |
| 95 }; |
| 96 |
| 97 exports.testTwoSubscriptionsDownloads = function(test) |
| 98 { |
| 99 let subscription1 = Subscription.fromURL("http://example.com/subscription1"); |
| 100 FilterStorage.addSubscription(subscription1); |
| 101 |
| 102 let subscription2 = Subscription.fromURL("http://example.com/subscription2"); |
| 103 subscription2.expires = |
| 104 subscription2.softExpiration = |
| 105 (this.currentTime + 2 * MILLIS_IN_HOUR) / MILLIS_IN_SECOND; |
| 106 FilterStorage.addSubscription(subscription2); |
| 107 |
| 108 let requests = []; |
| 109 let handler = metadata => |
| 110 { |
| 111 requests.push([this.getTimeOffset(), metadata.method, metadata.path]); |
| 112 return [Cr.NS_OK, 200, "[Adblock]\n! ExPiREs: 1day\nfoo\nbar"]; |
| 113 }; |
| 114 |
| 115 this.registerHandler("/subscription1", handler); |
| 116 this.registerHandler("/subscription2", handler); |
| 117 |
| 118 this.runScheduledTasks(55).then(() => |
| 119 { |
| 120 test.deepEqual(requests, [ |
| 121 [0 + initialDelay, "GET", "/subscription1"], |
| 122 [2 + initialDelay, "GET", "/subscription2"], |
| 123 [24 + initialDelay, "GET", "/subscription1"], |
| 124 [26 + initialDelay, "GET", "/subscription2"], |
| 125 [48 + initialDelay, "GET", "/subscription1"], |
| 126 [50 + initialDelay, "GET", "/subscription2"] |
| 127 ], "Requests after 55 hours"); |
| 128 }).catch(unexpectedError.bind(test)).then(() => test.done()); |
| 129 }; |
| 130 |
| 131 exports.testSubscriptionHeaders = {}; |
| 132 |
| 133 for (let currentTest of [ |
| 134 {header: "[Adblock]", downloadStatus: "synchronize_ok", requiredVersion: ""}, |
| 135 {header: "[Adblock Plus]", downloadStatus: "synchronize_ok", requiredVersion:
""}, |
| 136 {header: "(something)[Adblock]", downloadStatus: "synchronize_ok", requiredVer
sion: ""}, |
| 137 {header: "[Adblock Plus 0.0.1]", downloadStatus: "synchronize_ok", requiredVer
sion: "0.0.1"}, |
| 138 {header: "[Adblock Plus 99.9]", downloadStatus: "synchronize_ok", requiredVers
ion: "99.9"}, |
| 139 {header: "[Foo]", downloadStatus: "synchronize_invalid_data", requiredVersion:
""} |
| 140 ]) |
| 141 { |
| 142 exports.testSubscriptionHeaders[currentTest.header] = function(test) |
| 143 { |
| 144 let subscription = Subscription.fromURL("http://example.com/subscription"); |
| 145 FilterStorage.addSubscription(subscription); |
| 146 |
| 147 this.registerHandler("/subscription", metadata => |
| 148 { |
| 149 return [Cr.NS_OK, 200, currentTest.header + "\n!Expires: 8 hours\nfoo\n!ba
r\n\n@@bas\n#bam"]; |
| 150 }); |
| 151 |
| 152 this.runScheduledTasks(2).then(() => |
| 153 { |
| 154 test.equal(subscription.downloadStatus, currentTest.downloadStatus, "Downl
oad status"); |
| 155 test.equal(subscription.requiredVersion, currentTest.requiredVersion, "Req
uired version"); |
| 156 |
| 157 if (currentTest.downloadStatus == "synchronize_ok") |
| 158 { |
| 159 testFiltersEqual(test, subscription, [ |
| 160 Filter.fromText("foo"), |
| 161 Filter.fromText("!bar"), |
| 162 Filter.fromText("@@bas"), |
| 163 Filter.fromText("#bam") |
| 164 ], "Resulting subscription filters"); |
| 165 } |
| 166 else |
| 167 { |
| 168 testFiltersEqual(test, subscription, [], |
| 169 "Resulting subscription filters"); |
| 170 } |
| 171 }).catch(unexpectedError.bind(test)).then(() => test.done()); |
| 172 }; |
| 173 } |
| 174 |
| 175 exports.testsDisabledUpdates = function(test) |
| 176 { |
| 177 Prefs.subscriptions_autoupdate = false; |
| 178 |
| 179 let subscription = Subscription.fromURL("http://example.com/subscription"); |
| 180 FilterStorage.addSubscription(subscription); |
| 181 |
| 182 let requests = 0; |
| 183 this.registerHandler("/subscription", metadata => |
| 184 { |
| 185 requests++; |
| 186 throw new Error("Unexpected request"); |
| 187 }); |
| 188 |
| 189 this.runScheduledTasks(50).then(() => |
| 190 { |
| 191 test.equal(requests, 0, "Request count"); |
| 192 }).catch(unexpectedError.bind(test)).then(() => test.done()); |
| 193 }; |
| 194 |
| 195 exports.testExpirationTime = {}; |
| 196 |
| 197 for (let currentTest of [ |
| 198 { |
| 199 expiration: "default", |
| 200 randomResult: 0.5, |
| 201 requests: [0 + initialDelay, 5 * 24 + initialDelay] |
| 202 }, |
| 203 { |
| 204 expiration: "1 hours", // Minimal expiration interval |
| 205 randomResult: 0.5, |
| 206 requests: [0 + initialDelay, 1 + initialDelay, 2 + initialDelay, 3 + initial
Delay] |
| 207 }, |
| 208 { |
| 209 expiration: "26 hours", |
| 210 randomResult: 0.5, |
| 211 requests: [0 + initialDelay, 26 + initialDelay] |
| 212 }, |
| 213 { |
| 214 expiration: "2 days", |
| 215 randomResult: 0.5, |
| 216 requests: [0 + initialDelay, 48 + initialDelay] |
| 217 }, |
| 218 { |
| 219 expiration: "20 days", // Too large, will be corrected |
| 220 randomResult: 0.5, |
| 221 requests: [0 + initialDelay, 14 * 24 + initialDelay] |
| 222 }, |
| 223 { |
| 224 expiration: "35 hours", |
| 225 randomResult: 0, // Changes interval by factor 0.8 |
| 226 requests: [0 + initialDelay, 28 + initialDelay] |
| 227 }, |
| 228 { |
| 229 expiration: "35 hours", |
| 230 randomResult: 1, // Changes interval by factor 1.2 |
| 231 requests: [0 + initialDelay, 42 + initialDelay] |
| 232 }, |
| 233 { |
| 234 expiration: "35 hours", |
| 235 randomResult: 0.25, // Changes interval by factor 0.9 |
| 236 requests: [0 + initialDelay, 32 + initialDelay] |
| 237 }, |
| 238 { |
| 239 expiration: "40 hours", |
| 240 randomResult: 0.5, |
| 241 skipAfter: 5 + initialDelay, |
| 242 skip: 10, // Short break should not increase soft expiration |
| 243 requests: [0 + initialDelay, 40 + initialDelay] |
| 244 }, |
| 245 { |
| 246 expiration: "40 hours", |
| 247 randomResult: 0.5, |
| 248 skipAfter: 5 + initialDelay, |
| 249 skip: 30, // Long break should increase soft expiration |
| 250 requests: [0 + initialDelay, 70 + initialDelay] |
| 251 }, |
| 252 { |
| 253 expiration: "40 hours", |
| 254 randomResult: 0.5, |
| 255 skipAfter: 5 + initialDelay, |
| 256 skip: 80, // Hitting hard expiration, immediate download |
| 257 requests: [0 + initialDelay, 85 + initialDelay] |
| 258 } |
| 259 ]) |
| 260 { |
| 261 let testId = `"${currentTest.expiration}"`; |
| 262 if (currentTest.randomResult != 0.5) |
| 263 testId += " with Math.random() returning " + currentTest.randomResult; |
| 264 if (currentTest.skip) |
| 265 testId += " skipping " + currentTest.skip + " hours after " + currentTest.sk
ipAfter + " hours"; |
| 266 exports.testExpirationTime[testId] = function(test) |
| 267 { |
| 268 let subscription = Subscription.fromURL("http://example.com/subscription"); |
| 269 FilterStorage.addSubscription(subscription); |
| 270 |
| 271 let requests = []; |
| 272 this.registerHandler("/subscription", metadata => |
| 273 { |
| 274 requests.push(this.getTimeOffset()); |
| 275 return [Cr.NS_OK, 200, "[Adblock]\nfoo\n!Expires: " + currentTest.expirati
on + "\nbar"]; |
| 276 }); |
| 277 |
| 278 this.randomResult = currentTest.randomResult; |
| 279 |
| 280 let maxHours = Math.round(Math.max.apply(null, currentTest.requests)) + 1; |
| 281 this.runScheduledTasks(maxHours, currentTest.skipAfter, currentTest.skip).th
en(() => |
| 282 { |
| 283 test.deepEqual(requests, currentTest.requests, "Requests"); |
| 284 }).catch(unexpectedError.bind(test)).then(() => test.done()); |
| 285 }; |
| 286 } |
| 287 |
| 288 exports.testSpecialComments = {}; |
| 289 |
| 290 for (let [comment, check] of [ |
| 291 ["! Homepage: http://example.com/", (test, subscription) => |
| 292 { |
| 293 test.equal(subscription.homepage, "http://example.com/", "Valid homepage com
ment"); |
| 294 }], |
| 295 ["! Homepage: ssh://example.com/", (test, subscription) => |
| 296 { |
| 297 test.equal(subscription.homepage, "", "Invalid homepage comment"); |
| 298 }], |
| 299 ["! Title: foo", (test, subscription) => |
| 300 { |
| 301 test.equal(subscription.title, "foo", "Title comment"); |
| 302 test.equal(subscription.fixedTitle, true, "Fixed title"); |
| 303 }], |
| 304 ["! Version: 1234", (test, subscription) => |
| 305 { |
| 306 test.equal(subscription.version, 1234, "Version comment"); |
| 307 }] |
| 308 ]) |
| 309 { |
| 310 exports.testSpecialComments[comment] = function(test) |
| 311 { |
| 312 let subscription = Subscription.fromURL("http://example.com/subscription"); |
| 313 FilterStorage.addSubscription(subscription); |
| 314 |
| 315 this.registerHandler("/subscription", metadata => |
| 316 { |
| 317 return [Cr.NS_OK, 200, "[Adblock]\n" + comment + "\nfoo\nbar"]; |
| 318 }); |
| 319 |
| 320 this.runScheduledTasks(2).then(() => |
| 321 { |
| 322 check(test, subscription); |
| 323 testFiltersEqual(test, subscription, [Filter.fromText("foo"), Filter.fromT
ext("bar")], "Special comment not added to filters"); |
| 324 }).catch(unexpectedError.bind(test)).then(() => test.done()); |
| 325 }; |
| 326 } |
| 327 |
| 328 exports.testRedirects = function(test) |
| 329 { |
| 330 let subscription = Subscription.fromURL("http://example.com/subscription"); |
| 331 FilterStorage.addSubscription(subscription); |
| 332 |
| 333 this.registerHandler("/subscription", metadata => |
| 334 { |
| 335 return [Cr.NS_OK, 200, "[Adblock]\nfoo\n!Redirect: http://example.com/redire
cted\nbar"]; |
| 336 }); |
| 337 |
| 338 let requests; |
| 339 |
| 340 this.runScheduledTasks(30).then(() => |
| 341 { |
| 342 testSubscriptionEqual(test, FilterStorage.subscriptionAt(0), subscription, "
Invalid redirect ignored"); |
| 343 test.equal(subscription.downloadStatus, "synchronize_connection_error", "Con
nection error recorded"); |
| 344 test.equal(subscription.errors, 2, "Number of download errors"); |
| 345 |
| 346 requests = []; |
| 347 |
| 348 this.registerHandler("/redirected", metadata => |
| 349 { |
| 350 requests.push(this.getTimeOffset()); |
| 351 return [Cr.NS_OK, 200, "[Adblock]\nfoo\n! Expires: 8 hours\nbar"]; |
| 352 }); |
| 353 |
| 354 resetSubscription(subscription); |
| 355 return this.runScheduledTasks(15); |
| 356 }).then(() => |
| 357 { |
| 358 test.equal(FilterStorage.subscriptionAt(0).url, "http://example.com/redirect
ed", "Redirect followed"); |
| 359 test.deepEqual(requests, [0 + initialDelay, 8 + initialDelay], "Resulting re
quests"); |
| 360 |
| 361 this.registerHandler("/redirected", metadata => |
| 362 { |
| 363 return [Cr.NS_OK, 200, "[Adblock]\nfoo\n!Redirect: http://example.com/subs
cription\nbar"]; |
| 364 }); |
| 365 |
| 366 subscription = Subscription.fromURL("http://example.com/subscription"); |
| 367 resetSubscription(subscription); |
| 368 FilterStorage.removeSubscription(FilterStorage.subscriptionAt(0)); |
| 369 FilterStorage.addSubscription(subscription); |
| 370 |
| 371 return this.runScheduledTasks(2); |
| 372 }).then(() => |
| 373 { |
| 374 testSubscriptionEqual(test, FilterStorage.subscriptionAt(0), subscription, "
Redirect not followed on redirect loop"); |
| 375 test.equal(subscription.downloadStatus, "synchronize_connection_error", "Dow
nload status after redirect loop"); |
| 376 }).catch(unexpectedError.bind(test)).then(() => test.done()); |
| 377 }; |
| 378 |
| 379 exports.testFallback = function(test) |
| 380 { |
| 381 Prefs.subscriptions_fallbackerrors = 3; |
| 382 Prefs.subscriptions_fallbackurl = "http://example.com/fallback?%SUBSCRIPTION%&
%CHANNELSTATUS%&%RESPONSESTATUS%"; |
| 383 |
| 384 let subscription = Subscription.fromURL("http://example.com/subscription"); |
| 385 FilterStorage.addSubscription(subscription); |
| 386 |
| 387 // No valid response from fallback |
| 388 |
| 389 let requests = []; |
| 390 let fallbackParams; |
| 391 let redirectedRequests; |
| 392 this.registerHandler("/subscription", metadata => |
| 393 { |
| 394 requests.push(this.getTimeOffset()); |
| 395 return [Cr.NS_OK, 404, ""]; |
| 396 }); |
| 397 |
| 398 this.runScheduledTasks(100).then(() => |
| 399 { |
| 400 test.deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialD
elay, 72 + initialDelay, 96 + initialDelay], "Continue trying if the fallback do
esn't respond"); |
| 401 |
| 402 // Fallback giving "Gone" response |
| 403 |
| 404 resetSubscription(subscription); |
| 405 requests = []; |
| 406 fallbackParams = null; |
| 407 this.registerHandler("/fallback", metadata => |
| 408 { |
| 409 fallbackParams = decodeURIComponent(metadata.queryString); |
| 410 return [Cr.NS_OK, 200, "410 Gone"]; |
| 411 }); |
| 412 |
| 413 return this.runScheduledTasks(100); |
| 414 }).then(() => |
| 415 { |
| 416 test.deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialD
elay], "Stop trying if the fallback responds with Gone"); |
| 417 test.equal(fallbackParams, "http://example.com/subscription&0&404", "Fallbac
k arguments"); |
| 418 |
| 419 // Fallback redirecting to a missing file |
| 420 |
| 421 subscription = Subscription.fromURL("http://example.com/subscription"); |
| 422 resetSubscription(subscription); |
| 423 FilterStorage.removeSubscription(FilterStorage.subscriptionAt(0)); |
| 424 FilterStorage.addSubscription(subscription); |
| 425 requests = []; |
| 426 |
| 427 this.registerHandler("/fallback", metadata => |
| 428 { |
| 429 return [Cr.NS_OK, 200, "301 http://example.com/redirected"]; |
| 430 }); |
| 431 return this.runScheduledTasks(100); |
| 432 }).then(() => |
| 433 { |
| 434 test.equal(FilterStorage.subscriptionAt(0).url, "http://example.com/subscrip
tion", "Ignore invalid redirect from fallback"); |
| 435 test.deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialD
elay, 72 + initialDelay, 96 + initialDelay], "Requests not affected by invalid r
edirect"); |
| 436 |
| 437 // Fallback redirecting to an existing file |
| 438 |
| 439 resetSubscription(subscription); |
| 440 requests = []; |
| 441 redirectedRequests = []; |
| 442 this.registerHandler("/redirected", metadata => |
| 443 { |
| 444 redirectedRequests.push(this.getTimeOffset()); |
| 445 return [Cr.NS_OK, 200, "[Adblock]\n!Expires: 1day\nfoo\nbar"]; |
| 446 }); |
| 447 |
| 448 return this.runScheduledTasks(100); |
| 449 }).then(() => |
| 450 { |
| 451 test.equal(FilterStorage.subscriptionAt(0).url, "http://example.com/redirect
ed", "Valid redirect from fallback is followed"); |
| 452 test.deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialD
elay], "Stop polling original URL after a valid redirect from fallback"); |
| 453 test.deepEqual(redirectedRequests, [48 + initialDelay, 72 + initialDelay, 96
+ initialDelay], "Request new URL after a valid redirect from fallback"); |
| 454 |
| 455 // Redirect loop |
| 456 |
| 457 this.registerHandler("/subscription", metadata => |
| 458 { |
| 459 return [Cr.NS_OK, 200, "[Adblock]\n! Redirect: http://example.com/subscrip
tion2"]; |
| 460 }); |
| 461 this.registerHandler("/subscription2", metadata => |
| 462 { |
| 463 return [Cr.NS_OK, 200, "[Adblock]\n! Redirect: http://example.com/subscrip
tion"]; |
| 464 }); |
| 465 |
| 466 subscription = Subscription.fromURL("http://example.com/subscription"); |
| 467 resetSubscription(subscription); |
| 468 FilterStorage.removeSubscription(FilterStorage.subscriptionAt(0)); |
| 469 FilterStorage.addSubscription(subscription); |
| 470 |
| 471 return this.runScheduledTasks(100); |
| 472 }).then(() => |
| 473 { |
| 474 test.equal(FilterStorage.subscriptionAt(0).url, "http://example.com/redirect
ed", "Fallback can still redirect even after a redirect loop"); |
| 475 }).catch(unexpectedError.bind(test)).then(() => test.done()); |
| 476 }; |
| 477 |
| 478 exports.testStateFields = function(test) |
| 479 { |
| 480 let subscription = Subscription.fromURL("http://example.com/subscription"); |
| 481 FilterStorage.addSubscription(subscription); |
| 482 |
| 483 this.registerHandler("/subscription", metadata => |
| 484 { |
| 485 return [Cr.NS_OK, 200, "[Adblock]\n! Expires: 2 hours\nfoo\nbar"]; |
| 486 }); |
| 487 |
| 488 let startTime = this.currentTime; |
| 489 this.runScheduledTasks(2).then(() => |
| 490 { |
| 491 test.equal(subscription.downloadStatus, "synchronize_ok", "downloadStatus af
ter successful download"); |
| 492 test.equal(subscription.lastDownload * MILLIS_IN_SECOND, startTime + initial
Delay * MILLIS_IN_HOUR, "lastDownload after successful download"); |
| 493 test.equal(subscription.lastSuccess * MILLIS_IN_SECOND, startTime + initialD
elay * MILLIS_IN_HOUR, "lastSuccess after successful download"); |
| 494 test.equal(subscription.lastCheck * MILLIS_IN_SECOND, startTime + (1 + initi
alDelay) * MILLIS_IN_HOUR, "lastCheck after successful download"); |
| 495 test.equal(subscription.errors, 0, "errors after successful download"); |
| 496 |
| 497 this.registerHandler("/subscription", metadata => |
| 498 { |
| 499 return [Cr.NS_ERROR_FAILURE, 0, ""]; |
| 500 }); |
| 501 |
| 502 return this.runScheduledTasks(2); |
| 503 }).then(() => |
| 504 { |
| 505 test.equal(subscription.downloadStatus, "synchronize_connection_error", "dow
nloadStatus after connection error"); |
| 506 test.equal(subscription.lastDownload * MILLIS_IN_SECOND, startTime + (2 + in
itialDelay) * MILLIS_IN_HOUR, "lastDownload after connection error"); |
| 507 test.equal(subscription.lastSuccess * MILLIS_IN_SECOND, startTime + initialD
elay * MILLIS_IN_HOUR, "lastSuccess after connection error"); |
| 508 test.equal(subscription.lastCheck * MILLIS_IN_SECOND, startTime + (3 + initi
alDelay) * MILLIS_IN_HOUR, "lastCheck after connection error"); |
| 509 test.equal(subscription.errors, 1, "errors after connection error"); |
| 510 |
| 511 this.registerHandler("/subscription", metadata => |
| 512 { |
| 513 return [Cr.NS_OK, 404, ""]; |
| 514 }); |
| 515 |
| 516 return this.runScheduledTasks(24); |
| 517 }).then(() => |
| 518 { |
| 519 test.equal(subscription.downloadStatus, "synchronize_connection_error", "dow
nloadStatus after download error"); |
| 520 test.equal(subscription.lastDownload * MILLIS_IN_SECOND, startTime + (26 + i
nitialDelay) * MILLIS_IN_HOUR, "lastDownload after download error"); |
| 521 test.equal(subscription.lastSuccess * MILLIS_IN_SECOND, startTime + initialD
elay * MILLIS_IN_HOUR, "lastSuccess after download error"); |
| 522 test.equal(subscription.lastCheck * MILLIS_IN_SECOND, startTime + (27 + init
ialDelay) * MILLIS_IN_HOUR, "lastCheck after download error"); |
| 523 test.equal(subscription.errors, 2, "errors after download error"); |
| 524 }).catch(unexpectedError.bind(test)).then(() => test.done()); |
| 525 }; |
LEFT | RIGHT |