From d3df4189fcb6653f81efa55db77982ade5752774 Mon Sep 17 00:00:00 2001
From: ChangAo Chen <cca5507@qq.com>
Date: Thu, 25 Jun 2026 13:47:41 +0800
Subject: [PATCH v4 2/2] Add test case for vacuum with a concurrent drop.

---
 src/backend/commands/vacuum.c                 |  2 +
 src/test/modules/injection_points/Makefile    |  1 +
 .../expected/vacuum_concurrent_drop.out       | 38 +++++++++++++
 src/test/modules/injection_points/meson.build |  1 +
 .../specs/vacuum_concurrent_drop.spec         | 55 +++++++++++++++++++
 5 files changed, 97 insertions(+)
 create mode 100644 src/test/modules/injection_points/expected/vacuum_concurrent_drop.out
 create mode 100644 src/test/modules/injection_points/specs/vacuum_concurrent_drop.spec

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 79d09b9d70f..12d4ec11167 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -1066,6 +1066,8 @@ get_all_vacuum_rels(MemoryContext vac_context, int options)
 
 	scan = table_beginscan_catalog(pgclass, 0, NULL);
 
+	INJECTION_POINT("vacuum-constructing-vacuumable-rels", NULL);
+
 	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
diff --git a/src/test/modules/injection_points/Makefile b/src/test/modules/injection_points/Makefile
index c01d2fb095c..2fae0e01f15 100644
--- a/src/test/modules/injection_points/Makefile
+++ b/src/test/modules/injection_points/Makefile
@@ -18,6 +18,7 @@ ISOLATION = basic \
 	    repack_temporal \
 	    repack_temporal_multirange \
 	    repack_toast \
+		vacuum_concurrent_drop \
 	    syscache-update-pruned \
 	    heap_lock_update
 
diff --git a/src/test/modules/injection_points/expected/vacuum_concurrent_drop.out b/src/test/modules/injection_points/expected/vacuum_concurrent_drop.out
new file mode 100644
index 00000000000..40172f42f1a
--- /dev/null
+++ b/src/test/modules/injection_points/expected/vacuum_concurrent_drop.out
@@ -0,0 +1,38 @@
+Parsed test spec with 2 sessions
+
+starting permutation: create1 setrole1 vacuum1 drop2 wakeup2 resetrole1
+injection_points_attach
+-----------------------
+                       
+(1 row)
+
+step create1: 
+    CREATE TABLE foo (id int);
+
+step setrole1: 
+    SET ROLE regress_vacuum;
+
+step vacuum1: 
+    VACUUM;
+ <waiting ...>
+step drop2: 
+    DROP TABLE foo;
+
+step wakeup2: 
+    SELECT injection_points_wakeup('vacuum-constructing-vacuumable-rels');
+
+injection_points_wakeup
+-----------------------
+                       
+(1 row)
+
+s1: WARNING:  skipping vacuum of "foo" --- relation no longer exists
+step vacuum1: <... completed>
+step resetrole1: 
+    RESET ROLE;
+
+injection_points_detach
+-----------------------
+                       
+(1 row)
+
diff --git a/src/test/modules/injection_points/meson.build b/src/test/modules/injection_points/meson.build
index 59dba1cb023..dbb1edf0bfe 100644
--- a/src/test/modules/injection_points/meson.build
+++ b/src/test/modules/injection_points/meson.build
@@ -49,6 +49,7 @@ tests += {
       'repack_temporal',
       'repack_temporal_multirange',
       'repack_toast',
+      'vacuum_concurrent_drop',
       'syscache-update-pruned',
       'heap_lock_update',
     ],
diff --git a/src/test/modules/injection_points/specs/vacuum_concurrent_drop.spec b/src/test/modules/injection_points/specs/vacuum_concurrent_drop.spec
new file mode 100644
index 00000000000..60c7d14d8c7
--- /dev/null
+++ b/src/test/modules/injection_points/specs/vacuum_concurrent_drop.spec
@@ -0,0 +1,55 @@
+# Test vacuum with a concurrent drop when constructing the list
+# of vacuumable relations. The vacuum should not error out when
+# a concurrent drop happens.
+
+setup
+{
+	CREATE EXTENSION injection_points;
+    CREATE ROLE regress_vacuum IN ROLE pg_maintain;
+}
+teardown
+{
+    DROP ROLE regress_vacuum;
+	DROP EXTENSION injection_points;
+}
+
+session s1
+setup
+{
+	SELECT injection_points_set_local();
+	SELECT injection_points_attach('vacuum-constructing-vacuumable-rels', 'wait');
+}
+step create1
+{
+    CREATE TABLE foo (id int);
+}
+# Make sure that current user is not the owner of current database so
+# that we will check the MAINTAIN privilege on 'foo'.
+step setrole1
+{
+    SET ROLE regress_vacuum;
+}
+step vacuum1
+{
+    VACUUM;
+}
+step resetrole1
+{
+    RESET ROLE;
+}
+teardown
+{
+	SELECT injection_points_detach('vacuum-constructing-vacuumable-rels');
+}
+
+session s2
+step drop2
+{
+    DROP TABLE foo;
+}
+step wakeup2
+{
+    SELECT injection_points_wakeup('vacuum-constructing-vacuumable-rels');
+}
+
+permutation create1 setrole1 vacuum1 drop2 wakeup2 resetrole1
-- 
2.34.1

