mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
Reindent Perl files with perltidy version 20170521.
Discussion: https://postgr.es/m/CABUevEzK3cNiHZQ18f5tK0guoT+cN_jWeVzhYYxY=r+1Q3SmoA@mail.gmail.com
This commit is contained in:
@ -17,12 +17,12 @@ my ($krb5_bin_dir, $krb5_sbin_dir);
|
||||
|
||||
if ($^O eq 'darwin')
|
||||
{
|
||||
$krb5_bin_dir = '/usr/local/opt/krb5/bin';
|
||||
$krb5_bin_dir = '/usr/local/opt/krb5/bin';
|
||||
$krb5_sbin_dir = '/usr/local/opt/krb5/sbin';
|
||||
}
|
||||
elsif ($^O eq 'freebsd')
|
||||
{
|
||||
$krb5_bin_dir = '/usr/local/bin';
|
||||
$krb5_bin_dir = '/usr/local/bin';
|
||||
$krb5_sbin_dir = '/usr/local/sbin';
|
||||
}
|
||||
elsif ($^O eq 'linux')
|
||||
@ -30,45 +30,48 @@ elsif ($^O eq 'linux')
|
||||
$krb5_sbin_dir = '/usr/sbin';
|
||||
}
|
||||
|
||||
my $krb5_config = 'krb5-config';
|
||||
my $kinit = 'kinit';
|
||||
my $kdb5_util = 'kdb5_util';
|
||||
my $krb5_config = 'krb5-config';
|
||||
my $kinit = 'kinit';
|
||||
my $kdb5_util = 'kdb5_util';
|
||||
my $kadmin_local = 'kadmin.local';
|
||||
my $krb5kdc = 'krb5kdc';
|
||||
my $krb5kdc = 'krb5kdc';
|
||||
|
||||
if ($krb5_bin_dir && -d $krb5_bin_dir)
|
||||
{
|
||||
$krb5_config = $krb5_bin_dir . '/' . $krb5_config;
|
||||
$kinit = $krb5_bin_dir . '/' . $kinit;
|
||||
$kinit = $krb5_bin_dir . '/' . $kinit;
|
||||
}
|
||||
if ($krb5_sbin_dir && -d $krb5_sbin_dir)
|
||||
{
|
||||
$kdb5_util = $krb5_sbin_dir . '/' . $kdb5_util;
|
||||
$kdb5_util = $krb5_sbin_dir . '/' . $kdb5_util;
|
||||
$kadmin_local = $krb5_sbin_dir . '/' . $kadmin_local;
|
||||
$krb5kdc = $krb5_sbin_dir . '/' . $krb5kdc;
|
||||
$krb5kdc = $krb5_sbin_dir . '/' . $krb5kdc;
|
||||
}
|
||||
|
||||
my $realm = 'EXAMPLE.COM';
|
||||
|
||||
my $krb5_conf = "${TestLib::tmp_check}/krb5.conf";
|
||||
my $kdc_conf = "${TestLib::tmp_check}/kdc.conf";
|
||||
my $krb5_log = "${TestLib::tmp_check}/krb5libs.log";
|
||||
my $kdc_log = "${TestLib::tmp_check}/krb5kdc.log";
|
||||
my $kdc_port = int(rand() * 16384) + 49152;
|
||||
my $krb5_conf = "${TestLib::tmp_check}/krb5.conf";
|
||||
my $kdc_conf = "${TestLib::tmp_check}/kdc.conf";
|
||||
my $krb5_log = "${TestLib::tmp_check}/krb5libs.log";
|
||||
my $kdc_log = "${TestLib::tmp_check}/krb5kdc.log";
|
||||
my $kdc_port = int(rand() * 16384) + 49152;
|
||||
my $kdc_datadir = "${TestLib::tmp_check}/krb5kdc";
|
||||
my $kdc_pidfile = "${TestLib::tmp_check}/krb5kdc.pid";
|
||||
my $keytab = "${TestLib::tmp_check}/krb5.keytab";
|
||||
my $keytab = "${TestLib::tmp_check}/krb5.keytab";
|
||||
|
||||
note "setting up Kerberos";
|
||||
|
||||
my ($stdout, $krb5_version);
|
||||
run_log [ $krb5_config, '--version' ], '>', \$stdout or BAIL_OUT("could not execute krb5-config");
|
||||
run_log [ $krb5_config, '--version' ], '>', \$stdout
|
||||
or BAIL_OUT("could not execute krb5-config");
|
||||
BAIL_OUT("Heimdal is not supported") if $stdout =~ m/heimdal/;
|
||||
$stdout =~ m/Kerberos 5 release ([0-9]+\.[0-9]+)/ or BAIL_OUT("could not get Kerberos version");
|
||||
$stdout =~ m/Kerberos 5 release ([0-9]+\.[0-9]+)/
|
||||
or BAIL_OUT("could not get Kerberos version");
|
||||
$krb5_version = $1;
|
||||
|
||||
append_to_file($krb5_conf,
|
||||
qq![logging]
|
||||
append_to_file(
|
||||
$krb5_conf,
|
||||
qq![logging]
|
||||
default = FILE:$krb5_log
|
||||
kdc = FILE:$kdc_log
|
||||
|
||||
@ -80,27 +83,32 @@ $realm = {
|
||||
kdc = localhost:$kdc_port
|
||||
}!);
|
||||
|
||||
append_to_file($kdc_conf,
|
||||
qq![kdcdefaults]
|
||||
append_to_file(
|
||||
$kdc_conf,
|
||||
qq![kdcdefaults]
|
||||
!);
|
||||
|
||||
# For new-enough versions of krb5, use the _listen settings rather
|
||||
# than the _ports settings so that we can bind to localhost only.
|
||||
if ($krb5_version >= 1.15)
|
||||
{
|
||||
append_to_file($kdc_conf,
|
||||
qq!kdc_listen = localhost:$kdc_port
|
||||
append_to_file(
|
||||
$kdc_conf,
|
||||
qq!kdc_listen = localhost:$kdc_port
|
||||
kdc_tcp_listen = localhost:$kdc_port
|
||||
!);
|
||||
}
|
||||
else
|
||||
{
|
||||
append_to_file($kdc_conf,
|
||||
qq!kdc_ports = $kdc_port
|
||||
append_to_file(
|
||||
$kdc_conf,
|
||||
qq!kdc_ports = $kdc_port
|
||||
kdc_tcp_ports = $kdc_port
|
||||
!);
|
||||
}
|
||||
append_to_file($kdc_conf,
|
||||
qq!
|
||||
append_to_file(
|
||||
$kdc_conf,
|
||||
qq!
|
||||
[realms]
|
||||
$realm = {
|
||||
database_name = $kdc_datadir/principal
|
||||
@ -111,7 +119,7 @@ $realm = {
|
||||
|
||||
mkdir $kdc_datadir or die;
|
||||
|
||||
$ENV{'KRB5_CONFIG'} = $krb5_conf;
|
||||
$ENV{'KRB5_CONFIG'} = $krb5_conf;
|
||||
$ENV{'KRB5_KDC_PROFILE'} = $kdc_conf;
|
||||
|
||||
my $service_principal = "$ENV{with_krb_srvnam}/localhost";
|
||||
@ -128,7 +136,7 @@ system_or_bail $krb5kdc, '-P', $kdc_pidfile;
|
||||
|
||||
END
|
||||
{
|
||||
kill 'INT', `cat $kdc_pidfile` if -f $kdc_pidfile;
|
||||
kill 'INT', `cat $kdc_pidfile` if -f $kdc_pidfile;
|
||||
}
|
||||
|
||||
note "setting up PostgreSQL instance";
|
||||
@ -148,9 +156,12 @@ sub test_access
|
||||
my ($node, $role, $expected_res, $test_name) = @_;
|
||||
|
||||
# need to connect over TCP/IP for Kerberos
|
||||
my $res = $node->psql('postgres', 'SELECT 1',
|
||||
extra_params => [ '-d', $node->connstr('postgres').' host=localhost',
|
||||
'-U', $role ]);
|
||||
my $res = $node->psql(
|
||||
'postgres',
|
||||
'SELECT 1',
|
||||
extra_params => [
|
||||
'-d', $node->connstr('postgres') . ' host=localhost',
|
||||
'-U', $role ]);
|
||||
is($res, $expected_res, $test_name);
|
||||
}
|
||||
|
||||
@ -171,7 +182,8 @@ test_access($node, 'test1', 0, 'succeeds with mapping');
|
||||
|
||||
truncate($node->data_dir . '/pg_ident.conf', 0);
|
||||
unlink($node->data_dir . '/pg_hba.conf');
|
||||
$node->append_conf('pg_hba.conf', qq{host all all localhost gss include_realm=0});
|
||||
$node->append_conf('pg_hba.conf',
|
||||
qq{host all all localhost gss include_realm=0});
|
||||
$node->restart;
|
||||
|
||||
test_access($node, 'test1', 0, 'succeeds with include_realm=0');
|
||||
|
@ -15,22 +15,22 @@ else
|
||||
|
||||
my ($slapd, $ldap_bin_dir, $ldap_schema_dir);
|
||||
|
||||
$ldap_bin_dir = undef; # usually in PATH
|
||||
$ldap_bin_dir = undef; # usually in PATH
|
||||
|
||||
if ($^O eq 'darwin')
|
||||
{
|
||||
$slapd = '/usr/local/opt/openldap/libexec/slapd';
|
||||
$slapd = '/usr/local/opt/openldap/libexec/slapd';
|
||||
$ldap_schema_dir = '/usr/local/etc/openldap/schema';
|
||||
}
|
||||
elsif ($^O eq 'linux')
|
||||
{
|
||||
$slapd = '/usr/sbin/slapd';
|
||||
$slapd = '/usr/sbin/slapd';
|
||||
$ldap_schema_dir = '/etc/ldap/schema' if -d '/etc/ldap/schema';
|
||||
$ldap_schema_dir = '/etc/openldap/schema' if -d '/etc/openldap/schema';
|
||||
}
|
||||
elsif ($^O eq 'freebsd')
|
||||
{
|
||||
$slapd = '/usr/local/libexec/slapd';
|
||||
$slapd = '/usr/local/libexec/slapd';
|
||||
$ldap_schema_dir = '/usr/local/etc/openldap/schema';
|
||||
}
|
||||
|
||||
@ -41,26 +41,27 @@ elsif ($^O eq 'freebsd')
|
||||
|
||||
$ENV{PATH} = "$ldap_bin_dir:$ENV{PATH}" if $ldap_bin_dir;
|
||||
|
||||
my $ldap_datadir = "${TestLib::tmp_check}/openldap-data";
|
||||
my $slapd_certs = "${TestLib::tmp_check}/slapd-certs";
|
||||
my $slapd_conf = "${TestLib::tmp_check}/slapd.conf";
|
||||
my $ldap_datadir = "${TestLib::tmp_check}/openldap-data";
|
||||
my $slapd_certs = "${TestLib::tmp_check}/slapd-certs";
|
||||
my $slapd_conf = "${TestLib::tmp_check}/slapd.conf";
|
||||
my $slapd_pidfile = "${TestLib::tmp_check}/slapd.pid";
|
||||
my $slapd_logfile = "${TestLib::tmp_check}/slapd.log";
|
||||
my $ldap_conf = "${TestLib::tmp_check}/ldap.conf";
|
||||
my $ldap_server = 'localhost';
|
||||
my $ldap_port = int(rand() * 16384) + 49152;
|
||||
my $ldaps_port = $ldap_port + 1;
|
||||
my $ldap_url = "ldap://$ldap_server:$ldap_port";
|
||||
my $ldaps_url = "ldaps://$ldap_server:$ldaps_port";
|
||||
my $ldap_basedn = 'dc=example,dc=net';
|
||||
my $ldap_rootdn = 'cn=Manager,dc=example,dc=net';
|
||||
my $ldap_rootpw = 'secret';
|
||||
my $ldap_pwfile = "${TestLib::tmp_check}/ldappassword";
|
||||
my $ldap_conf = "${TestLib::tmp_check}/ldap.conf";
|
||||
my $ldap_server = 'localhost';
|
||||
my $ldap_port = int(rand() * 16384) + 49152;
|
||||
my $ldaps_port = $ldap_port + 1;
|
||||
my $ldap_url = "ldap://$ldap_server:$ldap_port";
|
||||
my $ldaps_url = "ldaps://$ldap_server:$ldaps_port";
|
||||
my $ldap_basedn = 'dc=example,dc=net';
|
||||
my $ldap_rootdn = 'cn=Manager,dc=example,dc=net';
|
||||
my $ldap_rootpw = 'secret';
|
||||
my $ldap_pwfile = "${TestLib::tmp_check}/ldappassword";
|
||||
|
||||
note "setting up slapd";
|
||||
|
||||
append_to_file($slapd_conf,
|
||||
qq{include $ldap_schema_dir/core.schema
|
||||
append_to_file(
|
||||
$slapd_conf,
|
||||
qq{include $ldap_schema_dir/core.schema
|
||||
include $ldap_schema_dir/cosine.schema
|
||||
include $ldap_schema_dir/nis.schema
|
||||
include $ldap_schema_dir/inetorgperson.schema
|
||||
@ -84,16 +85,23 @@ rootdn "$ldap_rootdn"
|
||||
rootpw $ldap_rootpw});
|
||||
|
||||
# don't bother to check the server's cert (though perhaps we should)
|
||||
append_to_file($ldap_conf,
|
||||
qq{TLS_REQCERT never
|
||||
append_to_file(
|
||||
$ldap_conf,
|
||||
qq{TLS_REQCERT never
|
||||
});
|
||||
|
||||
mkdir $ldap_datadir or die;
|
||||
mkdir $slapd_certs or die;
|
||||
mkdir $slapd_certs or die;
|
||||
|
||||
system_or_bail "openssl", "req", "-new", "-nodes", "-keyout", "$slapd_certs/ca.key", "-x509", "-out", "$slapd_certs/ca.crt", "-subj", "/cn=CA";
|
||||
system_or_bail "openssl", "req", "-new", "-nodes", "-keyout", "$slapd_certs/server.key", "-out", "$slapd_certs/server.csr", "-subj", "/cn=server";
|
||||
system_or_bail "openssl", "x509", "-req", "-in", "$slapd_certs/server.csr", "-CA", "$slapd_certs/ca.crt", "-CAkey", "$slapd_certs/ca.key", "-CAcreateserial", "-out", "$slapd_certs/server.crt";
|
||||
system_or_bail "openssl", "req", "-new", "-nodes", "-keyout",
|
||||
"$slapd_certs/ca.key", "-x509", "-out", "$slapd_certs/ca.crt", "-subj",
|
||||
"/cn=CA";
|
||||
system_or_bail "openssl", "req", "-new", "-nodes", "-keyout",
|
||||
"$slapd_certs/server.key", "-out", "$slapd_certs/server.csr", "-subj",
|
||||
"/cn=server";
|
||||
system_or_bail "openssl", "x509", "-req", "-in", "$slapd_certs/server.csr",
|
||||
"-CA", "$slapd_certs/ca.crt", "-CAkey", "$slapd_certs/ca.key",
|
||||
"-CAcreateserial", "-out", "$slapd_certs/server.crt";
|
||||
|
||||
system_or_bail $slapd, '-f', $slapd_conf, '-h', "$ldap_url $ldaps_url";
|
||||
|
||||
@ -105,15 +113,17 @@ END
|
||||
append_to_file($ldap_pwfile, $ldap_rootpw);
|
||||
chmod 0600, $ldap_pwfile or die;
|
||||
|
||||
$ENV{'LDAPURI'} = $ldap_url;
|
||||
$ENV{'LDAPURI'} = $ldap_url;
|
||||
$ENV{'LDAPBINDDN'} = $ldap_rootdn;
|
||||
$ENV{'LDAPCONF'} = $ldap_conf;
|
||||
$ENV{'LDAPCONF'} = $ldap_conf;
|
||||
|
||||
note "loading LDAP data";
|
||||
|
||||
system_or_bail 'ldapadd', '-x', '-y', $ldap_pwfile, '-f', 'authdata.ldif';
|
||||
system_or_bail 'ldappasswd', '-x', '-y', $ldap_pwfile, '-s', 'secret1', 'uid=test1,dc=example,dc=net';
|
||||
system_or_bail 'ldappasswd', '-x', '-y', $ldap_pwfile, '-s', 'secret2', 'uid=test2,dc=example,dc=net';
|
||||
system_or_bail 'ldapadd', '-x', '-y', $ldap_pwfile, '-f', 'authdata.ldif';
|
||||
system_or_bail 'ldappasswd', '-x', '-y', $ldap_pwfile, '-s', 'secret1',
|
||||
'uid=test1,dc=example,dc=net';
|
||||
system_or_bail 'ldappasswd', '-x', '-y', $ldap_pwfile, '-s', 'secret2',
|
||||
'uid=test2,dc=example,dc=net';
|
||||
|
||||
note "setting up PostgreSQL instance";
|
||||
|
||||
@ -131,50 +141,66 @@ sub test_access
|
||||
{
|
||||
my ($node, $role, $expected_res, $test_name) = @_;
|
||||
|
||||
my $res = $node->psql('postgres', 'SELECT 1', extra_params => [ '-U', $role ]);
|
||||
is($res, $expected_res, $test_name);
|
||||
my $res =
|
||||
$node->psql('postgres', 'SELECT 1', extra_params => [ '-U', $role ]);
|
||||
is($res, $expected_res, $test_name);
|
||||
}
|
||||
|
||||
note "simple bind";
|
||||
|
||||
unlink($node->data_dir . '/pg_hba.conf');
|
||||
$node->append_conf('pg_hba.conf', qq{local all all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapprefix="uid=" ldapsuffix=",dc=example,dc=net"});
|
||||
$node->append_conf('pg_hba.conf',
|
||||
qq{local all all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapprefix="uid=" ldapsuffix=",dc=example,dc=net"}
|
||||
);
|
||||
$node->restart;
|
||||
|
||||
$ENV{"PGPASSWORD"} = 'wrong';
|
||||
test_access($node, 'test0', 2, 'simple bind authentication fails if user not found in LDAP');
|
||||
test_access($node, 'test1', 2, 'simple bind authentication fails with wrong password');
|
||||
test_access($node, 'test0', 2,
|
||||
'simple bind authentication fails if user not found in LDAP');
|
||||
test_access($node, 'test1', 2,
|
||||
'simple bind authentication fails with wrong password');
|
||||
$ENV{"PGPASSWORD"} = 'secret1';
|
||||
test_access($node, 'test1', 0, 'simple bind authentication succeeds');
|
||||
|
||||
note "search+bind";
|
||||
|
||||
unlink($node->data_dir . '/pg_hba.conf');
|
||||
$node->append_conf('pg_hba.conf', qq{local all all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapbasedn="$ldap_basedn"});
|
||||
$node->append_conf('pg_hba.conf',
|
||||
qq{local all all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapbasedn="$ldap_basedn"}
|
||||
);
|
||||
$node->restart;
|
||||
|
||||
$ENV{"PGPASSWORD"} = 'wrong';
|
||||
test_access($node, 'test0', 2, 'search+bind authentication fails if user not found in LDAP');
|
||||
test_access($node, 'test1', 2, 'search+bind authentication fails with wrong password');
|
||||
test_access($node, 'test0', 2,
|
||||
'search+bind authentication fails if user not found in LDAP');
|
||||
test_access($node, 'test1', 2,
|
||||
'search+bind authentication fails with wrong password');
|
||||
$ENV{"PGPASSWORD"} = 'secret1';
|
||||
test_access($node, 'test1', 0, 'search+bind authentication succeeds');
|
||||
|
||||
note "LDAP URLs";
|
||||
|
||||
unlink($node->data_dir . '/pg_hba.conf');
|
||||
$node->append_conf('pg_hba.conf', qq{local all all ldap ldapurl="$ldap_url/$ldap_basedn?uid?sub"});
|
||||
$node->append_conf('pg_hba.conf',
|
||||
qq{local all all ldap ldapurl="$ldap_url/$ldap_basedn?uid?sub"});
|
||||
$node->restart;
|
||||
|
||||
$ENV{"PGPASSWORD"} = 'wrong';
|
||||
test_access($node, 'test0', 2, 'search+bind with LDAP URL authentication fails if user not found in LDAP');
|
||||
test_access($node, 'test1', 2, 'search+bind with LDAP URL authentication fails with wrong password');
|
||||
test_access($node, 'test0', 2,
|
||||
'search+bind with LDAP URL authentication fails if user not found in LDAP'
|
||||
);
|
||||
test_access($node, 'test1', 2,
|
||||
'search+bind with LDAP URL authentication fails with wrong password');
|
||||
$ENV{"PGPASSWORD"} = 'secret1';
|
||||
test_access($node, 'test1', 0, 'search+bind with LDAP URL authentication succeeds');
|
||||
test_access($node, 'test1', 0,
|
||||
'search+bind with LDAP URL authentication succeeds');
|
||||
|
||||
note "search filters";
|
||||
|
||||
unlink($node->data_dir . '/pg_hba.conf');
|
||||
$node->append_conf('pg_hba.conf', qq{local all all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapbasedn="$ldap_basedn" ldapsearchfilter="(|(uid=\$username)(mail=\$username))"});
|
||||
$node->append_conf('pg_hba.conf',
|
||||
qq{local all all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapbasedn="$ldap_basedn" ldapsearchfilter="(|(uid=\$username)(mail=\$username))"}
|
||||
);
|
||||
$node->restart;
|
||||
|
||||
$ENV{"PGPASSWORD"} = 'secret1';
|
||||
@ -185,7 +211,9 @@ test_access($node, 'test2@example.net', 0, 'search filter finds by mail');
|
||||
note "search filters in LDAP URLs";
|
||||
|
||||
unlink($node->data_dir . '/pg_hba.conf');
|
||||
$node->append_conf('pg_hba.conf', qq{local all all ldap ldapurl="$ldap_url/$ldap_basedn??sub?(|(uid=\$username)(mail=\$username))"});
|
||||
$node->append_conf('pg_hba.conf',
|
||||
qq{local all all ldap ldapurl="$ldap_url/$ldap_basedn??sub?(|(uid=\$username)(mail=\$username))"}
|
||||
);
|
||||
$node->restart;
|
||||
|
||||
$ENV{"PGPASSWORD"} = 'secret1';
|
||||
@ -197,7 +225,9 @@ test_access($node, 'test2@example.net', 0, 'search filter finds by mail');
|
||||
# settings. ldapurl is always parsed first, then the other settings
|
||||
# override. It might be useful in a case like this.
|
||||
unlink($node->data_dir . '/pg_hba.conf');
|
||||
$node->append_conf('pg_hba.conf', qq{local all all ldap ldapurl="$ldap_url/$ldap_basedn??sub" ldapsearchfilter="(|(uid=\$username)(mail=\$username))"});
|
||||
$node->append_conf('pg_hba.conf',
|
||||
qq{local all all ldap ldapurl="$ldap_url/$ldap_basedn??sub" ldapsearchfilter="(|(uid=\$username)(mail=\$username))"}
|
||||
);
|
||||
$node->restart;
|
||||
|
||||
$ENV{"PGPASSWORD"} = 'secret1';
|
||||
@ -207,7 +237,9 @@ note "diagnostic message";
|
||||
|
||||
# note bad ldapprefix with a question mark that triggers a diagnostic message
|
||||
unlink($node->data_dir . '/pg_hba.conf');
|
||||
$node->append_conf('pg_hba.conf', qq{local all all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapprefix="?uid=" ldapsuffix=""});
|
||||
$node->append_conf('pg_hba.conf',
|
||||
qq{local all all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapprefix="?uid=" ldapsuffix=""}
|
||||
);
|
||||
$node->restart;
|
||||
|
||||
$ENV{"PGPASSWORD"} = 'secret1';
|
||||
@ -217,7 +249,9 @@ note "TLS";
|
||||
|
||||
# request StartTLS with ldaptls=1
|
||||
unlink($node->data_dir . '/pg_hba.conf');
|
||||
$node->append_conf('pg_hba.conf', qq{local all all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapbasedn="$ldap_basedn" ldapsearchfilter="(uid=\$username)" ldaptls=1});
|
||||
$node->append_conf('pg_hba.conf',
|
||||
qq{local all all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapbasedn="$ldap_basedn" ldapsearchfilter="(uid=\$username)" ldaptls=1}
|
||||
);
|
||||
$node->restart;
|
||||
|
||||
$ENV{"PGPASSWORD"} = 'secret1';
|
||||
@ -225,7 +259,9 @@ test_access($node, 'test1', 0, 'StartTLS');
|
||||
|
||||
# request LDAPS with ldapscheme=ldaps
|
||||
unlink($node->data_dir . '/pg_hba.conf');
|
||||
$node->append_conf('pg_hba.conf', qq{local all all ldap ldapserver=$ldap_server ldapscheme=ldaps ldapport=$ldaps_port ldapbasedn="$ldap_basedn" ldapsearchfilter="(uid=\$username)"});
|
||||
$node->append_conf('pg_hba.conf',
|
||||
qq{local all all ldap ldapserver=$ldap_server ldapscheme=ldaps ldapport=$ldaps_port ldapbasedn="$ldap_basedn" ldapsearchfilter="(uid=\$username)"}
|
||||
);
|
||||
$node->restart;
|
||||
|
||||
$ENV{"PGPASSWORD"} = 'secret1';
|
||||
@ -233,7 +269,9 @@ test_access($node, 'test1', 0, 'LDAPS');
|
||||
|
||||
# request LDAPS with ldapurl=ldaps://...
|
||||
unlink($node->data_dir . '/pg_hba.conf');
|
||||
$node->append_conf('pg_hba.conf', qq{local all all ldap ldapurl="$ldaps_url/$ldap_basedn??sub?(uid=\$username)"});
|
||||
$node->append_conf('pg_hba.conf',
|
||||
qq{local all all ldap ldapurl="$ldaps_url/$ldap_basedn??sub?(uid=\$username)"}
|
||||
);
|
||||
$node->restart;
|
||||
|
||||
$ENV{"PGPASSWORD"} = 'secret1';
|
||||
@ -241,7 +279,9 @@ test_access($node, 'test1', 0, 'LDAPS with URL');
|
||||
|
||||
# bad combination of LDAPS and StartTLS
|
||||
unlink($node->data_dir . '/pg_hba.conf');
|
||||
$node->append_conf('pg_hba.conf', qq{local all all ldap ldapurl="$ldaps_url/$ldap_basedn??sub?(uid=\$username)" ldaptls=1});
|
||||
$node->append_conf('pg_hba.conf',
|
||||
qq{local all all ldap ldapurl="$ldaps_url/$ldap_basedn??sub?(uid=\$username)" ldaptls=1}
|
||||
);
|
||||
$node->restart;
|
||||
|
||||
$ENV{"PGPASSWORD"} = 'secret1';
|
||||
|
@ -15,25 +15,27 @@ $node->start;
|
||||
$node->safe_psql('postgres', 'create extension pageinspect');
|
||||
|
||||
# Create a table with an autosummarizing BRIN index
|
||||
$node->safe_psql('postgres',
|
||||
$node->safe_psql(
|
||||
'postgres',
|
||||
'create table brin_wi (a int) with (fillfactor = 10);
|
||||
create index brin_wi_idx on brin_wi using brin (a) with (pages_per_range=1, autosummarize=on);
|
||||
'
|
||||
);
|
||||
my $count = $node->safe_psql('postgres',
|
||||
"select count(*) from brin_page_items(get_raw_page('brin_wi_idx', 2), 'brin_wi_idx'::regclass)"
|
||||
"select count(*) from brin_page_items(get_raw_page('brin_wi_idx', 2), 'brin_wi_idx'::regclass)"
|
||||
);
|
||||
is($count, '1', "initial index state is correct");
|
||||
|
||||
$node->safe_psql('postgres',
|
||||
'insert into brin_wi select * from generate_series(1, 100)');
|
||||
|
||||
$node->poll_query_until('postgres',
|
||||
"select count(*) > 1 from brin_page_items(get_raw_page('brin_wi_idx', 2), 'brin_wi_idx'::regclass)",
|
||||
$node->poll_query_until(
|
||||
'postgres',
|
||||
"select count(*) > 1 from brin_page_items(get_raw_page('brin_wi_idx', 2), 'brin_wi_idx'::regclass)",
|
||||
't');
|
||||
|
||||
$count = $node->safe_psql('postgres',
|
||||
"select count(*) > 1 from brin_page_items(get_raw_page('brin_wi_idx', 2), 'brin_wi_idx'::regclass)"
|
||||
"select count(*) > 1 from brin_page_items(get_raw_page('brin_wi_idx', 2), 'brin_wi_idx'::regclass)"
|
||||
);
|
||||
is($count, 't', "index got summarized");
|
||||
$node->stop;
|
||||
|
@ -64,7 +64,7 @@ my %pgdump_runs = (
|
||||
'--no-sync',
|
||||
"--file=$tempdir/createdb.sql",
|
||||
'-C',
|
||||
'-R', # no-op, just for testing
|
||||
'-R', # no-op, just for testing
|
||||
'postgres', ], },
|
||||
data_only => {
|
||||
dump_cmd => [
|
||||
@ -72,7 +72,7 @@ my %pgdump_runs = (
|
||||
'--no-sync',
|
||||
"--file=$tempdir/data_only.sql",
|
||||
'-a',
|
||||
'-v', # no-op, just make sure it works
|
||||
'-v', # no-op, just make sure it works
|
||||
'postgres', ], },
|
||||
defaults => {
|
||||
dump_cmd => [ 'pg_dump', '-f', "$tempdir/defaults.sql", 'postgres', ],
|
||||
@ -178,14 +178,13 @@ my %pgdump_runs = (
|
||||
# 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,
|
||||
);
|
||||
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' => {
|
||||
@ -197,7 +196,7 @@ my %tests = (
|
||||
\n\s+\Qcol1 integer NOT NULL,\E
|
||||
\n\s+\Qcol2 integer\E
|
||||
\n\);\n/xm,
|
||||
like => { binary_upgrade => 1, }, },
|
||||
like => { binary_upgrade => 1, }, },
|
||||
|
||||
'CREATE EXTENSION test_pg_dump' => {
|
||||
create_order => 2,
|
||||
@ -207,10 +206,9 @@ my %tests = (
|
||||
\n/xm,
|
||||
like => {
|
||||
%full_runs,
|
||||
schema_only => 1,
|
||||
schema_only => 1,
|
||||
section_pre_data => 1, },
|
||||
unlike => {
|
||||
binary_upgrade => 1, }, },
|
||||
unlike => { binary_upgrade => 1, }, },
|
||||
|
||||
'CREATE ROLE regress_dump_test_role' => {
|
||||
create_order => 1,
|
||||
@ -228,7 +226,7 @@ my %tests = (
|
||||
\n\s+\QNO MAXVALUE\E
|
||||
\n\s+\QCACHE 1;\E
|
||||
\n/xm,
|
||||
like => { binary_upgrade => 1, }, },
|
||||
like => { binary_upgrade => 1, }, },
|
||||
|
||||
'CREATE TABLE regress_pg_dump_table_added' => {
|
||||
create_order => 7,
|
||||
@ -239,7 +237,7 @@ my %tests = (
|
||||
\n\s+\Qcol1 integer NOT NULL,\E
|
||||
\n\s+\Qcol2 integer\E
|
||||
\n\);\n/xm,
|
||||
like => { binary_upgrade => 1, }, },
|
||||
like => { binary_upgrade => 1, }, },
|
||||
|
||||
'CREATE SEQUENCE regress_pg_dump_seq' => {
|
||||
regexp => qr/^
|
||||
@ -250,7 +248,7 @@ my %tests = (
|
||||
\n\s+\QNO MAXVALUE\E
|
||||
\n\s+\QCACHE 1;\E
|
||||
\n/xm,
|
||||
like => { binary_upgrade => 1, }, },
|
||||
like => { binary_upgrade => 1, }, },
|
||||
|
||||
'SETVAL SEQUENCE regress_seq_dumpable' => {
|
||||
create_order => 6,
|
||||
@ -260,7 +258,7 @@ my %tests = (
|
||||
\n/xm,
|
||||
like => {
|
||||
%full_runs,
|
||||
data_only => 1,
|
||||
data_only => 1,
|
||||
section_data => 1, }, },
|
||||
|
||||
'CREATE TABLE regress_pg_dump_table' => {
|
||||
@ -269,13 +267,13 @@ my %tests = (
|
||||
\n\s+\Qcol1 integer NOT NULL,\E
|
||||
\n\s+\Qcol2 integer\E
|
||||
\n\);\n/xm,
|
||||
like => { binary_upgrade => 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, }, },
|
||||
like => { binary_upgrade => 1, }, },
|
||||
|
||||
'COMMENT ON EXTENSION test_pg_dump' => {
|
||||
regexp => qr/^
|
||||
@ -294,7 +292,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, }, },
|
||||
like => { binary_upgrade => 1, }, },
|
||||
|
||||
'REVOKE SELECT regress_pg_dump_table_added post-ALTER EXTENSION' => {
|
||||
create_order => 10,
|
||||
@ -307,8 +305,7 @@ my %tests = (
|
||||
%full_runs,
|
||||
schema_only => 1,
|
||||
section_pre_data => 1, },
|
||||
unlike => {
|
||||
no_privs => 1, }, },
|
||||
unlike => { no_privs => 1, }, },
|
||||
|
||||
'GRANT SELECT ON TABLE regress_pg_dump_table' => {
|
||||
regexp => qr/^
|
||||
@ -316,7 +313,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, }, },
|
||||
like => { binary_upgrade => 1, }, },
|
||||
|
||||
'GRANT SELECT(col1) ON regress_pg_dump_table' => {
|
||||
regexp => qr/^
|
||||
@ -324,10 +321,11 @@ 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, }, },
|
||||
like => { binary_upgrade => 1, }, },
|
||||
|
||||
'GRANT SELECT(col2) ON regress_pg_dump_table TO regress_dump_test_role' =>
|
||||
{ create_order => 4,
|
||||
'GRANT SELECT(col2) ON regress_pg_dump_table TO regress_dump_test_role'
|
||||
=> {
|
||||
create_order => 4,
|
||||
create_sql => 'GRANT SELECT(col2) ON regress_pg_dump_table
|
||||
TO regress_dump_test_role;',
|
||||
regexp => qr/^
|
||||
@ -337,8 +335,7 @@ my %tests = (
|
||||
%full_runs,
|
||||
schema_only => 1,
|
||||
section_pre_data => 1, },
|
||||
unlike => {
|
||||
no_privs => 1, }, },
|
||||
unlike => { no_privs => 1, }, },
|
||||
|
||||
'GRANT USAGE ON regress_pg_dump_table_col1_seq TO regress_dump_test_role'
|
||||
=> {
|
||||
@ -352,14 +349,13 @@ my %tests = (
|
||||
%full_runs,
|
||||
schema_only => 1,
|
||||
section_pre_data => 1, },
|
||||
unlike => {
|
||||
no_privs => 1, }, },
|
||||
unlike => { 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, }, },
|
||||
like => { binary_upgrade => 1, }, },
|
||||
|
||||
'REVOKE SELECT(col1) ON regress_pg_dump_table' => {
|
||||
create_order => 3,
|
||||
@ -372,8 +368,7 @@ my %tests = (
|
||||
%full_runs,
|
||||
schema_only => 1,
|
||||
section_pre_data => 1, },
|
||||
unlike => {
|
||||
no_privs => 1, }, },
|
||||
unlike => { no_privs => 1, }, },
|
||||
|
||||
# Objects included in extension part of a schema created by this extension */
|
||||
'CREATE TABLE regress_pg_dump_schema.test_table' => {
|
||||
@ -382,7 +377,7 @@ my %tests = (
|
||||
\n\s+\Qcol1 integer,\E
|
||||
\n\s+\Qcol2 integer\E
|
||||
\n\);\n/xm,
|
||||
like => { binary_upgrade => 1, }, },
|
||||
like => { binary_upgrade => 1, }, },
|
||||
|
||||
'GRANT SELECT ON regress_pg_dump_schema.test_table' => {
|
||||
regexp => qr/^
|
||||
@ -390,7 +385,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, }, },
|
||||
like => { binary_upgrade => 1, }, },
|
||||
|
||||
'CREATE SEQUENCE regress_pg_dump_schema.test_seq' => {
|
||||
regexp => qr/^
|
||||
@ -401,7 +396,7 @@ my %tests = (
|
||||
\n\s+\QNO MAXVALUE\E
|
||||
\n\s+\QCACHE 1;\E
|
||||
\n/xm,
|
||||
like => { binary_upgrade => 1, }, },
|
||||
like => { binary_upgrade => 1, }, },
|
||||
|
||||
'GRANT USAGE ON regress_pg_dump_schema.test_seq' => {
|
||||
regexp => qr/^
|
||||
@ -409,14 +404,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, }, },
|
||||
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, }, },
|
||||
like => { binary_upgrade => 1, }, },
|
||||
|
||||
'GRANT USAGE ON regress_pg_dump_schema.test_type' => {
|
||||
regexp => qr/^
|
||||
@ -424,14 +419,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, }, },
|
||||
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, }, },
|
||||
like => { binary_upgrade => 1, }, },
|
||||
|
||||
'GRANT ALL ON regress_pg_dump_schema.test_func' => {
|
||||
regexp => qr/^
|
||||
@ -439,7 +434,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, }, },
|
||||
like => { binary_upgrade => 1, }, },
|
||||
|
||||
'CREATE AGGREGATE regress_pg_dump_schema.test_agg' => {
|
||||
regexp => qr/^
|
||||
@ -447,7 +442,7 @@ my %tests = (
|
||||
\n\s+\QSFUNC = int2_sum,\E
|
||||
\n\s+\QSTYPE = bigint\E
|
||||
\n\);\n/xm,
|
||||
like => { binary_upgrade => 1, }, },
|
||||
like => { binary_upgrade => 1, }, },
|
||||
|
||||
'GRANT ALL ON regress_pg_dump_schema.test_agg' => {
|
||||
regexp => qr/^
|
||||
@ -455,7 +450,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, }, },
|
||||
like => { binary_upgrade => 1, }, },
|
||||
|
||||
# Objects not included in extension, part of schema created by extension
|
||||
'CREATE TABLE regress_pg_dump_schema.external_tab' => {
|
||||
@ -468,9 +463,8 @@ my %tests = (
|
||||
\n\);\n/xm,
|
||||
like => {
|
||||
%full_runs,
|
||||
schema_only => 1,
|
||||
section_pre_data => 1, }, },
|
||||
);
|
||||
schema_only => 1,
|
||||
section_pre_data => 1, }, },);
|
||||
|
||||
#########################################
|
||||
# Create a PG instance to test actually dumping from
|
||||
@ -504,8 +498,9 @@ foreach my $run (sort keys %pgdump_runs)
|
||||
# Then count all the tests run against each run
|
||||
foreach my $test (sort keys %tests)
|
||||
{
|
||||
# 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}))
|
||||
# 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++;
|
||||
}
|
||||
@ -585,18 +580,18 @@ foreach my $run (sort keys %pgdump_runs)
|
||||
{
|
||||
# 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}))
|
||||
if ($tests{$test}->{like}->{$test_key}
|
||||
&& !defined($tests{$test}->{unlike}->{$test_key}))
|
||||
{
|
||||
if (!ok($output_file =~ $tests{$test}->{regexp}, "$run: should dump $test"))
|
||||
if (!ok($output_file =~ $tests{$test}->{regexp},
|
||||
"$run: should dump $test"))
|
||||
{
|
||||
diag("Review $run results in $tempdir");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ok(
|
||||
$output_file !~
|
||||
$tests{$test}->{regexp},
|
||||
if (!ok($output_file !~ $tests{$test}->{regexp},
|
||||
"$run: should not dump $test"))
|
||||
{
|
||||
diag("Review $run results in $tempdir");
|
||||
|
@ -284,7 +284,7 @@ sub group_access
|
||||
my $dir_stat = stat($self->data_dir);
|
||||
|
||||
defined($dir_stat)
|
||||
or die('unable to stat ' . $self->data_dir);
|
||||
or die('unable to stat ' . $self->data_dir);
|
||||
|
||||
return (S_IMODE($dir_stat->mode) == 0750);
|
||||
}
|
||||
@ -482,8 +482,8 @@ sub init
|
||||
}
|
||||
close $conf;
|
||||
|
||||
chmod($self->group_access ? 0640 : 0600, "$pgdata/postgresql.conf")
|
||||
or die("unable to set permissions for $pgdata/postgresql.conf");
|
||||
chmod($self->group_access ? 0640 : 0600, "$pgdata/postgresql.conf")
|
||||
or die("unable to set permissions for $pgdata/postgresql.conf");
|
||||
|
||||
$self->set_replication_conf if $params{allows_streaming};
|
||||
$self->enable_archiving if $params{has_archiving};
|
||||
@ -510,8 +510,8 @@ sub append_conf
|
||||
|
||||
TestLib::append_to_file($conffile, $str . "\n");
|
||||
|
||||
chmod($self->group_access() ? 0640 : 0600, $conffile)
|
||||
or die("unable to set permissions for $conffile");
|
||||
chmod($self->group_access() ? 0640 : 0600, $conffile)
|
||||
or die("unable to set permissions for $conffile");
|
||||
}
|
||||
|
||||
=pod
|
||||
@ -1535,7 +1535,7 @@ sub wait_for_catchup
|
||||
}
|
||||
else
|
||||
{
|
||||
$lsn_expr = 'pg_current_wal_lsn()'
|
||||
$lsn_expr = 'pg_current_wal_lsn()';
|
||||
}
|
||||
print "Waiting for replication conn "
|
||||
. $standby_name . "'s "
|
||||
@ -1686,8 +1686,8 @@ to check for timeout. retval is undef on timeout.
|
||||
|
||||
sub pg_recvlogical_upto
|
||||
{
|
||||
my ($self, $dbname, $slot_name, $endpos, $timeout_secs, %plugin_options) =
|
||||
@_;
|
||||
my ($self, $dbname, $slot_name, $endpos, $timeout_secs, %plugin_options)
|
||||
= @_;
|
||||
my ($stdout, $stderr);
|
||||
|
||||
my $timeout_exception = 'pg_recvlogical timed out';
|
||||
|
@ -71,7 +71,7 @@ sub copypath
|
||||
{
|
||||
croak "if specified, filterfn must be a subroutine reference"
|
||||
unless defined(ref $params{filterfn})
|
||||
and (ref $params{filterfn} eq 'CODE');
|
||||
and (ref $params{filterfn} eq 'CODE');
|
||||
|
||||
$filterfn = $params{filterfn};
|
||||
}
|
||||
|
@ -169,16 +169,17 @@ sub tempdir_short
|
||||
# not under msys, return the input argument unchanged.
|
||||
sub real_dir
|
||||
{
|
||||
my $dir = "$_[0]";
|
||||
return $dir unless -d $dir;
|
||||
return $dir unless $Config{osname} eq 'msys';
|
||||
my $here = cwd;
|
||||
chdir $dir;
|
||||
my $dir = "$_[0]";
|
||||
return $dir unless -d $dir;
|
||||
return $dir unless $Config{osname} eq 'msys';
|
||||
my $here = cwd;
|
||||
chdir $dir;
|
||||
|
||||
# this odd way of calling 'pwd -W' is the only way that seems to work.
|
||||
$dir = qx{sh -c "pwd -W"};
|
||||
chomp $dir;
|
||||
chdir $here;
|
||||
return $dir;
|
||||
$dir = qx{sh -c "pwd -W"};
|
||||
chomp $dir;
|
||||
chdir $here;
|
||||
return $dir;
|
||||
}
|
||||
|
||||
sub system_log
|
||||
@ -254,12 +255,9 @@ sub check_mode_recursive
|
||||
# Result defaults to true
|
||||
my $result = 1;
|
||||
|
||||
find
|
||||
(
|
||||
{follow_fast => 1,
|
||||
wanted =>
|
||||
sub
|
||||
{
|
||||
find(
|
||||
{ follow_fast => 1,
|
||||
wanted => sub {
|
||||
my $file_stat = stat($File::Find::name);
|
||||
|
||||
# Is file in the ignore list?
|
||||
@ -272,7 +270,7 @@ sub check_mode_recursive
|
||||
}
|
||||
|
||||
defined($file_stat)
|
||||
or die("unable to stat $File::Find::name");
|
||||
or die("unable to stat $File::Find::name");
|
||||
|
||||
my $file_mode = S_IMODE($file_stat->mode);
|
||||
|
||||
@ -281,35 +279,39 @@ sub check_mode_recursive
|
||||
{
|
||||
if ($file_mode != $expected_file_mode)
|
||||
{
|
||||
print(*STDERR,
|
||||
print(
|
||||
*STDERR,
|
||||
sprintf("$File::Find::name mode must be %04o\n",
|
||||
$expected_file_mode));
|
||||
$expected_file_mode));
|
||||
|
||||
$result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
# Else a directory?
|
||||
elsif (S_ISDIR($file_stat->mode))
|
||||
{
|
||||
if ($file_mode != $expected_dir_mode)
|
||||
{
|
||||
print(*STDERR,
|
||||
print(
|
||||
*STDERR,
|
||||
sprintf("$File::Find::name mode must be %04o\n",
|
||||
$expected_dir_mode));
|
||||
$expected_dir_mode));
|
||||
|
||||
$result = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
# Else something we can't handle
|
||||
else
|
||||
{
|
||||
die "unknown file type for $File::Find::name";
|
||||
}
|
||||
}},
|
||||
$dir
|
||||
);
|
||||
}
|
||||
},
|
||||
$dir);
|
||||
|
||||
return $result;
|
||||
}
|
||||
@ -319,23 +321,21 @@ sub chmod_recursive
|
||||
{
|
||||
my ($dir, $dir_mode, $file_mode) = @_;
|
||||
|
||||
find
|
||||
(
|
||||
{follow_fast => 1,
|
||||
wanted =>
|
||||
sub
|
||||
{
|
||||
find(
|
||||
{ follow_fast => 1,
|
||||
wanted => sub {
|
||||
my $file_stat = stat($File::Find::name);
|
||||
|
||||
if (defined($file_stat))
|
||||
{
|
||||
chmod(S_ISDIR($file_stat->mode) ? $dir_mode : $file_mode,
|
||||
$File::Find::name)
|
||||
or die "unable to chmod $File::Find::name";
|
||||
chmod(
|
||||
S_ISDIR($file_stat->mode) ? $dir_mode : $file_mode,
|
||||
$File::Find::name
|
||||
) or die "unable to chmod $File::Find::name";
|
||||
}
|
||||
}},
|
||||
$dir
|
||||
);
|
||||
}
|
||||
},
|
||||
$dir);
|
||||
}
|
||||
|
||||
# Check presence of a given regexp within pg_config.h for the installation
|
||||
@ -351,7 +351,7 @@ sub check_pg_config
|
||||
chomp($stdout);
|
||||
|
||||
open my $pg_config_h, '<', "$stdout/pg_config.h" or die "$!";
|
||||
my $match = (grep {/^$regexp/} <$pg_config_h>);
|
||||
my $match = (grep { /^$regexp/ } <$pg_config_h>);
|
||||
close $pg_config_h;
|
||||
return $match;
|
||||
}
|
||||
|
@ -80,8 +80,7 @@ is($stdout_recv, $expected,
|
||||
|
||||
$node_master->poll_query_until('postgres',
|
||||
"SELECT EXISTS (SELECT 1 FROM pg_replication_slots WHERE slot_name = 'test_slot' AND active_pid IS NULL)"
|
||||
)
|
||||
or die "slot never became inactive";
|
||||
) or die "slot never became inactive";
|
||||
|
||||
$stdout_recv = $node_master->pg_recvlogical_upto(
|
||||
'postgres', 'test_slot', $endpos, 10,
|
||||
|
@ -333,9 +333,9 @@ $cur_master->psql(
|
||||
|
||||
# Ensure that last transaction is replayed on standby.
|
||||
my $cur_master_lsn =
|
||||
$cur_master->safe_psql('postgres', "SELECT pg_current_wal_lsn()");
|
||||
$cur_master->safe_psql('postgres', "SELECT pg_current_wal_lsn()");
|
||||
my $caughtup_query =
|
||||
"SELECT '$cur_master_lsn'::pg_lsn <= pg_last_wal_replay_lsn()";
|
||||
"SELECT '$cur_master_lsn'::pg_lsn <= pg_last_wal_replay_lsn()";
|
||||
$cur_standby->poll_query_until('postgres', $caughtup_query)
|
||||
or die "Timed out while waiting for standby to catch up";
|
||||
|
||||
|
@ -30,8 +30,9 @@ $node->init(allows_streaming => 1);
|
||||
$node->start();
|
||||
|
||||
# by default PostgresNode doesn't doesn't restart after a crash
|
||||
$node->safe_psql('postgres',
|
||||
q[ALTER SYSTEM SET restart_after_crash = 1;
|
||||
$node->safe_psql(
|
||||
'postgres',
|
||||
q[ALTER SYSTEM SET restart_after_crash = 1;
|
||||
ALTER SYSTEM SET log_connections = 1;
|
||||
SELECT pg_reload_conf();]);
|
||||
|
||||
@ -68,7 +69,7 @@ INSERT INTO alive VALUES($$committed-before-sigquit$$);
|
||||
SELECT pg_backend_pid();
|
||||
];
|
||||
ok(pump_until($killme, \$killme_stdout, qr/[[:digit:]]+[\r\n]$/m),
|
||||
'acquired pid for SIGQUIT');
|
||||
'acquired pid for SIGQUIT');
|
||||
my $pid = $killme_stdout;
|
||||
chomp($pid);
|
||||
$killme_stdout = '';
|
||||
@ -80,7 +81,7 @@ BEGIN;
|
||||
INSERT INTO alive VALUES($$in-progress-before-sigquit$$) RETURNING status;
|
||||
];
|
||||
ok(pump_until($killme, \$killme_stdout, qr/in-progress-before-sigquit/m),
|
||||
'inserted in-progress-before-sigquit');
|
||||
'inserted in-progress-before-sigquit');
|
||||
$killme_stdout = '';
|
||||
$killme_stderr = '';
|
||||
|
||||
@ -93,7 +94,7 @@ SELECT $$psql-connected$$;
|
||||
SELECT pg_sleep(3600);
|
||||
];
|
||||
ok(pump_until($monitor, \$monitor_stdout, qr/psql-connected/m),
|
||||
'monitor connected');
|
||||
'monitor connected');
|
||||
$monitor_stdout = '';
|
||||
$monitor_stderr = '';
|
||||
|
||||
@ -107,8 +108,12 @@ is($ret, 0, "killed process with SIGQUIT");
|
||||
$killme_stdin .= q[
|
||||
SELECT 1;
|
||||
];
|
||||
ok(pump_until($killme, \$killme_stderr, qr/WARNING: terminating connection because of crash of another server process|server closed the connection unexpectedly/m),
|
||||
"psql query died successfully after SIGQUIT");
|
||||
ok( pump_until(
|
||||
$killme,
|
||||
\$killme_stderr,
|
||||
qr/WARNING: terminating connection because of crash of another server process|server closed the connection unexpectedly/m
|
||||
),
|
||||
"psql query died successfully after SIGQUIT");
|
||||
$killme_stderr = '';
|
||||
$killme_stdout = '';
|
||||
$killme->finish;
|
||||
@ -116,13 +121,21 @@ $killme->finish;
|
||||
# Wait till server restarts - we should get the WARNING here, but
|
||||
# sometimes the server is unable to send that, if interrupted while
|
||||
# sending.
|
||||
ok(pump_until($monitor, \$monitor_stderr, qr/WARNING: terminating connection because of crash of another server process|server closed the connection unexpectedly/m),
|
||||
"psql monitor died successfully after SIGQUIT");
|
||||
ok( pump_until(
|
||||
$monitor,
|
||||
\$monitor_stderr,
|
||||
qr/WARNING: terminating connection because of crash of another server process|server closed the connection unexpectedly/m
|
||||
),
|
||||
"psql monitor died successfully after SIGQUIT");
|
||||
$monitor->finish;
|
||||
|
||||
# Wait till server restarts
|
||||
is($node->poll_query_until('postgres', 'SELECT $$restarted after sigquit$$;', 'restarted after sigquit'),
|
||||
"1", "reconnected after SIGQUIT");
|
||||
is( $node->poll_query_until(
|
||||
'postgres',
|
||||
'SELECT $$restarted after sigquit$$;',
|
||||
'restarted after sigquit'),
|
||||
"1",
|
||||
"reconnected after SIGQUIT");
|
||||
|
||||
|
||||
# restart psql processes, now that the crash cycle finished
|
||||
@ -137,10 +150,10 @@ $killme_stdin .= q[
|
||||
SELECT pg_backend_pid();
|
||||
];
|
||||
ok(pump_until($killme, \$killme_stdout, qr/[[:digit:]]+[\r\n]$/m),
|
||||
"acquired pid for SIGKILL");
|
||||
"acquired pid for SIGKILL");
|
||||
$pid = $killme_stdout;
|
||||
chomp($pid);
|
||||
$pid = $killme_stdout;
|
||||
$pid = $killme_stdout;
|
||||
$killme_stdout = '';
|
||||
$killme_stderr = '';
|
||||
|
||||
@ -151,7 +164,7 @@ BEGIN;
|
||||
INSERT INTO alive VALUES($$in-progress-before-sigkill$$) RETURNING status;
|
||||
];
|
||||
ok(pump_until($killme, \$killme_stdout, qr/in-progress-before-sigkill/m),
|
||||
'inserted in-progress-before-sigkill');
|
||||
'inserted in-progress-before-sigkill');
|
||||
$killme_stdout = '';
|
||||
$killme_stderr = '';
|
||||
|
||||
@ -164,7 +177,7 @@ SELECT $$psql-connected$$;
|
||||
SELECT pg_sleep(3600);
|
||||
];
|
||||
ok(pump_until($monitor, \$monitor_stdout, qr/psql-connected/m),
|
||||
'monitor connected');
|
||||
'monitor connected');
|
||||
$monitor_stdout = '';
|
||||
$monitor_stderr = '';
|
||||
|
||||
@ -179,35 +192,51 @@ is($ret, 0, "killed process with KILL");
|
||||
$killme_stdin .= q[
|
||||
SELECT 1;
|
||||
];
|
||||
ok(pump_until($killme, \$killme_stderr, qr/server closed the connection unexpectedly/m),
|
||||
"psql query died successfully after SIGKILL");
|
||||
ok( pump_until(
|
||||
$killme, \$killme_stderr,
|
||||
qr/server closed the connection unexpectedly/m),
|
||||
"psql query died successfully after SIGKILL");
|
||||
$killme->finish;
|
||||
|
||||
# Wait till server restarts - we should get the WARNING here, but
|
||||
# sometimes the server is unable to send that, if interrupted while
|
||||
# sending.
|
||||
ok(pump_until($monitor, \$monitor_stderr, qr/WARNING: terminating connection because of crash of another server process|server closed the connection unexpectedly/m),
|
||||
"psql monitor died successfully after SIGKILL");
|
||||
ok( pump_until(
|
||||
$monitor,
|
||||
\$monitor_stderr,
|
||||
qr/WARNING: terminating connection because of crash of another server process|server closed the connection unexpectedly/m
|
||||
),
|
||||
"psql monitor died successfully after SIGKILL");
|
||||
$monitor->finish;
|
||||
|
||||
# Wait till server restarts
|
||||
is($node->poll_query_until('postgres', 'SELECT 1', '1'), "1", "reconnected after SIGKILL");
|
||||
is($node->poll_query_until('postgres', 'SELECT 1', '1'),
|
||||
"1", "reconnected after SIGKILL");
|
||||
|
||||
# Make sure the committed rows survived, in-progress ones not
|
||||
is($node->safe_psql('postgres', 'SELECT * FROM alive'),
|
||||
"committed-before-sigquit\ncommitted-before-sigkill", 'data survived');
|
||||
is( $node->safe_psql('postgres', 'SELECT * FROM alive'),
|
||||
"committed-before-sigquit\ncommitted-before-sigkill",
|
||||
'data survived');
|
||||
|
||||
is($node->safe_psql('postgres', 'INSERT INTO alive VALUES($$before-orderly-restart$$) RETURNING status'),
|
||||
'before-orderly-restart', 'can still write after crash restart');
|
||||
is( $node->safe_psql(
|
||||
'postgres',
|
||||
'INSERT INTO alive VALUES($$before-orderly-restart$$) RETURNING status'),
|
||||
'before-orderly-restart',
|
||||
'can still write after crash restart');
|
||||
|
||||
# Just to be sure, check that an orderly restart now still works
|
||||
$node->restart();
|
||||
|
||||
is($node->safe_psql('postgres', 'SELECT * FROM alive'),
|
||||
"committed-before-sigquit\ncommitted-before-sigkill\nbefore-orderly-restart", 'data survived');
|
||||
is( $node->safe_psql('postgres', 'SELECT * FROM alive'),
|
||||
"committed-before-sigquit\ncommitted-before-sigkill\nbefore-orderly-restart",
|
||||
'data survived');
|
||||
|
||||
is($node->safe_psql('postgres', 'INSERT INTO alive VALUES($$after-orderly-restart$$) RETURNING status'),
|
||||
'after-orderly-restart', 'can still write after orderly restart');
|
||||
is( $node->safe_psql(
|
||||
'postgres',
|
||||
'INSERT INTO alive VALUES($$after-orderly-restart$$) RETURNING status'
|
||||
),
|
||||
'after-orderly-restart',
|
||||
'can still write after orderly restart');
|
||||
|
||||
$node->stop();
|
||||
|
||||
@ -221,7 +250,7 @@ sub pump_until
|
||||
if ($psql_timeout->is_expired)
|
||||
{
|
||||
diag("aborting wait: program timed out");
|
||||
diag("stream contents: >>", $$stream,"<<");
|
||||
diag("stream contents: >>", $$stream, "<<");
|
||||
diag("pattern searched for: ", $untl);
|
||||
|
||||
return 0;
|
||||
@ -229,7 +258,7 @@ sub pump_until
|
||||
if (not $proc->pumpable())
|
||||
{
|
||||
diag("aborting wait: program died");
|
||||
diag("stream contents: >>", $$stream,"<<");
|
||||
diag("stream contents: >>", $$stream, "<<");
|
||||
diag("pattern searched for: ", $untl);
|
||||
|
||||
return 0;
|
||||
@ -239,4 +268,4 @@ sub pump_until
|
||||
}
|
||||
return 1;
|
||||
|
||||
};
|
||||
}
|
||||
|
@ -32,8 +32,7 @@ my $tablespaceDir = TestLib::tempdir;
|
||||
|
||||
my $realTSDir = TestLib::real_dir($tablespaceDir);
|
||||
|
||||
$node->safe_psql('postgres',
|
||||
"CREATE TABLESPACE ts1 LOCATION '$realTSDir'");
|
||||
$node->safe_psql('postgres', "CREATE TABLESPACE ts1 LOCATION '$realTSDir'");
|
||||
$node->safe_psql('postgres',
|
||||
'CREATE UNLOGGED TABLE ts1_unlogged (id int) TABLESPACE ts1');
|
||||
|
||||
@ -64,11 +63,9 @@ unlink("$pgdata/${ts1UnloggedPath}")
|
||||
$node->start;
|
||||
|
||||
# check unlogged table in base
|
||||
ok(-f "$pgdata/${baseUnloggedPath}_init",
|
||||
'init fork in base still exists');
|
||||
ok(-f "$pgdata/$baseUnloggedPath",
|
||||
'main fork in base recreated at startup');
|
||||
ok( !-f "$pgdata/${baseUnloggedPath}_vm",
|
||||
ok(-f "$pgdata/${baseUnloggedPath}_init", 'init fork in base still exists');
|
||||
ok(-f "$pgdata/$baseUnloggedPath", 'main fork in base recreated at startup');
|
||||
ok(!-f "$pgdata/${baseUnloggedPath}_vm",
|
||||
'vm fork in base removed at startup');
|
||||
ok( !-f "$pgdata/${baseUnloggedPath}_fsm",
|
||||
'fsm fork in base removed at startup');
|
||||
|
@ -41,7 +41,8 @@ sub test_connect_ok
|
||||
my ($common_connstr, $connstr, $test_name) = @_;
|
||||
|
||||
my $cmd = [
|
||||
'psql', '-X', '-A', '-t', '-c', "SELECT \$\$connected with $connstr\$\$",
|
||||
'psql', '-X', '-A', '-t', '-c',
|
||||
"SELECT \$\$connected with $connstr\$\$",
|
||||
'-d', "$common_connstr $connstr" ];
|
||||
|
||||
command_ok($cmd, $test_name);
|
||||
@ -52,7 +53,8 @@ sub test_connect_fails
|
||||
my ($common_connstr, $connstr, $expected_stderr, $test_name) = @_;
|
||||
|
||||
my $cmd = [
|
||||
'psql', '-X', '-A', '-t', '-c', "SELECT \$\$connected with $connstr\$\$",
|
||||
'psql', '-X', '-A', '-t', '-c',
|
||||
"SELECT \$\$connected with $connstr\$\$",
|
||||
'-d', "$common_connstr $connstr" ];
|
||||
|
||||
command_fails_like($cmd, $expected_stderr, $test_name);
|
||||
@ -89,9 +91,11 @@ sub configure_test_server_for_ssl
|
||||
if (defined($password))
|
||||
{
|
||||
$node->psql('postgres',
|
||||
"SET password_encryption='$password_enc'; ALTER USER ssltestuser PASSWORD '$password';");
|
||||
"SET password_encryption='$password_enc'; ALTER USER ssltestuser PASSWORD '$password';"
|
||||
);
|
||||
$node->psql('postgres',
|
||||
"SET password_encryption='$password_enc'; ALTER USER anotheruser PASSWORD '$password';");
|
||||
"SET password_encryption='$password_enc'; ALTER USER anotheruser PASSWORD '$password';"
|
||||
);
|
||||
}
|
||||
|
||||
# enable logging etc.
|
||||
@ -149,7 +153,7 @@ sub switch_server_cert
|
||||
sub configure_hba_for_ssl
|
||||
{
|
||||
my ($node, $serverhost, $authmethod) = @_;
|
||||
my $pgdata = $node->data_dir;
|
||||
my $pgdata = $node->data_dir;
|
||||
|
||||
# Only accept SSL connections from localhost. Our tests don't depend on this
|
||||
# but seems best to keep it as narrow as possible for security reasons.
|
||||
|
@ -53,26 +53,28 @@ configure_test_server_for_ssl($node, $SERVERHOSTADDR, 'trust');
|
||||
|
||||
note "testing password-protected keys";
|
||||
|
||||
open my $sslconf, '>', $node->data_dir."/sslconfig.conf";
|
||||
open my $sslconf, '>', $node->data_dir . "/sslconfig.conf";
|
||||
print $sslconf "ssl=on\n";
|
||||
print $sslconf "ssl_cert_file='server-cn-only.crt'\n";
|
||||
print $sslconf "ssl_key_file='server-password.key'\n";
|
||||
print $sslconf "ssl_passphrase_command='echo wrongpassword'\n";
|
||||
close $sslconf;
|
||||
|
||||
command_fails(['pg_ctl', '-D', $node->data_dir, '-l', $node->logfile, 'restart'],
|
||||
'restart fails with password-protected key file with wrong password');
|
||||
command_fails(
|
||||
[ 'pg_ctl', '-D', $node->data_dir, '-l', $node->logfile, 'restart' ],
|
||||
'restart fails with password-protected key file with wrong password');
|
||||
$node->_update_pid(0);
|
||||
|
||||
open $sslconf, '>', $node->data_dir."/sslconfig.conf";
|
||||
open $sslconf, '>', $node->data_dir . "/sslconfig.conf";
|
||||
print $sslconf "ssl=on\n";
|
||||
print $sslconf "ssl_cert_file='server-cn-only.crt'\n";
|
||||
print $sslconf "ssl_key_file='server-password.key'\n";
|
||||
print $sslconf "ssl_passphrase_command='echo secret1'\n";
|
||||
close $sslconf;
|
||||
|
||||
command_ok(['pg_ctl', '-D', $node->data_dir, '-l', $node->logfile, 'restart'],
|
||||
'restart succeeds with password-protected key file');
|
||||
command_ok(
|
||||
[ 'pg_ctl', '-D', $node->data_dir, '-l', $node->logfile, 'restart' ],
|
||||
'restart succeeds with password-protected key file');
|
||||
$node->_update_pid(1);
|
||||
|
||||
### Run client-side tests.
|
||||
@ -89,93 +91,110 @@ $common_connstr =
|
||||
"user=ssltestuser dbname=trustdb sslcert=invalid hostaddr=$SERVERHOSTADDR host=common-name.pg-ssltest.test";
|
||||
|
||||
# The server should not accept non-SSL connections.
|
||||
test_connect_fails($common_connstr, "sslmode=disable",
|
||||
qr/\Qno pg_hba.conf entry\E/,
|
||||
"server doesn't accept non-SSL connections");
|
||||
test_connect_fails(
|
||||
$common_connstr, "sslmode=disable",
|
||||
qr/\Qno pg_hba.conf entry\E/,
|
||||
"server doesn't accept non-SSL connections");
|
||||
|
||||
# Try without a root cert. In sslmode=require, this should work. In verify-ca
|
||||
# or verify-full mode it should fail.
|
||||
test_connect_ok($common_connstr, "sslrootcert=invalid sslmode=require",
|
||||
"connect without server root cert sslmode=require");
|
||||
test_connect_fails($common_connstr, "sslrootcert=invalid sslmode=verify-ca",
|
||||
qr/root certificate file "invalid" does not exist/,
|
||||
"connect without server root cert sslmode=verify-ca");
|
||||
test_connect_fails($common_connstr, "sslrootcert=invalid sslmode=verify-full",
|
||||
qr/root certificate file "invalid" does not exist/,
|
||||
"connect without server root cert sslmode=verify-full");
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"sslrootcert=invalid sslmode=require",
|
||||
"connect without server root cert sslmode=require");
|
||||
test_connect_fails(
|
||||
$common_connstr,
|
||||
"sslrootcert=invalid sslmode=verify-ca",
|
||||
qr/root certificate file "invalid" does not exist/,
|
||||
"connect without server root cert sslmode=verify-ca");
|
||||
test_connect_fails(
|
||||
$common_connstr,
|
||||
"sslrootcert=invalid sslmode=verify-full",
|
||||
qr/root certificate file "invalid" does not exist/,
|
||||
"connect without server root cert sslmode=verify-full");
|
||||
|
||||
# Try with wrong root cert, should fail. (We're using the client CA as the
|
||||
# root, but the server's key is signed by the server CA.)
|
||||
test_connect_fails($common_connstr,
|
||||
"sslrootcert=ssl/client_ca.crt sslmode=require",
|
||||
qr/SSL error/,
|
||||
"connect with wrong server root cert sslmode=require");
|
||||
"sslrootcert=ssl/client_ca.crt sslmode=require",
|
||||
qr/SSL error/, "connect with wrong server root cert sslmode=require");
|
||||
test_connect_fails($common_connstr,
|
||||
"sslrootcert=ssl/client_ca.crt sslmode=verify-ca",
|
||||
qr/SSL error/,
|
||||
"connect with wrong server root cert sslmode=verify-ca");
|
||||
"sslrootcert=ssl/client_ca.crt sslmode=verify-ca",
|
||||
qr/SSL error/, "connect with wrong server root cert sslmode=verify-ca");
|
||||
test_connect_fails($common_connstr,
|
||||
"sslrootcert=ssl/client_ca.crt sslmode=verify-full",
|
||||
qr/SSL error/,
|
||||
"connect with wrong server root cert sslmode=verify-full");
|
||||
"sslrootcert=ssl/client_ca.crt sslmode=verify-full",
|
||||
qr/SSL error/, "connect with wrong server root cert sslmode=verify-full");
|
||||
|
||||
# Try with just the server CA's cert. This fails because the root file
|
||||
# must contain the whole chain up to the root CA.
|
||||
test_connect_fails($common_connstr,
|
||||
"sslrootcert=ssl/server_ca.crt sslmode=verify-ca",
|
||||
qr/SSL error/,
|
||||
"connect with server CA cert, without root CA");
|
||||
"sslrootcert=ssl/server_ca.crt sslmode=verify-ca",
|
||||
qr/SSL error/, "connect with server CA cert, without root CA");
|
||||
|
||||
# And finally, with the correct root cert.
|
||||
test_connect_ok($common_connstr,
|
||||
"sslrootcert=ssl/root+server_ca.crt sslmode=require",
|
||||
"connect with correct server CA cert file sslmode=require");
|
||||
test_connect_ok($common_connstr,
|
||||
"sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca",
|
||||
"connect with correct server CA cert file sslmode=verify-ca");
|
||||
test_connect_ok($common_connstr,
|
||||
"sslrootcert=ssl/root+server_ca.crt sslmode=verify-full",
|
||||
"connect with correct server CA cert file sslmode=verify-full");
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"sslrootcert=ssl/root+server_ca.crt sslmode=require",
|
||||
"connect with correct server CA cert file sslmode=require");
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca",
|
||||
"connect with correct server CA cert file sslmode=verify-ca");
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"sslrootcert=ssl/root+server_ca.crt sslmode=verify-full",
|
||||
"connect with correct server CA cert file sslmode=verify-full");
|
||||
|
||||
# Test with cert root file that contains two certificates. The client should
|
||||
# be able to pick the right one, regardless of the order in the file.
|
||||
test_connect_ok($common_connstr,
|
||||
"sslrootcert=ssl/both-cas-1.crt sslmode=verify-ca",
|
||||
"cert root file that contains two certificates, order 1");
|
||||
test_connect_ok($common_connstr,
|
||||
"sslrootcert=ssl/both-cas-2.crt sslmode=verify-ca",
|
||||
"cert root file that contains two certificates, order 2");
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"sslrootcert=ssl/both-cas-1.crt sslmode=verify-ca",
|
||||
"cert root file that contains two certificates, order 1");
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"sslrootcert=ssl/both-cas-2.crt sslmode=verify-ca",
|
||||
"cert root file that contains two certificates, order 2");
|
||||
|
||||
# CRL tests
|
||||
|
||||
# Invalid CRL filename is the same as no CRL, succeeds
|
||||
test_connect_ok($common_connstr,
|
||||
"sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=invalid",
|
||||
"sslcrl option with invalid file name");
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=invalid",
|
||||
"sslcrl option with invalid file name");
|
||||
|
||||
# A CRL belonging to a different CA is not accepted, fails
|
||||
test_connect_fails($common_connstr,
|
||||
"sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=ssl/client.crl",
|
||||
qr/SSL error/,
|
||||
"CRL belonging to a different CA");
|
||||
test_connect_fails(
|
||||
$common_connstr,
|
||||
"sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=ssl/client.crl",
|
||||
qr/SSL error/,
|
||||
"CRL belonging to a different CA");
|
||||
|
||||
# With the correct CRL, succeeds (this cert is not revoked)
|
||||
test_connect_ok($common_connstr,
|
||||
"sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=ssl/root+server.crl",
|
||||
"CRL with a non-revoked cert");
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=ssl/root+server.crl",
|
||||
"CRL with a non-revoked cert");
|
||||
|
||||
# Check that connecting with verify-full fails, when the hostname doesn't
|
||||
# match the hostname in the server's certificate.
|
||||
$common_connstr =
|
||||
"user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR";
|
||||
|
||||
test_connect_ok($common_connstr, "sslmode=require host=wronghost.test",
|
||||
"mismatch between host name and server certificate sslmode=require");
|
||||
test_connect_ok($common_connstr, "sslmode=verify-ca host=wronghost.test",
|
||||
"mismatch between host name and server certificate sslmode=verify-ca");
|
||||
test_connect_fails($common_connstr, "sslmode=verify-full host=wronghost.test",
|
||||
qr/\Qserver certificate for "common-name.pg-ssltest.test" does not match host name "wronghost.test"\E/,
|
||||
"mismatch between host name and server certificate sslmode=verify-full");
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"sslmode=require host=wronghost.test",
|
||||
"mismatch between host name and server certificate sslmode=require");
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"sslmode=verify-ca host=wronghost.test",
|
||||
"mismatch between host name and server certificate sslmode=verify-ca");
|
||||
test_connect_fails(
|
||||
$common_connstr,
|
||||
"sslmode=verify-full host=wronghost.test",
|
||||
qr/\Qserver certificate for "common-name.pg-ssltest.test" does not match host name "wronghost.test"\E/,
|
||||
"mismatch between host name and server certificate sslmode=verify-full");
|
||||
|
||||
# Test Subject Alternative Names.
|
||||
switch_server_cert($node, 'server-multiple-alt-names');
|
||||
@ -183,20 +202,29 @@ switch_server_cert($node, 'server-multiple-alt-names');
|
||||
$common_connstr =
|
||||
"user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full";
|
||||
|
||||
test_connect_ok($common_connstr, "host=dns1.alt-name.pg-ssltest.test",
|
||||
"host name matching with X.509 Subject Alternative Names 1");
|
||||
test_connect_ok($common_connstr, "host=dns2.alt-name.pg-ssltest.test",
|
||||
"host name matching with X.509 Subject Alternative Names 2");
|
||||
test_connect_ok($common_connstr, "host=foo.wildcard.pg-ssltest.test",
|
||||
"host name matching with X.509 Subject Alternative Names wildcard");
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"host=dns1.alt-name.pg-ssltest.test",
|
||||
"host name matching with X.509 Subject Alternative Names 1");
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"host=dns2.alt-name.pg-ssltest.test",
|
||||
"host name matching with X.509 Subject Alternative Names 2");
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"host=foo.wildcard.pg-ssltest.test",
|
||||
"host name matching with X.509 Subject Alternative Names wildcard");
|
||||
|
||||
test_connect_fails($common_connstr, "host=wronghost.alt-name.pg-ssltest.test",
|
||||
qr/\Qserver certificate for "dns1.alt-name.pg-ssltest.test" (and 2 other names) does not match host name "wronghost.alt-name.pg-ssltest.test"\E/,
|
||||
"host name not matching with X.509 Subject Alternative Names");
|
||||
test_connect_fails($common_connstr,
|
||||
"host=deep.subdomain.wildcard.pg-ssltest.test",
|
||||
qr/\Qserver certificate for "dns1.alt-name.pg-ssltest.test" (and 2 other names) does not match host name "deep.subdomain.wildcard.pg-ssltest.test"\E/,
|
||||
"host name not matching with X.509 Subject Alternative Names wildcard");
|
||||
test_connect_fails(
|
||||
$common_connstr,
|
||||
"host=wronghost.alt-name.pg-ssltest.test",
|
||||
qr/\Qserver certificate for "dns1.alt-name.pg-ssltest.test" (and 2 other names) does not match host name "wronghost.alt-name.pg-ssltest.test"\E/,
|
||||
"host name not matching with X.509 Subject Alternative Names");
|
||||
test_connect_fails(
|
||||
$common_connstr,
|
||||
"host=deep.subdomain.wildcard.pg-ssltest.test",
|
||||
qr/\Qserver certificate for "dns1.alt-name.pg-ssltest.test" (and 2 other names) does not match host name "deep.subdomain.wildcard.pg-ssltest.test"\E/,
|
||||
"host name not matching with X.509 Subject Alternative Names wildcard");
|
||||
|
||||
# Test certificate with a single Subject Alternative Name. (this gives a
|
||||
# slightly different error message, that's all)
|
||||
@ -205,16 +233,22 @@ switch_server_cert($node, 'server-single-alt-name');
|
||||
$common_connstr =
|
||||
"user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full";
|
||||
|
||||
test_connect_ok($common_connstr, "host=single.alt-name.pg-ssltest.test",
|
||||
"host name matching with a single X.509 Subject Alternative Name");
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"host=single.alt-name.pg-ssltest.test",
|
||||
"host name matching with a single X.509 Subject Alternative Name");
|
||||
|
||||
test_connect_fails($common_connstr, "host=wronghost.alt-name.pg-ssltest.test",
|
||||
qr/\Qserver certificate for "single.alt-name.pg-ssltest.test" does not match host name "wronghost.alt-name.pg-ssltest.test"\E/,
|
||||
"host name not matching with a single X.509 Subject Alternative Name");
|
||||
test_connect_fails($common_connstr,
|
||||
"host=deep.subdomain.wildcard.pg-ssltest.test",
|
||||
qr/\Qserver certificate for "single.alt-name.pg-ssltest.test" does not match host name "deep.subdomain.wildcard.pg-ssltest.test"\E/,
|
||||
"host name not matching with a single X.509 Subject Alternative Name wildcard");
|
||||
test_connect_fails(
|
||||
$common_connstr,
|
||||
"host=wronghost.alt-name.pg-ssltest.test",
|
||||
qr/\Qserver certificate for "single.alt-name.pg-ssltest.test" does not match host name "wronghost.alt-name.pg-ssltest.test"\E/,
|
||||
"host name not matching with a single X.509 Subject Alternative Name");
|
||||
test_connect_fails(
|
||||
$common_connstr,
|
||||
"host=deep.subdomain.wildcard.pg-ssltest.test",
|
||||
qr/\Qserver certificate for "single.alt-name.pg-ssltest.test" does not match host name "deep.subdomain.wildcard.pg-ssltest.test"\E/,
|
||||
"host name not matching with a single X.509 Subject Alternative Name wildcard"
|
||||
);
|
||||
|
||||
# Test server certificate with a CN and SANs. Per RFCs 2818 and 6125, the CN
|
||||
# should be ignored when the certificate has both.
|
||||
@ -223,13 +257,19 @@ switch_server_cert($node, 'server-cn-and-alt-names');
|
||||
$common_connstr =
|
||||
"user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full";
|
||||
|
||||
test_connect_ok($common_connstr, "host=dns1.alt-name.pg-ssltest.test",
|
||||
"certificate with both a CN and SANs 1");
|
||||
test_connect_ok($common_connstr, "host=dns2.alt-name.pg-ssltest.test",
|
||||
"certificate with both a CN and SANs 2");
|
||||
test_connect_fails($common_connstr, "host=common-name.pg-ssltest.test",
|
||||
qr/\Qserver certificate for "dns1.alt-name.pg-ssltest.test" (and 1 other name) does not match host name "common-name.pg-ssltest.test"\E/,
|
||||
"certificate with both a CN and SANs ignores CN");
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"host=dns1.alt-name.pg-ssltest.test",
|
||||
"certificate with both a CN and SANs 1");
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"host=dns2.alt-name.pg-ssltest.test",
|
||||
"certificate with both a CN and SANs 2");
|
||||
test_connect_fails(
|
||||
$common_connstr,
|
||||
"host=common-name.pg-ssltest.test",
|
||||
qr/\Qserver certificate for "dns1.alt-name.pg-ssltest.test" (and 1 other name) does not match host name "common-name.pg-ssltest.test"\E/,
|
||||
"certificate with both a CN and SANs ignores CN");
|
||||
|
||||
# Finally, test a server certificate that has no CN or SANs. Of course, that's
|
||||
# not a very sensible certificate, but libpq should handle it gracefully.
|
||||
@ -237,13 +277,15 @@ switch_server_cert($node, 'server-no-names');
|
||||
$common_connstr =
|
||||
"user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR";
|
||||
|
||||
test_connect_ok($common_connstr,
|
||||
"sslmode=verify-ca host=common-name.pg-ssltest.test",
|
||||
"server certificate without CN or SANs sslmode=verify-ca");
|
||||
test_connect_fails($common_connstr,
|
||||
"sslmode=verify-full host=common-name.pg-ssltest.test",
|
||||
qr/could not get server's host name from server certificate/,
|
||||
"server certificate without CN or SANs sslmode=verify-full");
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"sslmode=verify-ca host=common-name.pg-ssltest.test",
|
||||
"server certificate without CN or SANs sslmode=verify-ca");
|
||||
test_connect_fails(
|
||||
$common_connstr,
|
||||
"sslmode=verify-full host=common-name.pg-ssltest.test",
|
||||
qr/could not get server's host name from server certificate/,
|
||||
"server certificate without CN or SANs sslmode=verify-full");
|
||||
|
||||
# Test that the CRL works
|
||||
switch_server_cert($node, 'server-revoked');
|
||||
@ -252,13 +294,15 @@ $common_connstr =
|
||||
"user=ssltestuser dbname=trustdb sslcert=invalid hostaddr=$SERVERHOSTADDR host=common-name.pg-ssltest.test";
|
||||
|
||||
# Without the CRL, succeeds. With it, fails.
|
||||
test_connect_ok($common_connstr,
|
||||
"sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca",
|
||||
"connects without client-side CRL");
|
||||
test_connect_fails($common_connstr,
|
||||
"sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=ssl/root+server.crl",
|
||||
qr/SSL error/,
|
||||
"does not connect with client-side CRL");
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca",
|
||||
"connects without client-side CRL");
|
||||
test_connect_fails(
|
||||
$common_connstr,
|
||||
"sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=ssl/root+server.crl",
|
||||
qr/SSL error/,
|
||||
"does not connect with client-side CRL");
|
||||
|
||||
### Server-side tests.
|
||||
###
|
||||
@ -270,47 +314,51 @@ $common_connstr =
|
||||
"sslrootcert=ssl/root+server_ca.crt sslmode=require dbname=certdb hostaddr=$SERVERHOSTADDR";
|
||||
|
||||
# no client cert
|
||||
test_connect_fails($common_connstr,
|
||||
"user=ssltestuser sslcert=invalid",
|
||||
qr/connection requires a valid client certificate/,
|
||||
"certificate authorization fails without client cert");
|
||||
test_connect_fails(
|
||||
$common_connstr,
|
||||
"user=ssltestuser sslcert=invalid",
|
||||
qr/connection requires a valid client certificate/,
|
||||
"certificate authorization fails without client cert");
|
||||
|
||||
# correct client cert
|
||||
test_connect_ok($common_connstr,
|
||||
"user=ssltestuser sslcert=ssl/client.crt sslkey=ssl/client_tmp.key",
|
||||
"certificate authorization succeeds with correct client cert");
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"user=ssltestuser sslcert=ssl/client.crt sslkey=ssl/client_tmp.key",
|
||||
"certificate authorization succeeds with correct client cert");
|
||||
|
||||
# client key with wrong permissions
|
||||
test_connect_fails($common_connstr,
|
||||
"user=ssltestuser sslcert=ssl/client.crt sslkey=ssl/client_wrongperms_tmp.key",
|
||||
qr!\Qprivate key file "ssl/client_wrongperms_tmp.key" has group or world access\E!,
|
||||
"certificate authorization fails because of file permissions");
|
||||
test_connect_fails(
|
||||
$common_connstr,
|
||||
"user=ssltestuser sslcert=ssl/client.crt sslkey=ssl/client_wrongperms_tmp.key",
|
||||
qr!\Qprivate key file "ssl/client_wrongperms_tmp.key" has group or world access\E!,
|
||||
"certificate authorization fails because of file permissions");
|
||||
|
||||
# client cert belonging to another user
|
||||
test_connect_fails($common_connstr,
|
||||
"user=anotheruser sslcert=ssl/client.crt sslkey=ssl/client_tmp.key",
|
||||
qr/certificate authentication failed for user "anotheruser"/,
|
||||
"certificate authorization fails with client cert belonging to another user");
|
||||
test_connect_fails(
|
||||
$common_connstr,
|
||||
"user=anotheruser sslcert=ssl/client.crt sslkey=ssl/client_tmp.key",
|
||||
qr/certificate authentication failed for user "anotheruser"/,
|
||||
"certificate authorization fails with client cert belonging to another user");
|
||||
|
||||
# revoked client cert
|
||||
test_connect_fails($common_connstr,
|
||||
"user=ssltestuser sslcert=ssl/client-revoked.crt sslkey=ssl/client-revoked_tmp.key",
|
||||
qr/SSL error/,
|
||||
"certificate authorization fails with revoked client cert");
|
||||
test_connect_fails(
|
||||
$common_connstr,
|
||||
"user=ssltestuser sslcert=ssl/client-revoked.crt sslkey=ssl/client-revoked_tmp.key",
|
||||
qr/SSL error/,
|
||||
"certificate authorization fails with revoked client cert");
|
||||
|
||||
# intermediate client_ca.crt is provided by client, and isn't in server's ssl_ca_file
|
||||
switch_server_cert($node, 'server-cn-only', 'root_ca');
|
||||
$common_connstr =
|
||||
"user=ssltestuser dbname=certdb sslkey=ssl/client_tmp.key sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR";
|
||||
|
||||
test_connect_ok($common_connstr,
|
||||
"sslmode=require sslcert=ssl/client+client_ca.crt",
|
||||
"intermediate client certificate is provided by client");
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"sslmode=require sslcert=ssl/client+client_ca.crt",
|
||||
"intermediate client certificate is provided by client");
|
||||
test_connect_fails($common_connstr, "sslmode=require sslcert=ssl/client.crt",
|
||||
qr/SSL error/,
|
||||
"intermediate client certificate is missing");
|
||||
qr/SSL error/, "intermediate client certificate is missing");
|
||||
|
||||
# clean up
|
||||
unlink("ssl/client_tmp.key",
|
||||
"ssl/client_wrongperms_tmp.key",
|
||||
"ssl/client-revoked_tmp.key");
|
||||
unlink("ssl/client_tmp.key", "ssl/client_wrongperms_tmp.key",
|
||||
"ssl/client-revoked_tmp.key");
|
||||
|
@ -20,7 +20,7 @@ my $SERVERHOSTADDR = '127.0.0.1';
|
||||
|
||||
# Determine whether build supports tls-server-end-point.
|
||||
my $supports_tls_server_end_point =
|
||||
check_pg_config("#define HAVE_X509_GET_SIGNATURE_NID 1");
|
||||
check_pg_config("#define HAVE_X509_GET_SIGNATURE_NID 1");
|
||||
|
||||
# Allocation of base connection string shared among multiple tests.
|
||||
my $common_connstr;
|
||||
@ -39,38 +39,41 @@ $node->start;
|
||||
|
||||
# Configure server for SSL connections, with password handling.
|
||||
configure_test_server_for_ssl($node, $SERVERHOSTADDR, "scram-sha-256",
|
||||
"pass", "scram-sha-256");
|
||||
"pass", "scram-sha-256");
|
||||
switch_server_cert($node, 'server-cn-only');
|
||||
$ENV{PGPASSWORD} = "pass";
|
||||
$common_connstr =
|
||||
"user=ssltestuser dbname=trustdb sslmode=require hostaddr=$SERVERHOSTADDR";
|
||||
"user=ssltestuser dbname=trustdb sslmode=require hostaddr=$SERVERHOSTADDR";
|
||||
|
||||
# Default settings
|
||||
test_connect_ok($common_connstr, '',
|
||||
"SCRAM authentication with default channel binding");
|
||||
"SCRAM authentication with default channel binding");
|
||||
|
||||
# Channel binding settings
|
||||
test_connect_ok($common_connstr,
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"scram_channel_binding=tls-unique",
|
||||
"SCRAM authentication with tls-unique as channel binding");
|
||||
test_connect_ok($common_connstr,
|
||||
"scram_channel_binding=''",
|
||||
"SCRAM authentication without channel binding");
|
||||
test_connect_ok($common_connstr, "scram_channel_binding=''",
|
||||
"SCRAM authentication without channel binding");
|
||||
if ($supports_tls_server_end_point)
|
||||
{
|
||||
test_connect_ok($common_connstr,
|
||||
"scram_channel_binding=tls-server-end-point",
|
||||
"SCRAM authentication with tls-server-end-point as channel binding");
|
||||
test_connect_ok(
|
||||
$common_connstr,
|
||||
"scram_channel_binding=tls-server-end-point",
|
||||
"SCRAM authentication with tls-server-end-point as channel binding");
|
||||
}
|
||||
else
|
||||
{
|
||||
test_connect_fails($common_connstr,
|
||||
"scram_channel_binding=tls-server-end-point",
|
||||
qr/channel binding type "tls-server-end-point" is not supported by this build/,
|
||||
"SCRAM authentication with tls-server-end-point as channel binding");
|
||||
test_connect_fails(
|
||||
$common_connstr,
|
||||
"scram_channel_binding=tls-server-end-point",
|
||||
qr/channel binding type "tls-server-end-point" is not supported by this build/,
|
||||
"SCRAM authentication with tls-server-end-point as channel binding");
|
||||
$number_of_tests++;
|
||||
}
|
||||
test_connect_fails($common_connstr,
|
||||
test_connect_fails(
|
||||
$common_connstr,
|
||||
"scram_channel_binding=not-exists",
|
||||
qr/unsupported SCRAM channel-binding type/,
|
||||
"SCRAM authentication with invalid channel binding");
|
||||
|
@ -32,7 +32,8 @@ $node_publisher->safe_psql('postgres',
|
||||
$node_publisher->safe_psql('postgres',
|
||||
"INSERT INTO tab_mixed (a, b) VALUES (1, 'foo')");
|
||||
$node_publisher->safe_psql('postgres',
|
||||
"CREATE TABLE tab_include (a int, b text, CONSTRAINT covering PRIMARY KEY(a) INCLUDE(b))");
|
||||
"CREATE TABLE tab_include (a int, b text, CONSTRAINT covering PRIMARY KEY(a) INCLUDE(b))"
|
||||
);
|
||||
|
||||
# Setup structure on subscriber
|
||||
$node_subscriber->safe_psql('postgres', "CREATE TABLE tab_notrep (a int)");
|
||||
@ -48,7 +49,8 @@ $node_subscriber->safe_psql('postgres',
|
||||
|
||||
# replication of the table with included index
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"CREATE TABLE tab_include (a int, b text, CONSTRAINT covering PRIMARY KEY(a) INCLUDE(b))");
|
||||
"CREATE TABLE tab_include (a int, b text, CONSTRAINT covering PRIMARY KEY(a) INCLUDE(b))"
|
||||
);
|
||||
|
||||
# Setup logical replication
|
||||
my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
|
||||
@ -97,7 +99,8 @@ $node_publisher->safe_psql('postgres',
|
||||
|
||||
$node_publisher->safe_psql('postgres',
|
||||
"INSERT INTO tab_include SELECT generate_series(1,50)");
|
||||
$node_publisher->safe_psql('postgres', "DELETE FROM tab_include WHERE a > 20");
|
||||
$node_publisher->safe_psql('postgres',
|
||||
"DELETE FROM tab_include WHERE a > 20");
|
||||
$node_publisher->safe_psql('postgres', "UPDATE tab_include SET a = -a");
|
||||
|
||||
$node_publisher->wait_for_catchup($appname);
|
||||
@ -117,7 +120,8 @@ is( $result, qq(|foo|1
|
||||
|
||||
$result = $node_subscriber->safe_psql('postgres',
|
||||
"SELECT count(*), min(a), max(a) FROM tab_include");
|
||||
is($result, qq(20|-20|-1), 'check replicated changes with primary key index with included columns');
|
||||
is($result, qq(20|-20|-1),
|
||||
'check replicated changes with primary key index with included columns');
|
||||
|
||||
# insert some duplicate rows
|
||||
$node_publisher->safe_psql('postgres',
|
||||
|
@ -34,7 +34,7 @@ $node_publisher->wait_for_catchup($appname);
|
||||
|
||||
# Wait for initial sync to finish as well
|
||||
my $synced_query =
|
||||
"SELECT count(1) = 0 FROM pg_subscription_rel WHERE srsubstate NOT IN ('s', 'r');";
|
||||
"SELECT count(1) = 0 FROM pg_subscription_rel WHERE srsubstate NOT IN ('s', 'r');";
|
||||
$node_subscriber->poll_query_until('postgres', $synced_query)
|
||||
or die "Timed out while waiting for subscriber to synchronize data";
|
||||
|
||||
|
@ -30,18 +30,19 @@ $node_publisher->wait_for_catchup($appname);
|
||||
|
||||
# Wait for initial sync to finish as well
|
||||
my $synced_query =
|
||||
"SELECT count(1) = 0 FROM pg_subscription_rel WHERE srsubstate NOT IN ('s', 'r');";
|
||||
"SELECT count(1) = 0 FROM pg_subscription_rel WHERE srsubstate NOT IN ('s', 'r');";
|
||||
$node_subscriber->poll_query_until('postgres', $synced_query)
|
||||
or die "Timed out while waiting for subscriber to synchronize data";
|
||||
|
||||
$node_publisher->safe_psql('postgres', q{INSERT INTO test1 (a, b) VALUES (1, 'one'), (2, 'two');});
|
||||
$node_publisher->safe_psql('postgres',
|
||||
q{INSERT INTO test1 (a, b) VALUES (1, 'one'), (2, 'two');});
|
||||
|
||||
$node_publisher->wait_for_catchup($appname);
|
||||
|
||||
is($node_subscriber->safe_psql('postgres', q{SELECT a, b FROM test1}),
|
||||
qq(1|one
|
||||
is( $node_subscriber->safe_psql('postgres', q{SELECT a, b FROM test1}),
|
||||
qq(1|one
|
||||
2|two),
|
||||
'initial data replicated to subscriber');
|
||||
'initial data replicated to subscriber');
|
||||
|
||||
# DDL that causes a heap rewrite
|
||||
my $ddl2 = "ALTER TABLE test1 ADD c int NOT NULL DEFAULT 0;";
|
||||
@ -50,15 +51,16 @@ $node_publisher->safe_psql('postgres', $ddl2);
|
||||
|
||||
$node_publisher->wait_for_catchup($appname);
|
||||
|
||||
$node_publisher->safe_psql('postgres', q{INSERT INTO test1 (a, b, c) VALUES (3, 'three', 33);});
|
||||
$node_publisher->safe_psql('postgres',
|
||||
q{INSERT INTO test1 (a, b, c) VALUES (3, 'three', 33);});
|
||||
|
||||
$node_publisher->wait_for_catchup($appname);
|
||||
|
||||
is($node_subscriber->safe_psql('postgres', q{SELECT a, b, c FROM test1}),
|
||||
qq(1|one|0
|
||||
is( $node_subscriber->safe_psql('postgres', q{SELECT a, b, c FROM test1}),
|
||||
qq(1|one|0
|
||||
2|two|0
|
||||
3|three|33),
|
||||
'data replicated to subscriber');
|
||||
'data replicated to subscriber');
|
||||
|
||||
$node_subscriber->stop;
|
||||
$node_publisher->stop;
|
||||
|
@ -28,7 +28,8 @@ $node_subscriber->safe_psql('postgres',
|
||||
|
||||
$node_publisher->wait_for_catchup($appname);
|
||||
|
||||
$node_subscriber->safe_psql('postgres', q{
|
||||
$node_subscriber->safe_psql(
|
||||
'postgres', q{
|
||||
BEGIN;
|
||||
ALTER SUBSCRIPTION mysub DISABLE;
|
||||
ALTER SUBSCRIPTION mysub SET (slot_name = NONE);
|
||||
|
@ -22,11 +22,14 @@ $node_publisher->safe_psql('postgres',
|
||||
"INSERT INTO test_tab VALUES (1, 'foo'), (2, 'bar')");
|
||||
|
||||
# Setup structure on subscriber
|
||||
$node_subscriber->safe_psql('postgres', "CREATE TABLE test_tab (a int primary key, b text, c timestamptz DEFAULT now(), d bigint DEFAULT 999, e int GENERATED BY DEFAULT AS IDENTITY)");
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"CREATE TABLE test_tab (a int primary key, b text, c timestamptz DEFAULT now(), d bigint DEFAULT 999, e int GENERATED BY DEFAULT AS IDENTITY)"
|
||||
);
|
||||
|
||||
# Setup logical replication
|
||||
my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
|
||||
$node_publisher->safe_psql('postgres', "CREATE PUBLICATION tap_pub FOR TABLE test_tab");
|
||||
$node_publisher->safe_psql('postgres',
|
||||
"CREATE PUBLICATION tap_pub FOR TABLE test_tab");
|
||||
|
||||
my $appname = 'tap_sub';
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
@ -42,7 +45,8 @@ $node_subscriber->poll_query_until('postgres', $synced_query)
|
||||
or die "Timed out while waiting for subscriber to synchronize data";
|
||||
|
||||
my $result =
|
||||
$node_subscriber->safe_psql('postgres', "SELECT count(*), count(c), count(d = 999) FROM test_tab");
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"SELECT count(*), count(c), count(d = 999) FROM test_tab");
|
||||
is($result, qq(2|2|2), 'check initial data was copied to subscriber');
|
||||
|
||||
# Update the rows on the publisher and check the additional columns on
|
||||
@ -52,19 +56,25 @@ $node_publisher->safe_psql('postgres', "UPDATE test_tab SET b = md5(b)");
|
||||
$node_publisher->wait_for_catchup($appname);
|
||||
|
||||
$result =
|
||||
$node_subscriber->safe_psql('postgres', "SELECT count(*), count(c), count(d = 999), count(e) FROM test_tab");
|
||||
is($result, qq(2|2|2|2), 'check extra columns contain local defaults after copy');
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"SELECT count(*), count(c), count(d = 999), count(e) FROM test_tab");
|
||||
is($result, qq(2|2|2|2),
|
||||
'check extra columns contain local defaults after copy');
|
||||
|
||||
# Change the local values of the extra columns on the subscriber,
|
||||
# update publisher, and check that subscriber retains the expected
|
||||
# values
|
||||
$node_subscriber->safe_psql('postgres', "UPDATE test_tab SET c = 'epoch'::timestamptz + 987654321 * interval '1s'");
|
||||
$node_publisher->safe_psql('postgres', "UPDATE test_tab SET b = md5(a::text)");
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"UPDATE test_tab SET c = 'epoch'::timestamptz + 987654321 * interval '1s'"
|
||||
);
|
||||
$node_publisher->safe_psql('postgres',
|
||||
"UPDATE test_tab SET b = md5(a::text)");
|
||||
|
||||
$node_publisher->wait_for_catchup($appname);
|
||||
|
||||
$result =
|
||||
$node_subscriber->safe_psql('postgres', "SELECT count(*), count(extract(epoch from c) = 987654321), count(d = 999) FROM test_tab");
|
||||
$result = $node_subscriber->safe_psql('postgres',
|
||||
"SELECT count(*), count(extract(epoch from c) = 987654321), count(d = 999) FROM test_tab"
|
||||
);
|
||||
is($result, qq(2|2|2), 'check extra columns contain locally changed data');
|
||||
|
||||
# Another insert
|
||||
@ -74,8 +84,10 @@ $node_publisher->safe_psql('postgres',
|
||||
$node_publisher->wait_for_catchup($appname);
|
||||
|
||||
$result =
|
||||
$node_subscriber->safe_psql('postgres', "SELECT count(*), count(c), count(d = 999), count(e) FROM test_tab");
|
||||
is($result, qq(3|3|3|3), 'check extra columns contain local defaults after apply');
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"SELECT count(*), count(c), count(d = 999), count(e) FROM test_tab");
|
||||
is($result, qq(3|3|3|3),
|
||||
'check extra columns contain local defaults after apply');
|
||||
|
||||
$node_subscriber->stop;
|
||||
$node_publisher->stop;
|
||||
|
@ -22,10 +22,13 @@ $node_subscriber->safe_psql('postgres',
|
||||
"CREATE SUBSCRIPTION mysub CONNECTION '$publisher_connstr application_name=$appname' PUBLICATION mypub;"
|
||||
);
|
||||
|
||||
$node_publisher->safe_psql('postgres', q{CREATE TABLE test1 (a int PRIMARY KEY, b text)});
|
||||
$node_publisher->safe_psql('postgres', q{INSERT INTO test1 (a, b) VALUES (1, 'one'), (2, 'two');});
|
||||
$node_publisher->safe_psql('postgres',
|
||||
q{CREATE TABLE test1 (a int PRIMARY KEY, b text)});
|
||||
$node_publisher->safe_psql('postgres',
|
||||
q{INSERT INTO test1 (a, b) VALUES (1, 'one'), (2, 'two');});
|
||||
|
||||
$node_subscriber->safe_psql('postgres', q{CREATE TABLE test1 (a int PRIMARY KEY, b text);});
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
q{CREATE TABLE test1 (a int PRIMARY KEY, b text);});
|
||||
|
||||
$node_publisher->wait_for_catchup($appname);
|
||||
|
||||
@ -34,8 +37,10 @@ $node_publisher->wait_for_catchup($appname);
|
||||
# need to make sure they are properly ignored. (bug #15044)
|
||||
|
||||
# create a MV with some data
|
||||
$node_publisher->safe_psql('postgres', q{CREATE MATERIALIZED VIEW testmv1 AS SELECT * FROM test1;});
|
||||
$node_publisher->safe_psql('postgres',
|
||||
q{CREATE MATERIALIZED VIEW testmv1 AS SELECT * FROM test1;});
|
||||
$node_publisher->wait_for_catchup($appname);
|
||||
|
||||
# There is no equivalent relation on the subscriber, but MV data is
|
||||
# not replicated, so this does not hang.
|
||||
|
||||
|
@ -42,11 +42,8 @@ $node_subscriber->safe_psql('postgres',
|
||||
"CREATE TABLE tab4 (x int PRIMARY KEY, y int REFERENCES tab3)");
|
||||
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"CREATE SEQUENCE seq1 OWNED BY tab1.a"
|
||||
);
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"ALTER SEQUENCE seq1 START 101"
|
||||
);
|
||||
"CREATE SEQUENCE seq1 OWNED BY tab1.a");
|
||||
$node_subscriber->safe_psql('postgres', "ALTER SEQUENCE seq1 START 101");
|
||||
|
||||
$node_publisher->safe_psql('postgres',
|
||||
"CREATE PUBLICATION pub1 FOR TABLE tab1");
|
||||
@ -55,11 +52,14 @@ $node_publisher->safe_psql('postgres',
|
||||
$node_publisher->safe_psql('postgres',
|
||||
"CREATE PUBLICATION pub3 FOR TABLE tab3, tab4");
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"CREATE SUBSCRIPTION sub1 CONNECTION '$publisher_connstr application_name=sub1' PUBLICATION pub1");
|
||||
"CREATE SUBSCRIPTION sub1 CONNECTION '$publisher_connstr application_name=sub1' PUBLICATION pub1"
|
||||
);
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"CREATE SUBSCRIPTION sub2 CONNECTION '$publisher_connstr application_name=sub2' PUBLICATION pub2");
|
||||
"CREATE SUBSCRIPTION sub2 CONNECTION '$publisher_connstr application_name=sub2' PUBLICATION pub2"
|
||||
);
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"CREATE SUBSCRIPTION sub3 CONNECTION '$publisher_connstr application_name=sub3' PUBLICATION pub3");
|
||||
"CREATE SUBSCRIPTION sub3 CONNECTION '$publisher_connstr application_name=sub3' PUBLICATION pub3"
|
||||
);
|
||||
|
||||
# Wait for initial sync of all subscriptions
|
||||
my $synced_query =
|
||||
@ -69,7 +69,8 @@ $node_subscriber->poll_query_until('postgres', $synced_query)
|
||||
|
||||
# insert data to truncate
|
||||
|
||||
$node_subscriber->safe_psql('postgres', "INSERT INTO tab1 VALUES (1), (2), (3)");
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"INSERT INTO tab1 VALUES (1), (2), (3)");
|
||||
|
||||
$node_publisher->wait_for_catchup('sub1');
|
||||
|
||||
@ -81,13 +82,10 @@ $node_publisher->wait_for_catchup('sub1');
|
||||
|
||||
my $result = $node_subscriber->safe_psql('postgres',
|
||||
"SELECT count(*), min(a), max(a) FROM tab1");
|
||||
is($result, qq(0||),
|
||||
'truncate replicated');
|
||||
is($result, qq(0||), 'truncate replicated');
|
||||
|
||||
$result = $node_subscriber->safe_psql('postgres',
|
||||
"SELECT nextval('seq1')");
|
||||
is($result, qq(1),
|
||||
'sequence not restarted');
|
||||
$result = $node_subscriber->safe_psql('postgres', "SELECT nextval('seq1')");
|
||||
is($result, qq(1), 'sequence not restarted');
|
||||
|
||||
# truncate with restart identity
|
||||
|
||||
@ -95,14 +93,13 @@ $node_publisher->safe_psql('postgres', "TRUNCATE tab1 RESTART IDENTITY");
|
||||
|
||||
$node_publisher->wait_for_catchup('sub1');
|
||||
|
||||
$result = $node_subscriber->safe_psql('postgres',
|
||||
"SELECT nextval('seq1')");
|
||||
is($result, qq(101),
|
||||
'truncate restarted identities');
|
||||
$result = $node_subscriber->safe_psql('postgres', "SELECT nextval('seq1')");
|
||||
is($result, qq(101), 'truncate restarted identities');
|
||||
|
||||
# test publication that does not replicate truncate
|
||||
|
||||
$node_subscriber->safe_psql('postgres', "INSERT INTO tab2 VALUES (1), (2), (3)");
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"INSERT INTO tab2 VALUES (1), (2), (3)");
|
||||
|
||||
$node_publisher->safe_psql('postgres', "TRUNCATE tab2");
|
||||
|
||||
@ -110,8 +107,7 @@ $node_publisher->wait_for_catchup('sub2');
|
||||
|
||||
$result = $node_subscriber->safe_psql('postgres',
|
||||
"SELECT count(*), min(a), max(a) FROM tab2");
|
||||
is($result, qq(3|1|3),
|
||||
'truncate not replicated');
|
||||
is($result, qq(3|1|3), 'truncate not replicated');
|
||||
|
||||
$node_publisher->safe_psql('postgres',
|
||||
"ALTER PUBLICATION pub2 SET (publish = 'insert, truncate')");
|
||||
@ -122,13 +118,14 @@ $node_publisher->wait_for_catchup('sub2');
|
||||
|
||||
$result = $node_subscriber->safe_psql('postgres',
|
||||
"SELECT count(*), min(a), max(a) FROM tab2");
|
||||
is($result, qq(0||),
|
||||
'truncate replicated after publication change');
|
||||
is($result, qq(0||), 'truncate replicated after publication change');
|
||||
|
||||
# test multiple tables connected by foreign keys
|
||||
|
||||
$node_subscriber->safe_psql('postgres', "INSERT INTO tab3 VALUES (1), (2), (3)");
|
||||
$node_subscriber->safe_psql('postgres', "INSERT INTO tab4 VALUES (11, 1), (111, 1), (22, 2)");
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"INSERT INTO tab3 VALUES (1), (2), (3)");
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"INSERT INTO tab4 VALUES (11, 1), (111, 1), (22, 2)");
|
||||
|
||||
$node_publisher->safe_psql('postgres', "TRUNCATE tab3, tab4");
|
||||
|
||||
@ -136,20 +133,20 @@ $node_publisher->wait_for_catchup('sub3');
|
||||
|
||||
$result = $node_subscriber->safe_psql('postgres',
|
||||
"SELECT count(*), min(a), max(a) FROM tab3");
|
||||
is($result, qq(0||),
|
||||
'truncate of multiple tables replicated');
|
||||
is($result, qq(0||), 'truncate of multiple tables replicated');
|
||||
$result = $node_subscriber->safe_psql('postgres',
|
||||
"SELECT count(*), min(x), max(x) FROM tab4");
|
||||
is($result, qq(0||),
|
||||
'truncate of multiple tables replicated');
|
||||
is($result, qq(0||), 'truncate of multiple tables replicated');
|
||||
|
||||
# test truncate of multiple tables, some of which are not published
|
||||
|
||||
$node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION sub2");
|
||||
$node_publisher->safe_psql('postgres', "DROP PUBLICATION pub2");
|
||||
|
||||
$node_subscriber->safe_psql('postgres', "INSERT INTO tab1 VALUES (1), (2), (3)");
|
||||
$node_subscriber->safe_psql('postgres', "INSERT INTO tab2 VALUES (1), (2), (3)");
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"INSERT INTO tab1 VALUES (1), (2), (3)");
|
||||
$node_subscriber->safe_psql('postgres',
|
||||
"INSERT INTO tab2 VALUES (1), (2), (3)");
|
||||
|
||||
$node_publisher->safe_psql('postgres', "TRUNCATE tab1, tab2");
|
||||
|
||||
@ -157,9 +154,7 @@ $node_publisher->wait_for_catchup('sub1');
|
||||
|
||||
$result = $node_subscriber->safe_psql('postgres',
|
||||
"SELECT count(*), min(a), max(a) FROM tab1");
|
||||
is($result, qq(0||),
|
||||
'truncate of multiple tables some not published');
|
||||
is($result, qq(0||), 'truncate of multiple tables some not published');
|
||||
$result = $node_subscriber->safe_psql('postgres',
|
||||
"SELECT count(*), min(a), max(a) FROM tab2");
|
||||
is($result, qq(3|1|3),
|
||||
'truncate of multiple tables some not published');
|
||||
is($result, qq(3|1|3), 'truncate of multiple tables some not published');
|
||||
|
Reference in New Issue
Block a user