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

Unified Diff: chrome/content/tests/synchronizer.js

Issue 10964120: Made Synchronizer tests work again (Closed)
Patch Set: Updated for Synchronizer changes Created July 17, 2013, 12:33 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/content/tests/subscriptionClasses.js ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/content/tests/synchronizer.js
===================================================================
rename from chrome/content/tests/test_synchronizer.html
rename to chrome/content/tests/synchronizer.js
--- a/chrome/content/tests/test_synchronizer.html
+++ b/chrome/content/tests/synchronizer.js
@@ -1,857 +1,745 @@
-<!DOCTYPE HTML>
-<html>
-<head>
- <title>Subscription synchronizer tests</title>
+(function()
+{
+ let testRunner = null;
+ let server = null;
+ let randomResult = 0.5;
- <link rel="stylesheet" type="text/css" href="/content/tests/SimpleTest/test.css" />
+ const MILLIS_IN_SECOND = 1000;
+ const MILLIS_IN_MINUTE = 60 * MILLIS_IN_SECOND;
+ const MILLIS_IN_HOUR = 60 * MILLIS_IN_MINUTE;
+ const MILLIS_IN_DAY = 24 * MILLIS_IN_HOUR;
- <script type="text/javascript" src="/content/MochiKit/MochiKit.js"></script>
- <script type="application/x-javascript;version=1.7" src="../httpd.js"></script>
- <script type="text/javascript; version=1.7" src="/content/tests/SimpleTest/specialpowersAPI.js"></script>
- <script type="text/javascript; version=1.7" src="/content/tests/SimpleTest/SpecialPowersObserverAPI.js"></script>
- <script type="text/javascript; version=1.7" src="/content/tests/SimpleTest/ChromePowers.js"></script>
- <script type="text/javascript" src="/content/tests/SimpleTest/SimpleTest.js"></script>
+ module("Synchronizer", {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
- <script type="application/x-javascript;version=1.7" src="common.js"></script>
+ setup: function()
+ {
+ testRunner = this;
-</head>
-<body>
- <p id="display"></p>
- <div id="content" style="display: none">
+ prepareFilterComponents.call(this);
+ preparePrefs.call(this);
- </div>
+ let SynchronizerGlobal = Cu.getGlobalForObject(Synchronizer);
+ let SynchronizerModule = getModuleGlobal("synchronizer");
+ let DownloaderGlobal = Cu.getGlobalForObject(SynchronizerModule.downloader);
- <pre id="test">
- <script type="application/x-javascript;version=1.7">
- let {Synchronizer} = require("synchronizer");
- let SynchronizerGlobal = Cu.getGlobalForObject(Synchronizer);
- prepareFilterComponents();
- preparePrefs();
+ server = new nsHttpServer();
+ server.start(1234);
- let currentTime = 20000 * 24 * 60 * 60 * 1000;
- let startTime = 0;
- let scheduledTasks = [];
+ let currentTime = 100000 * MILLIS_IN_HOUR;
+ let startTime = currentTime;
+ let scheduledTasks = [];
- let oldRandom = SynchronizerGlobal.Math.random;
- let oldNow = SynchronizerGlobal.Date.now;
- SynchronizerGlobal.Date.now = function()
- {
- return currentTime;
- };
- Date.now = SynchronizerGlobal.Date.now; // Override for httpd Date header
+ // Replace Date.now() function
+ this._origNow = SynchronizerGlobal.Date.now;
+ SynchronizerGlobal.Date.now = DownloaderGlobal.Date.now = function() currentTime;
- let outstandingRequests = 0;
+ // Replace Math.random() function
+ this._origRandom = DownloaderGlobal.Math.random;
+ DownloaderGlobal.Math.random = function() randomResult;
- function runScheduledTasks(maxHours, noExecution)
- {
- startTime = currentTime;
- let maxTime = maxHours * 60 * 60 * 1000;
- let endTime = currentTime + maxTime;
- while (true)
- {
- let nextTask = null;
- for each (let task in scheduledTasks)
- {
- if (!nextTask || nextTask.nextExecution > task.nextExecution)
- nextTask = task;
- }
- if (!nextTask || nextTask.nextExecution > endTime)
- break;
-
- currentTime = nextTask.nextExecution;
- if (!noExecution)
- nextTask.handler();
-
- // Let all asynchronous actions finish
- let thread = Services.tm.currentThread;
- let loopStartTime = Date.now();
-
- while (outstandingRequests > 0 || thread.hasPendingEvents())
- {
- thread.processNextEvent(true);
-
- if (Date.now() - loopStartTime > 5000)
- {
- ok(false, "Synchronizer stuck downloading subscriptions");
- return;
- }
- }
-
- if (nextTask.type == Components.interfaces.nsITimer.TYPE_ONE_SHOT)
- scheduledTasks = scheduledTasks.filter(function(task) task != nextTask);
- else
- nextTask.nextExecution = currentTime + nextTask.delay;
- }
-
- currentTime = endTime;
- }
-
- Prefs.subscriptions_fallbackerrors = 7;
- Prefs.subscriptions_fallbackurl = "http://127.0.0.1:1234/fallback?%SUBSCRIPTION%&%URL%&%CHANNELSTATUS%&%RESPONSESTATUS%";
-
- {
- let timer = {__proto__: SynchronizerGlobal.timer};
+ // Replace global timer variable
+ let timer = {__proto__: SynchronizerModule.downloader._timer, delay: 0.1 * MILLIS_IN_HOUR};
let callback = timer.callback;
timer.handler = function() { callback.notify(timer); };
timer.nextExecution = currentTime + timer.delay;
+ scheduledTasks.push(timer);
+ SynchronizerModule.downloader._timer.cancel();
+ SynchronizerModule.downloader._timer = timer;
- scheduledTasks.push(timer);
+ // Register observer to track outstanding requests
+ this._outstandingRequests = 0;
+ Services.obs.addObserver(this, "http-on-modify-request", true);
+ Services.obs.addObserver(this, "http-on-examine-response", true);
- SynchronizerGlobal.timer.cancel();
- SynchronizerGlobal.timer = timer;
+ this.runScheduledTasks = function(maxHours, initial, skip)
+ {
+ if (typeof maxHours != "number")
+ throw new Error("Numerical parameter expected");
+ if (typeof initial != "number")
+ initial = 0;
+ if (typeof skip != "number")
+ skip = 0;
+
+ startTime = currentTime;
+ if (initial >= 0)
+ {
+ this._runScheduledTasks(initial);
+ maxHours -= initial;
+ }
+ if (skip)
+ {
+ this._skipTasks(skip);
+ maxHours -= skip;
+ }
+ this._runScheduledTasks(maxHours);
+ }
+
+ this._runScheduledTasks = function(maxHours)
+ {
+ let endTime = currentTime + maxHours * MILLIS_IN_HOUR;
+ while (true)
+ {
+ let nextTask = null;
+ for each (let task in scheduledTasks)
+ {
+ if (!nextTask || nextTask.nextExecution > task.nextExecution)
+ nextTask = task;
+ }
+ if (!nextTask || nextTask.nextExecution > endTime)
+ break;
+
+ currentTime = nextTask.nextExecution;
+ nextTask.handler();
+
+ // Let all asynchronous actions finish
+ let thread = Services.tm.currentThread;
+ let loopStartTime = Date.now();
+
+ while (this._outstandingRequests > 0 || thread.hasPendingEvents())
+ {
+ thread.processNextEvent(true);
+
+ if (Date.now() - loopStartTime > 5000)
+ throw new Error("Synchronizer stuck downloading subscriptions");
+ }
+
+ if (nextTask.type == Components.interfaces.nsITimer.TYPE_ONE_SHOT)
+ scheduledTasks = scheduledTasks.filter(function(task) task != nextTask);
+ else
+ nextTask.nextExecution = currentTime + nextTask.delay;
+ }
+
+ currentTime = endTime;
+ }
+
+ this._skipTasks = function(hours)
+ {
+ let newTasks = [];
+ currentTime += hours * MILLIS_IN_HOUR;
+ for each (let task in scheduledTasks)
+ {
+ if (task.nextExecution >= currentTime)
+ newTasks.push(task);
+ else if (task.type != Components.interfaces.nsITimer.TYPE_ONE_SHOT)
+ {
+ task.nextExecution = currentTime;
+ newTasks.push(task);
+ }
+ }
+ scheduledTasks = newTasks;
+ }
+
+ this.getTimeOffset = function() (currentTime - startTime) / MILLIS_IN_HOUR;
+
+ this.__defineGetter__("currentTime", function() currentTime);
+ },
+
+ observe: function(subject, topic, data)
+ {
+ let orig = this._outstandingRequests;
+ if (topic == "http-on-modify-request")
+ this._outstandingRequests++;
+ else if (topic == "http-on-examine-response")
+ this._outstandingRequests--;
+ },
+
+ teardown: function()
+ {
+ restoreFilterComponents.call(this);
+ restorePrefs.call(this);
+
+ stop();
+ server.stop(function()
+ {
+ server = null;
+ start();
+ });
+
+ if (this._origNow)
+ {
+ let SynchronizerGlobal = Cu.getGlobalForObject(Synchronizer);
+ let SynchronizerModule = getModuleGlobal("synchronizer");
+ let DownloaderGlobal = Cu.getGlobalForObject(SynchronizerModule.downloader);
+ SynchronizerGlobal.Date.now = DownloaderGlobal.Date.now = this._origNow;
+ delete this._origNow;
+ }
+
+ if (this._origRandom)
+ {
+ let SynchronizerModule = getModuleGlobal("synchronizer");
+ let DownloaderGlobal = Cu.getGlobalForObject(SynchronizerModule.downloader);
+ DownloaderGlobal.Math.random = this._origRandom;
+ delete this._origRandom;
+ }
+
+ Synchronizer.init();
+ }
+ });
+
+ function resetSubscription(subscription)
+ {
+ FilterStorage.updateSubscriptionFilters(subscription, []);
+ subscription.lastCheck = subscription.lastDownload =
+ subscription.version = subscription.lastSuccess =
+ subscription.expires = subscription.softExpiration = 0;
+ subscription.title = "";
+ subscription.homepage = null;
+ subscription.errors = 0;
+ subscription.downloadStatus = null;
+ subscription.requiredVersion = null;
+ }
+
+ test("Downloads of one subscription", function()
+ {
+ // Always use average download interval
+ randomResult = 0.5;
+
+ let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription");
+ FilterStorage.addSubscription(subscription);
+
+ let requests = [];
+ function handler(metadata, response)
+ {
+ requests.push([testRunner.getTimeOffset(), metadata.method, metadata.path]);
+
+ response.setStatusLine("1.1", "200", "OK");
+ response.setHeader("Content-Type", "text/plain");
+
+ let result = "[Adblock]\n! ExPiREs: 1day\nfoo\nbar";
+ response.bodyOutputStream.write(result, result.length);
}
- // Track requests initiated by Synchronizer object by hooking its
- // XMLHttpRequest constructor.
- let oldXMLHttp = SynchronizerGlobal.XMLHttpRequest;
- SynchronizerGlobal.XMLHttpRequest = function()
+ server.registerPathHandler("/subscription", handler);
+
+ testRunner.runScheduledTasks(50);
+ deepEqual(requests, [
+ [0.1, "GET", "/subscription"],
+ [24.1, "GET", "/subscription"],
+ [48.1, "GET", "/subscription"],
+ ], "Requests after 50 hours");
+ });
+
+ test("Downloads of two subscriptions", function()
+ {
+ // Always use average download interval
+ randomResult = 0.5;
+
+ let subscription1 = Subscription.fromURL("http://127.0.0.1:1234/subscription1");
+ FilterStorage.addSubscription(subscription1);
+
+ let subscription2 = Subscription.fromURL("http://127.0.0.1:1234/subscription2");
+ subscription2.expires =
+ subscription2.softExpiration =
+ (testRunner.currentTime + 2 * MILLIS_IN_HOUR) / MILLIS_IN_SECOND;
+ FilterStorage.addSubscription(subscription2);
+
+ let requests = [];
+ function handler(metadata, response)
{
- let inner = new oldXMLHttp();
+ requests.push([testRunner.getTimeOffset(), metadata.method, metadata.path]);
- return {
- __proto__: inner,
- send: function()
- {
- outstandingRequests++;
- function finished()
- {
- outstandingRequests--;
- }
- inner.addEventListener("load", finished, false);
- inner.addEventListener("error", finished, false);
+ response.setStatusLine("1.1", "200", "OK");
+ response.setHeader("Content-Type", "text/plain");
- inner.send.apply(inner, arguments);
- }
+ let result = "[Adblock]\n! ExPiREs: 1day\nfoo\nbar";
+ response.bodyOutputStream.write(result, result.length);
+ }
+
+ server.registerPathHandler("/subscription1", handler);
+ server.registerPathHandler("/subscription2", handler);
+
+ testRunner.runScheduledTasks(55);
+ deepEqual(requests, [
+ [0.1, "GET", "/subscription1"],
+ [2.1, "GET", "/subscription2"],
+ [24.1, "GET", "/subscription1"],
+ [26.1, "GET", "/subscription2"],
+ [48.1, "GET", "/subscription1"],
+ [50.1, "GET", "/subscription2"],
+ ], "Requests after 55 hours");
+ });
+
+ test("Download result, various subscription headers", function()
+ {
+ // Always use average download interval
+ randomResult = 0.5;
+
+ let test;
+ let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription");
+ FilterStorage.addSubscription(subscription);
+
+ function handler(metadata, response)
+ {
+ response.setStatusLine("1.1", "200", "OK");
+
+ // Wrong content type shouldn't matter
+ response.setHeader("Content-Type", "text/xml");
+
+ let result = test.header + "\n!Expires: 8 hours\nfoo\n!bar\n\n@@bas\n#bam";
+ response.bodyOutputStream.write(result, result.length);
+ }
+ server.registerPathHandler("/subscription", handler);
+
+ let tests = [
+ {header: "[Adblock]", downloadStatus: "synchronize_ok", requiredVersion: null},
+ {header: "[Adblock Plus]", downloadStatus: "synchronize_ok", requiredVersion: null},
+ {header: "(something)[Adblock]", downloadStatus: "synchronize_ok", requiredVersion: null},
+ {header: "[Adblock Plus 0.0.1]", downloadStatus: "synchronize_ok", requiredVersion: "0.0.1"},
+ {header: "[Adblock Plus 99.9]", downloadStatus: "synchronize_ok", requiredVersion: "99.9"},
+ {header: "[Foo]", downloadStatus: "synchronize_invalid_data", requiredVersion: null}
+ ];
+ for each (test in tests)
+ {
+ resetSubscription(subscription)
+ testRunner.runScheduledTasks(2);
+
+ equal(subscription.downloadStatus, test.downloadStatus, "Download status for " + test.header)
+ equal(subscription.requiredVersion, test.requiredVersion, "Required version for " + test.header)
+
+ if (test.downloadStatus == "synchronize_ok")
+ {
+ deepEqual(subscription.filters, [
+ Filter.fromText("foo"),
+ Filter.fromText("!bar"),
+ Filter.fromText("@@bas"),
+ Filter.fromText("#bam"),
+ ], "Resulting subscription filters for " + test.header);
+ }
+ else
+ {
+ deepEqual(subscription.filters, [
+ ], "Resulting subscription filters for " + test.header);
}
}
+ })
- // Make sure to restore everything when this document unloads
- window.addEventListener("unload", function()
+ test("Automatic updates disabled", function()
+ {
+ Prefs.subscriptions_autoupdate = false;
+
+ let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription");
+ FilterStorage.addSubscription(subscription);
+
+ let requests = 0;
+ function handler(metadata, response)
{
- SynchronizerGlobal.Date.now = oldNow;
- SynchronizerGlobal.XMLHttpRequest = oldXMLHttp;
- SynchronizerGlobal.Math.random = oldRandom;
- Synchronizer.startup();
- }, false);
+ requests++;
+ throw new Error("Unexpected request");
+ }
- let server = new nsHttpServer();
+ server.registerPathHandler("/subscription", handler);
+ testRunner.runScheduledTasks(50);
+ equal(requests, 0, "Request count");
+ });
+
+ test("Expiration time", function()
+ {
+ let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription");
+ FilterStorage.addSubscription(subscription);
+
+ let test;
let requests = [];
+ function handler(metadata, response)
+ {
+ requests.push(testRunner.getTimeOffset());
- let subscription1 = Subscription.fromURL("http://127.0.0.1:1234/subscription1");
- let subscription2 = Subscription.fromURL("http://127.0.0.1:1234/subscription2");
- let subscription3 = Subscription.fromURL("http://127.0.0.1:1234/subscription3");
+ response.setStatusLine("1.1", "200", "OK");
+ response.setHeader("Content-Type", "text/plain");
- let subscriptionStatus = [200, "OK"];
- let subscriptionExtraHeaders = null;
- let subscriptionBody = "[Adblock]\nfoo\nbar";
- function getSubscription(metadata, response)
+ let result = "[Adblock]\nfoo\n!Expires: " + test.expiration + "\nbar";
+ response.bodyOutputStream.write(result, result.length);
+ }
+ server.registerPathHandler("/subscription", handler);
+
+ let tests = [
+ {
+ expiration: "default",
+ randomResult: 0.5,
+ requests: [0.1, 5 * 24 + 0.1]
+ },
+ {
+ expiration: "1 hours", // Minimal expiration interval
+ randomResult: 0.5,
+ requests: [0.1, 1.1, 2.1, 3.1]
+ },
+ {
+ expiration: "26 hours",
+ randomResult: 0.5,
+ requests: [0.1, 26.1]
+ },
+ {
+ expiration: "2 days",
+ randomResult: 0.5,
+ requests: [0.1, 48.1]
+ },
+ {
+ expiration: "20 days", // Too large, will be corrected
+ randomResult: 0.5,
+ requests: [0.1, 14 * 24 + 0.1]
+ },
+ {
+ expiration: "35 hours",
+ randomResult: 0, // Changes interval by factor 0.8
+ requests: [0.1, 28.1]
+ },
+ {
+ expiration: "35 hours",
+ randomResult: 1, // Changes interval by factor 1.2
+ requests: [0.1, 42.1]
+ },
+ {
+ expiration: "35 hours",
+ randomResult: 0.25, // Changes interval by factor 0.9
+ requests: [0.1, 32.1]
+ },
+ {
+ expiration: "40 hours",
+ randomResult: 0.5,
+ skipAfter: 5.1,
+ skip: 10, // Short break should not increase soft expiration
+ requests: [0.1, 40.1]
+ },
+ {
+ expiration: "40 hours",
+ randomResult: 0.5,
+ skipAfter: 5.1,
+ skip: 30, // Long break should increase soft expiration
+ requests: [0.1, 70.1]
+ },
+ {
+ expiration: "40 hours",
+ randomResult: 0.5,
+ skipAfter: 5.1,
+ skip: 80, // Hitting hard expiration, immediate download
+ requests: [0.1, 85.1]
+ }
+ ]
+
+ for each (test in tests)
{
- requests.push((currentTime - startTime) / 3600000 + ": " + metadata.method + " " + metadata.path);
+ requests = [];
+ randomResult = test.randomResult;
+ resetSubscription(subscription);
- response.setStatusLine("1.1", subscriptionStatus[0], subscriptionStatus[1]);
- // Return wrong MIME type, client should be able to handle it
- response.setHeader("Content-Type", "text/xml");
+ let maxHours = Math.round(Math.max.apply(null, test.requests)) + 1;
+ testRunner.runScheduledTasks(maxHours, test.skipAfter, test.skip);
- if (subscriptionExtraHeaders)
- {
- for each (let [header, value] in subscriptionExtraHeaders(metadata))
- response.setHeader(header, value);
- }
+ let randomAddendum = (randomResult == 0.5 ? "" : " with Math.random() returning " + randomResult);
+ let skipAddendum = (typeof test.skip != "number" ? "" : " skipping " + test.skip + " hours after " + test.skipAfter + " hours");
+ deepEqual(requests, test.requests, "Requests for \"" + test.expiration + "\"" + randomAddendum + skipAddendum);
+ }
+ });
+
+ test("Checksum verification", function()
+ {
+ // Always use average download interval
+ randomResult = 0.5;
+
+ let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription");
+ FilterStorage.addSubscription(subscription);
+
+ let testName, subscriptionBody, expectedResult;
+ let tests = [
+ ["Correct checksum", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\nfoo\nbar\n", true],
+ ["Wrong checksum", "[Adblock]\n! Checksum: wrongggny6Fn24b7JHsq/A\nfoo\nbar\n", false],
+ ["Empty lines ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\n\nfoo\n\nbar\n\n", true],
+ ["CR LF line breaks treated like LR", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\nfoo\r\nbar\r\n", true],
+ ["CR line breaks treated like LR", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\nfoo\rbar\r", true],
+ ["Trailing line break not ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\nfoo\nbar", false],
+ ["Line breaks between lines not ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\nfoobar", false],
+ ["Lines with spaces not ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\n \nfoo\n\nbar\n", false],
+ ["Extra content in checksum line is part of the checksum", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A foobar\nfoo\nbar\n", false],
+ ["= symbols after checksum are ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A===\nfoo\nbar\n", true],
+ ["Header line is part of the checksum", "[Adblock Plus]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\nfoo\nbar\n", false],
+ ["Special comments are part of the checksum", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\n! Expires: 1\nfoo\nbar\n", false],
+ ];
+
+ function handler(metadata, response)
+ {
+ response.setStatusLine("1.1", "200", "OK");
+ response.setHeader("Content-Type", "text/plain");
response.bodyOutputStream.write(subscriptionBody, subscriptionBody.length);
}
+ server.registerPathHandler("/subscription", handler);
- let redirectPermanent = null;
- let redirectURL = null;
- let redirectExtraHeaders = null;
- function redirectHandler(metadata, response)
+ for each ([testName, subscriptionBody, expectedResult] in tests)
{
- response.setStatusLine("1.1", redirectPermanent ? 301 : 302, redirectPermanent ? "Moved Permanently" : "Moved Temporarily");
- response.setHeader("Location", redirectURL);
+ resetSubscription(subscription);
+ testRunner.runScheduledTasks(2);
+ equal(subscription.downloadStatus, expectedResult ? "synchronize_ok" : "synchronize_checksum_mismatch", testName);
+ }
+ });
- if (redirectExtraHeaders)
- {
- for each (let [header, value] in redirectExtraHeaders(metadata))
- response.setHeader(header, value);
- }
+ test("Special comments", function()
+ {
+ // Always use average download interval
+ randomResult = 0.5;
+
+ let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription");
+ FilterStorage.addSubscription(subscription);
+
+ let comment, check;
+ let tests = [
+ ["! Homepage: http://example.com/", function() equal(subscription.homepage, "http://example.com/", "Valid homepage comment")],
+ ["! Homepage: ssh://example.com/", function() equal(subscription.homepage, null, "Invalid homepage comment")],
+ ["! Title: foo", function()
+ {
+ equal(subscription.title, "foo", "Title comment");
+ equal(subscription.fixedTitle, true, "Fixed title");
+ }],
+ ["! Version: 1234", function() equal(subscription.version, 1234, "Version comment")]
+ ];
+
+ function handler(metadata, response)
+ {
+ response.setStatusLine("1.1", "200", "OK");
+ response.setHeader("Content-Type", "text/plain");
+
+ let result = "[Adblock]\n" + comment + "\nfoo\nbar";
+ response.bodyOutputStream.write(result, result.length);
}
- function commentRedirectHandler(metadata, response)
+ server.registerPathHandler("/subscription", handler);
+
+ for each([comment, check] in tests)
{
- getSubscription(metadata, response);
+ resetSubscription(subscription);
+ testRunner.runScheduledTasks(2);
+ check();
+ deepEqual(subscription.filters, [Filter.fromText("foo"), Filter.fromText("bar")], "Special comment not added to filters");
+ }
+ });
- if (redirectExtraHeaders)
- {
- for each (let [header, value] in redirectExtraHeaders(metadata))
- response.setHeader(header, value);
- }
+ test("Redirects", function()
+ {
+ // Always use average download interval
+ randomResult = 0.5;
- var comment = "\n! Redirect: " + redirectURL;
- response.bodyOutputStream.write(comment, comment.length);
+ let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription");
+ FilterStorage.addSubscription(subscription);
+
+ function redirect_handler(metadata, response)
+ {
+ response.setStatusLine("1.1", "200", "OK");
+ response.setHeader("Content-Type", "text/plain");
+
+ let result = "[Adblock]\nfoo\n!Redirect: http://127.0.0.1:1234/redirected\nbar";
+ response.bodyOutputStream.write(result, result.length);
}
+ server.registerPathHandler("/subscription", redirect_handler);
- var fallbackResult = "";
- function fallbackHandler(metadata, response)
+ testRunner.runScheduledTasks(30);
+ equal(FilterStorage.subscriptions[0], subscription, "Invalid redirect ignored");
+ equal(subscription.downloadStatus, "synchronize_connection_error", "Connection error recorded");
+ equal(subscription.errors, 2, "Number of download errors");
+
+ let requests = [];
+ function handler(metadata, response)
{
- requests.push((currentTime - startTime) / 3600000 + ": " + metadata.method + " " + metadata.path + " " + decodeURIComponent(metadata.queryString));
+ requests.push(testRunner.getTimeOffset());
- response.setStatusLine("1.1", 200, "OK");
- // Return wrong MIME type, client should be able to handle it
- response.setHeader("Content-Type", "application/x-foo-bar");
+ response.setStatusLine("1.1", "200", "OK");
+ response.setHeader("Content-Type", "text/plain");
- if (subscriptionExtraHeaders)
- {
- for each (let [header, value] in subscriptionExtraHeaders())
- response.setHeader(header, value);
- }
+ let result = "[Adblock]\nfoo\n! Expires: 8 hours\nbar";
+ response.bodyOutputStream.write(result, result.length);
+ }
+ server.registerPathHandler("/redirected", handler);
- response.bodyOutputStream.write(fallbackResult, fallbackResult.length);
+ resetSubscription(subscription);
+ testRunner.runScheduledTasks(15);
+ equal(FilterStorage.subscriptions[0].url, "http://127.0.0.1:1234/redirected", "Redirect followed");
+ deepEqual(requests, [0.1, 8.1], "Resulting requests");
+
+ server.registerPathHandler("/redirected", function(metadata, response)
+ {
+ response.setStatusLine("1.1", "200", "OK");
+ response.setHeader("Content-Type", "text/plain");
+
+ let result = "[Adblock]\nfoo\n!Redirect: http://127.0.0.1:1234/subscription\nbar";
+ response.bodyOutputStream.write(result, result.length);
+ })
+
+ let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription");
+ resetSubscription(subscription);
+ FilterStorage.removeSubscription(FilterStorage.subscriptions[0]);
+ FilterStorage.addSubscription(subscription);
+
+ testRunner.runScheduledTasks(2);
+ equal(FilterStorage.subscriptions[0], subscription, "Redirect not followed on redirect loop");
+ equal(subscription.downloadStatus, "synchronize_connection_error", "Download status after redirect loop");
+ });
+
+ test("Fallback", function()
+ {
+ // Always use average download interval
+ randomResult = 0.5;
+
+ Prefs.subscriptions_fallbackerrors = 3;
+ Prefs.subscriptions_fallbackurl = "http://127.0.0.1:1234/fallback?%SUBSCRIPTION%&%CHANNELSTATUS%&%RESPONSESTATUS%";
+
+ let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription");
+ FilterStorage.addSubscription(subscription);
+
+ // No valid response from fallback
+
+ let requests = [];
+ function handler(metadata, response)
+ {
+ requests.push(testRunner.getTimeOffset());
+
+ response.setStatusLine("1.1", "404", "Not found");
}
+ server.registerPathHandler("/subscription", handler);
- function compareRequests(test, expected)
+ testRunner.runScheduledTasks(100);
+ deepEqual(requests, [0.1, 24.1, 48.1, 72.1, 96.1], "Continue trying if the fallback doesn't respond");
+
+ // Fallback giving "Gone" response
+
+ resetSubscription(subscription);
+ requests = [];
+ fallbackParams = null;
+ server.registerPathHandler("/fallback", function(metadata, response)
{
- is(requests.join("\n"), expected.join("\n"), test);
- requests = [];
+ response.setStatusLine("1.1", "200", "OK");
+ fallbackParams = decodeURIComponent(metadata.queryString);
+
+ let result = "410 Gone";
+ response.bodyOutputStream.write(result, result.length);
+ });
+
+ testRunner.runScheduledTasks(100);
+ deepEqual(requests, [0.1, 24.1, 48.1], "Stop trying if the fallback responds with Gone");
+ equal(fallbackParams, "http://127.0.0.1:1234/subscription&0&404", "Fallback arguments");
+
+ // Fallback redirecting to a missing file
+
+ subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription");
+ resetSubscription(subscription);
+ FilterStorage.removeSubscription(FilterStorage.subscriptions[0]);
+ FilterStorage.addSubscription(subscription);
+ requests = [];
+
+ server.registerPathHandler("/fallback", function(metadata, response)
+ {
+ response.setStatusLine("1.1", "200", "OK");
+
+ let result = "301 http://127.0.0.1:1234/redirected";
+ response.bodyOutputStream.write(result, result.length);
+ });
+ testRunner.runScheduledTasks(100);
+ equal(FilterStorage.subscriptions[0].url, "http://127.0.0.1:1234/subscription", "Ignore invalid redirect from fallback");
+ deepEqual(requests, [0.1, 24.1, 48.1, 72.1, 96.1], "Requests not affected by invalid redirect");
+
+ // Fallback redirecting to an existing file
+
+ resetSubscription(subscription);
+ requests = [];
+ let redirectedRequests = [];
+ server.registerPathHandler("/redirected", function(metadata, response)
+ {
+ redirectedRequests.push(testRunner.getTimeOffset());
+
+ response.setStatusLine("1.1", "200", "OK");
+ response.setHeader("Content-Type", "text/plain");
+
+ let result = "[Adblock]\n!Expires: 1day\nfoo\nbar";
+ response.bodyOutputStream.write(result, result.length);
+ });
+
+ testRunner.runScheduledTasks(100);
+ equal(FilterStorage.subscriptions[0].url, "http://127.0.0.1:1234/redirected", "Valid redirect from fallback is followed");
+ deepEqual(requests, [0.1, 24.1, 48.1], "Stop polling original URL after a valid redirect from fallback");
+ deepEqual(redirectedRequests, [48.1, 72.1, 96.1], "Request new URL after a valid redirect from fallback");
+
+ // Checksum mismatch
+
+ function handler2(metadata, response)
+ {
+ response.setStatusLine("1.1", "200", "OK");
+ response.setHeader("Content-Type", "text/plain");
+
+ let result = "[Adblock]\n! Checksum: wrong\nfoo\nbar";
+ response.bodyOutputStream.write(result, result.length);
}
+ server.registerPathHandler("/subscription", handler2);
- function compareFilters(test, expected, expectedStatus, expectedVersion)
+ subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription");
+ resetSubscription(subscription);
+ FilterStorage.removeSubscription(FilterStorage.subscriptions[0]);
+ FilterStorage.addSubscription(subscription);
+
+ testRunner.runScheduledTasks(100);
+ equal(FilterStorage.subscriptions[0].url, "http://127.0.0.1:1234/redirected", "Wrong checksum produces fallback request");
+
+ // Redirect loop
+
+ server.registerPathHandler("/subscription", function(metadata, response)
{
- let result = subscription1.filters.map(function(filter) filter.text).join("\n");
- is(result, expected, test);
- is(subscription1.downloadStatus, expectedStatus, "Subscription status after previous test");
- is(subscription1.requiredVersion, expectedVersion, "Required version after previous test");
- requests = [];
- }
+ response.setStatusLine("1.1", "200", "OK");
+ response.setHeader("Content-Type", "text/plain");
- function resetSubscriptions()
+ let result = "[Adblock]\n! Redirect: http://127.0.0.1:1234/subscription2";
+ response.bodyOutputStream.write(result, result.length);
+ });
+ server.registerPathHandler("/subscription2", function(metadata, response)
{
- FilterStorage.removeSubscription(subscription1);
- FilterStorage.removeSubscription(subscription2);
- FilterStorage.removeSubscription(subscription3);
- FilterStorage.addSubscription(subscription1);
- FilterStorage.addSubscription(subscription2);
- subscription2.autoDownload = false;
- }
+ response.setStatusLine("1.1", "200", "OK");
+ response.setHeader("Content-Type", "text/plain");
- function compareSubscriptions(test, expectedSubscriptions)
+ let result = "[Adblock]\n! Redirect: http://127.0.0.1:1234/subscription";
+ response.bodyOutputStream.write(result, result.length);
+ });
+
+ subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription");
+ resetSubscription(subscription);
+ FilterStorage.removeSubscription(FilterStorage.subscriptions[0]);
+ FilterStorage.addSubscription(subscription);
+
+ testRunner.runScheduledTasks(100);
+ equal(FilterStorage.subscriptions[0].url, "http://127.0.0.1:1234/redirected", "Fallback can still redirect even after a redirect loop");
+ });
+
+ test("State fields", function()
+ {
+ // Always use average download interval
+ randomResult = 0.5;
+
+ let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription");
+ FilterStorage.addSubscription(subscription);
+
+ server.registerPathHandler("/subscription", function successHandler(metadata, response)
{
- let result = FilterStorage.subscriptions.map(function(subscription) subscription.url).join("\n");
- let expected = expectedSubscriptions.map(function(subscription) subscription.url).join("\n");
- is(result, expected, test);
- requests = [];
- resetSubscriptions();
- }
+ response.setStatusLine("1.1", "200", "OK");
+ response.setHeader("Content-Type", "text/plain");
- function runTests()
+ let result = "[Adblock]\n! Expires: 2 hours\nfoo\nbar";
+ response.bodyOutputStream.write(result, result.length);
+ });
+
+ let startTime = testRunner.currentTime;
+ testRunner.runScheduledTasks(2);
+
+ equal(subscription.downloadStatus, "synchronize_ok", "downloadStatus after successful download");
+ equal(subscription.lastDownload * MILLIS_IN_SECOND, startTime + 0.1 * MILLIS_IN_HOUR, "lastDownload after successful download");
+ equal(subscription.lastSuccess * MILLIS_IN_SECOND, startTime + 0.1 * MILLIS_IN_HOUR, "lastSuccess after successful download");
+ equal(subscription.lastCheck * MILLIS_IN_SECOND, startTime + 1.1 * MILLIS_IN_HOUR, "lastCheck after successful download");
+ equal(subscription.errors, 0, "errors after successful download");
+
+ server.registerPathHandler("/subscription", function errorHandler(metadata, response)
{
- is(typeof Synchronizer, "object", "typeof Synchronizer");
+ response.setStatusLine("1.1", "404", "Not Found");
+ });
- server.registerPathHandler("/subscription1", getSubscription);
- server.registerPathHandler("/subscription2", getSubscription);
- server.registerPathHandler("/subscription3", getSubscription);
- server.registerPathHandler("/fallback", fallbackHandler);
+ testRunner.runScheduledTasks(2);
- FilterStorage.addSubscription(subscription1);
-
- subscription2.autoDownload = false;
- FilterStorage.addSubscription(subscription2);
-
- //
- // General subscription download testing
- //
-
- SynchronizerGlobal.Math.random = function() 0.5;
-
- runScheduledTasks(50);
- compareRequests("Downloads of one subscription (50 hours)", [
- "0.1: GET /subscription1",
- "24.1: GET /subscription1",
- "48.1: GET /subscription1"
- ]);
-
- subscription2.autoDownload = true;
- runScheduledTasks(70);
- compareRequests("Downloads with second subscription switched on (48 hours)", [
- "0.1: GET /subscription2",
- "22.1: GET /subscription1",
- "24.1: GET /subscription2",
- "46.1: GET /subscription1",
- "48.1: GET /subscription2"
- ]);
- subscription2.autoDownload = false;
-
- //
- // Header variations testing
- //
-
- subscriptionBody = "[Adblock]\nfoo\n!bar\n\n\n@@bas\n#bam";
- runScheduledTasks(24);
- compareFilters("Filters of downloaded subscription", "foo\n!bar\n@@bas\n#bam", "synchronize_ok", null);
-
- subscriptionBody = "[Adblock Plus]\nfoo2\n!bar2\n@@bas2\n#bam2";
- runScheduledTasks(24);
- compareFilters("Filters of downloaded subscription with [Adblock Plus] header", "foo2\n!bar2\n@@bas2\n#bam2", "synchronize_ok", null);
-
- subscriptionBody = "[Adblock Plus 0.0.1]\nfoo3\n!bar3\n@@bas3\n#bam3";
- runScheduledTasks(24);
- compareFilters("Filters of downloaded subscription with [Adblock Plus 0.0.1] header", "foo3\n!bar3\n@@bas3\n#bam3", "synchronize_ok", "0.0.1");
-
- subscriptionBody = "(something)[Adblock]\nfoo4\n!bar4\n@@bas4\n#bam4";
- runScheduledTasks(24);
- compareFilters("Filters of downloaded subscription with (something)[Adblock] header", "foo4\n!bar4\n@@bas4\n#bam4", "synchronize_ok", null);
-
- subscriptionBody = "[Foo]\nthis should not be accepted";
- runScheduledTasks(24);
- compareFilters("Filters of downloaded subscription with [Foo] header", "foo4\n!bar4\n@@bas4\n#bam4", "synchronize_invalid_data", null);
-
- subscriptionBody = "[Adblock Plus 99.9]\nsome_new_syntax";
- runScheduledTasks(24);
- compareFilters("Filters of downloaded subscription with [Adblock Plus 99.9] header", "some_new_syntax", "synchronize_ok", "99.9");
-
- //
- // Expiration testing
- //
-
- // Expiration time too small - should be changed into 24 hours
- subscriptionBody = "[Adblock]\n! Expires after 1 hour\nfoo";
- runScheduledTasks(36);
- compareRequests("Expiration comment with less than default update interval (25 hours)", [
- "0.1: GET /subscription1",
- "24.1: GET /subscription1"
- ]);
-
- subscriptionBody = "[Adblock]\n! Expires after 26 hours\nfoo";
- runScheduledTasks(48);
- compareRequests("Downloads with 'Expires after 26 hours' comment (48 hours)", [
- "12.1: GET /subscription1",
- "38.1: GET /subscription1"
- ]);
-
- subscriptionBody = "[Adblock]\n! Expires: 2 days\nfoo";
- runScheduledTasks(70);
- compareRequests("Downloads with 'Expires: 2 days' comment (70 hours)", [
- "16.1: GET /subscription1",
- "64.1: GET /subscription1"
- ]);
-
- subscriptionBody = "[Adblock]\nfoo";
- subscriptionExtraHeaders = function() [["Expires", new Date(currentTime + 30 * 60 * 60 * 1000).toGMTString()]];
- runScheduledTasks(80);
- compareRequests("Downloads with 'Expires: +30h' HTTP header (80 hours)", [
- "42.1: GET /subscription1",
- "72.1: GET /subscription1"
- ]);
-
- // Expiration time too small, should be changed into 24 hours
- subscriptionExtraHeaders = function() [["Expires", new Date(currentTime + 20 * 60 * 60 * 1000).toGMTString()]];
- runScheduledTasks(48);
- compareRequests("Expiration header with less than default update interval (48 hours)", [
- "22.1: GET /subscription1",
- "46.1: GET /subscription1"
- ]);
-
- // Expiration time too large, should be changed into 14 days
- subscriptionExtraHeaders = function() [["Expires", new Date(currentTime + 504 * 60 * 60 * 1000).toGMTString()]];
- runScheduledTasks(692);
- compareRequests("Expiration header more than two weeks in future (692 hours)", [
- "22.1: GET /subscription1",
- "358.1: GET /subscription1"
- ]);
-
- // Soft expiration interval should be randomized - random returning 0 means factor 0.8
- subscriptionExtraHeaders = function() [["Expires", new Date(currentTime + 35 * 60 * 60 * 1000).toGMTString()]];
- SynchronizerGlobal.Math.random = function() 0;
- runScheduledTasks(56);
- compareRequests("Soft expiration should be multiplied with 0.8 if Math.random() returns 0 (48 hours)", [
- "2.1: GET /subscription1",
- "30.1: GET /subscription1"
- ]);
-
- // Soft expiration interval should be randomized - random returning 0.9 means factor 1.16
- subscriptionExtraHeaders = function() [["Expires", new Date(currentTime + 35 * 60 * 60 * 1000).toGMTString()]];
- SynchronizerGlobal.Math.random = function() 0.9;
- runScheduledTasks(82);
- compareRequests("Soft expiration should be multiplied with 1.16 if Math.random() returns 0.9 (82 hours)", [
- "2.1: GET /subscription1",
- "43.1: GET /subscription1"
- ]);
- SynchronizerGlobal.Math.random = function() 0.5;
-
- // Soft expiration interval should increase if the user is off-line more than a day
- subscriptionExtraHeaders = function() [["Expires", new Date(currentTime + 35 * 60 * 60 * 1000).toGMTString()]];
- runScheduledTasks(4);
- requests = [];
- runScheduledTasks(26, true); // Skip the next 26 hours
- runScheduledTasks(104);
- compareRequests("Soft expiration interval should increase if user is offline for more than a day (104 hours)", [
- "34.1: GET /subscription1",
- "69.1: GET /subscription1"
- ]);
-
- // Soft expiration interval should *not* increase if the user was off-line for a short period
- subscriptionExtraHeaders = function() [["Expires", new Date(currentTime + 35 * 60 * 60 * 1000).toGMTString()]];
- runScheduledTasks(2);
- requests = [];
- runScheduledTasks(10, true); // Skip the next 10 hours
- runScheduledTasks(93);
- compareRequests("Soft expiration interval should not increase if user is offline for a few hours (93 hours)", [
- "23.1: GET /subscription1",
- "58.1: GET /subscription1"
- ]);
-
- // Hard expiration interval: if the user was away too long the download should happen immediately
- subscriptionExtraHeaders = function() [["Expires", new Date(currentTime + 35 * 60 * 60 * 1000).toGMTString()]];
- runScheduledTasks(4);
- requests = [];
- runScheduledTasks(80, true); // Skip the next 80 hours, more than twice the expiration time
- runScheduledTasks(70);
- compareRequests("Download should happen immediately if hard expiration interval is hit (70 hours)", [
- "0.1: GET /subscription1",
- "35.1: GET /subscription1"
- ]);
-
- subscriptionExtraHeaders = null;
-
- //
- // Redirect testing
- //
-
- server.registerPathHandler("/subscription1", commentRedirectHandler);
-
- redirectURL = subscription2.url;
- runScheduledTasks(48);
- compareSubscriptions("Subscriptions after comment redirect to /subscription2", [subscription2]);
-
- redirectURL = subscription2.url.replace("subscription2", "invalid_url");
- runScheduledTasks(48);
- compareSubscriptions("Subscriptions after redirect to /invalid_url", [subscription1, subscription2]);
-
- server.registerPathHandler("/subscription1", redirectHandler);
-
- redirectURL = subscription2.url;
- redirectPermanent = false;
- runScheduledTasks(48);
- compareSubscriptions("Subscriptions after temporary redirect to /subscription2", [subscription1, subscription2]);
-
- redirectPermanent = true;
- runScheduledTasks(48);
- compareSubscriptions("Subscriptions after permanent redirect to /subscription2", [subscription2]);
-
- redirectURL = subscription3.url;
- redirectPermanent = false;
- runScheduledTasks(48);
- compareSubscriptions("Subscriptions after temporary redirect to /subscription3", [subscription1, subscription2]);
-
- redirectPermanent = true;
- runScheduledTasks(48);
- compareSubscriptions("Subscriptions after permanent redirect to /subscription3", [subscription2, subscription3]);
-
- redirectURL = subscription2.url.replace("subscription2", "invalid_url");
- redirectPermanent = false;
- runScheduledTasks(48);
- compareSubscriptions("Subscriptions after temporary redirect to /invalid_url", [subscription1, subscription2]);
-
- redirectPermanent = true;
- runScheduledTasks(48);
- compareSubscriptions("Subscriptions after permanent redirect to /invalid_url", [subscription1, subscription2]);
-
- server.registerPathHandler("/subscription3", redirectHandler);
-
- server.registerPathHandler("/subscription1", function redirectHandler(metadata, response)
- {
- response.setStatusLine("1.1", 302, "Moved Temporarily");
- response.setHeader("Location", subscription3.url);
- });
-
- redirectURL = subscription2.url;
- redirectPermanent = false;
- runScheduledTasks(48);
- compareSubscriptions("Subscriptions after temporary redirect to /subscription3 followed by temporary redirect to /subscription2", [subscription1, subscription2]);
-
- redirectPermanent = true;
- runScheduledTasks(48);
- compareSubscriptions("Subscriptions after temporary redirect to /subscription3 followed by permanent redirect to /subscription2", [subscription1, subscription2]);
-
- redirectURL = subscription2.url.replace("subscription2", "invalid_url");;
- redirectPermanent = false;
- runScheduledTasks(48);
- compareSubscriptions("Subscriptions after temporary redirect to /subscription3 followed by temporary redirect to /invalid_url", [subscription1, subscription2]);
-
- redirectPermanent = true;
- runScheduledTasks(48);
- compareSubscriptions("Subscriptions after temporary redirect to /subscription3 followed by permanent redirect to /invalid_url", [subscription1, subscription2]);
-
- server.registerPathHandler("/subscription1", function redirectHandler(metadata, response)
- {
- response.setStatusLine("1.1", 301, "Moved Permanently");
- response.setHeader("Location", subscription3.url);
- });
-
- redirectURL = subscription2.url;
- redirectPermanent = false;
- runScheduledTasks(48);
- compareSubscriptions("Subscriptions after permanent redirect to /subscription3 followed by temporary redirect to /subscription2", [subscription2, subscription3]);
-
- redirectPermanent = true;
- runScheduledTasks(48);
- compareSubscriptions("Subscriptions after permanent redirect to /subscription3 followed by permanent redirect to /subscription2", [subscription2]);
-
- redirectURL = subscription2.url.replace("subscription2", "invalid_url");;
- redirectPermanent = false;
- runScheduledTasks(48);
- compareSubscriptions("Subscriptions after permanent redirect to /subscription3 followed by temporary redirect to /invalid_url", [subscription1, subscription2]);
-
- redirectPermanent = true;
- runScheduledTasks(48);
- compareSubscriptions("Subscriptions after permanent redirect to /subscription3 followed by permanent redirect to /invalid_url", [subscription1, subscription2]);
-
- server.registerPathHandler("/subscription1", getSubscription);
- server.registerPathHandler("/subscription3", getSubscription);
-
- //
- // Behavior on errors
- //
-
- runScheduledTasks(48); // reset error counters
- requests = [];
-
- subscriptionStatus = [404, "Not Found"];
- runScheduledTasks(72);
- compareRequests("Requests after 404 error (72 hours)", [
- "0.1: GET /subscription1",
- "24.1: GET /subscription1",
- "48.1: GET /subscription1"
- ]);
-
- subscriptionStatus = [200, "OK"];
- subscriptionBody = "Not a valid subscription";
- runScheduledTasks(72);
- compareRequests("Requests for invalid subscription (72 hours)", [
- "0.1: GET /subscription1",
- "24.1: GET /subscription1",
- "48.1: GET /subscription1"
- ]);
-
- server.registerPathHandler("/subscription1", function(metadata, response)
- {
- getSubscription(metadata, response);
- response.setStatusLine("1.1", "404", "Not found");
- });
- subscriptionBody = "[Adblock]\nfoo\nbar";
- runScheduledTasks(216);
- compareRequests("Requests with fallback calls (216 hours)", [
- "0.1: GET /subscription1",
- "0.1: GET /fallback " + subscription1.url + "&" + subscription1.url + "&0&404",
- "24.1: GET /subscription1",
- "48.1: GET /subscription1",
- "72.1: GET /subscription1",
- "96.1: GET /subscription1",
- "120.1: GET /subscription1",
- "144.1: GET /subscription1",
- "168.1: GET /subscription1",
- "168.1: GET /fallback " + subscription1.url + "&" + subscription1.url + "&0&404",
- "192.1: GET /subscription1"
- ]);
-
- fallbackResult = "410 Gone";
- runScheduledTasks(216);
- compareRequests("Requests with fallback returning 410 Gone (216 hours)", [
- "0.1: GET /subscription1",
- "24.1: GET /subscription1",
- "48.1: GET /subscription1",
- "72.1: GET /subscription1",
- "96.1: GET /subscription1",
- "120.1: GET /subscription1",
- "120.1: GET /fallback " + subscription1.url + "&" + subscription1.url + "&0&404",
- ]);
- subscription1.autoDownload = true;
-
- fallbackResult = "301 " + subscription2.url;
- runScheduledTasks(216);
- compareRequests("Requests with fallback redirecting to /subscription2 (216 hours)", [
- "0.1: GET /subscription1",
- "24.1: GET /subscription1",
- "48.1: GET /subscription1",
- "72.1: GET /subscription1",
- "96.1: GET /subscription1",
- "120.1: GET /subscription1",
- "144.1: GET /subscription1",
- "144.1: GET /fallback " + subscription1.url + "&" + subscription1.url + "&0&404",
- "168.1: GET /subscription2",
- "192.1: GET /subscription2"
- ]);
- compareSubscriptions("Subscriptions after test above", [subscription2]);
- subscription1.autoDownload = true;
-
- fallbackResult = "301 " + subscription3.url;
- runScheduledTasks(216);
- compareRequests("Requests with fallback redirecting to /subscription3 (216 hours)", [
- "0.1: GET /subscription1",
- "24.1: GET /subscription1",
- "48.1: GET /subscription1",
- "72.1: GET /subscription1",
- "96.1: GET /subscription1",
- "120.1: GET /subscription1",
- "144.1: GET /subscription1",
- "144.1: GET /fallback " + subscription1.url + "&" + subscription1.url + "&0&404",
- "168.1: GET /subscription3",
- "192.1: GET /subscription3"
- ]);
- compareSubscriptions("Subscriptions after test above", [subscription2, subscription3]);
- subscription1.autoDownload = true;
-
- fallbackResult = "301 " + subscription2.url.replace("subscription2", "invalid_url");
- runScheduledTasks(384);
- compareRequests("Requests with fallback redirecting to /invalid_url (384 hours)", [
- "0.1: GET /subscription1",
- "24.1: GET /subscription1",
- "48.1: GET /subscription1",
- "72.1: GET /subscription1",
- "96.1: GET /subscription1",
- "120.1: GET /subscription1",
- "144.1: GET /subscription1",
- "144.1: GET /fallback " + subscription1.url + "&" + subscription1.url + "&0&404",
- "192.1: GET /subscription1",
- "216.1: GET /subscription1",
- "240.1: GET /subscription1",
- "264.1: GET /subscription1",
- "288.1: GET /subscription1",
- "312.1: GET /subscription1",
- "312.1: GET /fallback " + subscription1.url + "&" + subscription1.url + "&0&404",
- "360.1: GET /subscription1"
- ]);
- compareSubscriptions("Subscriptions after test above", [subscription1, subscription2]);
- subscription1.autoDownload = true;
-
- server.registerPathHandler("/subscription1", getSubscription);
- fallbackResult = "";
-
- //
- // Checksum verification
- //
-
- subscriptionBody = "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\nfoo\nbar\n";
-
- runScheduledTasks(48);
- is(subscription1.downloadStatus, "synchronize_ok", "Subscription download with correct checksum succeeded");
-
- subscriptionBody = subscriptionBody.replace(/Checksum: /, "$&wrong");
- runScheduledTasks(48);
- is(subscription1.downloadStatus, "synchronize_checksum_mismatch", "Subscription download with wrong checksum failed");
- subscriptionBody = subscriptionBody.replace(/wrong/, "");
-
- subscriptionBody = subscriptionBody.replace(/\n/g, "\n\n");
- runScheduledTasks(48);
- is(subscription1.downloadStatus, "synchronize_ok", "Empty lines are ignored for checksum validation");
- subscriptionBody = subscriptionBody.replace(/\n\n/g, "\n");
-
- subscriptionBody = subscriptionBody.replace(/\n/g, "\n \n");
- runScheduledTasks(48);
- is(subscription1.downloadStatus, "synchronize_checksum_mismatch", "Lines with spaces are not ignored for checksum validation");
- subscriptionBody = subscriptionBody.replace(/\n \n/g, "\n");
-
- subscriptionBody = subscriptionBody.replace(/(Checksum[^\r\n]*)/, "extra1 $& extra2");
- runScheduledTasks(48);
- is(subscription1.downloadStatus, "synchronize_ok", "Extra content in checksum line is ignored");
- subscriptionBody = subscriptionBody.replace(/extra1 /, "").replace(/ extra2/, "");
-
- subscriptionBody = subscriptionBody.replace(/\n/g, "\r\n");
- runScheduledTasks(48);
- is(subscription1.downloadStatus, "synchronize_ok", "LF symbols are ignored for checksum validation");
- subscriptionBody = subscriptionBody.replace(/\r\n/g, "\n");
-
- subscriptionBody = subscriptionBody.replace(/\n/g, "\r");
- runScheduledTasks(48);
- is(subscription1.downloadStatus, "synchronize_ok", "CR symbols are relevant for checksum validation");
- subscriptionBody = subscriptionBody.replace(/\r/g, "\n");
-
- subscriptionBody = subscriptionBody.replace(/(Checksum[^\r\n]*)/, "$&extra");
- runScheduledTasks(48);
- is(subscription1.downloadStatus, "synchronize_checksum_mismatch", "Extra symbols in the checksum are interpreted as part of the checksum");
- subscriptionBody = subscriptionBody.replace(/extra/, "");
-
- subscriptionBody = subscriptionBody.replace(/(Checksum[^\r\n]*)/, "$&===");
- runScheduledTasks(48);
- is(subscription1.downloadStatus, "synchronize_ok", "= symbols after checksum are ignored");
- subscriptionBody = subscriptionBody.replace(/===/, "");
-
- requests = [];
- subscriptionBody = subscriptionBody.replace(/Checksum: /, "$&wrong");
- runScheduledTasks(216);
- compareRequests("Requests with checksum failures shouldn't trigger fallback URL (27 hours)", [
- "0.1: GET /subscription1",
- "24.1: GET /subscription1",
- "48.1: GET /subscription1",
- "72.1: GET /subscription1",
- "96.1: GET /subscription1",
- "120.1: GET /subscription1",
- "144.1: GET /subscription1",
- "168.1: GET /subscription1",
- "192.1: GET /subscription1",
- ]);
- subscriptionBody = subscriptionBody.replace(/wrong/, "");
-
- //
- // Alternative download locations
- //
-
- subscriptionBody = "[Adblock]\nfoo\nbar\n";
- let alternativeLocations = subscription2.url + ";q=0.5," + subscription3.url + ";q=2";
- subscriptionExtraHeaders = function() [["X-Alternative-Locations", alternativeLocations]];
-
- runScheduledTasks(48);
- is(subscription1.downloadStatus, "synchronize_ok", "= symbols after checksum are ignored");
- is(subscription1.alternativeLocations, alternativeLocations, "Alternative locations header processed on download");
-
- requests = [];
- SynchronizerGlobal.Math.random = function() 0;
- runScheduledTasks(72);
- compareRequests("Base URL should be chosen if Math.random() returns 0", [
- "0.1: GET /subscription1",
- "24.1: GET /subscription1",
- "48.1: GET /subscription1",
- ]);
-
- requests = [];
- SynchronizerGlobal.Math.random = function() 0.28;
- runScheduledTasks(72);
- compareRequests("Base URL should be chosen if Math.random() returns 0.28", [
- "0.1: GET /subscription1",
- "24.1: GET /subscription1",
- "48.1: GET /subscription1",
- ]);
-
- requests = [];
- SynchronizerGlobal.Math.random = function() 0.29;
- runScheduledTasks(72);
- compareRequests("First alternative should be chosen if Math.random() returns 0.29", [
- "0.1: GET /subscription2",
- "24.1: GET /subscription2",
- "48.1: GET /subscription2",
- ]);
-
- requests = [];
- SynchronizerGlobal.Math.random = function() 0.42;
- runScheduledTasks(72);
- compareRequests("First alternative should be chosen if Math.random() returns 0.42", [
- "0.1: GET /subscription2",
- "24.1: GET /subscription2",
- "48.1: GET /subscription2",
- ]);
-
- requests = [];
- SynchronizerGlobal.Math.random = function() 0.43;
- runScheduledTasks(72);
- compareRequests("Second alternative should be chosen if Math.random() returns 0.43", [
- "0.1: GET /subscription3",
- "24.1: GET /subscription3",
- "48.1: GET /subscription3",
- ]);
-
- requests = [];
- SynchronizerGlobal.Math.random = function() 0.99; // Note: side-effect is increasing soft expiration interval to 29 hours
- runScheduledTasks(87);
- compareRequests("Second alternative should be chosen if Math.random() returns 0.99", [
- "0.1: GET /subscription3",
- "29.1: GET /subscription3",
- "58.1: GET /subscription3",
- ]);
-
- subscriptionStatus = [404, "Not Found"];
- SynchronizerGlobal.Math.random = function() 0;
- runScheduledTasks(24);
- is(subscription1.alternativeLocations, alternativeLocations, "Alternative locations shouldn't be reset on download failure for base URL");
-
- SynchronizerGlobal.Math.random = function() 0.99;
- runScheduledTasks(24);
- is(subscription1.alternativeLocations, null, "Alternative locations should be reset on download failure for alternative URL");
-
- requests = [];
- subscriptionStatus = [200, "OK"];
- SynchronizerGlobal.Math.random = function() 0.99; // Note: side-effect is increasing soft expiration interval to 29 hours
- runScheduledTasks(87);
- compareRequests("Alternative locations should be used again once the base URL returns a new list", [
- "0.1: GET /subscription1",
- "29.1: GET /subscription3",
- "58.1: GET /subscription3",
- ]);
-
- server.registerPathHandler("/subscription1", commentRedirectHandler);
- redirectURL = subscription2.url;
- SynchronizerGlobal.Math.random = function() 0;
- runScheduledTasks(24);
- is(subscription1.nextURL, subscription2.url, "Redirect comment accepted from base URL");
- subscription1.nextURL = null;
- server.registerPathHandler("/subscription1", getSubscription);
-
- server.registerPathHandler("/subscription3", commentRedirectHandler);
- redirectURL = subscription2.url;
- SynchronizerGlobal.Math.random = function() 0.99;
- runScheduledTasks(29);
- is(subscription1.nextURL, null, "Redirect comment ignored from alternative URL");
-
- server.registerPathHandler("/subscription3", redirectHandler);
- redirectURL = subscription2.url;
- SynchronizerGlobal.Math.random = function() 0.99;
- redirectPermanent = true;
- runScheduledTasks(29);
- compareSubscriptions("Subscriptions after redirect from alternative URL", [subscription1, subscription2]);
- server.registerPathHandler("/subscription3", getSubscription);
-
- server.registerPathHandler("/subscription1", redirectHandler);
- redirectURL = subscription2.url;
- SynchronizerGlobal.Math.random = function() 0;
- redirectPermanent = true;
- runScheduledTasks(24);
- compareSubscriptions("Subscriptions after redirect from base URL", [subscription2]);
- server.registerPathHandler("/subscription1", getSubscription);
-
- subscriptionExtraHeaders = redirectExtraHeaders =
- function(metadata) [["X-Alternative-Locations", metadata.path == "/subscription1" ? subscription2.url : subscription1.url]];
- server.registerPathHandler("/subscription1", redirectHandler);
- redirectURL = subscription2.url;
- SynchronizerGlobal.Math.random = function() 0;
- redirectPermanent = false;
- runScheduledTasks(24);
- is(subscription1.alternativeLocations, subscription2.url, "Alternative locations not taken over from redirect target on temporary redirect");
- resetSubscriptions();
- server.registerPathHandler("/subscription1", getSubscription);
-
- server.registerPathHandler("/subscription1", redirectHandler);
- redirectURL = subscription2.url;
- SynchronizerGlobal.Math.random = function() 0;
- redirectPermanent = true;
- runScheduledTasks(24);
- is(subscription1.alternativeLocations, subscription1.url, "Alternative locations taken over from redirect target on permanent redirect");
- resetSubscriptions();
- server.registerPathHandler("/subscription1", getSubscription);
-
- subscriptionExtraHeaders = null;
- redirectExtraHeaders = null;
-
- // @TODO: If-Modified-Since
- }
-
- SimpleTest.waitForExplicitFinish();
- addLoadEvent(function()
- {
- try
- {
- server.start(1234);
- runTests();
- }
- catch (e)
- {
- ok(false, e);
- throw e;
- }
- finally
- {
- server.stop();
- SimpleTest.finish();
- }
- });
- </script>
- </pre>
-</body>
-</html>
+ equal(subscription.downloadStatus, "synchronize_connection_error", "downloadStatus after download error");
+ equal(subscription.lastDownload * MILLIS_IN_SECOND, startTime + 2.1 * MILLIS_IN_HOUR, "lastDownload after download error");
+ equal(subscription.lastSuccess * MILLIS_IN_SECOND, startTime + 0.1 * MILLIS_IN_HOUR, "lastSuccess after download error");
+ equal(subscription.lastCheck * MILLIS_IN_SECOND, startTime + 3.1 * MILLIS_IN_HOUR, "lastCheck after download error");
+ equal(subscription.errors, 1, "errors after download error");
+ });
+})();
« no previous file with comments | « chrome/content/tests/subscriptionClasses.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld