Bug 1147031 - Write mach command for luciddream. r=jgriffin
authorAlexandre Poirot <poirot.alex@gmail.com>
Thu, 09 Apr 2015 11:46:00 -0400
changeset 238397 3990835968206cf9f4c9955b9a6dfe8783f9c13e
parent 238396 ff04a9792eb2ae7aea9a5651e831c0a33c456a06
child 238398 17f7421d7b53561c139cd6be114f89420cb931d3
push id58212
push userryanvm@gmail.com
push dateThu, 09 Apr 2015 19:19:31 +0000
treeherdermozilla-inbound@e58ede36707b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgriffin
bugs1147031
milestone40.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1147031 - Write mach command for luciddream. r=jgriffin
build/mach_bootstrap.py
testing/luciddream/luciddream/__init__.py
testing/luciddream/luciddream/runluciddream.py
testing/luciddream/mach_commands.py
testing/mach_commands.py
--- a/build/mach_bootstrap.py
+++ b/build/mach_bootstrap.py
@@ -47,16 +47,17 @@ SEARCH_PATHS = [
     'testing',
     'testing/taskcluster',
     'testing/xpcshell',
     'testing/web-platform',
     'testing/web-platform/harness',
     'testing/marionette/client',
     'testing/marionette/transport',
     'testing/marionette/driver',
+    'testing/luciddream',
     'testing/mozbase/mozcrash',
     'testing/mozbase/mozdebug',
     'testing/mozbase/mozdevice',
     'testing/mozbase/mozfile',
     'testing/mozbase/mozhttpd',
     'testing/mozbase/mozlog',
     'testing/mozbase/moznetwork',
     'testing/mozbase/mozprocess',
@@ -79,16 +80,17 @@ MACH_MODULES = [
     'python/mach_commands.py',
     'python/mach/mach/commands/commandinfo.py',
     'python/compare-locales/mach_commands.py',
     'python/mozboot/mozboot/mach_commands.py',
     'python/mozbuild/mozbuild/mach_commands.py',
     'python/mozbuild/mozbuild/backend/mach_commands.py',
     'python/mozbuild/mozbuild/frontend/mach_commands.py',
     'services/common/tests/mach_commands.py',
+    'testing/luciddream/mach_commands.py',
     'testing/mach_commands.py',
     'testing/taskcluster/mach_commands.py',
     'testing/marionette/mach_commands.py',
     'testing/mochitest/mach_commands.py',
     'testing/xpcshell/mach_commands.py',
     'testing/talos/mach_commands.py',
     'testing/web-platform/mach_commands.py',
     'testing/xpcshell/mach_commands.py',
--- a/testing/luciddream/luciddream/__init__.py
+++ b/testing/luciddream/luciddream/__init__.py
@@ -5,18 +5,19 @@
 #
 
 import os
 import sys
 from marionette.marionette_test import MarionetteTestCase, MarionetteJSTestCase
 from marionette_driver.errors import ScriptTimeoutException
 
 class LucidDreamTestCase(MarionetteTestCase):
-    def __init__(self, marionette_weakref, browser=None, **kwargs):
+    def __init__(self, marionette_weakref, browser=None, logger=None, **kwargs):
         self.browser = browser
+        self.logger = logger
         MarionetteTestCase.__init__(self, marionette_weakref, **kwargs)
 
     def run_js_test(self, filename, marionette):
         '''
         Run a JavaScript test file and collect its set of assertions
         into the current test's results.
 
         :param filename: The path to the JavaScript test file to execute.
--- a/testing/luciddream/luciddream/runluciddream.py
+++ b/testing/luciddream/luciddream/runluciddream.py
@@ -17,48 +17,48 @@ import marionette
 from mozlog import structured
 
 
 class CommandLineError(Exception):
     pass
 
 
 def validate_options(options):
-    if not (options.b2gPath or options.b2gDesktopPath):
-        raise CommandLineError('You must specify --b2gpath or ' +
+    if not (options.emulator_path or options.b2g_desktop_path):
+        raise CommandLineError('You must specify --emulator-path or ' +
                                '--b2g-desktop-path')
-    if options.b2gPath and options.b2gDesktopPath:
-        raise CommandLineError('You may only use one of --b2gpath or ' +
+    if options.emulator_path and options.b2g_desktop_path:
+        raise CommandLineError('You may only use one of --emulator-path or ' +
                                '--b2g-desktop-path')
-    if options.gaiaProfile and options.b2gPath:
+    if options.gaia_profile and options.emulator_path:
         raise CommandLineError('You may not use --gaia-profile with ' +
-                               '--b2gpath')
-    if not options.browserPath:
+                               '--emulator-path')
+    if not options.browser_path:
         raise CommandLineError('You must specify --browser-path')
     if not os.path.isfile(options.manifest):
         raise CommandLineError('The manifest at "%s" does not exist!'
                                % options.manifest)
 
 
 # BaseMarionetteOptions has a lot of stuff we don't care about, and
 # it seems hard to apply directly to this problem. We can revisit this
 # decision later if necessary.
 def parse_args(in_args):
     parser = argparse.ArgumentParser(description='Run Luciddream tests.')
-    parser.add_argument('--emulator', dest='emulator', action='store',
+    parser.add_argument('--emulator-arch', dest='emulator_arch', action='store',
                         default='arm',
                         help='Architecture of emulator to use: x86 or arm')
-    parser.add_argument('--b2gpath', dest='b2gPath', action='store',
+    parser.add_argument('--emulator-path', dest='emulator_path', action='store',
                         help='path to B2G repo or qemu dir')
-    parser.add_argument('--b2g-desktop-path', dest='b2gDesktopPath',
+    parser.add_argument('--b2g-desktop-path', dest='b2g_desktop_path',
                         action='store',
                         help='path to B2G desktop binary')
-    parser.add_argument('--browser-path', dest='browserPath', action='store',
+    parser.add_argument('--browser-path', dest='browser_path', action='store',
                         help='path to Firefox binary')
-    parser.add_argument('--gaia-profile', dest='gaiaProfile', action='store',
+    parser.add_argument('--gaia-profile', dest='gaia_profile', action='store',
                         help='path to Gaia profile')
     parser.add_argument('manifest', metavar='MANIFEST', action='store',
                         help='path to manifest of tests to run')
     structured.commandline.add_logging_group(parser)
 
     args = parser.parse_args(in_args)
     try:
         validate_options(args)
@@ -71,81 +71,81 @@ def parse_args(in_args):
 
 class LucidDreamTestRunner(BaseMarionetteTestRunner):
     def __init__(self, **kwargs):
         BaseMarionetteTestRunner.__init__(self, **kwargs)
         #TODO: handle something like MarionetteJSTestCase
         self.test_handlers = [LucidDreamTestCase]
 
 
-def start_browser(browserPath):
+def start_browser(browser_path, app_args):
     '''
     Start a Firefox browser and return a Marionette instance that
     can talk to it.
     '''
     marionette = Marionette(
-        bin=browserPath,
+        bin=browser_path,
         # Need to avoid the browser and emulator's ports stepping
         # on each others' toes.
         port=2929,
+        app_args=app_args,
+        gecko_log="firefox.log"
     )
     runner = marionette.runner
     if runner:
         runner.start()
     marionette.wait_for_port()
     marionette.start_session()
     marionette.set_context(marionette.CONTEXT_CHROME)
     return marionette
 
 
 #TODO: make marionette/client/marionette/runtests.py importable so we can
 # just use cli from there. A lot of this is copy/paste from that function.
-def main():
-    try:
-        args = parse_args(sys.argv[1:])
-    except CommandLineError as e:
-        return 1
-
-    logger = structured.commandline.setup_logging(
-        'luciddream', args, {"tbpl": sys.stdout})
-
+def run(browser_path=None, b2g_desktop_path=None, emulator_path=None, emulator_arch=None, gaia_profile=None, manifest=None, browser_args=None, **kwargs):
     # It's sort of debatable here whether the marionette instance managed
     # by the test runner should be the browser or the emulator. Right now
     # it's the emulator because it feels like there's more fiddly setup around
     # that, but longer-term if we want to run tests against different
     # (non-B2G) targets this won't match up very well, so maybe it ought to
     # be the browser?
-    browser = start_browser(args.browserPath)
-    kwargs = {
-        'browser': browser,
-        'logger': logger,
-    }
-    if args.b2gPath:
-        kwargs['homedir'] = args.b2gPath
-        kwargs['emulator'] = args.emulator
-    elif args.b2gDesktopPath:
+    browser = start_browser(browser_path, browser_args)
+
+    kwargs["browser"] = browser
+    if not "logger" in kwargs:
+        logger = structured.commandline.setup_logging(
+            "luciddream", kwargs, {"tbpl": sys.stdout})
+        kwargs["logger"] = logger
+
+    if emulator_path:
+        kwargs['homedir'] = emulator_path
+        kwargs['emulator'] = emulator_arch
+    elif b2g_desktop_path:
         # Work around bug 859952
-        if '-bin' not in args.b2gDesktopPath:
-            if args.b2gDesktopPath.endswith('.exe'):
-                newpath = args.b2gDesktopPath[:-4] + '-bin.exe'
+        if '-bin' not in b2g_desktop_path:
+            if b2g_desktop_path.endswith('.exe'):
+                newpath = b2g_desktop_path[:-4] + '-bin.exe'
             else:
-                newpath = args.b2gDesktopPath + '-bin'
+                newpath = b2g_desktop_path + '-bin'
             if os.path.exists(newpath):
-                args.b2gDesktopPath = newpath
-        kwargs['binary'] = args.b2gDesktopPath
+                b2g_desktop_path = newpath
+        kwargs['binary'] = b2g_desktop_path
         kwargs['app'] = 'b2gdesktop'
-        if args.gaiaProfile:
-            kwargs['profile'] = args.gaiaProfile
+        if gaia_profile:
+            kwargs['profile'] = gaia_profile
         else:
             kwargs['profile'] = os.path.join(
-                os.path.dirname(args.b2gDesktopPath),
+                os.path.dirname(b2g_desktop_path),
                 'gaia',
                 'profile'
             )
     runner = LucidDreamTestRunner(**kwargs)
-    runner.run_tests([args.manifest])
+    runner.run_tests([manifest])
     if runner.failed > 0:
         sys.exit(10)
     sys.exit(0)
 
+def main():
+    args = parse_args(sys.argv[1:])
+    run(**vars(args))
 
 if __name__ == '__main__':
     main()
new file mode 100644
--- /dev/null
+++ b/testing/luciddream/mach_commands.py
@@ -0,0 +1,99 @@
+# 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/.
+
+# Integrates luciddream test runner with mach.
+
+import os
+import re
+import sys
+
+import mozpack.path as mozpath
+
+from mozbuild.base import (
+    MachCommandBase,
+    MachCommandConditions as conditions,
+    MozbuildObject,
+)
+
+from mach.decorators import (
+    CommandArgument,
+    CommandProvider,
+    Command,
+)
+
+class LucidDreamRunner(MozbuildObject):
+    """Run luciddream tests."""
+    def run_tests(self, **kwargs):
+        self._run_make(target='jetpack-tests')
+
+@CommandProvider
+class MachCommands(MachCommandBase):
+    @Command('luciddream', category='testing',
+        description='Runs the luciddream test suite.')
+    @CommandArgument("--consoles", action="store_true",
+                     help="Open jsconsole in both runtimes.")
+    @CommandArgument('--b2g-desktop', dest="b2g_desktop_path", type=str, default=None,
+                     help='Path to b2g desktop binary.')
+    @CommandArgument('--browser', dest="browser_path", type=str, default=None,
+                     help='Path to firefox binary.')
+    @CommandArgument('--gaia-profile', type=str, default=None,
+                     help='Path to gaia profile, optional, if not bundled with b2g desktop.')
+    @CommandArgument('--emulator', dest="emulator_path", type=str, default=None,
+                     help='Path to android emulator.')
+    @CommandArgument('--emulator-arch', type=str, default="arm",
+                     help='Emulator arch: x86 or arm.')
+    @CommandArgument('test_paths', default=None, nargs='*', metavar='TEST',
+                     help='Test to run. Can be specified as a single file, a '
+                          'directory, or omitted. If omitted, the entire test suite is '
+                          'executed.')
+    def run_luciddream_test(self, browser_path, b2g_desktop_path, test_paths, consoles, **params):
+        # import luciddream lazily as its marionette dependency make ./mach clobber fails
+        # early on TBPL
+        import luciddream.runluciddream
+
+        # get_binary_path is going to throw if we haven't built any product
+        # but luciddream can still be run if we provide both binaries...
+        binary_path=False
+        try:
+            binary_path = self.get_binary_path()
+        except Exception:
+            pass
+
+        # otherwise, if we have a build, automatically fetch the binary
+        if conditions.is_b2g(self):
+            if not b2g_desktop_path and binary_path:
+                b2g_desktop_path = binary_path
+        else:
+            if not browser_path and binary_path:
+                browser_path = binary_path
+
+        if not browser_path:
+            print "Need firefox binary path via --browser_path argument"
+            return 1
+        elif not os.path.exists(browser_path):
+            print "Firefox binary doesn't exists: " + browser_path
+            return 1
+
+        if not b2g_desktop_path:
+            print "Need b2g desktop binary path via --b2g-desktop argument"
+            return 1
+        elif not os.path.exists(b2g_desktop_path):
+            print "B2G desktop binary doesn't exists: " + b2g_desktop_path
+            return 1
+
+        if not test_paths or len(test_paths) == 0:
+            print "Please specify a test manifest to run"
+            return 1
+
+        browser_args = None
+        if consoles:
+            browser_args = ["-jsconsole"]
+            if "app_args" in params and isinstance(params["app_args"], list):
+                params["app_args"].append("-jsconsole")
+            else:
+                params["app_args"] = ["-jsconsole"]
+
+        for test in test_paths:
+          luciddream.runluciddream.run(browser_path=browser_path, b2g_desktop_path=b2g_desktop_path,
+            manifest=test, browser_args=browser_args, **params)
--- a/testing/mach_commands.py
+++ b/testing/mach_commands.py
@@ -82,16 +82,20 @@ TEST_SUITES = {
     },
     'mochitest-ipcplugins': {
         'make_target': 'mochitest-ipcplugins',
     },
     'mochitest-plain': {
         'mach_command': 'mochitest',
         'kwargs': {'flavor': 'mochitest', 'test_paths': None},
     },
+    'luciddream': {
+        'mach_command': 'luciddream',
+        'kwargs': {'test_paths': None},
+    },
     'reftest': {
         'aliases': ('RR', 'rr', 'Rr'),
         'mach_command': 'reftest',
         'kwargs': {'test_file': None},
     },
     'reftest-ipc': {
         'aliases': ('Ripc',),
         'mach_command': 'reftest-ipc',