From f85b402491dd22ecc2521bbb7a3f75bfe47c60a8 Mon Sep 17 00:00:00 2001
From: Ronan Dunklau <ronan.dunklau@aiven.io>
Date: Wed, 20 Oct 2021 14:52:13 +0200
Subject: [PATCH v8 4/4] Add tests making sure pg_receivewal can follow a
 timeline switch.

---
 src/bin/pg_basebackup/t/020_pg_receivewal.pl | 61 +++++++++++++++++++-
 1 file changed, 60 insertions(+), 1 deletion(-)

diff --git a/src/bin/pg_basebackup/t/020_pg_receivewal.pl b/src/bin/pg_basebackup/t/020_pg_receivewal.pl
index 42749c3a40..a5e19c5616 100644
--- a/src/bin/pg_basebackup/t/020_pg_receivewal.pl
+++ b/src/bin/pg_basebackup/t/020_pg_receivewal.pl
@@ -5,7 +5,7 @@ use strict;
 use warnings;
 use TestLib;
 use PostgresNode;
-use Test::More tests => 32;
+use Test::More tests => 38;
 
 program_help_ok('pg_receivewal');
 program_version_ok('pg_receivewal');
@@ -185,6 +185,65 @@ $primary->command_ok(
 $slot = $primary->slot($slot_name);
 ok(-e "$stream_dir/$walfile_to_be_archived", "WAL from the slot's restart_lsn has been archived");
 
+# Check what happens on a timeline switch
+sub change_timeline{
+  # Setup a new standby, start pg_receivewal once, then promote it.
+  my ($primary, $backup_name, $standby_name, $slot_name, $stream_dir) = @_;
+  my $standby = PostgresNode->new($standby_name);
+  $standby->init_from_backup($primary, $backup_name, has_streaming => 1);
+  $standby->start;
+  $primary->wait_for_catchup($standby, 'replay', $primary->lsn('write'));
+  $standby->psql('', "CREATE_REPLICATION_SLOT $slot_name PHYSICAL (RESERVE_WAL)",
+                 replication => 1);
+  $primary->psql('postgres',
+	'INSERT INTO test_table VALUES (generate_series(1,100));');
+  # Get a position which can act as an end position.
+  my $nextlsn = $primary->safe_psql('postgres', 'SELECT pg_current_wal_insert_lsn();');
+  $primary->safe_psql('postgres', 'SELECT pg_switch_wal();');
+  # Stream some wal, this will populate the stream directory for the
+  # resume-from-archive test case.
+  $standby->run_log(
+    [ 'pg_receivewal', '-D', $stream_dir, '--verbose', '--endpos', $nextlsn, "--slot", $slot_name],
+    "Stream some wal before promoting");
+  $standby->psql(
+	'postgres',
+	"SELECT pg_promote(wait_seconds => 300)");
+  $standby->psql('postgres',
+	'INSERT INTO test_table VALUES (generate_series(1,100));');
+  $standby->safe_psql('postgres', 'SELECT pg_switch_wal();');
+  # Get a full walfilename that will be generated.
+  my $walfilename = $standby->safe_psql('postgres', "SELECT pg_walfile_name(pg_current_wal_insert_lsn())");
+  $standby->psql('postgres',
+	'INSERT INTO test_table VALUES (generate_series(1,100));');
+  $standby->safe_psql('postgres', 'SELECT pg_switch_wal();');
+  $nextlsn = $standby->safe_psql('postgres', 'SELECT pg_current_wal_insert_lsn();');
+  return $standby, $nextlsn, $walfilename;
+}
+
+my $backup_name = 'my_backup';
+$primary->backup($backup_name);
+my $standby;
+unlink glob "'${stream_dir}/*'";
+# First test: change timeline, and check we can resume from the slot.
+($standby, $nextlsn, $walfile_to_be_archived) = change_timeline($primary, 'my_backup', 'standby1', $slot_name, $stream_dir);
+# To resume from the slot, the target directory must be empty
+unlink glob "'${stream_dir}/*'";
+$standby->command_ok(
+	[ 'pg_receivewal', '-D', $stream_dir, '--verbose', '--endpos', $nextlsn, "--slot", $slot_name],
+	"Stream some wal after promoting, resuming from the slot's position");
+ok(-e "$stream_dir/$walfile_to_be_archived", "WAL from the new timeline has been archived");
+ok(-e "$stream_dir/00000002.history", "Timeline history file has been archived");
+
+# Now do the same, but resuming from the latest archived file.
+# Cleanup leftover from the first standby
+unlink glob "'${stream_dir}/*'";
+($standby, $nextlsn, $walfile_to_be_archived) = change_timeline($primary, 'my_backup', 'standby2', $slot_name, $stream_dir);
+$standby->command_ok(
+	[ 'pg_receivewal', '-D', $stream_dir, '--verbose', '--endpos', $nextlsn],
+	"Stream some wal after promoting, resuming from the latest archived file");
+ok(-e "$stream_dir/$walfile_to_be_archived", "WAL from the new timeline has been archived");
+ok(-e "$stream_dir/00000002.history", "Timeline history file has been archived");
+
 # Permissions on WAL files should be default
 SKIP:
 {
-- 
2.33.0

