| 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 |
| 11 1. For tests that simply run a native process (i.e. no activity is spawned): | 11 1. For tests that simply run a native process (i.e. no activity is spawned): |
| 12 | 12 |
| 13 Call tool.CopyFiles(). | 13 Call tool.CopyFiles(). |
| 14 Prepend test command line with tool.GetTestWrapper(). | 14 Prepend test command line with tool.GetTestWrapper(). |
| 15 | 15 |
| 16 2. For tests that spawn an activity: | 16 2. For tests that spawn an activity: |
| 17 | 17 |
| 18 Call tool.CopyFiles(). | 18 Call tool.CopyFiles(). |
| 19 Call tool.SetupEnvironment(). | 19 Call tool.SetupEnvironment(). |
| 20 Run the test as usual. | 20 Run the test as usual. |
| 21 Call tool.CleanUpEnvironment(). | 21 Call tool.CleanUpEnvironment(). |
| 22 """ | 22 """ |
| 23 | 23 |
| 24 import os.path | 24 import os.path |
| 25 import sys | 25 import sys |
| 26 | 26 |
| 27 from run_tests_helper import CHROME_DIR | 27 from constants import CHROME_DIR |
| 28 | 28 |
| 29 | 29 |
| 30 class BaseTool(object): | 30 class BaseTool(object): |
| 31 """A tool that does nothing.""" | 31 """A tool that does nothing.""" |
| 32 | 32 |
| 33 def __init__(self, *args, **kwargs): | 33 def __init__(self, *args, **kwargs): |
| 34 pass | 34 pass |
| 35 | 35 |
| 36 def GetTestWrapper(self): | 36 def GetTestWrapper(self): |
| 37 """Returns a string that is to be prepended to the test command line.""" | 37 """Returns a string that is to be prepended to the test command line.""" |
| 38 return '' | 38 return '' |
| 39 | 39 |
| 40 def GetUtilWrapper(self): |
| 41 """Returns a string that is to be prepended to the command line of utility |
| 42 processes (forwarder, etc.)""" |
| 43 return '' |
| 44 |
| 40 def CopyFiles(self): | 45 def CopyFiles(self): |
| 41 """Copies tool-specific files to the device, create directories, etc.""" | 46 """Copies tool-specific files to the device, create directories, etc.""" |
| 42 pass | 47 pass |
| 43 | 48 |
| 44 def SetupEnvironment(self): | 49 def SetupEnvironment(self): |
| 45 """Sets up the system environment for a test. | 50 """Sets up the system environment for a test. |
| 46 | 51 |
| 47 This is a good place to set system properties. | 52 This is a good place to set system properties. |
| 48 """ | 53 """ |
| 49 pass | 54 pass |
| 50 | 55 |
| 51 def CleanUpEnvironment(self): | 56 def CleanUpEnvironment(self): |
| 52 """Cleans up environment.""" | 57 """Cleans up environment.""" |
| 53 pass | 58 pass |
| 54 | 59 |
| 55 def GetTimeoutScale(self): | 60 def GetTimeoutScale(self): |
| 56 """Returns a multiplier that should be applied to timeout values.""" | 61 """Returns a multiplier that should be applied to timeout values.""" |
| 57 return 1.0 | 62 return 1.0 |
| 58 | 63 |
| 59 def NeedsDebugInfo(self): | 64 def NeedsDebugInfo(self): |
| 60 """Whether this tool requires debug info. | 65 """Whether this tool requires debug info. |
| 61 | 66 |
| 62 Returns True if this tool can not work with stripped binaries. | 67 Returns True if this tool can not work with stripped binaries. |
| 63 """ | 68 """ |
| 64 return False | 69 return False |
| 65 | 70 |
| 66 | 71 |
| 72 class AddressSanitizerTool(BaseTool): |
| 73 """AddressSanitizer tool.""" |
| 74 |
| 75 WRAPPER_PATH = "/system/bin/asanwrapper" |
| 76 |
| 77 def __init__(self, adb): |
| 78 self.adb = adb |
| 79 self.wrap_properties = ['wrap.com.google.android.apps.ch', |
| 80 'wrap.org.chromium.native_test'] |
| 81 |
| 82 def CopyFiles(self): |
| 83 """Copies ASan tools to the device.""" |
| 84 files = ['system/lib/libasan_preload.so', |
| 85 'system/bin/asanwrapper', |
| 86 'system/bin/asan/app_process', |
| 87 'system/bin/linker'] |
| 88 android_product_out = os.environ['ANDROID_PRODUCT_OUT'] |
| 89 self.adb.MakeSystemFolderWritable() |
| 90 for f in files: |
| 91 self.adb.PushIfNeeded(os.path.join(android_product_out, f), |
| 92 os.path.join('/', f)) |
| 93 |
| 94 def GetTestWrapper(self): |
| 95 return AddressSanitizerTool.WRAPPER_PATH |
| 96 |
| 97 def GetUtilWrapper(self): |
| 98 """ AddressSanitizer wrapper must be added to all instrumented binaries, |
| 99 including forwarder and the like. This can be removed if such binaries |
| 100 were built without instrumentation. """ |
| 101 return AddressSanitizerTool.WRAPPER_PATH |
| 102 |
| 103 def SetupEnvironment(self): |
| 104 for prop in self.wrap_properties: |
| 105 self.adb.RunShellCommand('setprop %s "logwrapper %s"' % ( |
| 106 prop, self.GetTestWrapper())) |
| 107 self.adb.RunShellCommand('setprop chrome.timeout_scale %f' % ( |
| 108 self.GetTimeoutScale())) |
| 109 |
| 110 def CleanUpEnvironment(self): |
| 111 for prop in self.wrap_properties: |
| 112 self.adb.RunShellCommand('setprop %s ""' % (prop,)) |
| 113 self.adb.RunShellCommand('setprop chrome.timeout_scale ""') |
| 114 |
| 115 def GetTimeoutScale(self): |
| 116 # Very slow startup. |
| 117 return 20.0 |
| 118 |
| 119 |
| 67 class ValgrindTool(BaseTool): | 120 class ValgrindTool(BaseTool): |
| 68 """Base abstract class for Valgrind tools.""" | 121 """Base abstract class for Valgrind tools.""" |
| 69 | 122 |
| 70 VG_DIR = '/data/local/tmp/valgrind' | 123 VG_DIR = '/data/local/tmp/valgrind' |
| 71 VGLOGS_DIR = '/data/local/tmp/vglogs' | 124 VGLOGS_DIR = '/data/local/tmp/vglogs' |
| 72 | 125 |
| 73 def __init__(self, adb, renderer=False): | 126 def __init__(self, adb, renderer=False): |
| 74 self.adb = adb | 127 self.adb = adb |
| 75 if renderer: | 128 # exactly 31 chars, SystemProperties::PROP_NAME_MAX |
| 76 # exactly 31 chars, SystemProperties::PROP_NAME_MAX | 129 self.wrap_properties = ['wrap.com.google.android.apps.ch', |
| 77 self.wrap_property = 'wrap.com.android.chrome:sandbox' | 130 'wrap.org.chromium.native_test'] |
| 78 else: | |
| 79 self.wrap_property = 'wrap.com.android.chrome' | |
| 80 | 131 |
| 81 def CopyFiles(self): | 132 def CopyFiles(self): |
| 82 """Copies Valgrind tools to the device.""" | 133 """Copies Valgrind tools to the device.""" |
| 83 self.adb.RunShellCommand('rm -r %s; mkdir %s' % | 134 self.adb.RunShellCommand('rm -r %s; mkdir %s' % |
| 84 (ValgrindTool.VG_DIR, ValgrindTool.VG_DIR)) | 135 (ValgrindTool.VG_DIR, ValgrindTool.VG_DIR)) |
| 85 self.adb.RunShellCommand('rm -r %s; mkdir %s' % | 136 self.adb.RunShellCommand('rm -r %s; mkdir %s' % |
| 86 (ValgrindTool.VGLOGS_DIR, ValgrindTool.VGLOGS_DIR)) | 137 (ValgrindTool.VGLOGS_DIR, ValgrindTool.VGLOGS_DIR)) |
| 87 files = self.GetFilesForTool() | 138 files = self.GetFilesForTool() |
| 88 for f in files: | 139 for f in files: |
| 89 self.adb.PushIfNeeded(os.path.join(CHROME_DIR, f), | 140 self.adb.PushIfNeeded(os.path.join(CHROME_DIR, f), |
| 90 os.path.join(ValgrindTool.VG_DIR, | 141 os.path.join(ValgrindTool.VG_DIR, |
| 91 os.path.basename(f))) | 142 os.path.basename(f))) |
| 92 | 143 |
| 93 def SetupEnvironment(self): | 144 def SetupEnvironment(self): |
| 94 """Sets up device environment.""" | 145 """Sets up device environment.""" |
| 95 self.adb.RunShellCommand('chmod 777 /data/local/tmp') | 146 self.adb.RunShellCommand('chmod 777 /data/local/tmp') |
| 96 self.adb.RunShellCommand('setprop %s "logwrapper %s"' % ( | 147 for prop in self.wrap_properties: |
| 97 self.wrap_property, self.GetTestWrapper())) | 148 self.adb.RunShellCommand('setprop %s "logwrapper %s"' % ( |
| 149 prop, self.GetTestWrapper())) |
| 98 self.adb.RunShellCommand('setprop chrome.timeout_scale %f' % ( | 150 self.adb.RunShellCommand('setprop chrome.timeout_scale %f' % ( |
| 99 self.GetTimeoutScale())) | 151 self.GetTimeoutScale())) |
| 100 | 152 |
| 101 def CleanUpEnvironment(self): | 153 def CleanUpEnvironment(self): |
| 102 """Cleans up device environment.""" | 154 """Cleans up device environment.""" |
| 103 self.adb.RunShellCommand('setprop %s ""' % (self.wrap_property,)) | 155 for prop in self.wrap_properties: |
| 156 self.adb.RunShellCommand('setprop %s ""' % (prop,)) |
| 104 self.adb.RunShellCommand('setprop chrome.timeout_scale ""') | 157 self.adb.RunShellCommand('setprop chrome.timeout_scale ""') |
| 105 | 158 |
| 106 def GetFilesForTool(self): | 159 def GetFilesForTool(self): |
| 107 """Returns a list of file names for the tool.""" | 160 """Returns a list of file names for the tool.""" |
| 108 raise NotImplementedError() | 161 raise NotImplementedError() |
| 109 | 162 |
| 110 def NeedsDebugInfo(self): | 163 def NeedsDebugInfo(self): |
| 111 """Whether this tool requires debug info. | 164 """Whether this tool requires debug info. |
| 112 | 165 |
| 113 Returns True if this tool can not work with stripped binaries. | 166 Returns True if this tool can not work with stripped binaries. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 | 208 |
| 156 def GetTimeoutScale(self): | 209 def GetTimeoutScale(self): |
| 157 """Returns a multiplier that should be applied to timeout values.""" | 210 """Returns a multiplier that should be applied to timeout values.""" |
| 158 return 30 | 211 return 30 |
| 159 | 212 |
| 160 | 213 |
| 161 TOOL_REGISTRY = { | 214 TOOL_REGISTRY = { |
| 162 'memcheck': lambda x: MemcheckTool(x, False), | 215 'memcheck': lambda x: MemcheckTool(x, False), |
| 163 'memcheck-renderer': lambda x: MemcheckTool(x, True), | 216 'memcheck-renderer': lambda x: MemcheckTool(x, True), |
| 164 'tsan': lambda x: TSanTool(x, False), | 217 'tsan': lambda x: TSanTool(x, False), |
| 165 'tsan-renderer': lambda x: TSanTool(x, True) | 218 'tsan-renderer': lambda x: TSanTool(x, True), |
| 219 'asan': lambda x: AddressSanitizerTool(x) |
| 166 } | 220 } |
| 167 | 221 |
| 168 | 222 |
| 169 def CreateTool(tool_name, adb): | 223 def CreateTool(tool_name, adb): |
| 170 """Creates a tool with the specified tool name. | 224 """Creates a tool with the specified tool name. |
| 171 | 225 |
| 172 Args: | 226 Args: |
| 173 tool_name: Name of the tool to create. | 227 tool_name: Name of the tool to create. |
| 174 adb: ADB interface the tool will use. | 228 adb: ADB interface the tool will use. |
| 175 """ | 229 """ |
| 176 if not tool_name: | 230 if not tool_name: |
| 177 return BaseTool() | 231 return BaseTool() |
| 178 | 232 |
| 179 ctor = TOOL_REGISTRY.get(tool_name) | 233 ctor = TOOL_REGISTRY.get(tool_name) |
| 180 if ctor: | 234 if ctor: |
| 181 return ctor(adb) | 235 return ctor(adb) |
| 182 else: | 236 else: |
| 183 print 'Unknown tool %s, available tools: %s' % ( | 237 print 'Unknown tool %s, available tools: %s' % ( |
| 184 tool_name, ', '.join(sorted(TOOL_REGISTRY.keys()))) | 238 tool_name, ', '.join(sorted(TOOL_REGISTRY.keys()))) |
| 185 sys.exit(1) | 239 sys.exit(1) |
| OLD | NEW |