1 : // Copyright 2012 Google Inc.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : //
15 : // Declares LcovWriter, a utility class for accumulating LineInfo with
16 : // file and line centric indexing, and eventually outputting said data as
17 : // GNU coverage (gcov) and LCOV (Linux Test Project GNU Coverage Extensions)
18 : // compatible .lcov files.
19 : //
20 : // We only support the minimum subset of LCOV that is used by Chromium code
21 : // coverage report generating tool, croc. Namely, the DA, LF and LH tags.
22 :
23 : #ifndef SYZYGY_GRINDER_LCOV_WRITER_H_
24 : #define SYZYGY_GRINDER_LCOV_WRITER_H_
25 :
26 : // There is no single document defining the LCOV file format so we summarize
27 : // it here. The information has been taken from LCOV source code and manpages
28 : // and collected here.
29 : //
30 : // An LCOV file is a plain-text ASCII file. Each line begins with a tag (in
31 : // all capital letters, to be discussed below) immediately followed by a
32 : // colon. Following each tag is an arbitrary amount of whitespace (may be none)
33 : // and then the tag data, the format of which depends on the tag type.
34 : //
35 : // The following tags are header tags and may be present only once at the
36 : // beginning of a file:
37 : //
38 : // TN: <name of test>
39 : // TD: <textual description of test>
40 : //
41 : // Following the header there are multiple records, one per source file for
42 : // which coverage results are present. Each record starts with the tag:
43 : //
44 : // SF: <full path to source file>
45 : //
46 : // Each instrumented line of text is indicated using the tag:
47 : //
48 : // DA: <line number>, <execution count>
49 : //
50 : // A line that is instrumented but not executed should be indicated with an
51 : // execution count of 0. A line that is not instrumented should have no DA
52 : // record.
53 : //
54 : // Optionally, a record may specify function information using the following
55 : // tags:
56 : //
57 : // FN: <line number of start of function>, <function name>
58 : // FNDA: <call count>, <function name>
59 : //
60 : // Again, FN* records should not be specified for functions that are not
61 : // instrumented.
62 : //
63 : // Optionally, branch coverage may be specified. For each instrumented branch
64 : // point in the code information is recorded using the following tag:
65 : //
66 : // BA: <line number>, <branch coverage value>
67 : //
68 : // where <branch coverage value> is one of:
69 : //
70 : // 0 - branch not executed.
71 : // 1 - branch executed but not taken.
72 : // 2 - branch executed and taken.
73 : //
74 : // Following DA/FN/FNDA/BA tags a record should contain appropriate summary
75 : // tags.
76 : //
77 : // If line instrumentation is present the following tags should be present:
78 : //
79 : // LH: <number of lines with non-zero execution count>
80 : // LF: <number of instrumented lines (number of DA records)>
81 : //
82 : // If function information is present the followings tags should be present:
83 : //
84 : // FNH: <number of functions (number of FN records)>
85 : // FNF: <number of functions with non-zero call count>
86 : //
87 : // Finally, a record (information regarding a single source file) should be
88 : // terminated with a single line containing the string 'end_of_record'.
89 :
90 : #include <map>
91 :
92 : #include "base/file_path.h"
93 : #include "syzygy/grinder/line_info.h"
94 :
95 : namespace grinder {
96 :
97 : // A simple class for accumulating data from LineInfo objects, representing
98 : // it with an alternative index, and finally dumping it to an LCOV text file.
99 : // Only handles line coverage results for now (DA, LF and LH tags).
100 : class LcovWriter {
101 : public:
102 : struct CoverageInfo; // Forward declaration.
103 :
104 : // A map of line numbers to execution counts.
105 : typedef std::map<size_t, size_t> LineExecutionCountMap;
106 : // A map of file names to coverage information.
107 : typedef std::map<std::string, CoverageInfo> SourceFileCoverageInfoMap;
108 :
109 : // Adds the given line information to the internal representation.
110 : // @param line_info the LineInfo object whose coverage information is to be
111 : // merged with our internal representation.
112 : // @returns true on success, false otherwise.
113 : bool Add(const LineInfo& line_info);
114 :
115 : // Dumps the coverage information to an LCOV file.
116 : // @param path the path to the file to be created or overwritten.
117 : // @param file the file handle to be written to.
118 : // @returns true on success, false otherwise.
119 : bool Write(const FilePath& path) const;
120 : bool Write(FILE* file) const;
121 :
122 E : const SourceFileCoverageInfoMap& source_file_coverage_info_map() const {
123 E : return source_file_coverage_info_map_;
124 E : }
125 :
126 : protected:
127 : // Store coverage results, per source file.
128 : SourceFileCoverageInfoMap source_file_coverage_info_map_;
129 : };
130 :
131 : // Coverage information that is stored per file. Right now this consists only
132 : // of line execution data, but branch and function data could be added.
133 : struct LcovWriter::CoverageInfo {
134 : LineExecutionCountMap line_execution_count_map;
135 : };
136 :
137 : } // namespace grinder
138 :
139 : #endif // SYZYGY_GRINDER_LCOV_WRITER_H_
|