-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgcov.py
142 lines (117 loc) · 4.5 KB
/
gcov.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import json
import gzip
import os
import subprocess
import sys
class cd:
def __init__(self, dirname):
self.dirname = os.path.expanduser(dirname)
def __enter__(self):
self.saved = os.getcwd()
os.chdir(self.dirname)
def __exit__(self, etype, value, traceback):
os.chdir(self.saved)
class Base:
def __init__(self, gcov, bin_dir, int_dir):
self.gcov = gcov
self.bin_dir = bin_dir
self.int_dir = int_dir
def preprocess(self, recurse):
gcno_dirs = {}
for gcno in recurse(os.path.abspath(self.bin_dir), ".gcno"):
dirname, filename = os.path.split(gcno)
if dirname not in gcno_dirs:
gcno_dirs[dirname] = []
gcno_dirs[dirname].append(filename)
for dirname in gcno_dirs:
int_dir = os.path.relpath(dirname, self.bin_dir).replace(os.sep, "#")
int_dir = os.path.join(self.int_dir, int_dir)
os.makedirs(int_dir, exist_ok=True)
files = [os.path.join(dirname, filen) for filen in gcno_dirs[dirname]]
with cd(int_dir):
import shlex
print(
shlex.join(
[self.gcov, "-l", "-b", "-c", "-i", "-p", "-o", dirname] + files
),
file=sys.stderr,
)
p = subprocess.Popen(
[self.gcov, "-l", "-b", "-c", "-i", "-p", "-o", dirname] + files,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
_, err = p.communicate()
if p.returncode:
print(err, file=sys.stderr)
print("error:", p.returncode, file=sys.stderr)
sys.exit(1)
def ext(self):
pass
def stats(self, bin_dir, gcov_file):
pass
class GCOV8(Base):
def __init__(self, gcov, bin_dir, int_dir):
Base.__init__(self, gcov, bin_dir, int_dir)
def ext(self):
return ".gcov"
def stats(self, gcov_file):
result = {}
filename = None
file = None
with open(gcov_file) as src:
for line in src:
split = line.split(":", 1)
if len(split) < 2:
continue
if split[0] == "file":
if file is not None:
result[filename] = file
filename = split[1].strip()
if not os.path.isabs(filename):
filename = os.path.abspath(os.path.join(self.bin_dir, filename))
file = [[], []]
continue
if split[0] == "function":
start, stop, count, name = split[1].split(",")
file[0].append((int(start), int(stop), int(count), name.strip()))
print(file[0][-1])
continue
if split[0] == "lcount":
line, count, has_unexecuted = split[1].split(",")
file[1].append((int(line), int(count), int(has_unexecuted)))
continue
if file is not None:
result[filename] = file
return result
class JSON1(Base):
def __init__(self, gcov, bin_dir, int_dir):
Base.__init__(self, gcov, bin_dir, int_dir)
def ext(self):
return ".gcov.json.gz"
def stats(self, gcov_file):
result = {}
with gzip.open(gcov_file, "rb") as compressed:
data = json.loads(compressed.read().decode("ascii"))["files"]
for coverage in data:
filename = coverage["file"]
if not os.path.isabs(filename):
filename = os.path.abspath(os.path.join(self.bin_dir, filename))
functions = [
(
fun.get("start_line"),
fun.get("end_line"),
fun.get("start_column"),
fun.get("end_column"),
fun.get("execution_count"),
fun.get("name"),
fun.get("demangled_name"),
)
for fun in coverage["functions"]
]
lines = [
(line["line_number"], line["count"], line["unexecuted_block"])
for line in coverage["lines"]
]
result[filename] = [functions, lines]
return result