LLVM coverage JSON
The JSON report llvm-cov export -format=text writes - type llvm.coverage.json.export, format versions 2.0.0 to
3.1.0 - as a JSON Schema.
Read by pyEDAA.Reports.CodeCoverage.LLVM.Document - see LLVM coverage JSON.
LLVM publishes no schema of its JSON export. This one is reverse-engineered from llvm-cov’s
llvm/tools/llvm-cov/CoverageExporterJson.cpp, LLVM 4 to 23:
Version |
LLVM |
Change |
|---|---|---|
2.0.0 |
4 |
Files with segments, expansions and summary; functions with regions; totals. |
2.0.1 |
11 |
A segment’s |
12 |
Branch regions of files, expansions and functions, and the summaries’ |
|
18 |
MC/DC records of files and functions, and the summaries’ |
|
3.0.0 |
21 |
An MC/DC record’s numbers of true and false decisions. |
3.0.1 |
21 |
An MC/DC record’s |
3.1.0 |
22 |
An MC/DC record’s test vectors; LLVM 23 lists the missing ones too, with |
A field a later LLVM added is optional; an MC/DC record matches one of its three shapes, by its length. An unknown field or version is rejected.
Download
LLVM-Coverage-JSON.schema.json (7.9 kiB)
Validate a report
check-jsonschema --schemafile LLVM-Coverage-JSON.schema.json coverage.json
Source
1{
2 "$schema": "https://json-schema.org/draft/2020-12/schema",
3 "$id": "https://edaa-org.github.io/pyEDAA.Reports/Schemas/LLVM-Coverage-JSON.schema.json",
4 "title": "LLVM code coverage export (JSON)",
5 "description": "The JSON report 'llvm-cov export -format=text' writes, type 'llvm.coverage.json.export', format versions 2.0.0 to 3.1.0. Reverse-engineered from llvm-cov's 'CoverageExporterJson.cpp' (LLVM 4 to 23): 2.0.1 added 'isGapRegion' to a segment; LLVM 12 added the branch regions and LLVM 18 the MC/DC records, without a new version; 3.0.0 added the numbers of true and false decisions to an MC/DC record, 3.0.1 its 'fileID', 3.1.0 its test vectors. Fields a version added later are optional.",
6 "type": "object",
7 "required": ["version", "type", "data"],
8 "properties": {
9 "version": {"description": "Version of the report format.", "enum": ["2.0.0", "2.0.1", "3.0.0", "3.0.1", "3.1.0"]},
10 "type": {"description": "Type of the report.", "const": "llvm.coverage.json.export"},
11 "data": {
12 "description": "The export of the coverage mapping; llvm-cov writes one.",
13 "type": "array",
14 "items": {"$ref": "#/$defs/Export"},
15 "minItems": 1,
16 "maxItems": 1
17 }
18 },
19 "additionalProperties": false,
20 "$defs": {
21 "Count": {"type": "integer", "minimum": 0},
22 "FileID": {"description": "Index into the file names of the function or expansion.", "type": "integer", "minimum": 0},
23 "Kind": {
24 "description": "Kind of the region: code, expansion, skipped, gap, branch, MC/DC decision, MC/DC branch.",
25 "enum": [0, 1, 2, 3, 4, 5, 6]
26 },
27 "Line": {"type": "integer", "minimum": 1},
28 "Column": {"type": "integer", "minimum": 1},
29 "Filenames": {"type": "array", "items": {"type": "string"}},
30 "Segment": {
31 "description": "[line, column, count, hasCount, isRegionEntry, isGapRegion]; 2.0.0 has no 'isGapRegion'.",
32 "type": "array",
33 "prefixItems": [
34 {"$ref": "#/$defs/Line"},
35 {"$ref": "#/$defs/Column"},
36 {"$ref": "#/$defs/Count"},
37 {"type": "boolean"},
38 {"type": "boolean"},
39 {"type": "boolean"}
40 ],
41 "items": false,
42 "minItems": 5
43 },
44 "Region": {
45 "description": "[lineStart, columnStart, lineEnd, columnEnd, count, fileID, expandedFileID, kind]",
46 "type": "array",
47 "prefixItems": [
48 {"$ref": "#/$defs/Line"},
49 {"$ref": "#/$defs/Column"},
50 {"$ref": "#/$defs/Line"},
51 {"$ref": "#/$defs/Column"},
52 {"$ref": "#/$defs/Count"},
53 {"$ref": "#/$defs/FileID"},
54 {"$ref": "#/$defs/FileID"},
55 {"$ref": "#/$defs/Kind"}
56 ],
57 "items": false,
58 "minItems": 8
59 },
60 "Branch": {
61 "description": "[lineStart, columnStart, lineEnd, columnEnd, trueCount, falseCount, fileID, expandedFileID, kind]",
62 "type": "array",
63 "prefixItems": [
64 {"$ref": "#/$defs/Line"},
65 {"$ref": "#/$defs/Column"},
66 {"$ref": "#/$defs/Line"},
67 {"$ref": "#/$defs/Column"},
68 {"$ref": "#/$defs/Count"},
69 {"$ref": "#/$defs/Count"},
70 {"$ref": "#/$defs/FileID"},
71 {"$ref": "#/$defs/FileID"},
72 {"enum": [4, 6]}
73 ],
74 "items": false,
75 "minItems": 9
76 },
77 "Conditions": {
78 "description": "Whether a pair of test vectors showed the independent effect, by condition.",
79 "type": "array",
80 "items": {"type": "boolean"}
81 },
82 "TestVector": {
83 "description": "The values of the conditions - null for one not evaluated -, and the outcome.",
84 "type": "object",
85 "required": ["conditions", "executed", "result"],
86 "properties": {
87 "conditions": {"type": "array", "items": {"type": ["boolean", "null"]}},
88 "executed": {"type": "boolean"},
89 "result": {"type": ["boolean", "null"]}
90 },
91 "additionalProperties": false
92 },
93 "MCDCRecord": {
94 "description": "A decision, in the shape of the format version: 2.0.1 [lineStart, columnStart, lineEnd, columnEnd, expandedFileID, kind, conditions]; 3.0.0 adds trueDecisions and falseDecisions after columnEnd, 3.0.1 fileID before expandedFileID, 3.1.0 the test vectors at the end.",
95 "type": "array",
96 "prefixItems": [
97 {"$ref": "#/$defs/Line"},
98 {"$ref": "#/$defs/Column"},
99 {"$ref": "#/$defs/Line"},
100 {"$ref": "#/$defs/Column"}
101 ],
102 "oneOf": [
103 {
104 "prefixItems": [true, true, true, true, {"$ref": "#/$defs/FileID"}, {"const": 5}, {"$ref": "#/$defs/Conditions"}],
105 "items": false,
106 "minItems": 7
107 },
108 {
109 "prefixItems": [
110 true, true, true, true, {"$ref": "#/$defs/Count"}, {"$ref": "#/$defs/Count"}, {"$ref": "#/$defs/FileID"},
111 {"const": 5}, {"$ref": "#/$defs/Conditions"}
112 ],
113 "items": false,
114 "minItems": 9
115 },
116 {
117 "prefixItems": [
118 true, true, true, true, {"$ref": "#/$defs/Count"}, {"$ref": "#/$defs/Count"}, {"$ref": "#/$defs/FileID"},
119 {"$ref": "#/$defs/FileID"}, {"const": 5}, {"$ref": "#/$defs/Conditions"},
120 {"type": "array", "items": {"$ref": "#/$defs/TestVector"}}
121 ],
122 "items": false,
123 "minItems": 10
124 }
125 ]
126 },
127 "Expansion": {
128 "description": "A macro expansion: the region it is expanded at, the regions of its function, and its branch regions.",
129 "type": "object",
130 "required": ["filenames", "source_region", "target_regions"],
131 "properties": {
132 "filenames": {"$ref": "#/$defs/Filenames"},
133 "source_region": {"$ref": "#/$defs/Region"},
134 "target_regions": {"type": "array", "items": {"$ref": "#/$defs/Region"}},
135 "branches": {"type": "array", "items": {"$ref": "#/$defs/Branch"}}
136 },
137 "additionalProperties": false
138 },
139 "Counters": {
140 "type": "object",
141 "required": ["count", "covered", "percent"],
142 "properties": {
143 "count": {"$ref": "#/$defs/Count"},
144 "covered": {"$ref": "#/$defs/Count"},
145 "notcovered": {"$ref": "#/$defs/Count"},
146 "percent": {"type": "number", "minimum": 0, "maximum": 100}
147 },
148 "additionalProperties": false
149 },
150 "Summary": {
151 "description": "Counters, as llvm-cov computed them; 'branches' since LLVM 12, 'mcdc' since LLVM 18.",
152 "type": "object",
153 "required": ["lines", "functions", "instantiations", "regions"],
154 "properties": {
155 "lines": {"$ref": "#/$defs/Counters"},
156 "functions": {"$ref": "#/$defs/Counters"},
157 "instantiations": {"$ref": "#/$defs/Counters"},
158 "regions": {"$ref": "#/$defs/Counters"},
159 "branches": {"$ref": "#/$defs/Counters"},
160 "mcdc": {"$ref": "#/$defs/Counters"}
161 },
162 "additionalProperties": false
163 },
164 "File": {
165 "description": "A file; '-summary-only' leaves only its summary, '-skip-expansions' its expansions out.",
166 "type": "object",
167 "required": ["filename", "summary"],
168 "properties": {
169 "filename": {"type": "string"},
170 "segments": {"type": "array", "items": {"$ref": "#/$defs/Segment"}},
171 "branches": {"type": "array", "items": {"$ref": "#/$defs/Branch"}},
172 "mcdc_records": {"type": "array", "items": {"$ref": "#/$defs/MCDCRecord"}},
173 "expansions": {"type": "array", "items": {"$ref": "#/$defs/Expansion"}},
174 "summary": {"$ref": "#/$defs/Summary"}
175 },
176 "additionalProperties": false
177 },
178 "Function": {
179 "description": "A function, or an instantiation of a template, by the name the profile gives it - e.g. mangled.",
180 "type": "object",
181 "required": ["name", "count", "regions", "filenames"],
182 "properties": {
183 "name": {"type": "string"},
184 "count": {"$ref": "#/$defs/Count"},
185 "regions": {"type": "array", "items": {"$ref": "#/$defs/Region"}},
186 "branches": {"type": "array", "items": {"$ref": "#/$defs/Branch"}},
187 "mcdc_records": {"type": "array", "items": {"$ref": "#/$defs/MCDCRecord"}},
188 "filenames": {"$ref": "#/$defs/Filenames"}
189 },
190 "additionalProperties": false
191 },
192 "Export": {
193 "description": "The files, the functions - unless written with '-skip-functions' or '-summary-only' -, and the totals.",
194 "type": "object",
195 "required": ["files", "totals"],
196 "properties": {
197 "files": {"type": "array", "items": {"$ref": "#/$defs/File"}},
198 "functions": {"type": "array", "items": {"$ref": "#/$defs/Function"}},
199 "totals": {"$ref": "#/$defs/Summary"}
200 },
201 "additionalProperties": false
202 }
203 }
204}