check check-tests installcheck installcheck-parallel installcheck-tests:
$(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
./config.status $@
ac_subst_vars='LTLIBOBJS
vpath_build
+PROVE
OSX
XSLTPROC
COLLATEINDEX
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
# We have to run the thread test near the end so we have all our symbols
AC_CHECK_PROGS(XSLTPROC, xsltproc)
AC_CHECK_PROGS(OSX, [osx sgml2xml sx])
+#
+# Check for test tools
+#
+AC_CHECK_PROGS(PROVE, prove)
+
# Thread testing
# We have to run the thread test near the end so we have all our symbols
<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
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>
</listitem>
</itemizedlist>
located in <filename>src/test/isolation</>.
</para>
</listitem>
+ <listitem>
+ <para>
+ Tests of client programs under <filename>src/bin</filename>. See
+ also <xref linkend="regress-tap">.
+ </para>
+ </listitem>
</itemizedlist>
<para>
</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">
<title>Test Coverage Examination</title>
GZIP = gzip
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.
install_bin = @install_bin@
/localtime.c
/initdb
+
+/tmp_check/
# ensure that changes in datadir propagate into object file
initdb.o: initdb.c $(top_builddir)/src/Makefile.global
+
+
+check: all
+ $(prove_check)
+
+installcheck:
+ $(prove_installcheck)
--- /dev/null
+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_receivexlog
/pg_recvlogical
+
+/tmp_check/
rm -f pg_basebackup$(X) pg_receivexlog$(X) pg_recvlogical$(X) \
pg_basebackup.o pg_receivexlog.o pg_recvlogical.o \
$(OBJS)
+
+check: all
+ $(prove_check)
+
+installcheck:
+ $(prove_installcheck)
--- /dev/null
+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');
--- /dev/null
+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');
clean distclean maintainer-clean:
rm -f pg_config$(X) $(OBJS)
+
+check: all
+ $(prove_check)
+
+installcheck:
+ $(prove_installcheck)
--- /dev/null
+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
+/tmp_check/
clean distclean maintainer-clean:
rm -f pg_controldata$(X) $(OBJS)
+
+check: all
+ $(prove_check)
+
+installcheck:
+ $(prove_installcheck)
--- /dev/null
+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');
clean distclean maintainer-clean:
rm -f pg_ctl$(X) $(OBJS)
+
+check: all
+ $(prove_check)
+
+installcheck:
+ $(prove_installcheck)
--- /dev/null
+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';
--- /dev/null
+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';
/kwlookup.c
/mbprint.c
/print.c
+
+/tmp_check/
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 dumputils.c print.c mbprint.c kwlookup.c keywords.c
+
+
+check: all
+ $(prove_check)
+
+installcheck:
+ $(prove_installcheck)
--- /dev/null
+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');
--- /dev/null
+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');
--- /dev/null
+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');
--- /dev/null
+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');
--- /dev/null
+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');
--- /dev/null
+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');
--- /dev/null
+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');
--- /dev/null
+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');
--- /dev/null
+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');
--- /dev/null
+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');
--- /dev/null
+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');
--- /dev/null
+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');
--- /dev/null
+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');
--- /dev/null
+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;