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