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

Side by Side Diff: chrome/content/tests/synchronizer.js

Issue 10964120: Made Synchronizer tests work again (Closed)
Patch Set: Created July 12, 2013, 1:43 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/content/index.html ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 <!DOCTYPE HTML> 1 (function()
2 <html> 2 {
3 <head> 3 let testRunner = null;
4 <title>Subscription synchronizer tests</title> 4 let server = null;
5 5 let randomResult = 0.5;
6 <link rel="stylesheet" type="text/css" href="/content/tests/SimpleTest/test.cs s" /> 6
7 7 const MILLIS_IN_SECOND = 1000;
8 <script type="text/javascript" src="/content/MochiKit/MochiKit.js"></script> 8 const MILLIS_IN_MINUTE = 60 * MILLIS_IN_SECOND;
9 <script type="application/x-javascript;version=1.7" src="../httpd.js"></script > 9 const MILLIS_IN_HOUR = 60 * MILLIS_IN_MINUTE;
10 <script type="text/javascript; version=1.7" src="/content/tests/SimpleTest/spe cialpowersAPI.js"></script> 10 const MILLIS_IN_DAY = 24 * MILLIS_IN_HOUR;
11 <script type="text/javascript; version=1.7" src="/content/tests/SimpleTest/Spe cialPowersObserverAPI.js"></script> 11
12 <script type="text/javascript; version=1.7" src="/content/tests/SimpleTest/Chr omePowers.js"></script> 12 module("Synchronizer", {
13 <script type="text/javascript" src="/content/tests/SimpleTest/SimpleTest.js">< /script> 13 QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakRef erence]),
14 14
15 <script type="application/x-javascript;version=1.7" src="common.js"></script> 15 setup: function()
16 16 {
17 </head> 17 testRunner = this;
18 <body> 18
19 <p id="display"></p> 19 prepareFilterComponents.call(this);
20 <div id="content" style="display: none"> 20 preparePrefs.call(this);
21 21
22 </div> 22 let SynchronizerGlobal = Cu.getGlobalForObject(Synchronizer);
23 23 let SynchronizerModule = getModuleGlobal("synchronizer");
24 <pre id="test"> 24
25 <script type="application/x-javascript;version=1.7"> 25 server = new nsHttpServer();
26 let {Synchronizer} = require("synchronizer"); 26 server.start(1234);
27 let SynchronizerGlobal = Cu.getGlobalForObject(Synchronizer); 27
28 prepareFilterComponents(); 28 let currentTime = 100000 * MILLIS_IN_HOUR;
29 preparePrefs(); 29 let startTime = currentTime;
30 30 let scheduledTasks = [];
31 let currentTime = 20000 * 24 * 60 * 60 * 1000; 31
32 let startTime = 0; 32 // Replace Date.now() function
33 let scheduledTasks = []; 33 this._origNow = SynchronizerGlobal.Date.now;
34 34 SynchronizerGlobal.Date.now = function() currentTime;
35 let oldRandom = SynchronizerGlobal.Math.random; 35
36 let oldNow = SynchronizerGlobal.Date.now; 36 // Replace Math.random() function
37 SynchronizerGlobal.Date.now = function() 37 this._origRandom = SynchronizerGlobal.Math.random;
38 { 38 SynchronizerGlobal.Math.random = function() randomResult;
39 return currentTime; 39
40 }; 40 // Replace global timer variable
41 Date.now = SynchronizerGlobal.Date.now; // Override for httpd Date header 41 let timer = {__proto__: SynchronizerModule.timer, delay: 0.1 * MILLIS_IN_H OUR};
42
43 let outstandingRequests = 0;
44
45 function runScheduledTasks(maxHours, noExecution)
46 {
47 startTime = currentTime;
48 let maxTime = maxHours * 60 * 60 * 1000;
49 let endTime = currentTime + maxTime;
50 while (true)
51 {
52 let nextTask = null;
53 for each (let task in scheduledTasks)
54 {
55 if (!nextTask || nextTask.nextExecution > task.nextExecution)
56 nextTask = task;
57 }
58 if (!nextTask || nextTask.nextExecution > endTime)
59 break;
60
61 currentTime = nextTask.nextExecution;
62 if (!noExecution)
63 nextTask.handler();
64
65 // Let all asynchronous actions finish
66 let thread = Services.tm.currentThread;
67 let loopStartTime = Date.now();
68
69 while (outstandingRequests > 0 || thread.hasPendingEvents())
70 {
71 thread.processNextEvent(true);
72
73 if (Date.now() - loopStartTime > 5000)
74 {
75 ok(false, "Synchronizer stuck downloading subscriptions");
76 return;
77 }
78 }
79
80 if (nextTask.type == Components.interfaces.nsITimer.TYPE_ONE_SHOT)
81 scheduledTasks = scheduledTasks.filter(function(task) task != nextTask );
82 else
83 nextTask.nextExecution = currentTime + nextTask.delay;
84 }
85
86 currentTime = endTime;
87 }
88
89 Prefs.subscriptions_fallbackerrors = 7;
90 Prefs.subscriptions_fallbackurl = "http://127.0.0.1:1234/fallback?%SUBSCRIPT ION%&%URL%&%CHANNELSTATUS%&%RESPONSESTATUS%";
91
92 {
93 let timer = {__proto__: SynchronizerGlobal.timer};
94 let callback = timer.callback; 42 let callback = timer.callback;
95 timer.handler = function() { callback.notify(timer); }; 43 timer.handler = function() { callback.notify(timer); };
96 timer.nextExecution = currentTime + timer.delay; 44 timer.nextExecution = currentTime + timer.delay;
97
98 scheduledTasks.push(timer); 45 scheduledTasks.push(timer);
99 46 SynchronizerModule.timer.cancel();
100 SynchronizerGlobal.timer.cancel(); 47 SynchronizerModule.timer = timer;
101 SynchronizerGlobal.timer = timer; 48
102 } 49 // Register observer to track outstanding requests
103 50 this._outstandingRequests = 0;
104 // Track requests initiated by Synchronizer object by hooking its 51 Services.obs.addObserver(this, "http-on-modify-request", true);
105 // XMLHttpRequest constructor. 52 Services.obs.addObserver(this, "http-on-examine-response", true);
106 let oldXMLHttp = SynchronizerGlobal.XMLHttpRequest; 53
107 SynchronizerGlobal.XMLHttpRequest = function() 54 this.runScheduledTasks = function(maxHours, initial, skip)
108 { 55 {
109 let inner = new oldXMLHttp(); 56 if (typeof maxHours != "number")
110 57 throw new Error("Numerical parameter expected");
111 return { 58 if (typeof initial != "number")
112 __proto__: inner, 59 initial = 0;
113 send: function() 60 if (typeof skip != "number")
61 skip = 0;
62
63 startTime = currentTime;
64 if (initial >= 0)
114 { 65 {
115 outstandingRequests++; 66 this._runScheduledTasks(initial);
116 function finished() 67 maxHours -= initial;
68 }
69 if (skip)
70 {
71 this._skipTasks(skip);
72 maxHours -= initial;
73 }
74 this._runScheduledTasks(maxHours);
75 }
76
77 this._runScheduledTasks = function(maxHours)
78 {
79 let endTime = currentTime + maxHours * MILLIS_IN_HOUR;
80 while (true)
81 {
82 let nextTask = null;
83 for each (let task in scheduledTasks)
117 { 84 {
118 outstandingRequests--; 85 if (!nextTask || nextTask.nextExecution > task.nextExecution)
86 nextTask = task;
119 } 87 }
120 inner.addEventListener("load", finished, false); 88 if (!nextTask || nextTask.nextExecution > endTime)
121 inner.addEventListener("error", finished, false); 89 break;
122 90
123 inner.send.apply(inner, arguments); 91 currentTime = nextTask.nextExecution;
92 nextTask.handler();
93
94 // Let all asynchronous actions finish
95 let thread = Services.tm.currentThread;
96 let loopStartTime = Date.now();
97
98 while (this._outstandingRequests > 0 || thread.hasPendingEvents())
99 {
100 thread.processNextEvent(true);
101
102 if (Date.now() - loopStartTime > 5000)
103 throw new Error("Synchronizer stuck downloading subscriptions");
104 }
105
106 if (nextTask.type == Components.interfaces.nsITimer.TYPE_ONE_SHOT)
107 scheduledTasks = scheduledTasks.filter(function(task) task != nextTa sk);
108 else
109 nextTask.nextExecution = currentTime + nextTask.delay;
124 } 110 }
125 } 111
126 } 112 currentTime = endTime;
127 113 }
128 // Make sure to restore everything when this document unloads 114
129 window.addEventListener("unload", function() 115 this._skipTasks = function(hours)
130 { 116 {
131 SynchronizerGlobal.Date.now = oldNow; 117 let newTasks = [];
132 SynchronizerGlobal.XMLHttpRequest = oldXMLHttp; 118 let endTime = currentTime + hours * MILLIS_IN_HOUR;
133 SynchronizerGlobal.Math.random = oldRandom; 119 for each (let task in scheduledTasks)
134 Synchronizer.startup(); 120 {
135 }, false); 121 if (task.nextExecution >= endTime)
136 122 newTasks.push(task);
137 let server = new nsHttpServer(); 123 else if (task.type != Components.interfaces.nsITimer.TYPE_ONE_SHOT)
124 {
125 task.nextExecution = endTime;
126 newTasks.push(task);
127 }
128 }
129 scheduledTasks = newTasks;
130 }
131
132 this.getTimeOffset = function() (currentTime - startTime) / MILLIS_IN_HOUR ;
133
134 this.__defineGetter__("currentTime", function() currentTime);
135 },
136
137 observe: function(subject, topic, data)
138 {
139 let orig = this._outstandingRequests;
140 if (topic == "http-on-modify-request")
141 this._outstandingRequests++;
142 else if (topic == "http-on-examine-response")
143 this._outstandingRequests--;
144 },
145
146 teardown: function()
147 {
148 restoreFilterComponents.call(this);
149 restorePrefs.call(this);
150
151 stop();
152 server.stop(function()
153 {
154 server = null;
155 start();
156 });
157
158 if (this._origNow)
159 {
160 let SynchronizerGlobal = Cu.getGlobalForObject(Synchronizer);
161 SynchronizerGlobal.Date.now = this._origNow;
162 delete this._origNow;
163 }
164
165 if (this._origRandom)
166 {
167 let SynchronizerGlobal = Cu.getGlobalForObject(Synchronizer);
168 SynchronizerGlobal.Math.random = this._origRandom;
169 delete this._origRandom;
170 }
171
172 Synchronizer.init();
173 }
174 });
175
176 function resetSubscription(subscription)
177 {
178 FilterStorage.updateSubscriptionFilters(subscription, []);
179 subscription.lastCheck = subscription.lastDownload =
180 subscription.lastSuccess = subscription.expires =
181 subscription.softExpiration = 0;
182 subscription.errors = 0;
183 subscription.downloadStatus = null;
184 subscription.requiredVersion = null;
185 subscription.nextURL = null;
186 }
187
188 test("Downloads of one subscription", function()
189 {
190 // Always use average download interval
191 randomResult = 0.5;
192
193 let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription" );
194 FilterStorage.addSubscription(subscription);
138 195
139 let requests = []; 196 let requests = [];
197 function handler(metadata, response)
198 {
199 requests.push([testRunner.getTimeOffset(), metadata.method, metadata.path] );
200
201 response.setStatusLine("1.1", "200", "OK");
202 response.setHeader("Content-Type", "text/plain");
203
204 let result = "[Adblock]\nfoo\nbar";
205 response.bodyOutputStream.write(result, result.length);
206 }
207
208 server.registerPathHandler("/subscription", handler);
209
210 testRunner.runScheduledTasks(50);
211 deepEqual(requests, [
212 [0.1, "GET", "/subscription"],
213 [24.1, "GET", "/subscription"],
214 [48.1, "GET", "/subscription"],
215 ], "Requests after 50 hours");
216 });
217
218 test("Downloads of two subscriptions", function()
219 {
220 // Always use average download interval
221 randomResult = 0.5;
140 222
141 let subscription1 = Subscription.fromURL("http://127.0.0.1:1234/subscription 1"); 223 let subscription1 = Subscription.fromURL("http://127.0.0.1:1234/subscription 1");
224 FilterStorage.addSubscription(subscription1);
225
142 let subscription2 = Subscription.fromURL("http://127.0.0.1:1234/subscription 2"); 226 let subscription2 = Subscription.fromURL("http://127.0.0.1:1234/subscription 2");
143 let subscription3 = Subscription.fromURL("http://127.0.0.1:1234/subscription 3"); 227 subscription2.expires =
144 228 subscription2.softExpiration =
145 let subscriptionStatus = [200, "OK"]; 229 (testRunner.currentTime + 2 * MILLIS_IN_HOUR) / MILLIS_IN_SECOND;
146 let subscriptionExtraHeaders = null; 230 FilterStorage.addSubscription(subscription2);
147 let subscriptionBody = "[Adblock]\nfoo\nbar"; 231
148 function getSubscription(metadata, response) 232 let requests = [];
149 { 233 function handler(metadata, response)
150 requests.push((currentTime - startTime) / 3600000 + ": " + metadata.method + " " + metadata.path); 234 {
151 235 requests.push([testRunner.getTimeOffset(), metadata.method, metadata.path] );
152 response.setStatusLine("1.1", subscriptionStatus[0], subscriptionStatus[1] ); 236
153 // Return wrong MIME type, client should be able to handle it 237 response.setStatusLine("1.1", "200", "OK");
238 response.setHeader("Content-Type", "text/plain");
239
240 let result = "[Adblock]\nfoo\nbar";
241 response.bodyOutputStream.write(result, result.length);
242 }
243
244 server.registerPathHandler("/subscription1", handler);
245 server.registerPathHandler("/subscription2", handler);
246
247 testRunner.runScheduledTasks(55);
248 deepEqual(requests, [
249 [0.1, "GET", "/subscription1"],
250 [2.1, "GET", "/subscription2"],
251 [24.1, "GET", "/subscription1"],
252 [26.1, "GET", "/subscription2"],
253 [48.1, "GET", "/subscription1"],
254 [50.1, "GET", "/subscription2"],
255 ], "Requests after 55 hours");
256 });
257
258 test("Download result, various subscription headers", function()
259 {
260 // Always use average download interval
261 randomResult = 0.5;
262
263 let test;
264 let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription" );
265 FilterStorage.addSubscription(subscription);
266
267 function handler(metadata, response)
268 {
269 response.setStatusLine("1.1", "200", "OK");
270
271 // Wrong content type shouldn't matter
154 response.setHeader("Content-Type", "text/xml"); 272 response.setHeader("Content-Type", "text/xml");
155 273
156 if (subscriptionExtraHeaders) 274 let result = test.header + "\nfoo\n!bar\n\n@@bas\n#bam";
157 { 275 response.bodyOutputStream.write(result, result.length);
158 for each (let [header, value] in subscriptionExtraHeaders(metadata)) 276 }
159 response.setHeader(header, value); 277 server.registerPathHandler("/subscription", handler);
160 } 278
161 279 let tests = [
162 response.bodyOutputStream.write(subscriptionBody, subscriptionBody.length) ; 280 {header: "[Adblock]", downloadStatus: "synchronize_ok", requiredVersion: n ull},
163 } 281 {header: "[Adblock Plus]", downloadStatus: "synchronize_ok", requiredVersi on: null},
164 282 {header: "(something)[Adblock]", downloadStatus: "synchronize_ok", require dVersion: null},
165 let redirectPermanent = null; 283 {header: "[Adblock Plus 0.0.1]", downloadStatus: "synchronize_ok", require dVersion: "0.0.1"},
166 let redirectURL = null; 284 {header: "[Adblock Plus 99.9]", downloadStatus: "synchronize_ok", required Version: "99.9"},
167 let redirectExtraHeaders = null; 285 {header: "[Foo]", downloadStatus: "synchronize_invalid_data", requiredVers ion: null}
168 function redirectHandler(metadata, response) 286 ];
169 { 287 for each (test in tests)
170 response.setStatusLine("1.1", redirectPermanent ? 301 : 302, redirectPerma nent ? "Moved Permanently" : "Moved Temporarily"); 288 {
171 response.setHeader("Location", redirectURL); 289 resetSubscription(subscription)
172 290 testRunner.runScheduledTasks(2);
173 if (redirectExtraHeaders) 291
174 { 292 equal(subscription.downloadStatus, test.downloadStatus, "Download status f or " + test.header)
175 for each (let [header, value] in redirectExtraHeaders(metadata)) 293 equal(subscription.requiredVersion, test.requiredVersion, "Required versio n for " + test.header)
176 response.setHeader(header, value); 294
177 } 295 if (test.downloadStatus == "synchronize_ok")
178 } 296 {
179 function commentRedirectHandler(metadata, response) 297 deepEqual(subscription.filters, [
180 { 298 Filter.fromText("foo"),
181 getSubscription(metadata, response); 299 Filter.fromText("!bar"),
182 300 Filter.fromText("@@bas"),
183 if (redirectExtraHeaders) 301 Filter.fromText("#bam"),
184 { 302 ], "Resulting subscription filters for " + test.header);
185 for each (let [header, value] in redirectExtraHeaders(metadata)) 303 }
186 response.setHeader(header, value); 304 else
187 } 305 {
188 306 deepEqual(subscription.filters, [
189 var comment = "\n! Redirect: " + redirectURL; 307 ], "Resulting subscription filters for " + test.header);
190 response.bodyOutputStream.write(comment, comment.length); 308 }
191 } 309 }
192 310 })
193 var fallbackResult = ""; 311
194 function fallbackHandler(metadata, response) 312 test("Automatic updates disabled", function()
195 { 313 {
196 requests.push((currentTime - startTime) / 3600000 + ": " + metadata.method + " " + metadata.path + " " + decodeURIComponent(metadata.queryString)); 314 Prefs.subscriptions_autoupdate = false;
197 315
198 response.setStatusLine("1.1", 200, "OK"); 316 let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription" );
199 // Return wrong MIME type, client should be able to handle it 317 FilterStorage.addSubscription(subscription);
200 response.setHeader("Content-Type", "application/x-foo-bar"); 318
201 319 let requests = 0;
202 if (subscriptionExtraHeaders) 320 function handler(metadata, response)
203 { 321 {
204 for each (let [header, value] in subscriptionExtraHeaders()) 322 requests++;
205 response.setHeader(header, value); 323 throw new Error("Unexpected request");
206 } 324 }
207 325
208 response.bodyOutputStream.write(fallbackResult, fallbackResult.length); 326 server.registerPathHandler("/subscription", handler);
209 } 327
210 328 testRunner.runScheduledTasks(50);
211 function compareRequests(test, expected) 329 equal(requests, 0, "Request count");
212 { 330 });
213 is(requests.join("\n"), expected.join("\n"), test); 331
332 test("Expiration time", function()
333 {
334 let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription" );
335 FilterStorage.addSubscription(subscription);
336
337 let test;
338 let requests = [];
339 function handler(metadata, response)
340 {
341 requests.push(testRunner.getTimeOffset());
342
343 response.setStatusLine("1.1", "200", "OK");
344 response.setHeader("Content-Type", "text/plain");
345
346 let result = "[Adblock]\nfoo\n!Expires: " + test.expiration + "\nbar";
347 response.bodyOutputStream.write(result, result.length);
348 }
349 server.registerPathHandler("/subscription", handler);
350
351 let tests = [
352 {
353 expiration: "1 hour", // Too small, will be corrected
354 randomResult: 0.5,
355 requests: [0.1, 24.1]
356 },
357 {
358 expiration: "26 hours",
359 randomResult: 0.5,
360 requests: [0.1, 26.1]
361 },
362 {
363 expiration: "2 days",
364 randomResult: 0.5,
365 requests: [0.1, 48.1]
366 },
367 {
368 expiration: "20 days", // Too large, will be corrected
369 randomResult: 0.5,
370 requests: [0.1, 14 * 24 + 0.1]
371 },
372 {
373 expiration: "35 hours",
374 randomResult: 0, // Changes interval by factor 0.8
375 requests: [0.1, 28.1]
376 },
377 {
378 expiration: "35 hours",
379 randomResult: 1, // Changes interval by factor 1.2
380 requests: [0.1, 42.1]
381 },
382 {
383 expiration: "35 hours",
384 randomResult: 0.25, // Changes interval by factor 0.9
385 requests: [0.1, 32.1]
386 },
387 {
388 expiration: "40 hours",
389 randomResult: 0.5,
390 skipAfter: 5.1,
391 skip: 10, // Short break should not increase soft expirati on
392 requests: [0.1, 40.1]
393 },
394 {
395 expiration: "40 hours",
396 randomResult: 0.5,
397 skipAfter: 5.1,
398 skip: 30, // Long break should increase soft expiration
399 requests: [0.1, 70.1]
400 },
401 {
402 expiration: "40 hours",
403 randomResult: 0.5,
404 skipAfter: 5.1,
405 skip: 80, // Hitting hard expiration, immediate download
406 requests: [0.1, 85.1]
407 }
408 ]
409
410 for each (test in tests)
411 {
214 requests = []; 412 requests = [];
215 } 413 randomResult = test.randomResult;
216 414 resetSubscription(subscription);
217 function compareFilters(test, expected, expectedStatus, expectedVersion) 415
218 { 416 let maxHours = Math.round(Math.max.apply(null, test.requests)) + 12;
219 let result = subscription1.filters.map(function(filter) filter.text).join( "\n"); 417 testRunner.runScheduledTasks(maxHours, test.skipAfter, test.skip);
220 is(result, expected, test); 418
221 is(subscription1.downloadStatus, expectedStatus, "Subscription status afte r previous test"); 419 let randomAddendum = (randomResult == 0.5 ? "" : " with Math.random() retu rning " + randomResult);
222 is(subscription1.requiredVersion, expectedVersion, "Required version after previous test"); 420 let skipAddendum = (typeof test.skip != "number" ? "" : " skipping " + tes t.skip + " hours after " + test.skipAfter + " hours");
223 requests = []; 421 deepEqual(requests, test.requests, "Requests for \"" + test.expiration + " \"" + randomAddendum + skipAddendum);
224 } 422
225 423 if (typeof test.skip == "number")
226 function resetSubscriptions() 424 {
227 { 425 // Ensure that next time synchronizer triggers at time offset 0.1 again
228 FilterStorage.removeSubscription(subscription1); 426 testRunner.runScheduledTasks(0.1);
229 FilterStorage.removeSubscription(subscription2); 427 }
230 FilterStorage.removeSubscription(subscription3); 428 }
231 FilterStorage.addSubscription(subscription1); 429 });
232 FilterStorage.addSubscription(subscription2); 430
233 subscription2.autoDownload = false; 431 test("Redirects", function()
234 } 432 {
235 433 let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription" );
236 function compareSubscriptions(test, expectedSubscriptions) 434 FilterStorage.addSubscription(subscription);
237 { 435
238 let result = FilterStorage.subscriptions.map(function(subscription) subscr iption.url).join("\n"); 436 function redirect_handler(metadata, response)
239 let expected = expectedSubscriptions.map(function(subscription) subscripti on.url).join("\n"); 437 {
240 is(result, expected, test); 438 response.setStatusLine("1.1", "200", "OK");
241 requests = []; 439 response.setHeader("Content-Type", "text/plain");
242 resetSubscriptions(); 440
243 } 441 let result = "[Adblock]\nfoo\n!Redirect: http://127.0.0.1:1234/redirected\ nbar";
244 442 response.bodyOutputStream.write(result, result.length);
245 function runTests() 443 }
246 { 444 server.registerPathHandler("/subscription", redirect_handler);
247 is(typeof Synchronizer, "object", "typeof Synchronizer"); 445
248 446 testRunner.runScheduledTasks(50);
249 server.registerPathHandler("/subscription1", getSubscription); 447 equal(FilterStorage.subscriptions[0].url, "http://127.0.0.1:1234/subscriptio n", "Invalid redirect ignored");
250 server.registerPathHandler("/subscription2", getSubscription); 448
251 server.registerPathHandler("/subscription3", getSubscription); 449 let requests = [];
252 server.registerPathHandler("/fallback", fallbackHandler); 450 function handler(metadata, response)
253 451 {
254 FilterStorage.addSubscription(subscription1); 452 requests.push(testRunner.getTimeOffset());
255 453
256 subscription2.autoDownload = false; 454 response.setStatusLine("1.1", "200", "OK");
257 FilterStorage.addSubscription(subscription2); 455 response.setHeader("Content-Type", "text/plain");
258 456
259 // 457 let result = "[Adblock]\nfoo\nbar";
260 // General subscription download testing 458 response.bodyOutputStream.write(result, result.length);
261 // 459 }
262 460 server.registerPathHandler("/redirected", handler);
263 SynchronizerGlobal.Math.random = function() 0.5; 461
264 462 resetSubscription(subscription);
265 runScheduledTasks(50); 463 testRunner.runScheduledTasks(50);
266 compareRequests("Downloads of one subscription (50 hours)", [ 464 equal(FilterStorage.subscriptions[0].url, "http://127.0.0.1:1234/redirected" , "Redirect followed");
267 "0.1: GET /subscription1", 465 deepEqual(requests, [24.1, 48.1], "Resulting requests");
268 "24.1: GET /subscription1", 466 });
269 "48.1: GET /subscription1" 467
270 ]); 468 test("Fallback", function()
271 469 {
272 subscription2.autoDownload = true; 470 Prefs.subscriptions_fallbackerrors = 3;
273 runScheduledTasks(70); 471 Prefs.subscriptions_fallbackurl = "http://127.0.0.1:1234/fallback?%URL%&%CHA NNELSTATUS%&%RESPONSESTATUS%";
274 compareRequests("Downloads with second subscription switched on (48 hours) ", [ 472
275 "0.1: GET /subscription2", 473 let subscription = Subscription.fromURL("http://127.0.0.1:1234/subscription" );
276 "22.1: GET /subscription1", 474 FilterStorage.addSubscription(subscription);
277 "24.1: GET /subscription2", 475
278 "46.1: GET /subscription1", 476 let requests = [];
279 "48.1: GET /subscription2" 477 function handler(metadata, response)
280 ]); 478 {
281 subscription2.autoDownload = false; 479 requests.push(testRunner.getTimeOffset());
282 480
283 // 481 response.setStatusLine("1.1", "404", "Not found");
284 // Header variations testing 482 }
285 // 483 server.registerPathHandler("/subscription", handler);
286 484
287 subscriptionBody = "[Adblock]\nfoo\n!bar\n\n\n@@bas\n#bam"; 485 testRunner.runScheduledTasks(100);
288 runScheduledTasks(24); 486 deepEqual(requests, [0.1, 24.1, 48.1, 72.1, 96.1], "Continue trying if the f allback doesn't respond");
289 compareFilters("Filters of downloaded subscription", "foo\n!bar\n@@bas\n#b am", "synchronize_ok", null); 487
290 488 resetSubscription(subscription);
291 subscriptionBody = "[Adblock Plus]\nfoo2\n!bar2\n@@bas2\n#bam2"; 489 requests = [];
292 runScheduledTasks(24); 490 fallbackParams = null;
293 compareFilters("Filters of downloaded subscription with [Adblock Plus] hea der", "foo2\n!bar2\n@@bas2\n#bam2", "synchronize_ok", null); 491 server.registerPathHandler("/fallback", function(metadata, response)
294 492 {
295 subscriptionBody = "[Adblock Plus 0.0.1]\nfoo3\n!bar3\n@@bas3\n#bam3"; 493 response.setStatusLine("1.1", "200", "OK");
296 runScheduledTasks(24); 494 fallbackParams = decodeURIComponent(metadata.queryString);
297 compareFilters("Filters of downloaded subscription with [Adblock Plus 0.0. 1] header", "foo3\n!bar3\n@@bas3\n#bam3", "synchronize_ok", "0.0.1"); 495
298 496 let result = "410 Gone";
299 subscriptionBody = "(something)[Adblock]\nfoo4\n!bar4\n@@bas4\n#bam4"; 497 response.bodyOutputStream.write(result, result.length);
300 runScheduledTasks(24);
301 compareFilters("Filters of downloaded subscription with (something)[Adbloc k] header", "foo4\n!bar4\n@@bas4\n#bam4", "synchronize_ok", null);
302
303 subscriptionBody = "[Foo]\nthis should not be accepted";
304 runScheduledTasks(24);
305 compareFilters("Filters of downloaded subscription with [Foo] header", "fo o4\n!bar4\n@@bas4\n#bam4", "synchronize_invalid_data", null);
306
307 subscriptionBody = "[Adblock Plus 99.9]\nsome_new_syntax";
308 runScheduledTasks(24);
309 compareFilters("Filters of downloaded subscription with [Adblock Plus 99.9 ] header", "some_new_syntax", "synchronize_ok", "99.9");
310
311 //
312 // Expiration testing
313 //
314
315 // Expiration time too small - should be changed into 24 hours
316 subscriptionBody = "[Adblock]\n! Expires after 1 hour\nfoo";
317 runScheduledTasks(36);
318 compareRequests("Expiration comment with less than default update interval (25 hours)", [
319 "0.1: GET /subscription1",
320 "24.1: GET /subscription1"
321 ]);
322
323 subscriptionBody = "[Adblock]\n! Expires after 26 hours\nfoo";
324 runScheduledTasks(48);
325 compareRequests("Downloads with 'Expires after 26 hours' comment (48 hours )", [
326 "12.1: GET /subscription1",
327 "38.1: GET /subscription1"
328 ]);
329
330 subscriptionBody = "[Adblock]\n! Expires: 2 days\nfoo";
331 runScheduledTasks(70);
332 compareRequests("Downloads with 'Expires: 2 days' comment (70 hours)", [
333 "16.1: GET /subscription1",
334 "64.1: GET /subscription1"
335 ]);
336
337 subscriptionBody = "[Adblock]\nfoo";
338 subscriptionExtraHeaders = function() [["Expires", new Date(currentTime + 30 * 60 * 60 * 1000).toGMTString()]];
339 runScheduledTasks(80);
340 compareRequests("Downloads with 'Expires: +30h' HTTP header (80 hours)", [
341 "42.1: GET /subscription1",
342 "72.1: GET /subscription1"
343 ]);
344
345 // Expiration time too small, should be changed into 24 hours
346 subscriptionExtraHeaders = function() [["Expires", new Date(currentTime + 20 * 60 * 60 * 1000).toGMTString()]];
347 runScheduledTasks(48);
348 compareRequests("Expiration header with less than default update interval (48 hours)", [
349 "22.1: GET /subscription1",
350 "46.1: GET /subscription1"
351 ]);
352
353 // Expiration time too large, should be changed into 14 days
354 subscriptionExtraHeaders = function() [["Expires", new Date(currentTime + 504 * 60 * 60 * 1000).toGMTString()]];
355 runScheduledTasks(692);
356 compareRequests("Expiration header more than two weeks in future (692 hour s)", [
357 "22.1: GET /subscription1",
358 "358.1: GET /subscription1"
359 ]);
360
361 // Soft expiration interval should be randomized - random returning 0 mean s factor 0.8
362 subscriptionExtraHeaders = function() [["Expires", new Date(currentTime + 35 * 60 * 60 * 1000).toGMTString()]];
363 SynchronizerGlobal.Math.random = function() 0;
364 runScheduledTasks(56);
365 compareRequests("Soft expiration should be multiplied with 0.8 if Math.ran dom() returns 0 (48 hours)", [
366 "2.1: GET /subscription1",
367 "30.1: GET /subscription1"
368 ]);
369
370 // Soft expiration interval should be randomized - random returning 0.9 me ans factor 1.16
371 subscriptionExtraHeaders = function() [["Expires", new Date(currentTime + 35 * 60 * 60 * 1000).toGMTString()]];
372 SynchronizerGlobal.Math.random = function() 0.9;
373 runScheduledTasks(82);
374 compareRequests("Soft expiration should be multiplied with 1.16 if Math.ra ndom() returns 0.9 (82 hours)", [
375 "2.1: GET /subscription1",
376 "43.1: GET /subscription1"
377 ]);
378 SynchronizerGlobal.Math.random = function() 0.5;
379
380 // Soft expiration interval should increase if the user is off-line more t han a day
381 subscriptionExtraHeaders = function() [["Expires", new Date(currentTime + 35 * 60 * 60 * 1000).toGMTString()]];
382 runScheduledTasks(4);
383 requests = [];
384 runScheduledTasks(26, true); // Skip the next 26 hours
385 runScheduledTasks(104);
386 compareRequests("Soft expiration interval should increase if user is offli ne for more than a day (104 hours)", [
387 "34.1: GET /subscription1",
388 "69.1: GET /subscription1"
389 ]);
390
391 // Soft expiration interval should *not* increase if the user was off-line for a short period
392 subscriptionExtraHeaders = function() [["Expires", new Date(currentTime + 35 * 60 * 60 * 1000).toGMTString()]];
393 runScheduledTasks(2);
394 requests = [];
395 runScheduledTasks(10, true); // Skip the next 10 hours
396 runScheduledTasks(93);
397 compareRequests("Soft expiration interval should not increase if user is o ffline for a few hours (93 hours)", [
398 "23.1: GET /subscription1",
399 "58.1: GET /subscription1"
400 ]);
401
402 // Hard expiration interval: if the user was away too long the download sh ould happen immediately
403 subscriptionExtraHeaders = function() [["Expires", new Date(currentTime + 35 * 60 * 60 * 1000).toGMTString()]];
404 runScheduledTasks(4);
405 requests = [];
406 runScheduledTasks(80, true); // Skip the next 80 hours, more than twice th e expiration time
407 runScheduledTasks(70);
408 compareRequests("Download should happen immediately if hard expiration int erval is hit (70 hours)", [
409 "0.1: GET /subscription1",
410 "35.1: GET /subscription1"
411 ]);
412
413 subscriptionExtraHeaders = null;
414
415 //
416 // Redirect testing
417 //
418
419 server.registerPathHandler("/subscription1", commentRedirectHandler);
420
421 redirectURL = subscription2.url;
422 runScheduledTasks(48);
423 compareSubscriptions("Subscriptions after comment redirect to /subscriptio n2", [subscription2]);
424
425 redirectURL = subscription2.url.replace("subscription2", "invalid_url");
426 runScheduledTasks(48);
427 compareSubscriptions("Subscriptions after redirect to /invalid_url", [subs cription1, subscription2]);
428
429 server.registerPathHandler("/subscription1", redirectHandler);
430
431 redirectURL = subscription2.url;
432 redirectPermanent = false;
433 runScheduledTasks(48);
434 compareSubscriptions("Subscriptions after temporary redirect to /subscript ion2", [subscription1, subscription2]);
435
436 redirectPermanent = true;
437 runScheduledTasks(48);
438 compareSubscriptions("Subscriptions after permanent redirect to /subscript ion2", [subscription2]);
439
440 redirectURL = subscription3.url;
441 redirectPermanent = false;
442 runScheduledTasks(48);
443 compareSubscriptions("Subscriptions after temporary redirect to /subscript ion3", [subscription1, subscription2]);
444
445 redirectPermanent = true;
446 runScheduledTasks(48);
447 compareSubscriptions("Subscriptions after permanent redirect to /subscript ion3", [subscription2, subscription3]);
448
449 redirectURL = subscription2.url.replace("subscription2", "invalid_url");
450 redirectPermanent = false;
451 runScheduledTasks(48);
452 compareSubscriptions("Subscriptions after temporary redirect to /invalid_u rl", [subscription1, subscription2]);
453
454 redirectPermanent = true;
455 runScheduledTasks(48);
456 compareSubscriptions("Subscriptions after permanent redirect to /invalid_u rl", [subscription1, subscription2]);
457
458 server.registerPathHandler("/subscription3", redirectHandler);
459
460 server.registerPathHandler("/subscription1", function redirectHandler(meta data, response)
461 {
462 response.setStatusLine("1.1", 302, "Moved Temporarily");
463 response.setHeader("Location", subscription3.url);
464 });
465
466 redirectURL = subscription2.url;
467 redirectPermanent = false;
468 runScheduledTasks(48);
469 compareSubscriptions("Subscriptions after temporary redirect to /subscript ion3 followed by temporary redirect to /subscription2", [subscription1, subscrip tion2]);
470
471 redirectPermanent = true;
472 runScheduledTasks(48);
473 compareSubscriptions("Subscriptions after temporary redirect to /subscript ion3 followed by permanent redirect to /subscription2", [subscription1, subscrip tion2]);
474
475 redirectURL = subscription2.url.replace("subscription2", "invalid_url");;
476 redirectPermanent = false;
477 runScheduledTasks(48);
478 compareSubscriptions("Subscriptions after temporary redirect to /subscript ion3 followed by temporary redirect to /invalid_url", [subscription1, subscripti on2]);
479
480 redirectPermanent = true;
481 runScheduledTasks(48);
482 compareSubscriptions("Subscriptions after temporary redirect to /subscript ion3 followed by permanent redirect to /invalid_url", [subscription1, subscripti on2]);
483
484 server.registerPathHandler("/subscription1", function redirectHandler(meta data, response)
485 {
486 response.setStatusLine("1.1", 301, "Moved Permanently");
487 response.setHeader("Location", subscription3.url);
488 });
489
490 redirectURL = subscription2.url;
491 redirectPermanent = false;
492 runScheduledTasks(48);
493 compareSubscriptions("Subscriptions after permanent redirect to /subscript ion3 followed by temporary redirect to /subscription2", [subscription2, subscrip tion3]);
494
495 redirectPermanent = true;
496 runScheduledTasks(48);
497 compareSubscriptions("Subscriptions after permanent redirect to /subscript ion3 followed by permanent redirect to /subscription2", [subscription2]);
498
499 redirectURL = subscription2.url.replace("subscription2", "invalid_url");;
500 redirectPermanent = false;
501 runScheduledTasks(48);
502 compareSubscriptions("Subscriptions after permanent redirect to /subscript ion3 followed by temporary redirect to /invalid_url", [subscription1, subscripti on2]);
503
504 redirectPermanent = true;
505 runScheduledTasks(48);
506 compareSubscriptions("Subscriptions after permanent redirect to /subscript ion3 followed by permanent redirect to /invalid_url", [subscription1, subscripti on2]);
507
508 server.registerPathHandler("/subscription1", getSubscription);
509 server.registerPathHandler("/subscription3", getSubscription);
510
511 //
512 // Behavior on errors
513 //
514
515 runScheduledTasks(48); // reset error counters
516 requests = [];
517
518 subscriptionStatus = [404, "Not Found"];
519 runScheduledTasks(72);
520 compareRequests("Requests after 404 error (72 hours)", [
521 "0.1: GET /subscription1",
522 "24.1: GET /subscription1",
523 "48.1: GET /subscription1"
524 ]);
525
526 subscriptionStatus = [200, "OK"];
527 subscriptionBody = "Not a valid subscription";
528 runScheduledTasks(72);
529 compareRequests("Requests for invalid subscription (72 hours)", [
530 "0.1: GET /subscription1",
531 "24.1: GET /subscription1",
532 "48.1: GET /subscription1"
533 ]);
534
535 server.registerPathHandler("/subscription1", function(metadata, response)
536 {
537 getSubscription(metadata, response);
538 response.setStatusLine("1.1", "404", "Not found");
539 });
540 subscriptionBody = "[Adblock]\nfoo\nbar";
541 runScheduledTasks(216);
542 compareRequests("Requests with fallback calls (216 hours)", [
543 "0.1: GET /subscription1",
544 "0.1: GET /fallback " + subscription1.url + "&" + subscription1.url + "& 0&404",
545 "24.1: GET /subscription1",
546 "48.1: GET /subscription1",
547 "72.1: GET /subscription1",
548 "96.1: GET /subscription1",
549 "120.1: GET /subscription1",
550 "144.1: GET /subscription1",
551 "168.1: GET /subscription1",
552 "168.1: GET /fallback " + subscription1.url + "&" + subscription1.url + "&0&404",
553 "192.1: GET /subscription1"
554 ]);
555
556 fallbackResult = "410 Gone";
557 runScheduledTasks(216);
558 compareRequests("Requests with fallback returning 410 Gone (216 hours)", [
559 "0.1: GET /subscription1",
560 "24.1: GET /subscription1",
561 "48.1: GET /subscription1",
562 "72.1: GET /subscription1",
563 "96.1: GET /subscription1",
564 "120.1: GET /subscription1",
565 "120.1: GET /fallback " + subscription1.url + "&" + subscription1.url + "&0&404",
566 ]);
567 subscription1.autoDownload = true;
568
569 fallbackResult = "301 " + subscription2.url;
570 runScheduledTasks(216);
571 compareRequests("Requests with fallback redirecting to /subscription2 (216 hours)", [
572 "0.1: GET /subscription1",
573 "24.1: GET /subscription1",
574 "48.1: GET /subscription1",
575 "72.1: GET /subscription1",
576 "96.1: GET /subscription1",
577 "120.1: GET /subscription1",
578 "144.1: GET /subscription1",
579 "144.1: GET /fallback " + subscription1.url + "&" + subscription1.url + "&0&404",
580 "168.1: GET /subscription2",
581 "192.1: GET /subscription2"
582 ]);
583 compareSubscriptions("Subscriptions after test above", [subscription2]);
584 subscription1.autoDownload = true;
585
586 fallbackResult = "301 " + subscription3.url;
587 runScheduledTasks(216);
588 compareRequests("Requests with fallback redirecting to /subscription3 (216 hours)", [
589 "0.1: GET /subscription1",
590 "24.1: GET /subscription1",
591 "48.1: GET /subscription1",
592 "72.1: GET /subscription1",
593 "96.1: GET /subscription1",
594 "120.1: GET /subscription1",
595 "144.1: GET /subscription1",
596 "144.1: GET /fallback " + subscription1.url + "&" + subscription1.url + "&0&404",
597 "168.1: GET /subscription3",
598 "192.1: GET /subscription3"
599 ]);
600 compareSubscriptions("Subscriptions after test above", [subscription2, sub scription3]);
601 subscription1.autoDownload = true;
602
603 fallbackResult = "301 " + subscription2.url.replace("subscription2", "inva lid_url");
604 runScheduledTasks(384);
605 compareRequests("Requests with fallback redirecting to /invalid_url (384 h ours)", [
606 "0.1: GET /subscription1",
607 "24.1: GET /subscription1",
608 "48.1: GET /subscription1",
609 "72.1: GET /subscription1",
610 "96.1: GET /subscription1",
611 "120.1: GET /subscription1",
612 "144.1: GET /subscription1",
613 "144.1: GET /fallback " + subscription1.url + "&" + subscription1.url + "&0&404",
614 "192.1: GET /subscription1",
615 "216.1: GET /subscription1",
616 "240.1: GET /subscription1",
617 "264.1: GET /subscription1",
618 "288.1: GET /subscription1",
619 "312.1: GET /subscription1",
620 "312.1: GET /fallback " + subscription1.url + "&" + subscription1.url + "&0&404",
621 "360.1: GET /subscription1"
622 ]);
623 compareSubscriptions("Subscriptions after test above", [subscription1, sub scription2]);
624 subscription1.autoDownload = true;
625
626 server.registerPathHandler("/subscription1", getSubscription);
627 fallbackResult = "";
628
629 //
630 // Checksum verification
631 //
632
633 subscriptionBody = "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\nfoo\nba r\n";
634
635 runScheduledTasks(48);
636 is(subscription1.downloadStatus, "synchronize_ok", "Subscription download with correct checksum succeeded");
637
638 subscriptionBody = subscriptionBody.replace(/Checksum: /, "$&wrong");
639 runScheduledTasks(48);
640 is(subscription1.downloadStatus, "synchronize_checksum_mismatch", "Subscri ption download with wrong checksum failed");
641 subscriptionBody = subscriptionBody.replace(/wrong/, "");
642
643 subscriptionBody = subscriptionBody.replace(/\n/g, "\n\n");
644 runScheduledTasks(48);
645 is(subscription1.downloadStatus, "synchronize_ok", "Empty lines are ignore d for checksum validation");
646 subscriptionBody = subscriptionBody.replace(/\n\n/g, "\n");
647
648 subscriptionBody = subscriptionBody.replace(/\n/g, "\n \n");
649 runScheduledTasks(48);
650 is(subscription1.downloadStatus, "synchronize_checksum_mismatch", "Lines w ith spaces are not ignored for checksum validation");
651 subscriptionBody = subscriptionBody.replace(/\n \n/g, "\n");
652
653 subscriptionBody = subscriptionBody.replace(/(Checksum[^\r\n]*)/, "extra1 $& extra2");
654 runScheduledTasks(48);
655 is(subscription1.downloadStatus, "synchronize_ok", "Extra content in check sum line is ignored");
656 subscriptionBody = subscriptionBody.replace(/extra1 /, "").replace(/ extra 2/, "");
657
658 subscriptionBody = subscriptionBody.replace(/\n/g, "\r\n");
659 runScheduledTasks(48);
660 is(subscription1.downloadStatus, "synchronize_ok", "LF symbols are ignored for checksum validation");
661 subscriptionBody = subscriptionBody.replace(/\r\n/g, "\n");
662
663 subscriptionBody = subscriptionBody.replace(/\n/g, "\r");
664 runScheduledTasks(48);
665 is(subscription1.downloadStatus, "synchronize_ok", "CR symbols are relevan t for checksum validation");
666 subscriptionBody = subscriptionBody.replace(/\r/g, "\n");
667
668 subscriptionBody = subscriptionBody.replace(/(Checksum[^\r\n]*)/, "$&extra ");
669 runScheduledTasks(48);
670 is(subscription1.downloadStatus, "synchronize_checksum_mismatch", "Extra s ymbols in the checksum are interpreted as part of the checksum");
671 subscriptionBody = subscriptionBody.replace(/extra/, "");
672
673 subscriptionBody = subscriptionBody.replace(/(Checksum[^\r\n]*)/, "$&===") ;
674 runScheduledTasks(48);
675 is(subscription1.downloadStatus, "synchronize_ok", "= symbols after checks um are ignored");
676 subscriptionBody = subscriptionBody.replace(/===/, "");
677
678 requests = [];
679 subscriptionBody = subscriptionBody.replace(/Checksum: /, "$&wrong");
680 runScheduledTasks(216);
681 compareRequests("Requests with checksum failures shouldn't trigger fallbac k URL (27 hours)", [
682 "0.1: GET /subscription1",
683 "24.1: GET /subscription1",
684 "48.1: GET /subscription1",
685 "72.1: GET /subscription1",
686 "96.1: GET /subscription1",
687 "120.1: GET /subscription1",
688 "144.1: GET /subscription1",
689 "168.1: GET /subscription1",
690 "192.1: GET /subscription1",
691 ]);
692 subscriptionBody = subscriptionBody.replace(/wrong/, "");
693
694 //
695 // Alternative download locations
696 //
697
698 subscriptionBody = "[Adblock]\nfoo\nbar\n";
699 let alternativeLocations = subscription2.url + ";q=0.5," + subscription3.u rl + ";q=2";
700 subscriptionExtraHeaders = function() [["X-Alternative-Locations", alterna tiveLocations]];
701
702 runScheduledTasks(48);
703 is(subscription1.downloadStatus, "synchronize_ok", "= symbols after checks um are ignored");
704 is(subscription1.alternativeLocations, alternativeLocations, "Alternative locations header processed on download");
705
706 requests = [];
707 SynchronizerGlobal.Math.random = function() 0;
708 runScheduledTasks(72);
709 compareRequests("Base URL should be chosen if Math.random() returns 0", [
710 "0.1: GET /subscription1",
711 "24.1: GET /subscription1",
712 "48.1: GET /subscription1",
713 ]);
714
715 requests = [];
716 SynchronizerGlobal.Math.random = function() 0.28;
717 runScheduledTasks(72);
718 compareRequests("Base URL should be chosen if Math.random() returns 0.28", [
719 "0.1: GET /subscription1",
720 "24.1: GET /subscription1",
721 "48.1: GET /subscription1",
722 ]);
723
724 requests = [];
725 SynchronizerGlobal.Math.random = function() 0.29;
726 runScheduledTasks(72);
727 compareRequests("First alternative should be chosen if Math.random() retur ns 0.29", [
728 "0.1: GET /subscription2",
729 "24.1: GET /subscription2",
730 "48.1: GET /subscription2",
731 ]);
732
733 requests = [];
734 SynchronizerGlobal.Math.random = function() 0.42;
735 runScheduledTasks(72);
736 compareRequests("First alternative should be chosen if Math.random() retur ns 0.42", [
737 "0.1: GET /subscription2",
738 "24.1: GET /subscription2",
739 "48.1: GET /subscription2",
740 ]);
741
742 requests = [];
743 SynchronizerGlobal.Math.random = function() 0.43;
744 runScheduledTasks(72);
745 compareRequests("Second alternative should be chosen if Math.random() retu rns 0.43", [
746 "0.1: GET /subscription3",
747 "24.1: GET /subscription3",
748 "48.1: GET /subscription3",
749 ]);
750
751 requests = [];
752 SynchronizerGlobal.Math.random = function() 0.99; // Note: side-effect is increasing soft expiration interval to 29 hours
753 runScheduledTasks(87);
754 compareRequests("Second alternative should be chosen if Math.random() retu rns 0.99", [
755 "0.1: GET /subscription3",
756 "29.1: GET /subscription3",
757 "58.1: GET /subscription3",
758 ]);
759
760 subscriptionStatus = [404, "Not Found"];
761 SynchronizerGlobal.Math.random = function() 0;
762 runScheduledTasks(24);
763 is(subscription1.alternativeLocations, alternativeLocations, "Alternative locations shouldn't be reset on download failure for base URL");
764
765 SynchronizerGlobal.Math.random = function() 0.99;
766 runScheduledTasks(24);
767 is(subscription1.alternativeLocations, null, "Alternative locations should be reset on download failure for alternative URL");
768
769 requests = [];
770 subscriptionStatus = [200, "OK"];
771 SynchronizerGlobal.Math.random = function() 0.99; // Note: side-effect is increasing soft expiration interval to 29 hours
772 runScheduledTasks(87);
773 compareRequests("Alternative locations should be used again once the base URL returns a new list", [
774 "0.1: GET /subscription1",
775 "29.1: GET /subscription3",
776 "58.1: GET /subscription3",
777 ]);
778
779 server.registerPathHandler("/subscription1", commentRedirectHandler);
780 redirectURL = subscription2.url;
781 SynchronizerGlobal.Math.random = function() 0;
782 runScheduledTasks(24);
783 is(subscription1.nextURL, subscription2.url, "Redirect comment accepted fr om base URL");
784 subscription1.nextURL = null;
785 server.registerPathHandler("/subscription1", getSubscription);
786
787 server.registerPathHandler("/subscription3", commentRedirectHandler);
788 redirectURL = subscription2.url;
789 SynchronizerGlobal.Math.random = function() 0.99;
790 runScheduledTasks(29);
791 is(subscription1.nextURL, null, "Redirect comment ignored from alternative URL");
792
793 server.registerPathHandler("/subscription3", redirectHandler);
794 redirectURL = subscription2.url;
795 SynchronizerGlobal.Math.random = function() 0.99;
796 redirectPermanent = true;
797 runScheduledTasks(29);
798 compareSubscriptions("Subscriptions after redirect from alternative URL", [subscription1, subscription2]);
799 server.registerPathHandler("/subscription3", getSubscription);
800
801 server.registerPathHandler("/subscription1", redirectHandler);
802 redirectURL = subscription2.url;
803 SynchronizerGlobal.Math.random = function() 0;
804 redirectPermanent = true;
805 runScheduledTasks(24);
806 compareSubscriptions("Subscriptions after redirect from base URL", [subscr iption2]);
807 server.registerPathHandler("/subscription1", getSubscription);
808
809 subscriptionExtraHeaders = redirectExtraHeaders =
810 function(metadata) [["X-Alternative-Locations", metadata.path == "/subsc ription1" ? subscription2.url : subscription1.url]];
811 server.registerPathHandler("/subscription1", redirectHandler);
812 redirectURL = subscription2.url;
813 SynchronizerGlobal.Math.random = function() 0;
814 redirectPermanent = false;
815 runScheduledTasks(24);
816 is(subscription1.alternativeLocations, subscription2.url, "Alternative loc ations not taken over from redirect target on temporary redirect");
817 resetSubscriptions();
818 server.registerPathHandler("/subscription1", getSubscription);
819
820 server.registerPathHandler("/subscription1", redirectHandler);
821 redirectURL = subscription2.url;
822 SynchronizerGlobal.Math.random = function() 0;
823 redirectPermanent = true;
824 runScheduledTasks(24);
825 is(subscription1.alternativeLocations, subscription1.url, "Alternative loc ations taken over from redirect target on permanent redirect");
826 resetSubscriptions();
827 server.registerPathHandler("/subscription1", getSubscription);
828
829 subscriptionExtraHeaders = null;
830 redirectExtraHeaders = null;
831
832 // @TODO: If-Modified-Since
833 }
834
835 SimpleTest.waitForExplicitFinish();
836 addLoadEvent(function()
837 {
838 try
839 {
840 server.start(1234);
841 runTests();
842 }
843 catch (e)
844 {
845 ok(false, e);
846 throw e;
847 }
848 finally
849 {
850 server.stop();
851 SimpleTest.finish();
852 }
853 }); 498 });
854 </script> 499
855 </pre> 500 testRunner.runScheduledTasks(100);
856 </body> 501 deepEqual(requests, [0.1, 24.1, 48.1], "Stop trying if the fallback responds with Gone");
857 </html> 502 equal(fallbackParams, "http://127.0.0.1:1234/subscription&0&404");
503
504 resetSubscription(subscription);
505 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]);
506 FilterStorage.addSubscription(subscription);
507 requests = [];
508
509 server.registerPathHandler("/fallback", function(metadata, response)
510 {
511 response.setStatusLine("1.1", "200", "OK");
512
513 let result = "301 http://127.0.0.1:1234/redirected";
514 response.bodyOutputStream.write(result, result.length);
515 });
516 testRunner.runScheduledTasks(100);
517 equal(FilterStorage.subscriptions[0].url, "http://127.0.0.1:1234/subscriptio n");
518 deepEqual(requests, [0.1, 24.1, 48.1, 96.1], "Come back after invalid redire ct from fallback");
519
520 resetSubscription(subscription);
521 requests = [];
522 let redirectedRequests = [];
523 server.registerPathHandler("/redirected", function(metadata, response)
524 {
525 redirectedRequests.push(testRunner.getTimeOffset());
526
527 response.setStatusLine("1.1", "200", "OK");
528 response.setHeader("Content-Type", "text/plain");
529
530 let result = "[Adblock]\nfoo\nbar";
531 response.bodyOutputStream.write(result, result.length);
532 });
533
534 testRunner.runScheduledTasks(100);
535 equal(FilterStorage.subscriptions[0].url, "http://127.0.0.1:1234/redirected" );
536 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");
538 });
539
540 // TODO: Checksum verification
541 })();
OLDNEW
« no previous file with comments | « chrome/content/index.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld