mirror of
https://github.com/postgres/postgres.git
synced 2025-05-03 22:24:49 +03:00
Back-port of a part of commit 690ed2b76ab91eb79ea04ee2bfbdc8a2693f2a37 that I'd depended on without realizing that it was only added recently. Since it seems entirely likely that other such tests will need to be back-patched in future, providing the flag seems like a better answer than just putting a test in-line. Per buildfarm.
290 lines
6.3 KiB
Perl
290 lines
6.3 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
|
|
system_log
|
|
run_log
|
|
|
|
command_ok
|
|
command_fails
|
|
command_exit_is
|
|
program_help_ok
|
|
program_version_ok
|
|
program_options_handling_ok
|
|
command_like
|
|
issues_sql_like
|
|
|
|
$tmp_check
|
|
$log_path
|
|
$windows_os
|
|
);
|
|
|
|
use Cwd;
|
|
use File::Basename;
|
|
use File::Spec;
|
|
use File::Temp ();
|
|
use IPC::Run qw(run start);
|
|
|
|
use SimpleTee;
|
|
|
|
use Test::More;
|
|
|
|
our $windows_os = $Config{osname} eq 'MSWin32' || $Config{osname} eq 'msys';
|
|
|
|
# Open log file. For each test, the log file name uses the name of the
|
|
# file launching this module, without the .pl suffix.
|
|
our ($tmp_check, $log_path);
|
|
$tmp_check = $ENV{TESTDIR} ? "$ENV{TESTDIR}/tmp_check" : "tmp_check";
|
|
$log_path = "$tmp_check/log";
|
|
mkdir $tmp_check;
|
|
mkdir $log_path;
|
|
my $test_logfile = basename($0);
|
|
$test_logfile =~ s/\.[^.]+$//;
|
|
$test_logfile = "$log_path/regress_log_$test_logfile";
|
|
open TESTLOG, '>', $test_logfile or die "Cannot open STDOUT to logfile: $!";
|
|
|
|
# Hijack STDOUT and STDERR to the log file
|
|
open(ORIG_STDOUT, ">&STDOUT");
|
|
open(ORIG_STDERR, ">&STDERR");
|
|
open(STDOUT, ">&TESTLOG");
|
|
open(STDERR, ">&TESTLOG");
|
|
|
|
# The test output (ok ...) needs to be printed to the original STDOUT so
|
|
# that the 'prove' program can parse it, and display it to the user in
|
|
# real time. But also copy it to the log file, to provide more context
|
|
# in the log.
|
|
my $builder = Test::More->builder;
|
|
my $fh = $builder->output;
|
|
tie *$fh, "SimpleTee", *ORIG_STDOUT, *TESTLOG;
|
|
$fh = $builder->failure_output;
|
|
tie *$fh, "SimpleTee", *ORIG_STDERR, *TESTLOG;
|
|
|
|
# Enable auto-flushing for all the file handles. Stderr and stdout are
|
|
# redirected to the same file, and buffering causes the lines to appear
|
|
# in the log in confusing order.
|
|
autoflush STDOUT 1;
|
|
autoflush STDERR 1;
|
|
autoflush TESTLOG 1;
|
|
|
|
# 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');
|
|
system_or_bail("$ENV{top_builddir}/src/test/regress/pg_regress",
|
|
'--config-auth', $pgdata);
|
|
|
|
open CONF, ">>$pgdata/postgresql.conf";
|
|
print CONF "\n# Added by TestLib.pm)\n";
|
|
print CONF "fsync = off\n";
|
|
close CONF;
|
|
}
|
|
|
|
my ($test_server_datadir, $test_server_logfile);
|
|
|
|
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',
|
|
"-k \"$tempdir_short\" --listen-addresses='' --log-statement=all",
|
|
'start');
|
|
if ($ret != 0)
|
|
{
|
|
print "# pg_ctl failed; logfile:\n";
|
|
system('cat', "$log_path/postmaster.log");
|
|
BAIL_OUT("pg_ctl failed");
|
|
}
|
|
|
|
$ENV{PGHOST} = $tempdir_short;
|
|
$test_server_datadir = "$tempdir/pgdata";
|
|
$test_server_logfile = "$log_path/postmaster.log";
|
|
}
|
|
|
|
sub restart_test_server
|
|
{
|
|
print("### Restarting test server\n");
|
|
system_log('pg_ctl', '-D', $test_server_datadir, '-w', '-l',
|
|
$test_server_logfile, 'restart');
|
|
}
|
|
|
|
END
|
|
{
|
|
if ($test_server_datadir)
|
|
{
|
|
system_log('pg_ctl', '-D', $test_server_datadir, '-m',
|
|
'immediate', 'stop');
|
|
}
|
|
}
|
|
|
|
sub psql
|
|
{
|
|
my ($dbname, $sql) = @_;
|
|
print("# Running SQL command: $sql\n");
|
|
run [ 'psql', '-X', '-q', '-d', $dbname, '-f', '-' ], '<', \$sql or die;
|
|
}
|
|
|
|
sub system_or_bail
|
|
{
|
|
if (system_log(@_) != 0)
|
|
{
|
|
BAIL_OUT("system $_[0] failed: $?");
|
|
}
|
|
}
|
|
|
|
sub system_log
|
|
{
|
|
print("# Running: " . join(" ", @_) ."\n");
|
|
return system(@_);
|
|
}
|
|
|
|
sub run_log
|
|
{
|
|
print("# Running: " . join(" ", @{$_[0]}) ."\n");
|
|
return run (@_);
|
|
}
|
|
|
|
|
|
#
|
|
# Test functions
|
|
#
|
|
|
|
|
|
sub command_ok
|
|
{
|
|
my ($cmd, $test_name) = @_;
|
|
my $result = run_log($cmd);
|
|
ok($result, $test_name);
|
|
}
|
|
|
|
sub command_fails
|
|
{
|
|
my ($cmd, $test_name) = @_;
|
|
my $result = run_log($cmd);
|
|
ok(!$result, $test_name);
|
|
}
|
|
|
|
sub command_exit_is
|
|
{
|
|
my ($cmd, $expected, $test_name) = @_;
|
|
print("# Running: " . join(" ", @{$cmd}) ."\n");
|
|
my $h = start $cmd;
|
|
$h->finish();
|
|
is($h->result(0), $expected, $test_name);
|
|
}
|
|
|
|
sub program_help_ok
|
|
{
|
|
my ($cmd) = @_;
|
|
my ($stdout, $stderr);
|
|
print("# Running: $cmd --help\n");
|
|
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);
|
|
print("# Running: $cmd --version\n");
|
|
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);
|
|
print("# Running: $cmd --not-a-valid-option\n");
|
|
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);
|
|
print("# Running: " . join(" ", @{$cmd}) . "\n");
|
|
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) = @_;
|
|
truncate $test_server_logfile, 0;
|
|
my $result = run_log($cmd);
|
|
ok($result, "@$cmd exit code 0");
|
|
my $log = `cat '$test_server_logfile'`;
|
|
like($log, $expected_sql, "$test_name: SQL found in server log");
|
|
}
|
|
|
|
1;
|