Fix new test for CATCACHE_FORCE_RELEASE builds
authorÁlvaro Herrera <alvherre@kurilemu.de>
Thu, 27 Nov 2025 12:10:56 +0000 (13:10 +0100)
committerÁlvaro Herrera <alvherre@kurilemu.de>
Thu, 27 Nov 2025 12:10:56 +0000 (13:10 +0100)
Two of the isolation tests introduce by commit bc32a12e0db2 had a
problem under CATCACHE_FORCE_RELEASE, as evidenced by buildfarm member
prion.  An injection point is hit ahead of what the test spec expects,
so a session goes to sleep and there's no one there to wait it up.  Fix
in the simplest possible way, which is to conditionally wake the process
up if it's waiting.  An alternative output file is necessary to cover
both cases.

This suggests a couple of possible improvements to the injection points
infrastructure: a conditional wakeup (doing nothing if no one is
sleeping, as opposed to throwing an error), as well as a way to attach
to a point in "deactivated" mode, activated later.

Author: Álvaro Herrera <alvherre@kurilemu.de>
Reviewed-by: Mihail Nikalayeu <mihailnikalayeu@gmail.com>
Discussion: https://postgr.es/m/202511261817.fyixgtt3hqdr@alvherre.pgsql

src/test/modules/injection_points/expected/index-concurrently-upsert-predicate.out
src/test/modules/injection_points/expected/index-concurrently-upsert-predicate_1.out [new file with mode: 0644]
src/test/modules/injection_points/expected/index-concurrently-upsert.out
src/test/modules/injection_points/expected/index-concurrently-upsert_1.out [new file with mode: 0644]
src/test/modules/injection_points/specs/index-concurrently-upsert-predicate.spec
src/test/modules/injection_points/specs/index-concurrently-upsert.spec

index 3d9512c8fc76cf0ae471fbd99c598af6d942292b..5a57cd5fa4007747537867bea741eb94c2c787e3 100644 (file)
@@ -1,6 +1,6 @@
 Parsed test spec with 5 sessions
 
-starting permutation: s5_noop s3_start_create_index s1_start_upsert s4_wakeup_define_index_before_set_valid s2_start_upsert s5_wakeup_s1_from_invalidate_catalog_snapshot s4_wakeup_s2 s4_wakeup_s1
+starting permutation: s1_attach_invalidate_catalog_snapshot s4_wakeup_s1_setup s5_noop s3_start_create_index s1_start_upsert s4_wakeup_define_index_before_set_valid s2_start_upsert s5_wakeup_s1_from_invalidate_catalog_snapshot s4_wakeup_s2 s4_wakeup_s1
 injection_points_attach
 -----------------------
                        
@@ -16,6 +16,27 @@ injection_points_attach
                        
 (1 row)
 
+step s1_attach_invalidate_catalog_snapshot: 
+   SELECT injection_points_attach('invalidate-catalog-snapshot-end', 'wait');
+
+injection_points_attach
+-----------------------
+                       
+(1 row)
+
+step s4_wakeup_s1_setup: 
+   SELECT CASE WHEN
+           (SELECT pid FROM pg_stat_activity
+                 WHERE wait_event_type = 'InjectionPoint' AND
+                 wait_event = 'invalidate-catalog-snapshot-end') IS NOT NULL
+           THEN injection_points_wakeup('invalidate-catalog-snapshot-end')
+       END;
+
+case
+----
+    
+(1 row)
+
 step s5_noop: 
  <waiting ...>
 step s3_start_create_index: 
diff --git a/src/test/modules/injection_points/expected/index-concurrently-upsert-predicate_1.out b/src/test/modules/injection_points/expected/index-concurrently-upsert-predicate_1.out
new file mode 100644 (file)
index 0000000..d453dd6
--- /dev/null
@@ -0,0 +1,116 @@
+Parsed test spec with 5 sessions
+
+starting permutation: s1_attach_invalidate_catalog_snapshot s4_wakeup_s1_setup s5_noop s3_start_create_index s1_start_upsert s4_wakeup_define_index_before_set_valid s2_start_upsert s5_wakeup_s1_from_invalidate_catalog_snapshot s4_wakeup_s2 s4_wakeup_s1
+s1: NOTICE:  notice triggered for injection point pre-invalidate-catalog-snapshot-end
+injection_points_attach
+-----------------------
+                       
+(1 row)
+
+injection_points_attach
+-----------------------
+                       
+(1 row)
+
+injection_points_attach
+-----------------------
+                       
+(1 row)
+
+s1: NOTICE:  notice triggered for injection point pre-invalidate-catalog-snapshot-end
+s1: NOTICE:  notice triggered for injection point pre-invalidate-catalog-snapshot-end
+step s1_attach_invalidate_catalog_snapshot: 
+   SELECT injection_points_attach('invalidate-catalog-snapshot-end', 'wait');
+ <waiting ...>
+step s4_wakeup_s1_setup: 
+   SELECT CASE WHEN
+           (SELECT pid FROM pg_stat_activity
+                 WHERE wait_event_type = 'InjectionPoint' AND
+                 wait_event = 'invalidate-catalog-snapshot-end') IS NOT NULL
+           THEN injection_points_wakeup('invalidate-catalog-snapshot-end')
+       END;
+
+case
+----
+    
+(1 row)
+
+step s1_attach_invalidate_catalog_snapshot: <... completed>
+injection_points_attach
+-----------------------
+                       
+(1 row)
+
+step s5_noop: 
+ <waiting ...>
+step s3_start_create_index: 
+   CREATE UNIQUE INDEX CONCURRENTLY tbl_pkey_special_duplicate ON test.tbl(abs(i)) WHERE i < 10000;
+ <waiting ...>
+s1: NOTICE:  notice triggered for injection point pre-invalidate-catalog-snapshot-end
+step s1_start_upsert: 
+   INSERT INTO test.tbl VALUES(13,now()) ON CONFLICT (abs(i)) WHERE i < 100 DO UPDATE SET updated_at = now();
+ <waiting ...>
+step s5_noop: <... completed>
+step s4_wakeup_define_index_before_set_valid: 
+   SELECT injection_points_detach('define-index-before-set-valid');
+   SELECT injection_points_wakeup('define-index-before-set-valid');
+
+injection_points_detach
+-----------------------
+                       
+(1 row)
+
+injection_points_wakeup
+-----------------------
+                       
+(1 row)
+
+step s2_start_upsert: 
+   INSERT INTO test.tbl VALUES(13,now()) ON CONFLICT (abs(i)) WHERE i < 100 DO UPDATE SET updated_at = now();
+ <waiting ...>
+step s5_wakeup_s1_from_invalidate_catalog_snapshot: 
+   SELECT injection_points_detach('invalidate-catalog-snapshot-end');
+   SELECT injection_points_wakeup('invalidate-catalog-snapshot-end');
+
+injection_points_detach
+-----------------------
+                       
+(1 row)
+
+injection_points_wakeup
+-----------------------
+                       
+(1 row)
+
+step s4_wakeup_s2: 
+   SELECT injection_points_detach('exec-insert-before-insert-speculative');
+   SELECT injection_points_wakeup('exec-insert-before-insert-speculative');
+
+injection_points_detach
+-----------------------
+                       
+(1 row)
+
+injection_points_wakeup
+-----------------------
+                       
+(1 row)
+
+step s4_wakeup_s1: 
+   SELECT injection_points_detach('check-exclusion-or-unique-constraint-no-conflict');
+   SELECT injection_points_wakeup('check-exclusion-or-unique-constraint-no-conflict');
+
+injection_points_detach
+-----------------------
+                       
+(1 row)
+
+injection_points_wakeup
+-----------------------
+                       
+(1 row)
+
+s1: NOTICE:  notice triggered for injection point pre-invalidate-catalog-snapshot-end
+step s1_start_upsert: <... completed>
+step s2_start_upsert: <... completed>
+step s3_start_create_index: <... completed>
index a9e8bb5d00ed3711ccfce8988c04854637266ea3..97386a35bed0a752cb2483c4d59e1314088aa24a 100644 (file)
@@ -1,6 +1,6 @@
 Parsed test spec with 5 sessions
 
-starting permutation: s5_noop s3_start_create_index s1_start_upsert s4_wakeup_define_index_before_set_valid s2_start_upsert s5_wakeup_s1_from_invalidate_catalog_snapshot s4_wakeup_s2 s4_wakeup_s1
+starting permutation: s1_attach_invalidate_catalog_snapshot s4_wakeup_s1_setup s5_noop s3_start_create_index s1_start_upsert s4_wakeup_define_index_before_set_valid s2_start_upsert s5_wakeup_s1_from_invalidate_catalog_snapshot s4_wakeup_s2 s4_wakeup_s1
 injection_points_attach
 -----------------------
                        
@@ -16,6 +16,27 @@ injection_points_attach
                        
 (1 row)
 
+step s1_attach_invalidate_catalog_snapshot: 
+   SELECT injection_points_attach('invalidate-catalog-snapshot-end', 'wait');
+
+injection_points_attach
+-----------------------
+                       
+(1 row)
+
+step s4_wakeup_s1_setup: 
+   SELECT CASE WHEN
+           (SELECT pid FROM pg_stat_activity
+                 WHERE wait_event_type = 'InjectionPoint' AND
+                 wait_event = 'invalidate-catalog-snapshot-end') IS NOT NULL
+           THEN injection_points_wakeup('invalidate-catalog-snapshot-end')
+       END;
+
+case
+----
+    
+(1 row)
+
 step s5_noop: 
  <waiting ...>
 step s3_start_create_index: 
diff --git a/src/test/modules/injection_points/expected/index-concurrently-upsert_1.out b/src/test/modules/injection_points/expected/index-concurrently-upsert_1.out
new file mode 100644 (file)
index 0000000..4bd51b2
--- /dev/null
@@ -0,0 +1,116 @@
+Parsed test spec with 5 sessions
+
+starting permutation: s1_attach_invalidate_catalog_snapshot s4_wakeup_s1_setup s5_noop s3_start_create_index s1_start_upsert s4_wakeup_define_index_before_set_valid s2_start_upsert s5_wakeup_s1_from_invalidate_catalog_snapshot s4_wakeup_s2 s4_wakeup_s1
+s1: NOTICE:  notice triggered for injection point pre-invalidate-catalog-snapshot-end
+injection_points_attach
+-----------------------
+                       
+(1 row)
+
+injection_points_attach
+-----------------------
+                       
+(1 row)
+
+injection_points_attach
+-----------------------
+                       
+(1 row)
+
+s1: NOTICE:  notice triggered for injection point pre-invalidate-catalog-snapshot-end
+s1: NOTICE:  notice triggered for injection point pre-invalidate-catalog-snapshot-end
+step s1_attach_invalidate_catalog_snapshot: 
+   SELECT injection_points_attach('invalidate-catalog-snapshot-end', 'wait');
+ <waiting ...>
+step s4_wakeup_s1_setup: 
+   SELECT CASE WHEN
+           (SELECT pid FROM pg_stat_activity
+                 WHERE wait_event_type = 'InjectionPoint' AND
+                 wait_event = 'invalidate-catalog-snapshot-end') IS NOT NULL
+           THEN injection_points_wakeup('invalidate-catalog-snapshot-end')
+       END;
+
+case
+----
+    
+(1 row)
+
+step s1_attach_invalidate_catalog_snapshot: <... completed>
+injection_points_attach
+-----------------------
+                       
+(1 row)
+
+step s5_noop: 
+ <waiting ...>
+step s3_start_create_index: 
+   CREATE UNIQUE INDEX CONCURRENTLY tbl_pkey_duplicate ON test.tbl(i);
+ <waiting ...>
+s1: NOTICE:  notice triggered for injection point pre-invalidate-catalog-snapshot-end
+step s1_start_upsert: 
+    INSERT INTO test.tbl VALUES (13,now()) ON CONFLICT (i) DO UPDATE SET updated_at = now();
+ <waiting ...>
+step s5_noop: <... completed>
+step s4_wakeup_define_index_before_set_valid: 
+   SELECT injection_points_detach('define-index-before-set-valid');
+   SELECT injection_points_wakeup('define-index-before-set-valid');
+
+injection_points_detach
+-----------------------
+                       
+(1 row)
+
+injection_points_wakeup
+-----------------------
+                       
+(1 row)
+
+step s2_start_upsert: 
+   INSERT INTO test.tbl VALUES (13,now()) ON CONFLICT (i) DO UPDATE SET updated_at = now();
+ <waiting ...>
+step s5_wakeup_s1_from_invalidate_catalog_snapshot: 
+   SELECT injection_points_detach('invalidate-catalog-snapshot-end');
+   SELECT injection_points_wakeup('invalidate-catalog-snapshot-end');
+
+injection_points_detach
+-----------------------
+                       
+(1 row)
+
+injection_points_wakeup
+-----------------------
+                       
+(1 row)
+
+step s4_wakeup_s2: 
+   SELECT injection_points_detach('exec-insert-before-insert-speculative');
+   SELECT injection_points_wakeup('exec-insert-before-insert-speculative');
+
+injection_points_detach
+-----------------------
+                       
+(1 row)
+
+injection_points_wakeup
+-----------------------
+                       
+(1 row)
+
+step s4_wakeup_s1: 
+   SELECT injection_points_detach('check-exclusion-or-unique-constraint-no-conflict');
+   SELECT injection_points_wakeup('check-exclusion-or-unique-constraint-no-conflict');
+
+injection_points_detach
+-----------------------
+                       
+(1 row)
+
+injection_points_wakeup
+-----------------------
+                       
+(1 row)
+
+s1: NOTICE:  notice triggered for injection point pre-invalidate-catalog-snapshot-end
+step s1_start_upsert: <... completed>
+step s2_start_upsert: <... completed>
+step s3_start_create_index: <... completed>
index 725f6f222951fee9ccbfbb27ff1678a333463b05..1cbcaa6963fba0322dc1fc47207501ef279c4bab 100644 (file)
@@ -28,6 +28,9 @@ setup
    SELECT injection_points_set_local();
    SELECT injection_points_attach('check-exclusion-or-unique-constraint-no-conflict', 'wait');
    SELECT injection_points_attach('pre-invalidate-catalog-snapshot-end', 'notice');
+}
+step s1_attach_invalidate_catalog_snapshot
+{
    SELECT injection_points_attach('invalidate-catalog-snapshot-end', 'wait');
 }
 step s1_start_upsert
@@ -58,6 +61,19 @@ step s3_start_create_index
 }
 
 session s4
+# Step s1_attach_invalidate_catalog_snapshot sleeps or not depending on
+# build conditions (CATCACHE_FORCE_RELEASE). Here we send a wakeup signal if
+# it's sleeping or do nothing otherwise, and print a null value in either
+# case.
+step s4_wakeup_s1_setup
+{
+   SELECT CASE WHEN
+           (SELECT pid FROM pg_stat_activity
+                 WHERE wait_event_type = 'InjectionPoint' AND
+                 wait_event = 'invalidate-catalog-snapshot-end') IS NOT NULL
+           THEN injection_points_wakeup('invalidate-catalog-snapshot-end')
+       END;
+}
 step s4_wakeup_s1
 {
    SELECT injection_points_detach('check-exclusion-or-unique-constraint-no-conflict');
@@ -85,6 +101,8 @@ step s5_wakeup_s1_from_invalidate_catalog_snapshot
 }
 
 permutation
+   s1_attach_invalidate_catalog_snapshot
+   s4_wakeup_s1_setup
    s5_noop(s1_start_upsert notices 1)
    s3_start_create_index(s1_start_upsert, s2_start_upsert)
    s1_start_upsert
index 4487834aa8e06fa0b50da8e39d651bbb1320f236..2a6d888dcea72d19e435eb0491911875cd4b2776 100644 (file)
@@ -27,6 +27,9 @@ setup
    SELECT injection_points_set_local();
    SELECT injection_points_attach('check-exclusion-or-unique-constraint-no-conflict', 'wait');
    SELECT injection_points_attach('pre-invalidate-catalog-snapshot-end', 'notice');
+}
+step s1_attach_invalidate_catalog_snapshot
+{
    SELECT injection_points_attach('invalidate-catalog-snapshot-end', 'wait');
 }
 step s1_start_upsert
@@ -57,6 +60,19 @@ step s3_start_create_index
 }
 
 session s4
+# Step s1_attach_invalidate_catalog_snapshot sleeps or not depending on
+# build conditions (CATCACHE_FORCE_RELEASE). Here we send a wakeup signal if
+# it's sleeping or do nothing otherwise, and print a null value in either
+# case.
+step s4_wakeup_s1_setup
+{
+   SELECT CASE WHEN
+           (SELECT pid FROM pg_stat_activity
+                 WHERE wait_event_type = 'InjectionPoint' AND
+                 wait_event = 'invalidate-catalog-snapshot-end') IS NOT NULL
+           THEN injection_points_wakeup('invalidate-catalog-snapshot-end')
+       END;
+}
 step s4_wakeup_s1
 {
    SELECT injection_points_detach('check-exclusion-or-unique-constraint-no-conflict');
@@ -84,6 +100,8 @@ step s5_wakeup_s1_from_invalidate_catalog_snapshot
 }
 
 permutation
+   s1_attach_invalidate_catalog_snapshot
+   s4_wakeup_s1_setup
    s5_noop(s1_start_upsert notices 1)
    s3_start_create_index(s1_start_upsert, s2_start_upsert)
    s1_start_upsert