Refactor ssl tests to avoid using internal PostgreSQL::Test::Cluster methods
The SSL tests for pg_ctl restarts with an incorrect key passphrase run pg_ctl
manually and use the internal method _update_pid to set the server PID file
accordingly. This is needed since $node->restart will BAIL in case the restart
fails, which clearly isn't useful to anyone wanting to test restarts. This is
the only use of _update_pid outside of Cluster.pm.
To avoid this, the attached adds fail_ok functionality to restart() which makes
it easier to use it in tests, and aligns it with how stop() and start() works.
The resulting SSL tests are also more readable IMO.
--
Daniel Gustafsson
Attachments:
v1-0001-Avoid-using-internal-test-methods-in-SSL-tests.patchapplication/octet-stream; name=v1-0001-Avoid-using-internal-test-methods-in-SSL-tests.patch; x-unix-mode=0644Download
From 8ccb3641cce6e69e681a491c47d42ff8cfec778f Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Wed, 31 May 2023 12:23:05 +0200
Subject: [PATCH v1] Avoid using internal test methods in SSL tests
The SSL tests for pg_ctl restart with an incorrect key passphrase used
the internal _update_pid method to set the pidfile after running pg_ctl
manually instead of using the supplied ->restart method. This refactors
the ->restart method to accept a fail_ok parameter like how ->start and
->stop does, and changes the SSL tests to use this instead. This removes
the need to call internal test module functions.
---
src/test/perl/PostgreSQL/Test/Cluster.pm | 24 ++++++++++++++++++------
src/test/ssl/t/001_ssltests.pl | 12 ++++--------
2 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm
index baea0fcd1c..1dcc049525 100644
--- a/src/test/perl/PostgreSQL/Test/Cluster.pm
+++ b/src/test/perl/PostgreSQL/Test/Cluster.pm
@@ -999,11 +999,9 @@ Wrapper for pg_ctl restart
sub restart
{
- my ($self) = @_;
- my $port = $self->port;
- my $pgdata = $self->data_dir;
- my $logfile = $self->logfile;
+ my ($self, %params) = @_;
my $name = $self->name;
+ my $ret;
local %ENV = $self->_get_env(PGAPPNAME => undef);
@@ -1011,8 +1009,22 @@ sub restart
# -w is now the default but having it here does no harm and helps
# compatibility with older versions.
- PostgreSQL::Test::Utils::system_or_bail('pg_ctl', '-w', '-D', $pgdata,
- '-l', $logfile, 'restart');
+ $ret = PostgreSQL::Test::Utils::system_log(
+ 'pg_ctl', '-w', '-D', $self->data_dir,
+ '-l', $self->logfile, 'restart');
+
+ if ($ret != 0)
+ {
+ print "# pg_ctl restart failed; logfile:\n";
+ print PostgreSQL::Test::Utils::slurp_file($self->logfile);
+
+ # pg_ctl could have timed out, so check to see if there's a pid file;
+ # otherwise our END block will fail to shut down the new postmaster.
+ $self->_update_pid(-1);
+
+ BAIL_OUT("pg_ctl restart failed") unless $params{fail_ok};
+ return 0;
+ }
$self->_update_pid(1);
return;
diff --git a/src/test/ssl/t/001_ssltests.pl b/src/test/ssl/t/001_ssltests.pl
index 76442de063..547b574746 100644
--- a/src/test/ssl/t/001_ssltests.pl
+++ b/src/test/ssl/t/001_ssltests.pl
@@ -85,10 +85,8 @@ switch_server_cert(
passphrase_cmd => 'echo wrongpassword',
restart => 'no');
-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);
+$result = $node->restart(fail_ok => 1);
+is($result, 0, 'restart fails with password-protected key file with wrong password');
switch_server_cert(
$node,
@@ -98,10 +96,8 @@ switch_server_cert(
passphrase_cmd => 'echo secret1',
restart => 'no');
-command_ok(
- [ 'pg_ctl', '-D', $node->data_dir, '-l', $node->logfile, 'restart' ],
- 'restart succeeds with password-protected key file');
-$node->_update_pid(1);
+$result = $node->start(fail_ok => 1);
+is($result, 1, 'restart succeeds with password-protected key file');
# Test compatibility of SSL protocols.
# TLSv1.1 is lower than TLSv1.2, so it won't work.
--
2.32.1 (Apple Git-133)
Hi Daniel,
Thanks for the patch.
Daniel Gustafsson <daniel@yesql.se>, 31 May 2023 Çar, 15:48 tarihinde
şunu yazdı:
To avoid this, the attached adds fail_ok functionality to restart() which makes
it easier to use it in tests, and aligns it with how stop() and start() works.
The resulting SSL tests are also more readable IMO.
I agree that it's more readable this way.
I only have a few comments:
+ BAIL_OUT("pg_ctl restart failed") unless $params{fail_ok}; + return 0; + }$self->_update_pid(1);
return;
I was comparing this new restart function to start and stop functions.
I see that restart() does not return a value if it's successful while
others return 1.
Its return value is not checked anywhere, so it may not be useful at
the moment. But I feel like it would be nice to make it look like
start()/stop(). What do you think?
command_fails(
[ 'pg_ctl', '-D', $node->data_dir, '-l', $node->logfile, 'restart' ],
'restart fails with incorrect SSL protocol bounds');
There are two other places where ssl tests restart the node like
above. We can call $node->restart in those lines too.
Best,
--
Melih Mutlu
Microsoft
On 31 May 2023, at 15:46, Melih Mutlu <m.melihmutlu@gmail.com> wrote:
I was comparing this new restart function to start and stop functions.
I see that restart() does not return a value if it's successful while
others return 1.
Its return value is not checked anywhere, so it may not be useful at
the moment. But I feel like it would be nice to make it look like
start()/stop(). What do you think?
It should absolutely return 1, that was an oversight. Fixed as well as
documentation updated.
command_fails(
[ 'pg_ctl', '-D', $node->data_dir, '-l', $node->logfile, 'restart' ],
'restart fails with incorrect SSL protocol bounds');There are two other places where ssl tests restart the node like
above. We can call $node->restart in those lines too.
Fixed in the attached v2.
--
Daniel Gustafsson
Attachments:
v2-0001-Avoid-using-internal-test-methods-in-SSL-tests.patchapplication/octet-stream; name=v2-0001-Avoid-using-internal-test-methods-in-SSL-tests.patch; x-unix-mode=0644Download
From 4ed8977eaf4564ceb60e5ef153c0c75baa8e1297 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Wed, 31 May 2023 12:23:05 +0200
Subject: [PATCH v2] Avoid using internal test methods in SSL tests
The SSL tests for pg_ctl restart with an incorrect key passphrase used
the internal _update_pid method to set the pidfile after running pg_ctl
manually instead of using the supplied ->restart method. This refactors
the ->restart method to accept a fail_ok parameter like how ->start and
->stop does, and changes the SSL tests to use this instead. This removes
the need to call internal test module functions.
---
src/test/perl/PostgreSQL/Test/Cluster.pm | 31 ++++++++++++++++++------
src/test/ssl/t/001_ssltests.pl | 23 +++++++-----------
2 files changed, 32 insertions(+), 22 deletions(-)
diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm
index baea0fcd1c..18b4f3bad5 100644
--- a/src/test/perl/PostgreSQL/Test/Cluster.pm
+++ b/src/test/perl/PostgreSQL/Test/Cluster.pm
@@ -993,17 +993,18 @@ sub reload
=item $node->restart()
-Wrapper for pg_ctl restart
+Wrapper for pg_ctl restart.
+
+With optional extra param fail_ok => 1, returns 0 for failure
+instead of bailing out.
=cut
sub restart
{
- my ($self) = @_;
- my $port = $self->port;
- my $pgdata = $self->data_dir;
- my $logfile = $self->logfile;
+ my ($self, %params) = @_;
my $name = $self->name;
+ my $ret;
local %ENV = $self->_get_env(PGAPPNAME => undef);
@@ -1011,11 +1012,25 @@ sub restart
# -w is now the default but having it here does no harm and helps
# compatibility with older versions.
- PostgreSQL::Test::Utils::system_or_bail('pg_ctl', '-w', '-D', $pgdata,
- '-l', $logfile, 'restart');
+ $ret = PostgreSQL::Test::Utils::system_log(
+ 'pg_ctl', '-w', '-D', $self->data_dir,
+ '-l', $self->logfile, 'restart');
+
+ if ($ret != 0)
+ {
+ print "# pg_ctl restart failed; logfile:\n";
+ print PostgreSQL::Test::Utils::slurp_file($self->logfile);
+
+ # pg_ctl could have timed out, so check to see if there's a pid file;
+ # otherwise our END block will fail to shut down the new postmaster.
+ $self->_update_pid(-1);
+
+ BAIL_OUT("pg_ctl restart failed") unless $params{fail_ok};
+ return 0;
+ }
$self->_update_pid(1);
- return;
+ return 1;
}
=pod
diff --git a/src/test/ssl/t/001_ssltests.pl b/src/test/ssl/t/001_ssltests.pl
index 76442de063..e33f648aae 100644
--- a/src/test/ssl/t/001_ssltests.pl
+++ b/src/test/ssl/t/001_ssltests.pl
@@ -85,10 +85,8 @@ switch_server_cert(
passphrase_cmd => 'echo wrongpassword',
restart => 'no');
-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);
+$result = $node->restart(fail_ok => 1);
+is($result, 0, 'restart fails with password-protected key file with wrong password');
switch_server_cert(
$node,
@@ -98,10 +96,8 @@ switch_server_cert(
passphrase_cmd => 'echo secret1',
restart => 'no');
-command_ok(
- [ 'pg_ctl', '-D', $node->data_dir, '-l', $node->logfile, 'restart' ],
- 'restart succeeds with password-protected key file');
-$node->_update_pid(1);
+$result = $node->restart(fail_ok => 1);
+is($result, 1, 'restart succeeds with password-protected key file');
# Test compatibility of SSL protocols.
# TLSv1.1 is lower than TLSv1.2, so it won't work.
@@ -109,17 +105,16 @@ $node->append_conf(
'postgresql.conf',
qq{ssl_min_protocol_version='TLSv1.2'
ssl_max_protocol_version='TLSv1.1'});
-command_fails(
- [ 'pg_ctl', '-D', $node->data_dir, '-l', $node->logfile, 'restart' ],
- 'restart fails with incorrect SSL protocol bounds');
+$result = $node->restart(fail_ok => 1);
+is($result, 0, 'restart fails with incorrect SSL protocol bounds');
+
# Go back to the defaults, this works.
$node->append_conf(
'postgresql.conf',
qq{ssl_min_protocol_version='TLSv1.2'
ssl_max_protocol_version=''});
-command_ok(
- [ 'pg_ctl', '-D', $node->data_dir, '-l', $node->logfile, 'restart' ],
- 'restart succeeds with correct SSL protocol bounds');
+$result = $node->restart(fail_ok => 1);
+is($result, 1, 'restart succeeds with correct SSL protocol bounds');
### Run client-side tests.
###
--
2.32.1 (Apple Git-133)
On 31/05/2023 15:47, Daniel Gustafsson wrote:
The SSL tests for pg_ctl restarts with an incorrect key passphrase run pg_ctl
manually and use the internal method _update_pid to set the server PID file
accordingly. This is needed since $node->restart will BAIL in case the restart
fails, which clearly isn't useful to anyone wanting to test restarts. This is
the only use of _update_pid outside of Cluster.pm.To avoid this, the attached adds fail_ok functionality to restart() which makes
it easier to use it in tests, and aligns it with how stop() and start() works.
The resulting SSL tests are also more readable IMO.
Makes sense.
diff --git a/src/test/ssl/t/001_ssltests.pl b/src/test/ssl/t/001_ssltests.pl index 76442de063..e33f648aae 100644 --- a/src/test/ssl/t/001_ssltests.pl +++ b/src/test/ssl/t/001_ssltests.pl @@ -85,10 +85,8 @@ switch_server_cert( passphrase_cmd => 'echo wrongpassword', restart => 'no');-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); +$result = $node->restart(fail_ok => 1); +is($result, 0, 'restart fails with password-protected key file with wrong password');switch_server_cert(
$node,
In principle, this makes the tests more lenient. If "pg_ctl restart"
fails because of a timeout, for example, the PID file could be present.
Previously, the _update_pid(0) would error out on that, but now it's
accepted. I think that's fine, but just wanted to point it out.
--
Heikki Linnakangas
Neon (https://neon.tech)
On 3 Jul 2023, at 13:37, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
If "pg_ctl restart" fails because of a timeout, for example, the PID file could be present. Previously, the _update_pid(0) would error out on that, but now it's accepted. I think that's fine, but just wanted to point it out.
Revisiting an old patch. Agreed, I think that's fine, so I went ahead and
pushed this. Thanks for review!
It's unfortunately not that common for buildfarm animals to run the SSL tests,
so I guess I'll keep an extra eye on the CFBot for this one.
--
Daniel Gustafsson