From daa8126c90e7821f4f5de08926fb25d4a2cd98d3 Mon Sep 17 00:00:00 2001
From: Amul Sul <amul.sul@enterprisedb.com>
Date: Fri, 27 Aug 2021 08:18:40 -0400
Subject: [PATCH v32 8/9] Test: Few tap tests for wal prohibited system

Does following testing:

1. Verify wal write and checkpoint lsn after restart of wal prohibited
   system doesn't change along with wal prohibited state.
2. Standby server cannot be in wal prohibited, standby.signal or
   recovery.signal take out system from wal prohibited state.
3. At restart wal prohibited system shutdown and on start recovery end
   checkpoint is skipped, verify implicit checkpoint perform when
   system state changes to wal permitted.
---
 src/test/recovery/t/026_pg_prohibit_wal.pl | 134 +++++++++++++++++++++
 1 file changed, 134 insertions(+)
 create mode 100644 src/test/recovery/t/026_pg_prohibit_wal.pl

diff --git a/src/test/recovery/t/026_pg_prohibit_wal.pl b/src/test/recovery/t/026_pg_prohibit_wal.pl
new file mode 100644
index 00000000000..6abd04935fc
--- /dev/null
+++ b/src/test/recovery/t/026_pg_prohibit_wal.pl
@@ -0,0 +1,134 @@
+
+# Copyright (c) 2021, PostgreSQL Global Development Group
+
+# Test for pg_prohibit_wal().
+use strict;
+use warnings;
+use PostgresNode;
+use TestLib;
+use Test::More tests => 12;
+
+# Query to read wal_prohibited GUC
+my $show_wal_prohibited_query = "SELECT current_setting('wal_prohibited')";
+
+# Initialize primary node
+my $node_primary = PostgresNode->new('primary');
+my $port = $node_primary->port();
+$node_primary->init(
+	has_archiving    => 1,
+	allows_streaming => 1);
+$node_primary->start;
+
+# Create table and insert some data
+$node_primary->safe_psql('postgres', 'CREATE TABLE tab(i int)');
+$node_primary->safe_psql('postgres',
+	'INSERT INTO tab VALUES(generate_series(1,5))');
+
+# Change primary to WAL prohibited
+$node_primary->safe_psql('postgres', 'SELECT pg_prohibit_wal(true)');
+is($node_primary->safe_psql('postgres', $show_wal_prohibited_query),
+	'on', 'primary server is now wal prohibited');
+
+# Get current wal write and latest checkpoint lsn
+my $write_lsn = $node_primary->lsn('write');
+my $checkpoint_lsn = get_latest_checkpoint_location($node_primary);
+
+# Restart the server, shutdown and starup checkpoint will be skipped.
+$node_primary->restart;
+
+is($node_primary->safe_psql('postgres', $show_wal_prohibited_query),
+	'on', 'primary server is wal prohibited after restart too');
+is($node_primary->lsn('write'), $write_lsn,
+	"no wal writes on primary, last wal write lsn : $write_lsn");
+is(get_latest_checkpoint_location($node_primary), $checkpoint_lsn,
+	"no new checkpoint on primary, last checkpoint lsn : $checkpoint_lsn");
+
+# Now stop the primary server in WAL prohibited state and take filesystem level
+# backup and set up new server from it.
+$node_primary->stop;
+my $backup_name = 'my_backup';
+$node_primary->backup_fs_cold($backup_name);
+my $node_standby = PostgresNode->new('standby');
+$node_standby->init_from_backup($node_primary, $backup_name);
+$node_standby->start;
+
+# The primary server is stopped in wal prohibited state, the filesystem level
+# copy also be in wal prohibited state
+is($node_standby->safe_psql('postgres', $show_wal_prohibited_query), 'on',
+	'new server created using backup of a stopped primary is also wal prohibited');
+
+# Start Primary
+$node_primary->start;
+
+# Set the new server as standby of primary.
+# enable_streaming will create standby.signal file which will take out system
+# from wal prohibited state.
+$node_standby->enable_streaming($node_primary);
+$node_standby->restart;
+
+# Check if the new server has been taken out from the wal prohibited state.
+is($node_standby->safe_psql('postgres', $show_wal_prohibited_query),
+	'off', 'new server as standby is no longer wal prohibited');
+
+# Standby server cannot be put into wal prohibited state.
+my ($stdout, $stderr, $timed_out);
+$node_standby->psql('postgres', 'SELECT pg_prohibit_wal(true)',
+          stdout => \$stdout, stderr => \$stderr);
+like($stderr, qr/cannot execute pg_prohibit_wal\(\) during recovery/,
+	'standby server state cannot be changed to wal prohibited');
+
+# Primary is still in wal prohibited state, the further insert will fail.
+$node_primary->psql('postgres', 'INSERT INTO tab VALUES(6)',
+          stdout => \$stdout, stderr => \$stderr);
+like($stderr, qr/cannot execute INSERT in a read-only transaction/,
+	'primary server is wal prohibited, table insert is failed');
+
+# Change primary to WAL permitted
+$node_primary->safe_psql('postgres', 'SELECT pg_prohibit_wal(false)');
+is($node_primary->safe_psql('postgres', $show_wal_prohibited_query),
+	'off', 'primary server is change to wal permitted');
+
+my $new_checkpoint_lsn = get_latest_checkpoint_location($node_primary);
+is($new_checkpoint_lsn == $checkpoint_lsn, 1,
+	"new implicit checkpoint performed on primary, new checkpoint lsn : $new_checkpoint_lsn");
+
+# Insert data
+$node_primary->safe_psql('postgres', 'INSERT INTO tab VALUES(6)');
+is($node_primary->safe_psql('postgres', 'SELECT count(i) FROM tab'), '6',
+	'insert passed on primary');
+
+# Wait until necessary replay has been done on standby
+my $current_lsn =
+  $node_primary->safe_psql('postgres', "SELECT pg_current_wal_lsn();");
+my $caughtup_query =
+  "SELECT '$current_lsn'::pg_lsn <= pg_last_wal_replay_lsn()";
+$node_standby->poll_query_until('postgres', $caughtup_query)
+  or die "Timed out while waiting for standby to catch up";
+
+is($node_standby->safe_psql('postgres', 'SELECT count(i) FROM tab'), '6',
+	'new insert replicated on standby as well');
+
+#
+# Get latest checkpoint lsn from control file
+#
+sub get_latest_checkpoint_location
+{
+	my ($node) = @_;
+	my $data_dir = $node->data_dir;
+	my ($stdout, $stderr) = run_command([ 'pg_controldata', $data_dir ]);
+	my @control_data = split("\n", $stdout);
+
+	my $latest_checkpoint_lsn = undef;
+	foreach (@control_data)
+	{
+		if ($_ =~ /^Latest checkpoint location:\s*(.*)$/mg)
+		{
+			$latest_checkpoint_lsn = $1;
+			last;
+		}
+	}
+	die "No latest checkpoint location in control file found\n"
+	unless defined($latest_checkpoint_lsn);
+
+	return $latest_checkpoint_lsn;
+}
-- 
2.18.0

