#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
***************************************************************************
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 will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
# 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 sys
import re
import subprocess
from termcolor import colored
import string
fold_stack = list()
printable = set(string.printable)
def start_fold(tag):
sys.stdout.write('::group::{}\n'.format(tag))
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('test.{}'.format(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('build')
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=build
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())