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)