media/webrtc/trunk/build/android/pylib/valgrind_tools.py

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/webrtc/trunk/build/android/pylib/valgrind_tools.py	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,255 @@
     1.4 +# Copyright (c) 2012 The Chromium Authors. All rights reserved.
     1.5 +# Use of this source code is governed by a BSD-style license that can be
     1.6 +# found in the LICENSE file.
     1.7 +
     1.8 +"""
     1.9 +Classes in this file define additional actions that need to be taken to run a
    1.10 +test under some kind of runtime error detection tool.
    1.11 +
    1.12 +The interface is intended to be used as follows.
    1.13 +
    1.14 +1. For tests that simply run a native process (i.e. no activity is spawned):
    1.15 +
    1.16 +Call tool.CopyFiles().
    1.17 +Prepend test command line with tool.GetTestWrapper().
    1.18 +
    1.19 +2. For tests that spawn an activity:
    1.20 +
    1.21 +Call tool.CopyFiles().
    1.22 +Call tool.SetupEnvironment().
    1.23 +Run the test as usual.
    1.24 +Call tool.CleanUpEnvironment().
    1.25 +"""
    1.26 +
    1.27 +import os.path
    1.28 +import sys
    1.29 +
    1.30 +from constants import CHROME_DIR
    1.31 +
    1.32 +
    1.33 +def SetChromeTimeoutScale(adb, scale):
    1.34 +  """Sets the timeout scale in /data/local/tmp/chrome_timeout_scale to scale."""
    1.35 +  path = '/data/local/tmp/chrome_timeout_scale'
    1.36 +  if not scale or scale == 1.0:
    1.37 +    # Delete if scale is None/0.0/1.0 since the default timeout scale is 1.0
    1.38 +    adb.RunShellCommand('rm %s' % path)
    1.39 +  else:
    1.40 +    adb.SetFileContents(path, '%f' % scale)
    1.41 +
    1.42 +
    1.43 +class BaseTool(object):
    1.44 +  """A tool that does nothing."""
    1.45 +
    1.46 +  def GetTestWrapper(self):
    1.47 +    """Returns a string that is to be prepended to the test command line."""
    1.48 +    return ''
    1.49 +
    1.50 +  def GetUtilWrapper(self):
    1.51 +    """Returns the wrapper name for the utilities.
    1.52 +
    1.53 +    Returns:
    1.54 +       A string that is to be prepended to the command line of utility
    1.55 +    processes (forwarder, etc.).
    1.56 +    """
    1.57 +    return ''
    1.58 +
    1.59 +  def CopyFiles(self):
    1.60 +    """Copies tool-specific files to the device, create directories, etc."""
    1.61 +    pass
    1.62 +
    1.63 +  def SetupEnvironment(self):
    1.64 +    """Sets up the system environment for a test.
    1.65 +
    1.66 +    This is a good place to set system properties.
    1.67 +    """
    1.68 +    pass
    1.69 +
    1.70 +  def CleanUpEnvironment(self):
    1.71 +    """Cleans up environment."""
    1.72 +    pass
    1.73 +
    1.74 +  def GetTimeoutScale(self):
    1.75 +    """Returns a multiplier that should be applied to timeout values."""
    1.76 +    return 1.0
    1.77 +
    1.78 +  def NeedsDebugInfo(self):
    1.79 +    """Whether this tool requires debug info.
    1.80 +
    1.81 +    Returns:
    1.82 +      True if this tool can not work with stripped binaries.
    1.83 +    """
    1.84 +    return False
    1.85 +
    1.86 +
    1.87 +class AddressSanitizerTool(BaseTool):
    1.88 +  """AddressSanitizer tool."""
    1.89 +
    1.90 +  WRAPPER_PATH = '/system/bin/asanwrapper'
    1.91 +
    1.92 +  def __init__(self, adb):
    1.93 +    self._adb = adb
    1.94 +    self._wrap_properties = ['wrap.com.google.android.apps.ch',
    1.95 +                             'wrap.org.chromium.native_test']
    1.96 +
    1.97 +  def CopyFiles(self):
    1.98 +    """Copies ASan tools to the device."""
    1.99 +    files = ['system/lib/libasan_preload.so',
   1.100 +             'system/bin/asanwrapper',
   1.101 +             'system/bin/asan/app_process',
   1.102 +             'system/bin/linker']
   1.103 +    android_product_out = os.environ['ANDROID_PRODUCT_OUT']
   1.104 +    self._adb.MakeSystemFolderWritable()
   1.105 +    for f in files:
   1.106 +      self._adb.PushIfNeeded(os.path.join(android_product_out, f),
   1.107 +                             os.path.join('/', f))
   1.108 +
   1.109 +  def GetTestWrapper(self):
   1.110 +    return AddressSanitizerTool.WRAPPER_PATH
   1.111 +
   1.112 +  def GetUtilWrapper(self):
   1.113 +    """Returns the wrapper for utilities, such as forwarder.
   1.114 +
   1.115 +    AddressSanitizer wrapper must be added to all instrumented binaries,
   1.116 +    including forwarder and the like. This can be removed if such binaries
   1.117 +    were built without instrumentation. """
   1.118 +    return AddressSanitizerTool.WRAPPER_PATH
   1.119 +
   1.120 +  def SetupEnvironment(self):
   1.121 +    for prop in self._wrap_properties:
   1.122 +      self._adb.RunShellCommand('setprop %s "logwrapper %s"' % (
   1.123 +          prop, self.GetTestWrapper()))
   1.124 +    SetChromeTimeoutScale(self._adb, self.GetTimeoutScale())
   1.125 +
   1.126 +  def CleanUpEnvironment(self):
   1.127 +    for prop in self._wrap_properties:
   1.128 +      self._adb.RunShellCommand('setprop %s ""' % (prop,))
   1.129 +    SetChromeTimeoutScale(self._adb, None)
   1.130 +
   1.131 +  def GetTimeoutScale(self):
   1.132 +    # Very slow startup.
   1.133 +    return 20.0
   1.134 +
   1.135 +
   1.136 +class ValgrindTool(BaseTool):
   1.137 +  """Base abstract class for Valgrind tools."""
   1.138 +
   1.139 +  VG_DIR = '/data/local/tmp/valgrind'
   1.140 +  VGLOGS_DIR = '/data/local/tmp/vglogs'
   1.141 +
   1.142 +  def __init__(self, adb):
   1.143 +    self._adb = adb
   1.144 +    # exactly 31 chars, SystemProperties::PROP_NAME_MAX
   1.145 +    self._wrap_properties = ['wrap.com.google.android.apps.ch',
   1.146 +                             'wrap.org.chromium.native_test']
   1.147 +
   1.148 +  def CopyFiles(self):
   1.149 +    """Copies Valgrind tools to the device."""
   1.150 +    self._adb.RunShellCommand('rm -r %s; mkdir %s' %
   1.151 +                              (ValgrindTool.VG_DIR, ValgrindTool.VG_DIR))
   1.152 +    self._adb.RunShellCommand('rm -r %s; mkdir %s' %
   1.153 +                              (ValgrindTool.VGLOGS_DIR,
   1.154 +                               ValgrindTool.VGLOGS_DIR))
   1.155 +    files = self.GetFilesForTool()
   1.156 +    for f in files:
   1.157 +      self._adb.PushIfNeeded(os.path.join(CHROME_DIR, f),
   1.158 +                             os.path.join(ValgrindTool.VG_DIR,
   1.159 +                                          os.path.basename(f)))
   1.160 +
   1.161 +  def SetupEnvironment(self):
   1.162 +    """Sets up device environment."""
   1.163 +    self._adb.RunShellCommand('chmod 777 /data/local/tmp')
   1.164 +    for prop in self._wrap_properties:
   1.165 +      self._adb.RunShellCommand('setprop %s "logwrapper %s"' % (
   1.166 +          prop, self.GetTestWrapper()))
   1.167 +    SetChromeTimeoutScale(self._adb, self.GetTimeoutScale())
   1.168 +
   1.169 +  def CleanUpEnvironment(self):
   1.170 +    """Cleans up device environment."""
   1.171 +    for prop in self._wrap_properties:
   1.172 +      self._adb.RunShellCommand('setprop %s ""' % (prop,))
   1.173 +    SetChromeTimeoutScale(self._adb, None)
   1.174 +
   1.175 +  def GetFilesForTool(self):
   1.176 +    """Returns a list of file names for the tool."""
   1.177 +    raise NotImplementedError()
   1.178 +
   1.179 +  def NeedsDebugInfo(self):
   1.180 +    """Whether this tool requires debug info.
   1.181 +
   1.182 +    Returns:
   1.183 +      True if this tool can not work with stripped binaries.
   1.184 +    """
   1.185 +    return True
   1.186 +
   1.187 +
   1.188 +class MemcheckTool(ValgrindTool):
   1.189 +  """Memcheck tool."""
   1.190 +
   1.191 +  def __init__(self, adb):
   1.192 +    super(MemcheckTool, self).__init__(adb)
   1.193 +
   1.194 +  def GetFilesForTool(self):
   1.195 +    """Returns a list of file names for the tool."""
   1.196 +    return ['tools/valgrind/android/vg-chrome-wrapper.sh',
   1.197 +            'tools/valgrind/memcheck/suppressions.txt',
   1.198 +            'tools/valgrind/memcheck/suppressions_android.txt']
   1.199 +
   1.200 +  def GetTestWrapper(self):
   1.201 +    """Returns a string that is to be prepended to the test command line."""
   1.202 +    return ValgrindTool.VG_DIR + '/' + 'vg-chrome-wrapper.sh'
   1.203 +
   1.204 +  def GetTimeoutScale(self):
   1.205 +    """Returns a multiplier that should be applied to timeout values."""
   1.206 +    return 30
   1.207 +
   1.208 +
   1.209 +class TSanTool(ValgrindTool):
   1.210 +  """ThreadSanitizer tool. See http://code.google.com/p/data-race-test ."""
   1.211 +
   1.212 +  def __init__(self, adb):
   1.213 +    super(TSanTool, self).__init__(adb)
   1.214 +
   1.215 +  def GetFilesForTool(self):
   1.216 +    """Returns a list of file names for the tool."""
   1.217 +    return ['tools/valgrind/android/vg-chrome-wrapper-tsan.sh',
   1.218 +            'tools/valgrind/tsan/suppressions.txt',
   1.219 +            'tools/valgrind/tsan/suppressions_android.txt',
   1.220 +            'tools/valgrind/tsan/ignores.txt']
   1.221 +
   1.222 +  def GetTestWrapper(self):
   1.223 +    """Returns a string that is to be prepended to the test command line."""
   1.224 +    return ValgrindTool.VG_DIR + '/' + 'vg-chrome-wrapper-tsan.sh'
   1.225 +
   1.226 +  def GetTimeoutScale(self):
   1.227 +    """Returns a multiplier that should be applied to timeout values."""
   1.228 +    return 30.0
   1.229 +
   1.230 +
   1.231 +TOOL_REGISTRY = {
   1.232 +    'memcheck': lambda x: MemcheckTool(x),
   1.233 +    'memcheck-renderer': lambda x: MemcheckTool(x),
   1.234 +    'tsan': lambda x: TSanTool(x),
   1.235 +    'tsan-renderer': lambda x: TSanTool(x),
   1.236 +    'asan': lambda x: AddressSanitizerTool(x),
   1.237 +}
   1.238 +
   1.239 +
   1.240 +def CreateTool(tool_name, adb):
   1.241 +  """Creates a tool with the specified tool name.
   1.242 +
   1.243 +  Args:
   1.244 +    tool_name: Name of the tool to create.
   1.245 +    adb: ADB interface the tool will use.
   1.246 +  Returns:
   1.247 +    A tool for the specified tool_name.
   1.248 +  """
   1.249 +  if not tool_name:
   1.250 +    return BaseTool()
   1.251 +
   1.252 +  ctor = TOOL_REGISTRY.get(tool_name)
   1.253 +  if ctor:
   1.254 +    return ctor(adb)
   1.255 +  else:
   1.256 +    print 'Unknown tool %s, available tools: %s' % (
   1.257 +        tool_name, ', '.join(sorted(TOOL_REGISTRY.keys())))
   1.258 +    sys.exit(1)

mercurial