Bug 1150818 - Part 2: Load mozinfo.json into xpcshell tests. r=ted, a=test-only
authorHiroyuki Ikezoe <hiikezoe@mozilla-japan.org>
Thu, 20 Aug 2015 16:06:00 -0400
changeset 289076 4613a8921664b7b9ba3b36e18aa02bd900a0ea07
parent 289075 69fd3aae80f226efd1bddd5a32f0dd56aa02aa1a
child 289077 b8ea21b86a822ab6bbcf1260e35fdc7846f8c923
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted, test-only
bugs1150818
milestone42.0a2
Bug 1150818 - Part 2: Load mozinfo.json into xpcshell tests. r=ted, a=test-only
testing/xpcshell/head.js
testing/xpcshell/remotexpcshelltests.py
testing/xpcshell/runxpcshelltests.py
testing/xpcshell/selftest.py
--- a/testing/xpcshell/head.js
+++ b/testing/xpcshell/head.js
@@ -1209,16 +1209,17 @@ function do_load_child_test_harness()
     return;
   do_load_child_test_harness.alreadyRun = 1;
 
   _XPCSHELL_PROCESS = "parent";
 
   let command =
         "const _HEAD_JS_PATH=" + uneval(_HEAD_JS_PATH) + "; "
       + "const _HEAD_FILES=" + uneval(_HEAD_FILES) + "; "
+      + "const _MOZINFO_JS_PATH=" + uneval(_MOZINFO_JS_PATH) + "; "
       + "const _TAIL_FILES=" + uneval(_TAIL_FILES) + "; "
       + "const _TEST_NAME=" + uneval(_TEST_NAME) + "; "
       // We'll need more magic to get the debugger working in the child
       + "const _JSDEBUGGER_PORT=0; "
       + "const _XPCSHELL_PROCESS='child';";
 
   if (this._TESTING_MODULES_DIR) {
     command += " const _TESTING_MODULES_DIR=" + uneval(_TESTING_MODULES_DIR) + ";";
@@ -1514,8 +1515,34 @@ try {
   if (runningInParent) {
     let prefs = Components.classes["@mozilla.org/preferences-service;1"]
       .getService(Components.interfaces.nsIPrefBranch);
 
     prefs.deleteBranch("lightweightThemes.selectedThemeID");
     prefs.deleteBranch("browser.devedition.theme.enabled");
   }
 } catch (e) { }
+
+function _load_mozinfo() {
+  let mozinfoFile = Components.classes["@mozilla.org/file/local;1"]
+    .createInstance(Components.interfaces.nsIFile);
+  mozinfoFile.initWithPath(_MOZINFO_JS_PATH);
+  let stream = Components.classes["@mozilla.org/network/file-input-stream;1"]
+    .createInstance(Components.interfaces.nsIFileInputStream);
+  stream.init(mozinfoFile, -1, 0, 0);
+  let json = Components.classes["@mozilla.org/dom/json;1"]
+    .createInstance(Components.interfaces.nsIJSON);
+  let mozinfo = json.decodeFromStream(stream, stream.available());
+  stream.close();
+  return mozinfo;
+}
+
+Object.defineProperty(this, "mozinfo", {
+  configurable: true,
+  get() {
+    let _mozinfo = _load_mozinfo();
+    Object.defineProperty(this, "mozinfo", {
+      configurable: false,
+      value: _mozinfo
+    });
+    return _mozinfo;
+  }
+});
--- a/testing/xpcshell/remotexpcshelltests.py
+++ b/testing/xpcshell/remotexpcshelltests.py
@@ -66,16 +66,24 @@ class RemoteXPCShellTestThread(xpcshell.
         return pluginsDir
 
     def setupProfileDir(self):
         self.clearRemoteDir(self.profileDir)
         if self.interactive or self.singleFile:
             self.log.info("profile dir is %s" % self.profileDir)
         return self.profileDir
 
+    def setupMozinfoJS(self):
+        local = tempfile.mktemp()
+        mozinfo.output_to_file(local)
+        mozInfoJSPath = remoteJoin(self.profileDir, "mozinfo.json")
+        self.device.pushFile(local, mozInfoJSPath)
+        os.remove(local)
+        return mozInfoJSPath
+
     def logCommand(self, name, completeCmd, testdir):
         self.log.info("%s | full command: %r" % (name, completeCmd))
         self.log.info("%s | current directory: %r" % (name, self.remoteHere))
         self.log.info("%s | environment: %s" % (name, self.env))
 
     def getHeadAndTailFiles(self, test):
         """Override parent method to find files on remote device."""
         def sanitize_list(s, kind):
--- a/testing/xpcshell/runxpcshelltests.py
+++ b/testing/xpcshell/runxpcshelltests.py
@@ -387,16 +387,22 @@ class XPCShellTestThread(Thread):
             os.makedirs(profileDir)
         else:
             profileDir = mkdtemp(prefix='xpc-profile-')
         self.env["XPCSHELL_TEST_PROFILE_DIR"] = profileDir
         if self.interactive or self.singleFile:
             self.log.info("profile dir is %s" % profileDir)
         return profileDir
 
+    def setupMozinfoJS(self):
+        mozInfoJSPath = os.path.join(self.profileDir, 'mozinfo.json')
+        mozInfoJSPath = mozInfoJSPath.replace('\\', '\\\\')
+        mozinfo.output_to_file(mozInfoJSPath)
+        return mozInfoJSPath
+
     def buildCmdHead(self, headfiles, tailfiles, xpcscmd):
         """
           Build the command line arguments for the head and tail files,
           along with the address of the webserver which some tests require.
 
           On a remote system, this is overloaded to resolve quoting issues over a secondary command line.
         """
         cmdH = ", ".join(['"' + f.replace('\\', '/') + '"'
@@ -451,17 +457,18 @@ class XPCShellTestThread(Thread):
 
         self.xpcsCmd = [
             self.xpcshell,
             '-g', self.xrePath,
             '-a', self.appPath,
             '-r', self.httpdManifest,
             '-m',
             '-s',
-            '-e', 'const _HEAD_JS_PATH = "%s";' % self.headJSPath
+            '-e', 'const _HEAD_JS_PATH = "%s";' % self.headJSPath,
+            '-e', 'const _MOZINFO_JS_PATH = "%s";' % self.mozInfoJSPath,
         ]
 
         if self.testingModulesDir:
             # Escape backslashes in string literal.
             sanitized = self.testingModulesDir.replace('\\', '\\\\')
             self.xpcsCmd.extend([
                 '-e',
                 'const _TESTING_MODULES_DIR = "%s";' % sanitized
@@ -628,24 +635,26 @@ class XPCShellTestThread(Thread):
         if self.app_dir_key and self.app_dir_key in self.test_object:
             rel_app_dir = self.test_object[self.app_dir_key]
             rel_app_dir = os.path.join(self.xrePath, rel_app_dir)
             self.appPath = os.path.abspath(rel_app_dir)
         else:
             self.appPath = None
 
         test_dir = os.path.dirname(path)
-        self.buildXpcsCmd(test_dir)
-        head_files, tail_files = self.getHeadAndTailFiles(self.test_object)
-        cmdH = self.buildCmdHead(head_files, tail_files, self.xpcsCmd)
 
         # Create a profile and a temp dir that the JS harness can stick
         # a profile and temporary data in
         self.profileDir = self.setupProfileDir()
         self.tempDir = self.setupTempDir()
+        self.mozInfoJSPath = self.setupMozinfoJS()
+
+        self.buildXpcsCmd(test_dir)
+        head_files, tail_files = self.getHeadAndTailFiles(self.test_object)
+        cmdH = self.buildCmdHead(head_files, tail_files, self.xpcsCmd)
 
         # The test file will have to be loaded after the head files.
         cmdT = self.buildCmdTestFile(path)
 
         args = self.xpcsRunArgs[:]
         if 'debug' in self.test_object:
             args.insert(0, '-d')
 
--- a/testing/xpcshell/selftest.py
+++ b/testing/xpcshell/selftest.py
@@ -344,17 +344,31 @@ add_task(function test_task() {
   yield Promise.resolve(true);
 });
 
 add_task(function test_2() {
   yield Promise.resolve(true);
 });
 '''
 
+LOAD_MOZINFO = '''
+function run_test() {
+  do_check_neq(typeof mozinfo, undefined);
+  do_check_neq(typeof mozinfo.os, undefined);
+}
+'''
 
+CHILD_MOZINFO = '''
+function run_test () { run_next_test(); }
+
+add_test(function test_child_mozinfo () {
+  run_test_in_child("test_mozinfo.js");
+  run_next_test();
+});
+'''
 class XPCShellTestsTests(unittest.TestCase):
     """
     Yes, these are unit tests for a unit test harness.
     """
     def setUp(self):
         self.log = StringIO()
         self.tempdir = tempfile.mkdtemp()
         self.utility_path = os.path.join(objdir, 'dist', 'bin')
@@ -1198,10 +1212,39 @@ add_test({
 
         self.assertTestResult(True)
         self.assertEquals(1, self.x.testCount)
         self.assertEquals(1, self.x.passCount)
         self.assertEquals(0, self.x.failCount)
         self.assertInLog(TEST_PASS_STRING)
         self.assertNotInLog(TEST_FAIL_STRING)
 
+    def testMozinfo(self):
+        """
+        Check that mozinfo.json is loaded
+        """
+        self.writeFile("test_mozinfo.js", LOAD_MOZINFO)
+        self.writeManifest(["test_mozinfo.js"])
+        self.assertTestResult(True)
+        self.assertEquals(1, self.x.testCount)
+        self.assertEquals(1, self.x.passCount)
+        self.assertEquals(0, self.x.failCount)
+        self.assertEquals(0, self.x.todoCount)
+        self.assertInLog(TEST_PASS_STRING)
+        self.assertNotInLog(TEST_FAIL_STRING)
+
+    def testChildMozinfo(self):
+        """
+        Check that mozinfo.json is loaded in child process
+        """
+        self.writeFile("test_mozinfo.js", LOAD_MOZINFO)
+        self.writeFile("test_child_mozinfo.js", CHILD_MOZINFO)
+        self.writeManifest(["test_child_mozinfo.js"])
+        self.assertTestResult(True)
+        self.assertEquals(1, self.x.testCount)
+        self.assertEquals(1, self.x.passCount)
+        self.assertEquals(0, self.x.failCount)
+        self.assertEquals(0, self.x.todoCount)
+        self.assertInLog(TEST_PASS_STRING)
+        self.assertNotInLog(TEST_FAIL_STRING)
+
 if __name__ == "__main__":
     unittest.main(verbosity=3)