1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/mozapps/update/tests/unit_timermanager/consumerNotifications.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,447 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. 1.7 + */ 1.8 + 1.9 +/* General Update Timer Manager Tests */ 1.10 + 1.11 +const Cc = Components.classes; 1.12 +const Ci = Components.interfaces; 1.13 +const Cm = Components.manager; 1.14 +const Cr = Components.results; 1.15 + 1.16 +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); 1.17 + 1.18 +const CATEGORY_UPDATE_TIMER = "update-timer"; 1.19 + 1.20 +const PREF_APP_UPDATE_TIMERMINIMUMDELAY = "app.update.timerMinimumDelay"; 1.21 +const PREF_APP_UPDATE_TIMERFIRSTINTERVAL = "app.update.timerFirstInterval"; 1.22 +const PREF_APP_UPDATE_LOG_ALL = "app.update.log.all"; 1.23 +const PREF_BRANCH_LAST_UPDATE_TIME = "app.update.lastUpdateTime."; 1.24 + 1.25 +const MAIN_TIMER_INTERVAL = 1000; // milliseconds 1.26 +const CONSUMER_TIMER_INTERVAL = 1; // seconds 1.27 + 1.28 +const TESTS = [ { 1.29 + desc : "Test Timer Callback 1", 1.30 + timerID : "test1-update-timer", 1.31 + defaultInterval : "bogus", 1.32 + prefInterval : "test1.timer.interval", 1.33 + contractID : "@mozilla.org/test1/timercallback;1", 1.34 + method : "createInstance", 1.35 + classID : Components.ID("9c7ce81f-98bb-4729-adb4-4d0deb0f59e5"), 1.36 + notified : false 1.37 +}, { 1.38 + desc : "Test Timer Callback 2", 1.39 + timerID : "test2-update-timer", 1.40 + defaultInterval : 86400, 1.41 + prefInterval : "test2.timer.interval", 1.42 + contractID : "@mozilla.org/test2/timercallback;1", 1.43 + method : "createInstance", 1.44 + classID : Components.ID("512834f3-05bb-46be-84e0-81d881a140b7"), 1.45 + notified : false 1.46 +}, { 1.47 + desc : "Test Timer Callback 3", 1.48 + timerID : "test3-update-timer", 1.49 + defaultInterval : CONSUMER_TIMER_INTERVAL, 1.50 + prefInterval : "test3.timer.interval", 1.51 + contractID : "@mozilla.org/test3/timercallback;1", 1.52 + method : "createInstance", 1.53 + classID : Components.ID("c8ac5027-8d11-4471-9d7c-fd692501b437"), 1.54 + notified : false 1.55 +}, { 1.56 + desc : "Test Timer Callback 4", 1.57 + timerID : "test4-update-timer", 1.58 + defaultInterval : CONSUMER_TIMER_INTERVAL, 1.59 + prefInterval : "test4.timer.interval", 1.60 + contractID : "@mozilla.org/test4/timercallback;1", 1.61 + method : "createInstance", 1.62 + classID : Components.ID("6b0e79f3-4ab8-414c-8f14-dde10e185727"), 1.63 + notified : false 1.64 +}, { 1.65 + desc : "Test Timer Callback 5", 1.66 + timerID : "test5-update-timer", 1.67 + defaultInterval : CONSUMER_TIMER_INTERVAL, 1.68 + prefInterval : "test5.timer.interval", 1.69 + contractID : "@mozilla.org/test5/timercallback;1", 1.70 + method : "createInstance", 1.71 + classID : Components.ID("2f6b7b92-e40f-4874-bfbb-eeb2412c959d"), 1.72 + notified : false 1.73 +}, { 1.74 + desc : "Test Timer Callback 6", 1.75 + timerID : "test6-update-timer", 1.76 + defaultInterval : 86400, 1.77 + prefInterval : "test6.timer.interval", 1.78 + contractID : "@mozilla.org/test6/timercallback;1", 1.79 + method : "createInstance", 1.80 + classID : Components.ID("8a95f611-b2ac-4c7e-8b73-9748c4839731"), 1.81 + notified : false 1.82 +}, { 1.83 + desc : "Test Timer Callback 7", 1.84 + timerID : "test7-update-timer", 1.85 + defaultInterval : CONSUMER_TIMER_INTERVAL, 1.86 + prefInterval : "test7.timer.interval", 1.87 + contractID : "@mozilla.org/test7/timercallback;1", 1.88 + method : "createInstance", 1.89 + classID : Components.ID("2d091020-e23c-11e2-a28f-0800200c9a66"), 1.90 + notified : false 1.91 +}, { 1.92 + desc : "Test Timer Callback 8", 1.93 + timerID : "test8-update-timer", 1.94 + defaultInterval : CONSUMER_TIMER_INTERVAL, 1.95 + contractID : "@mozilla.org/test8/timercallback;1", 1.96 + classID : Components.ID("af878d4b-1d12-41f6-9a90-4e687367ecc1"), 1.97 + notified : false, 1.98 + lastUpdateTime : 0 1.99 +}, { 1.100 + desc : "Test Timer Callback 9", 1.101 + timerID : "test9-update-timer", 1.102 + defaultInterval : CONSUMER_TIMER_INTERVAL, 1.103 + contractID : "@mozilla.org/test9/timercallback;1", 1.104 + classID : Components.ID("5136b201-d64c-4328-8cf1-1a63491cc117"), 1.105 + notified : false, 1.106 + lastUpdateTime : 0 1.107 +} ]; 1.108 + 1.109 +var gUTM; 1.110 +var gNextFunc; 1.111 + 1.112 +XPCOMUtils.defineLazyServiceGetter(this, "gPref", 1.113 + "@mozilla.org/preferences-service;1", 1.114 + "nsIPrefBranch"); 1.115 + 1.116 +XPCOMUtils.defineLazyServiceGetter(this, "gCatMan", 1.117 + "@mozilla.org/categorymanager;1", 1.118 + "nsICategoryManager"); 1.119 + 1.120 +XPCOMUtils.defineLazyGetter(this, "gCompReg", function() { 1.121 + return Cm.QueryInterface(Ci.nsIComponentRegistrar); 1.122 +}); 1.123 + 1.124 +function run_test() { 1.125 + do_test_pending(); 1.126 + 1.127 + // Set the timer to fire every second 1.128 + gPref.setIntPref(PREF_APP_UPDATE_TIMERMINIMUMDELAY, MAIN_TIMER_INTERVAL/1000); 1.129 + gPref.setIntPref(PREF_APP_UPDATE_TIMERFIRSTINTERVAL, MAIN_TIMER_INTERVAL); 1.130 + gPref.setBoolPref(PREF_APP_UPDATE_LOG_ALL, true); 1.131 + 1.132 + // Remove existing update timers to prevent them from being notified 1.133 + var entries = gCatMan.enumerateCategory(CATEGORY_UPDATE_TIMER); 1.134 + while (entries.hasMoreElements()) { 1.135 + let entry = entries.getNext().QueryInterface(Ci.nsISupportsCString).data; 1.136 + gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, entry, false); 1.137 + } 1.138 + 1.139 + gUTM = Cc["@mozilla.org/updates/timer-manager;1"]. 1.140 + getService(Ci.nsIUpdateTimerManager). 1.141 + QueryInterface(Ci.nsIObserver); 1.142 + gUTM.observe(null, "utm-test-init", ""); 1.143 + 1.144 + do_execute_soon(run_test1thru7); 1.145 +} 1.146 + 1.147 +function end_test() { 1.148 + gUTM.observe(null, "xpcom-shutdown", ""); 1.149 + do_test_finished(); 1.150 +} 1.151 + 1.152 +function run_test1thru7() { 1.153 + gNextFunc = check_test1thru7; 1.154 + // bogus default interval 1.155 + gCompReg.registerFactory(TESTS[0].classID, TESTS[0].desc, 1.156 + TESTS[0].contractID, gTest1Factory); 1.157 + gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[0].desc, 1.158 + [TESTS[0].contractID, TESTS[0].method, 1.159 + TESTS[0].timerID, TESTS[0].prefInterval, 1.160 + TESTS[0].defaultInterval].join(","), false, true); 1.161 + 1.162 + // doesn't implement nsITimerCallback 1.163 + gCompReg.registerFactory(TESTS[1].classID, TESTS[1].desc, 1.164 + TESTS[1].contractID, gTest2Factory); 1.165 + gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[1].desc, 1.166 + [TESTS[1].contractID, TESTS[1].method, 1.167 + TESTS[1].timerID, TESTS[1].prefInterval, 1.168 + TESTS[1].defaultInterval].join(","), false, true); 1.169 + 1.170 + // has a last update time of now - 43200 which is half of its interval 1.171 + var lastUpdateTime = Math.round(Date.now() / 1000) - 43200; 1.172 + gPref.setIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[2].timerID, lastUpdateTime); 1.173 + gCompReg.registerFactory(TESTS[2].classID, TESTS[2].desc, 1.174 + TESTS[2].contractID, gTest3Factory); 1.175 + gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[2].desc, 1.176 + [TESTS[2].contractID, TESTS[2].method, 1.177 + TESTS[2].timerID, TESTS[2].prefInterval, 1.178 + TESTS[2].defaultInterval].join(","), false, true); 1.179 + 1.180 + // doesn't have a notify method 1.181 + gCompReg.registerFactory(TESTS[3].classID, TESTS[3].desc, 1.182 + TESTS[3].contractID, gTest4Factory); 1.183 + gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[3].desc, 1.184 + [TESTS[3].contractID, TESTS[3].method, 1.185 + TESTS[3].timerID, TESTS[3].prefInterval, 1.186 + TESTS[3].defaultInterval].join(","), false, true); 1.187 + 1.188 + // already has a last update time 1.189 + gPref.setIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[4].timerID, 1); 1.190 + gCompReg.registerFactory(TESTS[4].classID, TESTS[4].desc, 1.191 + TESTS[4].contractID, gTest5Factory); 1.192 + gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[4].desc, 1.193 + [TESTS[4].contractID, TESTS[4].method, 1.194 + TESTS[4].timerID, TESTS[4].prefInterval, 1.195 + TESTS[4].defaultInterval].join(","), false, true); 1.196 + 1.197 + // has an interval preference that overrides the default 1.198 + gPref.setIntPref(TESTS[5].prefInterval, CONSUMER_TIMER_INTERVAL); 1.199 + gCompReg.registerFactory(TESTS[5].classID, TESTS[5].desc, 1.200 + TESTS[5].contractID, gTest6Factory); 1.201 + gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[5].desc, 1.202 + [TESTS[5].contractID, TESTS[5].method, 1.203 + TESTS[5].timerID, TESTS[5].prefInterval, 1.204 + TESTS[5].defaultInterval].join(","), false, true); 1.205 + 1.206 + // has a next update time 24 hours from now 1.207 + var nextUpdateTime = Math.round(Date.now() / 1000) + 86400; 1.208 + gPref.setIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[6].timerID, nextUpdateTime); 1.209 + gCompReg.registerFactory(TESTS[6].classID, TESTS[6].desc, 1.210 + TESTS[6].contractID, gTest7Factory); 1.211 + gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[6].desc, 1.212 + [TESTS[6].contractID, TESTS[6].method, 1.213 + TESTS[6].timerID, TESTS[6].prefInterval, 1.214 + TESTS[6].defaultInterval].join(","), false, true); 1.215 +} 1.216 + 1.217 +function finished_test1thru7() { 1.218 + if (TESTS[4].notified && TESTS[5].notified && TESTS[6].notified) 1.219 + do_timeout(0, gNextFunc); 1.220 +} 1.221 + 1.222 +function check_test1thru7() { 1.223 + dump("Testing: a category registered timer didn't fire due to an invalid " + 1.224 + "default interval\n"); 1.225 + do_check_false(TESTS[0].notified); 1.226 + 1.227 + dump("Testing: a category registered timer didn't fire due to not " + 1.228 + "implementing nsITimerCallback\n"); 1.229 + do_check_false(TESTS[1].notified); 1.230 + 1.231 + dump("Testing: a category registered timer didn't fire due to the next " + 1.232 + "update time being in the future\n"); 1.233 + do_check_false(TESTS[2].notified); 1.234 + 1.235 + dump("Testing: a category registered timer didn't fire due to not " + 1.236 + "having a notify method\n"); 1.237 + do_check_false(TESTS[3].notified); 1.238 + 1.239 + dump("Testing: a category registered timer has fired\n"); 1.240 + do_check_true(TESTS[4].notified); 1.241 + 1.242 + dump("Testing: a category registered timer fired that has an interval " + 1.243 + "preference that overrides a default that wouldn't have fired yet\n"); 1.244 + do_check_true(TESTS[5].notified); 1.245 + 1.246 + dump("Testing: a category registered timer has fired due to the next " + 1.247 + "update time being reset due to a future last update time\n"); 1.248 + do_check_true(TESTS[6].notified); 1.249 + 1.250 + dump("Testing: two category registered timers last update time has " + 1.251 + "user values\n"); 1.252 + do_check_true(gPref.prefHasUserValue(PREF_BRANCH_LAST_UPDATE_TIME + 1.253 + TESTS[4].timerID)); 1.254 + do_check_true(gPref.prefHasUserValue(PREF_BRANCH_LAST_UPDATE_TIME + 1.255 + TESTS[5].timerID)); 1.256 + 1.257 + // Remove the category timers that should have failed 1.258 + gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[0].desc, true); 1.259 + gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[1].desc, true); 1.260 + gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[2].desc, true); 1.261 + gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[3].desc, true); 1.262 + var count = 0; 1.263 + var entries = gCatMan.enumerateCategory(CATEGORY_UPDATE_TIMER); 1.264 + while (entries.hasMoreElements()) { 1.265 + let entry = entries.getNext().QueryInterface(Ci.nsISupportsCString).data; 1.266 + gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, entry, false); 1.267 + count++; 1.268 + } 1.269 + dump("Testing: no " + CATEGORY_UPDATE_TIMER + " categories are still " + 1.270 + "registered\n"); 1.271 + do_check_eq(count, 0); 1.272 + 1.273 + do_timeout(0, run_test8); 1.274 +} 1.275 + 1.276 +function run_test8() { 1.277 + gNextFunc = check_test8; 1.278 + for (var i = 0; i < 2; i++) { 1.279 + gPref.setIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[7 + i].timerID, 1); 1.280 + gCompReg.registerFactory(TESTS[7 + i].classID, TESTS[7 + i].desc, 1.281 + TESTS[7 + i].contractID, eval("gTest" + (8 + i) + "Factory")); 1.282 + gUTM.registerTimer(TESTS[7 + i].timerID, eval("gTest" + (8 + i) + "TimerCallback"), 1.283 + TESTS[7 + i].defaultInterval); 1.284 + } 1.285 +} 1.286 + 1.287 +function check_test8() { 1.288 + var self = arguments.callee; 1.289 + self.timesCalled = (self.timesCalled || 0) + 1; 1.290 + if (self.timesCalled < 2) 1.291 + return; 1.292 + 1.293 + dump("Testing: two registerTimer registered timers have fired\n"); 1.294 + for (var i = 0; i < 2; i++) 1.295 + do_check_true(TESTS[7 + i].notified); 1.296 + 1.297 + // Check that 'staggering' has happened: even though the two events wanted to fire at 1.298 + // the same time, we waited a full MAIN_TIMER_INTERVAL between them. 1.299 + // (to avoid sensitivity to random timing issues, we fudge by a factor of 0.5 here) 1.300 + do_check_true(Math.abs(TESTS[7].notifyTime - TESTS[8].notifyTime) >= 1.301 + MAIN_TIMER_INTERVAL * 0.5); 1.302 + 1.303 + dump("Testing: two registerTimer registered timers last update time have " + 1.304 + "been updated\n"); 1.305 + for (var i = 0; i < 2; i++) 1.306 + do_check_neq(gPref.getIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[7 + i].timerID), 1); 1.307 + end_test(); 1.308 +} 1.309 + 1.310 +var gTest1TimerCallback = { 1.311 + notify: function T1CB_notify(aTimer) { 1.312 + do_throw("gTest1TimerCallback notify method should not have been called"); 1.313 + }, 1.314 + QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback]) 1.315 +}; 1.316 + 1.317 +var gTest1Factory = { 1.318 + createInstance: function (outer, iid) { 1.319 + if (outer == null) 1.320 + return gTest1TimerCallback.QueryInterface(iid); 1.321 + throw Cr.NS_ERROR_NO_AGGREGATION; 1.322 + } 1.323 +}; 1.324 + 1.325 +var gTest2TimerCallback = { 1.326 + notify: function T2CB_notify(aTimer) { 1.327 + do_throw("gTest2TimerCallback notify method should not have been called"); 1.328 + }, 1.329 + QueryInterface: XPCOMUtils.generateQI([Ci.nsITimer]) 1.330 +}; 1.331 + 1.332 +var gTest2Factory = { 1.333 + createInstance: function (outer, iid) { 1.334 + if (outer == null) 1.335 + return gTest2TimerCallback.QueryInterface(iid); 1.336 + throw Cr.NS_ERROR_NO_AGGREGATION; 1.337 + } 1.338 +}; 1.339 + 1.340 +var gTest3TimerCallback = { 1.341 + notify: function T3CB_notify(aTimer) { 1.342 + do_throw("gTest3TimerCallback notify method should not have been called"); 1.343 + }, 1.344 + QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback]) 1.345 +}; 1.346 + 1.347 +var gTest3Factory = { 1.348 + createInstance: function (outer, iid) { 1.349 + if (outer == null) 1.350 + return gTest3TimerCallback.QueryInterface(iid); 1.351 + throw Cr.NS_ERROR_NO_AGGREGATION; 1.352 + } 1.353 +}; 1.354 + 1.355 +var gTest4TimerCallback = { 1.356 + QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback]) 1.357 +}; 1.358 + 1.359 +var gTest4Factory = { 1.360 + createInstance: function (outer, iid) { 1.361 + if (outer == null) 1.362 + return gTest4TimerCallback.QueryInterface(iid); 1.363 + throw Cr.NS_ERROR_NO_AGGREGATION; 1.364 + } 1.365 +}; 1.366 + 1.367 +var gTest5TimerCallback = { 1.368 + notify: function T5CB_notify(aTimer) { 1.369 + gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[4].desc, true); 1.370 + TESTS[4].notified = true; 1.371 + finished_test1thru7(); 1.372 + }, 1.373 + QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback]) 1.374 +}; 1.375 + 1.376 +var gTest5Factory = { 1.377 + createInstance: function (outer, iid) { 1.378 + if (outer == null) 1.379 + return gTest5TimerCallback.QueryInterface(iid); 1.380 + throw Cr.NS_ERROR_NO_AGGREGATION; 1.381 + } 1.382 +}; 1.383 + 1.384 +var gTest6TimerCallback = { 1.385 + notify: function T6CB_notify(aTimer) { 1.386 + gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[5].desc, true); 1.387 + TESTS[5].notified = true; 1.388 + finished_test1thru7(); 1.389 + }, 1.390 + QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback]) 1.391 +}; 1.392 + 1.393 +var gTest6Factory = { 1.394 + createInstance: function (outer, iid) { 1.395 + if (outer == null) 1.396 + return gTest6TimerCallback.QueryInterface(iid); 1.397 + throw Cr.NS_ERROR_NO_AGGREGATION; 1.398 + } 1.399 +}; 1.400 + 1.401 +var gTest7TimerCallback = { 1.402 + notify: function T7CB_notify(aTimer) { 1.403 + gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[6].desc, true); 1.404 + TESTS[6].notified = true; 1.405 + finished_test1thru7(); 1.406 + }, 1.407 + QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback]) 1.408 +}; 1.409 + 1.410 +var gTest7Factory = { 1.411 + createInstance: function (outer, iid) { 1.412 + if (outer == null) 1.413 + return gTest7TimerCallback.QueryInterface(iid); 1.414 + throw Cr.NS_ERROR_NO_AGGREGATION; 1.415 + } 1.416 +}; 1.417 + 1.418 +var gTest8TimerCallback = { 1.419 + notify: function T8CB_notify(aTimer) { 1.420 + TESTS[7].notified = true; 1.421 + TESTS[7].notifyTime = Date.now(); 1.422 + do_timeout(0, check_test8); 1.423 + }, 1.424 + QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback]) 1.425 +}; 1.426 + 1.427 +var gTest8Factory = { 1.428 + createInstance: function (outer, iid) { 1.429 + if (outer == null) 1.430 + return gTest8TimerCallback.QueryInterface(iid); 1.431 + throw Cr.NS_ERROR_NO_AGGREGATION; 1.432 + } 1.433 +}; 1.434 + 1.435 +var gTest9TimerCallback = { 1.436 + notify: function T9CB_notify(aTimer) { 1.437 + TESTS[8].notified = true; 1.438 + TESTS[8].notifyTime = Date.now(); 1.439 + do_timeout(0, check_test8); 1.440 + }, 1.441 + QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback]) 1.442 +}; 1.443 + 1.444 +var gTest9Factory = { 1.445 + createInstance: function (outer, iid) { 1.446 + if (outer == null) 1.447 + return gTest9TimerCallback.QueryInterface(iid); 1.448 + throw Cr.NS_ERROR_NO_AGGREGATION; 1.449 + } 1.450 +};