You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2026-05-22 10:15:16 +02:00
Allow most unit tests to run outside of a container.
Three major changes were required to get this working: 1) Provide the path to pgbackrest in the build directory when running outside a container. Tests in a container will continue to install and run against /usr/bin/pgbackrest. 1) Set a per-test lock path so tests don't conflict on the default /tmp/pgbackrest path. Also set a per-test log-path while we are at it. 2) Use localhost instead of a custom host for TLS test connections. Tests in containers will continue to update /etc/hosts and use the custom host. Add infrastructure and update harnessCfgLoad*() to get the correct exe and paths loaded for testing. Since new tests are required to verify that running outside a container works, also rework the tests in Travis CI to provide coverage within a reasonable amount of time. Mainly, break up to doc tests by VM and run an abbreviated unit test suite on co6 and co7.
This commit is contained in:
@@ -86,16 +86,22 @@ sub process
|
||||
"services:\n" .
|
||||
" - docker\n" .
|
||||
"\n" .
|
||||
"env:\n";
|
||||
|
||||
$strConfig .= " - PGB_CI=\"doc\"\n";
|
||||
"matrix:\n" .
|
||||
" include:\n";
|
||||
|
||||
# Iterate each OS
|
||||
foreach my $strVm (VM_LIST)
|
||||
{
|
||||
$strConfig .= " - PGB_CI=\"--vm=${strVm} test\"\n";
|
||||
$strConfig .= " - env: PGB_CI=\"--vm=${strVm} test\"\n";
|
||||
}
|
||||
|
||||
$strConfig .=
|
||||
" - env: PGB_CI=\"--vm=u18 doc\"\n" .
|
||||
" - dist: bionic\n" .
|
||||
" env: PGB_CI=\"--vm=none test\"\n" .
|
||||
" - env: PGB_CI=\"--vm=co7 doc\"\n" .
|
||||
" - env: PGB_CI=\"--vm=co6 doc\"\n";
|
||||
|
||||
# Configure install and script
|
||||
$strConfig .=
|
||||
"\n" .
|
||||
|
||||
@@ -43,7 +43,7 @@ use constant TEST_GROUP_ID => getgrnam(
|
||||
|
||||
use constant BACKREST_USER => 'pgbackrest';
|
||||
push @EXPORT, qw(BACKREST_USER);
|
||||
use constant BACKREST_USER_ID => getpwnam(BACKREST_USER) . '';
|
||||
use constant BACKREST_USER_ID => getpwnam(BACKREST_USER) ? getpwnam(BACKREST_USER) . '' : undef;
|
||||
|
||||
####################################################################################################################################
|
||||
# Package constants
|
||||
|
||||
@@ -41,6 +41,8 @@ use constant TESTDEF_DB => 'db';
|
||||
push @EXPORT, qw(TESTDEF_DB);
|
||||
use constant TESTDEF_CONTAINER => 'container';
|
||||
push @EXPORT, qw(TESTDEF_CONTAINER);
|
||||
use constant TESTDEF_CONTAINER_REQUIRED => 'containerReq';
|
||||
push @EXPORT, qw(TESTDEF_CONTAINER_REQUIRED);
|
||||
use constant TESTDEF_COVERAGE => 'coverage';
|
||||
push @EXPORT, qw(TESTDEF_COVERAGE);
|
||||
use constant TESTDEF_EXPECT => 'expect';
|
||||
@@ -126,7 +128,8 @@ sub testDefLoad
|
||||
|
||||
# Resolve variables that can be set in the module or the test
|
||||
foreach my $strVar (
|
||||
TESTDEF_DEFINE, TESTDEF_DEFINE_TEST, TESTDEF_DEBUG_UNIT_SUPPRESS, TESTDEF_DB, TESTDEF_PERL_REQ, TESTDEF_VM)
|
||||
TESTDEF_DEFINE, TESTDEF_DEFINE_TEST, TESTDEF_DEBUG_UNIT_SUPPRESS, TESTDEF_DB, TESTDEF_PERL_REQ, TESTDEF_VM,
|
||||
TESTDEF_CONTAINER_REQUIRED)
|
||||
{
|
||||
$hTestDefHash->{$strModule}{$strTest}{$strVar} = coalesce(
|
||||
$hModuleTest->{$strVar}, $hModule->{$strVar}, $strVar eq TESTDEF_VM ? undef : false);
|
||||
|
||||
@@ -55,6 +55,7 @@ sub new
|
||||
# Set defaults
|
||||
$self->{bSuppressError} = defined($self->{bSuppressError}) ? $self->{bSuppressError} : false;
|
||||
$self->{bSuppressStdErr} = defined($self->{bSuppressStdErr}) ? $self->{bSuppressStdErr} : false;
|
||||
$self->{bOutLogOnError} = defined($self->{bOutLogOnError}) ? $self->{bOutLogOnError} : true;
|
||||
$self->{bShowOutput} = defined($self->{bShowOutput}) ? $self->{bShowOutput} : false;
|
||||
$self->{bShowOutputAsync} = defined($self->{bShowOutputAsync}) ? $self->{bShowOutputAsync} : false;
|
||||
$self->{iExpectedExitStatus} = defined($self->{iExpectedExitStatus}) ? $self->{iExpectedExitStatus} : 0;
|
||||
@@ -252,8 +253,10 @@ sub endRetry
|
||||
{
|
||||
confess &log(ERROR, "command '$self->{strCommand}' returned " . $iExitStatus .
|
||||
($self->{iExpectedExitStatus} != 0 ? ", but $self->{iExpectedExitStatus} was expected" : '') . "\n" .
|
||||
($self->{strOutLog} ne '' ? "STDOUT (last 10,000 characters):\n" . substr($self->{strOutLog},
|
||||
length($self->{strOutLog}) > 10000 ? length($self->{strOutLog}) - 10000 : 0) : '') .
|
||||
($self->{strOutLog} ne '' && $self->{bOutLogOnError} ? "STDOUT (last 10,000 characters):\n" .
|
||||
substr(
|
||||
$self->{strOutLog}, length($self->{strOutLog}) > 10000 ?
|
||||
length($self->{strOutLog}) - 10000 : 0) : '') .
|
||||
($self->{strErrorLog} ne '' ? "STDERR:\n$self->{strErrorLog}" : ''));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,6 @@ sub new
|
||||
$self->{oStorageTest},
|
||||
$self->{strBackRestBase},
|
||||
$self->{strTestPath},
|
||||
$self->{strCoveragePath},
|
||||
$self->{oTest},
|
||||
$self->{bDryRun},
|
||||
$self->{bVmOut},
|
||||
@@ -86,7 +85,6 @@ sub new
|
||||
{name => 'oStorageTest'},
|
||||
{name => 'strBackRestBase'},
|
||||
{name => 'strTestPath'},
|
||||
{name => 'strCoveragePath'},
|
||||
{name => 'oTest'},
|
||||
{name => 'bDryRun'},
|
||||
{name => 'bVmOut'},
|
||||
@@ -117,7 +115,7 @@ sub new
|
||||
|
||||
# Setup the path where gcc coverage will be performed
|
||||
$self->{strGCovPath} = "$self->{strTestPath}/gcov-$self->{oTest}->{&TEST_VM}-$self->{iVmIdx}";
|
||||
$self->{strExpectPath} = "$self->{strTestPath}/expect-$self->{iVmIdx}";
|
||||
$self->{strDataPath} = "$self->{strTestPath}/data-$self->{iVmIdx}";
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
@@ -189,24 +187,26 @@ sub run
|
||||
$bGCovExists = false;
|
||||
}
|
||||
|
||||
# Create expect directory
|
||||
if ($self->{oTest}->{&TEST_C} && !$self->{oStorageTest}->pathExists($self->{strExpectPath}))
|
||||
# Create data directory
|
||||
if ($self->{oTest}->{&TEST_C} && !$self->{oStorageTest}->pathExists($self->{strDataPath}))
|
||||
{
|
||||
$self->{oStorageTest}->pathCreate($self->{strExpectPath}, {strMode => '0770'});
|
||||
$self->{oStorageTest}->pathCreate($self->{strDataPath}, {strMode => '0770'});
|
||||
}
|
||||
|
||||
if ($self->{oTest}->{&TEST_CONTAINER})
|
||||
{
|
||||
executeTest(
|
||||
'docker run -itd -h ' . $self->{oTest}->{&TEST_VM} . "-test --name=${strImage}" .
|
||||
" -v $self->{strCoveragePath}:$self->{strCoveragePath} " .
|
||||
" -v ${strHostTestPath}:${strVmTestPath}" .
|
||||
($self->{oTest}->{&TEST_C} ? " -v $self->{strGCovPath}:$self->{strGCovPath}" : '') .
|
||||
($self->{oTest}->{&TEST_C} ? " -v $self->{strExpectPath}:$self->{strExpectPath}" : '') .
|
||||
" -v $self->{strBackRestBase}:$self->{strBackRestBase} " .
|
||||
containerRepo() . ':' . $self->{oTest}->{&TEST_VM} .
|
||||
"-test",
|
||||
{bSuppressStdErr => true});
|
||||
if ($self->{oTest}->{&TEST_VM} ne VM_NONE)
|
||||
{
|
||||
executeTest(
|
||||
'docker run -itd -h ' . $self->{oTest}->{&TEST_VM} . "-test --name=${strImage}" .
|
||||
" -v ${strHostTestPath}:${strVmTestPath}" .
|
||||
($self->{oTest}->{&TEST_C} ? " -v $self->{strGCovPath}:$self->{strGCovPath}" : '') .
|
||||
($self->{oTest}->{&TEST_C} ? " -v $self->{strDataPath}:$self->{strDataPath}" : '') .
|
||||
" -v $self->{strBackRestBase}:$self->{strBackRestBase} " .
|
||||
containerRepo() . ':' . $self->{oTest}->{&TEST_VM} .
|
||||
"-test",
|
||||
{bSuppressStdErr => true});
|
||||
}
|
||||
|
||||
# If testing C code copy source files to the test directory
|
||||
if ($self->{oTest}->{&TEST_C})
|
||||
@@ -230,7 +230,7 @@ sub run
|
||||
}
|
||||
|
||||
# If testing Perl code (or C code that calls Perl code) install bin and Perl C Library
|
||||
if (!$self->{oTest}->{&TEST_C} || $self->{oTest}->{&TEST_PERL_REQ})
|
||||
if ($self->{oTest}->{&TEST_VM} ne VM_NONE && (!$self->{oTest}->{&TEST_C} || $self->{oTest}->{&TEST_PERL_REQ}))
|
||||
{
|
||||
jobInstallC(
|
||||
$self->{strBackRestBase}, $self->{oTest}->{&TEST_VM}, $strImage,
|
||||
@@ -253,7 +253,8 @@ sub run
|
||||
if ($self->{oTest}->{&TEST_C})
|
||||
{
|
||||
$strCommand =
|
||||
'docker exec -i -u ' . TEST_USER . " ${strImage} bash -l -c '" .
|
||||
($self->{oTest}->{&TEST_VM} ne VM_NONE ? 'docker exec -i -u ' . TEST_USER . " ${strImage} " : '') .
|
||||
"bash -l -c '" .
|
||||
"cd $self->{strGCovPath} && " .
|
||||
"make -j $self->{iBuildMax} -s 2>&1 &&" .
|
||||
($self->{oTest}->{&TEST_VM} ne VM_CO6 && $self->{bValgrindUnit} &&
|
||||
@@ -372,9 +373,18 @@ sub run
|
||||
$strDepend;
|
||||
}
|
||||
|
||||
# Determine where the project exe is located
|
||||
my $strProjectExePath = $self->{oTest}->{&TEST_VM} eq VM_NONE ?
|
||||
"$self->{strBackRestBase}/test/.vagrant/bin/$self->{oTest}->{&TEST_VM}/src/" . PROJECT_EXE : PROJECT_EXE;
|
||||
|
||||
# Is this test running in a container?
|
||||
my $strContainer = $self->{oTest}->{&TEST_VM} eq VM_NONE ? 'false' : 'true';
|
||||
|
||||
# Set globals
|
||||
$strTestC =~ s/\{\[C\_TEST\_CONTAINER\]\}/$strContainer/g;
|
||||
$strTestC =~ s/\{\[C\_TEST\_PROJECT\_EXE\]\}/$strProjectExePath/g;
|
||||
$strTestC =~ s/\{\[C\_TEST\_PATH\]\}/$strVmTestPath/g;
|
||||
$strTestC =~ s/\{\[C\_TEST\_EXPECT_PATH\]\}/$self->{strExpectPath}/g;
|
||||
$strTestC =~ s/\{\[C\_TEST\_DATA_PATH\]\}/$self->{strDataPath}/g;
|
||||
$strTestC =~ s/\{\[C\_TEST\_REPO_PATH\]\}/$self->{strBackRestBase}/g;
|
||||
$strTestC =~ s/\{\[C\_TEST\_SCALE\]\}/$self->{iScale}/g;
|
||||
|
||||
@@ -571,7 +581,7 @@ sub end
|
||||
if ($iExitStatus == 0 && $self->{oTest}->{&TEST_C} && $self->{bProfile})
|
||||
{
|
||||
executeTest(
|
||||
'docker exec -i -u ' . TEST_USER . " ${strImage} " .
|
||||
($self->{oTest}->{&TEST_VM} ne VM_NONE ? 'docker exec -i -u ' . TEST_USER . " ${strImage} " : '') .
|
||||
"gprof $self->{strGCovPath}/test.bin $self->{strGCovPath}/gmon.out > $self->{strGCovPath}/gprof.txt");
|
||||
|
||||
$self->{oStorageTest}->pathCreate("$self->{strBackRestBase}/test/profile", {strMode => '0750', bIgnoreExists => true});
|
||||
@@ -606,7 +616,7 @@ sub end
|
||||
my $strLCovOutTmp = $self->{strGCovPath} . '/test.tmp.lcov';
|
||||
|
||||
executeTest(
|
||||
'docker exec -i -u ' . TEST_USER . " ${strImage} " .
|
||||
($self->{oTest}->{&TEST_VM} ne VM_NONE ? 'docker exec -i -u ' . TEST_USER . " ${strImage} " : '') .
|
||||
"${strLCovExeBase} --capture --directory=$self->{strGCovPath} --o=${strLCovOut}");
|
||||
|
||||
# Generate coverage report for each module
|
||||
@@ -731,8 +741,12 @@ sub end
|
||||
{
|
||||
my $strHostTestPath = "$self->{strTestPath}/${strImage}";
|
||||
|
||||
containerRemove("test-$self->{iVmIdx}");
|
||||
executeTest("sudo rm -rf ${strHostTestPath}");
|
||||
if ($self->{oTest}->{&TEST_VM} ne VM_NONE)
|
||||
{
|
||||
containerRemove("test-$self->{iVmIdx}");
|
||||
}
|
||||
|
||||
executeTest(($self->{oTest}->{&TEST_VM} ne VM_NONE ? "sudo " : '') . "rm -rf ${strHostTestPath}");
|
||||
}
|
||||
|
||||
$bDone = true;
|
||||
|
||||
@@ -65,6 +65,7 @@ sub testListGet
|
||||
my $strDbVersion = shift;
|
||||
my $bCoverageOnly = shift;
|
||||
my $bCOnly = shift;
|
||||
my $bContainerOnly = shift;
|
||||
|
||||
my $oyVm = vmGet();
|
||||
my $oyTestRun = [];
|
||||
@@ -113,6 +114,18 @@ sub testListGet
|
||||
# Skip this test if only C tests are requested and this is not a C test
|
||||
next if ($bCOnly && !$hTest->{&TESTDEF_C});
|
||||
|
||||
# Skip this test if it is integration and vm=none
|
||||
next if ($strVm eq VM_NONE && $hTest->{&TESTDEF_TYPE} eq TESTDEF_INTEGRATION);
|
||||
|
||||
# Skip this test if it is not C and vm=none. Perl tests require libc which is not supported.
|
||||
next if ($strVm eq VM_NONE && !$hTest->{&TESTDEF_C});
|
||||
|
||||
# Skip this test if a container is required and vm=none.
|
||||
next if ($strVm eq VM_NONE && $hTest->{&TESTDEF_CONTAINER_REQUIRED});
|
||||
|
||||
# Skip this if it does not require a container and container only tests are required.
|
||||
next if ($bContainerOnly && $hTest->{&TESTDEF_C} && !$hTest->{&TESTDEF_CONTAINER_REQUIRED});
|
||||
|
||||
for (my $iDbVersionIdx = $iDbVersionMax; $iDbVersionIdx >= $iDbVersionMin; $iDbVersionIdx--)
|
||||
{
|
||||
if ($iDbVersionIdx == -1 || $strDbVersion eq 'all' || $strDbVersion eq 'minimal' ||
|
||||
|
||||
@@ -80,6 +80,9 @@ use constant VM_ARCH_AMD64 => 'amd64';
|
||||
use constant VM_ALL => 'all';
|
||||
push @EXPORT, qw(VM_ALL);
|
||||
|
||||
use constant VM_NONE => 'none';
|
||||
push @EXPORT, qw(VM_NONE);
|
||||
|
||||
use constant VM_CO6 => 'co6';
|
||||
push @EXPORT, qw(VM_CO6);
|
||||
use constant VM_CO7 => 'co7';
|
||||
@@ -115,12 +118,33 @@ use constant VM3 => VM_CO7;
|
||||
use constant VM4 => VM_U18;
|
||||
push @EXPORT, qw(VM4);
|
||||
|
||||
# List of default test VMs (in this order: newest, oldest, next newest, next oldest)
|
||||
use constant VM_LIST => (VM4, VM1, VM3, VM2);
|
||||
# List of default test VMs
|
||||
use constant VM_LIST => (VM2, VM1, VM3, VM4);
|
||||
push @EXPORT, qw(VM_LIST);
|
||||
|
||||
my $oyVm =
|
||||
{
|
||||
# None
|
||||
&VM_NONE =>
|
||||
{
|
||||
&VM_OS_BASE => VM_OS_BASE_RHEL,
|
||||
&VM_OS => VM_OS_CENTOS,
|
||||
&VM_ARCH => VM_ARCH_AMD64,
|
||||
&VMDEF_COVERAGE_C => true,
|
||||
&VMDEF_PGSQL_BIN => '/usr/pgsql-{[version]}/bin',
|
||||
&VMDEF_PERL_ARCH_PATH => '/usr/local/lib64/perl5',
|
||||
|
||||
&VM_DB =>
|
||||
[
|
||||
PG_VERSION_10,
|
||||
],
|
||||
|
||||
&VM_DB_TEST =>
|
||||
[
|
||||
PG_VERSION_10,
|
||||
],
|
||||
},
|
||||
|
||||
# CentOS 6
|
||||
&VM_CO6 =>
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user