print("[Tesh/CRITICAL] " + str(msg))
tesh_exit(1)
+# retrocompatibility: support ${aaa:=.} variable format
+def replace_perl_variables(arg):
+ vname = arg.group(1)
+ vdefault = arg.group(2)
+ if vname in os.environ:
+ return "$" + vname
+ return vdefault
def setenv(arg):
"""
Set an environment variable.
arg must be a string with the format "variable=value"
"""
- print("[Tesh/INFO] setenv " + arg)
+ if '$' in arg:
+ arg = re.sub(r"\${(\w+):=([^}]*)}", replace_perl_variables, arg)
+ arg = expandvars2(arg)
(var, val) = arg.split("=", 1)
+ print("[Tesh/INFO] setenv " + var + "=" + val)
os.environ[var] = val
# os.putenv(var, val) does not work
# see http://stackoverflow.com/questions/17705419/python-os-environ-os-putenv-usr-bin-env
self.args_suffix = ""
self.ignore_regexps_common = []
self.jenkins = False # not a Jenkins run by default
+ self.auto_valgrind = True
self.timeout = 10 # default value: 10 sec
self.wrapper = None
self.keep = False
self.output_display = False
self.sort = -1
+ self.rerun_with_valgrind = False
self.ignore_regexps = TeshState().ignore_regexps_common
_thread.start_new_thread(Cmd._run, (self, lock))
else:
self._run()
+ if self.rerun_with_valgrind and TeshState().auto_valgrind:
+ print('\n\n\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')
+ print( 'XXXXXXXXX Rerunning this test with valgrind to help debugging it XXXXXXXXX')
+ print( 'XXXXXXXX (this will fail if valgrind is not installed, of course) XXXXXXXX')
+ print( 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n\n\n')
+
+ self.args = "valgrind " + self.args
+ self._run()
return True
+
def _run(self, lock=None):
# Python threads loose the cwd
os.chdir(self.cwd)
- # retrocompatibility: support ${aaa:=.} variable format
- def replace_perl_variables(arg):
- vname = arg.group(1)
- vdefault = arg.group(2)
- if vname in os.environ:
- return "$" + vname
- return vdefault
-
self.args = re.sub(r"\${(\w+):=([^}]*)}", replace_perl_variables, self.args)
# replace bash environment variables ($THINGS) to their values
self.args += TeshState().args_suffix
logs = list()
- logs.append("[{file}:{number}] {args}".format(file=FileReader().filename,
- number=self.linenumber, args=self.args))
+ msg = "[{file}:{number}] {args}".format(file=FileReader().filename, number=self.linenumber, args=self.args)
+ if self.background:
+ logs.append(msg)
+ else:
+ print(msg, flush=True)
args = shlex.split(self.args)
print('\n'.join(logs))
return
- if self.output_display:
- logs.append(str(stdout_data))
-
# remove text colors
ansi_escape = re.compile(r'\x1b[^m]*m')
stdout_data = ansi_escape.sub('', stdout_data)
+ if self.output_display:
+ logs.append(str(stdout_data))
+
+ if self.rerun_with_valgrind:
+ print(str(stdout_data), file=sys.stderr)
+ return
+
if self.ignore_output:
logs.append("(ignoring the output of <{cmd}> as requested)".format(cmd=cmd_name))
else:
logs.append("Test suite `{file}': NOK (<{cmd}> output mismatch)".format(
file=FileReader().filename, cmd=cmd_name))
+
+ # Also report any failed return code and/or signal we got in case of output mismatch
+ if not proc.returncode in self.expect_return:
+ if proc.returncode >= 0:
+ logs.append("In addition, <{cmd}> returned code {code}.".format(
+ cmd=cmd_name, code=proc.returncode))
+ else:
+ logs.append("In addition, <{cmd}> got signal {sig}.".format(cmd=cmd_name,
+ sig=SIGNALS_TO_NAMES_DICT[-proc.returncode]))
+ if proc.returncode == -signal.SIGSEGV:
+ self.rerun_with_valgrind = True
+
if lock is not None:
lock.release()
if TeshState().keep:
logs.append("Test suite `{file}': NOK (<{cmd}> got signal {sig})".format(
file=FileReader().filename, cmd=cmd_name,
sig=SIGNALS_TO_NAMES_DICT[-proc.returncode]))
+
+ if proc.returncode == -signal.SIGSEGV:
+ self.rerun_with_valgrind = True
+
if lock is not None:
lock.release()
TeshState().set_return_code(max(-proc.returncode, 1))
'--ignore-jenkins',
action='store_true',
help='ignore all cruft generated on SimGrid continuous integration servers')
+ group1.add_argument(
+ '--no-auto-valgrind',
+ action='store_true',
+ help='do not automaticall launch segfaulting commands in valgrind')
group1.add_argument('--wrapper', metavar='arg', help='Run each command in the provided wrapper (eg valgrind)')
group1.add_argument(
'--keep',
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 .*"),
+ re.compile(r"sthread is intercepting the execution of \.*"),
# Seen on CircleCI
re.compile(r"cmake: /usr/local/lib/libcurl\.so\.4: no version information available \(required by cmake\)"),
re.compile(
]
TeshState().jenkins = True # This is a Jenkins build
+ if options.no_auto_valgrind:
+ TeshState().auto_valgrind = False
+
if options.teshfile is None:
file = FileReader(None)
print("Test suite from stdin")
cmd.output_display = True
cmd.ignore_output = True
elif line[0:15] == "! expect return":
- cmd.expect_return = [int(line[16:])]
+ try:
+ cmd.expect_return = [int(line[16:])]
+ except ValueError as err:
+ fatal_error("Invalid expect return value: \""+(line[16:])+"\"")
#print("expect return "+str(int(line[16:])))
elif line[0:15] == "! expect signal":
cmd.expect_return = []
if "no" in line[len("! timeout "):]:
cmd.timeout = None
else:
- cmd.timeout = int(line[len("! timeout "):])
+ try:
+ cmd.timeout = [int(line[len("! timeout "):])]
+ except ValueError as err:
+ fatal_error("Invalid timeout value: \""+(line[len("! timeout "):])+"\"")
elif line[0:len("! output sort")] == "! output sort":
if len(line) >= len("! output sort "):
- sort = int(line[len("! output sort "):])
+ try:
+ sort = int(line[len("! output sort "):])
+ except ValueError as err:
+ fatal_error("Invalid sort value: \""+(line[len("! output sort "):])+"\"")
else:
sort = 0
cmd.sort = sort
cmd.add_ignore(line[len("! ignore "):])
else:
- fatal_error("UNRECOGNIZED OPTION")
+ fatal_error(f"UNRECOGNIZED OPTION LINE: {line}\n"
+ "Valid requests:\n"
+ " ! output ignore\n"
+ " ! output sort\n"
+ " ! output display\n"
+ " ! setenv XX=YY\n"
+ " ! ignore XYZ\n"
+ " ! expect return NN\n"
+ " ! expect signal NN\n"
+ " ! timeout NN\n")
line = file.readfullline()