1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-09-16 09:06:18 +02:00

Coverage testing always enabled on Debian-based containers.

* Full coverage is verified when specified.
* Modules marked with partial coverage will error if they are actually fully covered.
* Simplified test representation is DefineTest.
* Added new representation for queries in DefineTest and added API functions.
* Update modules using DefineTest to use new API.
This commit is contained in:
David Steele
2017-04-10 12:31:30 -04:00
parent eb4918d018
commit 367e06f4be
12 changed files with 648 additions and 358 deletions

View File

@@ -13,31 +13,35 @@ services:
- docker
env:
- PGB_TEST_VM="co6" PGB_BUILD_PARAM="--db=none" PGB_TEST_PARAM="--module=help --module=config --module=file --module=stanza --module=archive --module=backup --module=expire --module=info"
- PGB_TEST_VM="co6" PGB_BUILD_PARAM="--db=none" PGB_TEST_PARAM="--module=help --module=config --module=file --module=info --module=stanza --module=archive --module=backup --module=expire"
- PGB_TEST_VM="co6" PGB_BUILD_PARAM="--db=none" PGB_TEST_PARAM="--module=full --test=synthetic --no-lint --no-package"
- PGB_TEST_VM="co6" PGB_BUILD_PARAM="--db=9.1" PGB_TEST_PARAM="--module=full --test=real --db=9.1 --process-max=2 --no-lint --no-package"
- PGB_TEST_VM="co6" PGB_BUILD_PARAM="--db=9.0" PGB_TEST_PARAM="--module=full --test=real --db=9.0 --process-max=2 --no-lint --no-package"
- PGB_TEST_VM="u16" PGB_BUILD_PARAM="--db=none" PGB_TEST_PARAM="--module=help --module=config --module=file --module=stanza --module=archive --module=backup --module=expire --module=info --no-lint"
- PGB_TEST_VM="u16" PGB_BUILD_PARAM="--db=none" PGB_TEST_PARAM="--module=help --module=config --module=file --module=info --module=stanza --module=archive --module=backup --module=expire --no-lint"
- PGB_TEST_VM="u16" PGB_BUILD_PARAM="--db=none" PGB_TEST_PARAM="--module=full --test=synthetic --no-lint --no-package"
- PGB_TEST_VM="u16" PGB_BUILD_PARAM="--db=9.4" PGB_TEST_PARAM="--module=full --test=real --db=9.4 --process-max=2 --no-lint --no-package"
- PGB_TEST_VM="d8" PGB_BUILD_PARAM="--db=none" PGB_TEST_PARAM="--module=help --module=config --module=file --module=stanza --module=archive --module=backup --module=expire --module=info --no-lint"
- PGB_TEST_VM="d8" PGB_BUILD_PARAM="--db=none" PGB_TEST_PARAM="--module=help --module=config --module=file --module=info --module=stanza --module=archive --module=backup --module=expire --no-lint"
- PGB_TEST_VM="d8" PGB_BUILD_PARAM="--db=none" PGB_TEST_PARAM="--module=full --test=synthetic --no-lint --no-package"
- PGB_TEST_VM="d8" PGB_BUILD_PARAM="--db=9.3" PGB_TEST_PARAM="--module=full --test=real --db=9.3 --process-max=2 --no-lint --no-package"
- PGB_TEST_VM="d8" PGB_BUILD_PARAM="--db=8.4" PGB_TEST_PARAM="--module=full --test=real --db=8.4 --process-max=2 --no-lint --no-package"
- PGB_TEST_VM="co7" PGB_BUILD_PARAM="--db=none" PGB_TEST_PARAM="--module=help --module=config --module=file --module=stanza --module=archive --module=backup --module=expire --module=info --no-lint"
- PGB_TEST_VM="co7" PGB_BUILD_PARAM="--db=none" PGB_TEST_PARAM="--module=help --module=config --module=file --module=info --module=stanza --module=archive --module=backup --module=expire --no-lint"
- PGB_TEST_VM="co7" PGB_BUILD_PARAM="--db=none" PGB_TEST_PARAM="--module=full --test=synthetic --no-lint --no-package"
- PGB_TEST_VM="co7" PGB_BUILD_PARAM="--db=9.6" PGB_TEST_PARAM="--module=full --test=real --db=9.6 --process-max=2 --no-lint --no-package"
- PGB_TEST_VM="co7" PGB_BUILD_PARAM="--db=9.5" PGB_TEST_PARAM="--module=full --test=real --db=9.5 --process-max=2 --no-lint --no-package"
- PGB_TEST_VM="u14" PGB_BUILD_PARAM="--db=none" PGB_TEST_PARAM="--module=help --module=config --module=file --module=stanza --module=archive --module=backup --module=expire --module=info --no-lint"
- PGB_TEST_VM="u14" PGB_BUILD_PARAM="--db=none" PGB_TEST_PARAM="--module=help --module=config --module=file --module=info --module=stanza --module=archive --module=backup --module=expire --no-lint"
- PGB_TEST_VM="u14" PGB_BUILD_PARAM="--db=none" PGB_TEST_PARAM="--module=full --test=synthetic --no-lint --no-package"
- PGB_TEST_VM="u14" PGB_BUILD_PARAM="--db=9.2" PGB_TEST_PARAM="--module=full --test=real --db=9.2 --process-max=2 --no-lint --no-package"
- PGB_TEST_VM="u12" PGB_BUILD_PARAM="--db=none" PGB_TEST_PARAM="--module=help --module=config --module=file --module=stanza --module=archive --module=backup --module=expire --module=info --no-lint"
- PGB_TEST_VM="u12" PGB_BUILD_PARAM="--db=none" PGB_TEST_PARAM="--module=help --module=config --module=file --module=info --module=stanza --module=archive --module=backup --module=expire --no-lint"
- PGB_TEST_VM="u12" PGB_BUILD_PARAM="--db=none" PGB_TEST_PARAM="--module=full --test=synthetic --no-lint --no-package"
- PGB_TEST_VM="u12" PGB_BUILD_PARAM="--db=8.3" PGB_TEST_PARAM="--module=full --test=real --db=8.3 --process-max=2 --no-lint --no-package"
before_install:
- sudo apt-get -qq update
- sudo apt-get install libxml-checker-perl libdbd-pg-perl libperl-critic-perl libdevel-cover-perl
- sudo apt-get install libxml-checker-perl libdbd-pg-perl libperl-critic-perl libtemplate-perl libpod-coverage-perl libtest-differences-perl libhtml-parser-perl lintian debhelper txt2man devscripts libjson-perl
- git clone https://anonscm.debian.org/git/pkg-perl/packages/libdevel-cover-perl.git ~/libdevel-cover-perl
- cd ~/libdevel-cover-perl && git checkout debian/1.23-2 && debuild -i -us -uc -b
- sudo dpkg -i ~/libdevel-cover-perl_1.23-2_amd64.deb
- /usr/bin/cover -v
install:
- sudo adduser --ingroup=${USER?} --disabled-password --gecos "" backrest

View File

@@ -212,6 +212,10 @@
<release-test-list>
<release-refactor-list>
<release-item>
<p>Coverage testing always enabled on Debian-based containers.</p>
</release-item>
<release-item>
<p>Require description in every call to <code>testResult()</code>.</p>
</release-item>

View File

@@ -32,6 +32,24 @@ sub trim
push @EXPORT, qw(trim);
####################################################################################################################################
# coalesce
#
# Return the first non-null parameter.
####################################################################################################################################
sub coalesce
{
foreach my $strParam (@_)
{
if (defined($strParam))
{
return $strParam;
}
}
}
push @EXPORT, qw(coalesce);
####################################################################################################################################
# commonPrefix
#

42
test/Vagrantfile vendored
View File

@@ -13,6 +13,7 @@ Vagrant.configure(2) do |config|
# Provision the VM
config.vm.provision "shell", inline: <<-SHELL
#---------------------------------------------------------------------------------------------------------------------------
echo 'Build Begin' && date
# Suppress "dpkg-reconfigure: unable to re-open stdin: No file or directory" warning
@@ -22,18 +23,32 @@ Vagrant.configure(2) do |config|
sed -i 's/^127\.0\.0\.1\t.*/127\.0\.0\.1\tlocalhost pgbackrest-test/' /etc/hosts
hostnamectl set-hostname pgbackrest-test
# Update Apt
#---------------------------------------------------------------------------------------------------------------------------
echo 'Update Apt' && date
apt-get update
# Install build tools
apt-get install -y devscripts build-essential lintian git txt2man debhelper
# Synchronize date
#---------------------------------------------------------------------------------------------------------------------------
echo 'Synchronize Date' && date
apt-get install -y ntpdate
ntpdate pool.ntp.org
# Install Docker
#---------------------------------------------------------------------------------------------------------------------------
echo 'Install Perl Modules' && date
apt-get install -y libdbd-pg-perl libxml-checker-perl libperl-critic-perl libdevel-nytprof-perl
#---------------------------------------------------------------------------------------------------------------------------
echo 'Install Build Tools' && date
apt-get install -y devscripts build-essential lintian git txt2man debhelper
#---------------------------------------------------------------------------------------------------------------------------
echo 'Build Devel::Cover' && date
apt-get install -y libpod-coverage-perl libtest-differences-perl libhtml-parser-perl libtemplate-perl
git clone --branch debian/1.23-2 \
https://anonscm.debian.org/git/pkg-perl/packages/libdevel-cover-perl.git /root/libdevel-cover-perl
cd /root/libdevel-cover-perl && debuild --no-lintian -i -us -uc -b > /dev/null
dpkg -i /root/libdevel-cover-perl_1.23-2_amd64.deb
#---------------------------------------------------------------------------------------------------------------------------
echo 'Install Docker' && date
apt-get install -y apt-transport-https ca-certificates
apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
@@ -44,31 +59,28 @@ Vagrant.configure(2) do |config|
service docker start
sudo usermod -aG docker ubuntu
# Install Perl modules
echo 'Install Perl Modules' && date
apt-get install -y libdbd-pg-perl libxml-checker-perl libperl-critic-perl libdevel-nytprof-perl libdevel-cover-perl
# Install utilities
echo 'Install Utilities' && date
#---------------------------------------------------------------------------------------------------------------------------
echo 'Install Dev Utilities' && date
apt-get install -y vim htop
# Install TeX Live
#---------------------------------------------------------------------------------------------------------------------------
echo 'Install TeX Live' && date
apt-get install -y --no-install-recommends texlive-latex-base texlive-latex-extra texlive-fonts-recommended
apt-get install -y texlive-font-utils
# Create backrest user and postgres group
#---------------------------------------------------------------------------------------------------------------------------
echo 'Create Postgres Group & pgBackRest User' && date
groupadd -g5000 postgres
adduser --uid=5001 --ingroup=ubuntu --disabled-password --gecos "" backrest
# Build VM images
#---------------------------------------------------------------------------------------------------------------------------
echo 'Build VM Images' && date
rm -rf /backrest/test/.vagrant/docker/*
rm -rf /backrest/test/.vagrant/libc/*
rm -rf /backrest/test/.vagrant/package/*
sudo su - ubuntu -c '/backrest/test/test.pl --vm-build'
#---------------------------------------------------------------------------------------------------------------------------
echo 'Build End' && date
SHELL

View File

@@ -94,23 +94,20 @@ sub process
# Iterate each OS
foreach my $strVm (VM_LIST)
{
my $hTestDef = testDefGet();
my $hVm = vmGet();
my @stryModule;
my $hFullModule = undef;
my $strFullModule = undef;
# Get all modules but full to break up the tests
foreach my $hModule (@{$hTestDef->{&TESTDEF_MODULE}})
foreach my $strModule (testDefModuleList())
{
my $strModule = $hModule->{&TESTDEF_MODULE_NAME};
if ($strModule ne 'full')
{
push(@stryModule, $strModule);
}
else
{
$hFullModule = $hModule;
$strFullModule = $strModule;
}
}
@@ -124,20 +121,18 @@ sub process
$bFirst = false;
# Now generate full tests
my $hRealTest = undef;
my $strRealTest = undef;
if (!defined($hFullModule))
if (!defined($strFullModule))
{
confess "the full module is not defined, has the name changed?";
confess "${strFullModule} module not found, has the name changed?";
}
foreach my $hTest (@{$hFullModule->{&TESTDEF_TEST}})
foreach my $strTest (testDefModuleTestList($strFullModule))
{
my $strTest = $hTest->{&TESTDEF_TEST_NAME};
if ($strTest eq 'real')
{
$hRealTest = $hTest;
$strRealTest = $strTest;
foreach my $strDbVersion (sort {$b cmp $a} @{$hVm->{$strVm}{&VM_DB_MINIMAL}})
{
@@ -155,9 +150,9 @@ sub process
}
}
if (!defined($hRealTest))
if (!defined($strRealTest))
{
confess 'real test not found in full module, has the name changed?';
confess "${strRealTest} test not found in ${strFullModule} module, has the name changed?";
}
}
@@ -166,7 +161,12 @@ sub process
"\n" .
"before_install:\n" .
" - sudo apt-get -qq update\n" .
" - sudo apt-get install libxml-checker-perl libdbd-pg-perl libperl-critic-perl libdevel-cover-perl\n" .
" - sudo apt-get install libxml-checker-perl libdbd-pg-perl libperl-critic-perl libtemplate-perl libpod-coverage-perl" .
" libtest-differences-perl libhtml-parser-perl lintian debhelper txt2man devscripts libjson-perl\n" .
" - git clone https://anonscm.debian.org/git/pkg-perl/packages/libdevel-cover-perl.git ~/libdevel-cover-perl\n" .
' - cd ~/libdevel-cover-perl && git checkout debian/' . LIB_COVER_VERSION . " && debuild -i -us -uc -b\n" .
' - sudo dpkg -i ~/' . LIB_COVER_PACKAGE . "\n" .
' - ' . LIB_COVER_EXE . " -v\n" .
"\n" .
"install:\n" .
" - sudo adduser --ingroup=\${USER?} --disabled-password --gecos \"\" " . BACKREST_USER . "\n" .

View File

@@ -46,6 +46,16 @@ use constant BACKREST_USER => 'backrest
push @EXPORT, qw(BACKREST_USER);
use constant BACKREST_USER_ID => getpwnam(BACKREST_USER) . '';
####################################################################################################################################
# Package constants
####################################################################################################################################
use constant LIB_COVER_VERSION => '1.23-2';
push @EXPORT, qw(LIB_COVER_VERSION);
use constant LIB_COVER_PACKAGE => 'libdevel-cover-perl_' . LIB_COVER_VERSION . '_amd64.deb';
push @EXPORT, qw(LIB_COVER_PACKAGE);
use constant LIB_COVER_EXE => '/usr/bin/cover';
push @EXPORT, qw(LIB_COVER_EXE);
####################################################################################################################################
# Container repo
####################################################################################################################################
@@ -257,6 +267,27 @@ sub sudoSetup
return $strScript;
}
####################################################################################################################################
# Devel::Cover setup
####################################################################################################################################
sub coverSetup
{
my $strOS = shift;
my $strScript = '';
my $oVm = vmGet();
if ($$oVm{$strOS}{&VM_OS_BASE} eq VM_OS_BASE_DEBIAN)
{
$strScript .=
"\n\n# Install Devel::Cover\n" .
"COPY ${strOS}-" . LIB_COVER_PACKAGE . ' /tmp/' . LIB_COVER_PACKAGE . "\n" .
'RUN dpkg -i /tmp/' . LIB_COVER_PACKAGE;
}
return $strScript;
}
####################################################################################################################################
# Install Perl packages
####################################################################################################################################
@@ -269,27 +300,30 @@ sub perlInstall
if ($strOS eq VM_CO6)
{
return $strImage .
$strImage .=
'RUN yum install -y perl perl-Time-HiRes perl-parent perl-JSON perl-Digest-SHA perl-DBD-Pg';
}
elsif ($strOS eq VM_CO7)
{
return $strImage .
$strImage .=
'RUN yum install -y perl perl-JSON-PP perl-Digest-SHA perl-DBD-Pg';
}
elsif ($strOS eq VM_U12 || $strOS eq VM_U14)
{
return $strImage .
'RUN apt-get install -y libdbd-pg-perl libdbi-perl libnet-daemon-perl libplrpc-perl';
$strImage .=
'RUN apt-get install -y libdbd-pg-perl libdbi-perl libnet-daemon-perl libplrpc-perl libhtml-parser-perl';
}
elsif ($strOS eq VM_U16 || $strOS eq VM_D8)
{
return $strImage .
'RUN apt-get install -y libdbd-pg-perl libdbi-perl' .
($strOS eq VM_U16 ? ' libdevel-cover-perl libtest-pod-coverage-perl' : '');
$strImage .=
'RUN apt-get install -y libdbd-pg-perl libdbi-perl libhtml-parser-perl';
}
else
{
confess &log(ERROR, "unable to install perl for os '${strOS}'");
}
confess &log(ERROR, "unable to install perl for os '${strOS}'");
return $strImage;
}
####################################################################################################################################
@@ -487,8 +521,12 @@ sub containerBuild
{
$strScript =
"# Install package build tools and package source\n" .
"RUN apt-get install -y devscripts build-essential lintian git libxml-checker-perl txt2man debhelper && \\\n" .
" git clone https://anonscm.debian.org/git/pkg-postgresql/pgbackrest.git /root/package-src\n";
"RUN apt-get install -y devscripts build-essential lintian git libxml-checker-perl txt2man debhelper" .
" libpod-coverage-perl libppi-html-perl libtemplate-perl libtest-differences-perl && \\\n" .
" git clone https://anonscm.debian.org/git/pkg-postgresql/pgbackrest.git /root/package-src && \\\n" .
" git clone https://anonscm.debian.org/git/pkg-perl/packages/libdevel-cover-perl.git" .
" /root/libdevel-cover-perl && \\\n" .
' cd /root/libdevel-cover-perl && git checkout debian/' . LIB_COVER_VERSION . ' && debuild -i -us -uc -b';
}
else
{
@@ -500,6 +538,20 @@ sub containerBuild
# Write the image
containerWrite($strTempPath, $strOS, 'Build', $strImageParent, $strImage, $strScript, $bVmForce, false);
# Copy Devel::Cover to host so it can be installed in other containers
if ($$oVm{$strOS}{&VM_OS_BASE} eq VM_OS_BASE_DEBIAN)
{
executeTest('docker rm -f test-build', {bSuppressError => true});
executeTest(
"docker run -itd -h test-build --name=test-build" .
" -v ${strTempPath}:${strTempPath} " . containerRepo() . ":${strOS}-build",
{bSuppressStdErr => true});
executeTest(
"docker exec -i test-build " .
"bash -c 'cp /root/" . LIB_COVER_PACKAGE . " ${strTempPath}/${strOS}-" . LIB_COVER_PACKAGE . "'");
executeTest('docker rm -f test-build');
}
# Db image
###########################################################################################################################
my @stryDbBuild;
@@ -588,6 +640,9 @@ sub containerBuild
# Install SSH key
$strScript = sshSetup($strOS, TEST_USER, TEST_GROUP, $$oVm{$strOS}{&VM_CONTROL_MASTER});
# Setup Devel::Cover
$strScript .= coverSetup($strOS);
# Write the image
containerWrite($strTempPath, $strOS, "${strTitle} Test", $strImageParent, $strImage, $strScript, $bVmForce, true, true);
}
@@ -600,6 +655,9 @@ sub containerBuild
# Install SSH key
$strScript = sshSetup($strOS, TEST_USER, TEST_GROUP, $$oVm{$strOS}{&VM_CONTROL_MASTER});
# Setup Devel::Cover
$strScript .= coverSetup($strOS);
# Write the image
containerWrite($strTempPath, $strOS, 'Db Synthetic Test', $strImageParent, $strImage, $strScript, $bVmForce, true, true);
@@ -627,6 +685,9 @@ sub containerBuild
# Setup sudo
$strScript .= "\n\n" . sudoSetup($strOS, TEST_GROUP);
# Setup Devel::Cover
$strScript .= coverSetup($strOS);
# Write the image
containerWrite($strTempPath, $strOS, 'Loop Test', $strImageParent, $strImage, $strScript, $bVmForce, true, true);
@@ -680,6 +741,9 @@ sub containerBuild
"\n\n# Make " . TEST_USER . " home dir readable\n" .
'RUN chmod g+r,g+x /home/' . TEST_USER;
# Setup Devel::Cover
$strScript .= coverSetup($strOS);
# Write the image
containerWrite($strTempPath, $strOS, "${strTitle} Test", $strImageParent, $strImage, $strScript, $bVmForce, true, true);
}

View File

@@ -14,41 +14,50 @@ use Exporter qw(import);
our @EXPORT = qw();
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
################################################################################################################################
# Test definition constants
################################################################################################################################
use constant TESTDEF_MODULE => 'module';
push @EXPORT, qw(TESTDEF_MODULE);
use constant TESTDEF_MODULE_NAME => 'name';
push @EXPORT, qw(TESTDEF_MODULE_NAME);
use constant TESTDEF_EXPECT => 'expect';
push @EXPORT, qw(TESTDEF_EXPECT);
use constant TESTDEF_NAME => 'name';
push @EXPORT, qw(TESTDEF_NAME);
use constant TESTDEF_TEST => 'test';
push @EXPORT, qw(TESTDEF_TEST);
use constant TESTDEF_TEST_ALL => 'all';
push @EXPORT, qw(TESTDEF_TEST_ALL);
use constant TESTDEF_TEST_COVERAGE => 'coverage';
push @EXPORT, qw(TESTDEF_TEST_COVERAGE);
use constant TESTDEF_TEST_INDIVIDUAL => 'individual';
push @EXPORT, qw(TESTDEF_TEST_INDIVIDUAL);
use constant TESTDEF_TEST_NAME => 'name';
push @EXPORT, qw(TESTDEF_TEST_NAME);
use constant TESTDEF_TEST_TOTAL => 'total';
push @EXPORT, qw(TESTDEF_TEST_TOTAL);
use constant TESTDEF_TEST_CONTAINER => 'container';
push @EXPORT, qw(TESTDEF_TEST_CONTAINER);
use constant TESTDEF_TEST_PROCESS => 'process';
push @EXPORT, qw(TESTDEF_TEST_PROCESS);
use constant TESTDEF_TEST_DB => 'db';
push @EXPORT, qw(TESTDEF_TEST_DB);
# Determines if the test will be run against multiple db versions
use constant TESTDEF_DB => 'db';
push @EXPORT, qw(TESTDEF_DB);
# Determines if the test will be run in a container or will create containers itself
use constant TESTDEF_CONTAINER => 'container';
push @EXPORT, qw(TESTDEF_CONTAINER);
# Determines coverage for the test
use constant TESTDEF_COVERAGE => 'coverage';
push @EXPORT, qw(TESTDEF_COVERAGE);
# Should expect log tests be run
use constant TESTDEF_EXPECT => 'expect';
push @EXPORT, qw(TESTDEF_EXPECT);
# Determines if each run in a test will be run in a new container
use constant TESTDEF_INDIVIDUAL => 'individual';
push @EXPORT, qw(TESTDEF_INDIVIDUAL);
# Determines if the test will be run with multiple processes
use constant TESTDEF_PROCESS => 'process';
push @EXPORT, qw(TESTDEF_PROCESS);
# Total runs in the test
use constant TESTDEF_TOTAL => 'total';
push @EXPORT, qw(TESTDEF_TOTAL);
# The test provides full coverage for the module
use constant TESTDEF_COVERAGE_FULL => true;
push @EXPORT, qw(TESTDEF_COVERAGE_FULL);
# The test provides partial coverage for the module
use constant TESTDEF_COVERAGE_PARTIAL => false;
push @EXPORT, qw(TESTDEF_COVERAGE_PARTIAL);
################################################################################################################################
# Code modules
################################################################################################################################
use constant TESTDEF_MODULE_FILE => 'File';
push @EXPORT, qw(TESTDEF_MODULE_FILE);
use constant TESTDEF_MODULE_FILE_COMMON => TESTDEF_MODULE_FILE . 'Common';
@@ -86,218 +95,211 @@ my $oTestDef =
[
# Help tests
{
&TESTDEF_MODULE_NAME => 'help',
&TESTDEF_TEST_CONTAINER => true,
&TESTDEF_NAME => 'help',
&TESTDEF_CONTAINER => true,
&TESTDEF_EXPECT => true,
&TESTDEF_TEST =>
[
{
&TESTDEF_TEST_NAME => 'help',
&TESTDEF_TEST_TOTAL => 1,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_NAME => 'help',
&TESTDEF_TOTAL => 1,
}
]
},
# Config tests
{
&TESTDEF_MODULE_NAME => 'config',
&TESTDEF_TEST_CONTAINER => true,
&TESTDEF_NAME => 'config',
&TESTDEF_CONTAINER => true,
&TESTDEF_TEST =>
[
{
&TESTDEF_TEST_NAME => 'unit',
&TESTDEF_TEST_TOTAL => 7,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_NAME => 'unit',
&TESTDEF_TOTAL => 7,
},
{
&TESTDEF_TEST_NAME => 'option',
&TESTDEF_TEST_TOTAL => 34,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_NAME => 'option',
&TESTDEF_TOTAL => 34,
},
{
&TESTDEF_TEST_NAME => 'config',
&TESTDEF_TEST_TOTAL => 25,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_NAME => 'config',
&TESTDEF_TOTAL => 25,
}
]
},
# File tests
{
&TESTDEF_MODULE_NAME => 'file',
&TESTDEF_TEST_CONTAINER => true,
&TESTDEF_NAME => 'file',
&TESTDEF_CONTAINER => true,
&TESTDEF_TEST_COVERAGE =>
&TESTDEF_COVERAGE =>
{
&TESTDEF_MODULE_FILE => TESTDEF_COVERAGE_FULL,
&TESTDEF_MODULE_FILE_COMMON => TESTDEF_COVERAGE_FULL,
&TESTDEF_MODULE_FILE => TESTDEF_COVERAGE_PARTIAL,
&TESTDEF_MODULE_FILE_COMMON => TESTDEF_COVERAGE_PARTIAL,
},
&TESTDEF_TEST =>
[
{
&TESTDEF_TEST_NAME => 'unit',
&TESTDEF_TEST_TOTAL => 1,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_NAME => 'unit',
&TESTDEF_TOTAL => 1,
},
{
&TESTDEF_TEST_NAME => 'owner',
&TESTDEF_TEST_TOTAL => 8,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_NAME => 'owner',
&TESTDEF_TOTAL => 8,
},
{
&TESTDEF_TEST_NAME => 'path-create',
&TESTDEF_TEST_TOTAL => 8,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_NAME => 'path-create',
&TESTDEF_TOTAL => 8,
},
{
&TESTDEF_TEST_NAME => 'move',
&TESTDEF_TEST_TOTAL => 24,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_NAME => 'move',
&TESTDEF_TOTAL => 24,
},
{
&TESTDEF_TEST_NAME => 'compress',
&TESTDEF_TEST_TOTAL => 4,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_NAME => 'compress',
&TESTDEF_TOTAL => 4,
},
{
&TESTDEF_TEST_NAME => 'wait',
&TESTDEF_TEST_TOTAL => 2,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_NAME => 'wait',
&TESTDEF_TOTAL => 2,
},
{
&TESTDEF_TEST_NAME => 'link',
&TESTDEF_TEST_TOTAL => 1,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_NAME => 'link',
&TESTDEF_TOTAL => 1,
},
{
&TESTDEF_TEST_NAME => 'stat',
&TESTDEF_TEST_TOTAL => 1,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_NAME => 'stat',
&TESTDEF_TOTAL => 1,
},
{
&TESTDEF_TEST_NAME => 'manifest',
&TESTDEF_TEST_TOTAL => 5,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_NAME => 'manifest',
&TESTDEF_TOTAL => 5,
},
{
&TESTDEF_TEST_NAME => 'list',
&TESTDEF_TEST_TOTAL => 72,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_NAME => 'list',
&TESTDEF_TOTAL => 72,
},
{
&TESTDEF_TEST_NAME => 'remove',
&TESTDEF_TEST_TOTAL => 32,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_NAME => 'remove',
&TESTDEF_TOTAL => 32,
},
{
&TESTDEF_TEST_NAME => 'hash',
&TESTDEF_TEST_TOTAL => 16,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_NAME => 'hash',
&TESTDEF_TOTAL => 16,
},
{
&TESTDEF_TEST_NAME => 'exists',
&TESTDEF_TEST_TOTAL => 6,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_NAME => 'exists',
&TESTDEF_TOTAL => 6,
},
{
&TESTDEF_TEST_NAME => 'copy',
&TESTDEF_TEST_TOTAL => 144,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_NAME => 'copy',
&TESTDEF_TOTAL => 144,
}
]
},
# Info tests
{
&TESTDEF_NAME => 'info',
&TESTDEF_CONTAINER => true,
&TESTDEF_TEST =>
[
{
&TESTDEF_NAME => 'unit',
&TESTDEF_TOTAL => 1,
&TESTDEF_COVERAGE =>
{
&TESTDEF_MODULE_INFO => TESTDEF_COVERAGE_PARTIAL,
},
},
]
},
# Stanza tests
{
&TESTDEF_MODULE_NAME => 'stanza',
&TESTDEF_TEST_CONTAINER => false,
&TESTDEF_EXPECT => true,
&TESTDEF_NAME => 'stanza',
&TESTDEF_TEST_COVERAGE =>
&TESTDEF_COVERAGE =>
{
&TESTDEF_MODULE_STANZA => TESTDEF_COVERAGE_FULL,
&TESTDEF_MODULE_STANZA => TESTDEF_COVERAGE_PARTIAL,
},
&TESTDEF_TEST =>
[
{
&TESTDEF_TEST_NAME => 'unit',
&TESTDEF_EXPECT => false,
&TESTDEF_TEST_TOTAL => 2,
&TESTDEF_NAME => 'unit',
&TESTDEF_TOTAL => 2,
&TESTDEF_CONTAINER => true,
},
{
&TESTDEF_TEST_NAME => 'create',
&TESTDEF_TEST_TOTAL => 2
&TESTDEF_NAME => 'create',
&TESTDEF_TOTAL => 2,
&TESTDEF_EXPECT => true,
},
{
&TESTDEF_TEST_NAME => 'upgrade',
&TESTDEF_TEST_TOTAL => 2
&TESTDEF_NAME => 'upgrade',
&TESTDEF_TOTAL => 2,
&TESTDEF_EXPECT => true,
},
]
},
# Archive tests
{
&TESTDEF_MODULE_NAME => 'archive',
&TESTDEF_TEST_CONTAINER => false,
&TESTDEF_EXPECT => true,
&TESTDEF_NAME => 'archive',
&TESTDEF_TEST =>
[
{
&TESTDEF_TEST_NAME => 'unit',
&TESTDEF_TEST_TOTAL => 4,
&TESTDEF_TEST_CONTAINER => true,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_EXPECT => false,
&TESTDEF_NAME => 'unit',
&TESTDEF_TOTAL => 4,
&TESTDEF_CONTAINER => true,
&TESTDEF_TEST_COVERAGE =>
&TESTDEF_COVERAGE =>
{
&TESTDEF_TEST_ALL =>
{
&TESTDEF_MODULE_ARCHIVE_COMMON => TESTDEF_COVERAGE_PARTIAL,
}
&TESTDEF_MODULE_ARCHIVE_COMMON => TESTDEF_COVERAGE_PARTIAL,
},
},
{
&TESTDEF_TEST_NAME => 'push-unit',
&TESTDEF_TEST_TOTAL => 7,
&TESTDEF_TEST_CONTAINER => true,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_EXPECT => false,
&TESTDEF_NAME => 'push-unit',
&TESTDEF_TOTAL => 7,
&TESTDEF_CONTAINER => true,
&TESTDEF_TEST_COVERAGE =>
&TESTDEF_COVERAGE =>
{
&TESTDEF_TEST_ALL =>
{
&TESTDEF_MODULE_ARCHIVE_PUSH => TESTDEF_COVERAGE_FULL,
&TESTDEF_MODULE_ARCHIVE_PUSH_ASYNC => TESTDEF_COVERAGE_FULL,
&TESTDEF_MODULE_ARCHIVE_PUSH_FILE => TESTDEF_COVERAGE_PARTIAL,
}
&TESTDEF_MODULE_ARCHIVE_PUSH => TESTDEF_COVERAGE_FULL,
&TESTDEF_MODULE_ARCHIVE_PUSH_ASYNC => TESTDEF_COVERAGE_FULL,
&TESTDEF_MODULE_ARCHIVE_PUSH_FILE => TESTDEF_COVERAGE_FULL,
},
},
{
&TESTDEF_TEST_NAME => 'push',
&TESTDEF_TEST_TOTAL => 8,
&TESTDEF_TEST_PROCESS => true,
&TESTDEF_NAME => 'push',
&TESTDEF_TOTAL => 8,
&TESTDEF_PROCESS => true,
&TESTDEF_INDIVIDUAL => true,
&TESTDEF_EXPECT => true,
},
{
&TESTDEF_TEST_NAME => 'stop',
&TESTDEF_TEST_TOTAL => 6
&TESTDEF_NAME => 'stop',
&TESTDEF_TOTAL => 6,
&TESTDEF_INDIVIDUAL => true,
&TESTDEF_EXPECT => true,
},
{
&TESTDEF_TEST_NAME => 'get',
&TESTDEF_TEST_TOTAL => 8
&TESTDEF_NAME => 'get',
&TESTDEF_TOTAL => 8,
&TESTDEF_INDIVIDUAL => true,
&TESTDEF_EXPECT => true,
},
]
},
# Backup tests
{
&TESTDEF_MODULE_NAME => 'backup',
&TESTDEF_TEST_CONTAINER => false,
&TESTDEF_EXPECT => false,
&TESTDEF_NAME => 'backup',
&TESTDEF_CONTAINER => true,
&TESTDEF_TEST_COVERAGE =>
&TESTDEF_COVERAGE =>
{
&TESTDEF_MODULE_BACKUP_COMMON => TESTDEF_COVERAGE_FULL,
},
@@ -305,79 +307,51 @@ my $oTestDef =
&TESTDEF_TEST =>
[
{
&TESTDEF_TEST_NAME => 'unit',
&TESTDEF_TEST_TOTAL => 3,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_NAME => 'unit',
&TESTDEF_TOTAL => 3,
},
{
&TESTDEF_TEST_NAME => 'info-unit',
&TESTDEF_TEST_TOTAL => 1,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_NAME => 'info-unit',
&TESTDEF_TOTAL => 1,
},
]
},
# Expire tests
{
&TESTDEF_MODULE_NAME => 'expire',
&TESTDEF_TEST_CONTAINER => false,
&TESTDEF_NAME => 'expire',
&TESTDEF_EXPECT => true,
&TESTDEF_INDIVIDUAL => true,
&TESTDEF_TEST_COVERAGE =>
&TESTDEF_COVERAGE =>
{
&TESTDEF_MODULE_EXPIRE => TESTDEF_COVERAGE_FULL,
&TESTDEF_MODULE_EXPIRE => TESTDEF_COVERAGE_PARTIAL,
},
&TESTDEF_TEST =>
[
{
&TESTDEF_TEST_NAME => 'expire',
&TESTDEF_TEST_TOTAL => 2,
},
]
},
# Info tests
{
&TESTDEF_MODULE_NAME => 'info',
&TESTDEF_TEST_CONTAINER => false,
&TESTDEF_EXPECT => true,
&TESTDEF_TEST =>
[
{
&TESTDEF_TEST_NAME => 'unit',
&TESTDEF_TEST_CONTAINER => true,
&TESTDEF_TEST_INDIVIDUAL => false,
&TESTDEF_EXPECT => false,
&TESTDEF_TEST_TOTAL => 1,
&TESTDEF_TEST_COVERAGE =>
{
&TESTDEF_TEST_ALL =>
{
&TESTDEF_MODULE_INFO => TESTDEF_COVERAGE_FULL,
}
},
&TESTDEF_NAME => 'expire',
&TESTDEF_TOTAL => 2,
},
]
},
# Full tests
{
&TESTDEF_MODULE_NAME => 'full',
&TESTDEF_TEST_CONTAINER => false,
&TESTDEF_NAME => 'full',
&TESTDEF_EXPECT => true,
&TESTDEF_INDIVIDUAL => true,
&TESTDEF_PROCESS => true,
&TESTDEF_TEST =>
[
{
&TESTDEF_TEST_NAME => 'synthetic',
&TESTDEF_TEST_TOTAL => 8,
&TESTDEF_TEST_PROCESS => true
&TESTDEF_NAME => 'synthetic',
&TESTDEF_TOTAL => 8,
},
{
&TESTDEF_TEST_NAME => 'real',
&TESTDEF_TEST_TOTAL => 11,
&TESTDEF_TEST_PROCESS => true,
&TESTDEF_TEST_DB => true
&TESTDEF_NAME => 'real',
&TESTDEF_TOTAL => 11,
&TESTDEF_DB => true,
}
]
},
@@ -385,55 +359,154 @@ my $oTestDef =
};
####################################################################################################################################
# testDefGet
# Process normalized data into a more queryable form
####################################################################################################################################
sub testDefGet
my $hTestDefHash; # An easier way to query hash version of the above
my @stryModule; # Ordered list of modules
my $hModuleTest; # Ordered list of tests for each module
my $hCoverageType; # Coverage type for each code module (full/partial)
my $hCoverageList; # Tests required for full code module coverage (if type full)
# Iterate each module
foreach my $hModule (@{$oTestDef->{&TESTDEF_MODULE}})
{
return $oTestDef;
}
# Push the module onto the ordered list
my $strModule = $hModule->{&TESTDEF_NAME};
push(@stryModule, $strModule);
push @EXPORT, qw(testDefGet);
####################################################################################################################################
# testDefModuleGet
####################################################################################################################################
sub testDefModuleGet
{
my $strModule = shift;
# Find the module
foreach my $hModule (@{$oTestDef->{&TESTDEF_MODULE}})
{
if ($hModule->{&TESTDEF_MODULE_NAME} eq $strModule)
{
return $hModule;
}
}
confess &log(ASSERT, "unable to find module ${strModule}");
}
push @EXPORT, qw(testDefModuleGet);
####################################################################################################################################
# testDefModuleTestGet
####################################################################################################################################
sub testDefModuleTestGet
{
my $hModule = shift;
my $strModuleTest = shift;
# Iterate each test
my @stryModuleTest;
foreach my $hModuleTest (@{$hModule->{&TESTDEF_TEST}})
{
if ($hModuleTest->{&TESTDEF_TEST_NAME} eq $strModuleTest)
# Push the test on the order list
my $strTest = $hModuleTest->{&TESTDEF_NAME};
push(@stryModuleTest, $strTest);
# Resolve variables that can be set in the module or the test
foreach my $strVar (
TESTDEF_CONTAINER, TESTDEF_EXPECT, TESTDEF_PROCESS, TESTDEF_DB, TESTDEF_INDIVIDUAL)
{
return $hModuleTest;
$hTestDefHash->{$strModule}{$strTest}{$strVar} = coalesce(
$hModuleTest->{$strVar}, coalesce($hModule->{$strVar}, false));
}
# Set test count
$hTestDefHash->{$strModule}{$strTest}{&TESTDEF_TOTAL} = $hModuleTest->{&TESTDEF_TOTAL};
# Concatenate coverage for modules and tests
foreach my $hCoverage ($hModule->{&TESTDEF_COVERAGE}, $hModuleTest->{&TESTDEF_COVERAGE})
{
foreach my $strCodeModule (sort(keys(%{$hCoverage})))
{
if (defined($hTestDefHash->{$strModule}{$strTest}{&TESTDEF_COVERAGE}{$strCodeModule}))
{
confess &log(ASSERT,
"${strCodeModule} is defined for coverage in both module ${strModule} and test ${strTest}");
}
$hTestDefHash->{$strModule}{$strTest}{&TESTDEF_COVERAGE}{$strCodeModule} = $hCoverage->{$strCodeModule};
# Build coverage type hash and make sure coverage type does not change
if (!defined($hCoverageType->{$strCodeModule}))
{
$hCoverageType->{$strCodeModule} = $hCoverage->{$strCodeModule};
}
elsif ($hCoverageType->{$strCodeModule} != $hCoverage->{$strCodeModule})
{
confess &log(ASSERT, "cannot mix full/partial coverage for ${strCodeModule}");
}
# Add to coverage list
push(@{$hCoverageList->{$strCodeModule}}, {strModule=> $strModule, strTest => $strTest});
}
}
}
confess &log(ASSERT, "unable to find module test ${strModuleTest}");
$hModuleTest->{$strModule} = \@stryModuleTest;
}
push @EXPORT, qw(testDefModuleTestGet);
####################################################################################################################################
# testDefModuleList
####################################################################################################################################
sub testDefModuleList
{
return @stryModule;
}
push @EXPORT, qw(testDefModuleList);
####################################################################################################################################
# testDefModule
####################################################################################################################################
sub testDefModule
{
my $strModule = shift;
if (!defined($hTestDefHash->{$strModule}))
{
confess &log(ASSERT, "unable to find module ${strModule}");
}
return $hTestDefHash->{$strModule};
}
push @EXPORT, qw(testDefModule);
####################################################################################################################################
# testDefModuleTestList
####################################################################################################################################
sub testDefModuleTestList
{
my $strModule = shift;
if (!defined($hModuleTest->{$strModule}))
{
confess &log(ASSERT, "unable to find module ${strModule}");
}
return @{$hModuleTest->{$strModule}};
}
push @EXPORT, qw(testDefModuleTestList);
####################################################################################################################################
# testDefModuleTest
####################################################################################################################################
sub testDefModuleTest
{
my $strModule = shift;
my $strModuleTest = shift;
if (!defined($hTestDefHash->{$strModule}{$strModuleTest}))
{
confess &log(ASSERT, "unable to find module ${strModule}, test ${strModuleTest}");
}
return $hTestDefHash->{$strModule}{$strModuleTest};
}
push @EXPORT, qw(testDefModuleTest);
####################################################################################################################################
# testDefCoverageType
####################################################################################################################################
sub testDefCoverageType
{
return $hCoverageType;
}
push @EXPORT, qw(testDefCoverageType);
####################################################################################################################################
# testDefCoverageList
####################################################################################################################################
sub testDefCoverageList
{
return $hCoverageList;
}
push @EXPORT, qw(testDefCoverageList);
1;

View File

@@ -28,6 +28,7 @@ use pgBackRestTest::Common::ContainerTest;
use pgBackRestTest::Common::ExecuteTest;
use pgBackRestTest::Common::ListTest;
use pgBackRestTest::Common::RunTest;
use pgBackRestTest::Common::VmTest;
####################################################################################################################################
# new
@@ -56,7 +57,6 @@ sub new
$self->{strLogLevel},
$self->{bLogForce},
$self->{bShowOutputAsync},
$self->{bCoverage},
$self->{bNoCleanup},
$self->{iRetry},
) =
@@ -76,7 +76,6 @@ sub new
{name => 'strLogLevel'},
{name => 'bLogForce'},
{name => 'bShowOutputAsync'},
{name => 'bCoverage'},
{name => 'bNoCleanup'},
{name => 'iRetry'},
);
@@ -166,7 +165,7 @@ sub run
# Create command
my $strCommand =
($self->{oTest}->{&TEST_CONTAINER} ? 'docker exec -i -u ' . TEST_USER . " ${strImage} " : '') .
($self->{bCoverage} ? testRunExe(
(vmCoverage($self->{oTest}->{&TEST_VM}) ? testRunExe(
abs_path($0), dirname($self->{strCoveragePath}), $self->{strBackRestBase}, $self->{oTest}->{&TEST_MODULE},
$self->{oTest}->{&TEST_NAME}, defined($self->{oTest}->{&TEST_RUN}) ? $self->{oTest}->{&TEST_RUN} : 'all') :
abs_path($0)) .
@@ -180,7 +179,6 @@ sub run
(defined($self->{oTest}->{&TEST_PROCESS}) ? ' --process-max=' . $self->{oTest}->{&TEST_PROCESS} : '') .
($self->{strLogLevel} ne lc(INFO) ? " --log-level=$self->{strLogLevel}" : '') .
' --pgsql-bin=' . $self->{oTest}->{&TEST_PGSQL_BIN} .
($self->{bCoverage} ? ' --coverage' : '') .
($self->{bLogForce} ? ' --log-force' : '') .
($self->{bDryRun} ? ' --dry-run' : '') .
($self->{bDryRun} ? ' --vm-out' : '') .

View File

@@ -51,9 +51,8 @@ sub testListGet
my $iyModuleTestRun = shift;
my $strDbVersion = shift;
my $iProcessMax = shift;
my $bCoverage = shift;
my $bCoverageOnly = shift;
my $oTestDef = testDefGet();
my $oyVm = vmGet();
my $oyTestRun = [];
@@ -71,13 +70,17 @@ sub testListGet
foreach my $strTestOS (@stryTestOS)
{
foreach my $oModule (@{$$oTestDef{&TESTDEF_MODULE}})
foreach my $strModule (testDefModuleList())
{
if (@{$stryModule} == 0 || grep(/^$$oModule{&TESTDEF_MODULE_NAME}$/i, @{$stryModule}))
my $hModule = testDefModule($strModule);
if (@{$stryModule} == 0 || grep(/^$strModule$/i, @{$stryModule}))
{
foreach my $oTest (@{$$oModule{test}})
foreach my $strModuleTest (testDefModuleTestList($strModule))
{
if (@{$stryModuleTest} == 0 || grep(/^$$oTest{&TESTDEF_TEST_NAME}$/i, @{$stryModuleTest}))
my $hTest = testDefModuleTest($strModule, $strModuleTest);
if (@{$stryModuleTest} == 0 || grep(/^$strModuleTest$/i, @{$stryModuleTest}))
{
my $iDbVersionMin = -1;
my $iDbVersionMax = -1;
@@ -91,7 +94,7 @@ sub testListGet
$strDbVersionKey = &VM_DB_MINIMAL;
}
if (defined($$oTest{&TESTDEF_TEST_DB}) && $$oTest{&TESTDEF_TEST_DB})
if (defined($hTest->{&TESTDEF_DB}) && $hTest->{&TESTDEF_DB})
{
$iDbVersionMin = 0;
$iDbVersionMax = @{$$oyVm{$strTestOS}{$strDbVersionKey}} - 1;
@@ -107,10 +110,10 @@ sub testListGet
{
# Individual tests will be each be run in a separate container. This is the default.
my $bTestIndividual =
!defined($$oTest{&TESTDEF_TEST_INDIVIDUAL}) || $$oTest{&TESTDEF_TEST_INDIVIDUAL} ? true : false;
!defined($hTest->{&TESTDEF_INDIVIDUAL}) || $hTest->{&TESTDEF_INDIVIDUAL} ? true : false;
my $iTestRunMin = $bTestIndividual ? 1 : -1;
my $iTestRunMax = $bTestIndividual ? $$oTest{&TESTDEF_TEST_TOTAL} : -1;
my $iTestRunMax = $bTestIndividual ? $hTest->{&TESTDEF_TOTAL} : -1;
for (my $iTestRunIdx = $iTestRunMin; $iTestRunIdx <= $iTestRunMax; $iTestRunIdx++)
{
@@ -119,16 +122,12 @@ sub testListGet
$bTestIndividual && @{$iyModuleTestRun} != 0 &&
!grep(/^$iTestRunIdx$/i, @{$iyModuleTestRun}));
# Skip this run if coverage is requested and this test does not provide coverage
next if (
$bCoverage &&
(($bTestIndividual && !defined($oTest->{&TESTDEF_TEST_COVERAGE}{$iTestRunIdx})) ||
(!$bTestIndividual && !defined($oTest->{&TESTDEF_TEST_COVERAGE}{&TESTDEF_TEST_ALL}))) &&
!defined($oModule->{&TESTDEF_TEST_COVERAGE}));
# Skip this run if only coverage tests are requested and this test does not provide coverage
next if ($bCoverageOnly && !defined($hTest->{&TESTDEF_COVERAGE}));
my $iyProcessMax = [defined($iProcessMax) ? $iProcessMax : 1];
if (defined($$oTest{&TESTDEF_TEST_PROCESS}) && $$oTest{&TESTDEF_TEST_PROCESS} &&
if (defined($hTest->{&TESTDEF_PROCESS}) && $hTest->{&TESTDEF_PROCESS} &&
!defined($iProcessMax) && $bFirstDbVersion)
{
$iyProcessMax = [1, 4];
@@ -153,12 +152,12 @@ sub testListGet
my $oTestRun =
{
&TEST_VM => $strTestOS,
&TEST_CONTAINER => defined($oTest->{&TESTDEF_TEST_CONTAINER}) ?
$oTest->{&TESTDEF_TEST_CONTAINER} : $oModule->{&TESTDEF_TEST_CONTAINER},
&TEST_CONTAINER => defined($hTest->{&TESTDEF_CONTAINER}) ?
$hTest->{&TESTDEF_CONTAINER} : $hModule->{&TESTDEF_CONTAINER},
&TEST_PGSQL_BIN => $strPgSqlBin,
&TEST_PERL_ARCH_PATH => $$oyVm{$strTestOS}{&VMDEF_PERL_ARCH_PATH},
&TEST_MODULE => $$oModule{&TESTDEF_MODULE_NAME},
&TEST_NAME => $$oTest{&TESTDEF_TEST_NAME},
&TEST_MODULE => $strModule,
&TEST_NAME => $strModuleTest,
&TEST_RUN =>
$iTestRunIdx == -1 ? (@{$iyModuleTestRun} == 0 ? undef : $iyModuleTestRun) :
[$iTestRunIdx],

View File

@@ -22,6 +22,7 @@ use pgBackRest::Common::Wait;
use pgBackRestTest::Common::DefineTest;
use pgBackRestTest::Common::ExecuteTest;
use pgBackRestTest::Common::LogTest;
use pgBackRestTest::Common::VmTest;
####################################################################################################################################
# Constant to use when bogus data is required
@@ -118,7 +119,6 @@ sub process
$self->{bDryRun},
$self->{bCleanup},
$self->{bLogForce},
$self->{bCoverage},
$self->{strPgUser},
$self->{strBackRestUser},
$self->{strGroup},
@@ -141,7 +141,6 @@ sub process
{name => 'bDryRun'},
{name => 'bCleanup'},
{name => 'bLogForce'},
{name => 'bCoverage'},
{name => 'strPgUser'},
{name => 'strBackRestUser'},
{name => 'strGroup'},
@@ -157,12 +156,11 @@ sub process
$self->cleanModule();
# Make sure the correct number of tests ran
my $hModule = testDefModuleGet($self->{strModule});
my $hModuleTest = testDefModuleTestGet($hModule, $self->{strModuleTest});
my $hModuleTest = testDefModuleTest($self->{strModule}, $self->{strModuleTest});
if ($hModuleTest->{&TESTDEF_TEST_TOTAL} != $self->runCurrent())
if ($hModuleTest->{&TESTDEF_TOTAL} != $self->runCurrent())
{
confess &log(ASSERT, "expected $hModuleTest->{&TESTDEF_TEST_TOTAL} tests to run but $self->{iRun} ran");
confess &log(ASSERT, "expected $hModuleTest->{&TESTDEF_TOTAL} tests to run but $self->{iRun} ran");
}
# Return from function and log return values if any
@@ -205,14 +203,7 @@ sub begin
# Else get the default expect setting
else
{
my $hModule = testDefModuleGet($self->{strModule});
my $hModuleTest = testDefModuleTestGet($hModule, $self->{strModuleTest});
$self->{bExpect} =
defined($hModuleTest->{&TESTDEF_EXPECT}) ?
($hModuleTest->{&TESTDEF_EXPECT} ? true : false) :
(defined($hModule->{&TESTDEF_EXPECT}) ?
($hModule->{&TESTDEF_EXPECT} ? true : false) :
false);
$self->{bExpect} = (testDefModuleTest($self->{strModule}, $self->{strModuleTest}))->{&TESTDEF_EXPECT};
}
# Increment the run counter;
@@ -494,33 +485,9 @@ sub testRunExe
my $bLog = shift;
# Limit Perl modules tested to what is defined in the test coverage (if it exists)
my $hTestCoverage = (testDefModuleTest($strModule, $strTest))->{&TESTDEF_COVERAGE};
my $strPerlModule;
my $strPerlModuleLog;
my $hTestCoverage;
my $hTestDef = testDefGet();
foreach my $hTestModule (@{$hTestDef->{&TESTDEF_MODULE}})
{
if ($hTestModule->{&TESTDEF_MODULE_NAME} eq $strModule)
{
$hTestCoverage = $hTestModule->{&TESTDEF_TEST_COVERAGE};
foreach my $hTest (@{$hTestModule->{&TESTDEF_TEST}})
{
if (defined($strTest) && $hTest->{&TESTDEF_TEST_NAME} eq $strTest)
{
$hTestCoverage =
defined($hTest->{&TESTDEF_TEST_COVERAGE}{$iRun}) ? $hTest->{&TESTDEF_TEST_COVERAGE}{$iRun} :
$hTest->{&TESTDEF_TEST_COVERAGE}{&TESTDEF_TEST_ALL};
if (!defined($hTestCoverage))
{
$hTestCoverage = $hTestModule->{&TESTDEF_TEST_COVERAGE};
}
}
}
}
}
if (defined($hTestCoverage))
{
@@ -535,9 +502,8 @@ sub testRunExe
if (defined($strPerlModule))
{
$strExe =
'perl -MDevel::Cover=-silent,1,-dir,' . $strCoveragePath . ',-subs_only,1' .
",-select${strPerlModule},+inc," . $strBackRestBasePath .
',-coverage,statement,branch,condition,path,subroutine' . " ${strExe}";
"perl -MDevel::Cover=-silent,1,-dir,${strCoveragePath},-select${strPerlModule},+inc,${strBackRestBasePath}" .
",-coverage,statement,branch,condition,path,subroutine ${strExe}";
if (defined($bLog) && $bLog)
{
@@ -559,7 +525,7 @@ sub backrestExe {return shift->{strBackRestExe}}
sub backrestExeOriginal {return shift->{strBackRestExeOriginal}}
sub backrestUser {return shift->{strBackRestUser}}
sub basePath {return shift->{strBasePath}}
sub coverage {return shift->{bCoverage}}
sub coverage {vmBaseTest(shift->{strVm}, VM_OS_BASE_DEBIAN)}
sub dataPath {return shift->basePath() . '/test/data'}
sub doCleanup {return shift->{bCleanup}}
sub doExpect {return shift->{bExpect}}

View File

@@ -275,4 +275,29 @@ sub vmGet
push @EXPORT, qw(vmGet);
####################################################################################################################################
# vmBaseTest
####################################################################################################################################
sub vmBaseTest
{
my $strVm = shift;
my $strDistroTest = shift;
return $oyVm->{$strVm}{&VM_OS_BASE} eq $strDistroTest ? true : false;
}
push @EXPORT, qw(vmBaseTest);
####################################################################################################################################
# vmCoverage
####################################################################################################################################
sub vmCoverage
{
my $strVm = shift;
return $strVm eq VM_ALL ? false : vmBaseTest($strVm, VM_OS_BASE_DEBIAN);
}
push @EXPORT, qw(vmCoverage);
1;

View File

@@ -17,6 +17,7 @@ $SIG{__DIE__} = sub { Carp::confess @_ };
use File::Basename qw(dirname);
use Getopt::Long qw(GetOptions);
use Cwd qw(abs_path cwd);
use JSON::PP;
use Pod::Usage qw(pod2usage);
use POSIX qw(ceil strftime);
use Time::HiRes qw(gettimeofday);
@@ -39,6 +40,7 @@ use BackRestDoc::Custom::DocCustomRelease;
use pgBackRestTest::Common::ContainerTest;
use pgBackRestTest::Common::CiTest;
use pgBackRestTest::Common::DefineTest;
use pgBackRestTest::Common::ExecuteTest;
use pgBackRestTest::Common::HostGroupTest;
use pgBackRestTest::Common::JobTest;
@@ -69,11 +71,11 @@ test.pl [options]
--log-force force overwrite of current test log files
--no-lint disable static source code analysis
--build-only compile the C library / packages and run tests only
--coverage perform coverage analysis
--coverage-only only run coverage tests (as a subset of selected tests)
--smart perform libc/package builds only when source timestamps have changed
--no-package do not build packages
--no-ci-config don't overwrite the current continuous integration config
--dev --no-lint --smart --no-package --vm-out --process-max=1 --retry=0 --ci-no-config
--dev --no-lint --smart --no-package --vm-out --process-max=1
Configuration Options:
--psql-bin path to the psql executables (e.g. /usr/lib/postgresql/9.3/bin/)
@@ -113,13 +115,13 @@ my $bHelp = false;
my $bQuiet = false;
my $strDbVersion = 'minimal';
my $bLogForce = false;
my $strVm = VM_ALL;
my $strVm;
my $strVmHost = VM_HOST_DEFAULT;
my $bVmBuild = false;
my $bVmForce = false;
my $bNoLint = false;
my $bBuildOnly = false;
my $bCoverage = false;
my $bCoverageOnly = false;
my $bSmart = false;
my $bNoPackage = false;
my $bNoCiConfig = false;
@@ -151,7 +153,7 @@ GetOptions ('q|quiet' => \$bQuiet,
'build-only' => \$bBuildOnly,
'no-package' => \$bNoPackage,
'no-ci-config' => \$bNoCiConfig,
'coverage' => \$bCoverage,
'coverage-only' => \$bCoverageOnly,
'smart' => \$bSmart,
'dev' => \$bDev,
'retry=s' => \$iRetry)
@@ -190,7 +192,6 @@ eval
$bNoLint = true;
$bSmart = true;
$bNoPackage = true;
$bNoCiConfig = true;
$bVmOut = true;
$iProcessMax = 1;
}
@@ -231,18 +232,27 @@ eval
$strTestPath = cwd() . '/test';
}
# Coverage can only be run with u16 containers due to version compatibility issues
if ($bCoverage)
if ($bCoverageOnly)
{
if ($strVm eq VM_ALL)
if (!defined($strVm))
{
&log(INFO, "Set --vm=${strVmHost} for coverage testing");
$strVm = $strVmHost;
}
elsif ($strVm ne $strVmHost)
elsif ($strVm eq VM_ALL)
{
confess &log(ERROR, "only --vm=${strVmHost} can be used for coverage testing");
confess &log(ERROR, "select a single Debian-based VM for coverage testing");
}
elsif (!vmCoverage($strVm))
{
confess &log(ERROR, "only Debian-based VMs can be used for coverage testing");
}
}
# If VM is not defined then set it to all
if (!defined($strVm))
{
$strVm = VM_ALL;
}
# Get the base backrest path
@@ -572,7 +582,7 @@ eval
# Determine which tests to run
#-----------------------------------------------------------------------------------------------------------------------
my $oyTestRun = testListGet(
$strVm, \@stryModule, \@stryModuleTest, \@iyModuleTestRun, $strDbVersion, $iProcessMax, $bCoverage);
$strVm, \@stryModule, \@stryModuleTest, \@iyModuleTestRun, $strDbVersion, $iProcessMax, $bCoverageOnly);
if (@{$oyTestRun} == 0)
{
@@ -650,8 +660,7 @@ eval
{
my $oJob = new pgBackRestTest::Common::JobTest(
$strBackRestBase, $strTestPath, $strCoveragePath, $$oyTestRun[$iTestIdx], $bDryRun, $bVmOut, $iVmIdx,
$iVmMax, $iTestIdx, $iTestMax, $strLogLevel, $bLogForce, $bShowOutputAsync, $bCoverage, $bNoCleanup,
$iRetry);
$iVmMax, $iTestIdx, $iTestMax, $strLogLevel, $bLogForce, $bShowOutputAsync, $bNoCleanup, $iRetry);
$iTestIdx++;
if ($oJob->run())
@@ -665,18 +674,133 @@ eval
}
while ($iVmTotal > 0);
# Write out coverage info
# Write out coverage info and test coverage
#-----------------------------------------------------------------------------------------------------------------------
if ($bCoverage)
my $iUncoveredCodeModuleTotal = 0;
if (vmCoverage($strVm) && !$bDryRun)
{
&log(INFO, 'Writing coverage report');
&log(INFO, 'writing coverage report');
executeTest("rm -rf ${strBackRestBase}/test/coverage");
executeTest("cp -rp ${strCoveragePath} ${strCoveragePath}_temp");
executeTest("cover -report json -outputdir ${strBackRestBase}/test/coverage ${strCoveragePath}_temp");
executeTest("rm -rf ${strCoveragePath}_temp");
executeTest("cp -rp ${strCoveragePath} ${strCoveragePath}_temp");
executeTest("cover -outputdir ${strBackRestBase}/test/coverage ${strCoveragePath}_temp");
executeTest("rm -rf ${strCoveragePath}_temp");
executeTest(
LIB_COVER_EXE . " -report json -outputdir ${strBackRestBase}/test/coverage ${strCoveragePath}_temp",
{bSuppressStdErr => true});
executeTest("sudo rm -rf ${strCoveragePath}_temp");
executeTest("sudo cp -rp ${strCoveragePath} ${strCoveragePath}_temp");
executeTest(
LIB_COVER_EXE . " -outputdir ${strBackRestBase}/test/coverage ${strCoveragePath}_temp",
{bSuppressStdErr => true});
executeTest("sudo rm -rf ${strCoveragePath}_temp");
# Determine which modules were covered (only check coverage if all tests were successful)
#-----------------------------------------------------------------------------------------------------------------------
if ($iTestFail == 0)
{
my $hModuleTest; # Everything that was run
# Build a hash of all modules, tests, and runs that were executed
foreach my $hTestRun (@{$oyTestRun})
{
# Get coverage for the module
my $strModule = $hTestRun->{&TEST_MODULE};
my $hModule = testDefModule($strModule);
# Get coverage for the test
my $strTest = $hTestRun->{&TEST_NAME};
my $hTest = testDefModuleTest($strModule, $strTest);
# If no tests are listed it means all of them were run
if (@{$hTestRun->{&TEST_RUN}} == 0)
{
$hModuleTest->{$strModule}{$strTest} = true;
}
}
# Load the results of coverage testing from JSON
my $oJSON = JSON::PP->new()->allow_nonref();
my $hCoverageResult = $oJSON->decode(fileStringRead("${strBackRestBase}/test/coverage/cover.json"));
# Now compare against code modules that should have full coverage
my $hCoverageList = testDefCoverageList();
my $hCoverageType = testDefCoverageType();
my $hCoverageActual;
foreach my $strCodeModule (sort(keys(%{$hCoverageList})))
{
if (@{$hCoverageList->{$strCodeModule}} > 0)
{
my $iCoverageTotal = 0;
foreach my $hTest (@{$hCoverageList->{$strCodeModule}})
{
if (!defined($hModuleTest->{$hTest->{strModule}}{$hTest->{strTest}}))
{
next;
}
$iCoverageTotal++;
}
if (@{$hCoverageList->{$strCodeModule}} == $iCoverageTotal)
{
$hCoverageActual->{$strCodeModule} = $hCoverageType->{$strCodeModule};
}
}
}
if (keys(%{$hCoverageActual}) > 0)
{
&log(INFO, 'test coverage for: ' . join(', ', sort(keys(%{$hCoverageActual}))));
}
else
{
&log(INFO, 'no code modules had all tests run required for coverage');
}
foreach my $strCodeModule (sort(keys(%{$hCoverageActual})))
{
# Get summary results (??? Need to fix this for coverage testing on bin/pgbackrest since .pm is required)
my $hCoverageResultAll =
$hCoverageResult->{'summary'}
{"${strBackRestBase}/lib/" . BACKREST_NAME . "/${strCodeModule}.pm"}{total};
if (!defined($hCoverageResultAll))
{
confess &log(ERROR, "unable to find coverage results for ${strCodeModule}");
}
# Check that all code has been covered
if ($hCoverageActual->{$strCodeModule} == TESTDEF_COVERAGE_FULL)
{
my $iUncoveredLines =
$hCoverageResultAll->{total} - $hCoverageResultAll->{covered} - $hCoverageResultAll->{uncoverable};
if ($iUncoveredLines != 0)
{
&log(ERROR, "code module ${strCodeModule} is not fully covered");
$iUncoveredCodeModuleTotal++;
}
}
# Else test how much partial coverage where was
else
{
my $iCoveragePercent = int(
($hCoverageResultAll->{covered} + $hCoverageResultAll->{uncoverable}) * 100 /
$hCoverageResultAll->{total});
if ($iCoveragePercent == 100)
{
&log(ERROR, "code module ${strCodeModule} has 100% coverage but is not marked fully covered");
$iUncoveredCodeModuleTotal++;
}
else
{
&log(INFO, "code module ${strCodeModule} has (expected) partial coverage of ${iCoveragePercent}%");
}
}
}
}
}
# Print test info and exit
@@ -687,12 +811,16 @@ eval
}
else
{
&log(INFO, 'TESTS COMPLETED ' . ($iTestFail == 0 ? 'SUCCESSFULLY' : "WITH ${iTestFail} FAILURE(S)") .
($iTestRetry == 0 ? '' : ", ${iTestRetry} RETRY(IES)") .
' (' . (time() - $lStartTime) . 's)');
&log(INFO,
'TESTS COMPLETED ' . ($iTestFail == 0 ? 'SUCCESSFULLY' .
($iUncoveredCodeModuleTotal == 0 ? '' : " WITH ${iUncoveredCodeModuleTotal} MODULE(S) MISSING COVERAGE") :
"WITH ${iTestFail} FAILURE(S)") . ($iTestRetry == 0 ? '' : ", ${iTestRetry} RETRY(IES)") .
' (' . (time() - $lStartTime) . 's)');
exit 1 if ($iTestFail > 0 || $iUncoveredCodeModuleTotal > 0);
}
exit $iTestFail == 0 ? 0 : 1;
exit 0;
}
################################################################################################################################
@@ -713,7 +841,6 @@ eval
$strDbVersion ne 'minimal' ? $strDbVersion: undef, # Db version
$stryModule[0], $stryModuleTest[0], \@iyModuleTestRun, # Module info
$iProcessMax, $bVmOut, $bDryRun, $bNoCleanup, $bLogForce, # Test options
$bCoverage, # Test options
TEST_USER, BACKREST_USER, TEST_GROUP); # User/group info
if (!$bNoCleanup)