1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2026-05-22 10:15:16 +02:00

Test harness improvements.

* Allow more than one test to provide coverage for the same module.
* Add option to disable valgrind.
* Add option to disabled coverage.
* Add option to disable debug build.
* Add option to disable compiler optimization.
* Add --dev-test mode.
This commit is contained in:
David Steele
2018-05-18 06:45:14 -04:00
parent bce3d0fe1c
commit abb9651f4c
5 changed files with 139 additions and 31 deletions
+4
View File
@@ -33,6 +33,10 @@
<release-test-list> <release-test-list>
<release-development-list> <release-development-list>
<release-item>
<p>Test harness improvements. Allow more than one test to provide coverage for the same module. Add option to disable valgrind. Add option to disabled coverage. Add option to disable debug build. Add option to disable compiler optimization. Add <id>--dev-test</id> mode.</p>
</release-item>
<release-item> <release-item>
<p>Update SSL error message test on CentOS 7.</p> <p>Update SSL error message test on CentOS 7.</p>
</release-item> </release-item>
+1 -1
View File
@@ -1,6 +1,6 @@
test
.vagrant .vagrant
nytprof* nytprof*
scratch.txt scratch.txt
coverage* coverage*
ubuntu-xenial-16.04-cloudimg-console.log ubuntu-xenial-16.04-cloudimg-console.log
profile
+54 -24
View File
@@ -66,6 +66,11 @@ sub new
$self->{bShowOutputAsync}, $self->{bShowOutputAsync},
$self->{bNoCleanup}, $self->{bNoCleanup},
$self->{iRetry}, $self->{iRetry},
$self->{bValgrindUnit},
$self->{bCoverageUnit},
$self->{bOptimize},
$self->{bProfile},
$self->{bDebug},
) = ) =
logDebugParam logDebugParam
( (
@@ -86,6 +91,11 @@ sub new
{name => 'bShowOutputAsync'}, {name => 'bShowOutputAsync'},
{name => 'bNoCleanup'}, {name => 'bNoCleanup'},
{name => 'iRetry'}, {name => 'iRetry'},
{name => 'bValgrindUnit'},
{name => 'bCoverageUnit'},
{name => 'bOptimize'},
{name => 'bProfile'},
{name => 'bDebug'},
); );
# Set try to 0 # Set try to 0
@@ -179,16 +189,16 @@ sub run
# If testing C code copy source files to the test directory # If testing C code copy source files to the test directory
if ($self->{oTest}->{&TEST_C}) if ($self->{oTest}->{&TEST_C})
{ {
if (!$bGCovExists) # If any of the build flags have changed then we'll need to rebuild from scratch
{ my $bFlagsChanged =
executeTest("cp -r $self->{strBackRestBase}/src/* $self->{strGCovPath}"); defined($rhBuildFlags->{$self->{iVmIdx}}) != defined($self->{oTest}->{&TEST_CDEF}) ||
}
if (!$bGCovExists || defined($rhBuildFlags->{$self->{iVmIdx}}) != defined($self->{oTest}->{&TEST_CDEF}) ||
defined($rhBuildFlags->{$self->{iVmIdx}}) && defined($rhBuildFlags->{$self->{iVmIdx}}) &&
$rhBuildFlags->{$self->{iVmIdx}} ne $self->{oTest}->{&TEST_CDEF}) $rhBuildFlags->{$self->{iVmIdx}} ne $self->{oTest}->{&TEST_CDEF};
if (!$bGCovExists || $bFlagsChanged)
{ {
executeTest("cp -r $self->{strBackRestBase}/test/src/* $self->{strGCovPath}"); executeTest("rsync -rt --delete $self->{strBackRestBase}/src/ $self->{strGCovPath}");
executeTest("rsync -rt $self->{strBackRestBase}/test/src/ $self->{strGCovPath}");
} }
$rhBuildFlags->{$self->{iVmIdx}} = $self->{oTest}->{&TEST_CDEF}; $rhBuildFlags->{$self->{iVmIdx}} = $self->{oTest}->{&TEST_CDEF};
@@ -246,8 +256,6 @@ sub run
($self->{bNoCleanup} ? " --no-cleanup" : ''); ($self->{bNoCleanup} ? " --no-cleanup" : '');
} }
&log(DETAIL, $strCommand);
if (!$self->{bDryRun} || $self->{bVmOut}) if (!$self->{bDryRun} || $self->{bVmOut})
{ {
# If testing C code # If testing C code
@@ -341,7 +349,7 @@ sub run
# Build the Makefile # Build the Makefile
my $strMakefile = my $strMakefile =
"CC=gcc\n" . "CC=gcc\n" .
"CFLAGS=-I. -std=c99 -fPIC -g \\\n" . "CFLAGS=-I. -std=c99 -fPIC -g" . ($self->{bProfile} ? " -pg" : '') . "\\\n" .
" -Werror -Wfatal-errors -Wall -Wextra -Wwrite-strings -Wno-clobbered -Wswitch-enum -Wconversion \\\n" . " -Werror -Wfatal-errors -Wall -Wextra -Wwrite-strings -Wno-clobbered -Wswitch-enum -Wconversion \\\n" .
($self->{oTest}->{&TEST_VM} eq VM_U16 ? " -Wformat-signedness \\\n" : '') . ($self->{oTest}->{&TEST_VM} eq VM_U16 ? " -Wformat-signedness \\\n" : '') .
# This warning appears to be broken on U12 even though the functionality is fine # This warning appears to be broken on U12 even though the functionality is fine
@@ -351,24 +359,26 @@ sub run
" -Wpedantic \\\n" : '') . " -Wpedantic \\\n" : '') .
" -Wformat=2 -Wformat-nonliteral \\\n" . " -Wformat=2 -Wformat-nonliteral \\\n" .
" `perl -MExtUtils::Embed -e ccopts`\n" . " `perl -MExtUtils::Embed -e ccopts`\n" .
"LDFLAGS=-lcrypto" . (vmCoverage($self->{oTest}->{&TEST_VM}) ? " -lgcov" : '') . "LDFLAGS=-lcrypto" . (vmCoverage($self->{oTest}->{&TEST_VM}) && $self->{bCoverageUnit} ? " -lgcov" : '') .
" `perl -MExtUtils::Embed -e ldopts`\n" . " `perl -MExtUtils::Embed -e ldopts`\n" .
'TESTFLAGS=' . ($self->{oTest}->{&TEST_DEBUG_UNIT_SUPPRESS} ? '' : "-DDEBUG_UNIT ") . 'TESTFLAGS=' . ($self->{oTest}->{&TEST_DEBUG_UNIT_SUPPRESS} ? '' : "-DDEBUG_UNIT") .
($self->{oTest}->{&TEST_CDEF} ? "$self->{oTest}->{&TEST_CDEF}" : '') . ($self->{oTest}->{&TEST_CDEF} ? " $self->{oTest}->{&TEST_CDEF}" : '') .
($self->{bDebug} ? '' : " -DNDEBUG") .
"\n" . "\n" .
"\nSRCS=" . join(' ', @stryCFile) . "\n" . "\nSRCS=" . join(' ', @stryCFile) . "\n" .
"OBJS=\$(SRCS:.c=.o)\n" . "OBJS=\$(SRCS:.c=.o)\n" .
"\n" . "\n" .
"test: \$(OBJS) test.o\n" . "test: \$(OBJS) test.o\n" .
"\t\$(CC) -o test \$(OBJS) test.o \$(LDFLAGS)\n" . "\t\$(CC) -o test \$(OBJS) test.o" . ($self->{bProfile} ? " -pg" : '') . " \$(LDFLAGS)\n" .
"\n" . "\n" .
"test.o: test.c\n" . "test.o: test.c\n" .
"\t\$(CC) \$(CFLAGS) \$(TESTFLAGS) " . "\t\$(CC) \$(CFLAGS) \$(TESTFLAGS) -O0" .
(vmCoverage($self->{oTest}->{&TEST_VM}) ? '-fprofile-arcs -ftest-coverage -O0' : '-O2') . (vmCoverage($self->{oTest}->{&TEST_VM}) && $self->{bCoverageUnit} ?
' -fprofile-arcs -ftest-coverage' : '') .
" -c test.c\n" . " -c test.c\n" .
"\n" . "\n" .
".c.o:\n" . ".c.o:\n" .
"\t\$(CC) \$(CFLAGS) \$(TESTFLAGS) -O2 -c \$< -o \$@\n"; "\t\$(CC) \$(CFLAGS) \$(TESTFLAGS) " . ($self->{bOptimize} ? '-O2' : '-O0') . " -c \$< -o \$@\n";
$self->{oStorageTest}->put($self->{strGCovPath} . "/Makefile", $strMakefile); $self->{oStorageTest}->put($self->{strGCovPath} . "/Makefile", $strMakefile);
} }
@@ -426,8 +436,20 @@ sub end
syswrite(*STDOUT, "\n"); syswrite(*STDOUT, "\n");
} }
# If C library generate coverage info # If C code generate profile info
if ($iExitStatus == 0 && $self->{oTest}->{&TEST_C} && vmCoverage($self->{oTest}->{&TEST_VM})) if ($iExitStatus == 0 && $self->{oTest}->{&TEST_C} && $self->{bProfile})
{
executeTest(
'docker exec -i -u ' . TEST_USER . " ${strImage} " .
"gprof --flat-profile $self->{strGCovPath}/test $self->{strGCovPath}/gmon.out > $self->{strGCovPath}/gprof.flat.txt");
$self->{oStorageTest}->pathCreate("$self->{strBackRestBase}/test/profile", {strMode => '0750', bIgnoreExists => true});
$self->{oStorageTest}->copy(
"$self->{strGCovPath}/gprof.flat.txt", "$self->{strBackRestBase}/test/profile/gprof.flat.txt");
}
# If C code generate coverage info
if ($iExitStatus == 0 && $self->{oTest}->{&TEST_C} && vmCoverage($self->{oTest}->{&TEST_VM}) && $self->{bCoverageUnit})
{ {
# Generate a list of files to cover # Generate a list of files to cover
my $hTestCoverage = my $hTestCoverage =
@@ -447,6 +469,7 @@ sub end
# Generate coverage reports for the modules # Generate coverage reports for the modules
my $strLCovExe = "lcov --config-file=$self->{strBackRestBase}/test/src/lcov.conf"; my $strLCovExe = "lcov --config-file=$self->{strBackRestBase}/test/src/lcov.conf";
my $strLCovOut = $self->{strGCovPath} . '/test.lcov'; my $strLCovOut = $self->{strGCovPath} . '/test.lcov';
my $strLCovOutTmp = $self->{strGCovPath} . '/test.tmp.lcov';
executeTest( executeTest(
'docker exec -i -u ' . TEST_USER . " ${strImage} " . 'docker exec -i -u ' . TEST_USER . " ${strImage} " .
@@ -472,10 +495,18 @@ sub end
executeTest( executeTest(
'docker exec -i -u ' . TEST_USER . " ${strImage} " . 'docker exec -i -u ' . TEST_USER . " ${strImage} " .
"${strLCovExe} --extract=${strLCovOut} */${strModuleName}.c --o=${strLCovFile}"); "${strLCovExe} --extract=${strLCovOut} */${strModuleName}.c --o=${strLCovOutTmp}");
# Combine with prior run if there was one
if ($self->{oStorageTest}->exists($strLCovFile))
{
executeTest(
'docker exec -i -u ' . TEST_USER . " ${strImage} " .
"${strLCovExe} --add-tracefile=${strLCovOutTmp} --add-tracefile=${strLCovFile} --o=${strLCovOutTmp}");
}
# Update source file # Update source file
my $strCoverage = ${$self->{oStorageTest}->get($strLCovFile)}; my $strCoverage = ${$self->{oStorageTest}->get($strLCovOutTmp)};
if (defined($strCoverage)) if (defined($strCoverage))
{ {
@@ -506,10 +537,9 @@ sub end
# Fix source file name # Fix source file name
$strCoverage =~ s/^SF\:.*$/SF:$strModulePath\.c/mg; $strCoverage =~ s/^SF\:.*$/SF:$strModulePath\.c/mg;
# Save coverage file
$self->{oStorageTest}->put($strLCovFile, $strCoverage); $self->{oStorageTest}->put($strLCovFile, $strCoverage);
if ($self->{oStorageTest}->exists(${strLCovTotal})) if ($self->{oStorageTest}->exists($strLCovTotal))
{ {
executeTest( executeTest(
'docker exec -i -u ' . TEST_USER . " ${strImage} " . 'docker exec -i -u ' . TEST_USER . " ${strImage} " .
+32
View File
@@ -25,6 +25,8 @@ use constant VM_DB => 'db';
push @EXPORT, qw(VM_DB); push @EXPORT, qw(VM_DB);
use constant VM_DB_TEST => 'db-test'; use constant VM_DB_TEST => 'db-test';
push @EXPORT, qw(VM_DB_TEST); push @EXPORT, qw(VM_DB_TEST);
use constant VMDEF_DEBUG_INTEGRATION => 'debug-integration';
push @EXPORT, qw(VMDEF_DEBUG_INTEGRATION);
use constant VM_CONTROL_MASTER => 'control-master'; use constant VM_CONTROL_MASTER => 'control-master';
push @EXPORT, qw(VM_CONTROL_MASTER); push @EXPORT, qw(VM_CONTROL_MASTER);
use constant VM_DEPRECATED => 'deprecated'; use constant VM_DEPRECATED => 'deprecated';
@@ -41,6 +43,8 @@ use constant VMDEF_PGSQL_BIN => 'pgsql-bi
push @EXPORT, qw(VMDEF_PGSQL_BIN); push @EXPORT, qw(VMDEF_PGSQL_BIN);
use constant VMDEF_PERL_ARCH_PATH => 'perl-arch-path'; use constant VMDEF_PERL_ARCH_PATH => 'perl-arch-path';
push @EXPORT, qw(VMDEF_PERL_ARCH_PATH); push @EXPORT, qw(VMDEF_PERL_ARCH_PATH);
use constant VMDEF_WITH_BACKTRACE => 'with-backtrace';
push @EXPORT, qw(VMDEF_WITH_BACKTRACE);
#################################################################################################################################### ####################################################################################################################################
# Valid OS base List # Valid OS base List
@@ -142,6 +146,8 @@ my $oyVm =
&VMDEF_PGSQL_BIN => '/usr/pgsql-{[version]}/bin', &VMDEF_PGSQL_BIN => '/usr/pgsql-{[version]}/bin',
&VMDEF_PERL_ARCH_PATH => '/usr/local/lib64/perl5', &VMDEF_PERL_ARCH_PATH => '/usr/local/lib64/perl5',
&VMDEF_DEBUG_INTEGRATION => false,
&VM_DB => &VM_DB =>
[ [
PG_VERSION_96, PG_VERSION_96,
@@ -230,6 +236,8 @@ my $oyVm =
&VMDEF_PGSQL_BIN => '/usr/lib/postgresql/{[version]}/bin', &VMDEF_PGSQL_BIN => '/usr/lib/postgresql/{[version]}/bin',
&VMDEF_PERL_ARCH_PATH => '/usr/local/lib/x86_64-linux-gnu/perl/5.22.1', &VMDEF_PERL_ARCH_PATH => '/usr/local/lib/x86_64-linux-gnu/perl/5.22.1',
&VMDEF_WITH_BACKTRACE => true,
&VM_DB => &VM_DB =>
[ [
PG_VERSION_94, PG_VERSION_94,
@@ -345,4 +353,28 @@ sub vmArchBits
push @EXPORT, qw(vmArchBits); push @EXPORT, qw(vmArchBits);
####################################################################################################################################
# Does the VM support libbacktrace?
####################################################################################################################################
sub vmWithBackTrace
{
my $strVm = shift;
return ($oyVm->{$strVm}{&VMDEF_WITH_BACKTRACE} ? true : false);
}
push @EXPORT, qw(vmWithBackTrace);
####################################################################################################################################
# Will integration tests be run in debug mode?
####################################################################################################################################
sub vmDebugIntegration
{
my $strVm = shift;
return (defined($oyVm->{$strVm}{&VMDEF_DEBUG_INTEGRATION}) ? $oyVm->{$strVm}{&VMDEF_DEBUG_INTEGRATION} : true);
}
push @EXPORT, qw(vmDebugIntegration);
1; 1;
+48 -6
View File
@@ -86,8 +86,14 @@ test.pl [options]
--smart perform libc/package builds only when source timestamps have changed --smart perform libc/package builds only when source timestamps have changed
--no-package do not build packages --no-package do not build packages
--no-ci-config don't overwrite the current continuous integration config --no-ci-config don't overwrite the current continuous integration config
--dev --no-lint --smart --no-package --dev --no-lint --smart --no-package --no-optimize
--expect --no-lint --smart --no-package --vm=co7 --db=9.6 --log-force --dev-test --no-lint --no-package
--expect --no-lint --no-package --vm=co7 --db=9.6 --log-force
--no-valgrind don't run valgrind on C unit tests (saves time)
--no-coverage don't run coverage on C unit tests (saves time)
--no-optimize don't do compile optimization for C (saves compile time)
--profile generate profile info
--no-debug don't generate a debug build
Configuration Options: Configuration Options:
--psql-bin path to the psql executables (e.g. /usr/lib/postgresql/9.3/bin/) --psql-bin path to the psql executables (e.g. /usr/lib/postgresql/9.3/bin/)
@@ -133,6 +139,7 @@ my $bVmForce = false;
my $bNoLint = false; my $bNoLint = false;
my $bBuildOnly = false; my $bBuildOnly = false;
my $bCoverageOnly = false; my $bCoverageOnly = false;
my $bNoCoverage = false;
my $bCOnly = false; my $bCOnly = false;
my $bGenOnly = false; my $bGenOnly = false;
my $bCodeCount = false; my $bCodeCount = false;
@@ -140,7 +147,12 @@ my $bSmart = false;
my $bNoPackage = false; my $bNoPackage = false;
my $bNoCiConfig = false; my $bNoCiConfig = false;
my $bDev = false; my $bDev = false;
my $bDevTest = false;
my $bProfile = false;
my $bExpect = false; my $bExpect = false;
my $bNoValgrind = false;
my $bNoOptimize = false;
my $bNoDebug = false;
my $iRetry = 0; my $iRetry = 0;
GetOptions ('q|quiet' => \$bQuiet, GetOptions ('q|quiet' => \$bQuiet,
@@ -168,12 +180,18 @@ GetOptions ('q|quiet' => \$bQuiet,
'no-package' => \$bNoPackage, 'no-package' => \$bNoPackage,
'no-ci-config' => \$bNoCiConfig, 'no-ci-config' => \$bNoCiConfig,
'coverage-only' => \$bCoverageOnly, 'coverage-only' => \$bCoverageOnly,
'no-coverage' => \$bNoCoverage,
'c-only' => \$bCOnly, 'c-only' => \$bCOnly,
'gen-only' => \$bGenOnly, 'gen-only' => \$bGenOnly,
'code-count' => \$bCodeCount, 'code-count' => \$bCodeCount,
'smart' => \$bSmart, 'smart' => \$bSmart,
'dev' => \$bDev, 'dev' => \$bDev,
'dev-test' => \$bDevTest,
'profile' => \$bProfile,
'expect' => \$bExpect, 'expect' => \$bExpect,
'no-valgrind' => \$bNoValgrind,
'no-optimize' => \$bNoOptimize,
'no-debug', => \$bNoDebug,
'retry=s' => \$iRetry) 'retry=s' => \$iRetry)
or pod2usage(2); or pod2usage(2);
@@ -206,13 +224,34 @@ eval
} }
################################################################################################################################ ################################################################################################################################
# Update options for --dev # Update options for --dev and --dev-fast and --dev-test
################################################################################################################################ ################################################################################################################################
if ($bDev && $bDevTest)
{
confess "cannot combine --dev and --dev-test";
}
if ($bDev) if ($bDev)
{ {
$bNoLint = true; $bNoLint = true;
$bSmart = true; $bSmart = true;
$bNoPackage = true; $bNoPackage = true;
$bNoOptimize = true;
}
if ($bDevTest)
{
$bNoPackage = true;
$bNoLint = true;
}
################################################################################################################################
# Update options for --profile
################################################################################################################################
if ($bProfile)
{
$bNoValgrind = true;
$bNoCoverage = true;
} }
################################################################################################################################ ################################################################################################################################
@@ -588,10 +627,12 @@ eval
&log(INFO, " clang static analyzer ${strBuildVM} (${strBuildPath})"); &log(INFO, " clang static analyzer ${strBuildVM} (${strBuildPath})");
} }
my $strCDebug = vmDebugIntegration($strVm) ? 'CDEBUG=' : '';
executeTest( executeTest(
'docker exec -i test-build' . 'docker exec -i test-build' .
(vmCoverage($strVm) && !$bNoLint ? ' scan-build-5.0' : '') . (vmCoverage($strVm) && !$bNoLint ? ' scan-build-5.0' : '') .
" make --silent --directory ${strBuildPath} CEXTRA=-g CDEBUG=", " make --silent --directory ${strBuildPath} CEXTRA=-g ${strCDebug}",
{bShowOutputAsync => $bLogDetail}); {bShowOutputAsync => $bLogDetail});
executeTest( executeTest(
@@ -1019,7 +1060,8 @@ eval
{ {
my $oJob = new pgBackRestTest::Common::JobTest( my $oJob = new pgBackRestTest::Common::JobTest(
$oStorageTest, $strBackRestBase, $strTestPath, $strCoveragePath, $$oyTestRun[$iTestIdx], $bDryRun, $bVmOut, $oStorageTest, $strBackRestBase, $strTestPath, $strCoveragePath, $$oyTestRun[$iTestIdx], $bDryRun, $bVmOut,
$iVmIdx, $iVmMax, $iTestIdx, $iTestMax, $strLogLevel, $bLogForce, $bShowOutputAsync, $bNoCleanup, $iRetry); $iVmIdx, $iVmMax, $iTestIdx, $iTestMax, $strLogLevel, $bLogForce, $bShowOutputAsync, $bNoCleanup, $iRetry,
!$bNoValgrind, !$bNoCoverage, !$bNoOptimize, $bProfile, !$bNoDebug);
$iTestIdx++; $iTestIdx++;
if ($oJob->run()) if ($oJob->run())
@@ -1037,7 +1079,7 @@ eval
#--------------------------------------------------------------------------------------------------------------------------- #---------------------------------------------------------------------------------------------------------------------------
my $iUncoveredCodeModuleTotal = 0; my $iUncoveredCodeModuleTotal = 0;
if (vmCoverage($strVm) && !$bDryRun) if (vmCoverage($strVm) && !$bNoCoverage && !$bDryRun)
{ {
&log(INFO, 'writing coverage report'); &log(INFO, 'writing coverage report');
executeTest("cp -rp ${strCoveragePath} ${strCoveragePath}_temp"); executeTest("cp -rp ${strCoveragePath} ${strCoveragePath}_temp");