diff --git a/tests/auto/testlib/selftests/generate_expected_output.py b/tests/auto/testlib/selftests/generate_expected_output.py index b917dacc782..1bf8cf6603c 100755 --- a/tests/auto/testlib/selftests/generate_expected_output.py +++ b/tests/auto/testlib/selftests/generate_expected_output.py @@ -32,89 +32,185 @@ ## ############################################################################# -#regenerate all test's output +# Regenerate all tests' output. +# +# Usage: cd to the build directory corresponding to this script's +# location; invoke this script; optionally pass the names of sub-dirs +# to limit which tests to regenerate expected_* files for. import os -import sys import subprocess -import re -formats = ['xml', 'txt', 'xunitxml', 'lightxml'] +class Fail (Exception): pass -qtver = subprocess.check_output(['qmake', '-query', 'QT_VERSION']).strip().decode('utf-8') -rootPath = os.getcwd() +class Cleaner (object): + """Tool to clean up test output to make diff-ing runs useful. -isWindows = sys.platform == 'win32' + We care about whether tests pass or fail - if that changes, + something that matters has happened - and we care about some + changes to what they say when they do fail; but we don't care + exactly what line of what file the failing line of code now + occupies, nor do we care how many milliseconds each test took to + run; and changes to the Qt version number mean nothing to us. -replacements = [ - (qtver, r'@INSERT_QT_VERSION_HERE@'), - (r'Config: Using QtTest library.*', r'Config: Using QtTest library'), # Build string in text logs - (rootPath.encode('unicode-escape').decode('utf-8'), r''), - (r'( *)', r'\1'), - (r'( *)[^<]+', r'\1'), # Build element in xml, lightxml - (r'', r'') # Build in xunitxml -] + Create one singleton instance; it'll do mildly expensive things + once and you can use its .clean() method to tidy up your test + output.""" -extraArgs = { - "commandlinedata": "fiveTablePasses fiveTablePasses:fiveTablePasses_data1 -v2", - "benchlibcallgrind": "-callgrind", - "benchlibeventcounter": "-eventcounter", - "benchliboptions": "-eventcounter", - "benchlibtickcounter": "-tickcounter", - "badxml": "-eventcounter", - "benchlibcounting": "-eventcounter", - "printdatatags": "-datatags", - "printdatatagswithglobaltags": "-datatags", - "silent": "-silent", - "verbose1": "-v1", - "verbose2": "-v2", -} + def __init__(self, here, command): + """Set up the details we need for later cleaning. -# Replace all occurrences of searchExp in one file -def replaceInFile(file): - import sys - import fileinput - for line in fileinput.input(file, inplace=1): - for searchExp, replaceExp in replacements: - line = re.sub(searchExp, replaceExp, line) - sys.stdout.write(line) + Takes two parameters: here is $PWD and command is how this + script was invoked, from which we'll work out where it is; in + a shadow build, the former is the build tree's location + corresponding to this last. Checks $PWD does look as expected + in a build tree - raising Fail() if not - then invokes qmake + to discover Qt version (saved as .version for the benefit of + clients) and prepares the sequence of (regex, replace) pairs + that .clean() needs to do its job.""" + self.version, self.__replace = self.__getPatterns(here, command) -def subdirs(): - result = [] - for path in os.listdir('.'): - if os.path.isdir('./' + path): - result.append(path) - return result + import re + @staticmethod + def __getPatterns(here, command, + patterns = ( + # Timings: + (r'( *', r'\1"0"/>'), # xml, lightxml + (r'(Totals:.*,) *[0-9.]+ms', r'\1 0ms'), # txt + # Benchmarks: + (r'[0-9,.]+( (?:CPU ticks|msecs) per iteration \(total:) [0-9,.]+ ', r'0\1 0, '), # txt + (r'(,"(?:CPUTicks|WalltimeMilliseconds)"),\d+,\d+,', r'\1,0,0,'), # csv + (r'([^<]+', r'\1/>'), # xml, lightxml + (r'()', r'\1\2'), # xunitxml + # Line numbers in source files: + (r'(Loc: \[[^[\]()]+)\(\d+\)', r'\1(0)'), # txt + # (r'(\[Loc: [^[\]()]+)\(\d+\)', r'\1(0)'), # teamcity + (r'(