mirror of
https://github.com/postgres/postgres.git
synced 2025-06-29 10:41:53 +03:00
Add more TAP tests for pg_dumpall
Author: Matheus Alcantara <matheusssilv97@gmail.com> Author: Mahendra Singh Thalor <mahi6run@gmail.com>
This commit is contained in:
@ -102,6 +102,7 @@ tests += {
|
||||
't/003_pg_dump_with_server.pl',
|
||||
't/004_pg_dump_parallel.pl',
|
||||
't/005_pg_dump_filterfile.pl',
|
||||
't/006_pg_dumpall.pl',
|
||||
't/010_dump_connstr.pl',
|
||||
],
|
||||
},
|
||||
|
@ -242,6 +242,16 @@ command_fails_like(
|
||||
qr/\Qpg_restore: error: option --exclude-database cannot be used together with -g\/--globals-only\E/,
|
||||
'pg_restore: option --exclude-database cannot be used together with -g/--globals-only');
|
||||
|
||||
command_fails_like(
|
||||
[ 'pg_restore', '--exclude-database=foo', '-d', 'xxx', 'dumpdir' ],
|
||||
qr/\Qpg_restore: error: option --exclude-database can be used only when restoring multiple databases by archive of pg_dumpall\E/,
|
||||
'When option --exclude-database is used in pg_restore with dump of pg_dump');
|
||||
|
||||
command_fails_like(
|
||||
[ 'pg_restore', '--globals-only', '-d', 'xxx', 'dumpdir' ],
|
||||
qr/\Qpg_restore: error: option -g\/--globals-only can be used only when restoring multiple databases by archive of pg_dumpall\E/,
|
||||
'When option --globals-only is not used in pg_restore with dump of pg_dump');
|
||||
|
||||
# also fails for -r and -t, but it seems pointless to add more tests for those.
|
||||
command_fails_like(
|
||||
[ 'pg_dumpall', '--exclude-database=foo', '--globals-only' ],
|
||||
|
391
src/bin/pg_dump/t/006_pg_dumpall.pl
Normal file
391
src/bin/pg_dump/t/006_pg_dumpall.pl
Normal file
@ -0,0 +1,391 @@
|
||||
# Copyright (c) 2021-2025, PostgreSQL Global Development Group
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
|
||||
use PostgreSQL::Test::Cluster;
|
||||
use PostgreSQL::Test::Utils;
|
||||
use Test::More;
|
||||
|
||||
my $tempdir = PostgreSQL::Test::Utils::tempdir;
|
||||
my $run_db = 'postgres';
|
||||
my $sep = $windows_os ? "\\" : "/";
|
||||
|
||||
# Tablespace locations used by "restore_tablespace" test case.
|
||||
my $tablespace1 = "${tempdir}${sep}tbl1";
|
||||
my $tablespace2 = "${tempdir}${sep}tbl2";
|
||||
mkdir($tablespace1) || die "mkdir $tablespace1 $!";
|
||||
mkdir($tablespace2) || die "mkdir $tablespace2 $!";
|
||||
|
||||
# Scape tablespace locations on Windows.
|
||||
$tablespace1 = $windows_os ? ($tablespace1 =~ s/\\/\\\\/gr) : $tablespace1;
|
||||
$tablespace2 = $windows_os ? ($tablespace2 =~ s/\\/\\\\/gr) : $tablespace2;
|
||||
|
||||
# Where pg_dumpall will be executed.
|
||||
my $node = PostgreSQL::Test::Cluster->new('node');
|
||||
$node->init;
|
||||
$node->start;
|
||||
|
||||
|
||||
###############################################################
|
||||
# Definition of the pg_dumpall test cases to run.
|
||||
#
|
||||
# Each of these test cases are named and those names are used for fail
|
||||
# reporting and also to save the dump and restore information needed for the
|
||||
# test to assert.
|
||||
#
|
||||
# The "setup_sql" is a psql valid script that contains SQL commands to execute
|
||||
# before of actually execute the tests. The setups are all executed before of
|
||||
# any test execution.
|
||||
#
|
||||
# The "dump_cmd" and "restore_cmd" are the commands that will be executed. The
|
||||
# "restore_cmd" must have the --file flag to save the restore output so that we
|
||||
# can assert on it.
|
||||
#
|
||||
# The "like" and "unlike" is a regexp that is used to match the pg_restore
|
||||
# output. It must have at least one of then filled per test cases but it also
|
||||
# can have both. See "excluding_databases" test case for example.
|
||||
my %pgdumpall_runs = (
|
||||
restore_roles => {
|
||||
setup_sql => '
|
||||
CREATE ROLE dumpall WITH ENCRYPTED PASSWORD \'admin\' SUPERUSER;
|
||||
CREATE ROLE dumpall2 WITH REPLICATION CONNECTION LIMIT 10;',
|
||||
dump_cmd => [
|
||||
'pg_dumpall',
|
||||
'--format' => 'directory',
|
||||
'--file' => "$tempdir/restore_roles",
|
||||
],
|
||||
restore_cmd => [
|
||||
'pg_restore', '-C',
|
||||
'--format' => 'directory',
|
||||
'--file' => "$tempdir/restore_roles.sql",
|
||||
"$tempdir/restore_roles",
|
||||
],
|
||||
like => qr/
|
||||
^\s*\QCREATE ROLE dumpall;\E\s*\n
|
||||
\s*\QALTER ROLE dumpall WITH SUPERUSER INHERIT NOCREATEROLE NOCREATEDB NOLOGIN NOREPLICATION NOBYPASSRLS PASSWORD 'SCRAM-SHA-256\E
|
||||
[^']+';\s*\n
|
||||
\s*\QCREATE ROLE dumpall2;\E
|
||||
\s*\QALTER ROLE dumpall2 WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB NOLOGIN REPLICATION NOBYPASSRLS CONNECTION LIMIT 10;\E
|
||||
/xm
|
||||
},
|
||||
|
||||
restore_tablespace => {
|
||||
setup_sql => "
|
||||
CREATE ROLE tap;
|
||||
CREATE TABLESPACE tbl1 OWNER tap LOCATION '$tablespace1';
|
||||
CREATE TABLESPACE tbl2 OWNER tap LOCATION '$tablespace2' WITH (seq_page_cost=1.0);",
|
||||
dump_cmd => [
|
||||
'pg_dumpall',
|
||||
'--format' => 'directory',
|
||||
'--file' => "$tempdir/restore_tablespace",
|
||||
],
|
||||
restore_cmd => [
|
||||
'pg_restore', '-C',
|
||||
'--format' => 'directory',
|
||||
'--file' => "$tempdir/restore_tablespace.sql",
|
||||
"$tempdir/restore_tablespace",
|
||||
],
|
||||
# Match "E" as optional since it is added on LOCATION when running on
|
||||
# Windows.
|
||||
like => qr/^
|
||||
\n\QCREATE TABLESPACE tbl1 OWNER tap LOCATION \E(?:E)?\Q'$tablespace1';\E
|
||||
\n\QCREATE TABLESPACE tbl2 OWNER tap LOCATION \E(?:E)?\Q'$tablespace2';\E
|
||||
\n\QALTER TABLESPACE tbl2 SET (seq_page_cost=1.0);\E
|
||||
/xm,
|
||||
},
|
||||
|
||||
restore_grants => {
|
||||
setup_sql => "
|
||||
CREATE DATABASE tapgrantsdb;
|
||||
CREATE SCHEMA private;
|
||||
CREATE SEQUENCE serial START 101;
|
||||
CREATE FUNCTION fn() RETURNS void AS \$\$
|
||||
BEGIN
|
||||
END;
|
||||
\$\$ LANGUAGE plpgsql;
|
||||
CREATE ROLE super;
|
||||
CREATE ROLE grant1;
|
||||
CREATE ROLE grant2;
|
||||
CREATE ROLE grant3;
|
||||
CREATE ROLE grant4;
|
||||
CREATE ROLE grant5;
|
||||
CREATE ROLE grant6;
|
||||
CREATE ROLE grant7;
|
||||
CREATE ROLE grant8;
|
||||
|
||||
CREATE TABLE t (id int);
|
||||
INSERT INTO t VALUES (1), (2), (3), (4);
|
||||
|
||||
GRANT SELECT ON TABLE t TO grant1;
|
||||
GRANT INSERT ON TABLE t TO grant2;
|
||||
GRANT ALL PRIVILEGES ON TABLE t to grant3;
|
||||
GRANT CONNECT, CREATE ON DATABASE tapgrantsdb TO grant4;
|
||||
GRANT USAGE, CREATE ON SCHEMA private TO grant5;
|
||||
GRANT USAGE, SELECT, UPDATE ON SEQUENCE serial TO grant6;
|
||||
GRANT super TO grant7;
|
||||
GRANT EXECUTE ON FUNCTION fn() TO grant8;
|
||||
",
|
||||
dump_cmd => [
|
||||
'pg_dumpall',
|
||||
'--format' => 'directory',
|
||||
'--file' => "$tempdir/restore_grants",
|
||||
],
|
||||
restore_cmd => [
|
||||
'pg_restore', '-C',
|
||||
'--format' => 'directory',
|
||||
'--file' => "$tempdir/restore_grants.sql",
|
||||
"$tempdir/restore_grants",
|
||||
],
|
||||
like => qr/^
|
||||
\n\QGRANT super TO grant7 WITH INHERIT TRUE GRANTED BY\E
|
||||
(.*\n)*
|
||||
\n\QGRANT ALL ON SCHEMA private TO grant5;\E
|
||||
(.*\n)*
|
||||
\n\QGRANT ALL ON FUNCTION public.fn() TO grant8;\E
|
||||
(.*\n)*
|
||||
\n\QGRANT ALL ON SEQUENCE public.serial TO grant6;\E
|
||||
(.*\n)*
|
||||
\n\QGRANT SELECT ON TABLE public.t TO grant1;\E
|
||||
\n\QGRANT INSERT ON TABLE public.t TO grant2;\E
|
||||
\n\QGRANT ALL ON TABLE public.t TO grant3;\E
|
||||
(.*\n)*
|
||||
\n\QGRANT CREATE,CONNECT ON DATABASE tapgrantsdb TO grant4;\E
|
||||
/xm,
|
||||
},
|
||||
|
||||
excluding_databases => {
|
||||
setup_sql => 'CREATE DATABASE db1;
|
||||
\c db1
|
||||
CREATE TABLE t1 (id int);
|
||||
INSERT INTO t1 VALUES (1), (2), (3), (4);
|
||||
CREATE TABLE t2 (id int);
|
||||
INSERT INTO t2 VALUES (1), (2), (3), (4);
|
||||
|
||||
CREATE DATABASE db2;
|
||||
\c db2
|
||||
CREATE TABLE t3 (id int);
|
||||
INSERT INTO t3 VALUES (1), (2), (3), (4);
|
||||
CREATE TABLE t4 (id int);
|
||||
INSERT INTO t4 VALUES (1), (2), (3), (4);
|
||||
|
||||
CREATE DATABASE dbex3;
|
||||
\c dbex3
|
||||
CREATE TABLE t5 (id int);
|
||||
INSERT INTO t5 VALUES (1), (2), (3), (4);
|
||||
CREATE TABLE t6 (id int);
|
||||
INSERT INTO t6 VALUES (1), (2), (3), (4);
|
||||
|
||||
CREATE DATABASE dbex4;
|
||||
\c dbex4
|
||||
CREATE TABLE t7 (id int);
|
||||
INSERT INTO t7 VALUES (1), (2), (3), (4);
|
||||
CREATE TABLE t8 (id int);
|
||||
INSERT INTO t8 VALUES (1), (2), (3), (4);
|
||||
|
||||
CREATE DATABASE db5;
|
||||
\c db5
|
||||
CREATE TABLE t9 (id int);
|
||||
INSERT INTO t9 VALUES (1), (2), (3), (4);
|
||||
CREATE TABLE t10 (id int);
|
||||
INSERT INTO t10 VALUES (1), (2), (3), (4);
|
||||
',
|
||||
dump_cmd => [
|
||||
'pg_dumpall',
|
||||
'--format' => 'directory',
|
||||
'--file' => "$tempdir/excluding_databases",
|
||||
'--exclude-database' => 'dbex*',
|
||||
],
|
||||
restore_cmd => [
|
||||
'pg_restore', '-C',
|
||||
'--format' => 'directory',
|
||||
'--file' => "$tempdir/excluding_databases.sql",
|
||||
'--exclude-database' => 'db5',
|
||||
"$tempdir/excluding_databases",
|
||||
],
|
||||
like => qr/^
|
||||
\n\QCREATE DATABASE db1\E
|
||||
(.*\n)*
|
||||
\n\QCREATE TABLE public.t1 (\E
|
||||
(.*\n)*
|
||||
\n\QCREATE TABLE public.t2 (\E
|
||||
(.*\n)*
|
||||
\n\QCREATE DATABASE db2\E
|
||||
(.*\n)*
|
||||
\n\QCREATE TABLE public.t3 (\E
|
||||
(.*\n)*
|
||||
\n\QCREATE TABLE public.t4 (/xm,
|
||||
unlike => qr/^
|
||||
\n\QCREATE DATABASE db3\E
|
||||
(.*\n)*
|
||||
\n\QCREATE TABLE public.t5 (\E
|
||||
(.*\n)*
|
||||
\n\QCREATE TABLE public.t6 (\E
|
||||
(.*\n)*
|
||||
\n\QCREATE DATABASE db4\E
|
||||
(.*\n)*
|
||||
\n\QCREATE TABLE public.t7 (\E
|
||||
(.*\n)*
|
||||
\n\QCREATE TABLE public.t8 (\E
|
||||
\n\QCREATE DATABASE db5\E
|
||||
(.*\n)*
|
||||
\n\QCREATE TABLE public.t9 (\E
|
||||
(.*\n)*
|
||||
\n\QCREATE TABLE public.t10 (\E
|
||||
/xm,
|
||||
},
|
||||
|
||||
format_directory => {
|
||||
setup_sql => "CREATE TABLE format_directory(a int, b boolean, c text);
|
||||
INSERT INTO format_directory VALUES (1, true, 'name1'), (2, false, 'name2');",
|
||||
dump_cmd => [
|
||||
'pg_dumpall',
|
||||
'--format' => 'directory',
|
||||
'--file' => "$tempdir/format_directory",
|
||||
],
|
||||
restore_cmd => [
|
||||
'pg_restore', '-C',
|
||||
'--format' => 'directory',
|
||||
'--file' => "$tempdir/format_directory.sql",
|
||||
"$tempdir/format_directory",
|
||||
],
|
||||
like => qr/^\n\QCOPY public.format_directory (a, b, c) FROM stdin;/xm
|
||||
},
|
||||
|
||||
format_tar => {
|
||||
setup_sql => "CREATE TABLE format_tar(a int, b boolean, c text);
|
||||
INSERT INTO format_tar VALUES (1, false, 'name3'), (2, true, 'name4');",
|
||||
dump_cmd => [
|
||||
'pg_dumpall',
|
||||
'--format' => 'tar',
|
||||
'--file' => "$tempdir/format_tar",
|
||||
],
|
||||
restore_cmd => [
|
||||
'pg_restore', '-C',
|
||||
'--format' => 'tar',
|
||||
'--file' => "$tempdir/format_tar.sql",
|
||||
"$tempdir/format_tar",
|
||||
],
|
||||
like => qr/^\n\QCOPY public.format_tar (a, b, c) FROM stdin;/xm
|
||||
},
|
||||
|
||||
format_custom => {
|
||||
setup_sql => "CREATE TABLE format_custom(a int, b boolean, c text);
|
||||
INSERT INTO format_custom VALUES (1, false, 'name5'), (2, true, 'name6');",
|
||||
dump_cmd => [
|
||||
'pg_dumpall',
|
||||
'--format' => 'custom',
|
||||
'--file' => "$tempdir/format_custom",
|
||||
],
|
||||
restore_cmd => [
|
||||
'pg_restore', '-C',
|
||||
'--format' => 'custom',
|
||||
'--file' => "$tempdir/format_custom.sql",
|
||||
"$tempdir/format_custom",
|
||||
],
|
||||
like => qr/^ \n\QCOPY public.format_custom (a, b, c) FROM stdin;/xm
|
||||
},
|
||||
|
||||
dump_globals_only => {
|
||||
setup_sql => "CREATE TABLE format_dir(a int, b boolean, c text);
|
||||
INSERT INTO format_dir VALUES (1, false, 'name5'), (2, true, 'name6');",
|
||||
dump_cmd => [
|
||||
'pg_dumpall',
|
||||
'--format' => 'directory',
|
||||
'--globals-only',
|
||||
'--file' => "$tempdir/dump_globals_only",
|
||||
],
|
||||
restore_cmd => [
|
||||
'pg_restore', '-C', '--globals-only',
|
||||
'--format' => 'directory',
|
||||
'--file' => "$tempdir/dump_globals_only.sql",
|
||||
"$tempdir/dump_globals_only",
|
||||
],
|
||||
like => qr/
|
||||
^\s*\QCREATE ROLE dumpall;\E\s*\n
|
||||
/xm
|
||||
}, );
|
||||
|
||||
# First execute the setup_sql
|
||||
foreach my $run (sort keys %pgdumpall_runs)
|
||||
{
|
||||
if ($pgdumpall_runs{$run}->{setup_sql})
|
||||
{
|
||||
$node->safe_psql($run_db, $pgdumpall_runs{$run}->{setup_sql});
|
||||
}
|
||||
}
|
||||
|
||||
# Execute the tests
|
||||
foreach my $run (sort keys %pgdumpall_runs)
|
||||
{
|
||||
# Create a new target cluster to pg_restore each test case run so that we
|
||||
# don't need to take care of the cleanup from the target cluster after each
|
||||
# run.
|
||||
my $target_node = PostgreSQL::Test::Cluster->new("target_$run");
|
||||
$target_node->init;
|
||||
$target_node->start;
|
||||
|
||||
# Dumpall from node cluster.
|
||||
$node->command_ok(\@{ $pgdumpall_runs{$run}->{dump_cmd} },
|
||||
"$run: pg_dumpall runs");
|
||||
|
||||
# Restore the dump on "target_node" cluster.
|
||||
my @restore_cmd = (
|
||||
@{ $pgdumpall_runs{$run}->{restore_cmd} },
|
||||
'--host', $target_node->host, '--port', $target_node->port);
|
||||
|
||||
my ($stdout, $stderr) = run_command(\@restore_cmd);
|
||||
|
||||
# pg_restore --file output file.
|
||||
my $output_file = slurp_file("$tempdir/${run}.sql");
|
||||
|
||||
if (!($pgdumpall_runs{$run}->{like}) && !($pgdumpall_runs{$run}->{unlike}))
|
||||
{
|
||||
die "missing \"like\" or \"unlike\" in test \"$run\"";
|
||||
}
|
||||
|
||||
if ($pgdumpall_runs{$run}->{like})
|
||||
{
|
||||
like($output_file, $pgdumpall_runs{$run}->{like}, "should dump $run");
|
||||
}
|
||||
|
||||
if ($pgdumpall_runs{$run}->{unlike})
|
||||
{
|
||||
unlike(
|
||||
$output_file,
|
||||
$pgdumpall_runs{$run}->{unlike},
|
||||
"should not dump $run");
|
||||
}
|
||||
}
|
||||
|
||||
# Some negative test case with dump of pg_dumpall and restore using pg_restore
|
||||
# test case 1: when -C is not used in pg_restore with dump of pg_dumpall
|
||||
$node->command_fails_like(
|
||||
[ 'pg_restore',
|
||||
"$tempdir/format_custom",
|
||||
'--format' => 'custom',
|
||||
'--file' => "$tempdir/error_test.sql", ],
|
||||
qr/\Qpg_restore: error: -C\/--create option should be specified when restoring multiple databases by archive of pg_dumpall\E/,
|
||||
'When -C is not used in pg_restore with dump of pg_dumpall');
|
||||
|
||||
# test case 2: When --list option is used with dump of pg_dumpall
|
||||
$node->command_fails_like(
|
||||
[ 'pg_restore',
|
||||
"$tempdir/format_custom", '-C',
|
||||
'--format' => 'custom', '--list',
|
||||
'--file' => "$tempdir/error_test.sql", ],
|
||||
qr/\Qpg_restore: error: option -l\/--list cannot be used when restoring multiple databases by archive of pg_dumpall\E/,
|
||||
'When --list is used in pg_restore with dump of pg_dumpall');
|
||||
|
||||
# test case 3: When non-exist database is given with -d option
|
||||
$node->command_fails_like(
|
||||
[ 'pg_restore',
|
||||
"$tempdir/format_custom", '-C',
|
||||
'--format' => 'custom',
|
||||
'-d' => 'dbpq', ],
|
||||
qr/\Qpg_restore: error: could not connect to database "dbpq"\E/,
|
||||
'When non-exist datbase is given with -d option in pg_restore with dump of pg_dumpall');
|
||||
|
||||
$node->stop('fast');
|
||||
|
||||
done_testing();
|
Reference in New Issue
Block a user