Rewrite pg_dump TAP tests

This reworks how the tests to run are defined.  Instead of having to
define all runs for all tests, we define those tests which should pass
(generally using one of the defined broad hashes), add in any which
should be specific for this test, and exclude any specific runs that
shouldn't pass for this test.  This ends up removing some 4k+ lines
(more than half the file) but, more importantly, greatly simplifies the
way runs-to-be-tested are defined.

As discussed in the updated comments, for example, take the test which
does CREATE TABLE test_table.  That CREATE TABLE should show up in all
'full' runs of pg_dump, except those cases where 'test_table' is
excluded, of course, and that's exactly how the test gets defined now
(modulo a few other related cases, like where we dump only that table,
or we dump the schema it's in, or we exclude the schema it's in):

like => {
    %full_runs,
    %dump_test_schema_runs,
    only_dump_test_table    => 1,
    section_pre_data        => 1, },
unlike => {
    exclude_dump_test_schema => 1,
    exclude_test_table => 1, }, },

Next, we no longer expect every run to be listed for every test.  If a
run is listed in 'like' (directly or through a hash) then it's a 'like',
unless it's listed in 'unlike' in which case it's an 'unlike'.  If it
isn't listed in either, then it's considered an 'unlike' automatically.

Lastly, this changes the code to no longer use like/unlike but rather to
use 'ok()' with 'diag()' which allows much more control over what gets
spit out to the screen.  Gone are the days of the entire dump being sent
to the console, now you'll just get a couple of lines for each failing
test which say the test that failed and the run that it failed on.

This covers both the pg_dump TAP tests in src/bin/pg_dump and those in
src/test/modules/test_pg_dump.
This commit is contained in:
Stephen Frost 2018-04-04 15:26:51 -04:00
parent cd1661bbcc
commit 446f7f5d78
2 changed files with 766 additions and 4686 deletions

File diff suppressed because it is too large Load Diff

View File

@ -58,11 +58,6 @@ my %pgdump_runs = (
'--if-exists',
'--encoding=UTF8', # no-op, just tests that option is accepted
'postgres', ], },
column_inserts => {
dump_cmd => [
'pg_dump', '--no-sync',
"--file=$tempdir/column_inserts.sql", '-a',
'--column-inserts', 'postgres', ], },
createdb => {
dump_cmd => [
'pg_dump',
@ -161,22 +156,14 @@ my %pgdump_runs = (
# file of each of the runs which the test is to be run against
# and the success of the result will depend on if the regexp
# result matches the expected 'like' or 'unlike' case.
# The runs listed as 'like' will be checked if they match the
# regexp and, if so, the test passes. All runs which are not
# listed as 'like' will be checked to ensure they don't match
# the regexp; if they do, the test will fail.
#
# For each test, there are two sets of runs defined, one for
# the 'like' tests and one for the 'unlike' tests. 'like'
# essentially means "the regexp for this test must match the
# output file". 'unlike' is the opposite.
#
# There are a few 'catch-all' tests which can be used to have
# a single, simple, test to over a range of other tests. For
# example, there is a '^CREATE ' test, which is used for the
# 'data-only' test as there should never be any kind of CREATE
# statement in a 'data-only' run. Without the catch-all, we
# would have to list the 'data-only' run in each and every
# 'CREATE xxxx' test, which would be a lot of additional tests.
#
# Note that it makes no sense for the same run to ever be listed
# in both 'like' and 'unlike' categories.
# The below hashes provide convenience sets of runs. Individual
# runs can be excluded from a general hash by placing that run
# into the 'unlike' section.
#
# There can then be a 'create_sql' and 'create_order' for a
# given test. The 'create_sql' commands are collected up in
@ -188,6 +175,18 @@ my %pgdump_runs = (
# included in it are compiled. This greatly improves performance
# as the regexps are used for each run the test applies to.
# Tests which are considered 'full' dumps by pg_dump, but there
# are flags used to exclude specific items (ACLs, blobs, etc).
my %full_runs = (
binary_upgrade => 1,
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_privs => 1,
no_owner => 1,
);
my %tests = (
'ALTER EXTENSION test_pg_dump' => {
create_order => 9,
@ -198,18 +197,7 @@ my %tests = (
\n\s+\Qcol1 integer NOT NULL,\E
\n\s+\Qcol2 integer\E
\n\);\n/xm,
like => { binary_upgrade => 1, },
unlike => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_privs => 1,
no_owner => 1,
pg_dumpall_globals => 1,
schema_only => 1,
section_pre_data => 1,
section_post_data => 1, }, },
like => { binary_upgrade => 1, }, },
'CREATE EXTENSION test_pg_dump' => {
create_order => 2,
@ -218,35 +206,17 @@ my %tests = (
\QCREATE EXTENSION IF NOT EXISTS test_pg_dump WITH SCHEMA public;\E
\n/xm,
like => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_privs => 1,
no_owner => 1,
schema_only => 1,
%full_runs,
schema_only => 1,
section_pre_data => 1, },
unlike => {
binary_upgrade => 1,
pg_dumpall_globals => 1,
section_post_data => 1, }, },
binary_upgrade => 1, }, },
'CREATE ROLE regress_dump_test_role' => {
create_order => 1,
create_sql => 'CREATE ROLE regress_dump_test_role;',
regexp => qr/^CREATE ROLE regress_dump_test_role;\n/m,
like => { pg_dumpall_globals => 1, },
unlike => {
binary_upgrade => 1,
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_privs => 1,
no_owner => 1,
schema_only => 1,
section_pre_data => 1,
section_post_data => 1, }, },
like => { pg_dumpall_globals => 1, }, },
'CREATE SEQUENCE regress_pg_dump_table_col1_seq' => {
regexp => qr/^
@ -258,18 +228,7 @@ my %tests = (
\n\s+\QNO MAXVALUE\E
\n\s+\QCACHE 1;\E
\n/xm,
like => { binary_upgrade => 1, },
unlike => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_privs => 1,
no_owner => 1,
pg_dumpall_globals => 1,
schema_only => 1,
section_pre_data => 1,
section_post_data => 1, }, },
like => { binary_upgrade => 1, }, },
'CREATE TABLE regress_pg_dump_table_added' => {
create_order => 7,
@ -280,18 +239,7 @@ my %tests = (
\n\s+\Qcol1 integer NOT NULL,\E
\n\s+\Qcol2 integer\E
\n\);\n/xm,
like => { binary_upgrade => 1, },
unlike => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_privs => 1,
no_owner => 1,
pg_dumpall_globals => 1,
schema_only => 1,
section_pre_data => 1,
section_post_data => 1, }, },
like => { binary_upgrade => 1, }, },
'CREATE SEQUENCE regress_pg_dump_seq' => {
regexp => qr/^
@ -302,18 +250,7 @@ my %tests = (
\n\s+\QNO MAXVALUE\E
\n\s+\QCACHE 1;\E
\n/xm,
like => { binary_upgrade => 1, },
unlike => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_privs => 1,
no_owner => 1,
pg_dumpall_globals => 1,
schema_only => 1,
section_pre_data => 1,
section_post_data => 1, }, },
like => { binary_upgrade => 1, }, },
'SETVAL SEQUENCE regress_seq_dumpable' => {
create_order => 6,
@ -322,18 +259,9 @@ my %tests = (
\QSELECT pg_catalog.setval('public.regress_seq_dumpable', 1, true);\E
\n/xm,
like => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
data_only => 1,
defaults => 1,
no_owner => 1,
no_privs => 1, },
unlike => {
pg_dumpall_globals => 1,
schema_only => 1,
section_pre_data => 1,
section_post_data => 1, }, },
%full_runs,
data_only => 1,
section_data => 1, }, },
'CREATE TABLE regress_pg_dump_table' => {
regexp => qr/^
@ -341,35 +269,13 @@ my %tests = (
\n\s+\Qcol1 integer NOT NULL,\E
\n\s+\Qcol2 integer\E
\n\);\n/xm,
like => { binary_upgrade => 1, },
unlike => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_privs => 1,
no_owner => 1,
pg_dumpall_globals => 1,
schema_only => 1,
section_pre_data => 1,
section_post_data => 1, }, },
like => { binary_upgrade => 1, }, },
'CREATE ACCESS METHOD regress_test_am' => {
regexp => qr/^
\QCREATE ACCESS METHOD regress_test_am TYPE INDEX HANDLER bthandler;\E
\n/xm,
like => { binary_upgrade => 1, },
unlike => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_privs => 1,
no_owner => 1,
pg_dumpall_globals => 1,
schema_only => 1,
section_pre_data => 1,
section_post_data => 1, }, },
like => { binary_upgrade => 1, }, },
'COMMENT ON EXTENSION test_pg_dump' => {
regexp => qr/^
@ -377,18 +283,9 @@ my %tests = (
\QIS 'Test pg_dump with an extension';\E
\n/xm,
like => {
binary_upgrade => 1,
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_privs => 1,
no_owner => 1,
%full_runs,
schema_only => 1,
section_pre_data => 1, },
unlike => {
pg_dumpall_globals => 1,
section_post_data => 1, }, },
section_pre_data => 1, }, },
'GRANT SELECT regress_pg_dump_table_added pre-ALTER EXTENSION' => {
create_order => 8,
@ -397,18 +294,7 @@ my %tests = (
regexp => qr/^
\QGRANT SELECT ON TABLE public.regress_pg_dump_table_added TO regress_dump_test_role;\E
\n/xm,
like => { binary_upgrade => 1, },
unlike => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_privs => 1,
no_owner => 1,
pg_dumpall_globals => 1,
schema_only => 1,
section_pre_data => 1,
section_post_data => 1, }, },
like => { binary_upgrade => 1, }, },
'REVOKE SELECT regress_pg_dump_table_added post-ALTER EXTENSION' => {
create_order => 10,
@ -418,18 +304,11 @@ my %tests = (
\QREVOKE SELECT ON TABLE public.regress_pg_dump_table_added FROM regress_dump_test_role;\E
\n/xm,
like => {
binary_upgrade => 1,
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_owner => 1,
%full_runs,
schema_only => 1,
section_pre_data => 1, },
unlike => {
no_privs => 1,
pg_dumpall_globals => 1,
section_post_data => 1, }, },
no_privs => 1, }, },
'GRANT SELECT ON TABLE regress_pg_dump_table' => {
regexp => qr/^
@ -437,18 +316,7 @@ my %tests = (
\QGRANT SELECT ON TABLE public.regress_pg_dump_table TO regress_dump_test_role;\E\n
\QSELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\E
\n/xms,
like => { binary_upgrade => 1, },
unlike => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_owner => 1,
schema_only => 1,
section_pre_data => 1,
no_privs => 1,
pg_dumpall_globals => 1,
section_post_data => 1, }, },
like => { binary_upgrade => 1, }, },
'GRANT SELECT(col1) ON regress_pg_dump_table' => {
regexp => qr/^
@ -456,18 +324,7 @@ my %tests = (
\QGRANT SELECT(col1) ON TABLE public.regress_pg_dump_table TO PUBLIC;\E\n
\QSELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\E
\n/xms,
like => { binary_upgrade => 1, },
unlike => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_owner => 1,
schema_only => 1,
section_pre_data => 1,
no_privs => 1,
pg_dumpall_globals => 1,
section_post_data => 1, }, },
like => { binary_upgrade => 1, }, },
'GRANT SELECT(col2) ON regress_pg_dump_table TO regress_dump_test_role' =>
{ create_order => 4,
@ -477,18 +334,11 @@ my %tests = (
\QGRANT SELECT(col2) ON TABLE public.regress_pg_dump_table TO regress_dump_test_role;\E
\n/xm,
like => {
binary_upgrade => 1,
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_owner => 1,
%full_runs,
schema_only => 1,
section_pre_data => 1, },
unlike => {
no_privs => 1,
pg_dumpall_globals => 1,
section_post_data => 1, }, },
no_privs => 1, }, },
'GRANT USAGE ON regress_pg_dump_table_col1_seq TO regress_dump_test_role'
=> {
@ -499,35 +349,17 @@ my %tests = (
\QGRANT USAGE ON SEQUENCE public.regress_pg_dump_table_col1_seq TO regress_dump_test_role;\E
\n/xm,
like => {
binary_upgrade => 1,
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_owner => 1,
%full_runs,
schema_only => 1,
section_pre_data => 1, },
unlike => {
no_privs => 1,
pg_dumpall_globals => 1,
section_post_data => 1, }, },
no_privs => 1, }, },
'GRANT USAGE ON regress_pg_dump_seq TO regress_dump_test_role' => {
regexp => qr/^
\QGRANT USAGE ON SEQUENCE public.regress_pg_dump_seq TO regress_dump_test_role;\E
\n/xm,
like => { binary_upgrade => 1, },
unlike => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_owner => 1,
no_privs => 1,
pg_dumpall_globals => 1,
schema_only => 1,
section_pre_data => 1,
section_post_data => 1, }, },
like => { binary_upgrade => 1, }, },
'REVOKE SELECT(col1) ON regress_pg_dump_table' => {
create_order => 3,
@ -537,18 +369,11 @@ my %tests = (
\QREVOKE SELECT(col1) ON TABLE public.regress_pg_dump_table FROM PUBLIC;\E
\n/xm,
like => {
binary_upgrade => 1,
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_owner => 1,
%full_runs,
schema_only => 1,
section_pre_data => 1, },
unlike => {
no_privs => 1,
pg_dumpall_globals => 1,
section_post_data => 1, }, },
no_privs => 1, }, },
# Objects included in extension part of a schema created by this extension */
'CREATE TABLE regress_pg_dump_schema.test_table' => {
@ -557,18 +382,7 @@ my %tests = (
\n\s+\Qcol1 integer,\E
\n\s+\Qcol2 integer\E
\n\);\n/xm,
like => { binary_upgrade => 1, },
unlike => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_privs => 1,
no_owner => 1,
pg_dumpall_globals => 1,
schema_only => 1,
section_pre_data => 1,
section_post_data => 1, }, },
like => { binary_upgrade => 1, }, },
'GRANT SELECT ON regress_pg_dump_schema.test_table' => {
regexp => qr/^
@ -576,18 +390,7 @@ my %tests = (
\QGRANT SELECT ON TABLE regress_pg_dump_schema.test_table TO regress_dump_test_role;\E\n
\QSELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\E
\n/xms,
like => { binary_upgrade => 1, },
unlike => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_owner => 1,
no_privs => 1,
pg_dumpall_globals => 1,
schema_only => 1,
section_pre_data => 1,
section_post_data => 1, }, },
like => { binary_upgrade => 1, }, },
'CREATE SEQUENCE regress_pg_dump_schema.test_seq' => {
regexp => qr/^
@ -598,18 +401,7 @@ my %tests = (
\n\s+\QNO MAXVALUE\E
\n\s+\QCACHE 1;\E
\n/xm,
like => { binary_upgrade => 1, },
unlike => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_privs => 1,
no_owner => 1,
pg_dumpall_globals => 1,
schema_only => 1,
section_pre_data => 1,
section_post_data => 1, }, },
like => { binary_upgrade => 1, }, },
'GRANT USAGE ON regress_pg_dump_schema.test_seq' => {
regexp => qr/^
@ -617,36 +409,14 @@ my %tests = (
\QGRANT USAGE ON SEQUENCE regress_pg_dump_schema.test_seq TO regress_dump_test_role;\E\n
\QSELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\E
\n/xms,
like => { binary_upgrade => 1, },
unlike => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_owner => 1,
no_privs => 1,
pg_dumpall_globals => 1,
schema_only => 1,
section_pre_data => 1,
section_post_data => 1, }, },
like => { binary_upgrade => 1, }, },
'CREATE TYPE regress_pg_dump_schema.test_type' => {
regexp => qr/^
\QCREATE TYPE regress_pg_dump_schema.test_type AS (\E
\n\s+\Qcol1 integer\E
\n\);\n/xm,
like => { binary_upgrade => 1, },
unlike => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_privs => 1,
no_owner => 1,
pg_dumpall_globals => 1,
schema_only => 1,
section_pre_data => 1,
section_post_data => 1, }, },
like => { binary_upgrade => 1, }, },
'GRANT USAGE ON regress_pg_dump_schema.test_type' => {
regexp => qr/^
@ -654,36 +424,14 @@ my %tests = (
\QGRANT ALL ON TYPE regress_pg_dump_schema.test_type TO regress_dump_test_role;\E\n
\QSELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\E
\n/xms,
like => { binary_upgrade => 1, },
unlike => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_owner => 1,
no_privs => 1,
pg_dumpall_globals => 1,
schema_only => 1,
section_pre_data => 1,
section_post_data => 1, }, },
like => { binary_upgrade => 1, }, },
'CREATE FUNCTION regress_pg_dump_schema.test_func' => {
regexp => qr/^
\QCREATE FUNCTION regress_pg_dump_schema.test_func() RETURNS integer\E
\n\s+\QLANGUAGE sql\E
\n/xm,
like => { binary_upgrade => 1, },
unlike => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_privs => 1,
no_owner => 1,
pg_dumpall_globals => 1,
schema_only => 1,
section_pre_data => 1,
section_post_data => 1, }, },
like => { binary_upgrade => 1, }, },
'GRANT ALL ON regress_pg_dump_schema.test_func' => {
regexp => qr/^
@ -691,18 +439,7 @@ my %tests = (
\QGRANT ALL ON FUNCTION regress_pg_dump_schema.test_func() TO regress_dump_test_role;\E\n
\QSELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\E
\n/xms,
like => { binary_upgrade => 1, },
unlike => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_owner => 1,
no_privs => 1,
pg_dumpall_globals => 1,
schema_only => 1,
section_pre_data => 1,
section_post_data => 1, }, },
like => { binary_upgrade => 1, }, },
'CREATE AGGREGATE regress_pg_dump_schema.test_agg' => {
regexp => qr/^
@ -710,18 +447,7 @@ my %tests = (
\n\s+\QSFUNC = int2_sum,\E
\n\s+\QSTYPE = bigint\E
\n\);\n/xm,
like => { binary_upgrade => 1, },
unlike => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_privs => 1,
no_owner => 1,
pg_dumpall_globals => 1,
schema_only => 1,
section_pre_data => 1,
section_post_data => 1, }, },
like => { binary_upgrade => 1, }, },
'GRANT ALL ON regress_pg_dump_schema.test_agg' => {
regexp => qr/^
@ -729,18 +455,7 @@ my %tests = (
\QGRANT ALL ON FUNCTION regress_pg_dump_schema.test_agg(smallint) TO regress_dump_test_role;\E\n
\QSELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\E
\n/xms,
like => { binary_upgrade => 1, },
unlike => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_owner => 1,
no_privs => 1,
pg_dumpall_globals => 1,
schema_only => 1,
section_pre_data => 1,
section_post_data => 1, }, },
like => { binary_upgrade => 1, }, },
# Objects not included in extension, part of schema created by extension
'CREATE TABLE regress_pg_dump_schema.external_tab' => {
@ -752,18 +467,10 @@ my %tests = (
\n\s+\Qcol1 integer\E
\n\);\n/xm,
like => {
binary_upgrade => 1,
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
no_owner => 1,
no_privs => 1,
schema_only => 1,
section_pre_data => 1, },
unlike => {
pg_dumpall_globals => 1,
section_post_data => 1, }, },);
%full_runs,
schema_only => 1,
section_pre_data => 1, }, },
);
#########################################
# Create a PG instance to test actually dumping from
@ -797,13 +504,14 @@ foreach my $run (sort keys %pgdump_runs)
# Then count all the tests run against each run
foreach my $test (sort keys %tests)
{
if ($tests{$test}->{like}->{$test_key})
# If there is a like entry, but no unlike entry, then we will test the like case
if ($tests{$test}->{like}->{$test_key} && !defined($tests{$test}->{unlike}->{$test_key}))
{
$num_tests++;
}
if ($tests{$test}->{unlike}->{$test_key})
else
{
# We will test everything that isn't a 'like'
$num_tests++;
}
}
@ -875,17 +583,24 @@ foreach my $run (sort keys %pgdump_runs)
foreach my $test (sort keys %tests)
{
if ($tests{$test}->{like}->{$test_key})
# Run the test listed as a like, unless it is specifically noted
# as an unlike (generally due to an explicit exclusion or similar).
if ($tests{$test}->{like}->{$test_key} && !defined($tests{$test}->{unlike}->{$test_key}))
{
like($output_file, $tests{$test}->{regexp}, "$run: dumps $test");
if (!ok($output_file =~ $tests{$test}->{regexp}, "$run: should dump $test"))
{
diag("Review $run results in $tempdir");
}
}
if ($tests{$test}->{unlike}->{$test_key})
else
{
unlike(
$output_file,
$tests{$test}->{regexp},
"$run: does not dump $test");
if (!ok(
$output_file !~
$tests{$test}->{regexp},
"$run: should not dump $test"))
{
diag("Review $run results in $tempdir");
}
}
}
}