From ee0f1539ddb8d68cc80af229fa0afb5d58e55e92 Mon Sep 17 00:00:00 2001 From: Hayato Kuroda Date: Wed, 17 Sep 2025 15:20:45 +0900 Subject: [PATCH v8 2/3] add test --- contrib/test_decoding/Makefile | 2 +- .../test_decoding/expected/repl_origin.out | 79 +++++++++++++++++++ contrib/test_decoding/meson.build | 1 + contrib/test_decoding/specs/repl_origin.spec | 56 +++++++++++++ 4 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 contrib/test_decoding/expected/repl_origin.out create mode 100644 contrib/test_decoding/specs/repl_origin.spec diff --git a/contrib/test_decoding/Makefile b/contrib/test_decoding/Makefile index 02e961f4d31..8aa80054944 100644 --- a/contrib/test_decoding/Makefile +++ b/contrib/test_decoding/Makefile @@ -9,7 +9,7 @@ REGRESS = ddl xact rewrite toast permissions decoding_in_xact \ ISOLATION = mxact delayed_startup ondisk_startup concurrent_ddl_dml \ oldest_xmin snapshot_transfer subxact_without_top concurrent_stream \ twophase_snapshot slot_creation_error catalog_change_snapshot \ - skip_snapshot_restore invalidation_distribution + skip_snapshot_restore invalidation_distribution repl_origin REGRESS_OPTS = --temp-config $(top_srcdir)/contrib/test_decoding/logical.conf ISOLATION_OPTS = --temp-config $(top_srcdir)/contrib/test_decoding/logical.conf diff --git a/contrib/test_decoding/expected/repl_origin.out b/contrib/test_decoding/expected/repl_origin.out new file mode 100644 index 00000000000..9ef80217b9d --- /dev/null +++ b/contrib/test_decoding/expected/repl_origin.out @@ -0,0 +1,79 @@ +Parsed test spec with 2 sessions + +starting permutation: s0_setup s0_is_setup s1_setup s1_is_setup s0_add_message s0_store_lsn s1_add_message s1_store_lsn s0_compare s0_reset s1_reset +step s0_setup: SELECT pg_replication_origin_session_setup('origin'); +pg_replication_origin_session_setup +----------------------------------- + +(1 row) + +step s0_is_setup: SELECT pg_replication_origin_session_is_setup(); +pg_replication_origin_session_is_setup +-------------------------------------- +t +(1 row) + +step s1_setup: + SELECT pg_replication_origin_session_setup('origin', pid) + FROM pg_stat_activity + WHERE application_name = 'isolation/repl_origin/s0'; + +pg_replication_origin_session_setup +----------------------------------- + +(1 row) + +step s1_is_setup: SELECT pg_replication_origin_session_is_setup(); +pg_replication_origin_session_is_setup +-------------------------------------- +t +(1 row) + +step s0_add_message: + SELECT 1 + FROM pg_logical_emit_message(true, 'prefix', 'message on s0'); + +?column? +-------- + 1 +(1 row) + +step s0_store_lsn: + INSERT INTO local_lsn_store + SELECT 0, local_lsn FROM pg_replication_origin_status; + +step s1_add_message: + SELECT 1 + FROM pg_logical_emit_message(true, 'prefix', 'message on s1'); + +?column? +-------- + 1 +(1 row) + +step s1_store_lsn: + INSERT INTO local_lsn_store + SELECT 1, local_lsn FROM pg_replication_origin_status; + +step s0_compare: + SELECT s0.lsn < s1.lsn + FROM local_lsn_store as s0, local_lsn_store as s1 + WHERE s0.session = 0 AND s1.session = 1; + +?column? +-------- +t +(1 row) + +step s0_reset: SELECT pg_replication_origin_session_reset(); +pg_replication_origin_session_reset +----------------------------------- + +(1 row) + +step s1_reset: SELECT pg_replication_origin_session_reset(); +pg_replication_origin_session_reset +----------------------------------- + +(1 row) + diff --git a/contrib/test_decoding/meson.build b/contrib/test_decoding/meson.build index 25f6b8a9082..6d687eeb2d7 100644 --- a/contrib/test_decoding/meson.build +++ b/contrib/test_decoding/meson.build @@ -64,6 +64,7 @@ tests += { 'slot_creation_error', 'skip_snapshot_restore', 'invalidation_distribution', + 'repl_origin', ], 'regress_args': [ '--temp-config', files('logical.conf'), diff --git a/contrib/test_decoding/specs/repl_origin.spec b/contrib/test_decoding/specs/repl_origin.spec new file mode 100644 index 00000000000..266ce553444 --- /dev/null +++ b/contrib/test_decoding/specs/repl_origin.spec @@ -0,0 +1,56 @@ +# Test multi-session replication origin manipulations; ensure local_lsn can be +# updated by all attached sessions. + +setup +{ + SELECT pg_replication_origin_create('origin'); + CREATE UNLOGGED TABLE local_lsn_store (session int, lsn pg_lsn); +} + +teardown +{ + SELECT pg_replication_origin_drop('origin'); + DROP TABLE local_lsn_store; +} + +session "s0" +setup { SET synchronous_commit = on; } +step "s0_setup" { SELECT pg_replication_origin_session_setup('origin'); } +step "s0_is_setup" { SELECT pg_replication_origin_session_is_setup(); } +step "s0_add_message" { + SELECT 1 + FROM pg_logical_emit_message(true, 'prefix', 'message on s0'); +} +step "s0_store_lsn" { + INSERT INTO local_lsn_store + SELECT 0, local_lsn FROM pg_replication_origin_status; +} +step "s0_compare" { + SELECT s0.lsn < s1.lsn + FROM local_lsn_store as s0, local_lsn_store as s1 + WHERE s0.session = 0 AND s1.session = 1; +} +step "s0_reset" { SELECT pg_replication_origin_session_reset(); } + +session "s1" +setup { SET synchronous_commit = on; } +step "s1_setup" { + SELECT pg_replication_origin_session_setup('origin', pid) + FROM pg_stat_activity + WHERE application_name = 'isolation/repl_origin/s0'; +} +step "s1_is_setup" { SELECT pg_replication_origin_session_is_setup(); } +step "s1_add_message" { + SELECT 1 + FROM pg_logical_emit_message(true, 'prefix', 'message on s1'); +} +step "s1_store_lsn" { + INSERT INTO local_lsn_store + SELECT 1, local_lsn FROM pg_replication_origin_status; +} +step "s1_reset" { SELECT pg_replication_origin_session_reset(); } + +# Firstly s0 attaches to a origin and s1 attaches to the same. Both sessions +# commits a transaction and store the local_lsn of the replication origin. +# Compare LSNs and expect latter transaction (done by s1) has larger local_lsn. +permutation "s0_setup" "s0_is_setup" "s1_setup" "s1_is_setup" "s0_add_message" "s0_store_lsn" "s1_add_message" "s1_store_lsn" "s0_compare" "s0_reset" "s1_reset" -- 2.47.3