Add TAP tests for client programs

Reviewed-by: Pavel Stěhule <pavel.stehule@gmail.com>
Reviewed-by: Erik Rijkers <er@xs4all.nl>
This commit is contained in:
Peter Eisentraut 2014-04-14 21:33:46 -04:00
parent 7b5a9d61a8
commit 7d0f493f19
39 changed files with 745 additions and 3 deletions

View File

@ -66,9 +66,9 @@ check check-tests: all
check check-tests installcheck installcheck-parallel installcheck-tests: check check-tests installcheck installcheck-parallel installcheck-tests:
$(MAKE) -C src/test/regress $@ $(MAKE) -C src/test/regress $@
$(call recurse,check-world,src/test src/pl src/interfaces/ecpg contrib,check) $(call recurse,check-world,src/test src/pl src/interfaces/ecpg contrib src/bin,check)
$(call recurse,installcheck-world,src/test src/pl src/interfaces/ecpg contrib,installcheck) $(call recurse,installcheck-world,src/test src/pl src/interfaces/ecpg contrib src/bin,installcheck)
GNUmakefile: GNUmakefile.in $(top_builddir)/config.status GNUmakefile: GNUmakefile.in $(top_builddir)/config.status
./config.status $@ ./config.status $@

47
configure vendored
View File

@ -627,6 +627,7 @@ ac_includes_default="\
ac_subst_vars='LTLIBOBJS ac_subst_vars='LTLIBOBJS
vpath_build vpath_build
PROVE
OSX OSX
XSLTPROC XSLTPROC
COLLATEINDEX COLLATEINDEX
@ -14350,6 +14351,52 @@ fi
done done
#
# Check for test tools
#
for ac_prog in prove
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_PROVE+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$PROVE"; then
ac_cv_prog_PROVE="$PROVE" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_PROVE="$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
PROVE=$ac_cv_prog_PROVE
if test -n "$PROVE"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PROVE" >&5
$as_echo "$PROVE" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
test -n "$PROVE" && break
done
# Thread testing # Thread testing
# We have to run the thread test near the end so we have all our symbols # We have to run the thread test near the end so we have all our symbols

View File

@ -1817,6 +1817,11 @@ PGAC_PATH_COLLATEINDEX
AC_CHECK_PROGS(XSLTPROC, xsltproc) AC_CHECK_PROGS(XSLTPROC, xsltproc)
AC_CHECK_PROGS(OSX, [osx sgml2xml sx]) AC_CHECK_PROGS(OSX, [osx sgml2xml sx])
#
# Check for test tools
#
AC_CHECK_PROGS(PROVE, prove)
# Thread testing # Thread testing
# We have to run the thread test near the end so we have all our symbols # We have to run the thread test near the end so we have all our symbols

View File

@ -333,7 +333,8 @@ su - postgres
<application>Perl</> 5.8 or later is needed to build from a Git checkout, <application>Perl</> 5.8 or later is needed to build from a Git checkout,
or if you changed the input files for any of the build steps that or if you changed the input files for any of the build steps that
use Perl scripts. If building on Windows you will need use Perl scripts. If building on Windows you will need
<application>Perl</> in any case. <application>Perl</> in any case. <application>Perl</application> is
also required to run some test suites.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>

View File

@ -204,6 +204,12 @@ make installcheck-world
located in <filename>src/test/isolation</>. located in <filename>src/test/isolation</>.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
Tests of client programs under <filename>src/bin</filename>. See
also <xref linkend="regress-tap">.
</para>
</listitem>
</itemizedlist> </itemizedlist>
<para> <para>
@ -660,6 +666,28 @@ float8:out:i.86-.*-openbsd=float8-small-is-zero.out
</sect1> </sect1>
<sect1 id="regress-tap">
<title>TAP Tests</title>
<para>
The client program tests under <filename>src/bin</filename> use the Perl
TAP tools and are run by <command>prove</command>. You can pass
command-line options to <command>prove</command> by setting
the <command>make</command> variable <varname>PROVE_FLAGS</>, for example:
<programlisting>
make -C src/bin check PROVE_FLAGS='--reverse'
</programlisting>
The default is <literal>--verbose</literal>. See the manual page
of <command>prove</command> for more information.
</para>
<para>
The tests written in Perl require the Perl
module <literal>IPC::Run</literal>, otherwise most tests will be skipped.
This module is available from CPAN or an operating system package.
</para>
</sect1>
<sect1 id="regress-coverage"> <sect1 id="regress-coverage">
<title>Test Coverage Examination</title> <title>Test Coverage Examination</title>

View File

@ -292,6 +292,22 @@ XGETTEXT = @XGETTEXT@
GZIP = gzip GZIP = gzip
BZIP2 = bzip2 BZIP2 = bzip2
# Testing
PROVE = @PROVE@
PG_PROVE_FLAGS = --ext='.pl' -I $(top_srcdir)/src/test/perl/
PROVE_FLAGS = --verbose
define prove_installcheck
PATH="$(bindir):$$PATH" PGPORT='6$(DEF_PGPORT)' $(PROVE) $(PG_PROVE_FLAGS) $(PROVE_FLAGS)
endef
define prove_check
$(MKDIR_P) tmp_check/log
$(MAKE) -C $(top_builddir) DESTDIR=$(CURDIR)/tmp_check/install install >$(CURDIR)/tmp_check/log/install.log 2>&1
PATH="$(CURDIR)/tmp_check/install$(bindir):$$PATH" PGPORT='6$(DEF_PGPORT)' $(PROVE) $(PG_PROVE_FLAGS) $(PROVE_FLAGS)
endef
# Installation. # Installation.
install_bin = @install_bin@ install_bin = @install_bin@

View File

@ -2,3 +2,5 @@
/localtime.c /localtime.c
/initdb /initdb
/tmp_check/

View File

@ -57,3 +57,10 @@ clean distclean maintainer-clean:
# ensure that changes in datadir propagate into object file # ensure that changes in datadir propagate into object file
initdb.o: initdb.c $(top_builddir)/src/Makefile.global initdb.o: initdb.c $(top_builddir)/src/Makefile.global
check: all
$(prove_check)
installcheck:
$(prove_installcheck)

View File

@ -0,0 +1,37 @@
use strict;
use warnings;
use TestLib;
use Test::More tests => 14;
my $tempdir = TestLib::tempdir;
program_help_ok('initdb');
program_version_ok('initdb');
program_options_handling_ok('initdb');
command_ok(['initdb', "$tempdir/data"], 'basic initdb');
command_fails(['initdb', "$tempdir/data"], 'existing data directory');
command_ok(['initdb', '-N', "$tempdir/data2"], 'nosync');
command_ok(['initdb', '-S', "$tempdir/data2"], 'sync only');
command_fails(['initdb', '-S', "$tempdir/data3"], 'sync missing data directory');
mkdir "$tempdir/data4" or BAIL_OUT($!);
command_ok(['initdb', "$tempdir/data4"], 'existing empty data directory');
system_or_bail "rm -rf $tempdir/*";
command_ok(['initdb', "$tempdir/data", '-X', "$tempdir/pgxlog"], 'separate xlog directory');
system_or_bail "rm -rf $tempdir/*";
command_fails(['initdb', "$tempdir/data", '-X', 'pgxlog'], 'relative xlog directory not allowed');
system_or_bail "rm -rf $tempdir/*";
mkdir "$tempdir/pgxlog";
command_ok(['initdb', "$tempdir/data", '-X', "$tempdir/pgxlog"], 'existing empty xlog directory');
system_or_bail "rm -rf $tempdir/*";
mkdir "$tempdir/pgxlog";
mkdir "$tempdir/pgxlog/lost+found";
command_fails(['initdb', "$tempdir/data", '-X', "$tempdir/pgxlog"], 'existing nonempty xlog directory');
system_or_bail "rm -rf $tempdir/*";
command_ok(['initdb', "$tempdir/data", '-T', 'german'], 'select default dictionary');

View File

@ -1,3 +1,5 @@
/pg_basebackup /pg_basebackup
/pg_receivexlog /pg_receivexlog
/pg_recvlogical /pg_recvlogical
/tmp_check/

View File

@ -48,3 +48,9 @@ clean distclean maintainer-clean:
rm -f pg_basebackup$(X) pg_receivexlog$(X) pg_recvlogical$(X) \ rm -f pg_basebackup$(X) pg_receivexlog$(X) pg_recvlogical$(X) \
pg_basebackup.o pg_receivexlog.o pg_recvlogical.o \ pg_basebackup.o pg_receivexlog.o pg_recvlogical.o \
$(OBJS) $(OBJS)
check: all
$(prove_check)
installcheck:
$(prove_installcheck)

View File

@ -0,0 +1,90 @@
use strict;
use warnings;
use Cwd;
use TestLib;
use Test::More tests => 28;
program_help_ok('pg_basebackup');
program_version_ok('pg_basebackup');
program_options_handling_ok('pg_basebackup');
my $tempdir = tempdir;
start_test_server $tempdir;
command_fails(['pg_basebackup'], 'pg_basebackup needs target directory specified');
command_fails(['pg_basebackup', '-D', "$tempdir/backup"], 'pg_basebackup fails because of hba');
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;
system_or_bail 'pg_ctl', '-s', '-D', "$tempdir/pgdata", 'reload';
command_fails(['pg_basebackup', '-D', "$tempdir/backup"], 'pg_basebackup fails because of WAL configuration');
open CONF, ">>$tempdir/pgdata/postgresql.conf";
print CONF "max_wal_senders = 10\n";
print CONF "wal_level = archive\n";
close CONF;
restart_test_server;
command_ok(['pg_basebackup', '-D', "$tempdir/backup"], 'pg_basebackup runs');
ok(-f "$tempdir/backup/PG_VERSION", 'backup was created');
command_ok(['pg_basebackup', '-D', "$tempdir/backup2", '--xlogdir', "$tempdir/xlog2"], 'separate xlog directory');
ok(-f "$tempdir/backup2/PG_VERSION", 'backup was created');
ok(-d "$tempdir/xlog2/", 'xlog directory was created');
command_ok(['pg_basebackup', '-D', "$tempdir/tarbackup", '-Ft'], 'tar format');
ok(-f "$tempdir/tarbackup/base.tar", 'backup tar was created');
mkdir "$tempdir/tblspc1";
psql 'postgres', "CREATE TABLESPACE tblspc1 LOCATION '$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$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 '$tempdir/tbl=spc2';";
command_ok(['pg_basebackup', '-D', "$tempdir/backup3", '-Fp',
"-T$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');
command_fails(['pg_basebackup', '-D', "$tempdir/backup_foo", '-Fp',
"-T/foo="],
'-T with empty new directory fails');
command_fails(['pg_basebackup', '-D', "$tempdir/backup_foo", '-Fp',
"-T/foo=/bar=/baz"],
'-T with multiple = fails');
command_fails(['pg_basebackup', '-D', "$tempdir/backup_foo", '-Fp',
"-Tfoo=/bar"],
'-T with old directory not absolute fails');
command_fails(['pg_basebackup', '-D', "$tempdir/backup_foo", '-Fp',
"-T/foo=bar"],
'-T with new directory not absolute fails');
command_fails(['pg_basebackup', '-D', "$tempdir/backup_foo", '-Fp',
"-Tfoo"],
'-T with invalid format fails');

View File

@ -0,0 +1,8 @@
use strict;
use warnings;
use TestLib;
use Test::More tests => 3;
program_help_ok('pg_receivexlog');
program_version_ok('pg_receivexlog');
program_options_handling_ok('pg_receivexlog');

View File

@ -1 +1,2 @@
/pg_config /pg_config
/tmp_check/

View File

@ -47,3 +47,9 @@ uninstall:
clean distclean maintainer-clean: clean distclean maintainer-clean:
rm -f pg_config$(X) $(OBJS) rm -f pg_config$(X) $(OBJS)
check: all
$(prove_check)
installcheck:
$(prove_installcheck)

View File

@ -0,0 +1,12 @@
use strict;
use warnings;
use TestLib;
use Test::More tests => 7;
program_help_ok('pg_config');
program_version_ok('pg_config');
program_options_handling_ok('pg_config');
command_like(['pg_config', '--bindir'], qr/bin/, 'pg_config single option'); # XXX might be wrong
command_like(['pg_config', '--bindir', '--libdir'], qr/bin.*\n.*lib/, 'pg_config two options');
command_like(['pg_config', '--libdir', '--bindir'], qr/lib.*\n.*bin/, 'pg_config two options different order');
command_like(['pg_config'], qr/.*\n.*\n.*/, 'pg_config without options prints many lines');

View File

@ -1 +1,2 @@
/pg_controldata /pg_controldata
/tmp_check/

View File

@ -33,3 +33,9 @@ uninstall:
clean distclean maintainer-clean: clean distclean maintainer-clean:
rm -f pg_controldata$(X) $(OBJS) rm -f pg_controldata$(X) $(OBJS)
check: all
$(prove_check)
installcheck:
$(prove_installcheck)

View File

@ -0,0 +1,14 @@
use strict;
use warnings;
use TestLib;
use Test::More tests => 6;
my $tempdir = TestLib::tempdir;
program_help_ok('pg_controldata');
program_version_ok('pg_controldata');
program_options_handling_ok('pg_controldata');
command_fails(['pg_controldata'], 'pg_controldata without arguments fails');
command_fails(['pg_controldata', 'nonexistent'], 'pg_controldata with nonexistent directory fails');
system_or_bail "initdb -D $tempdir/data -A trust >/dev/null";
command_like(['pg_controldata', "$tempdir/data"], qr/checkpoint/, 'pg_controldata produces output');

View File

@ -1 +1,2 @@
/pg_ctl /pg_ctl
/tmp_check/

View File

@ -36,3 +36,9 @@ uninstall:
clean distclean maintainer-clean: clean distclean maintainer-clean:
rm -f pg_ctl$(X) $(OBJS) rm -f pg_ctl$(X) $(OBJS)
check: all
$(prove_check)
installcheck:
$(prove_installcheck)

View File

@ -0,0 +1,25 @@
use strict;
use warnings;
use TestLib;
use Test::More tests => 10;
my $tempdir = TestLib::tempdir;
program_help_ok('pg_ctl');
program_version_ok('pg_ctl');
program_options_handling_ok('pg_ctl');
command_ok(['pg_ctl', 'initdb', '-D', "$tempdir/data"], 'pg_ctl initdb');
open CONF, ">>$tempdir/data/postgresql.conf";
print CONF "listen_addresses = ''\n";
print CONF "unix_socket_directories = '$tempdir'\n";
close CONF;
command_ok(['pg_ctl', 'start', '-D', "$tempdir/data", '-w'], 'pg_ctl start -w');
command_ok(['pg_ctl', 'start', '-D', "$tempdir/data", '-w'], 'second pg_ctl start succeeds');
command_ok(['pg_ctl', 'stop', '-D', "$tempdir/data", '-w', '-m', 'fast'], 'pg_ctl stop -w');
command_fails(['pg_ctl', 'stop', '-D', "$tempdir/data", '-w', '-m', 'fast'], 'second pg_ctl stop fails');
command_ok(['pg_ctl', 'restart', '-D', "$tempdir/data", '-w', '-m', 'fast'], 'pg_ctl restart with server not running');
command_ok(['pg_ctl', 'restart', '-D', "$tempdir/data", '-w', '-m', 'fast'], 'pg_ctl restart with server running');
system_or_bail 'pg_ctl', '-s', 'stop', '-D', "$tempdir/data", '-m', 'fast';

View File

@ -0,0 +1,19 @@
use strict;
use warnings;
use TestLib;
use Test::More tests => 2;
my $tempdir = TestLib::tempdir;
system_or_bail "initdb -D $tempdir/data -A trust >/dev/null";
open CONF, ">>$tempdir/data/postgresql.conf";
print CONF "listen_addresses = ''\n";
print CONF "unix_socket_directories = '$tempdir'\n";
close CONF;
command_exit_is(['pg_ctl', 'status', '-D', "$tempdir/data"], 3, 'pg_ctl status with server not running');
system_or_bail 'pg_ctl', '-s', '-l', "$tempdir/logfile", '-D', "$tempdir/data", '-w', 'start';
command_exit_is(['pg_ctl', 'status', '-D', "$tempdir/data"], 0, 'pg_ctl status with server running');
system_or_bail 'pg_ctl', '-s', 'stop', '-D', "$tempdir/data", '-m', 'fast';

View File

@ -14,3 +14,5 @@
/kwlookup.c /kwlookup.c
/mbprint.c /mbprint.c
/print.c /print.c
/tmp_check/

View File

@ -68,3 +68,10 @@ clean distclean maintainer-clean:
rm -f $(addsuffix $(X), $(PROGRAMS)) $(addsuffix .o, $(PROGRAMS)) rm -f $(addsuffix $(X), $(PROGRAMS)) $(addsuffix .o, $(PROGRAMS))
rm -f common.o dumputils.o kwlookup.o keywords.o print.o mbprint.o $(WIN32RES) rm -f common.o dumputils.o kwlookup.o keywords.o print.o mbprint.o $(WIN32RES)
rm -f dumputils.c print.c mbprint.c kwlookup.c keywords.c rm -f dumputils.c print.c mbprint.c kwlookup.c keywords.c
check: all
$(prove_check)
installcheck:
$(prove_installcheck)

View File

@ -0,0 +1,18 @@
use strict;
use warnings;
use TestLib;
use Test::More tests => 6;
program_help_ok('clusterdb');
program_version_ok('clusterdb');
program_options_handling_ok('clusterdb');
my $tempdir = tempdir;
start_test_server $tempdir;
issues_sql_like(['clusterdb', 'postgres'], qr/statement: CLUSTER;/, 'SQL CLUSTER run');
command_fails(['clusterdb', '-t', 'nonexistent', 'postgres'], 'fails with nonexistent table');
psql 'postgres', 'CREATE TABLE test1 (a int); CREATE INDEX test1x ON test1 (a); CLUSTER test1 USING test1x';
issues_sql_like(['clusterdb', 'postgres', '-t', 'test1'], qr/statement: CLUSTER test1;/, 'cluster specific table');

View File

@ -0,0 +1,9 @@
use strict;
use warnings;
use TestLib;
use Test::More tests => 1;
my $tempdir = tempdir;
start_test_server $tempdir;
issues_sql_like(['clusterdb', '-a'], qr/statement: CLUSTER.*statement: CLUSTER/s, 'cluster all databases');

View File

@ -0,0 +1,16 @@
use strict;
use warnings;
use TestLib;
use Test::More tests => 6;
program_help_ok('createdb');
program_version_ok('createdb');
program_options_handling_ok('createdb');
my $tempdir = tempdir;
start_test_server $tempdir;
issues_sql_like(['createdb', 'foobar1'], qr/statement: CREATE DATABASE foobar1/, 'SQL CREATE DATABASE run');
issues_sql_like(['createdb', 'foobar2', '-l', 'C', '-E', 'LATIN1', '-T', 'template0'], qr/statement: CREATE DATABASE foobar2 ENCODING 'LATIN1'/, 'create database with encoding');
command_fails(['createdb', 'foobar1'], 'fails if database already exists');

View File

@ -0,0 +1,18 @@
use strict;
use warnings;
use TestLib;
use Test::More tests => 6;
program_help_ok('createlang');
program_version_ok('createlang');
program_options_handling_ok('createlang');
my $tempdir = tempdir;
start_test_server $tempdir;
command_fails(['createlang', 'plpgsql', 'postgres'], 'fails if language already exists');
psql 'postgres', 'DROP EXTENSION plpgsql';
issues_sql_like(['createlang', 'plpgsql', 'postgres'], qr/statement: CREATE EXTENSION "plpgsql"/, 'SQL CREATE EXTENSION run');
command_like(['createlang', '--list', 'postgres'], qr/plpgsql/, 'list output');

View File

@ -0,0 +1,26 @@
use strict;
use warnings;
use TestLib;
use Test::More tests => 8;
program_help_ok('createuser');
program_version_ok('createuser');
program_options_handling_ok('createuser');
my $tempdir = tempdir;
start_test_server $tempdir;
issues_sql_like(['createuser', 'user1'],
qr/statement: CREATE ROLE user1 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN;/,
'SQL CREATE USER run');
issues_sql_like(['createuser', '-L', 'role1'],
qr/statement: CREATE ROLE role1 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN;/,
'create a non-login role');
issues_sql_like(['createuser', '-r', 'user2'],
qr/statement: CREATE ROLE user2 NOSUPERUSER NOCREATEDB CREATEROLE INHERIT LOGIN;/,
'create a CREATEROLE user');
issues_sql_like(['createuser', '-s', 'user3'],
qr/statement: CREATE ROLE user3 SUPERUSER CREATEDB CREATEROLE INHERIT LOGIN;/,
'create a superuser');
command_fails(['createuser', 'user1'], 'fails if role already exists');

View File

@ -0,0 +1,16 @@
use strict;
use warnings;
use TestLib;
use Test::More tests => 5;
program_help_ok('dropdb');
program_version_ok('dropdb');
program_options_handling_ok('dropdb');
my $tempdir = tempdir;
start_test_server $tempdir;
psql 'postgres', 'CREATE DATABASE foobar1';
issues_sql_like(['dropdb', 'foobar1'], qr/statement: DROP DATABASE foobar1/, 'SQL DROP DATABASE run');
command_fails(['dropdb', 'nonexistent'], 'fails with nonexistent database');

View File

@ -0,0 +1,15 @@
use strict;
use warnings;
use TestLib;
use Test::More tests => 5;
program_help_ok('droplang');
program_version_ok('droplang');
program_options_handling_ok('droplang');
my $tempdir = tempdir;
start_test_server $tempdir;
issues_sql_like(['droplang', 'plpgsql', 'postgres'], qr/statement: DROP EXTENSION "plpgsql"/, 'SQL DROP EXTENSION run');
command_fails(['droplang', 'nonexistent', 'postgres'], 'fails with nonexistent language');

View File

@ -0,0 +1,16 @@
use strict;
use warnings;
use TestLib;
use Test::More tests => 5;
program_help_ok('dropuser');
program_version_ok('dropuser');
program_options_handling_ok('dropuser');
my $tempdir = tempdir;
start_test_server $tempdir;
psql 'postgres', 'CREATE ROLE foobar1';
issues_sql_like(['dropuser', 'foobar1'], qr/statement: DROP ROLE foobar1/, 'SQL DROP ROLE run');
command_fails(['dropuser', 'nonexistent'], 'fails with nonexistent user');

View File

@ -0,0 +1,15 @@
use strict;
use warnings;
use TestLib;
use Test::More tests => 5;
program_help_ok('pg_isready');
program_version_ok('pg_isready');
program_options_handling_ok('pg_isready');
command_fails(['pg_isready'], 'fails with no server running');
my $tempdir = tempdir;
start_test_server $tempdir;
command_ok(['pg_isready'], 'succeeds with server running');

View File

@ -0,0 +1,21 @@
use strict;
use warnings;
use TestLib;
use Test::More tests => 7;
program_help_ok('reindexdb');
program_version_ok('reindexdb');
program_options_handling_ok('reindexdb');
my $tempdir = tempdir;
start_test_server $tempdir;
$ENV{PGOPTIONS} = '--client-min-messages=WARNING';
issues_sql_like(['reindexdb', 'postgres'], qr/statement: REINDEX DATABASE postgres;/, 'SQL REINDEX run');
psql 'postgres', 'CREATE TABLE test1 (a int); CREATE INDEX test1x ON test1 (a);';
issues_sql_like(['reindexdb', 'postgres', '-t', 'test1'], qr/statement: REINDEX TABLE test1;/, 'reindex specific table');
issues_sql_like(['reindexdb', 'postgres', '-i', 'test1x'], qr/statement: REINDEX INDEX test1x;/, 'reindex specific index');
issues_sql_like(['reindexdb', 'postgres', '-s'], qr/statement: REINDEX SYSTEM postgres;/, 'reindex system tables');

View File

@ -0,0 +1,11 @@
use strict;
use warnings;
use TestLib;
use Test::More tests => 1;
my $tempdir = tempdir;
start_test_server $tempdir;
$ENV{PGOPTIONS} = '--client-min-messages=WARNING';
issues_sql_like(['reindexdb', '-a'], qr/statement: REINDEX.*statement: REINDEX/s, 'reindex all databases');

View File

@ -0,0 +1,17 @@
use strict;
use warnings;
use TestLib;
use Test::More tests => 8;
program_help_ok('vacuumdb');
program_version_ok('vacuumdb');
program_options_handling_ok('vacuumdb');
my $tempdir = tempdir;
start_test_server $tempdir;
issues_sql_like(['vacuumdb', 'postgres'], qr/statement: VACUUM;/, 'SQL VACUUM run');
issues_sql_like(['vacuumdb', '-f', 'postgres'], qr/statement: VACUUM \(FULL\);/, 'vacuumdb -f');
issues_sql_like(['vacuumdb', '-F', 'postgres'], qr/statement: VACUUM \(FREEZE\);/, 'vacuumdb -F');
issues_sql_like(['vacuumdb', '-z', 'postgres'], qr/statement: VACUUM \(ANALYZE\);/, 'vacuumdb -z');
issues_sql_like(['vacuumdb', '-Z', 'postgres'], qr/statement: ANALYZE;/, 'vacuumdb -z');

View File

@ -0,0 +1,9 @@
use strict;
use warnings;
use TestLib;
use Test::More tests => 1;
my $tempdir = tempdir;
start_test_server $tempdir;
issues_sql_like(['vacuumdb', '-a'], qr/statement: VACUUM.*statement: VACUUM/s, 'vacuum all databases');

186
src/test/perl/TestLib.pm Normal file
View File

@ -0,0 +1,186 @@
package TestLib;
use strict;
use warnings;
use Exporter 'import';
our @EXPORT = qw(
tempdir
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 Test::More;
BEGIN {
eval {
require IPC::Run;
import IPC::Run qw(run start);
1;
} or do {
plan skip_all => "IPC::Run not available";
}
}
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('testXXXX', DIR => cwd(), CLEANUP => 1);
}
my ($test_server_datadir, $test_server_logfile);
sub start_test_server {
my ($tempdir) = @_;
my $ret;
system "initdb -D $tempdir/pgdata -A trust -N >/dev/null";
$ret = system 'pg_ctl', '-D', "$tempdir/pgdata", '-s', '-w', '-l', "$tempdir/logfile", '-o', "--fsync=off -k $tempdir --listen-addresses='' --log-statement=all", 'start';
if ($ret != 0) {
system('cat', "$tempdir/logfile");
BAIL_OUT("pg_ctl failed");
}
$ENV{PGHOST} = $tempdir;
$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) = @_;
subtest "$cmd --help" => sub {
plan tests => 3;
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) = @_;
subtest "$cmd --version" => sub {
plan tests => 3;
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) = @_;
subtest "$cmd options handling" => sub {
plan tests => 2;
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) = @_;
subtest $test_name => sub {
plan tests => 3;
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) = @_;
subtest $test_name => sub {
plan tests => 2;
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;