| OLD | NEW |
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """ | 5 """ |
| 6 Classes in this file define additional actions that need to be taken to run a | 6 Classes in this file define additional actions that need to be taken to run a |
| 7 test under some kind of runtime error detection tool. | 7 test under some kind of runtime error detection tool. |
| 8 | 8 |
| 9 The interface is intended to be used as follows. | 9 The interface is intended to be used as follows. |
| 10 | 10 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 """ | 22 """ |
| 23 # pylint: disable=R0201 | 23 # pylint: disable=R0201 |
| 24 | 24 |
| 25 import os.path | 25 import os.path |
| 26 import subprocess | 26 import subprocess |
| 27 import sys | 27 import sys |
| 28 | 28 |
| 29 from pylib.constants import DIR_SOURCE_ROOT | 29 from pylib.constants import DIR_SOURCE_ROOT |
| 30 | 30 |
| 31 | 31 |
| 32 def SetChromeTimeoutScale(adb, scale): | 32 def SetChromeTimeoutScale(device, scale): |
| 33 """Sets the timeout scale in /data/local/tmp/chrome_timeout_scale to scale.""" | 33 """Sets the timeout scale in /data/local/tmp/chrome_timeout_scale to scale.""" |
| 34 path = '/data/local/tmp/chrome_timeout_scale' | 34 path = '/data/local/tmp/chrome_timeout_scale' |
| 35 if not scale or scale == 1.0: | 35 if not scale or scale == 1.0: |
| 36 # Delete if scale is None/0.0/1.0 since the default timeout scale is 1.0 | 36 # Delete if scale is None/0.0/1.0 since the default timeout scale is 1.0 |
| 37 adb.RunShellCommand('rm %s' % path) | 37 device.old_interface.RunShellCommand('rm %s' % path) |
| 38 else: | 38 else: |
| 39 adb.SetProtectedFileContents(path, '%f' % scale) | 39 device.old_interface.SetProtectedFileContents(path, '%f' % scale) |
| 40 | 40 |
| 41 | 41 |
| 42 class BaseTool(object): | 42 class BaseTool(object): |
| 43 """A tool that does nothing.""" | 43 """A tool that does nothing.""" |
| 44 | 44 |
| 45 def __init__(self): | 45 def __init__(self): |
| 46 """Does nothing.""" | 46 """Does nothing.""" |
| 47 pass | 47 pass |
| 48 | 48 |
| 49 def GetTestWrapper(self): | 49 def GetTestWrapper(self): |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 | 89 |
| 90 class AddressSanitizerTool(BaseTool): | 90 class AddressSanitizerTool(BaseTool): |
| 91 """AddressSanitizer tool.""" | 91 """AddressSanitizer tool.""" |
| 92 | 92 |
| 93 WRAPPER_NAME = '/system/bin/asanwrapper' | 93 WRAPPER_NAME = '/system/bin/asanwrapper' |
| 94 # Disable memcmp overlap check.There are blobs (gl drivers) | 94 # Disable memcmp overlap check.There are blobs (gl drivers) |
| 95 # on some android devices that use memcmp on overlapping regions, | 95 # on some android devices that use memcmp on overlapping regions, |
| 96 # nothing we can do about that. | 96 # nothing we can do about that. |
| 97 EXTRA_OPTIONS = 'strict_memcmp=0,use_sigaltstack=1' | 97 EXTRA_OPTIONS = 'strict_memcmp=0,use_sigaltstack=1' |
| 98 | 98 |
| 99 def __init__(self, adb): | 99 def __init__(self, device): |
| 100 super(AddressSanitizerTool, self).__init__() | 100 super(AddressSanitizerTool, self).__init__() |
| 101 self._adb = adb | 101 self._device = device |
| 102 # Configure AndroidCommands to run utils (such as md5sum_bin) under ASan. | 102 # Configure AndroidCommands to run utils (such as md5sum_bin) under ASan. |
| 103 # This is required because ASan is a compiler-based tool, and md5sum | 103 # This is required because ASan is a compiler-based tool, and md5sum |
| 104 # includes instrumented code from base. | 104 # includes instrumented code from base. |
| 105 adb.SetUtilWrapper(self.GetUtilWrapper()) | 105 device.old_interface.SetUtilWrapper(self.GetUtilWrapper()) |
| 106 | 106 |
| 107 def CopyFiles(self): | 107 def CopyFiles(self): |
| 108 """Copies ASan tools to the device.""" | 108 """Copies ASan tools to the device.""" |
| 109 subprocess.call([os.path.join(DIR_SOURCE_ROOT, | 109 subprocess.call([os.path.join(DIR_SOURCE_ROOT, |
| 110 'tools/android/asan/asan_device_setup.sh'), | 110 'tools/android/asan/asan_device_setup.sh'), |
| 111 '--device', self._adb.GetDevice(), | 111 '--device', self._device.old_interface.GetDevice(), |
| 112 '--extra-options', AddressSanitizerTool.EXTRA_OPTIONS]) | 112 '--extra-options', AddressSanitizerTool.EXTRA_OPTIONS]) |
| 113 self._adb.WaitForDevicePm() | 113 self._device.old_interface.WaitForDevicePm() |
| 114 | 114 |
| 115 def GetTestWrapper(self): | 115 def GetTestWrapper(self): |
| 116 return AddressSanitizerTool.WRAPPER_NAME | 116 return AddressSanitizerTool.WRAPPER_NAME |
| 117 | 117 |
| 118 def GetUtilWrapper(self): | 118 def GetUtilWrapper(self): |
| 119 """Returns the wrapper for utilities, such as forwarder. | 119 """Returns the wrapper for utilities, such as forwarder. |
| 120 | 120 |
| 121 AddressSanitizer wrapper must be added to all instrumented binaries, | 121 AddressSanitizer wrapper must be added to all instrumented binaries, |
| 122 including forwarder and the like. This can be removed if such binaries | 122 including forwarder and the like. This can be removed if such binaries |
| 123 were built without instrumentation. """ | 123 were built without instrumentation. """ |
| 124 return self.GetTestWrapper() | 124 return self.GetTestWrapper() |
| 125 | 125 |
| 126 def SetupEnvironment(self): | 126 def SetupEnvironment(self): |
| 127 self._adb.EnableAdbRoot() | 127 self._device.old_interface.EnableAdbRoot() |
| 128 SetChromeTimeoutScale(self._adb, self.GetTimeoutScale()) | 128 SetChromeTimeoutScale(self._device, self.GetTimeoutScale()) |
| 129 | 129 |
| 130 def CleanUpEnvironment(self): | 130 def CleanUpEnvironment(self): |
| 131 SetChromeTimeoutScale(self._adb, None) | 131 SetChromeTimeoutScale(self._device, None) |
| 132 | 132 |
| 133 def GetTimeoutScale(self): | 133 def GetTimeoutScale(self): |
| 134 # Very slow startup. | 134 # Very slow startup. |
| 135 return 20.0 | 135 return 20.0 |
| 136 | 136 |
| 137 | 137 |
| 138 class ValgrindTool(BaseTool): | 138 class ValgrindTool(BaseTool): |
| 139 """Base abstract class for Valgrind tools.""" | 139 """Base abstract class for Valgrind tools.""" |
| 140 | 140 |
| 141 VG_DIR = '/data/local/tmp/valgrind' | 141 VG_DIR = '/data/local/tmp/valgrind' |
| 142 VGLOGS_DIR = '/data/local/tmp/vglogs' | 142 VGLOGS_DIR = '/data/local/tmp/vglogs' |
| 143 | 143 |
| 144 def __init__(self, adb): | 144 def __init__(self, device): |
| 145 super(ValgrindTool, self).__init__() | 145 super(ValgrindTool, self).__init__() |
| 146 self._adb = adb | 146 self._device = device |
| 147 # exactly 31 chars, SystemProperties::PROP_NAME_MAX | 147 # exactly 31 chars, SystemProperties::PROP_NAME_MAX |
| 148 self._wrap_properties = ['wrap.com.google.android.apps.ch', | 148 self._wrap_properties = ['wrap.com.google.android.apps.ch', |
| 149 'wrap.org.chromium.native_test'] | 149 'wrap.org.chromium.native_test'] |
| 150 | 150 |
| 151 def CopyFiles(self): | 151 def CopyFiles(self): |
| 152 """Copies Valgrind tools to the device.""" | 152 """Copies Valgrind tools to the device.""" |
| 153 self._adb.RunShellCommand('rm -r %s; mkdir %s' % | 153 self._device.old_interface.RunShellCommand( |
| 154 (ValgrindTool.VG_DIR, ValgrindTool.VG_DIR)) | 154 'rm -r %s; mkdir %s' % (ValgrindTool.VG_DIR, ValgrindTool.VG_DIR)) |
| 155 self._adb.RunShellCommand('rm -r %s; mkdir %s' % | 155 self._device.old_interface.RunShellCommand( |
| 156 (ValgrindTool.VGLOGS_DIR, | 156 'rm -r %s; mkdir %s' % (ValgrindTool.VGLOGS_DIR, |
| 157 ValgrindTool.VGLOGS_DIR)) | 157 ValgrindTool.VGLOGS_DIR)) |
| 158 files = self.GetFilesForTool() | 158 files = self.GetFilesForTool() |
| 159 for f in files: | 159 for f in files: |
| 160 self._adb.PushIfNeeded(os.path.join(DIR_SOURCE_ROOT, f), | 160 self._device.old_interface.PushIfNeeded( |
| 161 os.path.join(ValgrindTool.VG_DIR, | 161 os.path.join(DIR_SOURCE_ROOT, f), |
| 162 os.path.basename(f))) | 162 os.path.join(ValgrindTool.VG_DIR, os.path.basename(f))) |
| 163 | 163 |
| 164 def SetupEnvironment(self): | 164 def SetupEnvironment(self): |
| 165 """Sets up device environment.""" | 165 """Sets up device environment.""" |
| 166 self._adb.RunShellCommand('chmod 777 /data/local/tmp') | 166 self._device.old_interface.RunShellCommand('chmod 777 /data/local/tmp') |
| 167 self._adb.RunShellCommand('setenforce 0') | 167 self._device.old_interface.RunShellCommand('setenforce 0') |
| 168 for prop in self._wrap_properties: | 168 for prop in self._wrap_properties: |
| 169 self._adb.RunShellCommand('setprop %s "logwrapper %s"' % ( | 169 self._device.old_interface.RunShellCommand( |
| 170 prop, self.GetTestWrapper())) | 170 'setprop %s "logwrapper %s"' % (prop, self.GetTestWrapper())) |
| 171 SetChromeTimeoutScale(self._adb, self.GetTimeoutScale()) | 171 SetChromeTimeoutScale(self._device, self.GetTimeoutScale()) |
| 172 | 172 |
| 173 def CleanUpEnvironment(self): | 173 def CleanUpEnvironment(self): |
| 174 """Cleans up device environment.""" | 174 """Cleans up device environment.""" |
| 175 for prop in self._wrap_properties: | 175 for prop in self._wrap_properties: |
| 176 self._adb.RunShellCommand('setprop %s ""' % (prop,)) | 176 self._device.RunShellCommand('setprop %s ""' % (prop,)) |
| 177 SetChromeTimeoutScale(self._adb, None) | 177 SetChromeTimeoutScale(self._device, None) |
| 178 | 178 |
| 179 def GetFilesForTool(self): | 179 def GetFilesForTool(self): |
| 180 """Returns a list of file names for the tool.""" | 180 """Returns a list of file names for the tool.""" |
| 181 raise NotImplementedError() | 181 raise NotImplementedError() |
| 182 | 182 |
| 183 def NeedsDebugInfo(self): | 183 def NeedsDebugInfo(self): |
| 184 """Whether this tool requires debug info. | 184 """Whether this tool requires debug info. |
| 185 | 185 |
| 186 Returns: | 186 Returns: |
| 187 True if this tool can not work with stripped binaries. | 187 True if this tool can not work with stripped binaries. |
| 188 """ | 188 """ |
| 189 return True | 189 return True |
| 190 | 190 |
| 191 | 191 |
| 192 class MemcheckTool(ValgrindTool): | 192 class MemcheckTool(ValgrindTool): |
| 193 """Memcheck tool.""" | 193 """Memcheck tool.""" |
| 194 | 194 |
| 195 def __init__(self, adb): | 195 def __init__(self, device): |
| 196 super(MemcheckTool, self).__init__(adb) | 196 super(MemcheckTool, self).__init__(device) |
| 197 | 197 |
| 198 def GetFilesForTool(self): | 198 def GetFilesForTool(self): |
| 199 """Returns a list of file names for the tool.""" | 199 """Returns a list of file names for the tool.""" |
| 200 return ['tools/valgrind/android/vg-chrome-wrapper.sh', | 200 return ['tools/valgrind/android/vg-chrome-wrapper.sh', |
| 201 'tools/valgrind/memcheck/suppressions.txt', | 201 'tools/valgrind/memcheck/suppressions.txt', |
| 202 'tools/valgrind/memcheck/suppressions_android.txt'] | 202 'tools/valgrind/memcheck/suppressions_android.txt'] |
| 203 | 203 |
| 204 def GetTestWrapper(self): | 204 def GetTestWrapper(self): |
| 205 """Returns a string that is to be prepended to the test command line.""" | 205 """Returns a string that is to be prepended to the test command line.""" |
| 206 return ValgrindTool.VG_DIR + '/' + 'vg-chrome-wrapper.sh' | 206 return ValgrindTool.VG_DIR + '/' + 'vg-chrome-wrapper.sh' |
| 207 | 207 |
| 208 def GetTimeoutScale(self): | 208 def GetTimeoutScale(self): |
| 209 """Returns a multiplier that should be applied to timeout values.""" | 209 """Returns a multiplier that should be applied to timeout values.""" |
| 210 return 30 | 210 return 30 |
| 211 | 211 |
| 212 | 212 |
| 213 class TSanTool(ValgrindTool): | 213 class TSanTool(ValgrindTool): |
| 214 """ThreadSanitizer tool. See http://code.google.com/p/data-race-test .""" | 214 """ThreadSanitizer tool. See http://code.google.com/p/data-race-test .""" |
| 215 | 215 |
| 216 def __init__(self, adb): | 216 def __init__(self, device): |
| 217 super(TSanTool, self).__init__(adb) | 217 super(TSanTool, self).__init__(device) |
| 218 | 218 |
| 219 def GetFilesForTool(self): | 219 def GetFilesForTool(self): |
| 220 """Returns a list of file names for the tool.""" | 220 """Returns a list of file names for the tool.""" |
| 221 return ['tools/valgrind/android/vg-chrome-wrapper-tsan.sh', | 221 return ['tools/valgrind/android/vg-chrome-wrapper-tsan.sh', |
| 222 'tools/valgrind/tsan/suppressions.txt', | 222 'tools/valgrind/tsan/suppressions.txt', |
| 223 'tools/valgrind/tsan/suppressions_android.txt', | 223 'tools/valgrind/tsan/suppressions_android.txt', |
| 224 'tools/valgrind/tsan/ignores.txt'] | 224 'tools/valgrind/tsan/ignores.txt'] |
| 225 | 225 |
| 226 def GetTestWrapper(self): | 226 def GetTestWrapper(self): |
| 227 """Returns a string that is to be prepended to the test command line.""" | 227 """Returns a string that is to be prepended to the test command line.""" |
| 228 return ValgrindTool.VG_DIR + '/' + 'vg-chrome-wrapper-tsan.sh' | 228 return ValgrindTool.VG_DIR + '/' + 'vg-chrome-wrapper-tsan.sh' |
| 229 | 229 |
| 230 def GetTimeoutScale(self): | 230 def GetTimeoutScale(self): |
| 231 """Returns a multiplier that should be applied to timeout values.""" | 231 """Returns a multiplier that should be applied to timeout values.""" |
| 232 return 30.0 | 232 return 30.0 |
| 233 | 233 |
| 234 | 234 |
| 235 TOOL_REGISTRY = { | 235 TOOL_REGISTRY = { |
| 236 'memcheck': MemcheckTool, | 236 'memcheck': MemcheckTool, |
| 237 'memcheck-renderer': MemcheckTool, | 237 'memcheck-renderer': MemcheckTool, |
| 238 'tsan': TSanTool, | 238 'tsan': TSanTool, |
| 239 'tsan-renderer': TSanTool, | 239 'tsan-renderer': TSanTool, |
| 240 'asan': AddressSanitizerTool, | 240 'asan': AddressSanitizerTool, |
| 241 } | 241 } |
| 242 | 242 |
| 243 | 243 |
| 244 def CreateTool(tool_name, adb): | 244 def CreateTool(tool_name, device): |
| 245 """Creates a tool with the specified tool name. | 245 """Creates a tool with the specified tool name. |
| 246 | 246 |
| 247 Args: | 247 Args: |
| 248 tool_name: Name of the tool to create. | 248 tool_name: Name of the tool to create. |
| 249 adb: ADB interface the tool will use. | 249 device: A DeviceUtils instance. |
| 250 Returns: | 250 Returns: |
| 251 A tool for the specified tool_name. | 251 A tool for the specified tool_name. |
| 252 """ | 252 """ |
| 253 if not tool_name: | 253 if not tool_name: |
| 254 return BaseTool() | 254 return BaseTool() |
| 255 | 255 |
| 256 ctor = TOOL_REGISTRY.get(tool_name) | 256 ctor = TOOL_REGISTRY.get(tool_name) |
| 257 if ctor: | 257 if ctor: |
| 258 return ctor(adb) | 258 return ctor(device) |
| 259 else: | 259 else: |
| 260 print 'Unknown tool %s, available tools: %s' % ( | 260 print 'Unknown tool %s, available tools: %s' % ( |
| 261 tool_name, ', '.join(sorted(TOOL_REGISTRY.keys()))) | 261 tool_name, ', '.join(sorted(TOOL_REGISTRY.keys()))) |
| 262 sys.exit(1) | 262 sys.exit(1) |
| OLD | NEW |