Make TAP tests work on Windows.

On Windows, use listen_address=127.0.0.1 to allow TCP connections. We were
already using "pg_regress --config-auth" to set up HBA appropriately. The
standard_initdb helper function now sets up the server's
unix_socket_directories or listen_addresses in the config file, so that
they don't need to be specified in the pg_ctl command line anymore. That
way, the pg_ctl invocations in test programs don't need to differ between
Windows and Unix.

Add another helper function to configure the server's pg_hba.conf to allow
replication connections. The configuration is done similarly to "pg_regress
--config-auth": trust on domain sockets on Unix, and SSPI authentication on
Windows.

Replace calls to "cat" and "touch" programs with built-in perl code, as
those programs don't normally exist on Windows.

Add instructions in the docs on how to install IPC::Run on Windows. Adjust
vcregress.pl to not replace PERL5LIB completely in vcregress.pl, because
otherwise cannot install IPC::Run in a non-standard location easily.

Michael Paquier, reviewed by Noah Misch, some additional tweaking by me.
This commit is contained in:
Heikki Linnakangas 2015-07-29 19:17:02 +03:00
parent 5f1066074c
commit 13d856e177
9 changed files with 232 additions and 101 deletions

View File

@ -439,6 +439,7 @@ $ENV{CONFIG}="Debug";
<userinput>vcregress modulescheck</userinput>
<userinput>vcregress ecpgcheck</userinput>
<userinput>vcregress isolationcheck</userinput>
<userinput>vcregress tapcheck</userinput>
<userinput>vcregress upgradecheck</userinput>
</screen>
@ -451,6 +452,29 @@ $ENV{CONFIG}="Debug";
For more information about the regression tests, see
<xref linkend="regress">.
</para>
<para>
Running the TAP regression tests, with "vcregress tapcheck", requires an
additional Perl module to be installed:
<variablelist>
<varlistentry>
<term><productname>IPC::Run</productname></term>
<listitem><para>
As of this writing, <literal>IPC::Run</> is not included in the
ActiveState Perl installation, nor in the ActiveState Perl Package
Manager (PPM) library. To install, download the
<filename>IPC-Run-&lt;version&gt;.tar.gz</> source archive from CPAN,
at <ulink url="http://search.cpan.org/dist/IPC-Run/"></>, and
uncompress. Edit the <filename>buildenv.pl</> file, and add a PERL5LIB
variable to point to the <filename>lib</> subdirectory from the
extracted archive. For example:
<programlisting>
$ENV{PERL5LIB}=$ENV{PERL5LIB} . ';c:\IPC-Run-0.94\lib';
</programlisting>
</para></listitem>
</varlistentry>
</variablelist>
</para>
</sect2>
<sect2>

View File

@ -339,7 +339,7 @@ endef
define prove_check
rm -rf $(CURDIR)/tmp_check/log
cd $(srcdir) && TESTDIR='$(CURDIR)' $(with_temp_install) PGPORT='6$(DEF_PGPORT)' top_builddir='$(CURDIR)/$(top_builddir)' $(PROVE) $(PG_PROVE_FLAGS) $(PROVE_FLAGS) t/*.pl
cd $(srcdir) && TESTDIR='$(CURDIR)' $(with_temp_install) PGPORT='6$(DEF_PGPORT)' PG_REGRESS='$(CURDIR)/$(top_builddir)/src/test/regress/pg_regress' $(PROVE) $(PG_PROVE_FLAGS) $(PROVE_FLAGS) t/*.pl
endef
else

View File

@ -1,6 +1,7 @@
use strict;
use warnings;
use Cwd;
use Config;
use TestLib;
use Test::More tests => 51;
@ -25,11 +26,7 @@ if (open BADCHARS, ">>$tempdir/pgdata/FOO\xe0\xe0\xe0BAR")
close BADCHARS;
}
open HBA, ">>$tempdir/pgdata/pg_hba.conf";
print HBA "local replication all trust\n";
print HBA "host replication all 127.0.0.1/32 trust\n";
print HBA "host replication all ::1/128 trust\n";
close HBA;
configure_hba_for_replication "$tempdir/pgdata";
system_or_bail 'pg_ctl', '-D', "$tempdir/pgdata", 'reload';
command_fails(
@ -62,61 +59,6 @@ command_ok([ 'pg_basebackup', '-D', "$tempdir/tarbackup", '-Ft' ],
'tar format');
ok(-f "$tempdir/tarbackup/base.tar", 'backup tar was created');
my $superlongname = "superlongname_" . ("x" x 100);
system_or_bail 'touch', "$tempdir/pgdata/$superlongname";
command_fails([ 'pg_basebackup', '-D', "$tempdir/tarbackup_l1", '-Ft' ],
'pg_basebackup tar with long name fails');
unlink "$tempdir/pgdata/$superlongname";
# Create a temporary directory in the system location and symlink it
# to our physical temp location. That way we can use shorter names
# for the tablespace directories, which hopefully won't run afoul of
# the 99 character length limit.
my $shorter_tempdir = tempdir_short . "/tempdir";
symlink "$tempdir", $shorter_tempdir;
mkdir "$tempdir/tblspc1";
psql 'postgres',
"CREATE TABLESPACE tblspc1 LOCATION '$shorter_tempdir/tblspc1';";
psql 'postgres', "CREATE TABLE test1 (a int) TABLESPACE tblspc1;";
command_ok([ 'pg_basebackup', '-D', "$tempdir/tarbackup2", '-Ft' ],
'tar format with tablespaces');
ok(-f "$tempdir/tarbackup2/base.tar", 'backup tar was created');
my @tblspc_tars = glob "$tempdir/tarbackup2/[0-9]*.tar";
is(scalar(@tblspc_tars), 1, 'one tablespace tar was created');
command_fails(
[ 'pg_basebackup', '-D', "$tempdir/backup1", '-Fp' ],
'plain format with tablespaces fails without tablespace mapping');
command_ok(
[ 'pg_basebackup', '-D', "$tempdir/backup1", '-Fp',
"-T$shorter_tempdir/tblspc1=$tempdir/tbackup/tblspc1" ],
'plain format with tablespaces succeeds with tablespace mapping');
ok(-d "$tempdir/tbackup/tblspc1", 'tablespace was relocated');
opendir(my $dh, "$tempdir/pgdata/pg_tblspc") or die;
ok( ( grep {
-l "$tempdir/backup1/pg_tblspc/$_"
and readlink "$tempdir/backup1/pg_tblspc/$_" eq
"$tempdir/tbackup/tblspc1"
} readdir($dh)),
"tablespace symlink was updated");
closedir $dh;
mkdir "$tempdir/tbl=spc2";
psql 'postgres', "DROP TABLE test1;";
psql 'postgres', "DROP TABLESPACE tblspc1;";
psql 'postgres',
"CREATE TABLESPACE tblspc2 LOCATION '$shorter_tempdir/tbl=spc2';";
command_ok(
[ 'pg_basebackup', '-D', "$tempdir/backup3", '-Fp',
"-T$shorter_tempdir/tbl\\=spc2=$tempdir/tbackup/tbl\\=spc2" ],
'mapping tablespace with = sign in path');
ok(-d "$tempdir/tbackup/tbl=spc2", 'tablespace with = sign was relocated');
psql 'postgres', "DROP TABLESPACE tblspc2;";
command_fails(
[ 'pg_basebackup', '-D', "$tempdir/backup_foo", '-Fp', "-T=/foo" ],
'-T with empty old directory fails');
@ -137,12 +79,75 @@ command_fails(
[ 'pg_basebackup', '-D', "$tempdir/backup_foo", '-Fp', "-Tfoo" ],
'-T with invalid format fails');
mkdir "$tempdir/$superlongname";
psql 'postgres',
"CREATE TABLESPACE tblspc3 LOCATION '$tempdir/$superlongname';";
command_ok([ 'pg_basebackup', '-D', "$tempdir/tarbackup_l3", '-Ft' ],
'pg_basebackup tar with long symlink target');
psql 'postgres', "DROP TABLESPACE tblspc3;";
# Tar format doesn't support filenames longer than 100 bytes.
my $superlongname = "superlongname_" . ("x" x 100);
my $superlongpath = "$tempdir/pgdata/$superlongname";
open FILE, ">$superlongpath" or die "unable to create file $superlongpath";
close FILE;
command_fails([ 'pg_basebackup', '-D', "$tempdir/tarbackup_l1", '-Ft' ],
'pg_basebackup tar with long name fails');
unlink "$tempdir/pgdata/$superlongname";
# The following tests test symlinks. Windows doesn't have symlinks, so
# skip on Windows.
SKIP: {
skip "symlinks not supported on Windows", 10 if ($Config{osname} eq "MSWin32");
# Create a temporary directory in the system location and symlink it
# to our physical temp location. That way we can use shorter names
# for the tablespace directories, which hopefully won't run afoul of
# the 99 character length limit.
my $shorter_tempdir = tempdir_short . "/tempdir";
symlink "$tempdir", $shorter_tempdir;
mkdir "$tempdir/tblspc1";
psql 'postgres',
"CREATE TABLESPACE tblspc1 LOCATION '$shorter_tempdir/tblspc1';";
psql 'postgres', "CREATE TABLE test1 (a int) TABLESPACE tblspc1;";
command_ok([ 'pg_basebackup', '-D', "$tempdir/tarbackup2", '-Ft' ],
'tar format with tablespaces');
ok(-f "$tempdir/tarbackup2/base.tar", 'backup tar was created');
my @tblspc_tars = glob "$tempdir/tarbackup2/[0-9]*.tar";
is(scalar(@tblspc_tars), 1, 'one tablespace tar was created');
command_fails(
[ 'pg_basebackup', '-D', "$tempdir/backup1", '-Fp' ],
'plain format with tablespaces fails without tablespace mapping');
command_ok(
[ 'pg_basebackup', '-D', "$tempdir/backup1", '-Fp',
"-T$shorter_tempdir/tblspc1=$tempdir/tbackup/tblspc1" ],
'plain format with tablespaces succeeds with tablespace mapping');
ok(-d "$tempdir/tbackup/tblspc1", 'tablespace was relocated');
opendir(my $dh, "$tempdir/pgdata/pg_tblspc") or die;
ok( ( grep {
-l "$tempdir/backup1/pg_tblspc/$_"
and readlink "$tempdir/backup1/pg_tblspc/$_" eq
"$tempdir/tbackup/tblspc1"
} readdir($dh)),
"tablespace symlink was updated");
closedir $dh;
mkdir "$tempdir/tbl=spc2";
psql 'postgres', "DROP TABLE test1;";
psql 'postgres', "DROP TABLESPACE tblspc1;";
psql 'postgres',
"CREATE TABLESPACE tblspc2 LOCATION '$shorter_tempdir/tbl=spc2';";
command_ok(
[ 'pg_basebackup', '-D', "$tempdir/backup3", '-Fp',
"-T$shorter_tempdir/tbl\\=spc2=$tempdir/tbackup/tbl\\=spc2" ],
'mapping tablespace with = sign in path');
ok(-d "$tempdir/tbackup/tbl=spc2", 'tablespace with = sign was relocated');
psql 'postgres', "DROP TABLESPACE tblspc2;";
mkdir "$tempdir/$superlongname";
psql 'postgres',
"CREATE TABLESPACE tblspc3 LOCATION '$tempdir/$superlongname';";
command_ok([ 'pg_basebackup', '-D', "$tempdir/tarbackup_l3", '-Ft' ],
'pg_basebackup tar with long symlink target');
psql 'postgres', "DROP TABLESPACE tblspc3;";
}
command_ok([ 'pg_basebackup', '-D', "$tempdir/backupR", '-R' ],
'pg_basebackup -R runs');
@ -169,7 +174,7 @@ is($lsn, '', 'restart LSN of new slot is null');
command_ok([ 'pg_basebackup', '-D', "$tempdir/backupxs_sl", '-X', 'stream', '-S', 'slot1' ],
'pg_basebackup -X stream with replication slot runs');
$lsn = psql 'postgres', q{SELECT restart_lsn FROM pg_replication_slots WHERE slot_name = 'slot1'};
like($lsn, qr!^0/[0-9A-Z]{8}$!, 'restart LSN of slot has advanced');
like($lsn, qr!^0/[0-9A-Z]{7,8}$!, 'restart LSN of slot has advanced');
command_ok([ 'pg_basebackup', '-D', "$tempdir/backupxs_sl_R", '-X', 'stream', '-S', 'slot1', '-R' ],
'pg_basebackup with replication slot and -R runs');

View File

@ -1,5 +1,6 @@
use strict;
use warnings;
use Config;
use TestLib;
use Test::More tests => 17;
@ -15,12 +16,19 @@ command_exit_is([ 'pg_ctl', 'start', '-D', "$tempdir/nonexistent" ],
command_ok([ 'pg_ctl', 'initdb', '-D', "$tempdir/data" ], 'pg_ctl initdb');
command_ok(
[ "$ENV{top_builddir}/src/test/regress/pg_regress", '--config-auth',
[ $ENV{PG_REGRESS}, '--config-auth',
"$tempdir/data" ],
'configure authentication');
open CONF, ">>$tempdir/data/postgresql.conf";
print CONF "listen_addresses = ''\n";
print CONF "unix_socket_directories = '$tempdir_short'\n";
if ($Config{osname} ne "MSWin32")
{
print CONF "listen_addresses = ''\n";
print CONF "unix_socket_directories = '$tempdir_short'\n";
}
else
{
print CONF "listen_addresses = '127.0.0.1'\n";
}
close CONF;
command_ok([ 'pg_ctl', 'start', '-D', "$tempdir/data", '-w' ],
'pg_ctl start -w');

View File

@ -10,10 +10,6 @@ command_exit_is([ 'pg_ctl', 'status', '-D', "$tempdir/nonexistent" ],
4, 'pg_ctl status with nonexistent directory');
standard_initdb "$tempdir/data";
open CONF, ">>$tempdir/data/postgresql.conf";
print CONF "listen_addresses = ''\n";
print CONF "unix_socket_directories = '$tempdir_short'\n";
close CONF;
command_exit_is([ 'pg_ctl', 'status', '-D', "$tempdir/data" ],
3, 'pg_ctl status with server not running');

View File

@ -192,20 +192,15 @@ max_connections = 10
));
# Accept replication connections on master
append_to_file(
"$test_master_datadir/pg_hba.conf", qq(
local replication all trust
));
configure_hba_for_replication $test_master_datadir;
system_or_bail('pg_ctl' , '-w',
'-D' , $test_master_datadir,
'-l', "$log_path/master.log",
"-o", "-k $tempdir_short --listen-addresses='' -p $port_master",
'start');
"-o", "-p $port_master", 'start');
#### Now run the test-specific parts to initialize the master before setting
# up standby
$ENV{PGHOST} = $tempdir_short;
}
sub create_standby
@ -227,8 +222,7 @@ recovery_target_timeline='latest'
# Start standby
system_or_bail('pg_ctl', '-w', '-D', $test_standby_datadir,
'-l', "$log_path/standby.log",
'-o', "-k $tempdir_short --listen-addresses='' -p $port_standby",
'start');
'-o', "-p $port_standby", 'start');
# Wait until the standby has caught up with the primary, by polling
# pg_stat_replication.
@ -264,7 +258,7 @@ sub run_pg_rewind
my $test_mode = shift;
# Stop the master and be ready to perform the rewind
system_or_bail('pg_ctl', '-D', $test_master_datadir, 'stop', '-m', 'fast');
system_or_bail('pg_ctl', '-D', $test_master_datadir, '-m', 'fast', 'stop');
# At this point, the rewind processing is ready to run.
# We now have a very simple scenario with a few diverged WAL record.
@ -282,8 +276,8 @@ sub run_pg_rewind
{
# Do rewind using a local pgdata as source
# Stop the master and be ready to perform the rewind
system_or_bail('pg_ctl', '-D', $test_standby_datadir, 'stop',
'-m', 'fast');
system_or_bail('pg_ctl', '-D', $test_standby_datadir,
'-m', 'fast', 'stop');
command_ok(['pg_rewind',
"--debug",
"--source-pgdata=$test_standby_datadir",
@ -323,8 +317,7 @@ recovery_target_timeline='latest'
# Restart the master to check that rewind went correctly
system_or_bail('pg_ctl', '-w', '-D', $test_master_datadir,
'-l', "$log_path/master.log",
'-o', "-k $tempdir_short --listen-addresses='' -p $port_master",
'start');
'-o', "-p $port_master", 'start');
#### Now run the test-specific parts to check the result
}

View File

@ -3,11 +3,13 @@ package TestLib;
use strict;
use warnings;
use Config;
use Exporter 'import';
our @EXPORT = qw(
tempdir
tempdir_short
standard_initdb
configure_hba_for_replication
start_test_server
restart_test_server
psql
@ -119,29 +121,74 @@ sub tempdir_short
return File::Temp::tempdir(CLEANUP => 1);
}
# Initialize a new cluster for testing.
#
# The PGHOST environment variable is set to connect to the new cluster.
#
# Authentication is set up so that only the current OS user can access the
# cluster. On Unix, we use Unix domain socket connections, with the socket in
# a directory that's only accessible to the current user to ensure that.
# On Windows, we use SSPI authentication to ensure the same (by pg_regress
# --config-auth).
sub standard_initdb
{
my $pgdata = shift;
system_or_bail('initdb', '-D', "$pgdata", '-A' , 'trust', '-N');
system_or_bail("$ENV{top_builddir}/src/test/regress/pg_regress",
'--config-auth', $pgdata);
system_or_bail($ENV{PG_REGRESS}, '--config-auth', $pgdata);
my $tempdir_short = tempdir_short;
open CONF, ">>$pgdata/postgresql.conf";
print CONF "\n# Added by TestLib.pm)\n";
if ($Config{osname} eq "MSWin32")
{
print CONF "listen_addresses = '127.0.0.1'\n";
}
else
{
print CONF "unix_socket_directories = '$tempdir_short'\n";
print CONF "listen_addresses = ''\n";
}
close CONF;
$ENV{PGHOST} = ($Config{osname} eq "MSWin32") ? "127.0.0.1" : $tempdir_short;
}
# Set up the cluster to allow replication connections, in the same way that
# standard_initdb does for normal connections.
sub configure_hba_for_replication
{
my $pgdata = shift;
open HBA, ">>$pgdata/pg_hba.conf";
print HBA "\n# Allow replication (set up by TestLib.pm)\n";
if ($Config{osname} ne "MSWin32")
{
print HBA "local replication all trust\n";
}
else
{
print HBA "host replication all 127.0.0.1/32 sspi include_realm=1 map=regress\n";
}
close HBA;
}
my ($test_server_datadir, $test_server_logfile);
# Initialize a new cluster for testing in given directory, and start it.
sub start_test_server
{
my ($tempdir) = @_;
my $ret;
my $tempdir_short = tempdir_short;
print("### Starting test server in $tempdir\n");
standard_initdb "$tempdir/pgdata";
$ret = system_log('pg_ctl', '-D', "$tempdir/pgdata", '-w', '-l',
"$log_path/postmaster.log", '-o',
"--fsync=off -k \"$tempdir_short\" --listen-addresses='' --log-statement=all",
'start');
"$log_path/postmaster.log", '-o', "--fsync=off --log-statement=all",
'start');
if ($ret != 0)
{
print "# pg_ctl failed; logfile:\n";
@ -149,7 +196,6 @@ sub start_test_server
BAIL_OUT("pg_ctl failed");
}
$ENV{PGHOST} = $tempdir_short;
$test_server_datadir = "$tempdir/pgdata";
$test_server_logfile = "$log_path/postmaster.log";
}
@ -242,7 +288,17 @@ sub command_exit_is
print("# Running: " . join(" ", @{$cmd}) ."\n");
my $h = start $cmd;
$h->finish();
is($h->result(0), $expected, $test_name);
# On Windows, the exit status of the process is returned directly as the
# process's exit code, while on Unix, it's returned in the high bits
# of the exit code (see WEXITSTATUS macro in the standard <sys/wait.h>
# header file). IPC::Run's result function always returns exit code >> 8,
# assuming the Unix convention, which will always return 0 on Windows as
# long as the process was not terminated by an exception. To work around
# that, use $h->full_result on Windows instead.
my $result = ($Config{osname} eq "MSWin32") ?
($h->full_results)[0] : $h->result(0);
is($result, $expected, $test_name);
}
sub program_help_ok
@ -295,7 +351,7 @@ sub issues_sql_like
truncate $test_server_logfile, 0;
my $result = run_log($cmd);
ok($result, "@$cmd exit code 0");
my $log = `cat '$test_server_logfile'`;
my $log = slurp_file($test_server_logfile);
like($log, $expected_sql, "$test_name: SQL found in server log");
}

View File

@ -88,6 +88,13 @@ if exist src\test\regress\regress.dll del /q src\test\regress\regress.dll
if exist src\test\regress\refint.dll del /q src\test\regress\refint.dll
if exist src\test\regress\autoinc.dll del /q src\test\regress\autoinc.dll
if exist src\bin\initdb\tmp_check rd /s /q src\bin\initdb\tmp_check
if exist src\bin\pg_basebackup\tmp_check rd /s /q src\bin\pg_basebackup\tmp_check
if exist src\bin\pg_config\tmp_check rd /s /q src\bin\pg_config\tmp_check
if exist src\bin\pg_ctl\tmp_check rd /s /q src\bin\pg_ctl\tmp_check
if exist src\bin\pg_rewind\tmp_check rd /s /q src\bin\pg_rewind\tmp_check
if exist src\bin\scripts\tmp_check rd /s /q src\bin\scripts\tmp_check
REM Clean up datafiles built with contrib
REM cd contrib
REM for /r %%f in (*.sql) do if exist %%f.in del %%f

View File

@ -7,7 +7,9 @@ use strict;
our $config;
use Cwd;
use File::Basename;
use File::Copy;
use File::Find ();
use Install qw(Install);
@ -32,7 +34,7 @@ if (-e "src/tools/msvc/buildenv.pl")
my $what = shift || "";
if ($what =~
/^(check|installcheck|plcheck|contribcheck|modulescheck|ecpgcheck|isolationcheck|upgradecheck)$/i
/^(check|installcheck|plcheck|contribcheck|modulescheck|ecpgcheck|isolationcheck|upgradecheck|tapcheck)$/i
)
{
$what = uc $what;
@ -59,7 +61,7 @@ unless ($schedule)
$schedule = "parallel" if ($what eq 'CHECK' || $what =~ /PARALLEL/);
}
$ENV{PERL5LIB} = "$topdir/src/tools/msvc";
$ENV{PERL5LIB} = "$topdir/src/tools/msvc;$ENV{PERL5LIB}";
my $maxconn = "";
$maxconn = "--max_connections=$ENV{MAX_CONNECTIONS}"
@ -79,6 +81,7 @@ my %command = (
CONTRIBCHECK => \&contribcheck,
MODULESCHECK => \&modulescheck,
ISOLATIONCHECK => \&isolationcheck,
TAPCHECK => \&tapcheck,
UPGRADECHECK => \&upgradecheck,);
my $proc = $command{$what};
@ -172,6 +175,45 @@ sub isolationcheck
exit $status if $status;
}
sub tapcheck
{
InstallTemp();
my @args = ( "prove", "--verbose", "t/*.pl");
$ENV{PATH} = "$tmp_installdir/bin;$ENV{PATH}";
$ENV{PERL5LIB} = "$topdir/src/test/perl;$ENV{PERL5LIB}";
$ENV{PG_REGRESS} = "$topdir/$Config/pg_regress/pg_regress";
# Find out all the existing TAP tests by looking for t/ directories
# in the tree.
my $tap_dirs = [];
my @top_dir = ($topdir);
File::Find::find(
{ wanted => sub {
/^t\z/s
&& push(@$tap_dirs, $File::Find::name);
}
},
@top_dir);
# Process each test
foreach my $test_path (@$tap_dirs)
{
# Like on Unix "make check-world", don't run the SSL test suite
# automatically.
next if ($test_path =~ /\/src\/test\/ssl\//);
my $dir = dirname($test_path);
chdir $dir;
# Reset those values, they may have been changed by another test.
$ENV{TESTDIR} = "$dir";
system(@args);
my $status = $? >> 8;
exit $status if $status;
}
}
sub plcheck
{
chdir $startdir;