From 90627cf98a8e7d0531789391fd798c9bfcc3bc1a Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter_e@gmx.net>
Date: Tue, 5 Sep 2017 12:22:33 -0400
Subject: [PATCH] Support retaining data dirs on successful TAP tests

This moves the data directories from using temporary directories with
randomness in the directory name to a static name, to make it easier to
debug.  The data directory will be retained if tests fail or the test
code dies/exits with failure, and is automatically removed on the next
make check.

If the environment variable PG_TEST_NOCLEAN is defined, the data
directories will be retained regardless of test or exit status.

Author: Daniel Gustafsson <daniel@yesql.se>
---
 src/Makefile.global.in                     |  6 ++-
 src/bin/pg_rewind/RewindTest.pm            |  7 +++-
 src/bin/pg_rewind/t/001_basic.pl           |  4 +-
 src/bin/pg_rewind/t/002_databases.pl       |  4 +-
 src/bin/pg_rewind/t/003_extrafiles.pl      |  4 +-
 src/bin/pg_rewind/t/004_pg_xlog_symlink.pl |  4 +-
 src/test/perl/PostgresNode.pm              | 47 ++++++++++++++++++++--
 7 files changed, 61 insertions(+), 15 deletions(-)

diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index e8b3a519cb..fae8068150 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -362,12 +362,14 @@ endef
 ifeq ($(enable_tap_tests),yes)
 
 define prove_installcheck
-rm -rf $(CURDIR)/tmp_check/log
+rm -rf '$(CURDIR)'/tmp_check
+$(MKDIR_P) '$(CURDIR)'/tmp_check
 cd $(srcdir) && TESTDIR='$(CURDIR)' PATH="$(bindir):$$PATH" PGPORT='6$(DEF_PGPORT)' top_builddir='$(CURDIR)/$(top_builddir)' PG_REGRESS='$(CURDIR)/$(top_builddir)/src/test/regress/pg_regress' $(PROVE) $(PG_PROVE_FLAGS) $(PROVE_FLAGS) $(if $(PROVE_TESTS),$(PROVE_TESTS),t/*.pl)
 endef
 
 define prove_check
-rm -rf $(CURDIR)/tmp_check/log
+rm -rf '$(CURDIR)'/tmp_check
+$(MKDIR_P) '$(CURDIR)'/tmp_check
 cd $(srcdir) && TESTDIR='$(CURDIR)' $(with_temp_install) PGPORT='6$(DEF_PGPORT)' PG_REGRESS='$(CURDIR)/$(top_builddir)/src/test/regress/pg_regress' $(PROVE) $(PG_PROVE_FLAGS) $(PROVE_FLAGS) $(if $(PROVE_TESTS),$(PROVE_TESTS),t/*.pl)
 endef
 
diff --git a/src/bin/pg_rewind/RewindTest.pm b/src/bin/pg_rewind/RewindTest.pm
index 6649c22b4f..76ce295cef 100644
--- a/src/bin/pg_rewind/RewindTest.pm
+++ b/src/bin/pg_rewind/RewindTest.pm
@@ -114,9 +114,10 @@ sub check_query
 
 sub setup_cluster
 {
+	my $extra_name = shift;
 
 	# Initialize master, data checksums are mandatory
-	$node_master = get_new_node('master');
+	$node_master = get_new_node('master' . ($extra_name ? "_${extra_name}" : ''));
 	$node_master->init(allows_streaming => 1);
 }
 
@@ -130,7 +131,9 @@ sub start_master
 
 sub create_standby
 {
-	$node_standby = get_new_node('standby');
+	my $extra_name = shift;
+
+	$node_standby = get_new_node('standby' . ($extra_name ? "_${extra_name}" : ''));
 	$node_master->backup('my_backup');
 	$node_standby->init_from_backup($node_master, 'my_backup');
 	my $connstr_master = $node_master->connstr();
diff --git a/src/bin/pg_rewind/t/001_basic.pl b/src/bin/pg_rewind/t/001_basic.pl
index 1764b17c90..736f34eae3 100644
--- a/src/bin/pg_rewind/t/001_basic.pl
+++ b/src/bin/pg_rewind/t/001_basic.pl
@@ -9,7 +9,7 @@ sub run_test
 {
 	my $test_mode = shift;
 
-	RewindTest::setup_cluster();
+	RewindTest::setup_cluster($test_mode);
 	RewindTest::start_master();
 
 	# Create a test table and insert a row in master.
@@ -28,7 +28,7 @@ sub run_test
 
 	master_psql("CHECKPOINT");
 
-	RewindTest::create_standby();
+	RewindTest::create_standby($test_mode);
 
 	# Insert additional data on master that will be replicated to standby
 	master_psql("INSERT INTO tbl1 values ('in master, before promotion')");
diff --git a/src/bin/pg_rewind/t/002_databases.pl b/src/bin/pg_rewind/t/002_databases.pl
index 20bdb4ab59..37cdd712f3 100644
--- a/src/bin/pg_rewind/t/002_databases.pl
+++ b/src/bin/pg_rewind/t/002_databases.pl
@@ -9,13 +9,13 @@ sub run_test
 {
 	my $test_mode = shift;
 
-	RewindTest::setup_cluster();
+	RewindTest::setup_cluster($test_mode);
 	RewindTest::start_master();
 
 	# Create a database in master.
 	master_psql('CREATE DATABASE inmaster');
 
-	RewindTest::create_standby();
+	RewindTest::create_standby($test_mode);
 
 	# Create another database, the creation is replicated to the standby
 	master_psql('CREATE DATABASE beforepromotion');
diff --git a/src/bin/pg_rewind/t/003_extrafiles.pl b/src/bin/pg_rewind/t/003_extrafiles.pl
index cedde1409b..2433a4aab6 100644
--- a/src/bin/pg_rewind/t/003_extrafiles.pl
+++ b/src/bin/pg_rewind/t/003_extrafiles.pl
@@ -14,7 +14,7 @@ sub run_test
 {
 	my $test_mode = shift;
 
-	RewindTest::setup_cluster();
+	RewindTest::setup_cluster($test_mode);
 	RewindTest::start_master();
 
 	my $test_master_datadir = $node_master->data_dir;
@@ -27,7 +27,7 @@ sub run_test
 	append_to_file "$test_master_datadir/tst_both_dir/both_subdir/both_file3",
 	  "in both3";
 
-	RewindTest::create_standby();
+	RewindTest::create_standby($test_mode);
 
 	# Create different subdirs and files in master and standby
 	my $test_standby_datadir = $node_standby->data_dir;
diff --git a/src/bin/pg_rewind/t/004_pg_xlog_symlink.pl b/src/bin/pg_rewind/t/004_pg_xlog_symlink.pl
index 12950ea1ca..feadaa6a0f 100644
--- a/src/bin/pg_rewind/t/004_pg_xlog_symlink.pl
+++ b/src/bin/pg_rewind/t/004_pg_xlog_symlink.pl
@@ -26,7 +26,7 @@ sub run_test
 	my $master_xlogdir = "${TestLib::tmp_check}/xlog_master";
 
 	rmtree($master_xlogdir);
-	RewindTest::setup_cluster();
+	RewindTest::setup_cluster($test_mode);
 
 	my $test_master_datadir = $node_master->data_dir;
 
@@ -43,7 +43,7 @@ sub run_test
 
 	master_psql("CHECKPOINT");
 
-	RewindTest::create_standby();
+	RewindTest::create_standby($test_mode);
 
 	# Insert additional data on master that will be replicated to standby
 	master_psql("INSERT INTO tbl1 values ('in master, before promotion')");
diff --git a/src/test/perl/PostgresNode.pm b/src/test/perl/PostgresNode.pm
index d9aeb277d9..3a81c1c60b 100644
--- a/src/test/perl/PostgresNode.pm
+++ b/src/test/perl/PostgresNode.pm
@@ -86,6 +86,7 @@ use Config;
 use Cwd;
 use Exporter 'import';
 use File::Basename;
+use File::Path qw(rmtree);
 use File::Spec;
 use File::Temp ();
 use IPC::Run;
@@ -100,7 +101,7 @@ our @EXPORT = qw(
   get_new_node
 );
 
-our ($test_localhost, $test_pghost, $last_port_assigned, @all_nodes);
+our ($test_localhost, $test_pghost, $last_port_assigned, @all_nodes, $died);
 
 # Windows path to virtual file system root
 
@@ -149,11 +150,13 @@ sub new
 	my $self = {
 		_port    => $pgport,
 		_host    => $pghost,
-		_basedir => TestLib::tempdir("data_" . $name),
+		_basedir => "$TestLib::tmp_check/t_${testname}_${name}_data",
 		_name    => $name,
 		_logfile => "$TestLib::log_path/${testname}_${name}.log" };
 
 	bless $self, $class;
+	mkdir $self->{_basedir}	or
+		BAIL_OUT("could not create data directory \"$self->{_basedir}\": $!");
 	$self->dump_info;
 
 	return $self;
@@ -928,9 +931,24 @@ sub get_new_node
 	return $node;
 }
 
+# Retain the errno on die() if set, else assume a generic errno of 1.
+# This will instruct the END handler on how to handle artifacts left
+# behind from tests.
+$SIG{__DIE__} = sub
+{
+	if ($!)
+	{
+		$died = $!;
+	}
+	else
+	{
+		$died = 1;
+	}
+};
+
 # Automatically shut down any still-running nodes when the test script exits.
 # Note that this just stops the postmasters (in the same order the nodes were
-# created in).  Temporary PGDATA directories are deleted, in an unspecified
+# created in).  Any temporary directories are deleted, in an unspecified
 # order, later when the File::Temp objects are destroyed.
 END
 {
@@ -941,6 +959,13 @@ END
 	foreach my $node (@all_nodes)
 	{
 		$node->teardown_node;
+
+		# skip clean if we are requested to retain the basedir
+		next if defined $ENV{'PG_TEST_NOCLEAN'};
+
+		# clean basedir on clean test invocation
+		$node->clean_node
+			if TestLib::all_tests_passing() && !defined $died && !$exit_code;
 	}
 
 	$? = $exit_code;
@@ -959,6 +984,22 @@ sub teardown_node
 	my $self = shift;
 
 	$self->stop('immediate');
+
+}
+
+=pod
+
+=item $node->clean_node()
+
+Remove the base directory of the node if the node has been stopped.
+
+=cut
+
+sub clean_node
+{
+	my $self = shift;
+
+	rmtree $self->{_basedir} unless defined $self->{_pid};
 }
 
 =pod
-- 
2.40.0