From cdab17f69cb1ed56f5e0223e29314f61a5f0b516 Mon Sep 17 00:00:00 2001 From: Nikita Kniazev Date: Sun, 16 Jul 2023 16:36:39 +0300 Subject: [PATCH] Fix disappeared messages from asserts (#301) Regressed after porting assert and errors modules to native modules. --- src/engine/mod_jam_errors.cpp | 9 ++++++- test/BoostBuild.py | 50 ++++++++++++++++++----------------- test/assert.py | 29 ++++++++++++++++++++ test/test_all.py | 1 + 4 files changed, 64 insertions(+), 25 deletions(-) create mode 100644 test/assert.py diff --git a/src/engine/mod_jam_errors.cpp b/src/engine/mod_jam_errors.cpp index e7241e7f09..87e13e90f5 100644 --- a/src/engine/mod_jam_errors.cpp +++ b/src/engine/mod_jam_errors.cpp @@ -114,6 +114,7 @@ void error_skip_frames(std::tuple skip_messages, { lists messages; messages.push_back(std::move(std::get<1>(skip_messages))); + messages.append(rest); error_skip_frames(std::get<0>(skip_messages), messages, context_ref); } @@ -195,7 +196,9 @@ void warning(const lists & rest, bind::context_ref_ context_ref) list_ref lol_to_list(const lists & rest) { list_ref result; - for (lists::size_type i = 0; i < rest.length(); ++i) + lists::size_type size = rest.length(); + while (size > 0 && rest[size - 1].empty()) --size; + for (lists::size_type i = 0; i < size; ++i) { if (i != 0) result.push_back(":"); for (auto l : rest[i]) @@ -230,6 +233,10 @@ if --no-error-backtrace in [ modules.peek : ARGV ] rule __test__ ( ) { + import assert ; + + assert.result \"a\" \"b\" \"c\" ":" \"d\" : lol->list a b c : d ; + # Show that we can correctly catch an expected error. try ; { diff --git a/test/BoostBuild.py b/test/BoostBuild.py index bed89c8bfb..1ea15d6263 100644 --- a/test/BoostBuild.py +++ b/test/BoostBuild.py @@ -458,7 +458,7 @@ def dump_stdio(self): annotation("STDERR", self.stderr()) def run_build_system(self, extra_args=None, subdir="", stdout=None, - stderr="", status=0, match=None, pass_toolset=None, + stderr="", status=0, match=None, match_filter=None, pass_toolset=None, use_test_config=None, ignore_toolset_requirements=None, expected_duration=None, **kw): @@ -539,29 +539,15 @@ def run_build_system(self, extra_args=None, subdir="", stdout=None, annotation("reason", "unexpected status returned by bjam") self.fail_test(1) - if stdout is not None and not match(self.stdout(), stdout): - stdout_test = match(self.stdout(), stdout) - annotation("failure", "Unexpected stdout") - annotation("Expected STDOUT", stdout) - annotation("Actual STDOUT", self.stdout()) - stderr = self.stderr() - if stderr: - annotation("STDERR", stderr) - self.do_diff(self.stdout(), stdout) - self.fail_test(1, dump_stdio=False) + if stdout is not None: + self.do_diff('STDOUT', self.stdout(), stdout, match, match_filter) # Intel tends to produce some messages to stderr which make tests fail. intel_workaround = re.compile("^xi(link|lib): executing.*\n", re.M) actual_stderr = re.sub(intel_workaround, "", self.stderr()) - if stderr is not None and not match(actual_stderr, stderr): - stderr_test = match(actual_stderr, stderr) - annotation("failure", "Unexpected stderr") - annotation("Expected STDERR", stderr) - annotation("Actual STDERR", self.stderr()) - annotation("STDOUT", self.stdout()) - self.do_diff(actual_stderr, stderr) - self.fail_test(1, dump_stdio=False) + if stderr is not None: + self.do_diff('STDERR', actual_stderr, stderr, match, match_filter) if expected_duration is not None: actual_duration = build_time_finish - build_time_start @@ -571,6 +557,27 @@ def run_build_system(self, extra_args=None, subdir="", stdout=None, expected_duration)) self.fail_test(1, dump_stdio=False) + def do_diff(self, what, actual, expected, matcher, match_filter): + actual_lines = actual.splitlines(keepends=True) + expected_lines = expected.splitlines(keepends=True) + if match_filter is not None: + actual_lines = list(filter(match_filter, actual_lines)) + expected_lines = list(filter(match_filter, expected_lines)) + match = matcher("".join(actual_lines), "".join(expected_lines)) + filtered = " (filtered)" + else: + match = matcher(actual, expected) + filtered = "" + if match: + return + diff = "".join(ndiff(expected_lines, actual_lines)) + annotation(f"Expected {what}", expected) + annotation(f"Actual {what}", actual) + if what.lower() == "stdout": + annotation("STDERR", self.stderr()) + annotation(f"Difference in {what}{filtered}", diff) + self.fail_test(True, dump_stdio=False) + def glob_file(self, name): name = self.adjust_name(name) result = None @@ -816,11 +823,6 @@ def sorted_(z): print(actual) self.fail_test(1) - def do_diff(self, actual, expected): - actual = actual.splitlines(keepends=True) - expected = expected.splitlines(keepends=True) - annotation("DIFFERENCE", "".join(ndiff(actual, expected))) - # Internal methods. def adjust_lib_name(self, name): global lib_prefix diff --git a/test/assert.py b/test/assert.py new file mode 100644 index 0000000000..94a4ea361d --- /dev/null +++ b/test/assert.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 + +# Copyright 2023 Nikita Kniazev +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE.txt or copy at +# https://www.bfgroup.xyz/b2/LICENSE.txt) + +# Tests assert module + +import BoostBuild + +t = BoostBuild.Tester(pass_toolset=False) + +t.write("Jamroot", """\ +import assert ; + +rule foo ( ) { return 1 2 3 ; } + +assert.result 1 2 4 : foo ; +""") + +t.run_build_system(status=1, stdout="""\ +error: assertion failure: [ foo ] +error: Expected: [ "1" "2" "4" ] +error: Got: [ "1" "2" "3" ] +""", match_filter=lambda x: "from module" not in x) +t.expect_nothing_more() + +t.cleanup() diff --git a/test/test_all.py b/test/test_all.py index 7802da1269..43b71361cf 100755 --- a/test/test_all.py +++ b/test/test_all.py @@ -231,6 +231,7 @@ def reorder_tests(tests, first_test): "alias", "alternatives", "always", + "assert", "bad_dirname", "build_dir", "build_file",