cppcheck/test/bug-hunting/itc.py

98 lines
2.8 KiB
Python

# Test if --bug-hunting works using the itc testsuite
# The itc test suite can be downloaded here:
# https://github.com/regehr/itc-benchmarks
import glob
import os
import re
import shutil
import sys
import subprocess
if sys.argv[0] in ('test/bug-hunting/itc.py', './test/bug-hunting/itc.py'):
CPPCHECK_PATH = './cppcheck'
else:
CPPCHECK_PATH = '../../cppcheck'
if len(sys.argv) >= 2 and sys.argv[-1] != '--clang':
TESTFILES = [sys.argv[-1]]
else:
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])
sys.exit(1)
RUN_CLANG = ('--clang' in sys.argv)
def get_error_lines(filename):
ret = []
f = open(filename, 'rt')
lines = f.readlines()
for linenr, line in enumerate(lines):
if line.find('/* ERROR:') > 0 or line.find('/*ERROR:') > 0:
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)
return ret
def check(filename):
cmd = [CPPCHECK_PATH,
'--bug-hunting',
'--platform=unix64',
filename]
if RUN_CLANG:
cmd.append('--clang')
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')
if RUN_CLANG:
shutil.rmtree('itc-build-dir')
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:
w = r'.*c:([0-9]+):[0-9]+: error: .*bughuntingUninit.*'
else:
w = r'.*c:([0-9]+):[0-9]+: error: .*bughunting.*'
ret = []
for line in stderr.split('\n'):
res = re.match(w, line)
if res is None:
continue
linenr = int(res.group(1))
if linenr not in ret:
ret.append(linenr)
return ret
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)