mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-04 09:43:08 +02:00
Use configure to generate Makefile variables for unit tests.
The unit test Makefile generation was a hodge-podge of constants and rules based on distros/versions that easily got out of date and did not work on an unknown system. All of this dates from the mixed Perl/C unit test implementation. Instead use configure to generate most of the important Makefile variables, which allows the unit tests to run on multiple platforms, e.g. MacOS and FreeBSD. There is plenty of work to be done here and not all the unit tests work on MacOS and FreeBSD for various reasons. As a POC update the MacOS and FreeBSD tests on Cirrus-CI to run a few command unit tests.
This commit is contained in:
parent
ef2dc6d3f4
commit
4e8d469f4d
19
.cirrus.yml
19
.cirrus.yml
@ -12,17 +12,16 @@ auto_cancellation: $CIRRUS_BRANCH != 'integration'
|
||||
freebsd_12_task:
|
||||
freebsd_instance:
|
||||
image_family: freebsd-12-1
|
||||
cpu: 4
|
||||
memory: 4G
|
||||
|
||||
install_script: pkg install -y git postgresql-libpqxx pkgconf libxml2 gmake
|
||||
install_script: pkg install -y git postgresql-libpqxx pkgconf libxml2 gmake perl5 p5-YAML rsync
|
||||
|
||||
script:
|
||||
- cd ${CIRRUS_WORKING_DIR}/src && ./configure
|
||||
- gmake -s -C ${CIRRUS_WORKING_DIR}/src
|
||||
- ${CIRRUS_WORKING_DIR}/src/pgbackrest
|
||||
- perl ${CIRRUS_WORKING_DIR}/test/test.pl --no-gen --make-cmd=gmake --vm=none --vm-max=2 --no-coverage --no-valgrind --module=command --test=backup --test=archive-get --test=archive-push
|
||||
|
||||
debug_script:
|
||||
- ls -lah ${CIRRUS_WORKING_DIR}
|
||||
- cat ${CIRRUS_WORKING_DIR}/src/Makefile
|
||||
|
||||
# MacOS Catalina
|
||||
# ----------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -33,14 +32,14 @@ macos_catalina_task:
|
||||
environment:
|
||||
LDFLAGS: -L/usr/local/opt/openssl@1.1/lib -L/usr/local/opt/libpq/lib -L/usr/local/opt/libxml2/lib
|
||||
CPPFLAGS: -I/usr/local/opt/openssl@1.1/include -I/usr/local/opt/libpq/include -I/usr/local/opt/libxml2/include/libxml2
|
||||
PERL5LIB: /usr/local/opt/perl5/lib/perl5
|
||||
|
||||
install_script: brew install openssl@1.1 libpq libxml2
|
||||
install_script:
|
||||
- brew install -q openssl@1.1 libpq libxml2 cpanm
|
||||
- cpanm --local-lib=/usr/local/opt/perl5 install YAML
|
||||
|
||||
script:
|
||||
- cd ${CIRRUS_WORKING_DIR}/src && ./configure
|
||||
- make -s -C ${CIRRUS_WORKING_DIR}/src
|
||||
- ${CIRRUS_WORKING_DIR}/src/pgbackrest
|
||||
- ${CIRRUS_WORKING_DIR}/test/test.pl --no-gen --vm=none --vm-max=2 --no-coverage --no-valgrind --module=command --test=backup --test=archive-get --test=archive-push
|
||||
|
||||
debug_script:
|
||||
- ls -lah ${CIRRUS_WORKING_DIR}
|
||||
- cat ${CIRRUS_WORKING_DIR}/src/Makefile
|
||||
|
@ -175,9 +175,9 @@ SRCS = \
|
||||
# Compiler options
|
||||
####################################################################################################################################
|
||||
CC = @CC@
|
||||
CFLAGS = @CFLAGS@
|
||||
CFLAGS = $(CFLAGS_EXTRA) @CFLAGS@
|
||||
CPPFLAGS = @CPPFLAGS@ -I@srcdir@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LDFLAGS = $(LDFLAGS_EXTRA) @LDFLAGS@
|
||||
LIBS = @LIBS@
|
||||
|
||||
####################################################################################################################################
|
||||
|
14
test/Vagrantfile
vendored
14
test/Vagrantfile
vendored
@ -136,7 +136,7 @@ Vagrant.configure(2) do |config|
|
||||
#-----------------------------------------------------------------------------------------------------------------------
|
||||
echo 'Install Build Tools' && date
|
||||
|
||||
pkg install -y git postgresql-libpqxx pkgconf libxml2 gmake
|
||||
pkg install -y git postgresql-libpqxx pkgconf libxml2 gmake perl5 p5-YAML rsync
|
||||
|
||||
#-----------------------------------------------------------------------------------------------------------------------
|
||||
echo 'Build End' && date
|
||||
@ -145,16 +145,16 @@ Vagrant.configure(2) do |config|
|
||||
|
||||
# MacOS
|
||||
#
|
||||
# Basic environment to build pgBackRest using homebrew installed in the local user account.
|
||||
# Basic environment to build/test pgBackRest using homebrew installed in the local user account.
|
||||
#-------------------------------------------------------------------------------------------------------------------------------
|
||||
# cd ~
|
||||
# mkdir homebrew && curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C homebrew
|
||||
# homebrew/bin/brew install libpq libxml2
|
||||
# mkdir ~/homebrew && curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C ~/homebrew
|
||||
# ~/homebrew/bin/brew install -q libpq libxml2 cpanm
|
||||
# ~/homebrew/bin/cpanm --local-lib=~/homebrew/perl5 install YAML
|
||||
#
|
||||
# export LDFLAGS="-L${HOME?}/homebrew/opt/openssl@1.1/lib -L${HOME?}/homebrew/opt/libpq/lib -L${HOME?}/homebrew/opt/libxml2/lib"
|
||||
# export CPPFLAGS="-I${HOME?}/homebrew/opt/openssl@1.1/include -I/${HOME?}/homebrew/opt/libpq/include"
|
||||
# export CPPFLAGS="${CPPFLAGS?} -I${HOME?}/homebrew/opt/libxml2/include/libxml2"
|
||||
#
|
||||
# cd [repo]/src && ./configure && make
|
||||
# export PERL5LIB=~/homebrew/perl5/lib/perl5"${PERL5LIB:+:${PERL5LIB}}"
|
||||
|
||||
# Don't share the default vagrant folder
|
||||
config.vm.synced_folder ".", "/vagrant", disabled: true
|
||||
|
@ -97,195 +97,3 @@ sub buildLastModTime
|
||||
}
|
||||
|
||||
push @EXPORT, qw(buildLastModTime);
|
||||
|
||||
####################################################################################################################################
|
||||
# Build a dependency tree for C files
|
||||
####################################################################################################################################
|
||||
sub buildDependencyTree
|
||||
{
|
||||
my $oStorage = shift;
|
||||
|
||||
my $rhDependencyTree = {};
|
||||
|
||||
# Iterate all files
|
||||
foreach my $strFile (sort(keys(%{$oStorage->manifest('src')})))
|
||||
{
|
||||
# Only process non-auto files
|
||||
if ($strFile =~ /^[A-Za-z0-9\/]+\.(c|h)$/)
|
||||
{
|
||||
buildDependencyTreeSub($oStorage, $rhDependencyTree, $strFile, true, undef, ['src']);
|
||||
}
|
||||
}
|
||||
|
||||
return $rhDependencyTree;
|
||||
}
|
||||
|
||||
push @EXPORT, qw(buildDependencyTree);
|
||||
|
||||
sub buildDependencyTreeSub
|
||||
{
|
||||
my $oStorage = shift;
|
||||
my $rhDependencyTree = shift;
|
||||
my $strFile = shift;
|
||||
my $bErrorOnBuildHeaderMissing = shift;
|
||||
my $strBasePath = shift;
|
||||
my $rstryPath = shift;
|
||||
|
||||
if (!defined($rhDependencyTree->{$strFile}))
|
||||
{
|
||||
$rhDependencyTree->{$strFile} = {};
|
||||
|
||||
# Load file contents
|
||||
my $rstrContent;
|
||||
|
||||
foreach my $strPath (@{$rstryPath})
|
||||
{
|
||||
$rstrContent = $oStorage->get(
|
||||
$oStorage->openRead(
|
||||
(defined($strBasePath) ? "${strBasePath}/" : '') . ($strPath ne '' ? "${strPath}/" : '') . "${strFile}",
|
||||
{bIgnoreMissing => true}));
|
||||
|
||||
if (defined($rstrContent) || $strFile eq BUILD_AUTO_H)
|
||||
{
|
||||
$rhDependencyTree->{$strFile}{path} = $strPath;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
if ($strFile ne BUILD_AUTO_H)
|
||||
{
|
||||
if (!defined($rstrContent))
|
||||
{
|
||||
confess &log(ERROR,
|
||||
"unable to find ${strFile} in " . $oStorage->pathGet($strBasePath) . " + [" . join(', ', @{$rstryPath}) . "]");
|
||||
}
|
||||
|
||||
# Process includes
|
||||
my $rhInclude = {};
|
||||
my $first = true;
|
||||
|
||||
foreach my $strInclude ($$rstrContent =~ /^\s*\#include [\"\<].+[\"\>]\s*$/mg)
|
||||
{
|
||||
if ($bErrorOnBuildHeaderMissing && $first &&
|
||||
$strFile =~ /\.c/ && trim($strInclude) ne ('#include "' . BUILD_AUTO_H . '"'))
|
||||
{
|
||||
confess &log(ERROR, "'" . BUILD_AUTO_H . "' must be included first in '${strFile}'");
|
||||
}
|
||||
|
||||
if (trim($strInclude) =~ /^\#include \"/)
|
||||
{
|
||||
$strInclude = (split('"', $strInclude))[1];
|
||||
$rhInclude->{$strInclude} = true;
|
||||
|
||||
buildDependencyTreeSub(
|
||||
$oStorage, $rhDependencyTree, $strInclude, $bErrorOnBuildHeaderMissing, $strBasePath, $rstryPath);
|
||||
|
||||
foreach my $strIncludeSub (@{$rhDependencyTree->{$strInclude}{include}})
|
||||
{
|
||||
$rhInclude->{$strIncludeSub} = true;
|
||||
}
|
||||
}
|
||||
|
||||
$first = false;
|
||||
}
|
||||
|
||||
my @stryInclude = sort(keys(%{$rhInclude}));
|
||||
$rhDependencyTree->{$strFile}{include} = \@stryInclude;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
push @EXPORT, qw(buildDependencyTreeSub);
|
||||
|
||||
####################################################################################################################################
|
||||
# Build Makefile object compile rules
|
||||
####################################################################################################################################
|
||||
sub buildMakefileObjectCompile
|
||||
{
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$oStorage,
|
||||
$rhOption,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '::buildMakefile', \@_,
|
||||
{name => 'oStorage'},
|
||||
{name => 'rhOption', optional => true},
|
||||
);
|
||||
|
||||
my $rhDependencyTree = buildDependencyTree($oStorage);
|
||||
my $strMakefile;
|
||||
|
||||
foreach my $strFile (sort(keys(%{$rhDependencyTree})))
|
||||
{
|
||||
if ($strFile =~ /^[A-Za-z0-9\/]+\.c$/)
|
||||
{
|
||||
my $strObject = substr($strFile, 0, length($strFile) - 1) . 'o';
|
||||
|
||||
my $strDepend = "${strFile}";
|
||||
|
||||
foreach my $strInclude (@{$rhDependencyTree->{$strFile}{include}})
|
||||
{
|
||||
$strDepend .= " ${strInclude}";
|
||||
}
|
||||
|
||||
$strMakefile .=
|
||||
(defined($strMakefile) ? "\n" : '') .
|
||||
"${strObject}: ${strDepend}\n" .
|
||||
"\t\$(CC) \$(CPPFLAGS) \$(CFLAGS) \$(CMAKE)" .
|
||||
(defined($rhOption->{$strObject}) ? ' ' . $rhOption->{$strObject} : '') . " -c ${strFile} -o ${strObject}\n";
|
||||
}
|
||||
}
|
||||
|
||||
return $strMakefile;
|
||||
}
|
||||
|
||||
push @EXPORT, qw(buildMakefileObjectCompile);
|
||||
|
||||
####################################################################################################################################
|
||||
# Update a Makefile with object compile rules
|
||||
####################################################################################################################################
|
||||
sub buildMakefile
|
||||
{
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$oStorage,
|
||||
$strMakefile,
|
||||
$rhOption,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '::buildMakefile', \@_,
|
||||
{name => 'oStorage'},
|
||||
{name => 'strMakeFile'},
|
||||
{name => 'rhOption', optional => true},
|
||||
);
|
||||
|
||||
# Trim off the end where the object compile is
|
||||
my $strHeader = 'Compile rules';
|
||||
|
||||
$strMakefile =~ s/^\#.*${strHeader}(.|\s)+//mg;
|
||||
|
||||
# Add object compile section
|
||||
$strMakefile .=
|
||||
"# $strHeader\n" .
|
||||
('#' x 132) . "\n" .
|
||||
buildMakefileObjectCompile($oStorage, {rhOption => $rhOption});
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'strMakefile', value => $strMakefile},
|
||||
);
|
||||
}
|
||||
|
||||
push @EXPORT, qw(buildMakefile);
|
||||
|
||||
|
||||
1;
|
||||
|
@ -16,7 +16,7 @@ use Exporter qw(import);
|
||||
our @EXPORT = qw();
|
||||
use File::Basename qw(dirname basename);
|
||||
use POSIX qw(ceil);
|
||||
use Time::HiRes qw(gettimeofday);
|
||||
use Time::HiRes qw(gettimeofday usleep);
|
||||
|
||||
use pgBackRestDoc::Common::Exception;
|
||||
use pgBackRestDoc::Common::Log;
|
||||
@ -33,11 +33,6 @@ use pgBackRestTest::Common::ListTest;
|
||||
use pgBackRestTest::Common::RunTest;
|
||||
use pgBackRestTest::Common::VmTest;
|
||||
|
||||
####################################################################################################################################
|
||||
# Has the C build directory been initialized yet?
|
||||
####################################################################################################################################
|
||||
my $rhBuildInit = undef;
|
||||
|
||||
####################################################################################################################################
|
||||
# new
|
||||
####################################################################################################################################
|
||||
@ -126,6 +121,7 @@ sub new
|
||||
# Setup the path where gcc coverage will be performed
|
||||
$self->{strGCovPath} = "$self->{strTestPath}/gcov-$self->{oTest}->{&TEST_VM}-$self->{iVmIdx}";
|
||||
$self->{strDataPath} = "$self->{strTestPath}/data-$self->{iVmIdx}";
|
||||
$self->{strRepoPath} = "$self->{strTestPath}/repo";
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
@ -215,29 +211,11 @@ sub run
|
||||
($self->{oTest}->{&TEST_C} ? " -v $self->{strGCovPath}:$self->{strGCovPath}" : '') .
|
||||
($self->{oTest}->{&TEST_C} ? " -v $self->{strDataPath}:$self->{strDataPath}" : '') .
|
||||
" -v $self->{strBackRestBase}:$self->{strBackRestBase}" .
|
||||
" -v $self->{strRepoPath}:$self->{strRepoPath}:ro" .
|
||||
($self->{oTest}->{&TEST_BIN_REQ} ? " -v ${strBinPath}:${strBinPath}:ro" : '') .
|
||||
' ' . containerRepo() . ':' . $self->{oTest}->{&TEST_VM} . '-test',
|
||||
{bSuppressStdErr => true});
|
||||
}
|
||||
|
||||
# If testing C code copy source files to the test directory
|
||||
if ($self->{oTest}->{&TEST_C})
|
||||
{
|
||||
# If this is the first build, then rsync files
|
||||
if (!$rhBuildInit->{$self->{oTest}->{&TEST_VM}}{$self->{iVmIdx}})
|
||||
{
|
||||
executeTest(
|
||||
'rsync -rt --delete --exclude=*.o --exclude=test.c --exclude=test.gcno ' .
|
||||
' --exclude=test --exclude=buildflags --exclude=testflags --exclude=harnessflags' .
|
||||
' --exclude=build.auto.h --exclude=build.auto.h.in --exclude=Makefile --exclude=Makefile.in' .
|
||||
' --exclude=configure --exclude=configure.ac' .
|
||||
" $self->{strBackRestBase}/src/ $self->{strGCovPath} && " .
|
||||
"rsync -rt --delete --exclude=*.o $self->{strBackRestBase}/test/src/ $self->{strGCovPath}/test");
|
||||
}
|
||||
|
||||
# Build directory has been initialized
|
||||
$rhBuildInit->{$self->{oTest}->{&TEST_VM}}{$self->{iVmIdx}} = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -249,89 +227,197 @@ sub run
|
||||
$strCommandRunParam .= ' --run=' . $iRunIdx;
|
||||
}
|
||||
|
||||
# Create command
|
||||
my $strCommand;
|
||||
|
||||
if ($self->{oTest}->{&TEST_C})
|
||||
{
|
||||
# Build filename for valgrind suppressions
|
||||
my $strValgrindSuppress = $self->{strGCovPath} . '/test/valgrind.suppress.' . $self->{oTest}->{&TEST_VM};
|
||||
|
||||
$strCommand =
|
||||
($self->{oTest}->{&TEST_VM} ne VM_NONE ? 'docker exec -i -u ' . TEST_USER . " ${strImage} " : '') .
|
||||
"bash -l -c '" .
|
||||
"cd $self->{strGCovPath} && " .
|
||||
# Remove coverage data from last run
|
||||
"rm -f test.gcda && " .
|
||||
$self->{strMakeCmd} . " -j $self->{iBuildMax} -s 2>&1 &&" .
|
||||
# Test with valgrind when requested
|
||||
($self->{bValgrindUnit} && $self->{oTest}->{&TEST_TYPE} ne TESTDEF_PERFORMANCE ?
|
||||
' valgrind -q --gen-suppressions=all ' .
|
||||
($self->{oStorageTest}->exists($strValgrindSuppress) ? " --suppressions=${strValgrindSuppress}" : '') .
|
||||
" --leak-check=full --leak-resolution=high --error-exitcode=25" : '') .
|
||||
" ./test.bin 2>&1'";
|
||||
}
|
||||
else
|
||||
{
|
||||
$strCommand =
|
||||
($self->{oTest}->{&TEST_CONTAINER} ? 'docker exec -i -u ' . TEST_USER . " ${strImage} " : '') .
|
||||
abs_path($0) .
|
||||
" --test-path=${strVmTestPath}" .
|
||||
" --vm-host=$self->{strVmHost}" .
|
||||
" --vm=$self->{oTest}->{&TEST_VM}" .
|
||||
" --vm-id=$self->{iVmIdx}" .
|
||||
" --module=" . $self->{oTest}->{&TEST_MODULE} .
|
||||
' --test=' . $self->{oTest}->{&TEST_NAME} .
|
||||
$strCommandRunParam .
|
||||
(defined($self->{oTest}->{&TEST_DB}) ? ' --pg-version=' . $self->{oTest}->{&TEST_DB} : '') .
|
||||
($self->{strLogLevel} ne lc(INFO) ? " --log-level=$self->{strLogLevel}" : '') .
|
||||
($self->{strLogLevelTestFile} ne lc(TRACE) ? " --log-level-test-file=$self->{strLogLevelTestFile}" : '') .
|
||||
($self->{bLogTimestamp} ? '' : ' --no-log-timestamp') .
|
||||
' --pgsql-bin=' . $self->{oTest}->{&TEST_PGSQL_BIN} .
|
||||
($self->{strTimeZone} ? " --tz='$self->{strTimeZone}'" : '') .
|
||||
($self->{bLogForce} ? ' --log-force' : '') .
|
||||
($self->{bDryRun} ? ' --dry-run' : '') .
|
||||
($self->{bDryRun} ? ' --vm-out' : '') .
|
||||
($self->{bNoCleanup} ? " --no-cleanup" : '');
|
||||
}
|
||||
|
||||
if (!$self->{bDryRun} || $self->{bVmOut})
|
||||
{
|
||||
my $strCommand = undef; # Command to run test
|
||||
|
||||
# If testing C code
|
||||
if ($self->{oTest}->{&TEST_C})
|
||||
{
|
||||
my $strRepoCopyPath = $self->{strTestPath} . '/repo'; # Path to repo copy
|
||||
my $strRepoCopySrcPath = $strRepoCopyPath . '/src'; # Path to repo copy src
|
||||
my $strRepoCopyTestSrcPath = $strRepoCopyPath . '/test/src'; # Path to repo copy test src
|
||||
|
||||
my $bCleanAll = false; # Do all object files need to be cleaned?
|
||||
my $bConfigure = false; # Does configure need to be run?
|
||||
|
||||
# If the build.processing file exists then wipe the path to start clean
|
||||
# ------------------------------------------------------------------------------------------------------------------
|
||||
my $strBuildProcessingFile = $self->{strGCovPath} . "/build.processing";
|
||||
|
||||
# If the file exists then processing terminated before test.bin was run in the last test and the path might be in a
|
||||
# bad state.
|
||||
if ($self->{oStorageTest}->exists($strBuildProcessingFile))
|
||||
{
|
||||
executeTest("find $self->{strGCovPath} -mindepth 1 -print0 | xargs -0 rm -rf");
|
||||
}
|
||||
|
||||
# Write build.processing to track processing of this test
|
||||
$self->{oStorageTest}->put($strBuildProcessingFile);
|
||||
|
||||
# Create Makefile.in
|
||||
# ------------------------------------------------------------------------------------------------------------------
|
||||
my $strMakefileIn =
|
||||
"CC_CONFIG = \@CC\@\n" .
|
||||
"CFLAGS_CONFIG = \@CFLAGS\@\n" .
|
||||
"CPPFLAGS_CONFIG = \@CPPFLAGS\@\n" .
|
||||
"LDFLAGS_CONFIG = \@LDFLAGS\@\n" .
|
||||
"LIBS_CONFIG = \@LIBS\@\n";
|
||||
|
||||
# If Makefile.in has changed then configure needs to be run and all files cleaned
|
||||
if (buildPutDiffers($self->{oStorageTest}, $self->{strGCovPath} . "/Makefile.in", $strMakefileIn))
|
||||
{
|
||||
$bConfigure = true;
|
||||
$bCleanAll = true;
|
||||
}
|
||||
|
||||
# Create Makefile.param
|
||||
# ------------------------------------------------------------------------------------------------------------------
|
||||
# Disable debug/coverage for performance and profile tests
|
||||
my $bPerformance = $self->{oTest}->{&TEST_TYPE} eq TESTDEF_PERFORMANCE;
|
||||
|
||||
if ($bPerformance || $self->{bProfile})
|
||||
{
|
||||
$self->{bDebug} = false;
|
||||
$self->{bDebugTestTrace} = false;
|
||||
$self->{bCoverageUnit} = false;
|
||||
}
|
||||
|
||||
# Is coverage being tested?
|
||||
my $bCoverage = vmCoverageC($self->{oTest}->{&TEST_VM}) && $self->{bCoverageUnit};
|
||||
|
||||
# Generate Makefile.param
|
||||
my $strMakefileParam =
|
||||
"CFLAGS =" .
|
||||
" \\\n\t-Werror -Wfatal-errors" .
|
||||
($self->{bProfile} ? " \\\n\t-pg" : '') .
|
||||
(vmArchBits($self->{oTest}->{&TEST_VM}) == 32 ? " \\\n\t-D_FILE_OFFSET_BITS=64" : '') .
|
||||
($self->{bDebug} ? '' : " \\\n\t-DNDEBUG") .
|
||||
($self->{oTest}->{&TEST_DEBUG_UNIT_SUPPRESS} ? '' : " \\\n\t-DDEBUG_UNIT") .
|
||||
($self->{oTest}->{&TEST_VM} eq VM_CO7 ? " \\\n\t-DDEBUG_EXEC_TIME" : '') .
|
||||
($bCoverage ? " \\\n\t-DDEBUG_COVERAGE" : '') .
|
||||
($self->{bDebugTestTrace} && $self->{bDebug} ? " \\\n\t-DDEBUG_TEST_TRACE" : '') .
|
||||
(vmWithBackTrace($self->{oTest}->{&TEST_VM}) && $self->{bBackTrace} ? " \\\n\t-DWITH_BACKTRACE" : '') .
|
||||
($self->{oTest}->{&TEST_CDEF} ? " \\\n\t$self->{oTest}->{&TEST_CDEF}" : '') .
|
||||
"\n" .
|
||||
"\n" .
|
||||
"CFLAGS_TEST =" .
|
||||
" \\\n\t" . (($self->{bOptimize} && ($self->{bProfile} || $bPerformance)) ? '-O2' : '-O0') .
|
||||
" \\\n\t-DDEBUG_MEM" .
|
||||
(!$self->{bDebugTestTrace} && $self->{bDebug} ? " \\\n\t-DDEBUG_TEST_TRACE" : '') .
|
||||
($bCoverage ? " \\\n\t-fprofile-arcs -ftest-coverage" : '') .
|
||||
($self->{oTest}->{&TEST_VM} eq VM_NONE ? '' : " \\\n\t-DTEST_CONTAINER_REQUIRED") .
|
||||
($self->{oTest}->{&TEST_CTESTDEF} ? " \\\n\t$self->{oTest}->{&TEST_CTESTDEF}" : '') .
|
||||
"\n" .
|
||||
"\n" .
|
||||
"CFLAGS_HARNESS =" .
|
||||
" \\\n\t" . ($self->{bOptimize} ? '-O2' : '-O0') .
|
||||
($self->{oTest}->{&TEST_CTESTDEF} ? " \\\n\t$self->{oTest}->{&TEST_CTESTDEF}" : '') .
|
||||
"\n" .
|
||||
"\n" .
|
||||
"CFLAGS_CORE =" .
|
||||
" \\\n\t" . ($self->{bOptimize} ? '-O2' : '-O0') .
|
||||
"\n" .
|
||||
"\n" .
|
||||
"LDFLAGS =" .
|
||||
($self->{bProfile} ? " \\\n\t-pg" : '') .
|
||||
"\n" .
|
||||
"\n" .
|
||||
"LIBS =" .
|
||||
($bCoverage ? " \\\n\t-lgcov" : '') .
|
||||
(vmWithBackTrace($self->{oTest}->{&TEST_VM}) && $self->{bBackTrace} ? " \\\n\t-lbacktrace" : '') .
|
||||
"\n" .
|
||||
"\n" .
|
||||
"INCLUDE =" .
|
||||
" \\\n\t-I\"${strRepoCopySrcPath}\"" .
|
||||
" \\\n\t-I\"${strRepoCopyTestSrcPath}\"" .
|
||||
"\n" .
|
||||
"\n" .
|
||||
"vpath \%.c ${strRepoCopySrcPath}:${strRepoCopyTestSrcPath}\n";
|
||||
|
||||
# If Makefile.param has changed then clean all files
|
||||
if (buildPutDiffers($self->{oStorageTest}, $self->{strGCovPath} . "/Makefile.param", $strMakefileParam))
|
||||
{
|
||||
$bCleanAll = true;
|
||||
}
|
||||
|
||||
# Generate list of harness files
|
||||
# ------------------------------------------------------------------------------------------------------------------
|
||||
my $strRepoCopyTestSrcHarnessPath = $strRepoCopyTestSrcPath . '/common';
|
||||
|
||||
my @stryHarnessFile;
|
||||
|
||||
foreach my $strFile (sort(keys(%{$self->{oStorageTest}->manifest($strRepoCopyTestSrcHarnessPath)})))
|
||||
{
|
||||
# Skip . and header files
|
||||
next if $strFile eq '.' || $strFile =~ /\.h$/;
|
||||
|
||||
push(@stryHarnessFile, "common/" . substr($strFile, 0, length($strFile) - 2));
|
||||
}
|
||||
|
||||
# Generate list of core files (files to be tested/included in this unit will be excluded)
|
||||
# ------------------------------------------------------------------------------------------------------------------
|
||||
my $hTest = (testDefModuleTest($self->{oTest}->{&TEST_MODULE}, $self->{oTest}->{&TEST_NAME}));
|
||||
my $hTestCoverage = $hTest->{&TESTDEF_COVERAGE};
|
||||
|
||||
my @stryCFile;
|
||||
my @stryCoreFile;
|
||||
|
||||
foreach my $strFile (sort(keys(%{$self->{oStorageTest}->manifest($self->{strGCovPath})})))
|
||||
foreach my $strFile (sort(keys(%{$self->{oStorageTest}->manifest($strRepoCopySrcPath)})))
|
||||
{
|
||||
my $strFileNoExt = substr($strFile, 0, length($strFile) - 2);
|
||||
|
||||
# Skip all files except .c files (including .auto.c)
|
||||
next if $strFile !~ /(?<!\.auto)\.c$/;
|
||||
|
||||
# Skip all files except .c files (including .vendor.c)
|
||||
next if $strFile !~ /(?<!\.vendor)\.c$/;
|
||||
# Skip all files except .c files (including .auto.c and .vendor.c)
|
||||
next if $strFile !~ /(?<!\.auto)\.c$/ || $strFile !~ /(?<!\.vendor)\.c$/;
|
||||
|
||||
# ??? Skip main for now until the function can be renamed to allow unit testing
|
||||
next if $strFile =~ /main\.c$/;
|
||||
|
||||
# Skip test.c -- it will be added manually at the end
|
||||
next if $strFile =~ /test\.c$/;
|
||||
|
||||
if (!defined($hTestCoverage->{$strFileNoExt}) && !grep(/^$strFileNoExt$/, @{$hTest->{&TESTDEF_INCLUDE}}) &&
|
||||
$strFile !~ /^test\/module\/[^\/]*\/.*Test\.c$/)
|
||||
if (!defined($hTestCoverage->{$strFileNoExt}) && !grep(/^$strFileNoExt$/, @{$hTest->{&TESTDEF_INCLUDE}}))
|
||||
{
|
||||
push(@stryCFile, "${strFile}");
|
||||
push(@stryCoreFile, "${strFileNoExt}");
|
||||
}
|
||||
}
|
||||
|
||||
# Create Makefile
|
||||
# ------------------------------------------------------------------------------------------------------------------
|
||||
my $strMakefile =
|
||||
"include Makefile.config\n" .
|
||||
"include Makefile.param\n" .
|
||||
"\n" .
|
||||
"SRCS = test.c \\\n" .
|
||||
"\t" . join('.c ', @stryHarnessFile) . ".c \\\n" .
|
||||
"\t" . join('.c ', @stryCoreFile) . ".c\n" .
|
||||
"\n" .
|
||||
".build/test.o: CFLAGS += \$(CFLAGS_TEST)\n" .
|
||||
"\n" .
|
||||
".build/" . join(".o: CFLAGS += \$(CFLAGS_HARNESS)\n.build/", @stryHarnessFile) .
|
||||
".o: CFLAGS += \$(CFLAGS_HARNESS)\n" .
|
||||
"\n" .
|
||||
".build/" . join(".o: CFLAGS += \$(CFLAGS_CORE)\n.build/", @stryCoreFile) .
|
||||
".o: CFLAGS += \$(CFLAGS_CORE)\n" .
|
||||
"\n" .
|
||||
".build/\%.o : \%.c\n" .
|
||||
" \@if test ! -d \$(\@D); then mkdir -p \$(\@D); fi\n" .
|
||||
" \$(CC_CONFIG) \$(INCLUDE) \$(CFLAGS_CONFIG) \$(CPPFLAGS_CONFIG) \$(CFLAGS)" .
|
||||
" -c -o \$\@ \$< -MMD -MP -MF .build/\$*.dep\n" .
|
||||
"\n" .
|
||||
"OBJS = \$(patsubst \%.c,.build/\%.o,\$(SRCS))\n" .
|
||||
"\n" .
|
||||
"test: \$(OBJS)\n" .
|
||||
" \$(CC_CONFIG) -o test.bin \$(OBJS) \$(LDFLAGS_CONFIG) \$(LDFLAGS) \$(LIBS_CONFIG) \$(LIBS)\n" .
|
||||
"\n" .
|
||||
"rwildcard = \$(wildcard \$1\$2) \$(foreach d,\$(wildcard \$1*),\$(call rwildcard,\$d/,\$2))\n" .
|
||||
"DEP_FILES = \$(call rwildcard,.build,*.dep)\n" .
|
||||
"include \$(DEP_FILES)\n";
|
||||
|
||||
buildPutDiffers($self->{oStorageTest}, $self->{strGCovPath} . "/Makefile", $strMakefile);
|
||||
|
||||
# Create test.c
|
||||
# ------------------------------------------------------------------------------------------------------------------
|
||||
# Generate list of C files to include for testing
|
||||
my $strTestDepend = '';
|
||||
my $strTestFile =
|
||||
"test/module/$self->{oTest}->{&TEST_MODULE}/" . testRunName($self->{oTest}->{&TEST_NAME}, false) . 'Test.c';
|
||||
"module/$self->{oTest}->{&TEST_MODULE}/" . testRunName($self->{oTest}->{&TEST_NAME}, false) . 'Test.c';
|
||||
my $strCInclude;
|
||||
|
||||
foreach my $strFile (sort(keys(%{$hTestCoverage}), @{$hTest->{&TESTDEF_INCLUDE}}))
|
||||
@ -349,12 +435,12 @@ sub run
|
||||
my $strCIncludeFile = "${strFile}.c";
|
||||
|
||||
# If the C file does not exist use the header file instead
|
||||
if (!$self->{oStorageTest}->exists("$self->{strGCovPath}/${strCIncludeFile}"))
|
||||
if (!$self->{oStorageTest}->exists("${strRepoCopySrcPath}/${strCIncludeFile}"))
|
||||
{
|
||||
# Error if code was expected
|
||||
if ($hTestCoverage->{$strFile} ne TESTDEF_COVERAGE_NOCODE)
|
||||
{
|
||||
confess &log(ERROR, "unable to find source file '$self->{strGCovPath}/${strCIncludeFile}'");
|
||||
confess &log(ERROR, "unable to find source file '${strRepoCopySrcPath}/${strCIncludeFile}'");
|
||||
}
|
||||
|
||||
$strCIncludeFile = "${strFile}.h";
|
||||
@ -365,7 +451,7 @@ sub run
|
||||
}
|
||||
|
||||
# Update C test file with test module
|
||||
my $strTestC = ${$self->{oStorageTest}->get("$self->{strGCovPath}/test/test.c")};
|
||||
my $strTestC = ${$self->{oStorageTest}->get("${strRepoCopyTestSrcPath}/test.c")};
|
||||
|
||||
if (defined($strCInclude))
|
||||
{
|
||||
@ -379,18 +465,6 @@ sub run
|
||||
$strTestC =~ s/\{\[C\_TEST\_INCLUDE\]\}/\#include \"$strTestFile\"/g;
|
||||
$strTestDepend .= " ${strTestFile}";
|
||||
|
||||
# Build dependencies for the test file
|
||||
my $rhDependencyTree = {};
|
||||
buildDependencyTreeSub(
|
||||
$self->{oStorageTest}, $rhDependencyTree, $strTestFile, false, $self->{strGCovPath}, ['', 'test']);
|
||||
|
||||
foreach my $strDepend (@{$rhDependencyTree->{$strTestFile}{include}})
|
||||
{
|
||||
$strTestDepend .=
|
||||
' ' . ($rhDependencyTree->{$strDepend}{path} ne '' ? $rhDependencyTree->{$strDepend}{path} . '/' : '') .
|
||||
$strDepend;
|
||||
}
|
||||
|
||||
# Determine where the project exe is located
|
||||
my $strProjectExePath = "$self->{strTestPath}/bin/$self->{oTest}->{&TEST_VM}/" . PROJECT_EXE;
|
||||
|
||||
@ -405,6 +479,7 @@ sub run
|
||||
$strTestC =~ s/\{\[C\_TEST\_CONTAINER\]\}/$strContainer/g;
|
||||
$strTestC =~ s/\{\[C\_TEST\_PROJECT\_EXE\]\}/$strProjectExePath/g;
|
||||
$strTestC =~ s/\{\[C\_TEST\_PATH\]\}/$strTestPathC/g;
|
||||
$strTestC =~ s/\{\[C\_TEST\_PGB\_PATH\]\}/$strRepoCopyPath/g;
|
||||
$strTestC =~ s/\{\[C\_TEST\_DATA_PATH\]\}/$self->{strDataPath}/g;
|
||||
$strTestC =~ s/\{\[C\_TEST\_IDX\]\}/$self->{iVmIdx}/g;
|
||||
$strTestC =~ s/\{\[C\_TEST\_REPO_PATH\]\}/$self->{strBackRestBase}/g;
|
||||
@ -446,135 +521,87 @@ sub run
|
||||
}
|
||||
|
||||
$strTestC =~ s/\{\[C\_TEST\_LIST\]\}/$strTestInit/g;
|
||||
buildPutDiffers($self->{oStorageTest}, "$self->{strGCovPath}/test.c", $strTestC);
|
||||
|
||||
# Create build.auto.h
|
||||
my $strBuildAutoH =
|
||||
"#define HAVE_STATIC_ASSERT\n" .
|
||||
"#define HAVE_BUILTIN_TYPES_COMPATIBLE_P\n" .
|
||||
(vmWithLz4($self->{oTest}->{&TEST_VM}) ? '#define HAVE_LIBLZ4' : '') . "\n" .
|
||||
(vmWithZst($self->{oTest}->{&TEST_VM}) ? '#define HAVE_LIBZST' : '') . "\n";
|
||||
# Save test.c and make sure it gets a new timestamp
|
||||
# ------------------------------------------------------------------------------------------------------------------
|
||||
my $strTestCFile = "$self->{strGCovPath}/test.c";
|
||||
|
||||
buildPutDiffers($self->{oStorageTest}, "$self->{strGCovPath}/" . BUILD_AUTO_H, $strBuildAutoH);
|
||||
|
||||
# Disable debug/coverage for performance and profile tests
|
||||
my $bPerformance = $self->{oTest}->{&TEST_TYPE} eq TESTDEF_PERFORMANCE;
|
||||
|
||||
if ($bPerformance || $self->{bProfile})
|
||||
if (buildPutDiffers($self->{oStorageTest}, "$self->{strGCovPath}/test.c", $strTestC))
|
||||
{
|
||||
$self->{bDebug} = false;
|
||||
$self->{bDebugTestTrace} = false;
|
||||
$self->{bCoverageUnit} = false;
|
||||
}
|
||||
# Get timestamp for test.bin if it existss
|
||||
my $oTestBinInfo = $self->{oStorageTest}->info("$self->{strGCovPath}/test.bin", {bIgnoreMissing => true});
|
||||
my $iTestBinOriginalTime = defined($oTestBinInfo) ? $oTestBinInfo->mtime : 0;
|
||||
|
||||
# When optimization is disabled add -ftree-coalesce-vars to make the compiler faster when available
|
||||
my $strNoOptimizeFlags = '-O0' . ($self->{oTest}->{&TEST_VM} ne VM_U12 ? ' -ftree-coalesce-vars' : '');
|
||||
# Get timestamp for test.c
|
||||
my $iTestCNewTime = $self->{oStorageTest}->info($strTestCFile)->mtime;
|
||||
|
||||
# Determine which warnings are available
|
||||
my $strWarningFlags =
|
||||
'-Werror -Wfatal-errors -Wall -Wextra -Wwrite-strings -Wconversion -Wformat=2' .
|
||||
' -Wformat-nonliteral -Wstrict-prototypes -Wpointer-arith -Wvla' .
|
||||
($self->{oTest}->{&TEST_VM} eq VM_U16 || $self->{oTest}->{&TEST_VM} eq VM_U18 ?
|
||||
' -Wformat-signedness' : '') .
|
||||
($self->{oTest}->{&TEST_VM} eq VM_U18 ?
|
||||
' -Wduplicated-branches -Wduplicated-cond' : '') .
|
||||
# This is theoretically a portability issue but a compiler that does not treat NULL and false as 0 is crazy
|
||||
' -Wno-missing-field-initializers';
|
||||
|
||||
# Flags that are common to all builds
|
||||
my $strCommonFlags =
|
||||
'-I. -Itest -std=c99 -fPIC -g -Wno-clobbered -D_POSIX_C_SOURCE=200809L -D_FILE_OFFSET_BITS=64' .
|
||||
' `pkg-config libxml-2.0 --cflags`' . ($self->{bProfile} ? " -pg" : '') .
|
||||
' -I`pg_config --includedir`' .
|
||||
($self->{oTest}->{&TEST_DEBUG_UNIT_SUPPRESS} ? '' : " -DDEBUG_UNIT") .
|
||||
(vmWithBackTrace($self->{oTest}->{&TEST_VM}) && $self->{bBackTrace} ? ' -DWITH_BACKTRACE' : '') .
|
||||
($self->{oTest}->{&TEST_CDEF} ? " $self->{oTest}->{&TEST_CDEF}" : '') .
|
||||
(vmCoverageC($self->{oTest}->{&TEST_VM}) && $self->{bCoverageUnit} ? ' -DDEBUG_COVERAGE' : '') .
|
||||
($self->{bDebug} ? '' : ' -DNDEBUG') .
|
||||
($self->{bDebugTestTrace} && $self->{bDebug} ? ' -DDEBUG_TEST_TRACE' : '') .
|
||||
($self->{oTest}->{&TEST_VM} eq VM_CO7 ? ' -DDEBUG_EXEC_TIME' : '');
|
||||
|
||||
# Flags used to build harness files
|
||||
my $strHarnessFlags =
|
||||
($self->{bOptimize} ? '-O2' : $strNoOptimizeFlags) .
|
||||
($self->{oTest}->{&TEST_CTESTDEF} ? " $self->{oTest}->{&TEST_CTESTDEF}" : '');
|
||||
|
||||
buildPutDiffers(
|
||||
$self->{oStorageTest}, "$self->{strGCovPath}/harnessflags",
|
||||
"${strCommonFlags} ${strWarningFlags} ${strHarnessFlags}");
|
||||
|
||||
# Flags used to build test.c
|
||||
my $strTestFlags =
|
||||
(($self->{bOptimize} && ($self->{bProfile} || $bPerformance)) ? '-O2' : $strNoOptimizeFlags) .
|
||||
(!$self->{bDebugTestTrace} && $self->{bDebug} ? ' -DDEBUG_TEST_TRACE' : '') .
|
||||
' -DDEBUG_MEM' .
|
||||
(vmCoverageC($self->{oTest}->{&TEST_VM}) && $self->{bCoverageUnit} ? ' -fprofile-arcs -ftest-coverage' : '') .
|
||||
($self->{oTest}->{&TEST_VM} eq VM_NONE ? '' : " -DTEST_CONTAINER_REQUIRED") .
|
||||
($self->{oTest}->{&TEST_CTESTDEF} ? " $self->{oTest}->{&TEST_CTESTDEF}" : '');
|
||||
|
||||
buildPutDiffers(
|
||||
$self->{oStorageTest}, "$self->{strGCovPath}/testflags",
|
||||
"${strCommonFlags} ${strWarningFlags} ${strTestFlags}");
|
||||
|
||||
# Flags used to build all other files
|
||||
my $strBuildFlags =
|
||||
($self->{bOptimize} ? '-O2' : $strNoOptimizeFlags);
|
||||
|
||||
buildPutDiffers(
|
||||
$self->{oStorageTest}, "$self->{strGCovPath}/buildflags",
|
||||
"${strCommonFlags} ${strWarningFlags} ${strBuildFlags}");
|
||||
|
||||
# Build the Makefile
|
||||
my $strMakefile =
|
||||
"CC=gcc\n" .
|
||||
"COMMONFLAGS=${strCommonFlags}\n" .
|
||||
"WARNINGFLAGS=${strWarningFlags}\n" .
|
||||
"BUILDFLAGS=${strBuildFlags}\n" .
|
||||
"HARNESSFLAGS=${strHarnessFlags}\n" .
|
||||
"TESTFLAGS=${strTestFlags}\n" .
|
||||
"LDFLAGS=-lcrypto -lssl -lxml2 -lz -lbz2" .
|
||||
(vmWithLz4($self->{oTest}->{&TEST_VM}) ? ' -llz4' : '') .
|
||||
(vmWithZst($self->{oTest}->{&TEST_VM}) ? ' -lzstd' : '') .
|
||||
(vmCoverageC($self->{oTest}->{&TEST_VM}) && $self->{bCoverageUnit} ? " -lgcov" : '') .
|
||||
(vmWithBackTrace($self->{oTest}->{&TEST_VM}) && $self->{bBackTrace} ? ' -lbacktrace' : '') .
|
||||
"\n" .
|
||||
"SRCS=" . join(' ', @stryCFile) . "\n" .
|
||||
"OBJS=\$(SRCS:.c=.o)\n" .
|
||||
"\n" .
|
||||
"test: \$(OBJS) test.o\n" .
|
||||
"\t\$(CC) -o test.bin \$(OBJS) test.o" . ($self->{bProfile} ? " -pg" : '') . " \$(LDFLAGS)\n" .
|
||||
"\n" .
|
||||
"test.o: testflags test.c${strTestDepend}\n" .
|
||||
"\t\$(CC) \$(COMMONFLAGS) \$(WARNINGFLAGS) \$(TESTFLAGS) -c test.c\n";
|
||||
|
||||
# Build C file dependencies
|
||||
foreach my $strCFile (@stryCFile)
|
||||
{
|
||||
my $bHarnessFile = $strCFile =~ /^test\// ? true : false;
|
||||
|
||||
buildDependencyTreeSub(
|
||||
$self->{oStorageTest}, $rhDependencyTree, $strCFile, !$bHarnessFile, $self->{strGCovPath}, ['', 'test']);
|
||||
|
||||
$strMakefile .=
|
||||
"\n" . substr($strCFile, 0, length($strCFile) - 2) . ".o:" .
|
||||
($bHarnessFile ? " harnessflags" : " buildflags") . " $strCFile";
|
||||
|
||||
foreach my $strDepend (@{$rhDependencyTree->{$strCFile}{include}})
|
||||
# Is the timestamp for test.c newer than test.bin?
|
||||
while ($iTestCNewTime <= $iTestBinOriginalTime)
|
||||
{
|
||||
$strMakefile .=
|
||||
' ' .
|
||||
($rhDependencyTree->{$strDepend}{path} ne '' ? $rhDependencyTree->{$strDepend}{path} . '/' : '') .
|
||||
$strDepend;
|
||||
}
|
||||
# If not then sleep until the next second
|
||||
my $iTimeToSleep = ($iTestBinOriginalTime + 1) - gettimeofday();
|
||||
|
||||
$strMakefile .=
|
||||
"\n" .
|
||||
"\t\$(CC) \$(COMMONFLAGS) \$(WARNINGFLAGS)" .
|
||||
($strCFile =~ /^test\// ? " \$(HARNESSFLAGS)" : " \$(BUILDFLAGS)") .
|
||||
" -c $strCFile -o " . substr($strCFile, 0, length($strCFile) - 2) . ".o\n";
|
||||
if ($iTimeToSleep > 0)
|
||||
{
|
||||
usleep($iTimeToSleep * 1000000);
|
||||
}
|
||||
|
||||
# Save the file again
|
||||
$self->{oStorageTest}->put($self->{oStorageTest}->openWrite($strTestCFile), $strTestC);
|
||||
$iTestCNewTime = $self->{oStorageTest}->info($strTestCFile)->mtime;
|
||||
}
|
||||
}
|
||||
|
||||
buildPutDiffers($self->{oStorageTest}, $self->{strGCovPath} . "/Makefile", $strMakefile);
|
||||
# Create command
|
||||
# ------------------------------------------------------------------------------------------------------------------
|
||||
# Build filename for valgrind suppressions
|
||||
my $strValgrindSuppress = $self->{strRepoPath} . '/test/src/valgrind.suppress.' . $self->{oTest}->{&TEST_VM};
|
||||
|
||||
$strCommand =
|
||||
($self->{oTest}->{&TEST_VM} ne VM_NONE ? "docker exec -i -u ${\TEST_USER} ${strImage} bash -l -c '" : '') .
|
||||
" \\\n" .
|
||||
"cd $self->{strGCovPath} && \\\n" .
|
||||
# Clean build
|
||||
($bCleanAll ? "rm -rf .build && \\\n" : '') .
|
||||
# Remove coverage data
|
||||
(!$bCleanAll && $bCoverage ? "rm -rf .build/test.gcda && \\\n" : '') .
|
||||
# Configure when required
|
||||
($bConfigure ?
|
||||
"mv Makefile Makefile.tmp && ${strRepoCopySrcPath}/configure -q --enable-test" .
|
||||
" && mv Makefile Makefile.config && mv Makefile.tmp Makefile && \\\n" :
|
||||
'') .
|
||||
$self->{strMakeCmd} . " -j $self->{iBuildMax} -s 2>&1 && \\\n" .
|
||||
"rm ${strBuildProcessingFile} && \\\n" .
|
||||
# Test with valgrind when requested
|
||||
($self->{bValgrindUnit} && $self->{oTest}->{&TEST_TYPE} ne TESTDEF_PERFORMANCE ?
|
||||
'valgrind -q --gen-suppressions=all' .
|
||||
($self->{oStorageTest}->exists($strValgrindSuppress) ? " --suppressions=${strValgrindSuppress}" : '') .
|
||||
" --leak-check=full --leak-resolution=high --error-exitcode=25" . ' ' : '') .
|
||||
"./test.bin 2>&1" .
|
||||
($self->{oTest}->{&TEST_VM} ne VM_NONE ? "'" : '');
|
||||
}
|
||||
else
|
||||
{
|
||||
$strCommand =
|
||||
($self->{oTest}->{&TEST_CONTAINER} ? 'docker exec -i -u ' . TEST_USER . " ${strImage} " : '') .
|
||||
abs_path($0) .
|
||||
" --test-path=${strVmTestPath}" .
|
||||
" --vm-host=$self->{strVmHost}" .
|
||||
" --vm=$self->{oTest}->{&TEST_VM}" .
|
||||
" --vm-id=$self->{iVmIdx}" .
|
||||
" --module=" . $self->{oTest}->{&TEST_MODULE} .
|
||||
' --test=' . $self->{oTest}->{&TEST_NAME} .
|
||||
$strCommandRunParam .
|
||||
(defined($self->{oTest}->{&TEST_DB}) ? ' --pg-version=' . $self->{oTest}->{&TEST_DB} : '') .
|
||||
($self->{strLogLevel} ne lc(INFO) ? " --log-level=$self->{strLogLevel}" : '') .
|
||||
($self->{strLogLevelTestFile} ne lc(TRACE) ? " --log-level-test-file=$self->{strLogLevelTestFile}" : '') .
|
||||
($self->{bLogTimestamp} ? '' : ' --no-log-timestamp') .
|
||||
' --pgsql-bin=' . $self->{oTest}->{&TEST_PGSQL_BIN} .
|
||||
($self->{strTimeZone} ? " --tz='$self->{strTimeZone}'" : '') .
|
||||
($self->{bLogForce} ? ' --log-force' : '') .
|
||||
($self->{bDryRun} ? ' --dry-run' : '') .
|
||||
($self->{bDryRun} ? ' --vm-out' : '') .
|
||||
($self->{bNoCleanup} ? " --no-cleanup" : '');
|
||||
}
|
||||
|
||||
my $oExec = new pgBackRestTest::Common::ExecuteTest(
|
||||
|
@ -120,11 +120,11 @@ testRun(void)
|
||||
testFunction1(99, false, NULL, NULL, NULL, 1.17, 0755);
|
||||
|
||||
harnessLogResult(
|
||||
"P00 DEBUG: test/module/common/debugOnTest::testFunction1: (paramInt: 99, paramBool: false, paramBoolP: null"
|
||||
", paramBoolPP: null, paramVoidP: null, paramDouble: 1.17, paramMode: 0755)\n"
|
||||
"P00 TRACE: test/module/common/debugOnTest::testFunction2: (void)\n"
|
||||
"P00 TRACE: test/module/common/debugOnTest::testFunction2: => void\n"
|
||||
"P00 DEBUG: test/module/common/debugOnTest::testFunction1: => 1");
|
||||
"P00 DEBUG: " TEST_PGB_PATH "/test/src/module/common/debugOnTest::testFunction1: (paramInt: 99, paramBool: false,"
|
||||
" paramBoolP: null, paramBoolPP: null, paramVoidP: null, paramDouble: 1.17, paramMode: 0755)\n"
|
||||
"P00 TRACE: " TEST_PGB_PATH "/test/src/module/common/debugOnTest::testFunction2: (void)\n"
|
||||
"P00 TRACE: " TEST_PGB_PATH "/test/src/module/common/debugOnTest::testFunction2: => void\n"
|
||||
"P00 DEBUG: " TEST_PGB_PATH "/test/src/module/common/debugOnTest::testFunction1: => 1");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
bool testBool = true;
|
||||
@ -135,11 +135,11 @@ testRun(void)
|
||||
testFunction1(99, false, testBoolP, testBoolPP, testVoidP, 1.17, 0755);
|
||||
|
||||
harnessLogResult(
|
||||
"P00 DEBUG: test/module/common/debugOnTest::testFunction1: (paramInt: 99, paramBool: false, paramBoolP: *true"
|
||||
", paramBoolPP: **true, paramVoidP: null, paramDouble: 1.17, paramMode: 0755)\n"
|
||||
"P00 TRACE: test/module/common/debugOnTest::testFunction2: (void)\n"
|
||||
"P00 TRACE: test/module/common/debugOnTest::testFunction2: => void\n"
|
||||
"P00 DEBUG: test/module/common/debugOnTest::testFunction1: => 1");
|
||||
"P00 DEBUG: " TEST_PGB_PATH "/test/src/module/common/debugOnTest::testFunction1: (paramInt: 99, paramBool: false,"
|
||||
" paramBoolP: *true, paramBoolPP: **true, paramVoidP: null, paramDouble: 1.17, paramMode: 0755)\n"
|
||||
"P00 TRACE: " TEST_PGB_PATH "/test/src/module/common/debugOnTest::testFunction2: (void)\n"
|
||||
"P00 TRACE: " TEST_PGB_PATH "/test/src/module/common/debugOnTest::testFunction2: => void\n"
|
||||
"P00 DEBUG: " TEST_PGB_PATH "/test/src/module/common/debugOnTest::testFunction1: => 1");
|
||||
|
||||
testBoolP = NULL;
|
||||
testVoidP = (void *)1;
|
||||
@ -147,11 +147,11 @@ testRun(void)
|
||||
testFunction1(99, false, testBoolP, testBoolPP, testVoidP, 1.17, 0755);
|
||||
|
||||
harnessLogResult(
|
||||
"P00 DEBUG: test/module/common/debugOnTest::testFunction1: (paramInt: 99, paramBool: false, paramBoolP: null"
|
||||
", paramBoolPP: *null, paramVoidP: *void, paramDouble: 1.17, paramMode: 0755)\n"
|
||||
"P00 TRACE: test/module/common/debugOnTest::testFunction2: (void)\n"
|
||||
"P00 TRACE: test/module/common/debugOnTest::testFunction2: => void\n"
|
||||
"P00 DEBUG: test/module/common/debugOnTest::testFunction1: => 1");
|
||||
"P00 DEBUG: " TEST_PGB_PATH "/test/src/module/common/debugOnTest::testFunction1: (paramInt: 99, paramBool: false,"
|
||||
" paramBoolP: null, paramBoolPP: *null, paramVoidP: *void, paramDouble: 1.17, paramMode: 0755)\n"
|
||||
"P00 TRACE: " TEST_PGB_PATH "/test/src/module/common/debugOnTest::testFunction2: (void)\n"
|
||||
"P00 TRACE: " TEST_PGB_PATH "/test/src/module/common/debugOnTest::testFunction2: => void\n"
|
||||
"P00 DEBUG: " TEST_PGB_PATH "/test/src/module/common/debugOnTest::testFunction1: => 1");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
harnessLogLevelReset();
|
||||
|
@ -183,12 +183,14 @@ testRun(void)
|
||||
CATCH(AssertError)
|
||||
{
|
||||
assert(errorCode() == AssertError.code);
|
||||
assert(strcmp(errorFileName(), "test/module/common/errorTest.c") == 0);
|
||||
assert(strcmp(errorFileName(), TEST_PGB_PATH "/test/src/module/common/errorTest.c") == 0);
|
||||
assert(strcmp(errorFunctionName(), "testTryRecurse") == 0);
|
||||
assert(errorFileLine() == 29);
|
||||
assert(
|
||||
strcmp(errorStackTrace(),
|
||||
"test/module/common/errorTest:testTryRecurse:29:(test build required for parameters)") == 0);
|
||||
strcmp(
|
||||
errorStackTrace(),
|
||||
TEST_PGB_PATH "/test/src/module/common/errorTest:testTryRecurse:29:(test build required for parameters)")
|
||||
== 0);
|
||||
assert(strcmp(errorMessage(), "too many nested try blocks") == 0);
|
||||
assert(strcmp(errorName(), AssertError.name) == 0);
|
||||
assert(errorType() == &AssertError);
|
||||
|
@ -95,7 +95,7 @@ testRun(void)
|
||||
{
|
||||
exitSafe(0, true, signalTypeNone);
|
||||
harnessLogResult(
|
||||
"P00 DEBUG: common/exit::exitSafe: (result: 0, error: true, signalType: 0)\n"
|
||||
"P00 DEBUG: " TEST_PGB_PATH "/src/common/exit::exitSafe: (result: 0, error: true, signalType: 0)\n"
|
||||
"P00 ERROR: [122]: test debug error message\n"
|
||||
" --------------------------------------------------------------------\n"
|
||||
" If SUBMITTING AN ISSUE please provide the following information:\n"
|
||||
@ -105,13 +105,13 @@ testRun(void)
|
||||
" options: --exec-id=1-test --process-max=4 --stanza=test\n"
|
||||
" \n"
|
||||
" stack trace:\n"
|
||||
" test/module/common/exitTest:testRun:92:(void)\n"
|
||||
" " TEST_PGB_PATH "/test/src/module/common/exitTest:testRun:92:(void)\n"
|
||||
" test:main:(argListSize: 1, argList: (char *[]))\n"
|
||||
" --------------------------------------------------------------------\n"
|
||||
"P00 INFO: archive-push:async command end: aborted with exception [122]\n"
|
||||
"P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)\n"
|
||||
"P00 DEBUG: common/lock::lockRelease: => false\n"
|
||||
"P00 DEBUG: common/exit::exitSafe: => 122");
|
||||
"P00 DEBUG: " TEST_PGB_PATH "/src/common/lock::lockRelease: (failOnNoLock: false)\n"
|
||||
"P00 DEBUG: " TEST_PGB_PATH "/src/common/lock::lockRelease: => false\n"
|
||||
"P00 DEBUG: " TEST_PGB_PATH "/src/common/exit::exitSafe: => 122");
|
||||
}
|
||||
TRY_END();
|
||||
|
||||
@ -135,7 +135,7 @@ testRun(void)
|
||||
" options: --exec-id=1-test --process-max=4 --stanza=test\n"
|
||||
" \n"
|
||||
" stack trace:\n"
|
||||
" test/module/common/exitTest:testRun:123:(void)\n"
|
||||
" " TEST_PGB_PATH "/test/src/module/common/exitTest:testRun:123:(void)\n"
|
||||
" test:main:(argListSize: 1, argList: (char *[]))\n"
|
||||
" --------------------------------------------------------------------\n"
|
||||
"P00 INFO: archive-push:async command end: aborted with exception [025]");
|
||||
|
@ -30,6 +30,9 @@ The test code is included directly so it can freely interact with the included C
|
||||
// Path where the test is running
|
||||
#define TEST_PATH "{[C_TEST_PATH]}"
|
||||
|
||||
// Path to source -- used to construct __FILENAME__ tests
|
||||
#define TEST_PGB_PATH "{[C_TEST_PGB_PATH]}"
|
||||
|
||||
#include "common/harnessDebug.h"
|
||||
#include "common/harnessTest.intern.h"
|
||||
|
||||
|
@ -753,7 +753,7 @@ eval
|
||||
($bDebugTestTrace ? ' -DDEBUG_TEST_TRACE' : '');
|
||||
my $strLdFlags = vmWithBackTrace($strBuildVM) && $bBackTrace ? '-lbacktrace' : '';
|
||||
my $strConfigOptions = (vmDebugIntegration($strBuildVM) ? ' --enable-test' : '');
|
||||
my $strBuildFlags = "CFLAGS=${strCFlags}\nLDFLAGS=${strLdFlags}\nCONFIGURE=${strConfigOptions}";
|
||||
my $strBuildFlags = "CFLAGS_EXTRA=${strCFlags}\nLDFLAGS_EXTRA=${strLdFlags}\nCONFIGURE=${strConfigOptions}";
|
||||
my $strBuildFlagFile = "${strBinPath}/${strBuildVM}/build.flags";
|
||||
|
||||
my $bBuildOptionsDiffer = buildPutDiffers($oStorageBackRest, $strBuildFlagFile, $strBuildFlags);
|
||||
@ -795,14 +795,15 @@ eval
|
||||
|
||||
executeTest(
|
||||
($strBuildVM ne VM_NONE ? 'docker exec -i -u ' . TEST_USER . ' test-build ' : '') .
|
||||
"bash -c 'cd ${strBuildPath} && ${strBackRestBase}/src/configure${strConfigOptions}'",
|
||||
"bash -c 'cd ${strBuildPath} && ${strBackRestBase}/src/configure -q${strConfigOptions}'",
|
||||
{bShowOutputAsync => $bLogDetail});
|
||||
}
|
||||
|
||||
executeTest(
|
||||
($strBuildVM ne VM_NONE ? 'docker exec -i -u ' . TEST_USER . ' test-build ' : '') .
|
||||
"${strMakeCmd} -j ${iBuildMax}" . ($bLogDetail ? '' : ' --silent') .
|
||||
" --directory ${strBuildPath} CFLAGS='${strCFlags}' LDFLAGS='${strLdFlags}'",
|
||||
"${strMakeCmd} -s -j ${iBuildMax}" . ($bLogDetail ? '' : ' --silent') .
|
||||
" --directory ${strBuildPath} CFLAGS_EXTRA='${strCFlags}'" .
|
||||
($strLdFlags ne '' ? " LDFLAGS_EXTRA='${strLdFlags}'" : ''),
|
||||
{bShowOutputAsync => $bLogDetail});
|
||||
|
||||
if ($strBuildVM ne VM_NONE)
|
||||
|
Loading…
Reference in New Issue
Block a user