Revision control

Copy as Markdown

# Copyright (C) 2017 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
package QtQA::Proc::Reliable::TESTDATA;
use strict;
use warnings;
=head1 NAME
QtQA::Proc::Reliable::TESTDATA - testdata for system tests of QtQA::Proc::Reliable
=head1 DESCRIPTION
This module is not intended for use by the end-user of QtQA::Proc::Reliable.
It is merely a holding area for a suite of testdata to be used in a few autotests
relating to QtQA::Proc::Reliable.
=cut
use Tie::IxHash;
use Readonly;
use base 'Exporter';
our @EXPORT_OK = qw( %TESTDATA );
# Helper regex portions for below testdata
Readonly my %RE => (
# Matches the text which states we're about to retry a command (not including the reason)
retry => qr{ \QQtQA::TestScript: It will be retried because\E }xms,
# Matches the reason why a command was restarted.
# These are set by the specific QtQA::Proc::Reliable strategies and are cumbersome
# to test, so we simply allow for any properly formatted text.
retry_reason => qr{
(?:
[^\n] # reason fits on a single line ...
| #
\nQtQA::TestScript: # ... or it takes multiple lines, all of them prefixed
)*
}xms,
# Matches the prefix on the line where the attempted command is printed
command => qr{
\QQtQA::TestScript: \E\$command
}xms,
# Matches the prefix for "the (n'th) attempt at running this command ..."
# Usage example: $RE{ attempt }{ second }
attempt => {
map {
$_ => qr{ \QQtQA::TestScript: The $_ attempt at running this command:\E }xms
}
qw(
first
second
third
fourth
fifth
sixth
) # add any more as needed
},
# Matches the text generated by failing with an exit code
# Usage example: $RE{ failed_with_exitcode }{ 12 }
failed_with_exitcode => {
map {
$_ => qr{ \QQtQA::TestScript: ... failed with exit code $_.\E }xms
}
(1..255)
},
);
# This is tied to retain order, as we want the tests to be run in order from least
# to most complex.
#
# Note, can't be Readonly without causing Params::Validate to segfault :(
tie our %TESTDATA => 'Tie::IxHash',
# simple passing command to ensure correct operation in the normal case
'git control' => {
command => [ 'git', 'clone', 'git://example.com/repo.git' ],
mock_command => {
sequence => [
{ exitcode => 0, stdout => "Hi\n" },
],
},
expected_raw_stdout => "Hi\n",
},
# recoverable git problem
'git remote end hung up' => {
command => [ 'git', 'clone', 'git://example.com/repo.git' ],
mock_command => {
sequence => [
{ exitcode => 12, stderr => "fatal: The remote end hung up unexpectedly\n" },
{ exitcode => 12, stderr => "fatal: The remote end hung up unexpectedly\n" },
{ exitcode => 0 },
],
},
expected_retries => 2,
expected_exe_stderr => qr"
\A
\Qfatal: The remote end hung up unexpectedly\E \n
$RE{ attempt }{ first } \n
$RE{ command } \Q = ['git','clone','git://example.com/repo.git'];\E \n
$RE{ failed_with_exitcode }{ 12 } \n
$RE{ retry } $RE{ retry_reason } \n
\Qfatal: The remote end hung up unexpectedly\E \n
$RE{ attempt }{ second } \n
$RE{ command } \Q = ['git','clone','git://example.com/repo.git'];\E \n
$RE{ failed_with_exitcode }{ 12 } \n
$RE{ retry } $RE{ retry_reason } \n
\z
"xms,
expected_raw_stderr => "fatal: The remote end hung up unexpectedly\n" x 2,
},
# error message but 0 exit code; make sure we don't retry
'git remote end hung up with 0 exit code' => {
command => [ 'git', 'clone', 'git://example.com/repo.git' ],
mock_command => {
sequence => [
{ exitcode => 0, stderr => "fatal: The remote end hung up unexpectedly\n" },
],
},
expected_retries => 0,
expected_raw_stderr => "fatal: The remote end hung up unexpectedly\n",
expected_exe_stderr => "fatal: The remote end hung up unexpectedly\n",
},
# unrecoverable git problem with no retries
'git unrecoverable simple' => {
command => [ 'git', 'clone', 'git://example.com/repo.git' ],
mock_command => {
sequence => [
{ exitcode => 12, stdout => "Cloning...\n", stderr => "fatal: Foo bar the baz\n" },
],
},
expected_raw_stderr => "fatal: Foo bar the baz\n",
expected_raw_stdout => "Cloning...\n",
expected_status => (12 << 8),
},
# unrecoverable git problem with some retries
'git unrecoverable with retry' => {
command => [ 'git', 'clone', 'git://example.com/repo.git' ],
mock_command => {
sequence => [
{ exitcode => 1, stderr => "fatal: The remote end hung up unexpectedly\n" },
{ exitcode => 2, stderr => "fatal: The remote end hung up unexpectedly\n" },
{ exitcode => 58, stderr => "fatal: Foo bar the baz\n" },
],
},
expected_retries => 2,
expected_exe_stderr => qr"
\A
\Qfatal: The remote end hung up unexpectedly\E \n
$RE{ attempt }{ first } \n
$RE{ command } \Q = ['git','clone','git://example.com/repo.git'];\E \n
$RE{ failed_with_exitcode }{ 1 } \n
$RE{ retry } $RE{ retry_reason } \n
\Qfatal: The remote end hung up unexpectedly\E \n
$RE{ attempt }{ second } \n
$RE{ command } \Q = ['git','clone','git://example.com/repo.git'];\E \n
$RE{ failed_with_exitcode }{ 2 } \n
$RE{ retry } $RE{ retry_reason } \n
\Qfatal: Foo bar the baz\E \n
\z
"xms,
expected_raw_stderr => ("fatal: The remote end hung up unexpectedly\n" x 2)
."fatal: Foo bar the baz\n",
expected_status => (58 << 8),
},
# git DNS failure - git:// protocol
'git DNS failure git://' => {
command => [ 'git', 'clone', 'git://example.com/repo.git' ],
mock_command => {
sequence => [
{ exitcode => 128, stderr => "fatal: Unable to look up example.com (port 9418) (Name or service not known)\n" },
{ exitcode => 0 },
],
},
expected_retries => 1,
expected_exe_stderr => qr"
\A
\Qfatal: Unable to look up example.com (port 9418) (Name or service not known)\E \n
$RE{ attempt }{ first } \n
$RE{ command } \Q = ['git','clone','git://example.com/repo.git'];\E \n
$RE{ failed_with_exitcode }{ 128 } \n
$RE{ retry } $RE{ retry_reason } \n
\z
"xms,
expected_raw_stderr => "fatal: Unable to look up example.com (port 9418) (Name or service not known)\n",
},
# git DNS failure - ssh:// protocol
# This test basically confirms that the Git strategy is subclassing the ssh strategy as
# expected. Other ssh:// protocol git issues aren't tested further.
'git DNS failure ssh://' => {
command => [ 'git', 'clone', 'ssh://example.com/repo.git' ],
mock_command => {
sequence => [
{ exitcode => 128, stderr => "ssh: Could not resolve hostname example.com: Name or service not known\n" },
{ exitcode => 0 },
],
},
expected_retries => 1,
expected_exe_stderr => qr"
\A
\Qssh: Could not resolve hostname example.com: Name or service not known\E \n
$RE{ attempt }{ first } \n
$RE{ command } \Q = ['git','clone','ssh://example.com/repo.git'];\E \n
$RE{ failed_with_exitcode }{ 128 } \n
$RE{ retry } $RE{ retry_reason } \n
\z
"xms,
expected_raw_stderr => "ssh: Could not resolve hostname example.com: Name or service not known\n",
},
# various scp problems
'scp network issues ultimately fatal' => {
command => [ 'scp', 'example.com:~/file1', '.' ],
mock_command => {
sequence => [
{ exitcode => 1, stderr => "ssh: Could not resolve hostname example.com: Name or service not known\n" },
{ exitcode => 2, stderr => "ssh: connect to host example.com: No route to host\n" },
{ exitcode => 3, stderr => "ssh: Connect to host example.com: Network is unreachable\n" },
{ exitcode => 4, stderr => "ssh: connect to host example.com port 1234: Connection timed out\n" },
{ exitcode => 5, stderr => "ssh: connect to host example.com port 22: Connection refused\n" },
# check that stdout does _not_ cause the command to be retried
{ exitcode => 6, stdout => "ssh: connect to host example.com port 23: Connection refused\n" },
],
},
expected_retries => 5,
expected_exe_stderr => qr"
\A
\Qssh: Could not resolve hostname example.com: Name or service not known\E \n
$RE{ attempt }{ first } \n
$RE{ command } \Q = ['scp','example.com:~/file1','.'];\E \n
$RE{ failed_with_exitcode }{ 1 } \n
$RE{ retry } $RE{ retry_reason } \n
\Qssh: connect to host example.com: No route to host\E \n
$RE{ attempt }{ second } \n
$RE{ command } \Q = ['scp','example.com:~/file1','.'];\E \n
$RE{ failed_with_exitcode }{ 2 } \n
$RE{ retry } $RE{ retry_reason } \n
\Qssh: Connect to host example.com: Network is unreachable\E \n
$RE{ attempt }{ third } \n
$RE{ command } \Q = ['scp','example.com:~/file1','.'];\E \n
$RE{ failed_with_exitcode }{ 3 } \n
$RE{ retry } $RE{ retry_reason } \n
\Qssh: connect to host example.com port 1234: Connection timed out\E \n
$RE{ attempt }{ fourth } \n
$RE{ command } \Q = ['scp','example.com:~/file1','.'];\E \n
$RE{ failed_with_exitcode }{ 4 } \n
$RE{ retry } $RE{ retry_reason } \n
\Qssh: connect to host example.com port 22: Connection refused\E \n
$RE{ attempt }{ fifth } \n
$RE{ command } \Q = ['scp','example.com:~/file1','.'];\E \n
$RE{ failed_with_exitcode }{ 5 } \n
$RE{ retry } $RE{ retry_reason } \n
\z
"xms,
expected_raw_stderr =>
"ssh: Could not resolve hostname example.com: Name or service not known\n"
."ssh: connect to host example.com: No route to host\n"
."ssh: Connect to host example.com: Network is unreachable\n"
."ssh: connect to host example.com port 1234: Connection timed out\n"
."ssh: connect to host example.com port 22: Connection refused\n"
,
expected_raw_stdout => "ssh: connect to host example.com port 23: Connection refused\n",
expected_status => (6 << 8),
},
# simple check with explicitly loading a strategy
'non-auto ssh failure' => {
command => [ 'frobnitz' ],
reliable => [ 'ssh' ],
mock_command => {
sequence => [
# check that the requested `reliable' loaded ssh strategy ...
{ exitcode => 128, stderr => "ssh: Could not resolve hostname example.com: Name or service not known\n" },
# ...and did _not_ load `git' strategy
{ exitcode => 128, stderr => "fatal: Unable to look up example.com (port 9418) (Name or service not known)\n" },
],
},
expected_retries => 1,
expected_exe_stderr => qr"
\A
\Qssh: Could not resolve hostname example.com: Name or service not known\E \n
$RE{ attempt }{ first } \n
$RE{ command } \Q = ['frobnitz'];\E \n
$RE{ failed_with_exitcode }{ 128 } \n
$RE{ retry } $RE{ retry_reason } \n
\Qfatal: Unable to look up example.com (port 9418) (Name or service not known)\E \n
\z
"xms,
expected_raw_stderr =>
"ssh: Could not resolve hostname example.com: Name or service not known\n"
."fatal: Unable to look up example.com (port 9418) (Name or service not known)\n"
,
expected_status => (128 << 8),
},
;
1;