1
1
#!/usr/bin/env python3
2
2
3
- # Compare "normal" check level and "exhaustive" check level
3
+ # Compare results and timings of different valueflow options
4
+ # Example usage:
5
+ # cd ~/cppcheck && make CXXFLAGS=-O2 MATCHCOMPILER=yes
6
+ # python3 compare-valueflow-options.py --cppcheck-path=~/cppcheck --packages-path=~/daca2-packages
4
7
5
8
import donate_cpu_lib as lib
6
9
import argparse
7
10
import glob
8
11
import os
12
+ import re
9
13
import sys
10
14
import random
11
15
@@ -16,6 +20,20 @@ def format_float(a, b=1):
16
20
return 'N/A'
17
21
18
22
23
+ def count_errors (errout :str , c :set ):
24
+ for line in errout .split ('\n ' ):
25
+ if not line .endswith (']' ):
26
+ continue
27
+ res = re .match (r'^[^:]+:[0-9]+:[0-9]+: (error|warning|style|portability|performance):.*\[([a-zA-Z0-9_\-]+)\]$' , line )
28
+ if res is None :
29
+ print ('No warning? ' + line )
30
+ continue
31
+ severity = res .group (1 )
32
+ c [severity ] = c .get (severity , 0 ) + 1
33
+ error_id = res .group (2 )
34
+ c [error_id ] = c .get (error_id , 0 ) + 1
35
+
36
+
19
37
if __name__ == "__main__" :
20
38
__my_script_name = os .path .splitext (os .path .basename (sys .argv [0 ]))[0 ]
21
39
__work_path = os .path .expanduser (os .path .join ('~' , 'cppcheck-' + __my_script_name + '-workfolder' ))
@@ -47,20 +65,18 @@ def format_float(a, b=1):
47
65
48
66
lib .set_jobs ('-j' + str (args .j ))
49
67
50
- def results_file (name ):
51
- f , ext = os .path .splitext (args .o )
52
- return os .path .join (work_path , f + '_' + name + ext )
68
+ results_file = os .path .join (work_path , args .o )
69
+ summary_file = os .path .join (work_path , 'summary.log' )
70
+
71
+ for f in (results_file , summary_file ):
72
+ if os .path .exists (f ):
73
+ os .remove (f )
53
74
54
75
opts = {'0' : '--check-level=exhaustive --suppress=valueFlow*' ,
55
76
'it2' : '--check-level=exhaustive --performance-valueflow-max-iterations=2 --suppress=valueFlow*' ,
56
77
'it1' : '--check-level=exhaustive --performance-valueflow-max-iterations=1 --suppress=valueFlow*' ,
57
78
'if8' : '--check-level=exhaustive --performance-valueflow-max-if-count=8 --suppress=valueFlow*' }
58
79
59
- for o in opts .keys ():
60
- f = results_file (o )
61
- if os .path .exists (f ):
62
- os .remove (f )
63
-
64
80
cppcheck_path = args .cppcheck_path
65
81
66
82
if cppcheck_path is None :
@@ -94,8 +110,9 @@ def results_file(name):
94
110
random .shuffle (packages_idxs )
95
111
96
112
packages_processed = 0
97
- crashes = []
98
- timeouts = []
113
+ summary_results = {}
114
+ for id in opts .keys ():
115
+ summary_results [id ] = {}
99
116
100
117
while (packages_processed < args .p and len (packages_idxs ) > 0 ) or args .packages :
101
118
if args .packages :
@@ -117,50 +134,66 @@ def results_file(name):
117
134
print ("No files to process" )
118
135
continue
119
136
120
- results_to_diff = list ()
121
- timings = list ()
122
-
123
- crashed = []
124
- timeout = []
137
+ results0 = None
138
+ time0 = None
125
139
126
140
enable = 'style'
127
141
debug_warnings = False
128
142
129
143
libraries = lib .library_includes .get_libraries (source_path )
130
144
145
+ with open (results_file , 'at' ) as myfile :
146
+ myfile .write ('package:' + package + '\n ' )
147
+ myfile .write ('libraries:' + ',' .join (libraries ) + '\n ' )
148
+
131
149
for id , extra_args in opts .items ():
132
- print ('scan:' + id )
150
+ print ('scan:' + id )
133
151
c , errout , info , time , cppcheck_options , timing_info = lib .scan_package (cppcheck_path , source_path , libraries , enable = enable , extra_args = extra_args )
152
+ error_text = None
134
153
if c < 0 :
135
154
if c == - 101 and 'error: could not find or open any of the paths given.' in errout :
136
155
# No sourcefile found (for example only headers present)
137
- print ( 'Error: 101' )
156
+ error_text = f' { id } ERR no source file'
138
157
elif c == lib .RETURN_CODE_TIMEOUT :
139
- print (id + ' timed out!' )
140
- timeout .append (id )
141
- continue # we don't want to compare timeouts
158
+ error_text = f'{ id } timeout'
142
159
else :
143
- print (f'{ id } crashed! code={ c } ' )
144
- crashed .append (id )
145
- results_to_diff .append (errout )
146
- timings .append (time )
147
-
148
- if len (results_to_diff ) <= 1 :
149
- continue
160
+ error_text = f'{ id } crash code={ c } '
150
161
151
- r0 = results_to_diff [0 ]
152
- with open (results_file (id ), 'a' ) as myfile :
153
- myfile .write (package + '\n ' )
154
- if id in crashed :
155
- myfile .write ('Crash\n ' )
156
- elif id in timeout :
157
- myfile .write ('Timeout\n ' )
162
+ with open (results_file , 'at' ) as myfile :
163
+ if error_text is not None :
164
+ myfile .write (f'{ error_text } \n ' )
158
165
else :
159
- diff = lib .diff_results ('0' , r0 , id , errout )
160
- if diff != '' :
161
- myfile .write ('diff:\n ' + diff + '\n ' )
162
- myfile .write ('time: %.1f %.1f\n ' % (timings [0 ], time ))
163
- myfile .write ('libraries:' + ',' .join (libraries ) + '\n ' )
166
+ results = {}
167
+ count_errors (errout , results )
168
+ count_errors (errout , summary_results [id ])
169
+ if results0 is None :
170
+ results0 = results
171
+ time0 = time
172
+ else :
173
+ for error_id , count in results0 .items ():
174
+ current_count = results .get (error_id , 0 )
175
+ if count > current_count :
176
+ myfile .write (f'{ id } : FN { error_id } : { current_count } of { count } \n ' )
177
+ if time > 10 or time0 > 10 :
178
+ myfile .write (f'{ id } : Time: %.1f\n ' % time )
179
+ time_factor = time / time0
180
+ myfile .write (f'{ id } : Timefactor: %.3f\n ' % time_factor )
181
+
182
+ with open (summary_file , 'wt' ) as myfile :
183
+ all = {}
184
+ for id , c in summary_results .items ():
185
+ for error_id , count in c .items ():
186
+ if error_id not in all :
187
+ all [error_id ] = {}
188
+ for id2 in opts .keys ():
189
+ all [error_id ][id2 ] = 0
190
+ all [error_id ][id ] += count
191
+
192
+ for error_id , id_count in all .items ():
193
+ myfile .write (f'{ error_id } :' )
194
+ for id , count in id_count .items ():
195
+ myfile .write (f' { id } :{ count } ' )
196
+ myfile .write ('\n ' )
164
197
165
198
packages_processed += 1
166
199
print (str (packages_processed ) + ' of ' + str (args .p ) + ' packages processed\n ' )
0 commit comments