Bug 1095635 - Accept '-' to correspond to stdout for marionette's --gecko-log option.;r=ahal
authorChris Manchester <cmanchester@mozilla.com>
Mon, 17 Nov 2014 22:21:51 -0500
changeset 216318 ebb36c4fc37f138d606b50b5beec3fb521e51cd4
parent 216317 f597a679642a498441affca8b19ece969c3cb399
child 216319 59107651d86d9f52c09aecd4c9b0e6381ca5119a
push id27845
push userkwierso@gmail.com
push dateWed, 19 Nov 2014 02:08:01 +0000
treeherdermozilla-central@64e7a6391916 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersahal
bugs1095635
milestone36.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 1095635 - Accept '-' to correspond to stdout for marionette's --gecko-log option.;r=ahal
testing/marionette/client/marionette/geckoinstance.py
testing/marionette/client/marionette/runner/base.py
testing/marionette/mach_commands.py
--- a/testing/marionette/client/marionette/geckoinstance.py
+++ b/testing/marionette/client/marionette/geckoinstance.py
@@ -1,16 +1,17 @@
 # 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/
 
 from copy import deepcopy
 import errno
 import platform
 import os
+import sys
 import time
 
 from mozprofile import Profile
 from mozrunner import Runner
 
 
 class GeckoInstance(object):
 
@@ -48,61 +49,68 @@ class GeckoInstance(object):
             profile_args["preferences"].update(self.prefs)
         if not self.profile_path:
             profile_args["restore"] = False
             profile = Profile(**profile_args)
         else:
             profile_args["path_from"] = self.profile_path
             profile = Profile.clone(**profile_args)
 
-        if self.gecko_log is None:
-            self.gecko_log = 'gecko.log'
-        elif os.path.isdir(self.gecko_log):
-            fname = "gecko-%d.log" % time.time()
-            self.gecko_log = os.path.join(self.gecko_log, fname)
+        process_args = {
+            'processOutputLine': [NullOutput()],
+        }
+
+        if self.gecko_log == '-':
+            process_args['stream'] = sys.stdout
+        else:
+            if self.gecko_log is None:
+                self.gecko_log = 'gecko.log'
+            elif os.path.isdir(self.gecko_log):
+                fname = "gecko-%d.log" % time.time()
+                self.gecko_log = os.path.join(self.gecko_log, fname)
 
-        self.gecko_log = os.path.realpath(self.gecko_log)
-        if os.access(self.gecko_log, os.F_OK):
-            if platform.system() is 'Windows':
-                # NOTE: windows has a weird filesystem where it happily 'closes'
-                # the file, but complains if you try to delete it. You get a
-                # 'file still in use' error. Sometimes you can wait a bit and
-                # a retry will succeed.
-                # If all retries fail, we'll just continue without removing
-                # the file. In this case, if we are restarting the instance,
-                # then the new logs just get appended to the old file.
-                tries = 0
-                while tries < 10:
-                    try:
-                        os.remove(self.gecko_log)
-                        break
-                    except WindowsError as e:
-                        if e.errno == errno.EACCES:
-                            tries += 1
-                            time.sleep(0.5)
-                        else:
-                            raise e
-            else:
-                os.remove(self.gecko_log)
+            self.gecko_log = os.path.realpath(self.gecko_log)
+            if os.access(self.gecko_log, os.F_OK):
+                if platform.system() is 'Windows':
+                    # NOTE: windows has a weird filesystem where it happily 'closes'
+                    # the file, but complains if you try to delete it. You get a
+                    # 'file still in use' error. Sometimes you can wait a bit and
+                    # a retry will succeed.
+                    # If all retries fail, we'll just continue without removing
+                    # the file. In this case, if we are restarting the instance,
+                    # then the new logs just get appended to the old file.
+                    tries = 0
+                    while tries < 10:
+                        try:
+                            os.remove(self.gecko_log)
+                            break
+                        except WindowsError as e:
+                            if e.errno == errno.EACCES:
+                                tries += 1
+                                time.sleep(0.5)
+                            else:
+                                raise e
+                else:
+                    os.remove(self.gecko_log)
+
+            process_args['logfile'] = self.gecko_log
 
         env = os.environ.copy()
 
         # environment variables needed for crashreporting
         # https://developer.mozilla.org/docs/Environment_variables_affecting_crash_reporting
         env.update({ 'MOZ_CRASHREPORTER': '1',
                      'MOZ_CRASHREPORTER_NO_REPORT': '1', })
         self.runner = Runner(
             binary=self.bin,
             profile=profile,
             cmdargs=['-no-remote', '-marionette'] + self.app_args,
             env=env,
             symbols_path=self.symbols_path,
-            process_args={
-                'processOutputLine': [NullOutput()],
-                'logfile': self.gecko_log})
+            process_args=process_args)
         self.runner.start()
 
     def close(self):
         if self.runner:
             self.runner.stop()
             self.runner.cleanup()
 
     def restart(self, prefs=None):
--- a/testing/marionette/client/marionette/runner/base.py
+++ b/testing/marionette/client/marionette/runner/base.py
@@ -374,17 +374,18 @@ class BaseMarionetteOptions(OptionParser
                         action='store',
                         help='sets the web server\'s root directory to the given path')
         self.add_option('--gecko-log',
                         dest='gecko_log',
                         action='store',
                         help="Define the path to store log file. If the path is"
                              " a directory, the real log file will be created"
                              " given the format gecko-(timestamp).log. If it is"
-                             " a file, if will be used directly. Default: 'gecko.log'")
+                             " a file, if will be used directly. '-' may be passed"
+                             " to write to stdout. Default: './gecko.log'")
         self.add_option('--logger-name',
                         dest='logger_name',
                         action='store',
                         default='Marionette-based Tests',
                         help='Define the name to associate with the logger used')
 
 
     def parse_args(self, args=None, values=None):
--- a/testing/marionette/mach_commands.py
+++ b/testing/marionette/mach_commands.py
@@ -123,13 +123,15 @@ class MachCommands(MachCommandBase):
     )
     @CommandArgument('--address',
         help='host:port of running Gecko instance to connect to.')
     @CommandArgument('--type',
         default='browser',
         help='Test type, usually one of: browser, b2g, b2g-qemu.')
     @CommandArgument('--profile',
         help='Path to gecko profile to use.')
+    @CommandArgument('--gecko-log',
+        help='Path to gecko log file, or "-" for stdout.')
     @CommandArgument('tests', nargs='*', metavar='TESTS',
         help='Path to test(s) to run.')
     def run_marionette_test(self, tests, **kwargs):
         binary = self.get_binary_path('app')
         return run_marionette(tests, binary=binary, topsrcdir=self.topsrcdir, **kwargs)