From 8c39710902e92a196a2233c1d0b9bb35dcdd5c83 Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Date: Mon, 24 Jul 2023 02:49:29 +0000
Subject: [PATCH v3] Add TAP tests to worker_spi module

This commit adds TAP tests to check if worker_spi starts
background workers as expected. sql/worker_spi.sql can't be used
for static bg workers, because the static workers need a database
which is not there when postmaster processes
shared_preload_libraries GUC setting.

The existing tests in sql/worker_spi.sql are kept as-is even though
all of them can be moved to the newly added TAP test file. These
SQL tests along with added TAP tests can help as an example for
module developers.

While here, this commit changes the names of bg workers to
distinguish static and dynamic bg workers.
---
 src/test/modules/worker_spi/Makefile          |  5 +-
 src/test/modules/worker_spi/dynamic.conf      |  1 -
 src/test/modules/worker_spi/meson.build       |  5 ++
 .../modules/worker_spi/t/001_worker_spi.pl    | 49 +++++++++++++++++++
 src/test/modules/worker_spi/worker_spi.c      | 11 +++--
 5 files changed, 64 insertions(+), 7 deletions(-)
 create mode 100644 src/test/modules/worker_spi/t/001_worker_spi.pl

diff --git a/src/test/modules/worker_spi/Makefile b/src/test/modules/worker_spi/Makefile
index cbf9b2e37f..09842dc8cc 100644
--- a/src/test/modules/worker_spi/Makefile
+++ b/src/test/modules/worker_spi/Makefile
@@ -8,12 +8,15 @@ PGFILEDESC = "worker_spi - background worker example"
 
 REGRESS = worker_spi
 
-# enable our module in shared_preload_libraries for dynamic bgworkers
+# Specify a database to connect to for dynamic bgworkers in custom
+# configuration file for SQL tests.
 REGRESS_OPTS = --temp-config $(top_srcdir)/src/test/modules/worker_spi/dynamic.conf
 
 # Disable installcheck to ensure we cover dynamic bgworkers.
 NO_INSTALLCHECK = 1
 
+TAP_TESTS = 1
+
 ifdef USE_PGXS
 PG_CONFIG = pg_config
 PGXS := $(shell $(PG_CONFIG) --pgxs)
diff --git a/src/test/modules/worker_spi/dynamic.conf b/src/test/modules/worker_spi/dynamic.conf
index bfe015f664..78ede3d079 100644
--- a/src/test/modules/worker_spi/dynamic.conf
+++ b/src/test/modules/worker_spi/dynamic.conf
@@ -1,2 +1 @@
-shared_preload_libraries = worker_spi
 worker_spi.database = contrib_regression
diff --git a/src/test/modules/worker_spi/meson.build b/src/test/modules/worker_spi/meson.build
index a8cdfdeb36..29ee875690 100644
--- a/src/test/modules/worker_spi/meson.build
+++ b/src/test/modules/worker_spi/meson.build
@@ -33,4 +33,9 @@ tests += {
     'regress_args': ['--temp-config', files('dynamic.conf')],
     'runningcheck': false,
   },
+  'tap': {
+    'tests': [
+      't/001_worker_spi.pl',
+    ],
+  },
 }
diff --git a/src/test/modules/worker_spi/t/001_worker_spi.pl b/src/test/modules/worker_spi/t/001_worker_spi.pl
new file mode 100644
index 0000000000..485bd64335
--- /dev/null
+++ b/src/test/modules/worker_spi/t/001_worker_spi.pl
@@ -0,0 +1,49 @@
+# Copyright (c) 2023, PostgreSQL Global Development Group
+
+# Test worker_spi module functionality
+use strict;
+use warnings;
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+# Test set-up
+my $node = PostgreSQL::Test::Cluster->new('mynode');
+$node->init;
+$node->start;
+
+$node->safe_psql('postgres', q(CREATE DATABASE mydb;));
+
+$node->append_conf('postgresql.conf', q{
+shared_preload_libraries = 'worker_spi'
+worker_spi.database = 'mydb'
+worker_spi.total_workers = 3
+});
+$node->restart;
+
+$node->safe_psql('mydb', 'CREATE EXTENSION worker_spi;');
+
+# Verify that worker_spi static bg workers have been launched.
+ok( $node->poll_query_until(
+        'mydb',
+        qq[SELECT count(*) = 3 FROM pg_stat_activity
+            WHERE backend_type = 'worker_spi static worker';],
+        't'),
+    'worker_spi static bg workers launched'
+) or die "Timed out while waiting for worker_spi static bg workers to be launched";
+
+# Ask worker_spi to launch dynamic bg workers
+my $worker1_pid = $node->safe_psql('mydb', 'SELECT worker_spi_launch(1);');
+my $worker2_pid = $node->safe_psql('mydb', 'SELECT worker_spi_launch(2);');
+
+# Verify that worker_spi dynamic bg workers have been launched.
+ok( $node->poll_query_until(
+        'mydb',
+        qq[SELECT count(*) = 2 FROM pg_stat_activity
+            WHERE backend_type = 'worker_spi dynamic worker' AND
+            pid IN ($worker1_pid, $worker2_pid);],
+        't'),
+    'worker_spi dynamic bg workers launched'
+) or die "Timed out while waiting for worker_spi dynamic bg workers to be launched";
+
+done_testing();
diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c
index ada0fb8ac7..461f272e77 100644
--- a/src/test/modules/worker_spi/worker_spi.c
+++ b/src/test/modules/worker_spi/worker_spi.c
@@ -5,7 +5,8 @@
  *		patterns: establishing a database connection; starting and committing
  *		transactions; using GUC variables, and heeding SIGHUP to reread
  *		the configuration file; reporting to pg_stat_activity; using the
- *		process latch to sleep and exit in case of postmaster death.
+ *		process latch to sleep and exit in case of postmaster death; writing
+ *		regression tests, both core (sql) and extended (TAP) tests.
  *
  * This code connects to a database, creates a schema and table, and summarizes
  * the numbers contained therein.  To see it working, insert an initial value
@@ -343,8 +344,8 @@ _PG_init(void)
 	 */
 	for (int i = 1; i <= worker_spi_total_workers; i++)
 	{
-		snprintf(worker.bgw_name, BGW_MAXLEN, "worker_spi worker %d", i);
-		snprintf(worker.bgw_type, BGW_MAXLEN, "worker_spi");
+		snprintf(worker.bgw_name, BGW_MAXLEN, "worker_spi static worker %d", i);
+		snprintf(worker.bgw_type, BGW_MAXLEN, "worker_spi static worker");
 		worker.bgw_main_arg = Int32GetDatum(i);
 
 		RegisterBackgroundWorker(&worker);
@@ -370,8 +371,8 @@ worker_spi_launch(PG_FUNCTION_ARGS)
 	worker.bgw_restart_time = BGW_NEVER_RESTART;
 	sprintf(worker.bgw_library_name, "worker_spi");
 	sprintf(worker.bgw_function_name, "worker_spi_main");
-	snprintf(worker.bgw_name, BGW_MAXLEN, "worker_spi worker %d", i);
-	snprintf(worker.bgw_type, BGW_MAXLEN, "worker_spi");
+	snprintf(worker.bgw_name, BGW_MAXLEN, "worker_spi dynamic worker %d", i);
+	snprintf(worker.bgw_type, BGW_MAXLEN, "worker_spi dynamic worker");
 	worker.bgw_main_arg = Int32GetDatum(i);
 	/* set bgw_notify_pid so that we can use WaitForBackgroundWorkerStartup */
 	worker.bgw_notify_pid = MyProcPid;
-- 
2.34.1

