Bug 1196430 - part 6 - move cut-and-paste stack fixer code into mozrunner; r=wlach
authorNathan Froyd <froydnj@mozilla.com>
Wed, 26 Aug 2015 19:57:36 -0400
changeset 294405 95b4e5d5b14c27268f60832be0bc1062c7199b05
parent 294404 c14dc117d23f191e6241bd20bce9a7a90eba83b3
child 294406 3f6c4bdd629574281b4648545f963b05cd0774a6
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswlach
bugs1196430
milestone43.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 1196430 - part 6 - move cut-and-paste stack fixer code into mozrunner; r=wlach This code is cut-and-pasted in several different places around the tree. Let's put it in a common place.
layout/tools/reftest/runreftest.py
testing/mochitest/runtests.py
testing/mozbase/mozrunner/mozrunner/utils.py
testing/xpcshell/runxpcshelltests.py
--- a/layout/tools/reftest/runreftest.py
+++ b/layout/tools/reftest/runreftest.py
@@ -24,17 +24,17 @@ sys.path.insert(0, SCRIPT_DIRECTORY)
 
 import mozcrash
 import mozdebug
 import mozinfo
 import mozleak
 import mozprocess
 import mozprofile
 import mozrunner
-from mozrunner.utils import test_environment
+from mozrunner.utils import get_stack_fixer_function, test_environment
 from mozscreenshot import printstatus, dump_screen
 
 here = os.path.abspath(os.path.dirname(__file__))
 
 try:
     from mozbuild.base import MozbuildObject
     build_obj = MozbuildObject.from_environment(cwd=here)
 except ImportError:
@@ -498,58 +498,19 @@ class RefTest(object):
                     self.format,
                     self.record_last_test,
                     self.handle_timeout_and_dump_screen,
                     self.log,
                     ]
 
         def stack_fixer(self):
             """
-            return stackFixerFunction, if any, to use on the output lines
+            return get_stack_fixer_function, if any, to use on the output lines
             """
-
-            if not mozinfo.info.get('debug'):
-                return None
-
-            stack_fixer_function = None
-
-            def import_stack_fixer_module(module_name):
-                sys.path.insert(0, self.utilityPath)
-                module = __import__(module_name, globals(), locals(), [])
-                sys.path.pop(0)
-                return module
-
-            if self.symbolsPath and os.path.exists(self.symbolsPath):
-                # Run each line through a function in fix_stack_using_bpsyms.py (uses breakpad symbol files).
-                # This method is preferred for Tinderbox builds, since native
-                # symbols may have been stripped.
-                stack_fixer_module = import_stack_fixer_module(
-                    'fix_stack_using_bpsyms')
-                stack_fixer_function = lambda line: stack_fixer_module.fixSymbols(
-                    line, self.symbolsPath)
-
-            elif mozinfo.isMac:
-                # Run each line through fix_macosx_stack.py (uses atos).
-                # This method is preferred for developer machines, so we don't
-                # have to run "make buildsymbols".
-                stack_fixer_module = import_stack_fixer_module(
-                    'fix_macosx_stack')
-                stack_fixer_function = lambda line: stack_fixer_module.fixSymbols(
-                    line)
-
-            elif mozinfo.isLinux:
-                # Run each line through fix_linux_stack.py (uses addr2line).
-                # This method is preferred for developer machines, so we don't
-                # have to run "make buildsymbols".
-                stack_fixer_module = import_stack_fixer_module(
-                    'fix_linux_stack')
-                stack_fixer_function = lambda line: stack_fixer_module.fixSymbols(
-                    line)
-
-            return stack_fixer_function
+            return get_stack_fixer_function(self.utilityPath, self.symbolsPath)
 
         # output line handlers:
         # these take a line and return a line
         def fix_stack(self, line):
             if self.stack_fixer_function:
                 return self.stack_fixer_function(line)
             return line
 
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -46,17 +46,17 @@ from manifestparser.filters import (
 )
 from leaks import ShutdownLeaks, LSANLeaks
 from mochitest_options import MochitestArgumentParser, build_obj
 from mozprofile import Profile, Preferences
 from mozprofile.permissions import ServerLocations
 from urllib import quote_plus as encodeURIComponent
 from mozlog.formatters import TbplFormatter
 from mozlog import commandline
-from mozrunner.utils import test_environment
+from mozrunner.utils import get_stack_fixer_function, test_environment
 from mozscreenshot import dump_screen
 import mozleak
 
 here = os.path.abspath(os.path.dirname(__file__))
 
 
 ###########################
 # Option for NSPR logging #
@@ -2352,57 +2352,19 @@ class Mochitest(MochitestUtilsMixin):
             if self.bisectChunk:
                 handlers.append(self.record_result)
                 handlers.append(self.first_error)
 
             return handlers
 
         def stackFixer(self):
             """
-            return stackFixerFunction, if any, to use on the output lines
+            return get_stack_fixer_function, if any, to use on the output lines
             """
-
-            if not mozinfo.info.get('debug'):
-                return None
-
-            stackFixerFunction = None
-
-            def import_stackFixerModule(module_name):
-                sys.path.insert(0, self.utilityPath)
-                module = __import__(module_name, globals(), locals(), [])
-                sys.path.pop(0)
-                return module
-
-            if self.symbolsPath and os.path.exists(self.symbolsPath):
-                # Run each line through a function in fix_stack_using_bpsyms.py (uses breakpad symbol files).
-                # This method is preferred for Tinderbox builds, since native
-                # symbols may have been stripped.
-                stackFixerModule = import_stackFixerModule(
-                    'fix_stack_using_bpsyms')
-                stackFixerFunction = lambda line: stackFixerModule.fixSymbols(
-                    line,
-                    self.symbolsPath)
-
-            elif mozinfo.isMac:
-                # Run each line through fix_macosx_stack.py (uses atos).
-                # This method is preferred for developer machines, so we don't
-                # have to run "make buildsymbols".
-                stackFixerModule = import_stackFixerModule('fix_macosx_stack')
-                stackFixerFunction = lambda line: stackFixerModule.fixSymbols(
-                    line)
-
-            elif mozinfo.isLinux:
-                # Run each line through fix_linux_stack.py (uses addr2line).
-                # This method is preferred for developer machines, so we don't
-                # have to run "make buildsymbols".
-                stackFixerModule = import_stackFixerModule('fix_linux_stack')
-                stackFixerFunction = lambda line: stackFixerModule.fixSymbols(
-                    line)
-
-            return stackFixerFunction
+            return get_stack_fixer_function(self.utilityPath, self.symbolsPath)
 
         def finish(self):
             if self.shutdownLeaks:
                 self.shutdownLeaks.process()
 
             if self.lsanLeaks:
                 self.lsanLeaks.process()
 
old mode 100644
new mode 100755
--- a/testing/mozbase/mozrunner/mozrunner/utils.py
+++ b/testing/mozbase/mozrunner/mozrunner/utils.py
@@ -238,8 +238,58 @@ def test_environment(xrePath, env=None, 
             env["TSAN_OPTIONS"] = "external_symbolizer_path=%s" % llvmsym
             log.info("INFO | runtests.py | TSan using symbolizer at %s"
                      % llvmsym)
         else:
             log.info("TEST-UNEXPECTED-FAIL | runtests.py | Failed to find TSan"
                      " symbolizer at %s" % llvmsym)
 
     return env
+
+
+def get_stack_fixer_function(utilityPath, symbolsPath):
+    """
+    Return a stack fixing function, if possible, to use on output lines.
+
+    A stack fixing function checks if a line conforms to the output from
+    MozFormatCodeAddressDetails.  If the line does not, the line is returned
+    unchanged.  If the line does, an attempt is made to convert the
+    file+offset into something human-readable (e.g. a function name).
+    """
+    if not mozinfo.info.get('debug'):
+        return None
+
+    stack_fixer_function = None
+
+    def import_stack_fixer_module(module_name):
+        sys.path.insert(0, utilityPath)
+        module = __import__(module_name, globals(), locals(), [])
+        sys.path.pop(0)
+        return module
+
+    if symbolsPath and os.path.exists(symbolsPath):
+        # Run each line through a function in fix_stack_using_bpsyms.py (uses breakpad symbol files).
+        # This method is preferred for Tinderbox builds, since native
+        # symbols may have been stripped.
+        stack_fixer_module = import_stack_fixer_module(
+            'fix_stack_using_bpsyms')
+        stack_fixer_function = lambda line: stack_fixer_module.fixSymbols(
+            line, symbolsPath)
+
+    elif mozinfo.isMac:
+        # Run each line through fix_macosx_stack.py (uses atos).
+        # This method is preferred for developer machines, so we don't
+        # have to run "make buildsymbols".
+        stack_fixer_module = import_stack_fixer_module(
+            'fix_macosx_stack')
+        stack_fixer_function = lambda line: stack_fixer_module.fixSymbols(
+            line)
+
+    elif mozinfo.isLinux:
+        # Run each line through fix_linux_stack.py (uses addr2line).
+        # This method is preferred for developer machines, so we don't
+        # have to run "make buildsymbols".
+        stack_fixer_module = import_stack_fixer_module(
+            'fix_linux_stack')
+        stack_fixer_function = lambda line: stack_fixer_module.fixSymbols(
+            line)
+
+    return stack_fixer_function
--- a/testing/xpcshell/runxpcshelltests.py
+++ b/testing/xpcshell/runxpcshelltests.py
@@ -61,16 +61,17 @@ if os.path.isdir(mozbase):
     for package in os.listdir(mozbase):
         sys.path.append(os.path.join(mozbase, package))
 
 from manifestparser import TestManifest
 from manifestparser.filters import chunk_by_slice, tags
 from mozlog import commandline
 import mozcrash
 import mozinfo
+from mozrunner.utils import get_stack_fixer_function
 
 # --------------------------------------------------------------
 
 # TODO: perhaps this should be in a more generally shared location?
 # This regex matches all of the C0 and C1 control characters
 # (U+0000 through U+001F; U+007F; U+0080 through U+009F),
 # except TAB (U+0009), CR (U+000D), LF (U+000A) and backslash (U+005C).
 # A raw string is deliberately not used.
@@ -86,49 +87,16 @@ def cleanup_encoding(s):
        sanitized unicode object."""
     if not isinstance(s, basestring):
         return unicode(s)
     if not isinstance(s, unicode):
         s = s.decode('utf-8', 'replace')
     # Replace all C0 and C1 control characters with \xNN escapes.
     return _cleanup_encoding_re.sub(_cleanup_encoding_repl, s)
 
-def find_stack_fixer(mozinfo, utility_dir, symbols_path):
-    # This is mostly taken from the equivalent in runreftest.py, itself similar
-    # to the mochitest version. It's not a huge amount of code, but deduping it
-    # might be nice. This version is indepenent of an enclosing harness class,
-    # so should easily be movable to a shared location.
-    if not mozinfo.info.get('debug'):
-        return None
-
-    def import_stack_fixer_module(module_name):
-        sys.path.insert(0, utility_dir)
-        module = importlib.import_module(module_name)
-        sys.path.pop(0)
-        return module
-
-    stack_fixer_function = None
-
-    if symbols_path and os.path.exists(symbols_path):
-        # Run each line through a function in fix_stack_using_bpsyms.py (uses breakpad symbol files).
-        # This method is preferred for Tinderbox builds, since native symbols may have been stripped.
-        stack_fixer_module = import_stack_fixer_module('fix_stack_using_bpsyms')
-        stack_fixer_function = lambda line: stack_fixer_module.fixSymbols(line, symbols_path)
-    elif mozinfo.isMac:
-        # Run each line through fix_macosx_stack.py (uses atos).
-        # This method is preferred for developer machines, so we don't have to run "make buildsymbols".
-        stack_fixer_module = import_stack_fixer_module('fix_macosx_stack')
-        stack_fixer_function = stack_fixer_module.fixSymbols
-    elif mozinfo.isLinux:
-        stack_fixer_module = import_stack_fixer_module('fix_linux_stack')
-        stack_fixer_function = stack_fixer_module.fixSymbols
-
-    return stack_fixer_function
-
-
 """ Control-C handling """
 gotSIGINT = False
 def markGotSIGINT(signum, stackFrame):
     global gotSIGINT
     gotSIGINT = True
 
 class XPCShellTestThread(Thread):
     def __init__(self, test_object, event, cleanup_dir_list, retry=True,
@@ -1214,19 +1182,17 @@ class XPCShellTests(object):
                 k = k.encode('ascii')
             fixedInfo[k] = v
         self.mozInfo = fixedInfo
 
         mozinfo.update(self.mozInfo)
 
         self.stack_fixer_function = None
         if utility_path and os.path.exists(utility_path):
-            self.stack_fixer_function = find_stack_fixer(mozinfo,
-                                                         utility_path,
-                                                         self.symbolsPath)
+            self.stack_fixer_function = get_stack_fixer_function(utility_path, self.symbolsPath)
 
         # buildEnvironment() needs mozInfo, so we call it after mozInfo is initialized.
         self.buildEnvironment()
 
         # The appDirKey is a optional entry in either the default or individual test
         # sections that defines a relative application directory for test runs. If
         # defined we pass 'grePath/$appDirKey' for the -a parameter of the xpcshell
         # test harness.