OLD | NEW |
---|---|
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 # purify_test.py | 6 # purify_test.py |
7 | 7 |
8 '''Runs an exe through Valgrind and puts the intermediate files in a | 8 '''Runs an exe through Valgrind and puts the intermediate files in a |
9 directory. | 9 directory. |
10 ''' | 10 ''' |
11 | 11 |
12 import datetime | 12 import datetime |
13 import glob | 13 import glob |
14 import logging | 14 import logging |
15 import optparse | 15 import optparse |
16 import os | 16 import os |
17 import re | |
17 import shutil | 18 import shutil |
18 import stat | 19 import stat |
19 import sys | 20 import sys |
20 import tempfile | 21 import tempfile |
21 | 22 |
22 import common | 23 import common |
23 | 24 |
24 import valgrind_analyze | 25 import valgrind_analyze |
25 | 26 |
26 import google.logging_utils | 27 import google.logging_utils |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
93 if self._options.verbose: | 94 if self._options.verbose: |
94 google.logging_utils.config_root(logging.DEBUG) | 95 google.logging_utils.config_root(logging.DEBUG) |
95 else: | 96 else: |
96 google.logging_utils.config_root() | 97 google.logging_utils.config_root() |
97 | 98 |
98 return True | 99 return True |
99 | 100 |
100 def Setup(self): | 101 def Setup(self): |
101 return self.ParseArgv() | 102 return self.ParseArgv() |
102 | 103 |
104 def PrepareForTest(self): | |
105 """Perform necessary tasks prior to executing the test.""" | |
106 pass | |
107 | |
103 def ValgrindCommand(self): | 108 def ValgrindCommand(self): |
104 """Get the valgrind command to run.""" | 109 """Get the valgrind command to run.""" |
105 raise RuntimeError, "Never use Valgrind directly. Always subclass and " \ | 110 raise RuntimeError, "Never use Valgrind directly. Always subclass and " \ |
106 "implement ValgrindCommand() at least" | 111 "implement ValgrindCommand() at least" |
107 | 112 |
108 def Execute(self): | 113 def Execute(self): |
109 ''' Execute the app to be tested after successful instrumentation. | 114 ''' Execute the app to be tested after successful instrumentation. |
110 Full execution command-line provided by subclassers via proc.''' | 115 Full execution command-line provided by subclassers via proc.''' |
111 logging.info("starting execution...") | 116 logging.info("starting execution...") |
112 | 117 |
(...skipping 16 matching lines...) Expand all Loading... | |
129 analyzer = valgrind_analyze.ValgrindAnalyze(self._source_dir, filenames, sel f._options.show_all_leaks) | 134 analyzer = valgrind_analyze.ValgrindAnalyze(self._source_dir, filenames, sel f._options.show_all_leaks) |
130 return analyzer.Report() | 135 return analyzer.Report() |
131 | 136 |
132 def Cleanup(self): | 137 def Cleanup(self): |
133 # Right now, we can cleanup by deleting our temporary directory. Other | 138 # Right now, we can cleanup by deleting our temporary directory. Other |
134 # cleanup is still a TODO? | 139 # cleanup is still a TODO? |
135 shutil.rmtree(self.TMP_DIR) | 140 shutil.rmtree(self.TMP_DIR) |
136 return True | 141 return True |
137 | 142 |
138 def RunTestsAndAnalyze(self): | 143 def RunTestsAndAnalyze(self): |
144 self.PrepareForTest() | |
145 | |
139 self.Execute() | 146 self.Execute() |
140 if self._generate_suppressions: | 147 if self._generate_suppressions: |
141 logging.info("Skipping analysis to let you look at the raw output...") | 148 logging.info("Skipping analysis to let you look at the raw output...") |
142 return 0 | 149 return 0 |
143 | 150 |
144 retcode = self.Analyze() | 151 retcode = self.Analyze() |
145 if retcode: | 152 if retcode: |
146 logging.error("Analyze failed.") | 153 logging.error("Analyze failed.") |
147 return retcode | 154 return retcode |
148 logging.info("Execution and analysis completed successfully.") | 155 logging.info("Execution and analysis completed successfully.") |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
233 class ValgrindMac(Valgrind): | 240 class ValgrindMac(Valgrind): |
234 | 241 |
235 """Valgrind on Mac OS X. | 242 """Valgrind on Mac OS X. |
236 | 243 |
237 Valgrind on OS X does not support suppressions (yet). | 244 Valgrind on OS X does not support suppressions (yet). |
238 """ | 245 """ |
239 | 246 |
240 def __init__(self): | 247 def __init__(self): |
241 Valgrind.__init__(self) | 248 Valgrind.__init__(self) |
242 | 249 |
250 def PrepareForTest(self): | |
251 """Runs dsymutil if needed. | |
252 | |
253 Valgrind for Mac OS X requires that debugging information be in a .dSYM | |
254 bundle generated by dsymutil. It is not currently able to chase DWARF | |
255 data into .o files like gdb does, so executables without .dSYM bundles or | |
256 with the Chromium-specific "fake_dsym" bundles generated by | |
257 build/mac/strip_save_dsym won't give source file and line number | |
258 information in valgrind. | |
259 | |
260 This function will run dsymutil if the .dSYM bundle is missing or if | |
261 it looks like a fake_dsym. A non-fake dsym that already exists is assumed | |
262 to be up-to-date. | |
263 """ | |
264 | |
265 test_command = self._args[0] | |
266 dsym_bundle = self._args[0] + '.dSYM' | |
267 dsym_file = os.path.join(dsym_bundle, 'Contents', 'Resources', 'DWARF', | |
268 os.path.basename(test_command)) | |
269 dsym_info_plist = os.path.join(dsym_bundle, 'Contents', 'Info.plist') | |
270 | |
271 needs_dsymutil = True | |
272 saved_test_command = None | |
273 | |
274 if os.path.exists(dsym_file) and os.path.exists(dsym_info_plist): | |
275 # Look for the special fake_dsym tag in dsym_info_plist. | |
276 dsym_info_plist_contents = open(dsym_info_plist).read() | |
277 | |
278 if not re.search('^\s*<key>fake_dsym</key>$', dsym_info_plist_contents, | |
279 re.MULTILINE): | |
280 # fake_dsym is not set, this is a real .dSYM bundle produced by | |
281 # dsymutil. dsymutil does not need to be run again. | |
282 needs_dsymutil = False | |
283 else: | |
284 # fake_dsym is set. dsym_file is a copy of the original test_command | |
285 # before it was stripped. Copy it back to test_command so that | |
286 # dsymutil has unstripped input to work with. Move the stripped | |
287 # test_command out of the way, it will be restored when this is | |
288 # done. | |
289 saved_test_command = test_command + '.stripped' | |
290 os.rename(test_command, saved_test_command) | |
291 shutil.copyfile(dsym_file, test_command) | |
292 | |
293 if needs_dsymutil: | |
294 # Remove the .dSYM bundle if it exists. | |
295 shutil.rmtree(dsym_bundle, True) | |
296 | |
297 dsymutil_command = ['dsymutil', test_command] | |
298 | |
299 # dsymutil is crazy slow. Let it run for up to a half hour. I hope | |
300 # that's enough. | |
301 common.RunSubprocess(dsymutil_command, 30 * 60) | |
302 | |
303 if saved_test_command: | |
304 os.rename(saved_test_command, test_command) | |
TVL
2009/03/27 20:04:31
do you want an exception handler on any of this to
| |
305 | |
243 def ValgrindCommand(self): | 306 def ValgrindCommand(self): |
244 """Get the valgrind command to run.""" | 307 """Get the valgrind command to run.""" |
245 proc = ["valgrind", "--smc-check=all", "--leak-check=full", | 308 proc = ["valgrind", "--smc-check=all", "--leak-check=full", |
246 "--num-callers=30"] | 309 "--num-callers=30"] |
247 | 310 |
248 if self._options.show_all_leaks: | 311 if self._options.show_all_leaks: |
249 proc += ["--show-reachable=yes"]; | 312 proc += ["--show-reachable=yes"]; |
250 | 313 |
251 # Either generate suppressions or load them. | 314 # Either generate suppressions or load them. |
252 # TODO(nirnimesh): Enable when Analyze() is implemented | 315 # TODO(nirnimesh): Enable when Analyze() is implemented |
(...skipping 28 matching lines...) Expand all Loading... | |
281 valgrind = ValgrindMac() | 344 valgrind = ValgrindMac() |
282 retcode = valgrind.Main() | 345 retcode = valgrind.Main() |
283 sys.exit(retcode) | 346 sys.exit(retcode) |
284 elif sys.platform == 'linux2': # Linux | 347 elif sys.platform == 'linux2': # Linux |
285 valgrind = ValgrindLinux() | 348 valgrind = ValgrindLinux() |
286 retcode = valgrind.Main() | 349 retcode = valgrind.Main() |
287 sys.exit(retcode) | 350 sys.exit(retcode) |
288 else: | 351 else: |
289 logging.error("Unknown platform: %s" % sys.platform) | 352 logging.error("Unknown platform: %s" % sys.platform) |
290 sys.exit(1) | 353 sys.exit(1) |
OLD | NEW |