summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xscripts/generic/parse_build_log.pl29
-rw-r--r--scripts/generic/t/data/raw-logs/qtjsondb-sync-profile-syntax-error.txt6
-rw-r--r--scripts/lib/perl5/QtQA/TestScript.pm60
-rw-r--r--scripts/lib/perl5/QtQA/t/10-TestScript.t46
-rwxr-xr-xscripts/qt/qtmod_test.pl4
5 files changed, 111 insertions, 34 deletions
diff --git a/scripts/generic/parse_build_log.pl b/scripts/generic/parse_build_log.pl
index 0ef6cfb0..e13f4f89 100755
--- a/scripts/generic/parse_build_log.pl
+++ b/scripts/generic/parse_build_log.pl
@@ -1648,19 +1648,33 @@ my %RE = (
\QQtQA::App::TestRunner: the test seems to be flaky\E
}xms,
- # The line where a QtQA::TestScript::fatal_error YAML error opens.
+ # The line where a QtQA::TestScript YAML message opens.
+ #
+ # Captures:
+ #
+ # type - the type of message (currently 'error' or 'failure')
#
yaml_begin => qr{
\A
- \Q--- !qtqa.qt-project.org/error\E
+ \Q--- !qtqa.qt-project.org/\E
+ (?<type>
+ .{1,50}
+ )
\z
}xms,
- # The line where a QtQA::TestScript::fatal_error YAML error ends.
+ # The line where a QtQA::TestScript YAML message ends.
+ #
+ # Captures:
+ #
+ # type - the type of message (currently 'error' or 'failure')
#
yaml_end => qr{
\A
- \Q... \E\#\Q end qtqa.qt-project.org/error\E
+ \Q... \E\#\Q end qtqa.qt-project.org/\E
+ (?<type>
+ .{1,50}
+ )
\z
}xms,
@@ -2139,6 +2153,11 @@ sub yaml_chunk_handler
my $text = "$line\n" . $chunk_ref->{ details };
my $loaded = eval { YAML::Load( $text ) };
if ($loaded) {
+ # for backwards compatibility: message now named 'message', but used
+ # to be named 'error', support both for a while.
+ if (my $error = delete $loaded->{ error }) {
+ $loaded->{ message } = $error;
+ }
push @{$out->{ yaml_fail }}, $loaded;
} else {
warn "log seems to contain a corrupt YAML block:\n$text\nFailed to parse: $@";
@@ -2435,7 +2454,7 @@ sub extract_yaml_fail
my $lines_ref = $args{ lines_ref };
foreach my $error (@{ $fail->{ yaml_fail } || []} ) {
- my @lines = split( /\n/, $error->{ error } );
+ my @lines = split( /\n/, $error->{ message } );
push @{$lines_ref}, @lines;
# each failure gets one trailing blank line to separate it from others
push @{$lines_ref}, q{};
diff --git a/scripts/generic/t/data/raw-logs/qtjsondb-sync-profile-syntax-error.txt b/scripts/generic/t/data/raw-logs/qtjsondb-sync-profile-syntax-error.txt
index 582550f4..05a71bd4 100644
--- a/scripts/generic/t/data/raw-logs/qtjsondb-sync-profile-syntax-error.txt
+++ b/scripts/generic/t/data/raw-logs/qtjsondb-sync-profile-syntax-error.txt
@@ -144,8 +144,8 @@
4/12/12 5:33:31 AM EST: Cloning into /build/recipes/179081964/base/qt...
4/12/12 5:33:32 AM EST: String found where operator expected at /build/recipes/179081964/base/sync.profile line 36, near ""libedit""
4/12/12 5:33:32 AM EST: (Missing semicolon on previous line?)
-4/12/12 5:33:32 AM EST: --- !qtqa.qt-project.org/error
-4/12/12 5:33:32 AM EST: error: |+
+4/12/12 5:33:32 AM EST: --- !qtqa.qt-project.org/failure
+4/12/12 5:33:32 AM EST: message: |+
4/12/12 5:33:32 AM EST: I couldn't parse /build/recipes/179081964/base/sync.profile, which I need to determine dependencies.
4/12/12 5:33:32 AM EST: The error was syntax error at /build/recipes/179081964/base/sync.profile line 36, near ""libedit""
4/12/12 5:33:32 AM EST:
@@ -153,7 +153,7 @@
4/12/12 5:33:32 AM EST: - reading dependencies from qtjsondb/sync.profile
4/12/12 5:33:32 AM EST: - setting up git repositories
4/12/12 5:33:32 AM EST: - testing qtjsondb
-4/12/12 5:33:32 AM EST: ... # end qtqa.qt-project.org/error
+4/12/12 5:33:32 AM EST: ... # end qtqa.qt-project.org/failure
4/12/12 5:33:32 AM EST: at _qtqa_latest/scripts/qt/qtmod_test.pl line 444
4/12/12 5:33:32 AM EST: QtQA::ModuleTest::read_dependencies('QtQA::ModuleTest=HASH(0x9daa310)', '/home/rmcgover/build/qt/qt5/qtsvg/sync.profile') called at ../qtqa/scripts/qt/qtmod_test.pl line 513
4/12/12 5:33:32 AM EST: QtQA::ModuleTest::run_git_checkout('QtQA::ModuleTest=HASH(0x9daa310)') called at ../qtqa/scripts/qt/qtmod_test.pl line 211
diff --git a/scripts/lib/perl5/QtQA/TestScript.pm b/scripts/lib/perl5/QtQA/TestScript.pm
index d3ce37e8..fa801673 100644
--- a/scripts/lib/perl5/QtQA/TestScript.pm
+++ b/scripts/lib/perl5/QtQA/TestScript.pm
@@ -468,14 +468,32 @@ sub exe_qx
sub fatal_error
{
- my ($self, $error) = @_;
+ my ($self, $text) = @_;
- # We want to ensure that the 'error' key always comes first.
+ $self->_croak( $self->_format_yaml_block( 'error', $text ) );
+
+ return;
+}
+
+sub fail
+{
+ my ($self, $text) = @_;
+
+ $self->_croak( $self->_format_yaml_block( 'failure', $text ) );
+
+ return;
+}
+
+sub _format_yaml_block
+{
+ my ($self, $type, $text) = @_;
+
+ # We want to ensure that the 'message' key always comes first.
# This is why we use YAML::Node.
- my $id = 'qtqa.qt-project.org/error';
+ my $id = "qtqa.qt-project.org/$type";
my $ynode = YAML::Node->new({}, $id );
%{$ynode} = (
- error => $error,
+ message => $text,
);
my @context = @{ $self->{ _context } || [] };
@@ -486,12 +504,9 @@ sub fatal_error
local $YAML::UseBlock = 1;
my $formatted = YAML::Dump( $ynode );
- $self->_croak( "$formatted... # end $id\n" );
-
- return;
+ return "$formatted... # end $id\n";
}
-
sub doing
{
my ($self, $thing) = @_;
@@ -894,8 +909,8 @@ Example:
=item B<doing>( STRING )
Pushes the given STRING onto an internal context stack, which may then be used for
-stack traces produced on error (e.g. by L<fatal_error>). The STRING should be a
-human-readable summary of a task (e.g. "compiling the autotests").
+stack traces produced on error or failure (e.g. by L<fatal_error> or L<fail>).
+The STRING should be a human-readable summary of a task (e.g. "compiling the autotests").
Returns a reference. When that reference is destroyed, the task is popped off
the context stack. It is invalid to call this function without storing the return
@@ -919,7 +934,7 @@ Example:
my $doing = $self->doing( 'compiling the frobnitz' );
# sanity check
- (-e 'Makefile') || $self->fatal_error(
+ (-e 'Makefile') || $self->fail(
'configure succeeded, but no Makefile found!'
);
@@ -928,8 +943,8 @@ Example:
...
-In the above example, if the sanity check for the Makefile failed, the fatal
-error message would include a trace of the form:
+In the above example, if the sanity check for the Makefile failed, the failure
+message would include a trace of the form:
while:
- compiling the frobnitz
@@ -937,7 +952,7 @@ error message would include a trace of the form:
Usage note: the most important consumer of this information is the
C<parse_build_log.pl> script in the qtqa repository. When this script finds
-a fatal error with context information, it uses the topmost part of the context
+a failure or error with context information, it uses the topmost part of the context
stack as the failure summary (which is usually pasted into Gerrit). The failure
from the previous example code may be summarized as:
@@ -967,10 +982,27 @@ exited with status 123" where the process is expected to output its own error
messages - it is generally better not to use this function, as the formatted
error message is unlikely to provide any additional value.
+This function should be called only when I<errors> occur, not when I<failures>
+occur. In this context, a "failure" is attributable to the software under test,
+while an "error" is not. For example, when testing Qt, some .cpp files failing
+to compile is most likely a "failure", but some git repositories failing to
+clone is most likely an "error".
+
+The primary reason for differentiating between failures and errors is that it
+may make sense to retry some actions when errors occur, but it rarely makes
+sense to retry when failures occur.
+
It is highly recommended to make use of this function together with L<doing>.
See the documentation of that function for more information.
+=item B<fail>( STRING )
+
+Like L<fatal_error>, but for I<failures> rather than I<errors>; formats the
+given failure STRING into a human and machine-readable value, then dies
+with the formatted string.
+See L<fatal_error> for discussion on the difference between a failure and an
+error.
=item B<get_options_from_array>( ARRAYREF [, LIST ] )
diff --git a/scripts/lib/perl5/QtQA/t/10-TestScript.t b/scripts/lib/perl5/QtQA/t/10-TestScript.t
index 7e9c6260..b6170c44 100644
--- a/scripts/lib/perl5/QtQA/t/10-TestScript.t
+++ b/scripts/lib/perl5/QtQA/t/10-TestScript.t
@@ -453,7 +453,7 @@ sub test_fatal_error
(?:\n|\A)
\Q--- !qtqa.qt-project.org/error
-error: |
+message: |
Error occurred while making sandwich:
Somebody left the fridge door open all weekend
... \E\#\Q end qtqa.qt-project.org/error\E
@@ -464,26 +464,51 @@ error: |
return;
}
-sub test_doing_with_fatal_error
+sub test_fail
{
my $script = QtQA::TestScript->new;
- my $error_header = qq{--- !qtqa.qt-project.org/error\nerror: };
+ throws_ok {
+ $script->fail(
+ "Error occurred while making sandwich:\n"
+ ."Somebody left the fridge door open all weekend\n"
+ );
+ } qr{
+
+(?:\n|\A)
+\Q--- !qtqa.qt-project.org/failure
+message: |
+ Error occurred while making sandwich:
+ Somebody left the fridge door open all weekend
+... \E\#\Q end qtqa.qt-project.org/failure\E
+(?:\n|\z)
+
+ }xms, 'fail output looks OK';
+
+ return;
+}
- my $expected_error_for_scopes = sub {
- my ($error, @scopes) = @_;
+sub test_doing
+{
+ my $script = QtQA::TestScript->new;
+
+ my $make_expected = sub {
+ my ($type, $message, @scopes) = @_;
@scopes = reverse @scopes;
return
- "${error_header}$error\n"
+ "--- !qtqa.qt-project.org/$type\nmessage: $message\n"
.(@scopes
? "while:\n - "
.join("\n - ", @scopes)
."\n"
: q{}
)
- ."... # end qtqa.qt-project.org/error\n";
+ ."... # end qtqa.qt-project.org/$type\n";
};
+ my $expected_error_for_scopes = sub { return $make_expected->( 'error', @_ ) };
+ my $expected_failure_for_scopes = sub { return $make_expected->( 'failure', @_ ) };
+
{
my $outer = $script->doing( 'outer1' );
@@ -493,8 +518,8 @@ sub test_doing_with_fatal_error
throws_ok { $script->fatal_error( 'quux' ) } qr{\A\Q$expected\E}, 'two scopes';
}
- my $expected = $expected_error_for_scopes->( 'bar', 'outer1' );
- throws_ok { $script->fatal_error( 'bar' ) } qr{\A\Q$expected\E}, 'one scope';
+ my $expected = $expected_failure_for_scopes->( 'bar', 'outer1' );
+ throws_ok { $script->fail( 'bar' ) } qr{\A\Q$expected\E}, 'one scope';
}
my $expected = $expected_error_for_scopes->( 'baz' );
@@ -521,7 +546,8 @@ sub run_test
test_exe_qx;
test_fatal_error;
- test_doing_with_fatal_error;
+ test_fail;
+ test_doing;
return;
}
diff --git a/scripts/qt/qtmod_test.pl b/scripts/qt/qtmod_test.pl
index a5aa2d2b..49b16624 100755
--- a/scripts/qt/qtmod_test.pl
+++ b/scripts/qt/qtmod_test.pl
@@ -569,7 +569,7 @@ sub read_dependencies
($action, $error) = ('execute', $!);
}
if ($error) {
- $self->fatal_error(
+ $self->fail(
"I couldn't $action $dependency_file, which I need to determine dependencies.\n"
."The error was $error\n"
);
@@ -1059,7 +1059,7 @@ sub run_install_check
my @required_files = map { "$qt_install_dir/$_" } qw(bin include);
my @missing_files = grep { ! -e $_ } @required_files;
if (@missing_files) {
- $self->fatal_error(
+ $self->fail(
'The make install command exited successfully, but the following expected file(s) '
.'are missing from the install tree:'.join("\n ", q{}, @missing_files)."\n"
);