OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2009 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2009 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 """Generate and process code coverage. | 6 """Generate and process code coverage. |
7 | 7 |
8 TODO(jrg): rename this from coverage_posix.py to coverage_all.py! | 8 TODO(jrg): rename this from coverage_posix.py to coverage_all.py! |
9 | 9 |
10 Written for and tested on Mac, Linux, and Windows. To use this script | 10 Written for and tested on Mac, Linux, and Windows. To use this script |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 import glob | 54 import glob |
55 import logging | 55 import logging |
56 import optparse | 56 import optparse |
57 import os | 57 import os |
58 import shutil | 58 import shutil |
59 import subprocess | 59 import subprocess |
60 import sys | 60 import sys |
61 import time | 61 import time |
62 import traceback | 62 import traceback |
63 | 63 |
| 64 |
64 class Coverage(object): | 65 class Coverage(object): |
65 """Doitall class for code coverage.""" | 66 """Doitall class for code coverage.""" |
66 | 67 |
67 def __init__(self, directory, options, args): | 68 def __init__(self, directory, options, args): |
68 super(Coverage, self).__init__() | 69 super(Coverage, self).__init__() |
69 logging.basicConfig(level=logging.DEBUG) | 70 logging.basicConfig(level=logging.DEBUG) |
70 self.directory = directory | 71 self.directory = directory |
71 self.options = options | 72 self.options = options |
72 self.args = args | 73 self.args = args |
73 self.directory_parent = os.path.dirname(self.directory) | 74 self.directory_parent = os.path.dirname(self.directory) |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 inclusion = ['unit_tests'] | 160 inclusion = ['unit_tests'] |
160 keep = [] | 161 keep = [] |
161 for test in self.tests: | 162 for test in self.tests: |
162 for i in inclusion: | 163 for i in inclusion: |
163 if i in test: | 164 if i in test: |
164 keep.append(test) | 165 keep.append(test) |
165 self.tests = keep | 166 self.tests = keep |
166 logging.info('After trimming tests we have ' + ' '.join(self.tests)) | 167 logging.info('After trimming tests we have ' + ' '.join(self.tests)) |
167 return | 168 return |
168 if self.IsLinux(): | 169 if self.IsLinux(): |
| 170 # self.tests = filter(lambda t: t.endswith('base_unittests'), self.tests) |
169 return | 171 return |
170 if self.IsMac(): | 172 if self.IsMac(): |
171 exclusion = ['automated_ui_tests'] | 173 exclusion = ['automated_ui_tests'] |
172 punted = [] | 174 punted = [] |
173 for test in self.tests: | 175 for test in self.tests: |
174 for e in exclusion: | 176 for e in exclusion: |
175 if test.endswith(e): | 177 if test.endswith(e): |
176 punted.append(test) | 178 punted.append(test) |
177 self.tests = filter(lambda t: t not in punted, self.tests) | 179 self.tests = filter(lambda t: t not in punted, self.tests) |
178 if punted: | 180 if punted: |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 if not os.path.exists(fulltest): | 255 if not os.path.exists(fulltest): |
254 logging.info(fulltest + ' does not exist') | 256 logging.info(fulltest + ' does not exist') |
255 if self.options.strict: | 257 if self.options.strict: |
256 sys.exit(2) | 258 sys.exit(2) |
257 else: | 259 else: |
258 logging.info('%s path exists' % fulltest) | 260 logging.info('%s path exists' % fulltest) |
259 cmdlist = [fulltest, '--gtest_print_time'] | 261 cmdlist = [fulltest, '--gtest_print_time'] |
260 | 262 |
261 # If asked, make this REAL fast for testing. | 263 # If asked, make this REAL fast for testing. |
262 if self.options.fast_test: | 264 if self.options.fast_test: |
| 265 logging.info('Running as a FAST test for testing') |
263 # cmdlist.append('--gtest_filter=RenderWidgetHost*') | 266 # cmdlist.append('--gtest_filter=RenderWidgetHost*') |
264 cmdlist.append('--gtest_filter=CommandLine*') | 267 # cmdlist.append('--gtest_filter=CommandLine*') |
| 268 cmdlist.append('--gtest_filter=C*') |
265 | 269 |
266 self.BeforeRunOneTest(fulltest) | 270 self.BeforeRunOneTest(fulltest) |
267 logging.info('Running test ' + str(cmdlist)) | 271 logging.info('Running test ' + str(cmdlist)) |
268 try: | 272 try: |
269 retcode = subprocess.call(cmdlist) | 273 retcode = subprocess.call(cmdlist) |
270 except: # can't "except WindowsError" since script runs on non-Windows | 274 except: # can't "except WindowsError" since script runs on non-Windows |
271 logging.info('EXCEPTION while running a unit test') | 275 logging.info('EXCEPTION while running a unit test') |
272 logging.info(traceback.format_exc()) | 276 logging.info(traceback.format_exc()) |
273 retcode = 999 | 277 retcode = 999 |
274 self.AfterRunOneTest(fulltest) | 278 self.AfterRunOneTest(fulltest) |
(...skipping 13 matching lines...) Expand all Loading... |
288 # Stop counters | 292 # Stop counters |
289 cmdlist = [self.perf, '-shutdown'] | 293 cmdlist = [self.perf, '-shutdown'] |
290 self.Run(cmdlist) | 294 self.Run(cmdlist) |
291 full_output = self.vsts_output + '.coverage' | 295 full_output = self.vsts_output + '.coverage' |
292 shutil.move(full_output, self.vsts_output) | 296 shutil.move(full_output, self.vsts_output) |
293 # generate lcov! | 297 # generate lcov! |
294 self.GenerateLcovWindows(testname) | 298 self.GenerateLcovWindows(testname) |
295 | 299 |
296 def AfterRunAllTests(self): | 300 def AfterRunAllTests(self): |
297 """Do things right after running ALL tests.""" | 301 """Do things right after running ALL tests.""" |
| 302 # On POSIX we can do it all at once without running out of memory. |
| 303 # This contrasts with Windows where we must do it after each test. |
298 if self.IsPosix(): | 304 if self.IsPosix(): |
299 # On POSIX we can do it all at once without running out of memory. | |
300 self.GenerateLcovPosix() | 305 self.GenerateLcovPosix() |
| 306 # Only on Linux do we have the Xvfb step. |
301 if self.IsLinux() and self.options.xvfb: | 307 if self.IsLinux() and self.options.xvfb: |
302 self.StopXvfb() | 308 self.StopXvfb() |
303 | 309 |
304 def StartXvfb(self): | 310 def StartXvfb(self): |
305 """Start Xvfb and set an appropriate DISPLAY environment. Linux only. | 311 """Start Xvfb and set an appropriate DISPLAY environment. Linux only. |
306 | 312 |
307 Copied from http://src.chromium.org/viewvc/chrome/trunk/tools/buildbot/ | 313 Copied from http://src.chromium.org/viewvc/chrome/trunk/tools/buildbot/ |
308 scripts/slave/slave_utils.py?view=markup | 314 scripts/slave/slave_utils.py?view=markup |
309 with some simplifications (e.g. no need to use xdisplaycheck, save | 315 with some simplifications (e.g. no need to use xdisplaycheck, save |
310 pid in var not file, etc) | 316 pid in var not file, etc) |
(...skipping 26 matching lines...) Expand all Loading... |
337 logging.info('Xvfb: killing') | 343 logging.info('Xvfb: killing') |
338 try: | 344 try: |
339 os.kill(self.xvfb_pid, signal.SIGKILL) | 345 os.kill(self.xvfb_pid, signal.SIGKILL) |
340 except: | 346 except: |
341 pass | 347 pass |
342 del os.environ['DISPLAY'] | 348 del os.environ['DISPLAY'] |
343 self.xvfb_pid = 0 | 349 self.xvfb_pid = 0 |
344 | 350 |
345 | 351 |
346 def GenerateLcovPosix(self): | 352 def GenerateLcovPosix(self): |
347 """Convert profile data to lcov.""" | 353 """Convert profile data to lcov on Mac or Linux.""" |
| 354 if self.IsLinux(): |
| 355 # With Linux/make the current directory for this command is |
| 356 # .../src/chrome but we need to be in .../src for the relative |
| 357 # path of source files to be correct. On Mac source files are |
| 358 # compiled with abs paths so this isn't a problem. |
| 359 start_dir = os.getcwd() |
| 360 os.chdir('..') |
348 command = [self.mcov, | 361 command = [self.mcov, |
349 '--directory', self.directory_parent, | 362 '--directory', self.directory_parent, |
350 '--output', self.coverage_info_file] | 363 '--output', self.coverage_info_file] |
351 print >>sys.stderr, 'Assembly command: ' + ' '.join(command) | 364 logging.info('Assembly command: ' + ' '.join(command)) |
352 retcode = subprocess.call(command) | 365 retcode = subprocess.call(command) |
353 if retcode: | 366 if retcode: |
354 logging.fatal('COVERAGE: %s failed; return code: %d' % | 367 logging.fatal('COVERAGE: %s failed; return code: %d' % |
355 (command[0], retcode)) | 368 (command[0], retcode)) |
356 if self.options.strict: | 369 if self.options.strict: |
357 sys.exit(retcode) | 370 sys.exit(retcode) |
| 371 if self.IsLinux(): |
| 372 os.chdir(start_dir) |
358 | 373 |
359 def GenerateLcovWindows(self, testname=None): | 374 def GenerateLcovWindows(self, testname=None): |
360 """Convert VSTS format to lcov. Appends coverage data to sum file.""" | 375 """Convert VSTS format to lcov. Appends coverage data to sum file.""" |
361 lcov_file = self.vsts_output + '.lcov' | 376 lcov_file = self.vsts_output + '.lcov' |
362 if os.path.exists(lcov_file): | 377 if os.path.exists(lcov_file): |
363 os.remove(lcov_file) | 378 os.remove(lcov_file) |
364 # generates the file (self.vsts_output + ".lcov") | 379 # generates the file (self.vsts_output + ".lcov") |
365 | 380 |
366 cmdlist = [self.analyzer, | 381 cmdlist = [self.analyzer, |
367 '-sym_path=' + self.directory, | 382 '-sym_path=' + self.directory, |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
455 if options.trim: | 470 if options.trim: |
456 coverage.TrimTests() | 471 coverage.TrimTests() |
457 coverage.RunTests() | 472 coverage.RunTests() |
458 if options.genhtml: | 473 if options.genhtml: |
459 coverage.GenerateHtml() | 474 coverage.GenerateHtml() |
460 return 0 | 475 return 0 |
461 | 476 |
462 | 477 |
463 if __name__ == '__main__': | 478 if __name__ == '__main__': |
464 sys.exit(main()) | 479 sys.exit(main()) |
OLD | NEW |