Add TAP test for auth_delay extension

Started by sh95119over 3 years ago7 messages
#1sh95119
sh95119@gmail.com
diff --git a/contrib/auth_delay/Makefile b/contrib/auth_delay/Makefile
index 4b86ec37f0..b65097789a 100644
--- a/contrib/auth_delay/Makefile
+++ b/contrib/auth_delay/Makefile
@@ -3,6 +3,8 @@
 MODULES = auth_delay
 PGFILEDESC = "auth_delay - delay authentication failure reports"
+TAP_TESTS = 1
+
 ifdef USE_PGXS
 PG_CONFIG = pg_config
 PGXS := $(shell $(PG_CONFIG) --pgxs)
diff --git a/contrib/auth_delay/t/001_auth_delay.pl b/contrib/auth_delay/t/001_auth_delay.pl
new file mode 100644
index 0000000000..644026e4f2
--- /dev/null
+++ b/contrib/auth_delay/t/001_auth_delay.pl
@@ -0,0 +1,87 @@
+
+# Copyright (c) 2021-2022, PostgreSQL Global Development Group
+
+use strict;
+use warnings;
+
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More;
+use Time::HiRes qw(gettimeofday tv_interval);
+
+# Delete pg_hba.conf from the given node, add a new entry to it
+# and then execute a reload to refresh it.
+sub reset_pg_hba
+{
+    my $node       = shift;
+    my $hba_method = shift;
+
+    unlink($node->data_dir . '/pg_hba.conf');
+    # just for testing purposes, use a continuation line
+    $node->append_conf('pg_hba.conf', "local all all $hba_method");
+    $node->reload;
+    return;
+}
+
+# Test access for a single role, with password
+sub test_login
+{
+    local $Test::Builder::Level = $Test::Builder::Level + 1;
+
+    my $node          = shift;
+    my $role          = shift;
+    my $password      = shift;
+    my $expected_res  = shift;
+    my $status_string = 'failed';
+
+    $status_string = 'success' if ($expected_res eq 0);
+
+    my $connstr = "user=$role";
+    my $testname =
+    "authentication $status_string for role $role with password $password";
+
+    $ENV{"PGPASSWORD"} = $password;
+
+    if ($expected_res eq 0)
+    {
+        $node->connect_ok($connstr, $testname);
+    }
+    else
+    {
+        # No checks of the error message, only the status code.
+        $node->connect_fails($connstr, $testname);
+    }
+}
+
+note "setting up PostgreSQL instance";
+
+my $delay_milliseconds = 500;
+
+my $node = PostgreSQL::Test::Cluster->new('main');
+$node->init;
+$node->append_conf('postgresql.conf',
+    qq{shared_preload_libraries = 'auth_delay'
+       auth_delay.milliseconds  = '$delay_milliseconds'});
+$node->start;
+
+$node->safe_psql(
+    'postgres',
+    "CREATE ROLE user_role LOGIN PASSWORD 'pass';");
+reset_pg_hba($node, 'password');
+
+note "running tests";
+
+# check enter wrong password
+my $t0 = [gettimeofday];
+test_login($node, 'user_role', "wrongpass", 2);
+my $elapsed = tv_interval($t0, [gettimeofday]);
+ok($elapsed >= $delay_milliseconds / 1000, "auth_delay $elapsed seconds");
+
+# check enter correct password
+my $t0 = [gettimeofday];
+test_login($node, 'user_role', "pass", 0);
+my $elapsed = tv_interval($t0, [gettimeofday]);
+ok($elapsed < $delay_milliseconds / 1000, "auth_delay $elapsed seconds");
+
+done_testing();
+
#2Dong Wook Lee
sh95119@gmail.com
In reply to: sh95119 (#1)
Re: Add TAP test for auth_delay extension

Hi Hackers,
I just wrote a test for `auth_delay` extension.
It's a test which confirms whether there is a delay for a second when
you enter the wrong password.
I sent an email using mutt, but I have a problem and sent it again.

---
Regards,
Dong Wook Lee.

#3Dong Wook Lee
sh95119@gmail.com
In reply to: Dong Wook Lee (#2)
Re: Add TAP test for auth_delay extension

2022년 6월 7일 (화) 오후 6:32, Dong Wook Lee <sh95119@gmail.com>님이 작성:

Hi Hackers,
I just wrote a test for `auth_delay` extension.
It's a test which confirms whether there is a delay for a second when
you enter the wrong password.
I sent an email using mutt, but I have a problem and sent it again.

---
Regards,
Dong Wook Lee.

Hi,

I have written a test for the auth_delay extension before,
but if it is okay, can you review it?

---
Regards,
DongWook Lee.

#4Michael Paquier
michael@paquier.xyz
In reply to: Dong Wook Lee (#3)
Re: Add TAP test for auth_delay extension

On Sat, Jun 18, 2022 at 11:06:02AM +0900, Dong Wook Lee wrote:

I have written a test for the auth_delay extension before,
but if it is okay, can you review it?

+# check enter wrong password
+my $t0 = [gettimeofday];
+test_login($node, 'user_role', "wrongpass", 2);
+my $elapsed = tv_interval($t0, [gettimeofday]);
+ok($elapsed >= $delay_milliseconds / 1000, "auth_delay $elapsed seconds");
+
+# check enter correct password
+my $t0 = [gettimeofday];
+test_login($node, 'user_role', "pass", 0);
+my $elapsed = tv_interval($t0, [gettimeofday]);
+ok($elapsed < $delay_milliseconds / 1000, "auth_delay $elapsed seconds");

On a slow machine, I suspect that the second test is going to be
unstable as it would fail if the login attempt (that succeeds) takes
more than $delay_milliseconds. You could increase more
delay_milliseconds to leverage that, but it would make the first test
slower for nothing on faster machines in the case where the
authentication attempt has failed. I guess that you could leverage
that by using a large value for delay_milliseconds in the second test,
because we are never going to wait. For the first test, you could on
the contrary use a much lower value, still on slow machines it may not
test what the code path of auth_delay you are willing to test.

As a whole, I am not sure that this is really worth spending cycles on
when running check-world or similar, and the code of the extension is
trivial.
--
Michael

#5Dong Wook Lee
sh95119@gmail.com
In reply to: Michael Paquier (#4)
1 attachment(s)
Re: Add TAP test for auth_delay extension

On 22/06/18 12:07오후, Michael Paquier wrote:

On Sat, Jun 18, 2022 at 11:06:02AM +0900, Dong Wook Lee wrote:

I have written a test for the auth_delay extension before,
but if it is okay, can you review it?

+# check enter wrong password
+my $t0 = [gettimeofday];
+test_login($node, 'user_role', "wrongpass", 2);
+my $elapsed = tv_interval($t0, [gettimeofday]);
+ok($elapsed >= $delay_milliseconds / 1000, "auth_delay $elapsed seconds");
+
+# check enter correct password
+my $t0 = [gettimeofday];
+test_login($node, 'user_role', "pass", 0);
+my $elapsed = tv_interval($t0, [gettimeofday]);
+ok($elapsed < $delay_milliseconds / 1000, "auth_delay $elapsed seconds");

On a slow machine, I suspect that the second test is going to be
unstable as it would fail if the login attempt (that succeeds) takes
more than $delay_milliseconds. You could increase more
delay_milliseconds to leverage that, but it would make the first test
slower for nothing on faster machines in the case where the
authentication attempt has failed. I guess that you could leverage
that by using a large value for delay_milliseconds in the second test,
because we are never going to wait. For the first test, you could on
the contrary use a much lower value, still on slow machines it may not
test what the code path of auth_delay you are willing to test.

Thank you for your valuable advice I didn't think about the slow system.
Therefore, in the case of the second test, the time was extended a little.

As a whole, I am not sure that this is really worth spending cycles on
when running check-world or similar, and the code of the extension is
trivial.

Even though it is trivial, I think it would be better if there was a test.

Show quoted text

--
Michael

Attachments:

0002_add_test_auth_delay.patchtext/x-diff; charset=us-asciiDownload
diff --git a/contrib/auth_delay/Makefile b/contrib/auth_delay/Makefile
index 4b86ec37f0..b65097789a 100644
--- a/contrib/auth_delay/Makefile
+++ b/contrib/auth_delay/Makefile
@@ -3,6 +3,8 @@
 MODULES = auth_delay
 PGFILEDESC = "auth_delay - delay authentication failure reports"
 
+TAP_TESTS = 1
+
 ifdef USE_PGXS
 PG_CONFIG = pg_config
 PGXS := $(shell $(PG_CONFIG) --pgxs)
diff --git a/contrib/auth_delay/t/001_auth_delay.pl b/contrib/auth_delay/t/001_auth_delay.pl
new file mode 100644
index 0000000000..644026e4f2
--- /dev/null
+++ b/contrib/auth_delay/t/001_auth_delay.pl
@@ -0,0 +1,87 @@
+
+# Copyright (c) 2021-2022, PostgreSQL Global Development Group
+
+use strict;
+use warnings;
+
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More;
+use Time::HiRes qw(gettimeofday tv_interval);
+
+# Delete pg_hba.conf from the given node, add a new entry to it
+# and then execute a reload to refresh it.
+sub reset_pg_hba
+{
+    my $node       = shift;
+    my $hba_method = shift;
+
+    unlink($node->data_dir . '/pg_hba.conf');
+    # just for testing purposes, use a continuation line
+    $node->append_conf('pg_hba.conf', "local all all $hba_method");
+    $node->reload;
+    return;
+}
+
+# Test access for a single role, with password
+sub test_login
+{
+    local $Test::Builder::Level = $Test::Builder::Level + 1;
+
+    my $node          = shift;
+    my $role          = shift;
+    my $password      = shift;
+    my $expected_res  = shift;
+    my $status_string = 'failed';
+
+    $status_string = 'success' if ($expected_res eq 0);
+
+    my $connstr = "user=$role";
+    my $testname =
+    "authentication $status_string for role $role with password $password";
+
+    $ENV{"PGPASSWORD"} = $password;
+
+    if ($expected_res eq 0)
+    {
+        $node->connect_ok($connstr, $testname);
+    }
+    else
+    {
+        # No checks of the error message, only the status code.
+        $node->connect_fails($connstr, $testname);
+    }
+}
+
+note "setting up PostgreSQL instance";
+
+my $delay_milliseconds = 500;
+
+my $node = PostgreSQL::Test::Cluster->new('main');
+$node->init;
+$node->append_conf('postgresql.conf',
+    qq{shared_preload_libraries = 'auth_delay'
+       auth_delay.milliseconds  = '$delay_milliseconds'});
+$node->start;
+
+$node->safe_psql(
+    'postgres',
+    "CREATE ROLE user_role LOGIN PASSWORD 'pass';");
+reset_pg_hba($node, 'password');
+
+note "running tests";
+
+# check enter wrong password
+my $t0 = [gettimeofday];
+test_login($node, 'user_role', "wrongpass", 2);
+my $elapsed = tv_interval($t0, [gettimeofday]);
+ok($elapsed >= $delay_milliseconds / 1000, "auth_delay $elapsed seconds");
+
+# check enter correct password
+my $t0 = [gettimeofday];
+test_login($node, 'user_role', "pass", 0);
+my $elapsed = tv_interval($t0, [gettimeofday]);
+ok($elapsed < $delay_milliseconds / 1000, "auth_delay $elapsed seconds");
+
+done_testing();
+
#6Tom Lane
tgl@sss.pgh.pa.us
In reply to: Dong Wook Lee (#5)
Re: Add TAP test for auth_delay extension

Dong Wook Lee <sh95119@gmail.com> writes:

On 22/06/18 12:07오후, Michael Paquier wrote:

As a whole, I am not sure that this is really worth spending cycles on
when running check-world or similar, and the code of the extension is
trivial.

Even though it is trivial, I think it would be better if there was a test.

I looked at this and concur with Michael's evaluation. A new TAP module
is quite an expensive thing, since it incurs (at least) an initdb run.
In this case, the need to delay a long time to ensure that the test
doesn't fail on slow systems makes that even worse. I don't think
I want to incur these costs every time I run check-world in order to
test a pg_usleep() call, which is what this module boils down to.

If we had some sort of "attic" of tests that aren't run by either
check-world or most buildfarm members, perhaps this would be worth
putting there. But we don't.

One idea could be to install the test but leave the TAP_TESTS line in
the Makefile commented out. Then, somebody who was actively working on
the module could enable the test easily enough (without even modifying
that file: just do "make check TAP_TESTS=1"), but otherwise we don't
pay for it. However, I'm not sure how well that plan will translate
to the upcoming meson build system.

If we don't do it like that, I'd vote for rejecting the patch.

regards, tom lane

#7Michael Paquier
michael@paquier.xyz
In reply to: Tom Lane (#6)
Re: Add TAP test for auth_delay extension

On Sat, Jul 30, 2022 at 05:13:12PM -0400, Tom Lane wrote:

If we don't do it like that, I'd vote for rejecting the patch.

Yep. Done this way.
--
Michael