1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-07-01 00:25:06 +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:
David Steele
2021-01-24 16:24:14 -05:00
parent ef2dc6d3f4
commit 4e8d469f4d
10 changed files with 299 additions and 459 deletions

View File

@ -12,17 +12,16 @@ auto_cancellation: $CIRRUS_BRANCH != 'integration'
freebsd_12_task: freebsd_12_task:
freebsd_instance: freebsd_instance:
image_family: freebsd-12-1 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: script:
- cd ${CIRRUS_WORKING_DIR}/src && ./configure - 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
- gmake -s -C ${CIRRUS_WORKING_DIR}/src
- ${CIRRUS_WORKING_DIR}/src/pgbackrest
debug_script: debug_script:
- ls -lah ${CIRRUS_WORKING_DIR} - ls -lah ${CIRRUS_WORKING_DIR}
- cat ${CIRRUS_WORKING_DIR}/src/Makefile
# MacOS Catalina # MacOS Catalina
# ---------------------------------------------------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------------------------------------------------
@ -33,14 +32,14 @@ macos_catalina_task:
environment: environment:
LDFLAGS: -L/usr/local/opt/openssl@1.1/lib -L/usr/local/opt/libpq/lib -L/usr/local/opt/libxml2/lib 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 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: script:
- cd ${CIRRUS_WORKING_DIR}/src && ./configure - ${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
- make -s -C ${CIRRUS_WORKING_DIR}/src
- ${CIRRUS_WORKING_DIR}/src/pgbackrest
debug_script: debug_script:
- ls -lah ${CIRRUS_WORKING_DIR} - ls -lah ${CIRRUS_WORKING_DIR}
- cat ${CIRRUS_WORKING_DIR}/src/Makefile

View File

@ -175,9 +175,9 @@ SRCS = \
# Compiler options # Compiler options
#################################################################################################################################### ####################################################################################################################################
CC = @CC@ CC = @CC@
CFLAGS = @CFLAGS@ CFLAGS = $(CFLAGS_EXTRA) @CFLAGS@
CPPFLAGS = @CPPFLAGS@ -I@srcdir@ CPPFLAGS = @CPPFLAGS@ -I@srcdir@
LDFLAGS = @LDFLAGS@ LDFLAGS = $(LDFLAGS_EXTRA) @LDFLAGS@
LIBS = @LIBS@ LIBS = @LIBS@
#################################################################################################################################### ####################################################################################################################################

14
test/Vagrantfile vendored
View File

@ -136,7 +136,7 @@ Vagrant.configure(2) do |config|
#----------------------------------------------------------------------------------------------------------------------- #-----------------------------------------------------------------------------------------------------------------------
echo 'Install Build Tools' && date 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 echo 'Build End' && date
@ -145,16 +145,16 @@ Vagrant.configure(2) do |config|
# MacOS # 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
# 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/brew install libpq libxml2 # ~/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 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="-I${HOME?}/homebrew/opt/openssl@1.1/include -I/${HOME?}/homebrew/opt/libpq/include"
# export CPPFLAGS="${CPPFLAGS?} -I${HOME?}/homebrew/opt/libxml2/include/libxml2" # export CPPFLAGS="${CPPFLAGS?} -I${HOME?}/homebrew/opt/libxml2/include/libxml2"
# # export PERL5LIB=~/homebrew/perl5/lib/perl5"${PERL5LIB:+:${PERL5LIB}}"
# cd [repo]/src && ./configure && make
# Don't share the default vagrant folder # Don't share the default vagrant folder
config.vm.synced_folder ".", "/vagrant", disabled: true config.vm.synced_folder ".", "/vagrant", disabled: true

View File

@ -97,195 +97,3 @@ sub buildLastModTime
} }
push @EXPORT, qw(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;

View File

@ -16,7 +16,7 @@ use Exporter qw(import);
our @EXPORT = qw(); our @EXPORT = qw();
use File::Basename qw(dirname basename); use File::Basename qw(dirname basename);
use POSIX qw(ceil); use POSIX qw(ceil);
use Time::HiRes qw(gettimeofday); use Time::HiRes qw(gettimeofday usleep);
use pgBackRestDoc::Common::Exception; use pgBackRestDoc::Common::Exception;
use pgBackRestDoc::Common::Log; use pgBackRestDoc::Common::Log;
@ -33,11 +33,6 @@ use pgBackRestTest::Common::ListTest;
use pgBackRestTest::Common::RunTest; use pgBackRestTest::Common::RunTest;
use pgBackRestTest::Common::VmTest; use pgBackRestTest::Common::VmTest;
####################################################################################################################################
# Has the C build directory been initialized yet?
####################################################################################################################################
my $rhBuildInit = undef;
#################################################################################################################################### ####################################################################################################################################
# new # new
#################################################################################################################################### ####################################################################################################################################
@ -126,6 +121,7 @@ sub new
# Setup the path where gcc coverage will be performed # Setup the path where gcc coverage will be performed
$self->{strGCovPath} = "$self->{strTestPath}/gcov-$self->{oTest}->{&TEST_VM}-$self->{iVmIdx}"; $self->{strGCovPath} = "$self->{strTestPath}/gcov-$self->{oTest}->{&TEST_VM}-$self->{iVmIdx}";
$self->{strDataPath} = "$self->{strTestPath}/data-$self->{iVmIdx}"; $self->{strDataPath} = "$self->{strTestPath}/data-$self->{iVmIdx}";
$self->{strRepoPath} = "$self->{strTestPath}/repo";
# Return from function and log return values if any # Return from function and log return values if any
return logDebugReturn return logDebugReturn
@ -215,29 +211,11 @@ sub run
($self->{oTest}->{&TEST_C} ? " -v $self->{strGCovPath}:$self->{strGCovPath}" : '') . ($self->{oTest}->{&TEST_C} ? " -v $self->{strGCovPath}:$self->{strGCovPath}" : '') .
($self->{oTest}->{&TEST_C} ? " -v $self->{strDataPath}:$self->{strDataPath}" : '') . ($self->{oTest}->{&TEST_C} ? " -v $self->{strDataPath}:$self->{strDataPath}" : '') .
" -v $self->{strBackRestBase}:$self->{strBackRestBase}" . " -v $self->{strBackRestBase}:$self->{strBackRestBase}" .
" -v $self->{strRepoPath}:$self->{strRepoPath}:ro" .
($self->{oTest}->{&TEST_BIN_REQ} ? " -v ${strBinPath}:${strBinPath}:ro" : '') . ($self->{oTest}->{&TEST_BIN_REQ} ? " -v ${strBinPath}:${strBinPath}:ro" : '') .
' ' . containerRepo() . ':' . $self->{oTest}->{&TEST_VM} . '-test', ' ' . containerRepo() . ':' . $self->{oTest}->{&TEST_VM} . '-test',
{bSuppressStdErr => true}); {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; $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}) if (!$self->{bDryRun} || $self->{bVmOut})
{ {
my $strCommand = undef; # Command to run test
# If testing C code # If testing C code
if ($self->{oTest}->{&TEST_C}) 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 $hTest = (testDefModuleTest($self->{oTest}->{&TEST_MODULE}, $self->{oTest}->{&TEST_NAME}));
my $hTestCoverage = $hTest->{&TESTDEF_COVERAGE}; 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); my $strFileNoExt = substr($strFile, 0, length($strFile) - 2);
# Skip all files except .c files (including .auto.c) # Skip all files except .c files (including .auto.c and .vendor.c)
next if $strFile !~ /(?<!\.auto)\.c$/; next if $strFile !~ /(?<!\.auto)\.c$/ || $strFile !~ /(?<!\.vendor)\.c$/;
# Skip all files except .c files (including .vendor.c)
next if $strFile !~ /(?<!\.vendor)\.c$/;
# ??? Skip main for now until the function can be renamed to allow unit testing # ??? Skip main for now until the function can be renamed to allow unit testing
next if $strFile =~ /main\.c$/; next if $strFile =~ /main\.c$/;
# Skip test.c -- it will be added manually at the end if (!defined($hTestCoverage->{$strFileNoExt}) && !grep(/^$strFileNoExt$/, @{$hTest->{&TESTDEF_INCLUDE}}))
next if $strFile =~ /test\.c$/;
if (!defined($hTestCoverage->{$strFileNoExt}) && !grep(/^$strFileNoExt$/, @{$hTest->{&TESTDEF_INCLUDE}}) &&
$strFile !~ /^test\/module\/[^\/]*\/.*Test\.c$/)
{ {
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 # Generate list of C files to include for testing
my $strTestDepend = ''; my $strTestDepend = '';
my $strTestFile = 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; my $strCInclude;
foreach my $strFile (sort(keys(%{$hTestCoverage}), @{$hTest->{&TESTDEF_INCLUDE}})) foreach my $strFile (sort(keys(%{$hTestCoverage}), @{$hTest->{&TESTDEF_INCLUDE}}))
@ -349,12 +435,12 @@ sub run
my $strCIncludeFile = "${strFile}.c"; my $strCIncludeFile = "${strFile}.c";
# If the C file does not exist use the header file instead # 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 # Error if code was expected
if ($hTestCoverage->{$strFile} ne TESTDEF_COVERAGE_NOCODE) 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"; $strCIncludeFile = "${strFile}.h";
@ -365,7 +451,7 @@ sub run
} }
# Update C test file with test module # 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)) if (defined($strCInclude))
{ {
@ -379,18 +465,6 @@ sub run
$strTestC =~ s/\{\[C\_TEST\_INCLUDE\]\}/\#include \"$strTestFile\"/g; $strTestC =~ s/\{\[C\_TEST\_INCLUDE\]\}/\#include \"$strTestFile\"/g;
$strTestDepend .= " ${strTestFile}"; $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 # Determine where the project exe is located
my $strProjectExePath = "$self->{strTestPath}/bin/$self->{oTest}->{&TEST_VM}/" . PROJECT_EXE; 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\_CONTAINER\]\}/$strContainer/g;
$strTestC =~ s/\{\[C\_TEST\_PROJECT\_EXE\]\}/$strProjectExePath/g; $strTestC =~ s/\{\[C\_TEST\_PROJECT\_EXE\]\}/$strProjectExePath/g;
$strTestC =~ s/\{\[C\_TEST\_PATH\]\}/$strTestPathC/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\_DATA_PATH\]\}/$self->{strDataPath}/g;
$strTestC =~ s/\{\[C\_TEST\_IDX\]\}/$self->{iVmIdx}/g; $strTestC =~ s/\{\[C\_TEST\_IDX\]\}/$self->{iVmIdx}/g;
$strTestC =~ s/\{\[C\_TEST\_REPO_PATH\]\}/$self->{strBackRestBase}/g; $strTestC =~ s/\{\[C\_TEST\_REPO_PATH\]\}/$self->{strBackRestBase}/g;
@ -446,135 +521,87 @@ sub run
} }
$strTestC =~ s/\{\[C\_TEST\_LIST\]\}/$strTestInit/g; $strTestC =~ s/\{\[C\_TEST\_LIST\]\}/$strTestInit/g;
buildPutDiffers($self->{oStorageTest}, "$self->{strGCovPath}/test.c", $strTestC);
# Create build.auto.h # Save test.c and make sure it gets a new timestamp
my $strBuildAutoH = # ------------------------------------------------------------------------------------------------------------------
"#define HAVE_STATIC_ASSERT\n" . my $strTestCFile = "$self->{strGCovPath}/test.c";
"#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";
buildPutDiffers($self->{oStorageTest}, "$self->{strGCovPath}/" . BUILD_AUTO_H, $strBuildAutoH); if (buildPutDiffers($self->{oStorageTest}, "$self->{strGCovPath}/test.c", $strTestC))
# Disable debug/coverage for performance and profile tests
my $bPerformance = $self->{oTest}->{&TEST_TYPE} eq TESTDEF_PERFORMANCE;
if ($bPerformance || $self->{bProfile})
{ {
$self->{bDebug} = false; # Get timestamp for test.bin if it existss
$self->{bDebugTestTrace} = false; my $oTestBinInfo = $self->{oStorageTest}->info("$self->{strGCovPath}/test.bin", {bIgnoreMissing => true});
$self->{bCoverageUnit} = false; my $iTestBinOriginalTime = defined($oTestBinInfo) ? $oTestBinInfo->mtime : 0;
# Get timestamp for test.c
my $iTestCNewTime = $self->{oStorageTest}->info($strTestCFile)->mtime;
# Is the timestamp for test.c newer than test.bin?
while ($iTestCNewTime <= $iTestBinOriginalTime)
{
# If not then sleep until the next second
my $iTimeToSleep = ($iTestBinOriginalTime + 1) - gettimeofday();
if ($iTimeToSleep > 0)
{
usleep($iTimeToSleep * 1000000);
} }
# When optimization is disabled add -ftree-coalesce-vars to make the compiler faster when available # Save the file again
my $strNoOptimizeFlags = '-O0' . ($self->{oTest}->{&TEST_VM} ne VM_U12 ? ' -ftree-coalesce-vars' : ''); $self->{oStorageTest}->put($self->{oStorageTest}->openWrite($strTestCFile), $strTestC);
$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}})
{
$strMakefile .=
' ' .
($rhDependencyTree->{$strDepend}{path} ne '' ? $rhDependencyTree->{$strDepend}{path} . '/' : '') .
$strDepend;
} }
$strMakefile .= # Create command
"\n" . # ------------------------------------------------------------------------------------------------------------------
"\t\$(CC) \$(COMMONFLAGS) \$(WARNINGFLAGS)" . # Build filename for valgrind suppressions
($strCFile =~ /^test\// ? " \$(HARNESSFLAGS)" : " \$(BUILDFLAGS)") . my $strValgrindSuppress = $self->{strRepoPath} . '/test/src/valgrind.suppress.' . $self->{oTest}->{&TEST_VM};
" -c $strCFile -o " . substr($strCFile, 0, length($strCFile) - 2) . ".o\n";
}
buildPutDiffers($self->{oStorageTest}, $self->{strGCovPath} . "/Makefile", $strMakefile); $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( my $oExec = new pgBackRestTest::Common::ExecuteTest(

View File

@ -120,11 +120,11 @@ testRun(void)
testFunction1(99, false, NULL, NULL, NULL, 1.17, 0755); testFunction1(99, false, NULL, NULL, NULL, 1.17, 0755);
harnessLogResult( harnessLogResult(
"P00 DEBUG: test/module/common/debugOnTest::testFunction1: (paramInt: 99, paramBool: false, paramBoolP: null" "P00 DEBUG: " TEST_PGB_PATH "/test/src/module/common/debugOnTest::testFunction1: (paramInt: 99, paramBool: false,"
", paramBoolPP: null, paramVoidP: null, paramDouble: 1.17, paramMode: 0755)\n" " paramBoolP: null, paramBoolPP: null, paramVoidP: null, paramDouble: 1.17, paramMode: 0755)\n"
"P00 TRACE: test/module/common/debugOnTest::testFunction2: (void)\n" "P00 TRACE: " TEST_PGB_PATH "/test/src/module/common/debugOnTest::testFunction2: (void)\n"
"P00 TRACE: test/module/common/debugOnTest::testFunction2: => void\n" "P00 TRACE: " TEST_PGB_PATH "/test/src/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: => 1");
// ------------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------------
bool testBool = true; bool testBool = true;
@ -135,11 +135,11 @@ testRun(void)
testFunction1(99, false, testBoolP, testBoolPP, testVoidP, 1.17, 0755); testFunction1(99, false, testBoolP, testBoolPP, testVoidP, 1.17, 0755);
harnessLogResult( harnessLogResult(
"P00 DEBUG: test/module/common/debugOnTest::testFunction1: (paramInt: 99, paramBool: false, paramBoolP: *true" "P00 DEBUG: " TEST_PGB_PATH "/test/src/module/common/debugOnTest::testFunction1: (paramInt: 99, paramBool: false,"
", paramBoolPP: **true, paramVoidP: null, paramDouble: 1.17, paramMode: 0755)\n" " paramBoolP: *true, paramBoolPP: **true, paramVoidP: null, paramDouble: 1.17, paramMode: 0755)\n"
"P00 TRACE: test/module/common/debugOnTest::testFunction2: (void)\n" "P00 TRACE: " TEST_PGB_PATH "/test/src/module/common/debugOnTest::testFunction2: (void)\n"
"P00 TRACE: test/module/common/debugOnTest::testFunction2: => void\n" "P00 TRACE: " TEST_PGB_PATH "/test/src/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: => 1");
testBoolP = NULL; testBoolP = NULL;
testVoidP = (void *)1; testVoidP = (void *)1;
@ -147,11 +147,11 @@ testRun(void)
testFunction1(99, false, testBoolP, testBoolPP, testVoidP, 1.17, 0755); testFunction1(99, false, testBoolP, testBoolPP, testVoidP, 1.17, 0755);
harnessLogResult( harnessLogResult(
"P00 DEBUG: test/module/common/debugOnTest::testFunction1: (paramInt: 99, paramBool: false, paramBoolP: null" "P00 DEBUG: " TEST_PGB_PATH "/test/src/module/common/debugOnTest::testFunction1: (paramInt: 99, paramBool: false,"
", paramBoolPP: *null, paramVoidP: *void, paramDouble: 1.17, paramMode: 0755)\n" " paramBoolP: null, paramBoolPP: *null, paramVoidP: *void, paramDouble: 1.17, paramMode: 0755)\n"
"P00 TRACE: test/module/common/debugOnTest::testFunction2: (void)\n" "P00 TRACE: " TEST_PGB_PATH "/test/src/module/common/debugOnTest::testFunction2: (void)\n"
"P00 TRACE: test/module/common/debugOnTest::testFunction2: => void\n" "P00 TRACE: " TEST_PGB_PATH "/test/src/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: => 1");
// ------------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------------
harnessLogLevelReset(); harnessLogLevelReset();

View File

@ -183,12 +183,14 @@ testRun(void)
CATCH(AssertError) CATCH(AssertError)
{ {
assert(errorCode() == AssertError.code); 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(strcmp(errorFunctionName(), "testTryRecurse") == 0);
assert(errorFileLine() == 29); assert(errorFileLine() == 29);
assert( assert(
strcmp(errorStackTrace(), strcmp(
"test/module/common/errorTest:testTryRecurse:29:(test build required for parameters)") == 0); 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(errorMessage(), "too many nested try blocks") == 0);
assert(strcmp(errorName(), AssertError.name) == 0); assert(strcmp(errorName(), AssertError.name) == 0);
assert(errorType() == &AssertError); assert(errorType() == &AssertError);

View File

@ -95,7 +95,7 @@ testRun(void)
{ {
exitSafe(0, true, signalTypeNone); exitSafe(0, true, signalTypeNone);
harnessLogResult( 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" "P00 ERROR: [122]: test debug error message\n"
" --------------------------------------------------------------------\n" " --------------------------------------------------------------------\n"
" If SUBMITTING AN ISSUE please provide the following information:\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" " options: --exec-id=1-test --process-max=4 --stanza=test\n"
" \n" " \n"
" stack trace:\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" " test:main:(argListSize: 1, argList: (char *[]))\n"
" --------------------------------------------------------------------\n" " --------------------------------------------------------------------\n"
"P00 INFO: archive-push:async command end: aborted with exception [122]\n" "P00 INFO: archive-push:async command end: aborted with exception [122]\n"
"P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)\n" "P00 DEBUG: " TEST_PGB_PATH "/src/common/lock::lockRelease: (failOnNoLock: false)\n"
"P00 DEBUG: common/lock::lockRelease: => false\n" "P00 DEBUG: " TEST_PGB_PATH "/src/common/lock::lockRelease: => false\n"
"P00 DEBUG: common/exit::exitSafe: => 122"); "P00 DEBUG: " TEST_PGB_PATH "/src/common/exit::exitSafe: => 122");
} }
TRY_END(); TRY_END();
@ -135,7 +135,7 @@ testRun(void)
" options: --exec-id=1-test --process-max=4 --stanza=test\n" " options: --exec-id=1-test --process-max=4 --stanza=test\n"
" \n" " \n"
" stack trace:\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" " test:main:(argListSize: 1, argList: (char *[]))\n"
" --------------------------------------------------------------------\n" " --------------------------------------------------------------------\n"
"P00 INFO: archive-push:async command end: aborted with exception [025]"); "P00 INFO: archive-push:async command end: aborted with exception [025]");

View File

@ -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 // Path where the test is running
#define TEST_PATH "{[C_TEST_PATH]}" #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/harnessDebug.h"
#include "common/harnessTest.intern.h" #include "common/harnessTest.intern.h"

View File

@ -753,7 +753,7 @@ eval
($bDebugTestTrace ? ' -DDEBUG_TEST_TRACE' : ''); ($bDebugTestTrace ? ' -DDEBUG_TEST_TRACE' : '');
my $strLdFlags = vmWithBackTrace($strBuildVM) && $bBackTrace ? '-lbacktrace' : ''; my $strLdFlags = vmWithBackTrace($strBuildVM) && $bBackTrace ? '-lbacktrace' : '';
my $strConfigOptions = (vmDebugIntegration($strBuildVM) ? ' --enable-test' : ''); 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 $strBuildFlagFile = "${strBinPath}/${strBuildVM}/build.flags";
my $bBuildOptionsDiffer = buildPutDiffers($oStorageBackRest, $strBuildFlagFile, $strBuildFlags); my $bBuildOptionsDiffer = buildPutDiffers($oStorageBackRest, $strBuildFlagFile, $strBuildFlags);
@ -795,14 +795,15 @@ eval
executeTest( executeTest(
($strBuildVM ne VM_NONE ? 'docker exec -i -u ' . TEST_USER . ' test-build ' : '') . ($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}); {bShowOutputAsync => $bLogDetail});
} }
executeTest( executeTest(
($strBuildVM ne VM_NONE ? 'docker exec -i -u ' . TEST_USER . ' test-build ' : '') . ($strBuildVM ne VM_NONE ? 'docker exec -i -u ' . TEST_USER . ' test-build ' : '') .
"${strMakeCmd} -j ${iBuildMax}" . ($bLogDetail ? '' : ' --silent') . "${strMakeCmd} -s -j ${iBuildMax}" . ($bLogDetail ? '' : ' --silent') .
" --directory ${strBuildPath} CFLAGS='${strCFlags}' LDFLAGS='${strLdFlags}'", " --directory ${strBuildPath} CFLAGS_EXTRA='${strCFlags}'" .
($strLdFlags ne '' ? " LDFLAGS_EXTRA='${strLdFlags}'" : ''),
{bShowOutputAsync => $bLogDetail}); {bShowOutputAsync => $bLogDetail});
if ($strBuildVM ne VM_NONE) if ($strBuildVM ne VM_NONE)