Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(175)

Side by Side Diff: tools/code_coverage/coverage_posix.py

Issue 118298: Add unit_tests (Chrome browser unit tests) to Mac/Linux coverage.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/lcov/bin/mcov ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 on POSIX systems. 6 """Generate and process code coverage on POSIX systems.
7 7
8 Written for and tested on Mac and Linux. To use this script to 8 Written for and tested on Mac and Linux. To use this script to
9 generate coverage numbers, please run from within a gyp-generated 9 generate coverage numbers, please run from within a gyp-generated
10 project. 10 project.
11 11
12 All platforms, to set up coverage: 12 All platforms, to set up coverage:
13 cd ...../chromium ; src/tools/gyp/gyp_dogfood -Dcoverage=1 src/build/all.gyp 13 cd ...../chromium ; src/tools/gyp/gyp_dogfood -Dcoverage=1 src/build/all.gyp
14 14
15 Run coverage on... 15 Run coverage on...
16 Mac: 16 Mac:
17 ( cd src/chrome ; xcodebuild -configuration Debug -target coverage ) 17 ( cd src/chrome ; xcodebuild -configuration Debug -target coverage )
18 Linux: 18 Linux:
19 ( cd src/chrome ; hammer coverage ) 19 ( cd src/chrome ; hammer coverage )
20 # In particular, don't try and run 'coverage' from src/build 20 # In particular, don't try and run 'coverage' from src/build
21 21
22 22
23 --directory=DIR: specify directory that contains gcda files, and where 23 --directory=DIR: specify directory that contains gcda files, and where
24 a "coverage" directory will be created containing the output html. 24 a "coverage" directory will be created containing the output html.
25 Example name: ..../chromium/src/xcodebuild/Debug 25 Example name: ..../chromium/src/xcodebuild/Debug
26 26
27 --all_unittests: is present, run all files named *_unittests that we 27 --genhtml: generate html output. If not specified only lcov is generated.
28
29 --all_unittests: if present, run all files named *_unittests that we
28 can find. 30 can find.
29 31
32 --fast_test: make the tests run real fast (just for testing)
33
30 Strings after all options are considered tests to run. Test names 34 Strings after all options are considered tests to run. Test names
31 have all text before a ':' stripped to help with gyp compatibility. 35 have all text before a ':' stripped to help with gyp compatibility.
32 For example, ../base/base.gyp:base_unittests is interpreted as a test 36 For example, ../base/base.gyp:base_unittests is interpreted as a test
33 named "base_unittests". 37 named "base_unittests".
34 """ 38 """
35 39
36 import glob 40 import glob
37 import logging 41 import logging
38 import optparse 42 import optparse
39 import os 43 import os
40 import shutil 44 import shutil
41 import subprocess 45 import subprocess
42 import sys 46 import sys
43 47
44 class Coverage(object): 48 class Coverage(object):
45 """Doitall class for code coverage.""" 49 """Doitall class for code coverage."""
46 50
47 def __init__(self, directory): 51 def __init__(self, directory, options, args):
48 super(Coverage, self).__init__() 52 super(Coverage, self).__init__()
49 self.directory = directory 53 self.directory = directory
54 self.options = options
55 self.args = args
50 self.directory_parent = os.path.dirname(self.directory) 56 self.directory_parent = os.path.dirname(self.directory)
51 self.output_directory = os.path.join(self.directory, 'coverage') 57 self.output_directory = os.path.join(self.directory, 'coverage')
52 if not os.path.exists(self.output_directory): 58 if not os.path.exists(self.output_directory):
53 os.mkdir(self.output_directory) 59 os.mkdir(self.output_directory)
54 self.lcov_directory = os.path.join(sys.path[0], 60 self.lcov_directory = os.path.join(sys.path[0],
55 '../../third_party/lcov/bin') 61 '../../third_party/lcov/bin')
56 self.lcov = os.path.join(self.lcov_directory, 'lcov') 62 self.lcov = os.path.join(self.lcov_directory, 'lcov')
57 self.mcov = os.path.join(self.lcov_directory, 'mcov') 63 self.mcov = os.path.join(self.lcov_directory, 'mcov')
58 self.genhtml = os.path.join(self.lcov_directory, 'genhtml') 64 self.genhtml = os.path.join(self.lcov_directory, 'genhtml')
59 self.coverage_info_file = os.path.join(self.directory, 'coverage.info') 65 self.coverage_info_file = os.path.join(self.directory, 'coverage.info')
60 self.ConfirmPlatformAndPaths() 66 self.ConfirmPlatformAndPaths()
61 self.tests = [] 67 self.tests = []
62 68
63 def FindTests(self, options, args): 69 def FindTests(self):
64 """Find unit tests to run; set self.tests to this list. 70 """Find unit tests to run; set self.tests to this list.
65 71
66 Obtain instructions from the command line seen in the provided 72 Assume all non-option items in the arg list are tests to be run.
67 parsed options and post-option args.
68 """ 73 """
69 # Small tests: can be run in the "chromium" directory. 74 # Small tests: can be run in the "chromium" directory.
70 # If asked, run all we can find. 75 # If asked, run all we can find.
71 if options.all_unittests: 76 if self.options.all_unittests:
72 self.tests += glob.glob(os.path.join(self.directory, '*_unittests')) 77 self.tests += glob.glob(os.path.join(self.directory, '*_unittests'))
73 78
74 # If told explicit tests, run those (after stripping the name as 79 # If told explicit tests, run those (after stripping the name as
75 # appropriate) 80 # appropriate)
76 for testname in args: 81 for testname in self.args:
77 if ':' in testname: 82 if ':' in testname:
78 self.tests += [os.path.join(self.directory, testname.split(':')[1])] 83 self.tests += [os.path.join(self.directory, testname.split(':')[1])]
79 else: 84 else:
80 self.tests += [os.path.join(self.directory, testname)] 85 self.tests += [os.path.join(self.directory, testname)]
81 86
82 # Needs to be run in the "chrome" directory? 87 # Needs to be run in the "chrome" directory?
83 # ut = os.path.join(self.directory, 'unit_tests') 88 # ut = os.path.join(self.directory, 'unit_tests')
84 # if os.path.exists(ut): 89 # if os.path.exists(ut):
85 # self.tests.append(ut) 90 # self.tests.append(ut)
86 # Medium tests? 91 # Medium tests?
87 # Not sure all of these work yet (e.g. page_cycler_tests) 92 # Not sure all of these work yet (e.g. page_cycler_tests)
88 # self.tests += glob.glob(os.path.join(self.directory, '*_tests')) 93 # self.tests += glob.glob(os.path.join(self.directory, '*_tests'))
89 94
90 def ConfirmPlatformAndPaths(self): 95 def ConfirmPlatformAndPaths(self):
91 """Confirm OS and paths (e.g. lcov).""" 96 """Confirm OS and paths (e.g. lcov)."""
92 if not self.IsPosix(): 97 if not self.IsPosix():
93 logging.fatal('Not posix.') 98 logging.fatal('Not posix.')
99 sys.exit(1)
94 programs = [self.lcov, self.genhtml] 100 programs = [self.lcov, self.genhtml]
95 if self.IsMac(): 101 if self.IsMac():
96 programs.append(self.mcov) 102 programs.append(self.mcov)
97 for program in programs: 103 for program in programs:
98 if not os.path.exists(program): 104 if not os.path.exists(program):
99 logging.fatal('lcov program missing: ' + program) 105 logging.fatal('lcov program missing: ' + program)
106 sys.exit(1)
100 107
101 def IsPosix(self): 108 def IsPosix(self):
102 """Return True if we are POSIX.""" 109 """Return True if we are POSIX."""
103 return self.IsMac() or self.IsLinux() 110 return self.IsMac() or self.IsLinux()
104 111
105 def IsMac(self): 112 def IsMac(self):
106 return sys.platform == 'darwin' 113 return sys.platform == 'darwin'
107 114
108 def IsLinux(self): 115 def IsLinux(self):
109 return sys.platform == 'linux2' 116 return sys.platform == 'linux2'
110 117
111 def ClearData(self): 118 def ClearData(self):
112 """Clear old gcda files""" 119 """Clear old gcda files"""
113 subprocess.call([self.lcov, 120 subprocess.call([self.lcov,
114 '--directory', self.directory_parent, 121 '--directory', self.directory_parent,
115 '--zerocounters']) 122 '--zerocounters'])
116 shutil.rmtree(os.path.join(self.directory, 'coverage')) 123 shutil.rmtree(os.path.join(self.directory, 'coverage'))
117 124
118 def RunTests(self): 125 def RunTests(self):
119 """Run all unit tests.""" 126 """Run all unit tests."""
120 for fulltest in self.tests: 127 for fulltest in self.tests:
121 if not os.path.exists(fulltest): 128 if not os.path.exists(fulltest):
122 logging.fatal(fulltest + ' does not exist') 129 logging.fatal(fulltest + ' does not exist')
130 sys.exit(2)
123 # TODO(jrg): add timeout? 131 # TODO(jrg): add timeout?
124 # TODO(jrg): check return value and choke if it failed? 132 print >>sys.stderr, 'Running test: ' + fulltest
125 # TODO(jrg): add --gtest_print_time like as run from XCode? 133 cmdlist = [fulltest, '--gtest_print_time']
126 print 'Running test: ' + fulltest
127 # subprocess.call([fulltest, '--gtest_filter=TupleTest*']) # quick check
128 subprocess.call([fulltest])
129 134
130 def GenerateOutput(self): 135 # If asked, make this REAL fast for testing.
131 """Convert profile data to html.""" 136 if self.options.fast_test:
137 cmdlist.append('--gtest_filter=TupleTest*')
138
139 retcode = subprocess.call(cmdlist)
140 if retcode:
141 logging.fatal('COVERAGE: test %s failed; return code: %d' %
142 (fulltest, retcode))
143 sys.exit(retcode)
144
145 def GenerateLcov(self):
146 """Convert profile data to lcov."""
132 if self.IsLinux(): 147 if self.IsLinux():
133 command = [self.lcov, 148 command = [self.lcov,
134 '--directory', self.directory, 149 '--directory', self.directory,
135 '--capture', 150 '--capture',
136 '--output-file', 151 '--output-file',
137 self.coverage_info_file] 152 self.coverage_info_file]
138 else: 153 else:
139 command = [self.mcov, 154 command = [self.mcov,
140 '--directory', self.directory_parent, 155 '--directory', self.directory_parent,
141 '--output', self.coverage_info_file] 156 '--output', self.coverage_info_file]
142 print 'Assembly command: ' + ' '.join(command) 157 print >>sys.stderr, 'Assembly command: ' + ' '.join(command)
143 subprocess.call(command) 158 retcode = subprocess.call(command)
159 if retcode:
160 logging.fatal('COVERAGE: %s failed; return code: %d' %
161 (command[0], retcode))
162 sys.exit(retcode)
144 163
164 def GenerateHtml(self):
165 """Convert lcov to html."""
166 # TODO(jrg): This isn't happy when run with unit_tests since V8 has a
167 # different "base" so V8 includes can't be found in ".". Fix.
145 command = [self.genhtml, 168 command = [self.genhtml,
146 self.coverage_info_file, 169 self.coverage_info_file,
147 '--output-directory', 170 '--output-directory',
148 self.output_directory] 171 self.output_directory]
149 print 'html generation command: ' + ' '.join(command) 172 print >>sys.stderr, 'html generation command: ' + ' '.join(command)
150 subprocess.call(command) 173 retcode = subprocess.call(command)
174 if retcode:
175 logging.fatal('COVERAGE: %s failed; return code: %d' %
176 (command[0], retcode))
177 sys.exit(retcode)
151 178
152 def main(): 179 def main():
180 # Print out the args to help someone do it by hand if needed
181 print >>sys.stderr, sys.argv
182
153 parser = optparse.OptionParser() 183 parser = optparse.OptionParser()
154 parser.add_option('-d', 184 parser.add_option('-d',
155 '--directory', 185 '--directory',
156 dest='directory', 186 dest='directory',
157 default=None, 187 default=None,
158 help='Directory of unit test files') 188 help='Directory of unit test files')
159 parser.add_option('-a', 189 parser.add_option('-a',
160 '--all_unittests', 190 '--all_unittests',
161 dest='all_unittests', 191 dest='all_unittests',
162 default=False, 192 default=False,
163 help='Run all tests we can find (*_unittests)') 193 help='Run all tests we can find (*_unittests)')
194 parser.add_option('-g',
195 '--genhtml',
196 dest='genhtml',
197 default=False,
198 help='Generate html from lcov output')
199 parser.add_option('-f',
200 '--fast_test',
201 dest='fast_test',
202 default=False,
203 help='Make the tests run REAL fast by doing little.')
164 (options, args) = parser.parse_args() 204 (options, args) = parser.parse_args()
165 if not options.directory: 205 if not options.directory:
166 parser.error('Directory not specified') 206 parser.error('Directory not specified')
167 207 coverage = Coverage(options.directory, options, args)
168 coverage = Coverage(options.directory)
169 coverage.ClearData() 208 coverage.ClearData()
170 coverage.FindTests(options, args) 209 coverage.FindTests()
171 coverage.RunTests() 210 coverage.RunTests()
172 coverage.GenerateOutput() 211 coverage.GenerateLcov()
212 if options.genhtml:
213 coverage.GenerateHtml()
173 return 0 214 return 0
174 215
175 216
176 if __name__ == '__main__': 217 if __name__ == '__main__':
177 sys.exit(main()) 218 sys.exit(main())
OLDNEW
« no previous file with comments | « third_party/lcov/bin/mcov ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698