Bug 1043699 - Mulet reftests. r=jlund
authorArmen Zambrano Gasparnian <armenzg@mozilla.com>
Mon, 29 Sep 2014 16:10:37 -0400
changeset 3221 b59a1a06dd1e
parent 3220 143f996273bb
child 3225 bb3c4a3a3d71
push id2465
push userarmenzg@mozilla.com
push dateMon, 29 Sep 2014 20:10:54 +0000
reviewersjlund
bugs1043699
Bug 1043699 - Mulet reftests. r=jlund
configs/b2g/generic_config.py
configs/b2g/mulet_config.py
mozharness/mozilla/gaia.py
mozharness/mozilla/testing/gaia_test.py
mozharness/mozilla/testing/testbase.py
scripts/b2g_desktop_unittest.py
scripts/gaia_unit.py
scripts/mulet_unittest.py
new file mode 100644
--- /dev/null
+++ b/configs/b2g/generic_config.py
@@ -0,0 +1,28 @@
+# This is a config with generic releng related values 
+import os
+
+config = {
+    # mozharness options
+    "tooltool_servers": ["http://runtime-binaries.pvt.build.mozilla.org/tooltool/"],
+
+    "exes": {
+        'python': '/tools/buildbot/bin/python',
+        'virtualenv': ['/tools/buildbot/bin/python', '/tools/misc-python/virtualenv.py'],
+        'tooltool.py': "/tools/tooltool.py",
+    },
+
+    "find_links": [
+        "http://pypi.pvt.build.mozilla.org/pub",
+        "http://pypi.pub.build.mozilla.org/pub",
+    ],
+    "pip_index": False,
+
+    "buildbot_json_path": "buildprops.json",
+
+    "download_symbols": "ondemand",
+    "download_minidump_stackwalk": True,
+    "default_blob_upload_servers": [
+        "https://blobupload.elasticbeanstalk.com",
+    ],
+    "blob_uploader_auth_file": os.path.join(os.getcwd(), "oauth.txt"),
+}
new file mode 100644
--- /dev/null
+++ b/configs/b2g/mulet_config.py
@@ -0,0 +1,13 @@
+# Call --cfg b2g/generic_config.py before this config
+config = {
+    "default_actions": [
+        'clobber',
+        'read-buildbot-config',
+        'pull',
+        'download-and-extract',
+        'create-virtualenv',
+        'install',
+        'run-tests',
+    ],
+    "in_tree_config": "config/mozharness/linux_mulet_config.py",
+}
--- a/mozharness/mozilla/gaia.py
+++ b/mozharness/mozilla/gaia.py
@@ -3,16 +3,34 @@ Module for performing gaia-specific task
 """
 
 import json
 import os
 
 from mozharness.base.errors import HgErrorList, BaseErrorList
 from mozharness.base.log import ERROR
 
+gaia_config_options = [
+    [["--gaia-dir"],
+    {"action": "store",
+     "dest": "gaia_dir",
+     "help": "directory where gaia repo should be cloned"
+     }],
+    [["--gaia-repo"],
+    {"action": "store",
+     "dest": "gaia_repo",
+     "help": "url of gaia repo to clone"
+    }],
+    [["--gaia-branch"],
+    {"action": "store",
+     "dest": "gaia_branch",
+     "default": "default",
+     "help": "branch of gaia repo to clone"
+    }],
+]
 
 class GaiaMixin(object):
 
     npm_error_list = BaseErrorList + [
         {'substr': r'''npm ERR! Error:''', 'level': ERROR}
     ]
 
     # This requires self to inherit a VCSMixin.
@@ -208,16 +226,55 @@ class GaiaMixin(object):
                 'repo': repo_path,
                 'revision': revision,
                 'branch': branch,
                 'dest': dest,
             }
 
             self.vcs_checkout_repos([repo], parent_dir=os.path.dirname(dest))
 
+    def preflight_pull(self):
+        if not self.buildbot_config:
+            if not self.config.get('gaia_repo'):
+                # gaia_branch by default is set to default
+                self.fatal("You're trying to run this outside of buildbot, " \
+                    "therefore, you need to specify --gaia-repo.")
+            if not self.config.get('gaia_branch'):
+                # gaia_branch by default is set to default
+                self.fatal("You're trying to run this outside of buildbot, " \
+                    "therefore, you need to specify --gaia-branch.")
+
+    def pull(self, **kwargs):
+        '''
+        Two ways of using this function:
+        - The user specifies --gaia-repo or in a config file
+        - The buildbot propeties exist and we query the gaia json url
+          for the current gecko tree
+        '''
+        dirs = self.query_abs_dirs()
+        dest = dirs['abs_gaia_dir']
+        repo = {}
+
+        if self.buildbot_config is not None:
+            # get gaia commit via hgweb (gecko's gaia.json)
+            repo = {
+                'revision': self.buildbot_config['properties']['revision'],
+                'repo_path': 'https://hg.mozilla.org/%s' % self.buildbot_config['properties']['repo_path'],
+                'branch': None,
+            }
+        else:
+            repo = {
+                'repo_path': self.config['gaia_repo'],
+                'revision': 'default',
+                'branch': self.config['gaia_branch']
+            }
+
+        self.clone_gaia(dest, repo,
+                        use_gaia_json=self.buildbot_config is not None)
+
     def make_gaia(self, gaia_dir, xre_dir, debug=False, noftu=True,
                   build_config_path=None):
         env = {'DEBUG': '1' if debug else '0',
                'NOFTU': '1' if noftu else '0',
                'DESKTOP': '0',
                'DESKTOP_SHIMS': '1',
                'USE_LOCAL_XULRUNNER_SDK': '1',
                'XULRUNNER_DIRECTORY': xre_dir
--- a/mozharness/mozilla/testing/gaia_test.py
+++ b/mozharness/mozilla/testing/gaia_test.py
@@ -15,46 +15,25 @@ sys.path.insert(1, os.path.dirname(os.pa
 
 from mozharness.base.errors import TarErrorList, ZipErrorList
 from mozharness.base.log import INFO, ERROR, WARNING, FATAL
 from mozharness.base.script import PreScriptAction
 from mozharness.base.transfer import TransferMixin
 from mozharness.base.vcs.vcsbase import MercurialScript
 from mozharness.mozilla.blob_upload import BlobUploadMixin, blobupload_config_options
 from mozharness.mozilla.buildbot import TBPL_SUCCESS, TBPL_WARNING, TBPL_FAILURE
-from mozharness.mozilla.gaia import GaiaMixin
+from mozharness.mozilla.gaia import GaiaMixin, gaia_config_options
 from mozharness.mozilla.testing.testbase import TestingMixin, testing_config_options
 from mozharness.mozilla.tooltool import TooltoolMixin
 from mozharness.mozilla.proxxy import Proxxy
 
 
 class GaiaTest(TestingMixin, TooltoolMixin, MercurialScript, TransferMixin,
                GaiaMixin, BlobUploadMixin):
     config_options = [[
-        ["--gaia-dir"],
-        {"action": "store",
-         "dest": "gaia_dir",
-         "default": None,
-         "help": "directory where gaia repo should be cloned"
-         }
-    ], [
-        ["--gaia-repo"],
-        {"action": "store",
-         "dest": "gaia_repo",
-         "default": "https://hg.mozilla.org/integration/gaia-central",
-         "help": "url of gaia repo to clone"
-         }
-    ], [
-        ["--gaia-branch"],
-        {"action": "store",
-         "dest": "gaia_branch",
-         "default": "default",
-         "help": "branch of gaia repo to clone"
-         }
-    ], [
         ["--application"],
         {"action": "store",
          "dest": "application",
          "default": "b2g",
          "help": "application binary name"
          }
     ], [
         ["--browser-arg"],
@@ -92,17 +71,18 @@ class GaiaTest(TestingMixin, TooltoolMix
          }
     ], [
         ["--this-chunk"],
         {"action": "store",
          "dest": "this_chunk",
          "help": "Number of this chunk",
          }
     ]] + copy.deepcopy(testing_config_options) + \
-        copy.deepcopy(blobupload_config_options)
+        copy.deepcopy(blobupload_config_options) + \
+        copy.deepcopy(gaia_config_options)
 
     error_list = [
         {'substr': 'FAILED (errors=', 'level': WARNING},
     ]
 
     virtualenv_modules = []
 
     repos = []
@@ -131,36 +111,17 @@ class GaiaTest(TestingMixin, TooltoolMix
         # these are necessary since self.config is read only
         c = self.config
         self.installer_url = c.get('installer_url')
         self.installer_path = c.get('installer_path')
         self.binary_path = c.get('binary_path')
         self.test_url = c.get('test_url')
 
     def pull(self, **kwargs):
-        dirs = self.query_abs_dirs()
-        dest = dirs['abs_gaia_dir']
-
-        repo = {
-            'repo_path': self.config.get('gaia_repo'),
-            'revision': 'default',
-            'branch': self.config.get('gaia_branch')
-        }
-
-        if self.buildbot_config is not None:
-            # get gaia commit via hgweb
-            repo.update({
-                'revision': self.buildbot_config['properties']['revision'],
-                'repo_path': 'https://hg.mozilla.org/%s' % self.buildbot_config['properties']['repo_path']
-            })
-
-        self.clone_gaia(dest, repo,
-                        use_gaia_json=self.buildbot_config is not None)
-
-        super(GaiaTest, self).pull(**kwargs)
+        GaiaMixin.pull(self, **kwargs)
 
     def query_abs_dirs(self):
         if self.abs_dirs:
             return self.abs_dirs
         abs_dirs = super(GaiaTest, self).query_abs_dirs()
         dirs = {}
         gaia_root_dir = self.config.get('gaia_dir')
         if not gaia_root_dir:
--- a/mozharness/mozilla/testing/testbase.py
+++ b/mozharness/mozilla/testing/testbase.py
@@ -110,16 +110,23 @@ class TestingMixin(VirtualenvMixin, Buil
                               exit_code=3):
         proxxy = self._query_proxxy()
         return proxxy.download_proxied_file(url=url, file_name=file_name,
                                             parent_dir=parent_dir,
                                             create_parent_dir=create_parent_dir,
                                             error_level=error_level,
                                             exit_code=exit_code)
 
+    def query_value(self, key):
+        """
+        This function allows us to check for a value
+        in the self.tree_config first and then on self.config
+        """
+        return self.tree_config.get(key, self.config.get(key))
+
     def query_jsshell_url(self):
         """
         Attempt to determine the url of the js shell package given
         the installer url.
         """
         if self.jsshell_url:
             return self.jsshell_url
         if not self.installer_url:
--- a/scripts/b2g_desktop_unittest.py
+++ b/scripts/b2g_desktop_unittest.py
@@ -66,21 +66,22 @@ class B2GDesktopTest(BlobUploadMixin, Te
         {'substr': 'FAILED (errors=', 'level': ERROR},
         {'substr': r'''Could not successfully complete transport of message to Gecko, socket closed''', 'level': ERROR},
         {'substr': r'''Could not communicate with Marionette server. Is the Gecko process still running''', 'level': ERROR},
         {'substr': r'''Connection to Marionette server is lost. Check gecko''', 'level': ERROR},
         {'substr': 'Timeout waiting for marionette on port', 'level': ERROR},
         {'regex': re.compile(r'''(Timeout|NoSuchAttribute|Javascript|NoSuchElement|XPathLookup|NoSuchWindow|StaleElement|ScriptTimeout|ElementNotVisible|NoSuchFrame|InvalidElementState|NoAlertPresent|InvalidCookieDomain|UnableToSetCookie|InvalidSelector|MoveTargetOutOfBounds)Exception'''), 'level': ERROR},
     ]
 
-    def __init__(self, require_config_file=False):
+    def __init__(self, options=[], require_config_file=False):
         super(B2GDesktopTest, self).__init__(
-            config_options=self.config_options,
+            config_options=self.config_options + copy.deepcopy(options),
             all_actions=['clobber',
                          'read-buildbot-config',
+                         'pull',
                          'download-and-extract',
                          'create-virtualenv',
                          'install',
                          'run-tests'],
             default_actions=['clobber',
                              'download-and-extract',
                              'create-virtualenv',
                              'install',
@@ -93,16 +94,20 @@ class B2GDesktopTest(BlobUploadMixin, Te
 
         # these are necessary since self.config is read only
         c = self.config
         self.installer_url = c.get('installer_url')
         self.installer_path = c.get('installer_path')
         self.test_url = c.get('test_url')
         self.test_manifest = c.get('test_manifest')
 
+        suite = self.config['test_suite']
+        if suite not in self.test_suites:
+            self.fatal("Don't know how to run --test-suite '%s'!" % suite)
+
     # TODO detect required config items and fail if not set
 
     def query_abs_dirs(self):
         if self.abs_dirs:
             return self.abs_dirs
         abs_dirs = super(B2GDesktopTest, self).query_abs_dirs()
         dirs = {}
         dirs['abs_blob_upload_dir'] = os.path.join(
@@ -140,17 +145,17 @@ class B2GDesktopTest(BlobUploadMixin, Te
         requirements = os.path.join(dirs['abs_config_dir'],
                                     'marionette_requirements.txt')
         self.register_virtualenv_module(requirements=[requirements],
                                         two_pass=True)
 
     def _query_abs_base_cmd(self, suite):
         dirs = self.query_abs_dirs()
         cmd = [self.query_python_path('python')]
-        cmd.append(self.config['run_file_names'][suite])
+        cmd.append(self.query_value("run_file_names")[suite])
 
         str_format_values = {
             'application': self.binary_path,
             'test_manifest': self.test_manifest,
             'symbols_path': self.symbols_path,
             'gaia_profile': self.gaia_profile,
             'utility_path': os.path.join(dirs['abs_tests_dir'], 'bin'),
             'total_chunks': self.config.get('total_chunks'),
--- a/scripts/gaia_unit.py
+++ b/scripts/gaia_unit.py
@@ -14,16 +14,19 @@ sys.path.insert(1, os.path.dirname(sys.p
 from mozharness.mozilla.testing.gaia_test import GaiaTest
 from mozharness.mozilla.testing.unittest import TestSummaryOutputParserHelper
 
 
 class GaiaUnitTest(GaiaTest):
     def __init__(self, require_config_file=False):
         GaiaTest.__init__(self, require_config_file)
 
+    def pull(self, **kwargs):
+        GaiaTest.pull(self, **kwargs)
+
     def run_tests(self):
         """
         Run the unit test suite.
         """
         dirs = self.query_abs_dirs()
 
         self.make_node_modules()
 
new file mode 100644
--- /dev/null
+++ b/scripts/mulet_unittest.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+# ***** BEGIN LICENSE BLOCK *****
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+# ***** END LICENSE BLOCK *****
+""" mulet_unittest.py
+This allows us to run Mulet unittests
+
+Author: Armen Zambrano Gasparnian
+"""
+import os
+import sys
+
+# load modules from parent dir
+sys.path.insert(1, os.path.dirname(sys.path[0]))
+
+from mozharness.base.transfer import TransferMixin
+from mozharness.mozilla.gaia import GaiaMixin, gaia_config_options
+from b2g_desktop_unittest import B2GDesktopTest
+
+class MuletUnittest(B2GDesktopTest, GaiaMixin, TransferMixin):
+    test_suites = ('reftest',)
+
+    def __init__(self):
+        super(MuletUnittest, self).__init__(options=gaia_config_options)
+
+    def pull(self, **kwargs):
+        GaiaMixin.pull(self, **kwargs)
+        super(MuletUnittest, self).pull(**kwargs)
+
+    def query_abs_dirs(self):
+        if self.abs_dirs:
+            return self.abs_dirs
+
+        abs_dirs = super(MuletUnittest, self).query_abs_dirs()
+        dirs = {}
+        dirs['abs_gaia_dir'] = os.path.join(
+                self.config["base_work_dir"], 'gaia')
+        dirs['abs_gaia_profile'] = os.path.join(
+                dirs["abs_gaia_dir"], 'profile')
+        self.gaia_profile = dirs['abs_gaia_profile']
+        abs_dirs.update(dirs)
+
+        self.abs_dirs = abs_dirs
+        return self.abs_dirs
+
+    def make_gaia(self, gaia_dir):
+        self.run_command(self.query_exe('make', return_type="list"),
+                         cwd=gaia_dir,
+                         halt_on_failure=True)
+
+    def preflight_run_tests(self):
+        # This is if we don't run all actions since we set this inside
+        # of download-and-extract()
+        if self.config.get("binary_path"):
+            self.binary_path = self.config["binary_path"]
+
+        if not self.binary_path:
+            self.fatal("Use --binary-path as it is needed for _query_abs_dir().")
+
+        # This is if we don't run all actions since we set this inside
+        # of download-and-extract()
+        if not self.tree_config:
+            self._read_tree_config()
+
+    def run_tests(self):
+        """
+        Run the unit test suite.
+        """
+        dirs = self.query_abs_dirs()
+
+        # NOTE: We currently don't clobber the checkout or the profile
+        if not os.path.isdir(dirs['abs_gaia_profile']):
+            # Make the gaia profile
+            self.make_gaia(dirs['abs_gaia_dir'])
+
+        super(MuletUnittest, self).run_tests()
+
+
+# main {{{1
+if __name__ == '__main__':
+    mulet_unittest = MuletUnittest()
+    mulet_unittest.run_and_exit()