Tests for Bug 471219 - Store timer registrations somewhere permanent. r=dtownsend
authorRobert Strong <robert.bugzilla@gmail.com>
Fri, 18 Sep 2009 11:03:45 -0700
changeset 32861 9a727d92fefd2d448c2f2ab0d99d0db127992f21
parent 32860 a66d6e710af215c587f0f1d53b57ee9a49748a1a
child 32862 43d3061ca0842b8ee333ca33fcd2b434b663b33d
push idunknown
push userunknown
push dateunknown
reviewersdtownsend
bugs471219
milestone1.9.3a1pre
Tests for Bug 471219 - Store timer registrations somewhere permanent. r=dtownsend
toolkit/mozapps/update/Makefile.in
toolkit/mozapps/update/test/unit/head_update.js.in
toolkit/mozapps/update/test/unit/tail_update.js
toolkit/mozapps/update/test/unit/test_0010_general.js
toolkit/mozapps/update/test_timermanager/Makefile.in
toolkit/mozapps/update/test_timermanager/unit/test_0010_timermanager.js
--- a/toolkit/mozapps/update/Makefile.in
+++ b/toolkit/mozapps/update/Makefile.in
@@ -40,15 +40,16 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 DIRS = public src
 
 ifdef ENABLE_TESTS
+DIRS += test_timermanager
 # Update tests require the updater binary
 ifdef MOZ_UPDATER
 DIRS += test
 endif
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/toolkit/mozapps/update/test/unit/head_update.js.in
+++ b/toolkit/mozapps/update/test/unit/head_update.js.in
@@ -149,22 +149,16 @@ function cleanUp() {
  */
 function setDefaultPrefs() {
   var pb = getPrefBranch();
   // Don't display UI for a successful installation. Some apps may not set this
   // pref to false like Firefox does.
   pb.setBoolPref(PREF_APP_UPDATE_SHOW_INSTALLED_UI, false);
   // Enable Update logging
   pb.setBoolPref("app.update.log.all", true);
-  // Lessens the noise in the logs when using Update Service logging
-  pb.setBoolPref("app.update.enabled", false);
-  pb.setBoolPref("extensions.blocklist.enabled", false);
-  pb.setBoolPref("extensions.update.enabled", false);
-  pb.setBoolPref("browser.search.update", false);
-  pb.setBoolPref("browser.microsummary.updateGenerators", false);
 }
 
 /**
  * Initializes nsIApplicationUpdateService and the most commonly used global
  * vars used by tests.
  */
 function startAUS() {
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1.0", "2.0");
deleted file mode 100644
--- a/toolkit/mozapps/update/test/unit/tail_update.js
+++ /dev/null
@@ -1,41 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Application Update Service.
- *
- * The Initial Developer of the Original Code is
- * Robert Strong <robert.bugzilla@gmail.com>.
- *
- * Portions created by the Initial Developer are Copyright (C) 2008
- * the Mozilla Foundation <http://www.mozilla.org/>. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK *****
- */
-
-// Initially moved to head_update since check-interactive was executing this
-// prior to _execute_test(); being executed (bug 384339). It hasn't been moved
-// back since it is easier to comment out the call to cleanUp when needed.
--- a/toolkit/mozapps/update/test/unit/test_0010_general.js
+++ b/toolkit/mozapps/update/test/unit/test_0010_general.js
@@ -36,16 +36,17 @@
  * ***** END LICENSE BLOCK *****
  */
 
 /* General Update Service Tests */
 
 function run_test() {
   // Verify write access to the custom app dir
   dump("Testing: write access is required to the application directory\n");
+  removeUpdateDirsAndFiles();
   var testFile = getCurrentProcessDir();
   testFile.append("update_write_access_test");
   testFile.create(AUS_Ci.nsIFile.NORMAL_FILE_TYPE, 0644);
   do_check_true(testFile.exists());
   testFile.remove(false);
   do_check_false(testFile.exists());
 
   startAUS();
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/update/test_timermanager/Makefile.in
@@ -0,0 +1,49 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Update Timer Manager.
+#
+# The Initial Developer of the Original Code is
+# Robert Strong <robert.bugzilla@gmail.com>.
+#
+# Portions created by the Initial Developer are Copyright (C) 2009
+# the Mozilla Foundation <http://www.mozilla.org/>. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = test_timermanager
+
+XPCSHELL_TESTS = unit
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/update/test_timermanager/unit/test_0010_timermanager.js
@@ -0,0 +1,400 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Update Timer Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * Robert Strong <robert.bugzilla@gmail.com>.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Mozilla Foundation <http://www.mozilla.org/>. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+/* General Update Timer Manager Tests */
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cm = Components.manager;
+const Cr = Components.results;
+
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+const CATEGORY_UPDATE_TIMER = "update-timer";
+
+const PREF_APP_UPDATE_TIMER = "app.update.timer";
+const PREF_APP_UPDATE_LOG_ALL = "app.update.log.all";
+const PREF_BRANCH_LAST_UPDATE_TIME = "app.update.lastUpdateTime.";
+
+const MAIN_TIMER_INTERVAL = 500;    // milliseconds
+const CONSUMER_TIMER_INTERVAL = 1; // seconds
+
+const TESTS = [ {
+  desc            : "Test Timer Callback 1",
+  timerID         : "test1-update-timer",
+  defaultInterval : "bogus",
+  prefInterval    : "test1.timer.interval",
+  contractID      : "@mozilla.org/test1/timercallback;1",
+  method          : "createInstance",
+  classID         : Components.ID("9c7ce81f-98bb-4729-adb4-4d0deb0f59e5"),
+  notified        : false
+}, {
+  desc            : "Test Timer Callback 2",
+  timerID         : "test2-update-timer",
+  defaultInterval : CONSUMER_TIMER_INTERVAL,
+  prefInterval    : "test2.timer.interval",
+  contractID      : "@mozilla.org/test2/timercallback;1",
+  method          : "createInstance",
+  classID         : Components.ID("512834f3-05bb-46be-84e0-81d881a140b7"),
+  notified        : false
+}, {
+  desc            : "Test Timer Callback 3",
+  timerID         : "test3-update-timer",
+  defaultInterval : CONSUMER_TIMER_INTERVAL,
+  prefInterval    : "test3.timer.interval",
+  contractID      : "@mozilla.org/test3/timercallback;1",
+  method          : "createInstance",
+  classID         : Components.ID("c8ac5027-8d11-4471-9d7c-fd692501b437"),
+  notified        : false
+}, {
+  desc            : "Test Timer Callback 4",
+  timerID         : "test4-update-timer",
+  defaultInterval : CONSUMER_TIMER_INTERVAL,
+  prefInterval    : "test4.timer.interval",
+  contractID      : "@mozilla.org/test4/timercallback;1",
+  method          : "createInstance",
+  classID         : Components.ID("6b0e79f3-4ab8-414c-8f14-dde10e185727"),
+  notified        : false
+}, {
+  desc            : "Test Timer Callback 5",
+  timerID         : "test5-update-timer",
+  defaultInterval : CONSUMER_TIMER_INTERVAL,
+  prefInterval    : "test5.timer.interval",
+  contractID      : "@mozilla.org/test5/timercallback;1",
+  method          : "createInstance",
+  classID         : Components.ID("2f6b7b92-e40f-4874-bfbb-eeb2412c959d"),
+  notified        : false
+}, {
+  desc            : "Test Timer Callback 6",
+  timerID         : "test6-update-timer",
+  defaultInterval : 86400,
+  prefInterval    : "test6.timer.interval",
+  contractID      : "@mozilla.org/test6/timercallback;1",
+  method          : "createInstance",
+  classID         : Components.ID("8a95f611-b2ac-4c7e-8b73-9748c4839731"),
+  notified        : false
+}, {
+  desc            : "Test Timer Callback 7",
+  timerID         : "test7-update-timer",
+  defaultInterval : CONSUMER_TIMER_INTERVAL,
+  contractID      : "@mozilla.org/test7/timercallback;1",
+  classID         : Components.ID("af878d4b-1d12-41f6-9a90-4e687367ecc1"),
+  notified        : false,
+  lastUpdateTime  : 0
+} ];
+
+var gUTM;
+var gNextFunc;
+
+XPCOMUtils.defineLazyServiceGetter(this, "gPref",
+                                   "@mozilla.org/preferences-service;1",
+                                   "nsIPrefBranch2");
+
+XPCOMUtils.defineLazyServiceGetter(this, "gCatMan",
+                                   "@mozilla.org/categorymanager;1",
+                                   "nsICategoryManager");
+
+XPCOMUtils.defineLazyGetter(this, "gCompReg", function() {
+  return Cm.QueryInterface(Ci.nsIComponentRegistrar);
+});
+
+function run_test() {
+  do_test_pending();
+
+  // Set the timer to fire every second
+  gPref.setIntPref(PREF_APP_UPDATE_TIMER, MAIN_TIMER_INTERVAL);
+  gPref.setBoolPref(PREF_APP_UPDATE_LOG_ALL, true);
+
+  // Remove existing update timers to prevent them from being notified
+  var entries = gCatMan.enumerateCategory(CATEGORY_UPDATE_TIMER);
+  while (entries.hasMoreElements()) {
+    let entry = entries.getNext().QueryInterface(Ci.nsISupportsCString).data;
+    gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, entry, false);
+  }
+
+  gUTM = Cc["@mozilla.org/updates/timer-manager;1"].
+         getService(Ci.nsIUpdateTimerManager).
+         QueryInterface(Ci.nsIObserver);
+  gUTM.observe(null, "profile-after-change", "");
+
+  do_execute_soon(run_test1thru6);
+}
+
+function end_test() {
+  gUTM.observe(null, "xpcom-shutdown", "");
+  do_test_finished();
+}
+
+function run_test1thru6() {
+  gNextFunc = "check_test1thru6()";
+  // bogus default interval
+  gCompReg.registerFactory(TESTS[0].classID, TESTS[0].desc,
+                           TESTS[0].contractID, gTest1Factory);
+  gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[0].desc,
+                           [TESTS[0].contractID, TESTS[0].method,
+                            TESTS[0].timerID, TESTS[0].prefInterval,
+                            TESTS[0].defaultInterval].join(","), false, true);
+
+  // doesn't implement nsITimerCallback
+  gCompReg.registerFactory(TESTS[1].classID, TESTS[1].desc,
+                           TESTS[1].contractID, gTest2Factory);
+  gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[1].desc,
+                           [TESTS[1].contractID, TESTS[1].method,
+                            TESTS[1].timerID, TESTS[1].prefInterval,
+                            TESTS[1].defaultInterval].join(","), false, true);
+
+  // has a next update time 24 hours from now
+  var nextUpdateTime = Math.round(Date.now() / 1000) + 86400;
+  gPref.setIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[2].timerID, nextUpdateTime);
+  gCompReg.registerFactory(TESTS[2].classID, TESTS[2].desc,
+                           TESTS[2].contractID, gTest3Factory);
+  gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[2].desc,
+                           [TESTS[2].contractID, TESTS[2].method,
+                            TESTS[2].timerID, TESTS[2].prefInterval,
+                            TESTS[2].defaultInterval].join(","), false, true);
+
+  // doesn't have a notify method
+  gCompReg.registerFactory(TESTS[3].classID, TESTS[3].desc,
+                           TESTS[3].contractID, gTest4Factory);
+  gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[3].desc,
+                           [TESTS[3].contractID, TESTS[3].method,
+                            TESTS[3].timerID, TESTS[3].prefInterval,
+                            TESTS[3].defaultInterval].join(","), false, true);
+
+  // already has a last update time
+  gPref.setIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[4].timerID, 1);
+  gCompReg.registerFactory(TESTS[4].classID, TESTS[4].desc,
+                           TESTS[4].contractID, gTest5Factory);
+  gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[4].desc,
+                           [TESTS[4].contractID, TESTS[4].method,
+                            TESTS[4].timerID, TESTS[4].prefInterval,
+                            TESTS[4].defaultInterval].join(","), false, true);
+
+  // has an interval preference that overrides the default
+  gPref.setIntPref(TESTS[5].prefInterval, CONSUMER_TIMER_INTERVAL);
+  gCompReg.registerFactory(TESTS[5].classID, TESTS[5].desc,
+                           TESTS[5].contractID, gTest6Factory);
+  gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[5].desc,
+                           [TESTS[5].contractID, TESTS[5].method,
+                            TESTS[5].timerID, TESTS[5].prefInterval,
+                            TESTS[5].defaultInterval].join(","), false, true);
+}
+
+function finished_test1thru6() {
+  if (TESTS[4].notified && TESTS[5].notified)
+    do_timeout(0, gNextFunc);
+}
+
+function check_test1thru6() {
+  dump("Testing: a category registered timer didn't fire due to an invalid " +
+       "default interval\n");
+  do_check_false(TESTS[0].notified);
+
+  dump("Testing: a category registered timer didn't fire due to not " +
+       "implementing nsITimerCallback\n");
+  do_check_false(TESTS[1].notified);
+
+  dump("Testing: a category registered timer didn't fire due to the next " +
+       "update time being 24 hours from now\n");
+  do_check_false(TESTS[2].notified);
+
+  dump("Testing: a category registered timer didn't fire due to not " +
+       "having a notify method\n");
+  do_check_false(TESTS[3].notified);
+
+  dump("Testing: a category registered timer has fired\n");
+  do_check_true(TESTS[4].notified);
+
+  dump("Testing: a category registered timer fired that has an interval " +
+       "preference that overrides a default that wouldn't have fired yet\n");
+  do_check_true(TESTS[5].notified);
+
+  dump("Testing: two category registered timers last update time has " +
+       "user values\n");
+  do_check_true(gPref.prefHasUserValue(PREF_BRANCH_LAST_UPDATE_TIME +
+                TESTS[4].timerID));
+  do_check_true(gPref.prefHasUserValue(PREF_BRANCH_LAST_UPDATE_TIME +
+                TESTS[5].timerID));
+
+  dump("Testing: one registerTimer registered timer last update time has " +
+       "been updated\n");
+  do_check_neq(gPref.getIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[4].timerID), 1);
+
+  // Remove the category timers that should have failed
+  gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[0].desc, true);
+  gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[1].desc, true);
+  gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[2].desc, true);
+  gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[3].desc, true);
+  var count = 0;
+  var entries = gCatMan.enumerateCategory(CATEGORY_UPDATE_TIMER);
+  while (entries.hasMoreElements()) {
+    let entry = entries.getNext().QueryInterface(Ci.nsISupportsCString).data;
+    gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, entry, false);
+    count++;
+  }
+  dump("Testing: no " + CATEGORY_UPDATE_TIMER + " categories are still " +
+       "registered\n");
+  do_check_eq(count, 0);
+
+  do_timeout(0, "run_test7()");
+}
+
+function run_test7() {
+  gNextFunc = "check_test7()";
+  gPref.setIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[6].timerID, 1);
+  gCompReg.registerFactory(TESTS[6].classID, TESTS[6].desc,
+                           TESTS[6].contractID, gTest7Factory);
+  gUTM.registerTimer(TESTS[6].timerID, gTest7TimerCallback,
+                     TESTS[6].defaultInterval);
+}
+
+function check_test7() {
+  dump("Testing: one registerTimer registered timer has fired\n");
+  do_check_true(TESTS[6].notified);
+  dump("Testing: one registerTimer registered timer last update time has " +
+       "been updated\n");
+  do_check_neq(gPref.getIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[6].timerID), 1);
+  end_test();
+}
+
+var gTest1TimerCallback = {
+  notify: function T1CB_notify(aTimer) {
+    do_throw("gTest1TimerCallback notify method should not have been called");
+  },
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback])
+};
+
+var gTest1Factory = {
+  createInstance: function (outer, iid) {
+    if (outer == null)
+      return gTest1TimerCallback.QueryInterface(iid);
+    throw Cr.NS_ERROR_NO_AGGREGATION;
+  }
+};
+
+var gTest2TimerCallback = {
+  notify: function T2CB_notify(aTimer) {
+    do_throw("gTest2TimerCallback notify method should not have been called");
+  },
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsITimer])
+};
+
+var gTest2Factory = {
+  createInstance: function (outer, iid) {
+    if (outer == null)
+      return gTest2TimerCallback.QueryInterface(iid);
+    throw Cr.NS_ERROR_NO_AGGREGATION;
+  }
+};
+
+var gTest3TimerCallback = {
+  notify: function T3CB_notify(aTimer) {
+    do_throw("gTest3TimerCallback notify method should not have been called");
+  },
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback])
+};
+
+var gTest3Factory = {
+  createInstance: function (outer, iid) {
+    if (outer == null)
+      return gTest3TimerCallback.QueryInterface(iid);
+    throw Cr.NS_ERROR_NO_AGGREGATION;
+  }
+};
+
+var gTest4TimerCallback = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback])
+};
+
+var gTest4Factory = {
+  createInstance: function (outer, iid) {
+    if (outer == null)
+      return gTest4TimerCallback.QueryInterface(iid);
+    throw Cr.NS_ERROR_NO_AGGREGATION;
+  }
+};
+
+var gTest5TimerCallback = {
+  notify: function T5CB_notify(aTimer) {
+    gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[4].desc, true);
+    TESTS[4].notified = true;
+    finished_test1thru6();
+  },
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback])
+};
+
+var gTest5Factory = {
+  createInstance: function (outer, iid) {
+    if (outer == null)
+      return gTest5TimerCallback.QueryInterface(iid);
+    throw Cr.NS_ERROR_NO_AGGREGATION;
+  }
+};
+
+var gTest6TimerCallback = {
+  notify: function T6CB_notify(aTimer) {
+    gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[5].desc, true);
+    TESTS[5].notified = true;
+    finished_test1thru6();
+  },
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback])
+};
+
+var gTest6Factory = {
+  createInstance: function (outer, iid) {
+    if (outer == null)
+      return gTest6TimerCallback.QueryInterface(iid);
+    throw Cr.NS_ERROR_NO_AGGREGATION;
+  }
+};
+
+var gTest7TimerCallback = {
+  notify: function T7CB_notify(aTimer) {
+    TESTS[6].notified = true;
+    do_timeout(0, "check_test7()");
+  },
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback])
+};
+
+var gTest7Factory = {
+  createInstance: function (outer, iid) {
+    if (outer == null)
+      return gTest7TimerCallback.QueryInterface(iid);
+    throw Cr.NS_ERROR_NO_AGGREGATION;
+  }
+};