From 360e45485475100c12f27eb617e0ff802cb2bf40 Mon Sep 17 00:00:00 2001
From: Andrey Borodin <amborodin@acm.org>
Date: Sun, 30 Nov 2025 16:34:41 +0500
Subject: [PATCH v14 4/4] Improve multixact wraparound test

1. Replace dd and rm
2. Sprincle comments
3. Check that all multis are readable after wraparound
---
 .../test_slru/t/002_multixact_wraparound.pl   | 54 +++++++++++++++----
 1 file changed, 43 insertions(+), 11 deletions(-)

diff --git a/src/test/modules/test_slru/t/002_multixact_wraparound.pl b/src/test/modules/test_slru/t/002_multixact_wraparound.pl
index efaf902e5e3..c05d6280bfb 100644
--- a/src/test/modules/test_slru/t/002_multixact_wraparound.pl
+++ b/src/test/modules/test_slru/t/002_multixact_wraparound.pl
@@ -10,7 +10,7 @@ use PostgreSQL::Test::Utils;
 
 use Test::More;
 
-my ($node, $result);
+my $node;
 
 $node = PostgreSQL::Test::Cluster->new('mike');
 $node->init;
@@ -26,23 +26,55 @@ command_ok(
 		$node_pgdata
 	],
 	"set the cluster's next multitransaction to 0xFFFFFFF0");
-command_ok(
-	[
-		'dd', 'if=/dev/zero', "of=$node_pgdata/pg_multixact/offsets/FFFF",
-		'bs=4', 'count=65536'
-	],
-	"init SLRU file");
 
-command_ok([ 'rm', "$node_pgdata/pg_multixact/offsets/0000", ],
-	"drop old SLRU file");
+# Initialize SLRU file with zeros (65536 entries * 4 bytes = 262144 bytes)
+my $slru_file = "$node_pgdata/pg_multixact/offsets/FFFF";
+open my $fh, ">", $slru_file
+	or die "could not open \"$slru_file\": $!";
+binmode $fh;
+# Write 65536 entries of 4 bytes each (all zeros)
+syswrite($fh, "\0" x 262144) == 262144
+	or die "could not write to \"$slru_file\": $!";
+close $fh;
+
+# Remove old SLRU file if it exists
+if (-f "$node_pgdata/pg_multixact/offsets/0000")
+{
+	unlink("$node_pgdata/pg_multixact/offsets/0000")
+		or die "could not unlink \"$node_pgdata/pg_multixact/offsets/0000\": $!";
+}
 
 $node->start;
 $node->safe_psql('postgres', q(CREATE EXTENSION test_slru));
 
-# Consume multixids to wrap around
+# Consume multixids to wrap around. We start at 0xFFFFFFF0, so after
+# creating 32 multixacts we should have wrapped around past FirstMultiXactId.
+# Capture all multixact IDs to verify they're all readable after wraparound.
+my @multixact_ids;
 foreach my $i (1 .. 32)
 {
-	$node->safe_psql('postgres', q{SELECT test_create_multixact();});
+	my $multi = $node->safe_psql('postgres', q{SELECT test_create_multixact();});
+	push @multixact_ids, $multi;
+}
+
+# Verify that wraparound occurred (last_multi should be less than first_multi
+# or very close to FirstMultiXactId)
+my $first_multi = $multixact_ids[0];
+my $last_multi = $multixact_ids[-1];
+ok($last_multi < $first_multi || $last_multi < 0x10000,
+	"multixact wraparound occurred (first: $first_multi, last: $last_multi)");
+
+# Verify that all multixacts created during wraparound are still readable
+foreach my $i (0 .. $#multixact_ids)
+{
+	my $multi = $multixact_ids[$i];
+	my $timed_out = 0;
+	$node->safe_psql(
+		'postgres',
+		qq{SELECT test_read_multixact('$multi'::xid);},
+		timeout => $PostgreSQL::Test::Utils::timeout_default,
+		timed_out => \$timed_out);
+	ok($timed_out == 0, "multixact $i (ID: $multi) is readable after wraparound");
 }
 
 $node->stop;
-- 
2.51.2

