diff --git a/tools/donate-cpu-server.py b/tools/donate-cpu-server.py index fca62838a..ac4bca607 100755 --- a/tools/donate-cpu-server.py +++ b/tools/donate-cpu-server.py @@ -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 = 'daca@home\n' html += '

daca@home

\n' html += 'Crash report
\n' + html += 'Timeout report
\n' html += 'Stale report
\n' html += 'Diff report
\n' html += 'HEAD report
\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 = 'Timeout report\n' + html += '

Timeout report

\n' + html += '
\n'
+    html += '' + fmt('Package', 'Date       Time', OLD_VERSION, 'Head', link=False) + '\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 += '
\n' + html += '\n' + return html + + def staleReport(results_path: str) -> str: html = 'Stale report\n' html += '

Stale report

\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') diff --git a/tools/donate-cpu.py b/tools/donate-cpu.py index 6e0cf68df..498060a2e 100755 --- a/tools/donate-cpu.py +++ b/tools/donate-cpu.py @@ -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('=========================================================') diff --git a/tools/donate_cpu_lib.py b/tools/donate_cpu_lib.py index a24f4073d..e14131392 100644 --- a/tools/donate_cpu_lib.py +++ b/tools/donate_cpu_lib.py @@ -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: diff --git a/tools/test-my-pr.py b/tools/test-my-pr.py index 3c762c315..98f4cd9d0 100755 --- a/tools/test-my-pr.py +++ b/tools/test-my-pr.py @@ -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)