X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/eb6970c22550a14398d08be4b4bc5824b81c7b89..198e3ed3d692a2668a1609ae85760a5010dc78e7:/tools/tesh/tesh.py diff --git a/tools/tesh/tesh.py b/tools/tesh/tesh.py index d62cd7f921..2552c71b4d 100755 --- a/tools/tesh/tesh.py +++ b/tools/tesh/tesh.py @@ -5,12 +5,11 @@ tesh -- testing shell ======================== -Copyright (c) 2012-2019. The SimGrid Team. All rights reserved. +Copyright (c) 2012-2021. The SimGrid Team. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the license (GNU LGPL) which comes with this package. - #TODO: child of child of child that printfs. Does it work? #TODO: a child dies after its parent. What happen? @@ -25,7 +24,6 @@ under the terms of the license (GNU LGPL) which comes with this package. """ - import sys import os import shlex @@ -33,6 +31,7 @@ import re import difflib import signal import argparse +import time if sys.version_info[0] == 3: import subprocess @@ -46,14 +45,12 @@ else: # # - def isWindows(): return sys.platform.startswith('win') # Singleton metaclass that works in Python 2 & 3 # http://stackoverflow.com/questions/6760685/creating-a-singleton-in-python - class _Singleton(type): """ A metaclass that creates a Singleton base class when called. """ _instances = {} @@ -63,11 +60,9 @@ class _Singleton(type): cls._instances[cls] = super(_Singleton, cls).__call__(*args, **kwargs) return cls._instances[cls] - class Singleton(_Singleton('SingletonMeta', (object,), {})): pass - SIGNALS_TO_NAMES_DICT = dict((getattr(signal, n), n) for n in dir(signal) if n.startswith('SIG') and '_' not in n) @@ -100,14 +95,6 @@ def setenv(arg): def expandvars2(path): return re.sub(r'(? timeout after {timeout} sec)".format( file=FileReader().filename, cmd=cmdName, timeout=self.timeout)) - running_pgids.remove(local_pgid) - kill_process_group(local_pgid) + running_pids.remove(local_pid) + kill_process_group(local_pid) # Try to get the output of the timeout process, to help in debugging. try: (stdout_data, stderr_data) = proc.communicate(timeout=1) @@ -410,7 +412,7 @@ class Cmd(object): logs.append("(ignoring the output of <{cmd}> as requested)".format(cmd=cmdName)) else: stdouta = stdout_data.split("\n") - while len(stdouta) > 0 and stdouta[-1] == "": + while stdouta and stdouta[-1] == "": del stdouta[-1] stdouta = self.remove_ignored_lines(stdouta) stdcpy = stdouta[:] @@ -430,7 +432,7 @@ class Cmd(object): lineterm="", fromfile='expected', tofile='obtained')) - if len(diff) > 0: + if diff: logs.append("Output of <{cmd}> mismatch:".format(cmd=cmdName)) if self.sort >= 0: # If sorted, truncate the diff output and show the unsorted version difflen = 0 @@ -454,7 +456,7 @@ class Cmd(object): if TeshState().keep: f = open('obtained', 'w') obtained = stdout_data.split("\n") - while len(obtained) > 0 and obtained[-1] == "": + while obtained and obtained[-1] == "": del obtained[-1] obtained = self.remove_ignored_lines(obtained) for line in obtained: @@ -470,7 +472,7 @@ class Cmd(object): print('\n'.join(logs)) return - if proc.returncode != self.expect_return: + if not proc.returncode in self.expect_return: if proc.returncode >= 0: logs.append("Test suite `{file}': NOK (<{cmd}> returned code {code})".format( file=FileReader().filename, cmd=cmdName, code=proc.returncode)) @@ -479,15 +481,15 @@ class Cmd(object): return_code = max(2, return_code) print('\n'.join(logs)) return - else: - logs.append("Test suite `{file}': NOK (<{cmd}> got signal {sig})".format( - file=FileReader().filename, cmd=cmdName, - sig=SIGNALS_TO_NAMES_DICT[-proc.returncode])) - if lock is not None: - lock.release() - return_code = max(max(-proc.returncode, 1), return_code) - print('\n'.join(logs)) - return + + logs.append("Test suite `{file}': NOK (<{cmd}> got signal {sig})".format( + file=FileReader().filename, cmd=cmdName, + sig=SIGNALS_TO_NAMES_DICT[-proc.returncode])) + if lock is not None: + lock.release() + return_code = max(max(-proc.returncode, 1), return_code) + print('\n'.join(logs)) + return if lock is not None: lock.release() @@ -497,14 +499,12 @@ class Cmd(object): def can_run(self): return self.args is not None - ############## # # Main # # - if __name__ == '__main__': signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) @@ -522,7 +522,7 @@ if __name__ == '__main__': group1.add_argument( '--ignore-jenkins', action='store_true', - help='ignore all cruft generated on SimGrid continous integration servers') + help='ignore all cruft generated on SimGrid continuous integration servers') group1.add_argument('--wrapper', metavar='arg', help='Run each command in the provided wrapper (eg valgrind)') group1.add_argument( '--keep', @@ -536,7 +536,7 @@ if __name__ == '__main__': os.chdir(options.cd) if options.ignore_jenkins: - print("Ignore all cruft seen on SimGrid's continous integration servers") + print("Ignore all cruft seen on SimGrid's continuous integration servers") # Note: regexps should match at the beginning of lines TeshState().ignore_regexps_common = [ re.compile(r"profiling:"), @@ -545,14 +545,14 @@ if __name__ == '__main__': re.compile(r"Picked up JAVA_TOOL_OPTIONS: "), re.compile(r"Picked up _JAVA_OPTIONS: "), re.compile(r"==[0-9]+== ?WARNING: ASan doesn't fully support"), - re.compile(r"==[0-9]+== ?WARNING: ASan is ignoring requested __asan_handle_no_return: stack top:"), + re.compile(r"==[0-9]+== ?WARNING: ASan is ignoring requested __asan_handle_no_return: stack "), re.compile(r"False positive error reports may follow"), - re.compile(r"For details see http://code.google.com/p/address-sanitizer/issues/detail\?id=189"), - re.compile(r"For details see https://github.com/google/sanitizers/issues/189"), + re.compile(r"For details see http://code\.google\.com/p/address-sanitizer/issues/detail\?id=189"), + re.compile(r"For details see https://github\.com/google/sanitizers/issues/189"), re.compile(r"Python runtime initialized with LC_CTYPE=C .*"), # Seen on CircleCI re.compile(r"cmake: /usr/local/lib/libcurl\.so\.4: no version information available \(required by cmake\)"), - re.compile(r".*mmap broken on FreeBSD, but dlopen\+thread broken too. Switching to dlopen\+raw contexts\."), + re.compile(r".*mmap broken on FreeBSD, but dlopen\+thread broken too\. Switching to dlopen\+raw contexts\."), re.compile(r".*dlopen\+thread broken on Apple and BSD\. Switching to raw contexts\."), ] TeshState().jenkins = True # This is a Jenkins build @@ -592,7 +592,7 @@ if __name__ == '__main__': line = f.readfullline() while line is not None: # print(">>============="+line+"==<<") - if len(line) == 0: + if not line: #print ("END CMD block") if cmd.run_if_possible(): cmd = Cmd() @@ -631,16 +631,17 @@ if __name__ == '__main__': cmd.output_display = True cmd.ignore_output = True elif line[0:15] == "! expect return": - cmd.expect_return = int(line[16:]) + cmd.expect_return = [int(line[16:])] #print("expect return "+str(int(line[16:]))) elif line[0:15] == "! expect signal": - sig = line[16:] - # get the signal integer value from the signal module - if sig not in signal.__dict__: - fatal_error("unrecognized signal '" + sig + "'") - sig = int(signal.__dict__[sig]) - # popen return -signal when a process ends with a signal - cmd.expect_return = -sig + cmd.expect_return = [] + for sig in (line[16:]).split("|"): + # get the signal integer value from the signal module + if sig not in signal.__dict__: + fatal_error("unrecognized signal '" + sig + "'") + sig = int(signal.__dict__[sig]) + # popen return -signal when a process ends with a signal + cmd.expect_return.append(-sig) elif line[0:len("! timeout ")] == "! timeout ": if "no" in line[len("! timeout "):]: cmd.timeout = None @@ -673,5 +674,4 @@ if __name__ == '__main__': print("Test suite from stdin OK") else: print("Test suite `" + f.filename + "' OK") - else: - tesh_exit(return_code) + tesh_exit(return_code)