Bug 1270359 Make MockRegistry a common test-only module r?kmag draft
authorAndrew Swan <aswan@mozilla.com>
Tue, 14 Jun 2016 05:27:36 -0700
changeset 378044 e757292c9868af732eeb8ac0e3a9deff4cce1309
parent 377515 b6f7d0eb61b1878d3d906bd231edf225463ece3f
child 378045 8ca88a0c81404f2f6193828536a2a6f106d92f1e
push id20920
push useraswan@mozilla.com
push dateTue, 14 Jun 2016 12:30:28 +0000
reviewerskmag
bugs1270359
milestone50.0a1
Bug 1270359 Make MockRegistry a common test-only module r?kmag MozReview-Commit-ID: DiLa3vfAh3R
testing/modules/MockRegistry.jsm
testing/modules/moz.build
toolkit/mozapps/extensions/test/xpcshell/head_addons.js
toolkit/mozapps/extensions/test/xpcshell/test_bug596607.js
toolkit/mozapps/extensions/test/xpcshell/test_registry.js
new file mode 100644
--- /dev/null
+++ b/testing/modules/MockRegistry.jsm
@@ -0,0 +1,115 @@
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = ["MockRegistry"];
+
+const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
+
+Cu.import("resource://testing-common/MockRegistrar.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+class MockRegistry {
+  constructor() {
+    // Three level structure of Maps pointing to Maps pointing to Maps
+    // this.roots is the top of the structure and has ROOT_KEY_* values
+    // as keys.  Maps at the second level are the values of the first
+    // level Map, they have registry keys (also called paths) as keys.
+    // Third level maps are the values in second level maps, they have
+    // map registry names to corresponding values (which in this implementation
+    // are always strings).
+    this.roots = new Map([
+      [Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, new Map()],
+      [Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, new Map()],
+      [Ci.nsIWindowsRegKey.ROOT_KEY_CLASSES_ROOT, new Map()],
+    ]);
+
+    let registry = this;
+
+    /**
+     * This is a mock nsIWindowsRegistry implementation. It only implements a
+     * subset of the interface used in tests.  In particular, only values
+     * of type string are supported.
+     */
+    function MockWindowsRegKey() { }
+    MockWindowsRegKey.prototype = {
+      values: null,
+
+      // --- Overridden nsISupports interface functions ---
+      QueryInterface: XPCOMUtils.generateQI([Ci.nsIWindowsRegKey]),
+
+      // --- Overridden nsIWindowsRegKey interface functions ---
+      open: function(root, path, mode) {
+        let rootKey = registry.getRoot(root);
+        if (!rootKey.has(path)) {
+          rootKey.set(path, new Map());
+        }
+        this.values = rootKey.get(path);
+      },
+
+      close: function() {
+        this.values = null;
+      },
+
+      get valueCount() {
+        if (!this.values)
+          throw Components.results.NS_ERROR_FAILURE;
+        return this.values.size;
+      },
+
+      hasValue: function(name) {
+        if (!this.values) {
+          return false;
+        }
+        return this.values.has(name);
+      },
+
+      getValueType: function(name) {
+        return Ci.nsIWindowsRegKey.TYPE_STRING;
+      },
+
+      getValueName: function(index) {
+        if (!this.values || index >= this.values.size)
+          throw Components.results.NS_ERROR_FAILURE;
+	let names = Array.from(this.values.keys());
+        return names[index];
+      },
+
+      readStringValue: function(name) {
+        if (!this.values) {
+          throw new Error("invalid registry path");
+        }
+        return this.values.get(name);
+      }
+    };
+
+    this.cid = MockRegistrar.register("@mozilla.org/windows-registry-key;1", MockWindowsRegKey);
+  }
+
+  shutdown() {
+    MockRegistrar.unregister(this.cid);
+    this.cid = null;
+  }
+
+  getRoot(root) {
+    if (!this.roots.has(root)) {
+      throw new Error(`No such root ${root}`);
+    }
+    return this.roots.get(root);
+  }
+
+  setValue(root, path, name, value) {
+    let rootKey = this.getRoot(root);
+
+    if (!rootKey.has(path)) {
+      rootKey.set(path, new Map());
+    }
+
+    let pathmap = rootKey.get(path);
+    if (value == null) {
+      pathmap.delete(name);
+    } else {
+      pathmap.set(name, value);
+    }
+  }
+};
+
--- a/testing/modules/moz.build
+++ b/testing/modules/moz.build
@@ -13,9 +13,15 @@ TESTING_JS_MODULES += [
     'Assert.jsm',
     'CoverageUtils.jsm',
     'MockRegistrar.jsm',
     'sinon-1.16.1.js',
     'StructuredLog.jsm',
     'TestUtils.jsm',
 ]
 
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
+    TESTING_JS_MODULES += [
+        'MockRegistry.jsm',
+    ]
+
+
 TEST_HARNESS_FILES.testing.mochitest.tests.SimpleTest += ['StructuredLog.jsm']
--- a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
@@ -33,22 +33,26 @@ Components.utils.import("resource://gre/
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 Components.utils.import("resource://gre/modules/FileUtils.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
 Components.utils.import("resource://gre/modules/NetUtil.jsm");
 Components.utils.import("resource://gre/modules/Promise.jsm");
 Components.utils.import("resource://gre/modules/Task.jsm");
 const { OS } = Components.utils.import("resource://gre/modules/osfile.jsm", {});
 Components.utils.import("resource://gre/modules/AsyncShutdown.jsm");
-Components.utils.import("resource://testing-common/MockRegistrar.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Extension",
                                   "resource://gre/modules/Extension.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "HttpServer",
                                   "resource://testing-common/httpd.js");
+XPCOMUtils.defineLazyModuleGetter(this, "MockRegistrar",
+                                  "resource://testing-common/MockRegistrar.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "MockRegistry",
+                                  "resource://testing-common/MockRegistry.jsm");
+
 
 // We need some internal bits of AddonManager
 var AMscope = Components.utils.import("resource://gre/modules/AddonManager.jsm", {});
 var { AddonManager, AddonManagerInternal, AddonManagerPrivate } = AMscope;
 
 // Mock out AddonManager's reference to the AsyncShutdown module so we can shut
 // down AddonManager from the test
 var MockAsyncShutdown = {
@@ -1742,114 +1746,16 @@ function installAllFiles(aFiles, aCallba
 }
 
 function promiseInstallAllFiles(aFiles, aIgnoreIncompatible) {
   let deferred = Promise.defer();
   installAllFiles(aFiles, deferred.resolve, aIgnoreIncompatible);
   return deferred.promise;
 }
 
-if ("nsIWindowsRegKey" in AM_Ci) {
-  var MockRegistry = {
-    LOCAL_MACHINE: {},
-    CURRENT_USER: {},
-    CLASSES_ROOT: {},
-
-    getRoot: function(aRoot) {
-      switch (aRoot) {
-      case AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE:
-        return MockRegistry.LOCAL_MACHINE;
-      case AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER:
-        return MockRegistry.CURRENT_USER;
-      case AM_Ci.nsIWindowsRegKey.ROOT_KEY_CLASSES_ROOT:
-        return MockRegistry.CLASSES_ROOT;
-      default:
-        do_throw("Unknown root " + aRoot);
-        return null;
-      }
-    },
-
-    setValue: function(aRoot, aPath, aName, aValue) {
-      let rootKey = MockRegistry.getRoot(aRoot);
-
-      if (!(aPath in rootKey)) {
-        rootKey[aPath] = [];
-      }
-      else {
-        for (let i = 0; i < rootKey[aPath].length; i++) {
-          if (rootKey[aPath][i].name == aName) {
-            if (aValue === null)
-              rootKey[aPath].splice(i, 1);
-            else
-              rootKey[aPath][i].value = aValue;
-            return;
-          }
-        }
-      }
-
-      if (aValue === null)
-        return;
-
-      rootKey[aPath].push({
-        name: aName,
-        value: aValue
-      });
-    }
-  };
-
-  /**
-   * This is a mock nsIWindowsRegistry implementation. It only implements the
-   * methods that the extension manager requires.
-   */
-  var MockWindowsRegKey = function MockWindowsRegKey() {
-  }
-
-  MockWindowsRegKey.prototype = {
-    values: null,
-
-    // --- Overridden nsISupports interface functions ---
-    QueryInterface: XPCOMUtils.generateQI([AM_Ci.nsIWindowsRegKey]),
-
-    // --- Overridden nsIWindowsRegKey interface functions ---
-    open: function(aRootKey, aRelPath, aMode) {
-      let rootKey = MockRegistry.getRoot(aRootKey);
-
-      if (!(aRelPath in rootKey))
-        rootKey[aRelPath] = [];
-      this.values = rootKey[aRelPath];
-    },
-
-    close: function() {
-      this.values = null;
-    },
-
-    get valueCount() {
-      if (!this.values)
-        throw Components.results.NS_ERROR_FAILURE;
-      return this.values.length;
-    },
-
-    getValueName: function(aIndex) {
-      if (!this.values || aIndex >= this.values.length)
-        throw Components.results.NS_ERROR_FAILURE;
-      return this.values[aIndex].name;
-    },
-
-    readStringValue: function(aName) {
-      for (let value of this.values) {
-        if (value.name == aName)
-          return value.value;
-      }
-      return null;
-    }
-  };
-
-  MockRegistrar.register("@mozilla.org/windows-registry-key;1", MockWindowsRegKey);
-}
-
 // Get the profile directory for tests to use.
 const gProfD = do_get_profile();
 
 const EXTENSIONS_DB = "extensions.json";
 var gExtensionsJSON = gProfD.clone();
 gExtensionsJSON.append(EXTENSIONS_DB);
 
 const EXTENSIONS_INI = "extensions.ini";
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug596607.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug596607.js
@@ -33,37 +33,44 @@ var addon2 = {
   }]
 };
 
 const addon1Dir = writeInstallRDFForExtension(addon1, gProfD, "addon1");
 const addon2Dir = writeInstallRDFForExtension(addon2, gProfD, "addon2");
 const addon3Dir = gProfD.clone();
 addon3Dir.append("addon3@tests.mozilla.org");
 
+let registry;
+
 function run_test() {
   // This test only works where there is a registry.
   if (!("nsIWindowsRegKey" in AM_Ci))
     return;
 
+  registry = new MockRegistry();
+  do_register_cleanup(() => {
+    registry.shutdown();
+  });
+
   do_test_pending();
 
   run_test_1();
 }
 
 // Tests whether starting a fresh profile with a bad entry works
 function run_test_1() {
-  MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
-                        "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
-                        "addon1@tests.mozilla.org", addon1Dir.path);
-  MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
-                        "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
-                        "addon2@tests.mozilla.org", addon2Dir.path);
-  MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
-                        "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
-                        "addon3@tests.mozilla.org", addon3Dir.path);
+  registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
+                    "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
+                    "addon1@tests.mozilla.org", addon1Dir.path);
+  registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
+                    "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
+                    "addon2@tests.mozilla.org", addon2Dir.path);
+  registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
+                    "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
+                    "addon3@tests.mozilla.org", addon3Dir.path);
 
   startupManager();
 
   AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
                                "addon2@tests.mozilla.org",
                                "addon3@tests.mozilla.org"], function([a1, a2, a3]) {
     do_check_neq(a1, null);
     do_check_true(a1.isActive);
@@ -80,19 +87,19 @@ function run_test_1() {
     do_execute_soon(run_test_2);
   });
 }
 
 // Tests whether removing the bad entry has any effect
 function run_test_2() {
   shutdownManager();
 
-  MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
-                        "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
-                        "addon3@tests.mozilla.org", addon3Dir.path);
+  registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
+                    "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
+                    "addon3@tests.mozilla.org", addon3Dir.path);
 
   startupManager(false);
 
   AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
                                "addon2@tests.mozilla.org",
                                "addon3@tests.mozilla.org"], function([a1, a2, a3]) {
     do_check_neq(a1, null);
     do_check_true(a1.isActive);
@@ -109,19 +116,19 @@ function run_test_2() {
     do_execute_soon(run_test_3);
   });
 }
 
 // Tests adding the bad entry to an existing profile has any effect
 function run_test_3() {
   shutdownManager();
 
-  MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
-                        "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
-                        "addon3@tests.mozilla.org", null);
+  registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
+                    "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
+                    "addon3@tests.mozilla.org", null);
 
   startupManager(false);
 
   AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
                                "addon2@tests.mozilla.org",
                                "addon3@tests.mozilla.org"], function([a1, a2, a3]) {
     do_check_neq(a1, null);
     do_check_true(a1.isActive);
--- a/toolkit/mozapps/extensions/test/xpcshell/test_registry.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_registry.js
@@ -30,34 +30,41 @@ var addon2 = {
     minVersion: "1",
     maxVersion: "2"
   }]
 };
 
 const addon1Dir = writeInstallRDFForExtension(addon1, gProfD, "addon1");
 const addon2Dir = writeInstallRDFForExtension(addon2, gProfD, "addon2");
 
+let registry;
+
 function run_test() {
   // This test only works where there is a registry.
   if (!("nsIWindowsRegKey" in AM_Ci))
     return;
 
+  registry = new MockRegistry();
+  do_register_cleanup(() => {
+    registry.shutdown();
+  });
+
   do_test_pending();
 
   run_test_1();
 }
 
 // Tests whether basic registry install works
 function run_test_1() {
-  MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
-                        "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
-                        "addon1@tests.mozilla.org", addon1Dir.path);
-  MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
-                        "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
-                        "addon2@tests.mozilla.org", addon2Dir.path);
+  registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
+                   "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
+                    "addon1@tests.mozilla.org", addon1Dir.path);
+  registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
+                    "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
+                    "addon2@tests.mozilla.org", addon2Dir.path);
 
   startupManager();
 
   AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
                                "addon2@tests.mozilla.org"], function([a1, a2]) {
     do_check_neq(a1, null);
     do_check_true(a1.isActive);
     do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_UNINSTALL));
@@ -69,42 +76,42 @@ function run_test_1() {
     do_check_eq(a2.scope, AddonManager.SCOPE_USER);
 
     do_execute_soon(run_test_2);
   });
 }
 
 // Tests whether uninstalling from the registry works
 function run_test_2() {
-  MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
-                        "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
-                        "addon1@tests.mozilla.org", null);
-  MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
-                        "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
-                        "addon2@tests.mozilla.org", null);
+  registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
+                    "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
+                    "addon1@tests.mozilla.org", null);
+  registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
+                    "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
+                    "addon2@tests.mozilla.org", null);
 
   restartManager();
 
   AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
                                "addon2@tests.mozilla.org"], function([a1, a2]) {
     do_check_eq(a1, null);
     do_check_eq(a2, null);
 
     do_execute_soon(run_test_3);
   });
 }
 
 // Checks that the ID in the registry must match that in the install manifest
 function run_test_3() {
-  MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
-                        "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
-                        "addon1@tests.mozilla.org", addon2Dir.path);
-  MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
-                        "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
-                        "addon2@tests.mozilla.org", addon1Dir.path);
+  registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
+                    "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
+                    "addon1@tests.mozilla.org", addon2Dir.path);
+  registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
+                    "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
+                    "addon2@tests.mozilla.org", addon1Dir.path);
 
   restartManager();
 
   AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
                                "addon2@tests.mozilla.org"], function([a1, a2]) {
     do_check_eq(a1, null);
     do_check_eq(a2, null);
 
@@ -112,36 +119,36 @@ function run_test_3() {
   });
 }
 
 // Tests whether an extension's ID can change without its directory changing
 function run_test_4() {
   // Restarting with bad items in the registry should not force an EM restart
   restartManager();
 
-  MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
-                        "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
-                        "addon1@tests.mozilla.org", null);
-  MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
-                        "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
-                        "addon2@tests.mozilla.org", null);
+  registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
+                    "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
+                    "addon1@tests.mozilla.org", null);
+  registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
+                    "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
+                    "addon2@tests.mozilla.org", null);
 
   restartManager();
 
-  MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
-                        "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
-                        "addon1@tests.mozilla.org", addon1Dir.path);
+  registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
+                    "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
+                    "addon1@tests.mozilla.org", addon1Dir.path);
   restartManager();
 
-  MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
-                        "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
-                        "addon1@tests.mozilla.org", null);
-  MockRegistry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
-                        "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
-                        "addon2@tests.mozilla.org", addon1Dir.path);
+  registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
+                    "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
+                    "addon1@tests.mozilla.org", null);
+  registry.setValue(AM_Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
+                    "SOFTWARE\\Mozilla\\XPCShell\\Extensions",
+                    "addon2@tests.mozilla.org", addon1Dir.path);
   writeInstallRDFForExtension(addon2, gProfD, "addon1");
 
   restartManager();
 
   AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
                                "addon2@tests.mozilla.org"], function([a1, a2]) {
     do_check_eq(a1, null);
     do_check_neq(a2, null);