sanitycheck: enable valgrind checking using an option

Enable valgrind using --enable-valgrind option and fix reporting.

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
This commit is contained in:
Anas Nashif 2019-10-11 07:32:45 -07:00
commit c1ea45280b

View file

@ -203,6 +203,7 @@ import logging
hw_map_local = threading.Lock() hw_map_local = threading.Lock()
report_lock = threading.Lock()
log_format = "%(levelname)s %(name)s::%(module)s.%(funcName)s():%(lineno)d: %(message)s" log_format = "%(levelname)s %(name)s::%(module)s.%(funcName)s():%(lineno)d: %(message)s"
@ -522,7 +523,6 @@ class BinaryHandler(Handler):
""" """
super().__init__(instance, type_str) super().__init__(instance, type_str)
self.valgrind = False
self.terminated = False self.terminated = False
def try_kill_process_by_pid(self): def try_kill_process_by_pid(self):
@ -566,12 +566,14 @@ class BinaryHandler(Handler):
else: else:
command = [self.binary] command = [self.binary]
if self.valgrind and shutil.which("valgrind"): run_valgrind = False
if options.enable_valgrind and shutil.which("valgrind"):
command = ["valgrind", "--error-exitcode=2", command = ["valgrind", "--error-exitcode=2",
"--leak-check=full", "--leak-check=full",
"--suppressions="+ZEPHYR_BASE+"/scripts/valgrind.supp", "--suppressions="+ZEPHYR_BASE+"/scripts/valgrind.supp",
"--log-file="+self.build_dir+"/valgrind.log" "--log-file="+self.build_dir+"/valgrind.log"
] + command ] + command
run_valgrind = True
verbose("Spawning process: " + verbose("Spawning process: " +
" ".join(shlex.quote(word) for word in command) + os.linesep + " ".join(shlex.quote(word) for word in command) + os.linesep +
@ -605,17 +607,22 @@ class BinaryHandler(Handler):
subprocess.call(["stty", "sane"]) subprocess.call(["stty", "sane"])
self.instance.results = harness.tests self.instance.results = harness.tests
if not self.terminated and self.returncode != 0: if not self.terminated and self.returncode != 0:
#When a process is killed, the default handler returns 128 + SIGTERM #When a process is killed, the default handler returns 128 + SIGTERM
#so in that case the return code itself is not meaningful #so in that case the return code itself is not meaningful
self.set_state("failed", handler_time) self.set_state("failed", handler_time)
self.instance.reason = "Handler error" self.instance.reason = "Handler Error"
elif run_valgrind and self.returncode == 2:
self.set_state("failed", handler_time)
self.instance.reason = "Valgrind error"
elif harness.state: elif harness.state:
self.set_state(harness.state, handler_time) self.set_state(harness.state, handler_time)
else: else:
self.set_state("timeout", handler_time) self.set_state("timeout", handler_time)
self.instance.reason = "Handler timeout" self.instance.reason = "Handler timeout"
self.record(harness) self.record(harness)
class DeviceHandler(Handler): class DeviceHandler(Handler):
@ -796,7 +803,6 @@ class DeviceHandler(Handler):
if c not in harness.tests: if c not in harness.tests:
harness.tests[c] = "BLOCK" harness.tests[c] = "BLOCK"
handler_time = time.time() - start_time handler_time = time.time() - start_time
self.instance.results = harness.tests self.instance.results = harness.tests
@ -1737,7 +1743,6 @@ class CMake():
msg = "Finished building %s for %s" %(self.source_dir, self.platform.name) msg = "Finished building %s for %s" %(self.source_dir, self.platform.name)
self.instance.status = "passed" self.instance.status = "passed"
self.instance.reason = ""
results = {'msg': msg, "returncode": p.returncode, "instance": self.instance} results = {'msg': msg, "returncode": p.returncode, "instance": self.instance}
if out: if out:
@ -1988,7 +1993,6 @@ class ProjectBuilder(FilterBuilder):
verbose("run test: %s" %self.instance.name) verbose("run test: %s" %self.instance.name)
self.run() self.run()
self.instance.status, _ = self.instance.handler.get_state() self.instance.status, _ = self.instance.handler.get_state()
self.instance.reason = ""
pipeline.put({ pipeline.put({
"op": "report", "op": "report",
"test": self.instance, "test": self.instance,
@ -1999,7 +2003,22 @@ class ProjectBuilder(FilterBuilder):
# Report results and output progress to screen # Report results and output progress to screen
elif op == "report": elif op == "report":
self.report_out() with report_lock:
self.report_out()
def log_info_file(self, instance):
build_dir = instance.build_dir
h_log = "{}/handler.log".format(build_dir)
b_log = "{}/build.log".format(build_dir)
v_log = "{}/valgrind.log".format(build_dir)
if os.path.exists(v_log) and "Valgrind" in instance.reason:
log_info("{}".format(v_log))
elif os.path.exists(h_log):
log_info("{}".format(h_log))
else:
log_info("{}".format(b_log))
def report_out(self): def report_out(self):
total_tests_width = len(str(self.suite.total_tests)) total_tests_width = len(str(self.suite.total_tests))
@ -2012,25 +2031,17 @@ class ProjectBuilder(FilterBuilder):
status = COLOR_RED + "FAILED " + COLOR_NORMAL + instance.reason status = COLOR_RED + "FAILED " + COLOR_NORMAL + instance.reason
else: else:
info( info(
"{:<25} {:<50} {}FAILED{}: {}".format( "\n{:<25} {:<50} {}FAILED{}: {}".format(
instance.platform.name, instance.platform.name,
instance.testcase.name, instance.testcase.name,
COLOR_RED, COLOR_RED,
COLOR_NORMAL, COLOR_NORMAL,
instance.reason), False) instance.reason), False)
if not VERBOSE:
# FIXME self.log_info_file(instance)
h_log = "{}/handler.log".format(instance.build_dir)
b_log = "{}/build.log".format(instance.build_dir)
if os.path.exists(h_log):
log_info("{}".format(h_log))
else:
log_info("{}".format(b_log))
elif instance.status == "skipped": elif instance.status == "skipped":
self.suite.total_skipped += 1 self.suite.total_skipped += 1
status = COLOR_YELLOW + "SKIPPED" + COLOR_NORMAL status = COLOR_YELLOW + "SKIPPED" + COLOR_NORMAL
else: else:
status = COLOR_GREEN + "PASSED" + COLOR_NORMAL status = COLOR_GREEN + "PASSED" + COLOR_NORMAL
@ -2053,13 +2064,7 @@ class ProjectBuilder(FilterBuilder):
instance.testcase.name, status, more_info)) instance.testcase.name, status, more_info))
if instance.status in ["failed", "timeout"]: if instance.status in ["failed", "timeout"]:
h_log = "{}/handler.log".format(instance.build_dir) self.log_info_file(instance)
b_log = "{}/build.log".format(instance.build_dir)
if os.path.exists(h_log):
log_info("{}".format(h_log))
else:
log_info("{}".format(b_log))
else: else:
sys.stdout.write("\rtotal complete: %s%4d/%4d%s %2d%% skipped: %s%4d%s, failed: %s%4d%s" % ( sys.stdout.write("\rtotal complete: %s%4d/%4d%s %2d%% skipped: %s%4d%s, failed: %s%4d%s" % (
COLOR_GREEN, COLOR_GREEN,
@ -3342,6 +3347,13 @@ structure in the main Zephyr tree: boards/<arch>/<board_name>/""")
NOTE: west-flash must be enabled to use this option. NOTE: west-flash must be enabled to use this option.
""" """
) )
parser.add_argument(
"--enable-valgrind", action="store_true",
help="""Run binary through valgrind and check for several memory access
errors." Valgrind needs to be installed on the host. This option only
works with host binaries such as those generated for the native_posix
configuration.
""")
parser.add_argument("--enable-coverage", action="store_true", parser.add_argument("--enable-coverage", action="store_true",
help="Enable code coverage using gcov.") help="Enable code coverage using gcov.")
@ -3378,7 +3390,7 @@ def log_info(filename):
log_file.write(data) log_file.write(data)
info("{:-^100}".format(filename)) info("{:-^100}".format(filename))
else: else:
info("\tsee: " + COLOR_YELLOW + filename + COLOR_NORMAL) info("\n\tsee: " + COLOR_YELLOW + filename + COLOR_NORMAL)
def size_report(sc): def size_report(sc):
info(sc.filename) info(sc.filename)