Commit 7122ffd5 authored by jrg@chromium.org's avatar jrg@chromium.org

Code coverage improvements.

Code coverage now works for Linux.  Unit tests to run passed from
project to coverage_posix.py so deps are correct.


Review URL: http://codereview.chromium.org/100189

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15016 0039d316-1c4b-4281-b951-d872f2087c98
parent a92f595d
......@@ -72,16 +72,13 @@
}],
],
}],
# TODO(jrg): complete this work once Linux transitions to gyp.
# This is untested (--> likely doesn't work).
# Linux gyp (into scons) doesn't like target_conditions?
# TODO(???): track down why 'target_conditions' doesn't work
# on Linux gyp into scons like it does on Mac gyp into xcodeproj.
['OS=="linux"', {
'cflags': [ '-ftest-coverage',
'-fprofile-arcs' ],
'target_conditions': [
['_type=="executable"', {
'link_settings': { 'libraries': [ '-lgcov' ] },
}],
],
'link_settings': { 'libraries': [ '-lgcov' ] },
}],
]},
# TODO(jrg): options for code coverage on Windows
......
......@@ -3000,8 +3000,7 @@
]}, # 'targets'
], # OS=="win"
# TODO(jrg): add in Windows code coverage targets.
# Also test on Linux.
['coverage!=0 and OS=="mac"',
['coverage!=0 and OS!="win"',
{ 'targets': [
{
'target_name': 'coverage',
......@@ -3011,16 +3010,26 @@
'type': 'none',
'dependencies': [
'../base/base.gyp:base_unittests',
'../media/media.gyp:media_unittests',
'../net/net.gyp:net_unittests',
'../printing/printing.gyp:printing_unittests',
],
'actions': [
{
# 'message' for Linux/scons in particular
'message': 'Running coverage_posix.py to generate coverage numbers',
'inputs': [],
'outputs': [],
'action_name': 'coverage',
'action': [ 'python',
'../tools/code_coverage/coverage_posix.py',
'--directory',
'<(PRODUCT_DIR)' ],
'<(PRODUCT_DIR)',
'--',
'<@(_dependencies)'],
# Use outputs of this action as inputs for the main target build.
# Seems as a misnomer but makes this happy on Linux (scons).
'process_outputs_as_sources': 1,
},
], # 'actions'
},
......
......@@ -5,30 +5,45 @@
"""Generate and process code coverage on POSIX systems.
Written for and tested on Mac.
Not tested on Linux yet.
Written for and tested on Mac and Linux. To use this script to
generate coverage numbers, please run from within a gyp-generated
project.
All platforms, to set up coverage:
cd ...../chromium ; src/tools/gyp/gyp_dogfood -Dcoverage=1 src/build/all.gyp
Run coverage on...
Mac:
( cd src/chrome ; xcodebuild -configuration Debug -target coverage )
Linux:
( cd src/chrome ; hammer coverage )
# In particular, don't try and run 'coverage' from src/build
--directory=DIR: specify directory that contains gcda files, and where
a "coverage" directory will be created containing the output html.
Example name: ..../chromium/src/xcodebuild/Debug
TODO(jrg): make list of unit tests an arg to this script
--all_unittests: is present, run all files named *_unittests that we
can find.
Strings after all options are considered tests to run. Test names
have all text before a ':' stripped to help with gyp compatibility.
For example, ../base/base.gyp:base_unittests is interpreted as a test
named "base_unittests".
"""
import glob
import logging
import optparse
import os
import shutil
import subprocess
import sys
class Coverage(object):
"""Doitall class for code coverage."""
# Unit test files to run.
UNIT_TESTS = [
'base_unittests',
# 'unit_tests,
]
def __init__(self, directory):
super(Coverage, self).__init__()
self.directory = directory
......@@ -43,6 +58,34 @@ class Coverage(object):
self.genhtml = os.path.join(self.lcov_directory, 'genhtml')
self.coverage_info_file = os.path.join(self.directory, 'coverage.info')
self.ConfirmPlatformAndPaths()
self.tests = []
def FindTests(self, options, args):
"""Find unit tests to run; set self.tests to this list.
Obtain instructions from the command line seen in the provided
parsed options and post-option args.
"""
# Small tests: can be run in the "chromium" directory.
# If asked, run all we can find.
if options.all_unittests:
self.tests += glob.glob(os.path.join(self.directory, '*_unittests'))
# If told explicit tests, run those (after stripping the name as
# appropriate)
for testname in args:
if ':' in testname:
self.tests += [os.path.join(self.directory, testname.split(':')[1])]
else:
self.tests += [os.path.join(self.directory, testname)]
# Needs to be run in the "chrome" directory?
# ut = os.path.join(self.directory, 'unit_tests')
# if os.path.exists(ut):
# self.tests.append(ut)
# Medium tests?
# Not sure all of these work yet (e.g. page_cycler_tests)
# self.tests += glob.glob(os.path.join(self.directory, '*_tests'))
def ConfirmPlatformAndPaths(self):
"""Confirm OS and paths (e.g. lcov)."""
......@@ -70,11 +113,11 @@ class Coverage(object):
subprocess.call([self.lcov,
'--directory', self.directory_parent,
'--zerocounters'])
shutil.rmtree(os.path.join(self.directory, 'coverage'))
def RunTests(self):
"""Run all unit tests."""
for test in self.UNIT_TESTS:
fulltest = os.path.join(self.directory, test)
for fulltest in self.tests:
if not os.path.exists(fulltest):
logging.fatal(fulltest + ' does not exist')
# TODO(jrg): add timeout?
......@@ -113,12 +156,18 @@ def main():
dest='directory',
default=None,
help='Directory of unit test files')
parser.add_option('-a',
'--all_unittests',
dest='all_unittests',
default=False,
help='Run all tests we can find (*_unittests)')
(options, args) = parser.parse_args()
if not options.directory:
parser.error('Directory not specified')
coverage = Coverage(options.directory)
coverage.ClearData()
coverage.FindTests(options, args)
coverage.RunTests()
coverage.GenerateOutput()
return 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment