Donate CPU/test-my-pr: Add timeout for the Cppcheck execution (#2500)
This adds a timeout of 60 minutes for the Cppcheck analysis. Timed out results do not count as crash but they are uploaded and marked with "TO!" in the list of the latest results. No "diff" is generated for timed out results so they do not add wrong entries to the "Diff report". In test-my-pr.py the timed out results are listed separately just like the crashes. donate-cpu-server.py: Add timeout report
This commit is contained in:
parent
11993ed999
commit
2d95c35974
|
@ -22,7 +22,7 @@ import operator
|
|||
# Version scheme (MAJOR.MINOR.PATCH) should orientate on "Semantic Versioning" https://semver.org/
|
||||
# Every change in this script should result in increasing the version number accordingly (exceptions may be cosmetic
|
||||
# changes)
|
||||
SERVER_VERSION = "1.3.1"
|
||||
SERVER_VERSION = "1.3.2"
|
||||
|
||||
OLD_VERSION = '1.90'
|
||||
|
||||
|
@ -67,6 +67,7 @@ def overviewReport() -> str:
|
|||
html = '<html><head><title>daca@home</title></head><body>\n'
|
||||
html += '<h1>daca@home</h1>\n'
|
||||
html += '<a href="crash.html">Crash report</a><br>\n'
|
||||
html += '<a href="timeout.html">Timeout report</a><br>\n'
|
||||
html += '<a href="stale.html">Stale report</a><br>\n'
|
||||
html += '<a href="diff.html">Diff report</a><br>\n'
|
||||
html += '<a href="head.html">HEAD report</a><br>\n'
|
||||
|
@ -82,7 +83,7 @@ def overviewReport() -> str:
|
|||
|
||||
|
||||
def fmt(a: str, b: str, c: str = None, d: str = None, e: str = None, link: bool = True) -> str:
|
||||
column_width = [40, 10, 5, 6, 6, 8]
|
||||
column_width = [40, 10, 5, 7, 7, 8]
|
||||
ret = a
|
||||
while len(ret) < column_width[0]:
|
||||
ret += ' '
|
||||
|
@ -218,6 +219,47 @@ def crashReport(results_path: str) -> str:
|
|||
return html
|
||||
|
||||
|
||||
def timeoutReport(results_path: str) -> str:
|
||||
html = '<html><head><title>Timeout report</title></head><body>\n'
|
||||
html += '<h1>Timeout report</h1>\n'
|
||||
html += '<pre>\n'
|
||||
html += '<b>' + fmt('Package', 'Date Time', OLD_VERSION, 'Head', link=False) + '</b>\n'
|
||||
current_year = datetime.date.today().year
|
||||
for filename in sorted(glob.glob(os.path.expanduser(results_path + '/*'))):
|
||||
if not os.path.isfile(filename):
|
||||
continue
|
||||
datestr = ''
|
||||
with open(filename, 'rt') as file_:
|
||||
for line in file_:
|
||||
line = line.strip()
|
||||
if line.startswith('cppcheck: '):
|
||||
if OLD_VERSION not in line:
|
||||
# Package results seem to be too old, skip
|
||||
break
|
||||
else:
|
||||
# Current package, parse on
|
||||
continue
|
||||
if line.startswith(str(current_year) + '-') or line.startswith(str(current_year - 1) + '-'):
|
||||
datestr = line
|
||||
if line.startswith('count:'):
|
||||
if line.find('TO!') < 0:
|
||||
break
|
||||
package = filename[filename.rfind('/')+1:]
|
||||
counts = line.strip().split(' ')
|
||||
c2 = ''
|
||||
if counts[2] == 'TO!':
|
||||
c2 = 'Timeout'
|
||||
c1 = ''
|
||||
if counts[1] == 'TO!':
|
||||
c1 = 'Timeout'
|
||||
html += fmt(package, datestr, c2, c1) + '\n'
|
||||
break
|
||||
|
||||
html += '</pre>\n'
|
||||
html += '</body></html>\n'
|
||||
return html
|
||||
|
||||
|
||||
def staleReport(results_path: str) -> str:
|
||||
html = '<html><head><title>Stale report</title></head><body>\n'
|
||||
html += '<h1>Stale report</h1>\n'
|
||||
|
@ -773,6 +815,9 @@ class HttpClientThread(Thread):
|
|||
elif url == 'crash.html':
|
||||
html = crashReport(self.resultPath)
|
||||
httpGetResponse(self.connection, html, 'text/html')
|
||||
elif url == 'timeout.html':
|
||||
html = timeoutReport(self.resultPath)
|
||||
httpGetResponse(self.connection, html, 'text/html')
|
||||
elif url == 'stale.html':
|
||||
html = staleReport(self.resultPath)
|
||||
httpGetResponse(self.connection, html, 'text/html')
|
||||
|
|
|
@ -172,6 +172,7 @@ while True:
|
|||
print("No files to process")
|
||||
continue
|
||||
crash = False
|
||||
timeout = False
|
||||
count = ''
|
||||
elapsed_time = ''
|
||||
results_to_diff = []
|
||||
|
@ -193,6 +194,10 @@ while True:
|
|||
if c == -101 and 'error: could not find or open any of the paths given.' in errout:
|
||||
# No sourcefile found (for example only headers present)
|
||||
count += ' 0'
|
||||
elif c == RETURN_CODE_TIMEOUT:
|
||||
# Timeout
|
||||
count += ' TO!'
|
||||
timeout = True
|
||||
else:
|
||||
crash = True
|
||||
count += ' Crash!'
|
||||
|
@ -220,7 +225,7 @@ while True:
|
|||
info_output += 'info messages:\n' + head_info_msg
|
||||
if 'head' in cppcheck_versions:
|
||||
output += 'head results:\n' + results_to_diff[cppcheck_versions.index('head')]
|
||||
if not crash:
|
||||
if not crash and not timeout:
|
||||
output += 'diff:\n' + diff_results(work_path, cppcheck_versions[0], results_to_diff[0], cppcheck_versions[1], results_to_diff[1]) + '\n'
|
||||
if package_url:
|
||||
print('=========================================================')
|
||||
|
|
|
@ -13,7 +13,13 @@ import tarfile
|
|||
# Version scheme (MAJOR.MINOR.PATCH) should orientate on "Semantic Versioning" https://semver.org/
|
||||
# Every change in this script should result in increasing the version number accordingly (exceptions may be cosmetic
|
||||
# changes)
|
||||
CLIENT_VERSION = "1.1.42"
|
||||
CLIENT_VERSION = "1.2.0"
|
||||
|
||||
# Timeout for analysis with Cppcheck in seconds
|
||||
CPPCHECK_TIMEOUT = 60 * 60
|
||||
|
||||
# Return code that is used to mark a timed out analysis
|
||||
RETURN_CODE_TIMEOUT = -999
|
||||
|
||||
|
||||
def check_requirements():
|
||||
|
@ -249,12 +255,18 @@ def run_command(cmd):
|
|||
print(cmd)
|
||||
startTime = time.time()
|
||||
p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
comm = p.communicate()
|
||||
try:
|
||||
comm = p.communicate(timeout=CPPCHECK_TIMEOUT)
|
||||
return_code = p.returncode
|
||||
except subprocess.TimeoutExpired:
|
||||
p.kill()
|
||||
comm = p.communicate()
|
||||
return_code = RETURN_CODE_TIMEOUT
|
||||
stop_time = time.time()
|
||||
stdout = comm[0].decode(encoding='utf-8', errors='ignore')
|
||||
stderr = comm[1].decode(encoding='utf-8', errors='ignore')
|
||||
elapsed_time = stop_time - startTime
|
||||
return p.returncode, stdout, stderr, elapsed_time
|
||||
return return_code, stdout, stderr, elapsed_time
|
||||
|
||||
|
||||
def scan_package(work_path, cppcheck_path, jobs, libraries):
|
||||
|
@ -300,6 +312,9 @@ def scan_package(work_path, cppcheck_path, jobs, libraries):
|
|||
else:
|
||||
stacktrace = stdout[last_check_pos:]
|
||||
return returncode, stacktrace, '', returncode, options, ''
|
||||
if returncode == RETURN_CODE_TIMEOUT:
|
||||
print('Timeout!')
|
||||
return returncode, stdout, '', elapsed_time, options, ''
|
||||
if returncode != 0:
|
||||
print('Error!')
|
||||
if returncode > 0:
|
||||
|
|
|
@ -69,6 +69,7 @@ if __name__ == "__main__":
|
|||
|
||||
packages_processed = 0
|
||||
crashes = []
|
||||
timeouts = []
|
||||
|
||||
while packages_processed < args.p and len(packages_idxs) > 0:
|
||||
package = lib.get_package(lib.server_address, packages_idxs.pop())
|
||||
|
@ -90,12 +91,18 @@ if __name__ == "__main__":
|
|||
master_crashed = False
|
||||
your_crashed = False
|
||||
|
||||
master_timeout = False
|
||||
your_timeout = False
|
||||
|
||||
libraries = lib.get_libraries()
|
||||
c, errout, info, time, cppcheck_options, timing_info = lib.scan_package(work_path, master_dir, jobs, libraries)
|
||||
if c < 0:
|
||||
if c == -101 and 'error: could not find or open any of the paths given.' in errout:
|
||||
# No sourcefile found (for example only headers present)
|
||||
print('Error: 101')
|
||||
elif c == lib.RETURN_CODE_TIMEOUT:
|
||||
print('Master timed out!')
|
||||
master_timeout = True
|
||||
else:
|
||||
print('Master crashed!')
|
||||
master_crashed = True
|
||||
|
@ -106,6 +113,9 @@ if __name__ == "__main__":
|
|||
if c == -101 and 'error: could not find or open any of the paths given.' in errout:
|
||||
# No sourcefile found (for example only headers present)
|
||||
print('Error: 101')
|
||||
elif c == lib.RETURN_CODE_TIMEOUT:
|
||||
print('Your code timed out!')
|
||||
your_timeout = True
|
||||
else:
|
||||
print('Your code crashed!')
|
||||
your_crashed = True
|
||||
|
@ -121,6 +131,16 @@ if __name__ == "__main__":
|
|||
who = 'Your'
|
||||
crashes.append(package + ' ' + who)
|
||||
|
||||
if master_timeout or your_timeout:
|
||||
who = None
|
||||
if master_timeout and your_timeout:
|
||||
who = 'Both'
|
||||
elif master_timeout:
|
||||
who = 'Master'
|
||||
else:
|
||||
who = 'Your'
|
||||
timeouts.append(package + ' ' + who)
|
||||
|
||||
with open(result_file, 'a') as myfile:
|
||||
myfile.write(package + '\n')
|
||||
diff = lib.diff_results(work_path, 'master', results_to_diff[0], 'your', results_to_diff[1])
|
||||
|
@ -134,4 +154,8 @@ if __name__ == "__main__":
|
|||
myfile.write('\n\ncrashes\n')
|
||||
myfile.write('\n'.join(crashes))
|
||||
|
||||
with open(result_file, 'a') as myfile:
|
||||
myfile.write('\n\ntimeouts\n')
|
||||
myfile.write('\n'.join(timeouts))
|
||||
|
||||
print('Result saved to: ' + result_file)
|
||||
|
|
Loading…
Reference in New Issue