#!/usr/bin/env python3 """ *************************************************************************** ctest2ci.py --------------------- Date : March 2017 Copyright : (C) 2017 by Matthias Kuhn Email : matthias@opengis.ch *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * *************************************************************************** """ __author__ = "Matthias Kuhn" __date__ = "March 2017" __copyright__ = "(C) 2017, Matthias Kuhn" # This script parses output from ctest and injects # # - Colors for failing unit tests and test cases # - Group control sequences to hide uninteresting output by default import re import string import subprocess import sys from termcolor import colored fold_stack = list() printable = set(string.printable) def start_fold(tag): sys.stdout.write(f"::group::{tag}\n") fold_stack.append(tag) def end_fold(): try: tag = fold_stack.pop() sys.stdout.write("::endgroup::\n") except IndexError: updated_line = colored("======================", "magenta") updated_line += colored( "ctest2ci error when processing the following line:", "magenta" ) updated_line += colored("----------------------", "magenta") updated_line += colored(updated_line, "magenta") updated_line += colored("----------------------", "magenta") updated_line += colored( "Tried to end fold, but fold was never started.", "magenta" ) updated_line += colored("======================", "magenta") test_count = 0 def start_test_fold(): global test_count sys.stdout.write("Running tests\n") start_fold(f"test.{test_count}") test_count += 1 in_failing_test = False in_failure = False p = subprocess.Popen(sys.argv[1:], stdout=subprocess.PIPE) for line in p.stdout: updated_line = line.decode("utf-8") # remove non printable characters https://stackoverflow.com/a/8689826/1548052 filter(lambda x: x in printable, updated_line) if re.match("Run dashboard with model Experimental", updated_line): start_fold("Run tests") updated_line = "{title}\n{line}".format( title=colored("Running tests...", "yellow", attrs=["bold"]), line=updated_line, ) elif re.match("Test project /home/runner/QGIS/QGIS/build", updated_line): end_fold() # tag=Run tests start_test_fold() if re.search(r"\*\*\*Failed", updated_line) or re.search( r"\*\*\*Timeout", updated_line ): end_fold() updated_line = colored(updated_line, "red") in_failing_test = True if in_failing_test: if re.match(" Start", updated_line): start_test_fold() in_failing_test = False elif in_failure: if re.match("PASS", updated_line) or re.match("Ran", updated_line): in_failure = False else: updated_line = colored(updated_line, "yellow") elif re.search(r"\*\*\* Segmentation fault", updated_line): start_fold("segfault") updated_line = colored(updated_line, "magenta") elif re.match(" Test failed: Segmentation fault", updated_line): end_fold() else: if re.match(r"(FAIL|ERROR)[:\!].*", updated_line): updated_line = colored(updated_line, "yellow") in_failure = True if not in_failing_test and re.search( "[0-9]+% tests passed, [0-9]+ tests failed out of", updated_line ): tests_failing = re.match(r".* ([0-9]+) tests failed", updated_line).group(1) # updated_line += '\n::set-output name=TESTS_FAILING::{}'.format(tests_failing) end_fold() if re.search("100% tests passed", updated_line): updated_line = colored(updated_line, "green") if re.match("Submit files", updated_line): start_fold("submit") elif re.search("Test results submitted to", updated_line): cdash_url = re.match(r".*(http.*)$", updated_line).group(1) # updated_line += '\n::set-output name=CDASH_URL::{}'.format(cdash_url) end_fold() sys.stdout.write(updated_line) exit(p.wait())