2020-01-20 10:43:42 +01:00
|
|
|
# Test if --bug-hunting works using the itc testsuite
|
2019-10-24 21:48:34 +02:00
|
|
|
# The itc test suite can be downloaded here:
|
|
|
|
# https://github.com/regehr/itc-benchmarks
|
|
|
|
|
|
|
|
|
|
|
|
import glob
|
|
|
|
import os
|
|
|
|
import re
|
2020-01-20 10:43:42 +01:00
|
|
|
import shutil
|
2019-10-24 21:48:34 +02:00
|
|
|
import sys
|
|
|
|
import subprocess
|
|
|
|
|
2020-01-20 10:43:42 +01:00
|
|
|
if sys.argv[0] in ('test/bug-hunting/itc.py', './test/bug-hunting/itc.py'):
|
2019-10-24 21:48:34 +02:00
|
|
|
CPPCHECK_PATH = './cppcheck'
|
|
|
|
else:
|
|
|
|
CPPCHECK_PATH = '../../cppcheck'
|
|
|
|
|
2020-01-20 10:43:42 +01:00
|
|
|
if len(sys.argv) >= 2 and sys.argv[-1] != '--clang':
|
2020-05-15 20:58:33 +02:00
|
|
|
TESTFILES = [sys.argv[-1]]
|
2019-12-23 11:23:56 +01:00
|
|
|
else:
|
2020-05-15 20:58:33 +02:00
|
|
|
TESTFILES = [os.path.expanduser('~/itc/01.w_Defects/zero_division.c'),
|
|
|
|
os.path.expanduser('~/itc/01.w_Defects/uninit_var.c')]
|
|
|
|
if not os.path.isfile(TESTFILES[0]):
|
|
|
|
print('ERROR: %s is not a file' % TESTFILES[0])
|
2020-05-06 11:55:22 +02:00
|
|
|
sys.exit(1)
|
2019-12-23 11:23:56 +01:00
|
|
|
|
2020-01-20 10:43:42 +01:00
|
|
|
RUN_CLANG = ('--clang' in sys.argv)
|
|
|
|
|
2019-10-24 21:48:34 +02:00
|
|
|
def get_error_lines(filename):
|
|
|
|
ret = []
|
|
|
|
f = open(filename, 'rt')
|
|
|
|
lines = f.readlines()
|
|
|
|
for linenr, line in enumerate(lines):
|
2020-01-12 10:28:48 +01:00
|
|
|
if line.find('/* ERROR:') > 0 or line.find('/*ERROR:') > 0:
|
2020-06-18 14:31:51 +02:00
|
|
|
linenr += 1
|
|
|
|
if testfile.find('uninit_') >= 0:
|
|
|
|
if linenr == 177:
|
|
|
|
linenr = 176
|
|
|
|
elif linenr == 200:
|
|
|
|
linenr = 225 # warn about function call
|
|
|
|
elif linenr == 241:
|
|
|
|
linenr = 242 # warn about usage
|
|
|
|
elif linenr == 266:
|
|
|
|
continue # no warning should be written
|
|
|
|
elif linenr == 295:
|
|
|
|
continue # FIXME: False negative
|
|
|
|
ret.append(linenr)
|
2019-10-24 21:48:34 +02:00
|
|
|
return ret
|
|
|
|
|
|
|
|
def check(filename):
|
|
|
|
cmd = [CPPCHECK_PATH,
|
2020-01-15 21:06:00 +01:00
|
|
|
'--bug-hunting',
|
2019-10-24 21:48:34 +02:00
|
|
|
'--platform=unix64',
|
|
|
|
filename]
|
2020-01-20 10:43:42 +01:00
|
|
|
if RUN_CLANG:
|
2020-05-15 20:58:33 +02:00
|
|
|
cmd.append('--clang')
|
2019-10-24 21:48:34 +02:00
|
|
|
print(' '.join(cmd))
|
|
|
|
|
|
|
|
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
|
|
comm = p.communicate()
|
|
|
|
stdout = comm[0].decode(encoding='utf-8', errors='ignore')
|
|
|
|
stderr = comm[1].decode(encoding='utf-8', errors='ignore')
|
|
|
|
|
2020-01-20 10:43:42 +01:00
|
|
|
if RUN_CLANG:
|
|
|
|
shutil.rmtree('itc-build-dir')
|
|
|
|
|
2020-05-15 20:58:33 +02:00
|
|
|
if filename.find('zero_division.c') >= 0:
|
|
|
|
w = r'.*zero_division.c:([0-9]+):[0-9]+: error: There is division.*'
|
|
|
|
elif filename.find('uninit_') >= 0:
|
2020-05-01 10:22:05 +02:00
|
|
|
w = r'.*c:([0-9]+):[0-9]+: error: .*bughuntingUninit.*'
|
2020-05-15 20:58:33 +02:00
|
|
|
else:
|
|
|
|
w = r'.*c:([0-9]+):[0-9]+: error: .*bughunting.*'
|
2020-01-12 10:28:48 +01:00
|
|
|
|
2019-10-24 21:48:34 +02:00
|
|
|
ret = []
|
|
|
|
for line in stderr.split('\n'):
|
2020-01-12 10:28:48 +01:00
|
|
|
res = re.match(w, line)
|
2019-10-24 21:48:34 +02:00
|
|
|
if res is None:
|
|
|
|
continue
|
2020-01-12 10:53:44 +01:00
|
|
|
linenr = int(res.group(1))
|
|
|
|
if linenr not in ret:
|
|
|
|
ret.append(linenr)
|
2019-10-24 21:48:34 +02:00
|
|
|
return ret
|
|
|
|
|
2020-05-15 20:58:33 +02:00
|
|
|
for testfile in TESTFILES:
|
|
|
|
wanted = get_error_lines(testfile)
|
|
|
|
actual = check(testfile)
|
|
|
|
missing = []
|
|
|
|
for w in wanted:
|
|
|
|
if w not in actual:
|
|
|
|
missing.append(w);
|
|
|
|
if len(missing) > 0:
|
|
|
|
print('wanted:' + str(wanted))
|
|
|
|
print('actual:' + str(actual))
|
|
|
|
print('missing:' + str(missing))
|
|
|
|
sys.exit(1)
|
2019-10-24 21:48:34 +02:00
|
|
|
|
|
|
|
|