Commit 7d0f493f authored by Peter Eisentraut's avatar Peter Eisentraut

Add TAP tests for client programs

Reviewed-by: default avatarPavel Stěhule <pavel.stehule@gmail.com>
Reviewed-by: default avatarErik Rijkers <er@xs4all.nl>
parent 7b5a9d61
...@@ -66,9 +66,9 @@ check check-tests: all ...@@ -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 $@
......
...@@ -627,6 +627,7 @@ ac_includes_default="\ ...@@ -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 ...@@ -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
......
...@@ -1817,6 +1817,11 @@ PGAC_PATH_COLLATEINDEX ...@@ -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
......
...@@ -333,7 +333,8 @@ su - postgres ...@@ -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>
......
...@@ -204,6 +204,12 @@ make installcheck-world ...@@ -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 ...@@ -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>
......
...@@ -292,6 +292,22 @@ XGETTEXT = @XGETTEXT@ ...@@ -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@
......
...@@ -2,3 +2,5 @@ ...@@ -2,3 +2,5 @@
/localtime.c /localtime.c
/initdb /initdb
/tmp_check/
...@@ -57,3 +57,10 @@ clean distclean maintainer-clean: ...@@ -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)
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');
/pg_basebackup /pg_basebackup
/pg_receivexlog /pg_receivexlog
/pg_recvlogical /pg_recvlogical
/tmp_check/
...@@ -48,3 +48,9 @@ clean distclean maintainer-clean: ...@@ -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)
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');
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');
/pg_config /pg_config
/tmp_check/
...@@ -47,3 +47,9 @@ uninstall: ...@@ -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)
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');
/pg_controldata /pg_controldata
/tmp_check/
...@@ -33,3 +33,9 @@ uninstall: ...@@ -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)
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');
...@@ -36,3 +36,9 @@ uninstall: ...@@ -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)
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';
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';
...@@ -14,3 +14,5 @@ ...@@ -14,3 +14,5 @@
/kwlookup.c /kwlookup.c
/mbprint.c /mbprint.c
/print.c /print.c
/tmp_check/
...@@ -68,3 +68,10 @@ clean distclean maintainer-clean: ...@@ -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)
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');
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');
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');
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');
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');
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');
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');
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');
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');
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');
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');
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');
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');
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;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment