| 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 |