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 isGapRegion.

12

Branch regions of files, expansions and functions, and the summaries’ branches.

18

MC/DC records of files and functions, and the summaries’ mcdc.

3.0.0

21

An MC/DC record’s numbers of true and false decisions.

3.0.1

21

An MC/DC record’s fileID.

3.1.0

22

An MC/DC record’s test vectors; LLVM 23 lists the missing ones too, with -show-mcdc-non-executed-vectors.

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}