1
0
mirror of https://github.com/postgres/postgres.git synced 2025-05-05 09:19:17 +03:00
postgres/src/test/perl/TestLib.pm
Noah Misch 6b87d423dc Lock down regression testing temporary clusters on Windows.
Use SSPI authentication to allow connections exclusively from the OS
user that launched the test suite.  This closes on Windows the
vulnerability that commit be76a6d39e2832d4b88c0e1cc381aa44a7f86881
closed on other platforms.  Users of "make installcheck" or custom test
harnesses can run "pg_regress --config-auth=DATADIR" to activate the
same authentication configuration that "make check" would use.
Back-patch to 9.0 (all supported versions).

Security: CVE-2014-0067
2014-12-17 22:48:45 -05:00

215 lines
4.4 KiB
Perl

package TestLib;
use strict;
use warnings;
use Exporter 'import';
our @EXPORT = qw(
tempdir
tempdir_short
standard_initdb
start_test_server
restart_test_server
psql
system_or_bail
command_ok
command_fails
command_exit_is
program_help_ok
program_version_ok
program_options_handling_ok
command_like
issues_sql_like
);
use Cwd;
use File::Spec;
use File::Temp ();
use IPC::Run qw(run start);
use Test::More;
# Set to untranslated messages, to be able to compare program output
# with expected strings.
delete $ENV{LANGUAGE};
delete $ENV{LC_ALL};
$ENV{LC_MESSAGES} = 'C';
delete $ENV{PGCONNECT_TIMEOUT};
delete $ENV{PGDATA};
delete $ENV{PGDATABASE};
delete $ENV{PGHOSTADDR};
delete $ENV{PGREQUIRESSL};
delete $ENV{PGSERVICE};
delete $ENV{PGSSLMODE};
delete $ENV{PGUSER};
if (!$ENV{PGPORT})
{
$ENV{PGPORT} = 65432;
}
$ENV{PGPORT} = int($ENV{PGPORT}) % 65536;
#
# Helper functions
#
sub tempdir
{
return File::Temp::tempdir('tmp_testXXXX', DIR => $ENV{TESTDIR} || cwd(), CLEANUP => 1);
}
sub tempdir_short
{
# Use a separate temp dir outside the build tree for the
# Unix-domain socket, to avoid file name length issues.
return File::Temp::tempdir(CLEANUP => 1);
}
sub standard_initdb
{
my $pgdata = shift;
system_or_bail("initdb -D '$pgdata' -A trust -N >/dev/null");
system_or_bail("$ENV{top_srcdir}/src/test/regress/pg_regress",
'--config-auth', $pgdata);
}
my ($test_server_datadir, $test_server_logfile);
sub start_test_server
{
my ($tempdir) = @_;
my $ret;
my $tempdir_short = tempdir_short;
standard_initdb "$tempdir/pgdata";
$ret = system 'pg_ctl', '-D', "$tempdir/pgdata", '-s', '-w', '-l',
"$tempdir/logfile", '-o',
"--fsync=off -k $tempdir_short --listen-addresses='' --log-statement=all",
'start';
if ($ret != 0)
{
system('cat', "$tempdir/logfile");
BAIL_OUT("pg_ctl failed");
}
$ENV{PGHOST} = $tempdir_short;
$test_server_datadir = "$tempdir/pgdata";
$test_server_logfile = "$tempdir/logfile";
}
sub restart_test_server
{
system 'pg_ctl', '-s', '-D', $test_server_datadir, '-w', '-l',
$test_server_logfile, 'restart';
}
END
{
if ($test_server_datadir)
{
system 'pg_ctl', '-D', $test_server_datadir, '-s', '-w', '-m',
'immediate', 'stop';
}
}
sub psql
{
my ($dbname, $sql) = @_;
run [ 'psql', '-X', '-q', '-d', $dbname, '-f', '-' ], '<', \$sql or die;
}
sub system_or_bail
{
system(@_) == 0 or BAIL_OUT("system @_ failed: $?");
}
#
# Test functions
#
sub command_ok
{
my ($cmd, $test_name) = @_;
my $result = run $cmd, '>', File::Spec->devnull(), '2>',
File::Spec->devnull();
ok($result, $test_name);
}
sub command_fails
{
my ($cmd, $test_name) = @_;
my $result = run $cmd, '>', File::Spec->devnull(), '2>',
File::Spec->devnull();
ok(!$result, $test_name);
}
sub command_exit_is
{
my ($cmd, $expected, $test_name) = @_;
my $h = start $cmd, '>', File::Spec->devnull(), '2>',
File::Spec->devnull();
$h->finish();
is($h->result(0), $expected, $test_name);
}
sub program_help_ok
{
my ($cmd) = @_;
my ($stdout, $stderr);
my $result = run [ $cmd, '--help' ], '>', \$stdout, '2>', \$stderr;
ok($result, "$cmd --help exit code 0");
isnt($stdout, '', "$cmd --help goes to stdout");
is($stderr, '', "$cmd --help nothing to stderr");
}
sub program_version_ok
{
my ($cmd) = @_;
my ($stdout, $stderr);
my $result = run [ $cmd, '--version' ], '>', \$stdout, '2>', \$stderr;
ok($result, "$cmd --version exit code 0");
isnt($stdout, '', "$cmd --version goes to stdout");
is($stderr, '', "$cmd --version nothing to stderr");
}
sub program_options_handling_ok
{
my ($cmd) = @_;
my ($stdout, $stderr);
my $result = run [ $cmd, '--not-a-valid-option' ], '>', \$stdout, '2>', \$stderr;
ok(!$result, "$cmd with invalid option nonzero exit code");
isnt($stderr, '', "$cmd with invalid option prints error message");
}
sub command_like
{
my ($cmd, $expected_stdout, $test_name) = @_;
my ($stdout, $stderr);
my $result = run $cmd, '>', \$stdout, '2>', \$stderr;
ok($result, "@$cmd exit code 0");
is($stderr, '', "@$cmd no stderr");
like($stdout, $expected_stdout, "$test_name: matches");
}
sub issues_sql_like
{
my ($cmd, $expected_sql, $test_name) = @_;
my ($stdout, $stderr);
truncate $test_server_logfile, 0;
my $result = run $cmd, '>', \$stdout, '2>', \$stderr;
ok($result, "@$cmd exit code 0");
my $log = `cat '$test_server_logfile'`;
like($log, $expected_sql, "$test_name: SQL found in server log");
}
1;