| OLD | NEW |
| (Empty) |
| 1 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 2 # Use of this source code is governed by a BSD-style license that can be | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 """ | |
| 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. | |
| 8 | |
| 9 The interface is intended to be used as follows. | |
| 10 | |
| 11 1. For tests that simply run a native process (i.e. no activity is spawned): | |
| 12 | |
| 13 Call tool.CopyFiles(). | |
| 14 Prepend test command line with tool.GetTestWrapper(). | |
| 15 | |
| 16 2. For tests that spawn an activity: | |
| 17 | |
| 18 Call tool.CopyFiles(). | |
| 19 Call tool.SetupEnvironment(). | |
| 20 Run the test as usual. | |
| 21 Call tool.CleanUpEnvironment(). | |
| 22 """ | |
| 23 | |
| 24 import os.path | |
| 25 import sys | |
| 26 | |
| 27 from run_tests_helper import CHROME_DIR | |
| 28 | |
| 29 | |
| 30 class BaseTool(object): | |
| 31 """A tool that does nothing.""" | |
| 32 | |
| 33 def __init__(self, *args, **kwargs): | |
| 34 pass | |
| 35 | |
| 36 def GetTestWrapper(self): | |
| 37 """Returns a string that is to be prepended to the test command line.""" | |
| 38 return '' | |
| 39 | |
| 40 def CopyFiles(self): | |
| 41 """Copies tool-specific files to the device, create directories, etc.""" | |
| 42 pass | |
| 43 | |
| 44 def SetupEnvironment(self): | |
| 45 """Sets up the system environment for a test. | |
| 46 | |
| 47 This is a good place to set system properties. | |
| 48 """ | |
| 49 pass | |
| 50 | |
| 51 def CleanUpEnvironment(self): | |
| 52 """Cleans up environment.""" | |
| 53 pass | |
| 54 | |
| 55 def GetTimeoutScale(self): | |
| 56 """Returns a multiplier that should be applied to timeout values.""" | |
| 57 return 1.0 | |
| 58 | |
| 59 def NeedsDebugInfo(self): | |
| 60 """Whether this tool requires debug info. | |
| 61 | |
| 62 Returns True if this tool can not work with stripped binaries. | |
| 63 """ | |
| 64 return False | |
| 65 | |
| 66 | |
| 67 class ValgrindTool(BaseTool): | |
| 68 """Base abstract class for Valgrind tools.""" | |
| 69 | |
| 70 VG_DIR = '/data/local/tmp/valgrind' | |
| 71 VGLOGS_DIR = '/data/local/tmp/vglogs' | |
| 72 | |
| 73 def __init__(self, adb, renderer=False): | |
| 74 self.adb = adb | |
| 75 if renderer: | |
| 76 # exactly 31 chars, SystemProperties::PROP_NAME_MAX | |
| 77 self.wrap_property = 'wrap.com.android.chrome:sandbox' | |
| 78 else: | |
| 79 self.wrap_property = 'wrap.com.android.chrome' | |
| 80 | |
| 81 def CopyFiles(self): | |
| 82 """Copies Valgrind tools to the device.""" | |
| 83 self.adb.RunShellCommand('rm -r %s; mkdir %s' % | |
| 84 (ValgrindTool.VG_DIR, ValgrindTool.VG_DIR)) | |
| 85 self.adb.RunShellCommand('rm -r %s; mkdir %s' % | |
| 86 (ValgrindTool.VGLOGS_DIR, ValgrindTool.VGLOGS_DIR)) | |
| 87 files = self.GetFilesForTool() | |
| 88 for f in files: | |
| 89 self.adb.PushIfNeeded(os.path.join(CHROME_DIR, f), | |
| 90 os.path.join(ValgrindTool.VG_DIR, | |
| 91 os.path.basename(f))) | |
| 92 | |
| 93 def SetupEnvironment(self): | |
| 94 """Sets up device environment.""" | |
| 95 self.adb.RunShellCommand('chmod 777 /data/local/tmp') | |
| 96 self.adb.RunShellCommand('setprop %s "logwrapper %s"' % ( | |
| 97 self.wrap_property, self.GetTestWrapper())) | |
| 98 self.adb.RunShellCommand('setprop chrome.timeout_scale %f' % ( | |
| 99 self.GetTimeoutScale())) | |
| 100 | |
| 101 def CleanUpEnvironment(self): | |
| 102 """Cleans up device environment.""" | |
| 103 self.adb.RunShellCommand('setprop %s ""' % (self.wrap_property,)) | |
| 104 self.adb.RunShellCommand('setprop chrome.timeout_scale ""') | |
| 105 | |
| 106 def GetFilesForTool(self): | |
| 107 """Returns a list of file names for the tool.""" | |
| 108 raise NotImplementedError() | |
| 109 | |
| 110 def NeedsDebugInfo(self): | |
| 111 """Whether this tool requires debug info. | |
| 112 | |
| 113 Returns True if this tool can not work with stripped binaries. | |
| 114 """ | |
| 115 return True | |
| 116 | |
| 117 | |
| 118 class MemcheckTool(ValgrindTool): | |
| 119 """Memcheck tool.""" | |
| 120 | |
| 121 def __init__(self, adb, renderer=False): | |
| 122 super(MemcheckTool, self).__init__(adb, renderer) | |
| 123 | |
| 124 def GetFilesForTool(self): | |
| 125 """Returns a list of file names for the tool.""" | |
| 126 return ['tools/valgrind/android/vg-chrome-wrapper.sh', | |
| 127 'tools/valgrind/memcheck/suppressions.txt', | |
| 128 'tools/valgrind/memcheck/suppressions_android.txt'] | |
| 129 | |
| 130 def GetTestWrapper(self): | |
| 131 """Returns a string that is to be prepended to the test command line.""" | |
| 132 return ValgrindTool.VG_DIR + '/' + 'vg-chrome-wrapper.sh' | |
| 133 | |
| 134 def GetTimeoutScale(self): | |
| 135 """Returns a multiplier that should be applied to timeout values.""" | |
| 136 return 30 | |
| 137 | |
| 138 | |
| 139 class TSanTool(ValgrindTool): | |
| 140 """ThreadSanitizer tool. See http://code.google.com/p/data-race-test .""" | |
| 141 | |
| 142 def __init__(self, adb, renderer=False): | |
| 143 super(TSanTool, self).__init__(adb, renderer) | |
| 144 | |
| 145 def GetFilesForTool(self): | |
| 146 """Returns a list of file names for the tool.""" | |
| 147 return ['tools/valgrind/android/vg-chrome-wrapper-tsan.sh', | |
| 148 'tools/valgrind/tsan/suppressions.txt', | |
| 149 'tools/valgrind/tsan/suppressions_android.txt', | |
| 150 'tools/valgrind/tsan/ignores.txt'] | |
| 151 | |
| 152 def GetTestWrapper(self): | |
| 153 """Returns a string that is to be prepended to the test command line.""" | |
| 154 return ValgrindTool.VG_DIR + '/' + 'vg-chrome-wrapper-tsan.sh' | |
| 155 | |
| 156 def GetTimeoutScale(self): | |
| 157 """Returns a multiplier that should be applied to timeout values.""" | |
| 158 return 30 | |
| 159 | |
| 160 | |
| 161 TOOL_REGISTRY = { | |
| 162 'memcheck': lambda x: MemcheckTool(x, False), | |
| 163 'memcheck-renderer': lambda x: MemcheckTool(x, True), | |
| 164 'tsan': lambda x: TSanTool(x, False), | |
| 165 'tsan-renderer': lambda x: TSanTool(x, True) | |
| 166 } | |
| 167 | |
| 168 | |
| 169 def CreateTool(tool_name, adb): | |
| 170 """Creates a tool with the specified tool name. | |
| 171 | |
| 172 Args: | |
| 173 tool_name: Name of the tool to create. | |
| 174 adb: ADB interface the tool will use. | |
| 175 """ | |
| 176 if not tool_name: | |
| 177 return BaseTool() | |
| 178 | |
| 179 ctor = TOOL_REGISTRY.get(tool_name) | |
| 180 if ctor: | |
| 181 return ctor(adb) | |
| 182 else: | |
| 183 print 'Unknown tool %s, available tools: %s' % ( | |
| 184 tool_name, ', '.join(sorted(TOOL_REGISTRY.keys()))) | |
| 185 sys.exit(1) | |
| OLD | NEW |