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

Side by Side Diff: third_party/lcov/bin/mcov

Issue 57083: lcov-1.7 into third_party for code coverage on POSIX systems.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 8 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/lcov ('k') | third_party/lcov/bin/updateversion.pl » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Name: svn:executable
+ *
OLDNEW
(Empty)
1 #!/usr/bin/perl -w
2 #
3 # mcov: script to convert gcov data to lcov format on Mac.
4 #
5 # Based on lcov (http://ltp.sourceforge.net/coverage/lcov.php)
6 # Written by ajeya at google dot com.
7 #
8 # usage:
9 # mcov --directory <base directory> --output <output file> --verbose <level>
10 #
11
12 use strict;
13
14 use Cwd;
15 use File::Basename;
16 use File::Find;
17 use File::Spec::Functions;
18 use Getopt::Long;
19
20 # function prototypes
21 sub process_dafile(@);
22 sub canonical_path(@);
23 sub split_filename(@);
24 sub read_gcov_header(@);
25 sub read_gcov_file(@);
26
27 # scalars with default values
28 my $directory = Cwd::abs_path(Cwd::getcwd);
29 my $data_file_extension = ".gcda";
30 my $output_filename = "output.lcov";
31 my $gcov_tool = "/usr/bin/gcov";
32 my $verbosity = 0;
33
34 # TODO(ajeya): GetOptions doesn't handle case where the script is called with
35 # no arguments. This needs to be fixed.
36 my $result = GetOptions("directory|d=s" => \$directory,
37 "output|o=s" => \$output_filename,
38 "verbose" => \$verbosity);
39 if (!$result) {
40 print "Usage: $0 --directory <base directory> --output <output file>";
41 print " [--verbose <level>]\n";
42 exit(1);
43 }
44
45 # convert the directory path to absolute path.
46 $directory = Cwd::abs_path($directory);
47
48 # convert the output file path to absolute path.
49 $output_filename = Cwd::abs_path($output_filename);
50
51 # open file for output
52 open(INFO_HANDLE, ">$output_filename");
53
54 my @file_list; # scalar to hold the list of all gcda files.
55 if (-d $directory) {
56 printf("Scanning $directory for $data_file_extension files ...\n");
57 find(sub {
58 my $file = $_;
59 if ($file =~ m/\Q$data_file_extension\E$/i) {
60 push(@file_list, Cwd::abs_path($file));
61 }},
62 $directory);
63 printf("Found %d data files in %s\n", $#file_list + 1, $directory);
64 }
65
66 # Process all files in list
67 foreach my $file (@file_list) {
68 process_dafile($file);
69 }
70 close(INFO_HANDLE);
71
72 # Remove the misc gcov files that are created.
73 my @gcov_list = glob("*.gcov");
74 foreach my $gcov_file (@gcov_list) {
75 unlink($gcov_file);
76 }
77
78 exit(0);
79
80 # end of script
81
82 # process_dafile:
83 # argument(s): a file path with gcda extension
84 # returns: void
85 # This method calls gcov to generate the coverage data and write the output in
86 # lcov format to the output file.
87 sub process_dafile(@) {
88 my ($filename) = @_;
89 print("Processing $filename ...\n");
90
91 my $da_filename; # Name of data file to process
92 my $base_name; # data filename without ".da/.gcda" extension
93 my $gcov_error; # Error code of gcov tool
94 my $object_dir; # Directory containing all object files
95 my $gcov_file; # Name of a .gcov file
96 my @gcov_data; # Contents of a .gcov file
97 my @gcov_list; # List of generated .gcov files
98 my $base_dir; # Base directory for current da file
99 local *OLD_STDOUT; # Handle to store STDOUT temporarily
100
101 # Get directory and basename of data file
102 ($base_dir, $base_name) = split_filename(canonical_path($filename));
103
104 # Check for writable $base_dir (gcov will try to write files there)
105 if (!-w $base_dir) {
106 print("ERROR: cannot write to directory $base_dir\n");
107 return;
108 }
109
110 # Construct name of graph file
111 $da_filename = File::Spec::Functions::catfile($base_dir,
112 join(".", $base_name, "gcno"));
113
114 # Ignore empty graph file (e.g. source file with no statement)
115 if (-z $da_filename) {
116 warn("WARNING: empty $da_filename (skipped)\n");
117 return;
118 }
119
120 # Set $object_dir to real location of object files. This may differ
121 # from $base_dir if the graph file is just a link to the "real" object
122 # file location.
123 $object_dir = dirname($da_filename);
124
125 # Save the current STDOUT to OLD_STDOUT and set STDOUT to /dev/null to mute
126 # standard output.
127 if (!$verbosity) {
128 open(OLD_STDOUT, ">>&STDOUT");
129 open(STDOUT, ">/dev/null");
130 }
131
132 # run gcov utility with the supplied gcno file and object directory.
133 $gcov_error = system($gcov_tool, $da_filename, "-o", $object_dir);
134
135 # Restore STDOUT if we changed it before.
136 if (!$verbosity) {
137 open(STDOUT, ">>&OLD_STDOUT");
138 }
139
140 if ($gcov_error) {
141 warn("WARNING: GCOV failed for $da_filename!\n");
142 return;
143 }
144
145 # Collect data from resulting .gcov files and create .info file
146 @gcov_list = glob("*.gcov");
147 # Check for files
148 if (!scalar(@gcov_list)) {
149 warn("WARNING: gcov did not create any files for $da_filename!\n");
150 }
151
152 foreach $gcov_file (@gcov_list) {
153 my $source_filename = read_gcov_header($gcov_file);
154
155 if (!defined($source_filename)) {
156 next;
157 }
158
159 $source_filename = canonical_path($source_filename);
160
161 # Read in contents of gcov file
162 @gcov_data = read_gcov_file($gcov_file);
163
164 # Skip empty files
165 if (!scalar(@gcov_data)) {
166 warn("WARNING: skipping empty file $gcov_file\n");
167 unlink($gcov_file);
168 next;
169 }
170
171 print(INFO_HANDLE "SF:", Cwd::abs_path($source_filename), "\n");
172
173 # Write coverage information for each instrumented line
174 # Note: @gcov_content contains a list of (flag, count, source)
175 # tuple for each source code line
176 while (@gcov_data) {
177 # Check for instrumented line
178 if ($gcov_data[0]) {
179 print(INFO_HANDLE "DA:", $gcov_data[3], ",", $gcov_data[1], "\n");
180 }
181 # Remove already processed data from array
182 splice(@gcov_data,0,4);
183 }
184 print(INFO_HANDLE "end_of_record\n");
185
186 # Remove .gcov file after processing
187 unlink($gcov_file);
188 } #end for_each
189 }
190
191 # canonical_path:
192 # argument(s): any file path
193 # returns: the file path as a string
194 #
195 # clean up the file path being passed.
196 sub canonical_path(@) {
197 my ($filename) = @_;
198 return (File::Spec::Functions::canonpath($filename));
199 }
200
201 # split_filename:
202 # argument(s): any file path
203 # returns: an array with the path components
204 #
205 # splits the file path into path and filename (with no extension).
206 sub split_filename(@){
207 my ($filename) = @_;
208 my ($base, $path, $ext) = File::Basename::fileparse($filename, '\.[^\.]*');
209 return ($path, $base);
210 }
211
212 # read_gcov_header:
213 # argument(s): path to gcov file
214 # returns: an array the contens of the gcov header.
215 #
216 # reads the gcov file and returns the parsed contents of a gcov header as an
217 # array.
218 sub read_gcov_header(@) {
219 my ($filename) = @_;
220 my $source;
221 local *INPUT;
222
223 if (!open(INPUT, $filename)) {
224 warn("WARNING: cannot read $filename!\n");
225 return (undef,undef);
226 }
227
228 my @lines = <INPUT>;
229 foreach my $line (@lines) {
230 chomp($line);
231 # check for lines with source string.
232 if ($line =~ /^\s+-:\s+0:Source:(.*)$/) {
233 # Source: header entry
234 $source = $1;
235 } else {
236 last;
237 }
238 }
239 close(INPUT);
240 return $source;
241 }
242
243 # read_gcov_file:
244 # argument(s): path to gcov file
245 # returns: an array with the contents of the gcov file.
246 #
247 # reads the gcov file and returns the parsed contents of a gcov file
248 # as an array.
249 sub read_gcov_file(@) {
250 my ($filename) = @_;
251 my @result = ();
252 my $number;
253 local *INPUT;
254
255 ## TODO(ajeya): Exit more gracefully here.
256 open(INPUT, $filename) or die("ERROR: cannot read $filename!\n");
257
258 # Parse gcov output and populate the array
259 my @lines = <INPUT>;
260 foreach my $line (@lines) {
261 chomp($line);
262 if ($line =~ /^\s*([^:]+):\s*(\d+?):(.*)$/) {
263 # <exec count>:<line number>:<source code>
264
265 if ($1 eq "-") {
266 # Uninstrumented line
267 push(@result, 0);
268 push(@result, 0);
269 push(@result, $3);
270 push(@result, $2);
271 } elsif ($2 eq "0") {
272 #ignore comments and other header info
273 } else {
274 # Source code execution data
275 $number = $1;
276 # Check for zero count
277 if ($number eq "#####") {
278 $number = 0;
279 }
280 push(@result, 1);
281 push(@result, $number);
282 push(@result, $3);
283 push(@result, $2);
284 }
285 }
286 }
287 close(INPUT);
288 return @result;
289 }
OLDNEW
« no previous file with comments | « third_party/lcov/bin/lcov ('k') | third_party/lcov/bin/updateversion.pl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698