2013-11-17 21:58:21 +03:00
|
|
|
#!/usr/bin/perl
|
2014-04-03 00:25:37 +03:00
|
|
|
####################################################################################################################################
|
2015-08-29 20:20:46 +02:00
|
|
|
# test.pl - pgBackRest Unit Tests
|
2014-04-03 00:25:37 +03:00
|
|
|
####################################################################################################################################
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# Perl includes
|
|
|
|
####################################################################################################################################
|
|
|
|
use strict;
|
2015-04-19 23:27:40 +02:00
|
|
|
use warnings FATAL => qw(all);
|
2015-06-14 00:25:49 +02:00
|
|
|
use Carp qw(confess longmess);
|
2016-09-06 15:44:50 +02:00
|
|
|
use English '-no_match_vars';
|
2015-06-14 00:25:49 +02:00
|
|
|
|
2015-08-29 20:20:46 +02:00
|
|
|
# Convert die to confess to capture the stack trace
|
2015-06-14 00:25:49 +02:00
|
|
|
$SIG{__DIE__} = sub { Carp::confess @_ };
|
2014-04-03 00:25:37 +03:00
|
|
|
|
2015-08-29 20:20:46 +02:00
|
|
|
use File::Basename qw(dirname);
|
|
|
|
use Getopt::Long qw(GetOptions);
|
2016-01-15 02:37:06 +02:00
|
|
|
use Cwd qw(abs_path cwd);
|
2015-08-29 20:20:46 +02:00
|
|
|
use Pod::Usage qw(pod2usage);
|
2016-01-09 15:21:53 +02:00
|
|
|
use POSIX qw(ceil);
|
|
|
|
use Time::HiRes qw(gettimeofday);
|
2014-04-03 00:25:37 +03:00
|
|
|
|
2016-11-04 13:56:26 +02:00
|
|
|
use lib dirname($0) . '/lib';
|
2014-09-16 18:22:55 +03:00
|
|
|
use lib dirname($0) . '/../lib';
|
2016-11-04 13:56:26 +02:00
|
|
|
use lib dirname($0) . '/../doc/lib';
|
|
|
|
|
2016-09-06 15:44:50 +02:00
|
|
|
use pgBackRest::Common::Exception;
|
2016-04-14 15:30:54 +02:00
|
|
|
use pgBackRest::Common::Ini;
|
|
|
|
use pgBackRest::Common::Log;
|
|
|
|
use pgBackRest::Common::String;
|
|
|
|
use pgBackRest::Common::Wait;
|
2016-09-06 15:35:02 +02:00
|
|
|
use pgBackRest::Config::Config;
|
2016-08-12 04:35:24 +02:00
|
|
|
use pgBackRest::DbVersion;
|
2016-05-11 00:12:37 +02:00
|
|
|
use pgBackRest::FileCommon;
|
2016-04-14 15:30:54 +02:00
|
|
|
use pgBackRest::Version;
|
2014-06-22 17:30:17 +03:00
|
|
|
|
2016-06-28 02:37:25 +02:00
|
|
|
use BackRestDoc::Custom::DocCustomRelease;
|
|
|
|
|
2016-06-24 14:12:58 +02:00
|
|
|
use pgBackRestTest::Backup::BackupTest;
|
|
|
|
use pgBackRestTest::Backup::Common::HostBackupTest;
|
|
|
|
use pgBackRestTest::Backup::Common::HostBaseTest;
|
|
|
|
use pgBackRestTest::Backup::Common::HostDbCommonTest;
|
|
|
|
use pgBackRestTest::Backup::Common::HostDbTest;
|
|
|
|
use pgBackRestTest::Common::ContainerTest;
|
2016-04-14 15:30:54 +02:00
|
|
|
use pgBackRestTest::Common::ExecuteTest;
|
2016-06-24 14:12:58 +02:00
|
|
|
use pgBackRestTest::Common::HostGroupTest;
|
|
|
|
use pgBackRestTest::Common::ListTest;
|
2016-04-14 15:30:54 +02:00
|
|
|
use pgBackRestTest::CommonTest;
|
2016-06-24 14:12:58 +02:00
|
|
|
use pgBackRestTest::Config::ConfigTest;
|
|
|
|
use pgBackRestTest::File::FileTest;
|
|
|
|
use pgBackRestTest::Help::HelpTest;
|
2014-04-03 00:25:37 +03:00
|
|
|
|
2015-01-11 18:52:16 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# Usage
|
|
|
|
####################################################################################################################################
|
|
|
|
|
|
|
|
=head1 NAME
|
|
|
|
|
2015-08-29 20:20:46 +02:00
|
|
|
test.pl - pgBackRest Unit Tests
|
2015-01-11 18:52:16 +02:00
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
|
|
|
|
test.pl [options]
|
|
|
|
|
|
|
|
Test Options:
|
2016-01-09 15:21:53 +02:00
|
|
|
--module test module to execute
|
2015-06-27 17:12:44 +02:00
|
|
|
--test execute the specified test in a module
|
|
|
|
--run execute only the specified test run
|
2016-09-06 15:35:02 +02:00
|
|
|
--process-max max processes to run for compression/transfer (default 1)
|
2015-01-12 16:05:26 +02:00
|
|
|
--dry-run show only the tests that would be executed but don't execute them
|
|
|
|
--no-cleanup don't cleaup after the last test is complete - useful for debugging
|
2016-05-11 14:59:34 +02:00
|
|
|
--db-version version of postgres to test (all, defaults to minimal)
|
2015-05-05 19:08:48 +02:00
|
|
|
--log-force force overwrite of current test log files
|
2016-02-23 16:25:22 +02:00
|
|
|
--no-lint Disable static source code analysis
|
2015-01-11 18:52:16 +02:00
|
|
|
|
|
|
|
Configuration Options:
|
2015-01-12 16:05:26 +02:00
|
|
|
--psql-bin path to the psql executables (e.g. /usr/lib/postgresql/9.3/bin/)
|
|
|
|
--test-path path where tests are executed (defaults to ./test)
|
|
|
|
--log-level log level to use for tests (defaults to INFO)
|
|
|
|
--quiet, -q equivalent to --log-level=off
|
2015-01-11 18:52:16 +02:00
|
|
|
|
2016-01-09 15:21:53 +02:00
|
|
|
VM Options:
|
2016-04-14 00:47:29 +02:00
|
|
|
--vm docker container to build/test (u12, u14, co6, co7)
|
2016-01-09 15:21:53 +02:00
|
|
|
--vm-build build Docker containers
|
2016-04-14 00:47:29 +02:00
|
|
|
--vm-force force a rebuild of Docker containers
|
2016-01-09 15:21:53 +02:00
|
|
|
--vm-out Show VM output (default false)
|
2016-09-06 15:35:02 +02:00
|
|
|
--vm-max max VMs to run in parallel (default 1)
|
2016-01-09 15:21:53 +02:00
|
|
|
|
2015-01-11 18:52:16 +02:00
|
|
|
General Options:
|
2015-01-12 16:05:26 +02:00
|
|
|
--version display version and exit
|
|
|
|
--help display usage and exit
|
2015-01-11 18:52:16 +02:00
|
|
|
=cut
|
|
|
|
|
2014-04-03 00:25:37 +03:00
|
|
|
####################################################################################################################################
|
2014-06-04 04:22:07 +03:00
|
|
|
# Command line parameters
|
|
|
|
####################################################################################################################################
|
2015-04-03 04:07:23 +02:00
|
|
|
my $strLogLevel = 'info';
|
2016-01-09 15:21:53 +02:00
|
|
|
my $bVmOut = false;
|
2014-06-05 17:20:03 +03:00
|
|
|
my $strModule = 'all';
|
|
|
|
my $strModuleTest = 'all';
|
2014-06-22 17:54:31 +03:00
|
|
|
my $iModuleTestRun = undef;
|
2016-09-06 15:35:02 +02:00
|
|
|
my $iProcessMax = undef;
|
|
|
|
my $iVmMax = 1;
|
|
|
|
my $iVmId = undef;
|
2014-07-16 05:32:41 +03:00
|
|
|
my $bDryRun = false;
|
|
|
|
my $bNoCleanup = false;
|
2014-08-11 04:22:17 +03:00
|
|
|
my $strPgSqlBin;
|
|
|
|
my $strTestPath;
|
2015-01-11 18:52:16 +02:00
|
|
|
my $bVersion = false;
|
|
|
|
my $bHelp = false;
|
|
|
|
my $bQuiet = false;
|
2016-05-11 14:59:34 +02:00
|
|
|
my $strDbVersion = 'minimal';
|
2015-05-05 19:08:48 +02:00
|
|
|
my $bLogForce = false;
|
2016-04-14 00:47:29 +02:00
|
|
|
my $strVm = 'all';
|
2016-01-09 15:21:53 +02:00
|
|
|
my $bVmBuild = false;
|
2016-04-14 00:47:29 +02:00
|
|
|
my $bVmForce = false;
|
2016-02-23 16:25:22 +02:00
|
|
|
my $bNoLint = false;
|
2015-01-11 18:52:16 +02:00
|
|
|
|
|
|
|
GetOptions ('q|quiet' => \$bQuiet,
|
|
|
|
'version' => \$bVersion,
|
|
|
|
'help' => \$bHelp,
|
|
|
|
'pgsql-bin=s' => \$strPgSqlBin,
|
2014-09-16 18:22:55 +03:00
|
|
|
'test-path=s' => \$strTestPath,
|
|
|
|
'log-level=s' => \$strLogLevel,
|
2016-04-14 00:47:29 +02:00
|
|
|
'vm=s' => \$strVm,
|
2016-01-09 15:21:53 +02:00
|
|
|
'vm-out' => \$bVmOut,
|
|
|
|
'vm-build' => \$bVmBuild,
|
2016-04-14 00:47:29 +02:00
|
|
|
'vm-force' => \$bVmForce,
|
2014-09-16 18:22:55 +03:00
|
|
|
'module=s' => \$strModule,
|
2015-06-27 17:12:44 +02:00
|
|
|
'test=s' => \$strModuleTest,
|
|
|
|
'run=s' => \$iModuleTestRun,
|
2016-01-09 15:21:53 +02:00
|
|
|
'process-max=s' => \$iProcessMax,
|
2016-09-06 15:35:02 +02:00
|
|
|
'vm-id=s' => \$iVmId,
|
2016-09-30 00:26:32 +02:00
|
|
|
'vm-max=s' => \$iVmMax,
|
2014-09-16 18:22:55 +03:00
|
|
|
'dry-run' => \$bDryRun,
|
2015-02-28 06:31:39 +02:00
|
|
|
'no-cleanup' => \$bNoCleanup,
|
2015-05-05 19:08:48 +02:00
|
|
|
'db-version=s' => \$strDbVersion,
|
2016-02-23 16:25:22 +02:00
|
|
|
'log-force' => \$bLogForce,
|
|
|
|
'no-lint' => \$bNoLint)
|
2015-01-11 18:52:16 +02:00
|
|
|
or pod2usage(2);
|
|
|
|
|
2016-09-06 15:44:50 +02:00
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# Run in eval block to catch errors
|
|
|
|
####################################################################################################################################
|
|
|
|
eval
|
2015-01-11 18:52:16 +02:00
|
|
|
{
|
2016-09-06 15:44:50 +02:00
|
|
|
# Display version and exit if requested
|
|
|
|
if ($bVersion || $bHelp)
|
|
|
|
{
|
|
|
|
syswrite(*STDOUT, BACKREST_NAME . ' ' . BACKREST_VERSION . " Test Engine\n");
|
|
|
|
|
|
|
|
if ($bHelp)
|
|
|
|
{
|
|
|
|
syswrite(*STDOUT, "\n");
|
|
|
|
pod2usage();
|
|
|
|
}
|
2015-01-11 18:52:16 +02:00
|
|
|
|
2016-09-06 15:44:50 +02:00
|
|
|
exit 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (@ARGV > 0)
|
2015-01-11 18:52:16 +02:00
|
|
|
{
|
2016-09-06 15:44:50 +02:00
|
|
|
syswrite(*STDOUT, "invalid parameter\n\n");
|
2015-01-11 18:52:16 +02:00
|
|
|
pod2usage();
|
|
|
|
}
|
|
|
|
|
2016-09-06 15:44:50 +02:00
|
|
|
################################################################################################################################
|
|
|
|
# Setup
|
|
|
|
################################################################################################################################
|
|
|
|
# Set a neutral umask so tests work as expected
|
|
|
|
umask(0);
|
2014-06-04 04:22:07 +03:00
|
|
|
|
2016-09-06 15:44:50 +02:00
|
|
|
# Set console log level
|
|
|
|
if ($bQuiet)
|
|
|
|
{
|
|
|
|
$strLogLevel = 'off';
|
|
|
|
}
|
2015-01-11 18:52:16 +02:00
|
|
|
|
2016-10-05 15:09:30 +02:00
|
|
|
logLevelSet(uc($strLogLevel), uc($strLogLevel), OFF);
|
2014-06-04 04:22:07 +03:00
|
|
|
|
2016-09-06 15:44:50 +02:00
|
|
|
if ($strModuleTest ne 'all' && $strModule eq 'all')
|
|
|
|
{
|
|
|
|
confess "--module must be provided for --test=\"${strModuleTest}\"";
|
|
|
|
}
|
2014-06-05 17:20:03 +03:00
|
|
|
|
2016-09-06 15:44:50 +02:00
|
|
|
if (defined($iModuleTestRun) && $strModuleTest eq 'all')
|
|
|
|
{
|
|
|
|
confess "--test must be provided for --run=\"${iModuleTestRun}\"";
|
|
|
|
}
|
2014-06-22 17:54:31 +03:00
|
|
|
|
2016-09-06 15:44:50 +02:00
|
|
|
# Check process total
|
|
|
|
if (defined($iProcessMax) && ($iProcessMax < 1 || $iProcessMax > OPTION_DEFAULT_PROCESS_MAX_MAX))
|
|
|
|
{
|
|
|
|
confess 'process-max must be between 1 and ' . OPTION_DEFAULT_PROCESS_MAX_MAX;
|
|
|
|
}
|
2015-02-28 17:21:36 +02:00
|
|
|
|
2016-09-06 15:44:50 +02:00
|
|
|
# Set test path if not expicitly set
|
|
|
|
if (!defined($strTestPath))
|
|
|
|
{
|
|
|
|
$strTestPath = cwd() . '/test';
|
|
|
|
}
|
2016-05-11 00:12:37 +02:00
|
|
|
|
2016-09-06 15:44:50 +02:00
|
|
|
# Get the base backrest path
|
|
|
|
my $strBackRestBase = dirname(dirname(abs_path($0)));
|
2016-06-02 15:32:56 +02:00
|
|
|
|
2016-09-06 15:44:50 +02:00
|
|
|
################################################################################################################################
|
|
|
|
# Build Docker containers
|
|
|
|
################################################################################################################################
|
|
|
|
if ($bVmBuild)
|
|
|
|
{
|
|
|
|
containerBuild($strVm, $bVmForce, $strDbVersion);
|
|
|
|
exit 0;
|
|
|
|
}
|
2016-01-09 15:21:53 +02:00
|
|
|
|
|
|
|
################################################################################################################################
|
|
|
|
# Start VM and run
|
|
|
|
################################################################################################################################
|
2016-09-06 15:35:02 +02:00
|
|
|
if (!defined($iVmId))
|
2016-01-09 15:21:53 +02:00
|
|
|
{
|
2016-05-24 02:04:36 +02:00
|
|
|
# Load the doc module dynamically since it is not supported on all systems
|
|
|
|
require BackRestDoc::Common::Doc;
|
|
|
|
BackRestDoc::Common::Doc->import();
|
|
|
|
|
|
|
|
# Make sure version number matches the latest release
|
2016-06-02 15:32:56 +02:00
|
|
|
my $strReleaseFile = dirname(dirname(abs_path($0))) . '/doc/xml/release.xml';
|
2016-06-28 02:37:25 +02:00
|
|
|
my $oRelease = (new BackRestDoc::Custom::DocCustomRelease(new BackRestDoc::Common::Doc($strReleaseFile)))->releaseLast();
|
|
|
|
my $strVersion = $oRelease->paramGet('version');
|
2016-05-24 02:04:36 +02:00
|
|
|
|
2016-06-28 02:37:25 +02:00
|
|
|
if ($strVersion =~ /dev$/ && BACKREST_VERSION !~ /dev$/)
|
2016-05-24 02:04:36 +02:00
|
|
|
{
|
2016-06-28 02:37:25 +02:00
|
|
|
if ($oRelease->nodeTest('release-core-list'))
|
2016-05-26 16:34:10 +02:00
|
|
|
{
|
2016-06-28 02:37:25 +02:00
|
|
|
confess "dev release ${strVersion} must match the program version when core changes have been made";
|
2016-05-26 16:34:10 +02:00
|
|
|
}
|
2016-06-28 02:37:25 +02:00
|
|
|
}
|
2016-07-19 21:22:20 +02:00
|
|
|
elsif ($strVersion ne BACKREST_VERSION)
|
2016-06-28 02:37:25 +02:00
|
|
|
{
|
|
|
|
confess 'unable to find version ' . BACKREST_VERSION . " as the most recent release in ${strReleaseFile}";
|
2016-05-24 02:04:36 +02:00
|
|
|
}
|
|
|
|
|
2016-01-15 02:37:06 +02:00
|
|
|
if (!$bDryRun)
|
|
|
|
{
|
2016-02-23 16:25:22 +02:00
|
|
|
# Run Perl critic
|
|
|
|
if (!$bNoLint)
|
|
|
|
{
|
|
|
|
my $strBasePath = dirname(dirname(abs_path($0)));
|
|
|
|
|
2016-05-26 22:57:35 +02:00
|
|
|
&log(INFO, "Performing static code analysis using perl -cw");
|
2016-02-23 16:25:22 +02:00
|
|
|
|
|
|
|
# Check the exe for warnings
|
2016-05-26 22:57:35 +02:00
|
|
|
my $strWarning = trim(executeTest("perl -cw ${strBasePath}/bin/pgbackrest 2>&1"));
|
2016-02-23 16:25:22 +02:00
|
|
|
|
2016-04-14 15:30:54 +02:00
|
|
|
if ($strWarning ne "${strBasePath}/bin/pgbackrest syntax OK")
|
2016-02-23 16:25:22 +02:00
|
|
|
{
|
2016-04-14 15:30:54 +02:00
|
|
|
confess &log(ERROR, "${strBasePath}/bin/pgbackrest failed syntax check:\n${strWarning}");
|
2016-02-23 16:25:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
&log(INFO, "Performing static code analysis using perlcritic");
|
|
|
|
|
|
|
|
executeTest('perlcritic --quiet --verbose=8 --brutal --top=10' .
|
|
|
|
' --verbose "[%p] %f: %m at line %l, column %c. %e. (Severity: %s)\n"' .
|
|
|
|
" \"--profile=${strBasePath}/test/lint/perlcritic.policy\"" .
|
2016-04-14 15:30:54 +02:00
|
|
|
" ${strBasePath}/bin/pgbackrest ${strBasePath}/lib/*" .
|
2016-02-23 16:25:22 +02:00
|
|
|
" ${strBasePath}/test/test.pl ${strBasePath}/test/lib/*" .
|
|
|
|
" ${strBasePath}/doc/doc.pl ${strBasePath}/doc/lib/*");
|
|
|
|
}
|
|
|
|
|
2016-01-15 02:37:06 +02:00
|
|
|
logFileSet(cwd() . "/test");
|
|
|
|
}
|
|
|
|
|
2016-01-09 15:21:53 +02:00
|
|
|
# Determine which tests to run
|
2016-06-24 14:12:58 +02:00
|
|
|
#-----------------------------------------------------------------------------------------------------------------------
|
2016-09-06 15:35:02 +02:00
|
|
|
my $oyTestRun = testListGet($strVm, $strModule, $strModuleTest, $iModuleTestRun, $strDbVersion, $iProcessMax);
|
2016-01-09 15:21:53 +02:00
|
|
|
|
2016-06-24 14:12:58 +02:00
|
|
|
if (@{$oyTestRun} == 0)
|
2016-01-09 15:21:53 +02:00
|
|
|
{
|
|
|
|
confess &log(ERROR, 'no tests were selected');
|
|
|
|
}
|
|
|
|
|
2016-06-24 14:12:58 +02:00
|
|
|
&log(INFO, @{$oyTestRun} . ' test' . (@{$oyTestRun} > 1 ? 's': '') . " selected\n");
|
2016-01-16 06:22:30 +02:00
|
|
|
|
2016-06-24 14:12:58 +02:00
|
|
|
if ($bNoCleanup && @{$oyTestRun} > 1)
|
2016-01-16 06:22:30 +02:00
|
|
|
{
|
|
|
|
confess &log(ERROR, '--no-cleanup is not valid when more than one test will run')
|
|
|
|
}
|
|
|
|
|
2016-06-24 14:12:58 +02:00
|
|
|
# Execute tests
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------------
|
2016-01-09 15:21:53 +02:00
|
|
|
my $iTestFail = 0;
|
|
|
|
my $oyProcess = [];
|
|
|
|
|
2016-01-14 05:43:26 +02:00
|
|
|
if (!$bDryRun || $bVmOut)
|
2016-01-09 15:21:53 +02:00
|
|
|
{
|
2016-06-12 15:00:16 +02:00
|
|
|
containerRemove('test-[0-9]+');
|
|
|
|
|
2016-09-06 15:35:02 +02:00
|
|
|
for (my $iVmIdx = 0; $iVmIdx < 8; $iVmIdx++)
|
2016-01-09 15:21:53 +02:00
|
|
|
{
|
|
|
|
push(@{$oyProcess}, undef);
|
|
|
|
}
|
2016-05-11 00:12:37 +02:00
|
|
|
|
|
|
|
executeTest("sudo rm -rf ${strTestPath}/*");
|
|
|
|
filePathCreate($strTestPath);
|
2016-01-09 15:21:53 +02:00
|
|
|
}
|
|
|
|
|
2016-01-14 05:43:26 +02:00
|
|
|
if ($bDryRun)
|
|
|
|
{
|
2016-09-06 15:35:02 +02:00
|
|
|
$iVmMax = 1;
|
2016-01-14 05:43:26 +02:00
|
|
|
}
|
|
|
|
|
2016-01-09 15:21:53 +02:00
|
|
|
my $iTestIdx = 0;
|
2016-09-06 15:35:02 +02:00
|
|
|
my $iVmTotal;
|
2016-01-09 15:21:53 +02:00
|
|
|
my $iTestMax = @{$oyTestRun};
|
|
|
|
my $lStartTime = time();
|
2016-09-06 15:35:02 +02:00
|
|
|
my $bShowOutputAsync = $bVmOut && (@{$oyTestRun} == 1 || $iVmMax == 1) && ! $bDryRun ? true : false;
|
2016-01-09 15:21:53 +02:00
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
2016-09-06 15:35:02 +02:00
|
|
|
$iVmTotal = 0;
|
2016-01-09 15:21:53 +02:00
|
|
|
|
2016-09-06 15:35:02 +02:00
|
|
|
for (my $iVmIdx = 0; $iVmIdx < $iVmMax; $iVmIdx++)
|
2016-01-09 15:21:53 +02:00
|
|
|
{
|
2016-09-06 15:35:02 +02:00
|
|
|
if (defined($$oyProcess[$iVmIdx]))
|
2016-01-09 15:21:53 +02:00
|
|
|
{
|
2016-09-06 15:35:02 +02:00
|
|
|
my $oExecDone = $$oyProcess[$iVmIdx]{exec};
|
|
|
|
my $strTestDone = $$oyProcess[$iVmIdx]{test};
|
|
|
|
my $iTestDoneIdx = $$oyProcess[$iVmIdx]{idx};
|
2016-01-09 15:21:53 +02:00
|
|
|
|
2016-09-06 15:35:02 +02:00
|
|
|
my $iExitStatus = $oExecDone->end(undef, $iVmMax == 1);
|
2016-01-09 15:21:53 +02:00
|
|
|
|
|
|
|
if (defined($iExitStatus))
|
|
|
|
{
|
2016-01-14 05:43:26 +02:00
|
|
|
if ($bShowOutputAsync)
|
|
|
|
{
|
|
|
|
syswrite(*STDOUT, "\n");
|
|
|
|
}
|
|
|
|
|
2016-09-06 15:35:02 +02:00
|
|
|
my $fTestElapsedTime = ceil((gettimeofday() - $$oyProcess[$iVmIdx]{start_time}) * 100) / 100;
|
2016-01-09 15:21:53 +02:00
|
|
|
|
|
|
|
if (!($iExitStatus == 0 || $iExitStatus == 255))
|
|
|
|
{
|
|
|
|
&log(ERROR, "${strTestDone} (err${iExitStatus}-${fTestElapsedTime}s)" .
|
2016-01-14 05:43:26 +02:00
|
|
|
(defined($oExecDone->{strOutLog}) && !$bShowOutputAsync ?
|
|
|
|
":\n\n" . trim($oExecDone->{strOutLog}) . "\n" : ''), undef, undef, 4);
|
2016-01-09 15:21:53 +02:00
|
|
|
$iTestFail++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-01-14 05:43:26 +02:00
|
|
|
&log(INFO, "${strTestDone} (${fTestElapsedTime}s)".
|
|
|
|
($bVmOut && !$bShowOutputAsync ?
|
|
|
|
":\n\n" . trim($oExecDone->{strOutLog}) . "\n" : ''), undef, undef, 4);
|
2016-01-09 15:21:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!$bNoCleanup)
|
|
|
|
{
|
2016-09-06 15:35:02 +02:00
|
|
|
my $strImage = 'test-' . $iVmIdx;
|
2016-05-11 00:12:37 +02:00
|
|
|
my $strHostTestPath = "${strTestPath}/${strImage}";
|
|
|
|
|
2016-09-06 15:35:02 +02:00
|
|
|
containerRemove("test-${iVmIdx}");
|
2016-05-11 00:12:37 +02:00
|
|
|
executeTest("sudo rm -rf ${strHostTestPath}");
|
2016-01-09 15:21:53 +02:00
|
|
|
}
|
|
|
|
|
2016-09-06 15:35:02 +02:00
|
|
|
$$oyProcess[$iVmIdx] = undef;
|
2016-01-09 15:21:53 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-09-06 15:35:02 +02:00
|
|
|
$iVmTotal++;
|
2016-01-09 15:21:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-06 15:35:02 +02:00
|
|
|
if ($iVmTotal == $iVmMax)
|
2016-01-09 15:21:53 +02:00
|
|
|
{
|
|
|
|
waitHiRes(.1);
|
|
|
|
}
|
|
|
|
}
|
2016-09-06 15:35:02 +02:00
|
|
|
while ($iVmTotal == $iVmMax);
|
2016-01-09 15:21:53 +02:00
|
|
|
|
2016-09-06 15:35:02 +02:00
|
|
|
for (my $iVmIdx = 0; $iVmIdx < $iVmMax; $iVmIdx++)
|
2016-01-09 15:21:53 +02:00
|
|
|
{
|
2016-09-06 15:35:02 +02:00
|
|
|
if (!defined($$oyProcess[$iVmIdx]) && $iTestIdx < @{$oyTestRun})
|
2016-01-09 15:21:53 +02:00
|
|
|
{
|
|
|
|
my $oTest = $$oyTestRun[$iTestIdx];
|
|
|
|
$iTestIdx++;
|
|
|
|
|
2016-09-06 15:35:02 +02:00
|
|
|
my $strTest = sprintf('P%0' . length($iVmMax) . 'd-T%0' . length($iTestMax) . 'd/%0' .
|
|
|
|
length($iTestMax) . "d - ", $iVmIdx, $iTestIdx, $iTestMax) .
|
2016-06-24 14:12:58 +02:00
|
|
|
'vm=' . $$oTest{&TEST_VM} .
|
|
|
|
', module=' . $$oTest{&TEST_MODULE} .
|
|
|
|
', test=' . $$oTest{&TEST_NAME} .
|
|
|
|
(defined($$oTest{&TEST_RUN}) ? ', run=' . $$oTest{&TEST_RUN} : '') .
|
2016-09-06 15:35:02 +02:00
|
|
|
(defined($$oTest{&TEST_PROCESS}) ? ', process-max=' . $$oTest{&TEST_PROCESS} : '') .
|
2016-06-24 14:12:58 +02:00
|
|
|
(defined($$oTest{&TEST_DB}) ? ', db=' . $$oTest{&TEST_DB} : '');
|
2016-01-09 15:21:53 +02:00
|
|
|
|
2016-09-06 15:35:02 +02:00
|
|
|
my $strImage = 'test-' . $iVmIdx;
|
2016-06-24 14:12:58 +02:00
|
|
|
my $strDbVersion = (defined($$oTest{&TEST_DB}) ? $$oTest{&TEST_DB} : PG_VERSION_94);
|
2016-01-23 01:01:21 +02:00
|
|
|
$strDbVersion =~ s/\.//;
|
2016-01-09 15:21:53 +02:00
|
|
|
|
2016-06-24 14:12:58 +02:00
|
|
|
&log($bDryRun && !$bVmOut || $bShowOutputAsync ? INFO : DETAIL, "${strTest}" .
|
2016-01-14 05:43:26 +02:00
|
|
|
($bVmOut || $bShowOutputAsync ? "\n" : ''));
|
2016-01-09 15:21:53 +02:00
|
|
|
|
2016-10-01 19:39:44 +02:00
|
|
|
my $strVmTestPath = '/home/' . TEST_USER . "/test/${strImage}";
|
2016-05-11 00:12:37 +02:00
|
|
|
my $strHostTestPath = "${strTestPath}/${strImage}";
|
|
|
|
|
|
|
|
# Don't create the container if this is a dry run unless output from the VM is required. Ouput can be requested
|
|
|
|
# to get more information about the specific tests that will be run.
|
2016-01-14 05:43:26 +02:00
|
|
|
if (!$bDryRun || $bVmOut)
|
2016-01-09 15:21:53 +02:00
|
|
|
{
|
2016-05-11 00:12:37 +02:00
|
|
|
# Create host test directory
|
|
|
|
filePathCreate($strHostTestPath, '0770');
|
|
|
|
|
2016-06-24 14:12:58 +02:00
|
|
|
if ($$oTest{&TEST_CONTAINER})
|
|
|
|
{
|
|
|
|
executeTest(
|
|
|
|
'docker run -itd -h ' . $$oTest{&TEST_VM} . "-test --name=${strImage}" .
|
|
|
|
" -v ${strHostTestPath}:${strVmTestPath}" .
|
2016-10-01 19:39:44 +02:00
|
|
|
" -v ${strBackRestBase}:${strBackRestBase} " . containerNamespace() . '/' . $$oTest{&TEST_VM} .
|
|
|
|
"-loop-test-pre");
|
2016-06-24 14:12:58 +02:00
|
|
|
}
|
2016-01-09 15:21:53 +02:00
|
|
|
}
|
|
|
|
|
2016-05-11 00:12:37 +02:00
|
|
|
my $strCommand =
|
2016-10-01 19:39:44 +02:00
|
|
|
($$oTest{&TEST_CONTAINER} ? 'docker exec -i -u ' . TEST_USER . " ${strImage} " : '') . abs_path($0) .
|
2016-06-02 15:32:56 +02:00
|
|
|
" --test-path=${strVmTestPath}" .
|
2016-06-24 14:12:58 +02:00
|
|
|
" --vm=$$oTest{&TEST_VM}" .
|
2016-09-06 15:35:02 +02:00
|
|
|
" --vm-id=${iVmIdx}" .
|
2016-06-24 14:12:58 +02:00
|
|
|
" --module=" . $$oTest{&TEST_MODULE} .
|
|
|
|
' --test=' . $$oTest{&TEST_NAME} .
|
|
|
|
(defined($$oTest{&TEST_RUN}) ? ' --run=' . $$oTest{&TEST_RUN} : '') .
|
|
|
|
(defined($$oTest{&TEST_DB}) ? ' --db-version=' . $$oTest{&TEST_DB} : '') .
|
2016-09-06 15:35:02 +02:00
|
|
|
(defined($$oTest{&TEST_PROCESS}) ? ' --process-max=' . $$oTest{&TEST_PROCESS} : '') .
|
2016-06-24 14:12:58 +02:00
|
|
|
($strLogLevel ne lc(INFO) ? " --log-level=${strLogLevel}" : '') .
|
|
|
|
' --pgsql-bin=' . $$oTest{&TEST_PGSQL_BIN} .
|
|
|
|
($bLogForce ? ' --log-force' : '') .
|
|
|
|
($bDryRun ? ' --dry-run' : '') .
|
|
|
|
($bVmOut ? ' --vm-out' : '') .
|
|
|
|
($bNoCleanup ? " --no-cleanup" : '');
|
|
|
|
|
|
|
|
&log(DETAIL, $strCommand);
|
2016-01-09 15:21:53 +02:00
|
|
|
|
2016-01-14 05:43:26 +02:00
|
|
|
if (!$bDryRun || $bVmOut)
|
2016-01-09 15:21:53 +02:00
|
|
|
{
|
|
|
|
my $fTestStartTime = gettimeofday();
|
2016-05-11 00:12:37 +02:00
|
|
|
|
2016-06-24 14:12:58 +02:00
|
|
|
filePathCreate($strVmTestPath, '0777', undef, true);
|
|
|
|
|
2016-05-11 00:12:37 +02:00
|
|
|
# Set permissions on the Docker test directory. This can be removed once users/groups are sync'd between
|
|
|
|
# Docker and the host VM.
|
2016-06-24 14:12:58 +02:00
|
|
|
if ($$oTest{&TEST_CONTAINER})
|
|
|
|
{
|
2016-10-01 19:39:44 +02:00
|
|
|
executeTest("docker exec ${strImage} chown " . TEST_USER . ":postgres -R ${strVmTestPath}");
|
2016-06-24 14:12:58 +02:00
|
|
|
}
|
2016-05-11 00:12:37 +02:00
|
|
|
|
2016-04-14 15:30:54 +02:00
|
|
|
my $oExec = new pgBackRestTest::Common::ExecuteTest(
|
2016-01-14 05:43:26 +02:00
|
|
|
$strCommand,
|
|
|
|
{bSuppressError => true, bShowOutputAsync => $bShowOutputAsync});
|
2016-01-09 15:21:53 +02:00
|
|
|
|
|
|
|
$oExec->begin();
|
|
|
|
|
|
|
|
my $oProcess =
|
|
|
|
{
|
|
|
|
exec => $oExec,
|
|
|
|
test => $strTest,
|
|
|
|
idx => $iTestIdx,
|
2016-06-24 14:12:58 +02:00
|
|
|
container => $$oTest{&TEST_CONTAINER},
|
2016-01-09 15:21:53 +02:00
|
|
|
start_time => $fTestStartTime
|
|
|
|
};
|
|
|
|
|
2016-09-06 15:35:02 +02:00
|
|
|
$$oyProcess[$iVmIdx] = $oProcess;
|
2016-01-09 15:21:53 +02:00
|
|
|
}
|
|
|
|
|
2016-09-06 15:35:02 +02:00
|
|
|
$iVmTotal++;
|
2016-01-09 15:21:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-09-06 15:35:02 +02:00
|
|
|
while ($iVmTotal > 0);
|
2016-01-09 15:21:53 +02:00
|
|
|
|
2016-06-24 14:12:58 +02:00
|
|
|
# Print test info and exit
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------------
|
2016-01-14 05:43:26 +02:00
|
|
|
if ($bDryRun)
|
|
|
|
{
|
|
|
|
&log(INFO, 'DRY RUN COMPLETED');
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
&log(INFO, 'TESTS COMPLETED ' . ($iTestFail == 0 ? 'SUCCESSFULLY' : "WITH ${iTestFail} FAILURE(S)") .
|
|
|
|
' (' . (time() - $lStartTime) . 's)');
|
|
|
|
}
|
2016-01-09 15:21:53 +02:00
|
|
|
|
|
|
|
exit 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
################################################################################################################################
|
|
|
|
# Runs tests
|
|
|
|
################################################################################################################################
|
|
|
|
my $iRun = 0;
|
2014-07-17 06:38:38 +03:00
|
|
|
|
2016-06-24 14:12:58 +02:00
|
|
|
# Set parameters in host group
|
|
|
|
my $oHostGroup = hostGroupGet();
|
|
|
|
$oHostGroup->paramSet(HOST_PARAM_VM, $strVm);
|
2016-09-06 15:35:02 +02:00
|
|
|
$oHostGroup->paramSet(HOST_PARAM_VM_ID, $iVmId);
|
2016-06-24 14:12:58 +02:00
|
|
|
$oHostGroup->paramSet(HOST_PARAM_TEST_PATH, $strTestPath);
|
|
|
|
$oHostGroup->paramSet(HOST_PARAM_BACKREST_EXE, "${strBackRestBase}/bin/pgbackrest");
|
2016-09-06 15:35:02 +02:00
|
|
|
$oHostGroup->paramSet(HOST_PARAM_PROCESS_MAX, $iProcessMax);
|
2016-10-01 19:39:44 +02:00
|
|
|
$oHostGroup->paramSet(HOST_DB_USER, TEST_USER);
|
2016-06-24 14:12:58 +02:00
|
|
|
$oHostGroup->paramSet(HOST_BACKUP_USER, 'backrest');
|
|
|
|
|
|
|
|
if ($strDbVersion ne 'minimal')
|
2015-02-28 06:31:39 +02:00
|
|
|
{
|
2016-06-24 14:12:58 +02:00
|
|
|
$oHostGroup->paramSet(HOST_PARAM_DB_VERSION, $strDbVersion);
|
|
|
|
$oHostGroup->paramSet(HOST_PARAM_DB_BIN_PATH, $strPgSqlBin);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (testSetup($strTestPath, $strPgSqlBin, $iModuleTestRun,
|
2016-06-12 15:00:16 +02:00
|
|
|
$bDryRun, $bNoCleanup, $bLogForce))
|
2016-06-24 14:12:58 +02:00
|
|
|
{
|
|
|
|
if (!$bVmOut &&
|
|
|
|
($strModule eq 'all' ||
|
|
|
|
$strModule eq 'backup' && $strModuleTest eq 'all' ||
|
|
|
|
$strModule eq 'backup' && $strModuleTest eq 'full'))
|
2015-06-14 00:25:49 +02:00
|
|
|
{
|
2016-06-24 14:12:58 +02:00
|
|
|
&log(INFO, "TESTING psql-bin = $strPgSqlBin\n");
|
|
|
|
}
|
2015-02-28 06:31:39 +02:00
|
|
|
|
2016-07-30 00:02:16 +02:00
|
|
|
if ($strModule eq 'all' || $strModule eq 'help')
|
|
|
|
{
|
|
|
|
helpTestRun($strModuleTest, $bVmOut);
|
|
|
|
}
|
2015-09-08 18:58:13 +02:00
|
|
|
|
2016-07-30 00:02:16 +02:00
|
|
|
if ($strModule eq 'all' || $strModule eq 'config')
|
|
|
|
{
|
|
|
|
configTestRun($strModuleTest, $bVmOut);
|
|
|
|
}
|
2015-04-03 04:07:23 +02:00
|
|
|
|
2016-06-24 14:12:58 +02:00
|
|
|
if ($strModule eq 'all' || $strModule eq 'file')
|
|
|
|
{
|
2016-07-30 00:02:16 +02:00
|
|
|
fileTestRun($strModuleTest, $bVmOut);
|
2016-06-24 14:12:58 +02:00
|
|
|
}
|
2015-06-14 00:25:49 +02:00
|
|
|
|
2016-06-24 14:12:58 +02:00
|
|
|
if ($strModule eq 'all' || $strModule eq 'backup')
|
|
|
|
{
|
2016-07-30 00:02:16 +02:00
|
|
|
backupTestRun($strModuleTest, $bVmOut);
|
2016-06-24 14:12:58 +02:00
|
|
|
}
|
|
|
|
}
|
2015-09-09 21:40:54 +02:00
|
|
|
|
2016-06-24 14:12:58 +02:00
|
|
|
if (!$bNoCleanup)
|
|
|
|
{
|
|
|
|
if ($oHostGroup->removeAll() > 0)
|
|
|
|
{
|
|
|
|
executeTest("sudo rm -rf ${strTestPath}");
|
2015-06-14 00:25:49 +02:00
|
|
|
}
|
2015-02-28 06:31:39 +02:00
|
|
|
}
|
2015-06-14 00:25:49 +02:00
|
|
|
|
2016-09-06 15:44:50 +02:00
|
|
|
if (!$bDryRun && !$bVmOut)
|
2015-04-08 00:36:59 +02:00
|
|
|
{
|
2016-09-06 15:44:50 +02:00
|
|
|
&log(INFO, 'TESTS COMPLETED SUCCESSFULLY (DESPITE ANY ERROR MESSAGES YOU SAW)');
|
2015-04-08 00:36:59 +02:00
|
|
|
}
|
2015-06-14 00:25:49 +02:00
|
|
|
|
2016-09-06 15:44:50 +02:00
|
|
|
# Exit with success
|
|
|
|
exit 0;
|
2014-06-22 18:56:01 +03:00
|
|
|
}
|
2015-06-14 00:25:49 +02:00
|
|
|
|
2016-09-06 15:44:50 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# Check for errors
|
|
|
|
####################################################################################################################################
|
|
|
|
or do
|
2014-07-16 05:32:41 +03:00
|
|
|
{
|
2016-09-06 15:44:50 +02:00
|
|
|
# If a backrest exception then return the code
|
|
|
|
exit $EVAL_ERROR->code() if (isException($EVAL_ERROR));
|
|
|
|
|
|
|
|
# Else output the unhandled error
|
|
|
|
print $EVAL_ERROR;
|
|
|
|
exit ERROR_UNHANDLED;
|
|
|
|
};
|
|
|
|
|
|
|
|
# It shouldn't be possible to get here
|
|
|
|
&log(ASSERT, 'execution reached invalid location in ' . __FILE__ . ', line ' . __LINE__);
|
|
|
|
exit ERROR_ASSERT;
|