public inbox for [email protected]  
help / color / mirror / Atom feed
[PATCH v8 4/8] Propagate changes to indisclustered to child/parents
7+ messages / 4 participants
[nested] [flat]

* [PATCH v8 4/8] Propagate changes to indisclustered to child/parents
@ 2020-10-07 03:11  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 7+ messages in thread

From: Justin Pryzby @ 2020-10-07 03:11 UTC (permalink / raw)

---
 src/backend/commands/cluster.c        | 109 ++++++++++++++++----------
 src/backend/commands/indexcmds.c      |   2 +
 src/test/regress/expected/cluster.out |  46 +++++++++++
 src/test/regress/sql/cluster.sql      |  11 +++
 4 files changed, 125 insertions(+), 43 deletions(-)

diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index cb4fc350c6..5c08f0642e 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -74,6 +74,7 @@ static void rebuild_relation(Relation OldHeap, Oid indexOid, bool verbose);
 static void copy_table_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
 							bool verbose, bool *pSwapToastByContent,
 							TransactionId *pFreezeXid, MultiXactId *pCutoffMulti);
+static void set_indisclustered(Oid indexOid, bool isclustered, Relation pg_index);
 static List *get_tables_to_cluster(MemoryContext cluster_context);
 static List *get_tables_to_cluster_partitioned(MemoryContext cluster_context,
 		Oid indexOid);
@@ -516,66 +517,88 @@ check_index_is_clusterable(Relation OldHeap, Oid indexOid, bool recheck, LOCKMOD
 	index_close(OldIndex, NoLock);
 }
 
+/*
+ * Helper for mark_index_clustered
+ * Mark a single index as clustered or not.
+ * pg_index is passed by caller to avoid repeatedly re-opening it.
+ */
+static void
+set_indisclustered(Oid indexOid, bool isclustered, Relation pg_index)
+{
+	HeapTuple	indexTuple;
+	Form_pg_index indexForm;
+
+	indexTuple = SearchSysCacheCopy1(INDEXRELID,
+									ObjectIdGetDatum(indexOid));
+	if (!HeapTupleIsValid(indexTuple))
+		elog(ERROR, "cache lookup failed for index %u", indexOid);
+	indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
+
+	/* this was checked earlier, but let's be real sure */
+	if (isclustered && !indexForm->indisvalid)
+		elog(ERROR, "cannot cluster on invalid index %u", indexOid);
+
+	indexForm->indisclustered = isclustered;
+	CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple);
+	heap_freetuple(indexTuple);
+}
+
 /*
  * mark_index_clustered: mark the specified index as the one clustered on
  *
- * With indexOid == InvalidOid, will mark all indexes of rel not-clustered.
+ * With indexOid == InvalidOid, mark all indexes of rel not-clustered.
+ * Otherwise, mark children of the clustered index as clustered, and parents of
+ * other indexes as unclustered.
+ * We wish to maintain the following properties:
+ * 1) Only one index on a relation can be marked clustered at once
+ * 2) If a partitioned index is clustered, then all its children must be
+ *     clustered.
  */
 void
 mark_index_clustered(Relation rel, Oid indexOid, bool is_internal)
 {
-	HeapTuple	indexTuple;
-	Form_pg_index indexForm;
-	Relation	pg_index;
-	ListCell   *index;
-
-	/*
-	 * If the index is already marked clustered, no need to do anything.
-	 */
-	if (OidIsValid(indexOid))
-	{
-		if (get_index_isclustered(indexOid))
-			return;
-	}
+	ListCell	*lc, *lc2;
+	List		*indexes;
+	Relation	pg_index = table_open(IndexRelationId, RowExclusiveLock);
+	List		*inh = find_all_inheritors(RelationGetRelid(rel), ShareRowExclusiveLock, NULL);
 
 	/*
 	 * Check each index of the relation and set/clear the bit as needed.
+	 * Iterate over the relation's children rather than the index's children
+	 * since we need to unset cluster for indexes on intermediate children,
+	 * too.
 	 */
-	pg_index = table_open(IndexRelationId, RowExclusiveLock);
-
-	foreach(index, RelationGetIndexList(rel))
+	foreach(lc, inh)
 	{
-		Oid			thisIndexOid = lfirst_oid(index);
-
-		indexTuple = SearchSysCacheCopy1(INDEXRELID,
-										 ObjectIdGetDatum(thisIndexOid));
-		if (!HeapTupleIsValid(indexTuple))
-			elog(ERROR, "cache lookup failed for index %u", thisIndexOid);
-		indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
+		Oid			inhrelid = lfirst_oid(lc);
+		Relation	thisrel = table_open(inhrelid, ShareRowExclusiveLock);
 
-		/*
-		 * Unset the bit if set.  We know it's wrong because we checked this
-		 * earlier.
-		 */
-		if (indexForm->indisclustered)
+		indexes = RelationGetIndexList(thisrel);
+		foreach (lc2, indexes)
 		{
-			indexForm->indisclustered = false;
-			CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple);
-		}
-		else if (thisIndexOid == indexOid)
-		{
-			/* this was checked earlier, but let's be real sure */
-			if (!indexForm->indisvalid)
-				elog(ERROR, "cannot cluster on invalid index %u", indexOid);
-			indexForm->indisclustered = true;
-			CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple);
-		}
+			bool	isclustered;
+			Oid		thisIndexOid = lfirst_oid(lc2);
+			List	*parentoids = get_rel_relispartition(thisIndexOid) ?
+				get_partition_ancestors(thisIndexOid) : NIL;
 
-		InvokeObjectPostAlterHookArg(IndexRelationId, thisIndexOid, 0,
-									 InvalidOid, is_internal);
+			/*
+			 * A child of the clustered index must be set clustered;
+			 * indexes which are not children of the clustered index are
+			 * set unclustered
+			 */
+			isclustered = (thisIndexOid == indexOid) ||
+					list_member_oid(parentoids, indexOid);
+			Assert(OidIsValid(indexOid) || !isclustered);
+			set_indisclustered(thisIndexOid, isclustered, pg_index);
+
+			InvokeObjectPostAlterHookArg(IndexRelationId, thisIndexOid, 0,
+										 InvalidOid, is_internal);
+		}
 
-		heap_freetuple(indexTuple);
+		list_free(indexes);
+		table_close(thisrel, ShareRowExclusiveLock);
 	}
+	list_free(inh);
 
 	table_close(pg_index, RowExclusiveLock);
 }
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 127ba7835d..4ca1ffbfa4 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -25,6 +25,7 @@
 #include "catalog/catalog.h"
 #include "catalog/index.h"
 #include "catalog/indexing.h"
+#include "catalog/partition.h"
 #include "catalog/pg_am.h"
 #include "catalog/pg_constraint.h"
 #include "catalog/pg_inherits.h"
@@ -32,6 +33,7 @@
 #include "catalog/pg_opfamily.h"
 #include "catalog/pg_tablespace.h"
 #include "catalog/pg_type.h"
+#include "commands/cluster.h"
 #include "commands/comment.h"
 #include "commands/dbcommands.h"
 #include "commands/defrem.h"
diff --git a/src/test/regress/expected/cluster.out b/src/test/regress/expected/cluster.out
index c74cfa88cc..1d436dfaae 100644
--- a/src/test/regress/expected/cluster.out
+++ b/src/test/regress/expected/cluster.out
@@ -495,6 +495,52 @@ Indexes:
     "clstrpart_idx" btree (a) CLUSTER
 Number of partitions: 3 (Use \d+ to list them.)
 
+-- Test that it recurses to grandchildren:
+\d clstrpart33
+            Table "public.clstrpart33"
+ Column |  Type   | Collation | Nullable | Default 
+--------+---------+-----------+----------+---------
+ a      | integer |           |          | 
+Partition of: clstrpart3 DEFAULT
+Indexes:
+    "clstrpart33_a_idx" btree (a) CLUSTER
+
+ALTER TABLE clstrpart SET WITHOUT CLUSTER;
+\d clstrpart33
+            Table "public.clstrpart33"
+ Column |  Type   | Collation | Nullable | Default 
+--------+---------+-----------+----------+---------
+ a      | integer |           |          | 
+Partition of: clstrpart3 DEFAULT
+Indexes:
+    "clstrpart33_a_idx" btree (a)
+
+ALTER TABLE clstrpart CLUSTER ON clstrpart_idx;
+\d clstrpart33
+            Table "public.clstrpart33"
+ Column |  Type   | Collation | Nullable | Default 
+--------+---------+-----------+----------+---------
+ a      | integer |           |          | 
+Partition of: clstrpart3 DEFAULT
+Indexes:
+    "clstrpart33_a_idx" btree (a) CLUSTER
+
+-- Check that only one child is marked clustered after marking clustered on a different parent
+CREATE INDEX clstrpart1_idx_2 ON clstrpart1(a);
+ALTER TABLE clstrpart CLUSTER ON clstrpart_idx;
+ALTER TABLE clstrpart1 CLUSTER ON clstrpart1_idx_2;
+\d clstrpart1
+       Partitioned table "public.clstrpart1"
+ Column |  Type   | Collation | Nullable | Default 
+--------+---------+-----------+----------+---------
+ a      | integer |           |          | 
+Partition of: clstrpart FOR VALUES FROM (1) TO (10)
+Partition key: RANGE (a)
+Indexes:
+    "clstrpart1_a_idx" btree (a)
+    "clstrpart1_idx_2" btree (a) CLUSTER
+Number of partitions: 2 (Use \d+ to list them.)
+
 -- Test CLUSTER with external tuplesorting
 create table clstr_4 as select * from tenk1;
 create index cluster_sort on clstr_4 (hundred, thousand, tenthous);
diff --git a/src/test/regress/sql/cluster.sql b/src/test/regress/sql/cluster.sql
index 9bcc77695c..0ded2be1ca 100644
--- a/src/test/regress/sql/cluster.sql
+++ b/src/test/regress/sql/cluster.sql
@@ -220,6 +220,17 @@ CLUSTER clstrpart1 USING clstrpart1_a_idx; -- partition which is itself partitio
 CLUSTER clstrpart12 USING clstrpart12_a_idx; -- partition which is itself partitioned, no childs
 CLUSTER clstrpart2 USING clstrpart2_a_idx; -- leaf
 \d clstrpart
+-- Test that it recurses to grandchildren:
+\d clstrpart33
+ALTER TABLE clstrpart SET WITHOUT CLUSTER;
+\d clstrpart33
+ALTER TABLE clstrpart CLUSTER ON clstrpart_idx;
+\d clstrpart33
+-- Check that only one child is marked clustered after marking clustered on a different parent
+CREATE INDEX clstrpart1_idx_2 ON clstrpart1(a);
+ALTER TABLE clstrpart CLUSTER ON clstrpart_idx;
+ALTER TABLE clstrpart1 CLUSTER ON clstrpart1_idx_2;
+\d clstrpart1
 
 -- Test CLUSTER with external tuplesorting
 
-- 
2.17.0


--O5XBE6gyVG5Rl6Rj
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
 filename="v8-0005-Invalidate-parent-indexes.patch"



^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* Re: Rewriting the test of pg_upgrade as a TAP test - take three - remastered set
@ 2022-01-05 08:12  Michael Paquier <[email protected]>
  0 siblings, 1 reply; 7+ messages in thread

From: Michael Paquier @ 2022-01-05 08:12 UTC (permalink / raw)
  To: Andres Freund <[email protected]>; +Cc: Tom Lane <[email protected]>; Andrew Dunstan <[email protected]>; Postgres hackers <[email protected]>

On Thu, Dec 16, 2021 at 11:51:55AM +0900, Michael Paquier wrote:
> I may have missed one thing or two, but I think that's pretty much
> what we should be looking for to do the switch to TAP in terms of
> coverage.

Rebased patch to cool down the CF bot, as per the addition of
--no-sync to pg_upgrade.
--
Michael


Attachments:

  [text/x-diff] v5-0001-Switch-tests-of-pg_upgrade-to-use-TAP.patch (28.2K, ../../[email protected]/2-v5-0001-Switch-tests-of-pg_upgrade-to-use-TAP.patch)
  download | inline diff:
From f7af03ec5e5c6a685796d58b6d82eb9f603565de Mon Sep 17 00:00:00 2001
From: Michael Paquier <[email protected]>
Date: Wed, 5 Jan 2022 17:11:12 +0900
Subject: [PATCH v5] Switch tests of pg_upgrade to use TAP

---
 src/bin/pg_upgrade/.gitignore            |   5 +
 src/bin/pg_upgrade/Makefile              |  23 +-
 src/bin/pg_upgrade/TESTING               |  33 ++-
 src/bin/pg_upgrade/t/001_basic.pl        |   9 +
 src/bin/pg_upgrade/t/002_pg_upgrade.pl   | 275 ++++++++++++++++++++++
 src/bin/pg_upgrade/test.sh               | 279 -----------------------
 src/test/perl/PostgreSQL/Test/Cluster.pm |  25 ++
 src/tools/msvc/vcregress.pl              |  94 +-------
 8 files changed, 355 insertions(+), 388 deletions(-)
 create mode 100644 src/bin/pg_upgrade/t/001_basic.pl
 create mode 100644 src/bin/pg_upgrade/t/002_pg_upgrade.pl
 delete mode 100644 src/bin/pg_upgrade/test.sh

diff --git a/src/bin/pg_upgrade/.gitignore b/src/bin/pg_upgrade/.gitignore
index 2d3bfeaa50..3b64522ab6 100644
--- a/src/bin/pg_upgrade/.gitignore
+++ b/src/bin/pg_upgrade/.gitignore
@@ -7,3 +7,8 @@
 /loadable_libraries.txt
 /log/
 /tmp_check/
+
+# Generated by pg_regress
+/sql/
+/expected/
+/results/
diff --git a/src/bin/pg_upgrade/Makefile b/src/bin/pg_upgrade/Makefile
index 44d06be5a6..35b6c123a5 100644
--- a/src/bin/pg_upgrade/Makefile
+++ b/src/bin/pg_upgrade/Makefile
@@ -28,6 +28,12 @@ OBJS = \
 override CPPFLAGS := -DDLSUFFIX=\"$(DLSUFFIX)\" -I$(srcdir) -I$(libpq_srcdir) $(CPPFLAGS)
 LDFLAGS_INTERNAL += -L$(top_builddir)/src/fe_utils -lpgfeutils $(libpq_pgport)
 
+# required for 002_pg_upgrade.pl
+REGRESS_SHLIB=$(abs_top_builddir)/src/test/regress/regress$(DLSUFFIX)
+export REGRESS_SHLIB
+REGRESS_OUTPUTDIR=$(abs_top_builddir)/src/bin/pg_upgrade
+export REGRESS_OUTPUTDIR
+
 all: pg_upgrade
 
 pg_upgrade: $(OBJS) | submake-libpq submake-libpgport submake-libpgfeutils
@@ -49,17 +55,8 @@ clean distclean maintainer-clean:
 	       pg_upgrade_dump_globals.sql \
 	       pg_upgrade_dump_*.custom pg_upgrade_*.log
 
-# When $(MAKE) is present, make automatically infers that this is a
-# recursive make. which is not actually what we want here, as that
-# e.g. prevents output synchronization from working (as make thinks
-# that the subsidiary make knows how to deal with that itself, but
-# we're invoking a shell script that doesn't know). Referencing
-# $(MAKE) indirectly avoids that behaviour.
-# See https://www.gnu.org/software/make/manual/html_node/MAKE-Variable.html#MAKE-Variable
-NOTSUBMAKEMAKE=$(MAKE)
+check:
+	$(prove_check)
 
-check: test.sh all temp-install
-	MAKE=$(NOTSUBMAKEMAKE) $(with_temp_install) bindir=$(abs_top_builddir)/tmp_install/$(bindir) EXTRA_REGRESS_OPTS="$(EXTRA_REGRESS_OPTS)" $(SHELL) $<
-
-# installcheck is not supported because there's no meaningful way to test
-# pg_upgrade against a single already-running server
+installcheck:
+	$(prove_installcheck)
diff --git a/src/bin/pg_upgrade/TESTING b/src/bin/pg_upgrade/TESTING
index 78b9747908..43a71566e2 100644
--- a/src/bin/pg_upgrade/TESTING
+++ b/src/bin/pg_upgrade/TESTING
@@ -2,21 +2,30 @@ THE SHORT VERSION
 -----------------
 
 On non-Windows machines, you can execute the testing process
-described below by running
+described below by running the following command in this directory:
 	make check
-in this directory.  This will run the shell script test.sh, performing
-an upgrade from the version in this source tree to a new instance of
-the same version.
 
-To test an upgrade from a different version, you must have a built
-source tree for the old version as well as this version, and you
-must have done "make install" for both versions.  Then do:
+This will run the TAP tests to run pg_upgrade, performing an upgrade
+from the version in this source tree to a  new instance of the same
+version.
+
+To test an upgrade from a different version, there are two options
+available:
+
+1) You have a built source tree for the old version as well as this
+version's binaries.  Then set up the following variables before
+launching the test:
 
 export oldsrc=...somewhere/postgresql	(old version's source tree)
-export oldbindir=...otherversion/bin	(old version's installed bin dir)
-export bindir=...thisversion/bin	(this version's installed bin dir)
-export libdir=...thisversion/lib	(this version's installed lib dir)
-sh test.sh
+export oldinstall=...otherversion/	(old version's install base path)
+
+2) You have a dump that can be used to set up the old version, as well
+as this version's binaries.  Then set up the following variables:
+export olddump=...somewhere/dump.sql	(old version's dump)
+export oldinstall=...otherversion/	(old version's install base path)
+
+Finally, the tests can be done by running
+	make check
 
 In this case, you will have to manually eyeball the resulting dump
 diff for version-specific differences, as explained below.
@@ -77,3 +86,5 @@ steps:
 
 7)  Diff the regression database dump file with the regression dump
     file loaded into the old server.
+
+The generated dump may be reusable with "olddump", as defined above.
diff --git a/src/bin/pg_upgrade/t/001_basic.pl b/src/bin/pg_upgrade/t/001_basic.pl
new file mode 100644
index 0000000000..75b0f98b08
--- /dev/null
+++ b/src/bin/pg_upgrade/t/001_basic.pl
@@ -0,0 +1,9 @@
+use strict;
+use warnings;
+
+use PostgreSQL::Test::Utils;
+use Test::More tests => 8;
+
+program_help_ok('pg_upgrade');
+program_version_ok('pg_upgrade');
+program_options_handling_ok('pg_upgrade');
diff --git a/src/bin/pg_upgrade/t/002_pg_upgrade.pl b/src/bin/pg_upgrade/t/002_pg_upgrade.pl
new file mode 100644
index 0000000000..17ba2d3cd2
--- /dev/null
+++ b/src/bin/pg_upgrade/t/002_pg_upgrade.pl
@@ -0,0 +1,275 @@
+# Set of tests for pg_upgrade, including cross-version checks.
+use strict;
+use warnings;
+
+use Cwd qw(abs_path getcwd);
+use File::Basename qw(dirname);
+
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More tests => 4;
+
+# Generate a database with a name made of a range of ASCII characters.
+sub generate_db
+{
+	my ($node, $from_char, $to_char) = @_;
+
+	my $dbname = '';
+	for my $i ($from_char .. $to_char)
+	{
+		next if $i == 7 || $i == 10 || $i == 13;    # skip BEL, LF, and CR
+		$dbname = $dbname . sprintf('%c', $i);
+	}
+	$node->run_log([ 'createdb', '--port', $node->port, $dbname ]);
+}
+
+# From now on, the test of pg_upgrade consists in setting up an instance.
+# This is the source instance used for the upgrade. Then a new and fresh
+# instance is created, and is used as the target instance for the
+# upgrade.  Before running an upgrade a logical dump of the old instance
+# is taken, and a second logical dump of the new instance is taken after
+# the upgrade.  The upgrade test passes if there are no differences after
+# running pg_upgrade.
+
+# Testing upgrades with an older instance of PostgreSQL requires
+# setting up two environment variables, among the following:
+# - "oldsrc", to point to the code source of the older version.
+#   This is required to set up the old instance with pg_upgrade.
+# - "olddump", to point to a dump file that will be used to set
+#   up the old instance to upgrade from.
+# - "oldinstall", to point to the installation path of the older
+# version.
+
+# "oldsrc" and "olddump" cannot be used together.  Setting up
+# "olddump" and "oldinstall" will use the dump pointed to to
+# set up the old instance.  If "oldsrc" is used instead of "olddump",
+# the full set of regression tests of the old instance is run
+# instead.
+
+if (defined($ENV{oldsrc}) && defined($ENV{olddump}))
+{
+	die "oldsrc and olddump are both defined";
+}
+elsif (defined($ENV{oldsrc}))
+{
+	if (   (defined($ENV{oldsrc}) && !defined($ENV{oldinstall}))
+		|| (!defined($ENV{oldsrc}) && defined($ENV{oldinstall})))
+	{
+		# Not all variables are defined, so leave and die if test is
+		# done with an older installation.
+		die "oldsrc or oldinstall is undefined";
+	}
+}
+elsif (defined($ENV{olddump}))
+{
+	if (   (defined($ENV{olddump}) && !defined($ENV{oldinstall}))
+		|| (!defined($ENV{olddump}) && defined($ENV{oldinstall})))
+	{
+		# Not all variables are defined, so leave and die if test is
+		# done with an older installation.
+		die "olddump or oldinstall is undefined";
+	}
+}
+
+if ((defined($ENV{oldsrc}) || defined($ENV{olddump})) && $windows_os)
+{
+	# This configuration is not supported on Windows, as regress.so
+	# location diverges across the compilation methods used on this
+	# platform.
+	die "No support for older version tests on Windows";
+}
+
+# Default is the location of this source code for both nodes used with
+# the upgrade.
+my $newsrc = abs_path("../../..");
+my $oldsrc = $ENV{oldsrc} || $newsrc;
+$oldsrc = abs_path($oldsrc);
+
+# Temporary location for the dumps taken
+my $tempdir = PostgreSQL::Test::Utils::tempdir;
+
+# Initialize node to upgrade
+my $oldnode = PostgreSQL::Test::Cluster->new('old_node',
+	install_path => $ENV{oldinstall});
+
+$oldnode->init(extra => [ '--locale', 'C', '--encoding', 'LATIN1' ]);
+$oldnode->start;
+
+# Set up the data of the old instance with pg_regress or an old dump.
+if (defined($ENV{olddump}))
+{
+	# Use the dump specified.
+	my $olddumpfile = $ENV{olddump};
+	die "no dump file found!" unless -e $olddumpfile;
+
+	# Load the dump, and we are done here.
+	$oldnode->command_ok(
+		[
+			'psql',   '-X',           '-f', $olddumpfile,
+			'--port', $oldnode->port, 'regression'
+		]);
+}
+else
+{
+	# Default is to just use pg_regress to setup the old instance
+	# Creating databases with names covering most ASCII bytes
+	generate_db($oldnode, 1,  45);
+	generate_db($oldnode, 46, 90);
+	generate_db($oldnode, 91, 127);
+
+	# Run core regression tests on the old instance.
+	$oldnode->run_log([ "createdb", '--port', $oldnode->port, 'regression' ]);
+
+	# Grab any regression options that may be passed down by caller.
+	my $extra_opts_val = $ENV{EXTRA_REGRESS_OPT} || "";
+	my @extra_opts     = split(/\s+/, $extra_opts_val);
+
+	# --dlpath is needed to be able to find the location of regress.so and
+	# any libraries the regression tests required.  This needs to point to
+	# in the old instance when using it.  In the default case, fallback to
+	# what the caller provided for REGRESS_SHLIB.
+	my $dlpath;
+	if (defined($ENV{oldinstall}))
+	{
+		$dlpath = "$oldsrc/src/test/regress";
+	}
+	else
+	{
+		$dlpath = dirname($ENV{REGRESS_SHLIB});
+	}
+	$dlpath = PostgreSQL::Test::Utils::perl2host($dlpath);
+
+	# --outputdir points to the path where to place the output files, which
+	# had better be this directory.
+	my $outputdir =
+	  PostgreSQL::Test::Utils::perl2host($ENV{REGRESS_OUTPUTDIR});
+
+	# --inputdir needs to point to the location of the input files, from the
+	# cluster to-be-upgraded.
+	my $inputdir =
+	  PostgreSQL::Test::Utils::perl2host("$oldsrc/src/test/regress");
+
+	my @regress_command = [
+		$ENV{PG_REGRESS}, '--make-testtablespace-dir',
+		'--schedule',     "$oldsrc/src/test/regress/parallel_schedule",
+		'--bindir',       $oldnode->config_data('--bindir'),
+		'--dlpath',       $dlpath,
+		'--port',         $oldnode->port,
+		'--outputdir',    $outputdir,
+		'--inputdir',     $inputdir,
+		'--use-existing'
+	];
+	@regress_command = (@regress_command, @extra_opts);
+
+	$oldnode->command_ok(@regress_command,
+		'regression test run on old instance');
+}
+
+# Before dumping, get rid of objects not existing or not supported in later
+# versions. This depends on the version of the old server used, and matters
+# only if different versions are used for the dump.
+if (defined($ENV{oldinstall}))
+{
+	# Note that upgrade_adapt.sql from the new version is used, to
+	# cope with an upgrade to this version.
+	$oldnode->run_log(
+		[
+			'psql', '-X', '-f',
+			PostgreSQL::Test::Utils::perl2host(
+				"$newsrc/src/bin/pg_upgrade/upgrade_adapt.sql"),
+			'--port',
+			$oldnode->port,
+			'regression'
+		]);
+}
+
+# Initialize a new node for the upgrade.  This is done early so as it is
+# possible to know with which node's PATH the initial dump needs to be
+# taken.
+my $newnode = PostgreSQL::Test::Cluster->new('new_node');
+$newnode->init(extra => [ '--locale=C', '--encoding=LATIN1' ]);
+my $newbindir = $newnode->config_data('--bindir');
+my $oldbindir = $oldnode->config_data('--bindir');
+
+# Take a dump before performing the upgrade as a base comparison. Note
+# that we need to use pg_dumpall from the new node here.
+$newnode->command_ok(
+	[
+		'pg_dumpall', '--no-sync',
+		'-d',         $oldnode->connstr('postgres'),
+		'-f',         "$tempdir/dump1.sql"
+	],
+	'dump before running pg_upgrade');
+
+# After dumping, update references to the old source tree's regress.so
+# to point to the new tree.
+if (defined($ENV{oldinstall}))
+{
+	# First, fetch all the references to libraries that are not part
+	# of the default path $libdir.
+	my $output = $oldnode->safe_psql('regression',
+		"SELECT DISTINCT probin::text FROM pg_proc WHERE probin NOT LIKE '\$libdir%';"
+	);
+	chomp($output);
+	my @libpaths = split("\n", $output);
+
+	my $dump_data = slurp_file("$tempdir/dump1.sql");
+
+	my $newregresssrc = "$newsrc/src/test/regress";
+	foreach (@libpaths)
+	{
+		my $libpath = $_;
+		$libpath = dirname($libpath);
+		$dump_data =~ s/$libpath/$newregresssrc/g;
+	}
+
+	open my $fh, ">", "$tempdir/dump1.sql" or die "could not open dump file";
+	print $fh $dump_data;
+	close $fh;
+
+	# This replaces any references to the old tree's regress.so
+	# the new tree's regress.so.  Any references that do *not*
+	# match $libdir are switched so as this request does not
+	# depend on the path of the old source tree.  This is useful
+	# when using an old dump.  Do the operation on all the database
+	# that allow connections so as this includes the regression
+	# database and anything the user has set up.
+	$output = $oldnode->safe_psql('postgres',
+		"SELECT datname FROM pg_database WHERE datallowconn;");
+	chomp($output);
+	my @datnames = split("\n", $output);
+	foreach (@datnames)
+	{
+		my $datname = $_;
+		$oldnode->safe_psql(
+			$datname, "UPDATE pg_proc SET probin =
+		  regexp_replace(probin, '.*/', '$newregresssrc/')
+		  WHERE probin NOT LIKE '\$libdir/%'");
+	}
+}
+
+# Update the instance.
+$oldnode->stop;
+
+# Time for the real run.
+$newnode->command_ok(
+	[
+		'pg_upgrade', '--no-sync',        '-d', $oldnode->data_dir,
+		'-D',         $newnode->data_dir, '-b', $oldbindir,
+		'-B',         $newbindir,         '-p', $oldnode->port,
+		'-P',         $newnode->port,
+	],
+	'run of pg_upgrade for new instance');
+$newnode->start;
+
+# Take a second dump on the upgraded instance.
+$newnode->run_log(
+	[
+		'pg_dumpall', '--no-sync',
+		'-d',         $newnode->connstr('postgres'),
+		'-f',         "$tempdir/dump2.sql"
+	]);
+
+# Compare the two dumps, there should be no differences.
+command_ok([ 'diff', '-q', "$tempdir/dump1.sql", "$tempdir/dump2.sql" ],
+	'old and new dump match after pg_upgrade');
diff --git a/src/bin/pg_upgrade/test.sh b/src/bin/pg_upgrade/test.sh
deleted file mode 100644
index d6a318367a..0000000000
--- a/src/bin/pg_upgrade/test.sh
+++ /dev/null
@@ -1,279 +0,0 @@
-#!/bin/sh
-
-# src/bin/pg_upgrade/test.sh
-#
-# Test driver for pg_upgrade.  Initializes a new database cluster,
-# runs the regression tests (to put in some data), runs pg_dumpall,
-# runs pg_upgrade, runs pg_dumpall again, compares the dumps.
-#
-# Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
-# Portions Copyright (c) 1994, Regents of the University of California
-
-set -e
-
-: ${MAKE=make}
-
-# Guard against parallel make issues (see comments in pg_regress.c)
-unset MAKEFLAGS
-unset MAKELEVEL
-
-# Run a given "initdb" binary and overlay the regression testing
-# authentication configuration.
-standard_initdb() {
-	# To increase coverage of non-standard segment size and group access
-	# without increasing test runtime, run these tests with a custom setting.
-	# Also, specify "-A trust" explicitly to suppress initdb's warning.
-	# --allow-group-access and --wal-segsize have been added in v11.
-	"$1" -N --wal-segsize 1 --allow-group-access -A trust
-	if [ -n "$TEMP_CONFIG" -a -r "$TEMP_CONFIG" ]
-	then
-		cat "$TEMP_CONFIG" >> "$PGDATA/postgresql.conf"
-	fi
-	../../test/regress/pg_regress --config-auth "$PGDATA"
-}
-
-# What flavor of host are we on?
-# Treat MINGW* (msys1) and MSYS* (msys2) the same.
-testhost=`uname -s | sed 's/^MSYS/MINGW/'`
-
-# Establish how the server will listen for connections
-case $testhost in
-	MINGW*)
-		LISTEN_ADDRESSES="localhost"
-		PG_REGRESS_SOCKET_DIR=""
-		PGHOST=localhost
-		;;
-	*)
-		LISTEN_ADDRESSES=""
-		# Select a socket directory.  The algorithm is from the "configure"
-		# script; the outcome mimics pg_regress.c:make_temp_sockdir().
-		if [ x"$PG_REGRESS_SOCKET_DIR" = x ]; then
-			set +e
-			dir=`(umask 077 &&
-				  mktemp -d /tmp/pg_upgrade_check-XXXXXX) 2>/dev/null`
-			if [ ! -d "$dir" ]; then
-				dir=/tmp/pg_upgrade_check-$$-$RANDOM
-				(umask 077 && mkdir "$dir")
-				if [ ! -d "$dir" ]; then
-					echo "could not create socket temporary directory in \"/tmp\""
-					exit 1
-				fi
-			fi
-			set -e
-			PG_REGRESS_SOCKET_DIR=$dir
-			trap 'rm -rf "$PG_REGRESS_SOCKET_DIR"' 0
-			trap 'exit 3' 1 2 13 15
-		fi
-		PGHOST=$PG_REGRESS_SOCKET_DIR
-		;;
-esac
-
-POSTMASTER_OPTS="-F -c listen_addresses=\"$LISTEN_ADDRESSES\" -k \"$PG_REGRESS_SOCKET_DIR\""
-export PGHOST
-
-# don't rely on $PWD here, as old shells don't set it
-temp_root=`pwd`/tmp_check
-rm -rf "$temp_root"
-mkdir "$temp_root"
-
-: ${oldbindir=$bindir}
-
-: ${oldsrc=../../..}
-oldsrc=`cd "$oldsrc" && pwd`
-newsrc=`cd ../../.. && pwd`
-
-# We need to make pg_regress use psql from the desired installation
-# (likely a temporary one), because otherwise the installcheck run
-# below would try to use psql from the proper installation directory
-# of the target version, which might be outdated or not exist. But
-# don't override anything else that's already in EXTRA_REGRESS_OPTS.
-EXTRA_REGRESS_OPTS="$EXTRA_REGRESS_OPTS --bindir='$oldbindir'"
-export EXTRA_REGRESS_OPTS
-
-# While in normal cases this will already be set up, adding bindir to
-# path allows test.sh to be invoked with different versions as
-# described in ./TESTING
-PATH=$bindir:$PATH
-export PATH
-
-BASE_PGDATA="$temp_root/data"
-PGDATA="${BASE_PGDATA}.old"
-export PGDATA
-
-# Send installcheck outputs to a private directory.  This avoids conflict when
-# check-world runs pg_upgrade check concurrently with src/test/regress check.
-# To retrieve interesting files after a run, use pattern tmp_check/*/*.diffs.
-outputdir="$temp_root/regress"
-EXTRA_REGRESS_OPTS="$EXTRA_REGRESS_OPTS --outputdir=$outputdir"
-export EXTRA_REGRESS_OPTS
-mkdir "$outputdir"
-
-# pg_regress --make-tablespacedir would take care of that in 14~, but this is
-# still required for older versions where this option is not supported.
-if [ "$newsrc" != "$oldsrc" ]; then
-	mkdir "$outputdir"/testtablespace
-	mkdir "$outputdir"/sql
-	mkdir "$outputdir"/expected
-fi
-
-logdir=`pwd`/log
-rm -rf "$logdir"
-mkdir "$logdir"
-
-# Clear out any environment vars that might cause libpq to connect to
-# the wrong postmaster (cf pg_regress.c)
-#
-# Some shells, such as NetBSD's, return non-zero from unset if the variable
-# is already unset. Since we are operating under 'set -e', this causes the
-# script to fail. To guard against this, set them all to an empty string first.
-PGDATABASE="";        unset PGDATABASE
-PGUSER="";            unset PGUSER
-PGSERVICE="";         unset PGSERVICE
-PGSSLMODE="";         unset PGSSLMODE
-PGREQUIRESSL="";      unset PGREQUIRESSL
-PGCONNECT_TIMEOUT=""; unset PGCONNECT_TIMEOUT
-PGHOSTADDR="";        unset PGHOSTADDR
-
-# Select a non-conflicting port number, similarly to pg_regress.c
-PG_VERSION_NUM=`grep '#define PG_VERSION_NUM' "$newsrc"/src/include/pg_config.h | awk '{print $3}'`
-PGPORT=`expr $PG_VERSION_NUM % 16384 + 49152`
-export PGPORT
-
-i=0
-while psql -X postgres </dev/null 2>/dev/null
-do
-	i=`expr $i + 1`
-	if [ $i -eq 16 ]
-	then
-		echo port $PGPORT apparently in use
-		exit 1
-	fi
-	PGPORT=`expr $PGPORT + 1`
-	export PGPORT
-done
-
-# buildfarm may try to override port via EXTRA_REGRESS_OPTS ...
-EXTRA_REGRESS_OPTS="$EXTRA_REGRESS_OPTS --port=$PGPORT"
-export EXTRA_REGRESS_OPTS
-
-standard_initdb "$oldbindir"/initdb
-"$oldbindir"/pg_ctl start -l "$logdir/postmaster1.log" -o "$POSTMASTER_OPTS" -w
-
-# Create databases with names covering the ASCII bytes other than NUL, BEL,
-# LF, or CR.  BEL would ring the terminal bell in the course of this test, and
-# it is not otherwise a special case.  PostgreSQL doesn't support the rest.
-dbname1=`awk 'BEGIN { for (i= 1; i < 46; i++)
-	if (i != 7 && i != 10 && i != 13) printf "%c", i }' </dev/null`
-# Exercise backslashes adjacent to double quotes, a Windows special case.
-dbname1='\"\'$dbname1'\\"\\\'
-dbname2=`awk 'BEGIN { for (i = 46; i <  91; i++) printf "%c", i }' </dev/null`
-dbname3=`awk 'BEGIN { for (i = 91; i < 128; i++) printf "%c", i }' </dev/null`
-createdb "regression$dbname1" || createdb_status=$?
-createdb "regression$dbname2" || createdb_status=$?
-createdb "regression$dbname3" || createdb_status=$?
-
-# Extra options to apply to the dump.  This may be changed later.
-extra_dump_options=""
-
-if "$MAKE" -C "$oldsrc" installcheck-parallel; then
-	oldpgversion=`psql -X -A -t -d regression -c "SHOW server_version_num"`
-
-	# Before dumping, tweak the database of the old instance depending
-	# on its version.
-	if [ "$newsrc" != "$oldsrc" ]; then
-		# This SQL script has its own idea of the cleanup that needs to be
-		# done on the cluster to-be-upgraded, and includes version checks.
-		# Note that this uses the script stored on the new branch.
-		psql -X -d regression -f "$newsrc/src/bin/pg_upgrade/upgrade_adapt.sql" \
-			|| psql_fix_sql_status=$?
-
-		# Handling of --extra-float-digits gets messy after v12.
-		# Note that this changes the dumps from the old and new
-		# instances if involving an old cluster of v11 or older.
-		if [ $oldpgversion -lt 120000 ]; then
-			extra_dump_options="--extra-float-digits=0"
-		fi
-	fi
-
-	pg_dumpall $extra_dump_options --no-sync \
-		-f "$temp_root"/dump1.sql || pg_dumpall1_status=$?
-
-	if [ "$newsrc" != "$oldsrc" ]; then
-		# update references to old source tree's regress.so etc
-		fix_sql=""
-		case $oldpgversion in
-			*)
-				fix_sql="UPDATE pg_proc SET probin = replace(probin, '$oldsrc', '$newsrc') WHERE probin LIKE '$oldsrc%';"
-				;;
-		esac
-		psql -X -d regression -c "$fix_sql;" || psql_fix_sql_status=$?
-
-		mv "$temp_root"/dump1.sql "$temp_root"/dump1.sql.orig
-		sed "s;$oldsrc;$newsrc;g" "$temp_root"/dump1.sql.orig >"$temp_root"/dump1.sql
-	fi
-else
-	make_installcheck_status=$?
-fi
-"$oldbindir"/pg_ctl -m fast stop
-if [ -n "$createdb_status" ]; then
-	exit 1
-fi
-if [ -n "$make_installcheck_status" ]; then
-	exit 1
-fi
-if [ -n "$psql_fix_sql_status" ]; then
-	exit 1
-fi
-if [ -n "$pg_dumpall1_status" ]; then
-	echo "pg_dumpall of pre-upgrade database cluster failed"
-	exit 1
-fi
-
-PGDATA="$BASE_PGDATA"
-
-standard_initdb 'initdb'
-
-pg_upgrade $PG_UPGRADE_OPTS --no-sync -d "${PGDATA}.old" -D "$PGDATA" -b "$oldbindir" -p "$PGPORT" -P "$PGPORT"
-
-# make sure all directories and files have group permissions, on Unix hosts
-# Windows hosts don't support Unix-y permissions.
-case $testhost in
-	MINGW*|CYGWIN*) ;;
-	*)	if [ `find "$PGDATA" -type f ! -perm 640 | wc -l` -ne 0 ]; then
-			echo "files in PGDATA with permission != 640";
-			exit 1;
-		fi ;;
-esac
-
-case $testhost in
-	MINGW*|CYGWIN*) ;;
-	*)	if [ `find "$PGDATA" -type d ! -perm 750 | wc -l` -ne 0 ]; then
-			echo "directories in PGDATA with permission != 750";
-			exit 1;
-		fi ;;
-esac
-
-pg_ctl start -l "$logdir/postmaster2.log" -o "$POSTMASTER_OPTS" -w
-
-pg_dumpall $extra_dump_options --no-sync \
-	-f "$temp_root"/dump2.sql || pg_dumpall2_status=$?
-pg_ctl -m fast stop
-
-if [ -n "$pg_dumpall2_status" ]; then
-	echo "pg_dumpall of post-upgrade database cluster failed"
-	exit 1
-fi
-
-case $testhost in
-	MINGW*)	MSYS2_ARG_CONV_EXCL=/c cmd /c delete_old_cluster.bat ;;
-	*)	    sh ./delete_old_cluster.sh ;;
-esac
-
-if diff "$temp_root"/dump1.sql "$temp_root"/dump2.sql >/dev/null; then
-	echo PASSED
-	exit 0
-else
-	echo "Files $temp_root/dump1.sql and $temp_root/dump2.sql differ"
-	echo "dumps were not identical"
-	exit 1
-fi
diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm
index c061e850fb..2bf2fcb69d 100644
--- a/src/test/perl/PostgreSQL/Test/Cluster.pm
+++ b/src/test/perl/PostgreSQL/Test/Cluster.pm
@@ -327,6 +327,31 @@ sub install_path
 
 =pod
 
+=item $node->config_data($option)
+
+Grab some data from pg_config, with $option being the switched
+used.
+
+=cut
+
+sub config_data
+{
+	my ($self, $option) = @_;
+	local %ENV = $self->_get_env();
+
+	my ($stdout, $stderr);
+	my $result =
+	  IPC::Run::run [ $self->installed_command('pg_config'), $option ],
+	  '>', \$stdout, '2>', \$stderr
+	  or die "could not execute pg_config";
+	chomp($stdout);
+	$stdout =~ s/\r$//;
+
+	return $stdout;
+}
+
+=pod
+
 =item $node->info()
 
 Return a string containing human-readable diagnostic information (paths, etc)
diff --git a/src/tools/msvc/vcregress.pl b/src/tools/msvc/vcregress.pl
index 29086cab51..d25810373a 100644
--- a/src/tools/msvc/vcregress.pl
+++ b/src/tools/msvc/vcregress.pl
@@ -287,6 +287,10 @@ sub bincheck
 	foreach my $dir (@bin_dirs)
 	{
 		next unless -d "$dir/t";
+		# Do not consider pg_upgrade, as it is handled by
+		# upgradecheck.
+		next if ($dir =~ "/pg_upgrade/");
+
 		my $status = tap_check($dir);
 		$mstat ||= $status;
 	}
@@ -591,91 +595,11 @@ sub generate_db
 
 sub upgradecheck
 {
-	my $status;
-	my $cwd = getcwd();
-
-	# Much of this comes from the pg_upgrade test.sh script,
-	# but it only covers the --install case, and not the case
-	# where the old and new source or bin dirs are different.
-	# i.e. only this version to this version check. That's
-	# what pg_upgrade's "make check" does.
-
-	$ENV{PGHOST} = 'localhost';
-	$ENV{PGPORT} ||= 50432;
-	my $tmp_root = "$topdir/src/bin/pg_upgrade/tmp_check";
-	rmtree($tmp_root);
-	mkdir $tmp_root || die $!;
-	my $upg_tmp_install = "$tmp_root/install";    # unshared temp install
-	print "Setting up temp install\n\n";
-	Install($upg_tmp_install, "all", $config);
-
-	# Install does a chdir, so change back after that
-	chdir $cwd;
-	my ($bindir, $libdir, $oldsrc, $newsrc) =
-	  ("$upg_tmp_install/bin", "$upg_tmp_install/lib", $topdir, $topdir);
-	$ENV{PATH} = "$bindir;$ENV{PATH}";
-	my $data = "$tmp_root/data";
-	$ENV{PGDATA} = "$data.old";
-	my $outputdir          = "$tmp_root/regress";
-	my @EXTRA_REGRESS_OPTS = ("--outputdir=$outputdir");
-	mkdir "$outputdir" || die $!;
-
-	my $logdir = "$topdir/src/bin/pg_upgrade/log";
-	rmtree($logdir);
-	mkdir $logdir || die $!;
-	print "\nRunning initdb on old cluster\n\n";
-	standard_initdb() or exit 1;
-	print "\nStarting old cluster\n\n";
-	my @args = ('pg_ctl', 'start', '-l', "$logdir/postmaster1.log");
-	system(@args) == 0 or exit 1;
-
-	print "\nCreating databases with names covering most ASCII bytes\n\n";
-	generate_db("\\\"\\", 1,  45,  "\\\\\"\\\\\\");
-	generate_db('',       46, 90,  '');
-	generate_db('',       91, 127, '');
-
-	print "\nSetting up data for upgrading\n\n";
-	installcheck_internal('parallel', @EXTRA_REGRESS_OPTS);
-
-	# now we can chdir into the source dir
-	chdir "$topdir/src/bin/pg_upgrade";
-	print "\nDumping old cluster\n\n";
-	@args = ('pg_dumpall', '-f', "$tmp_root/dump1.sql");
-	system(@args) == 0 or exit 1;
-	print "\nStopping old cluster\n\n";
-	system("pg_ctl stop") == 0 or exit 1;
-	$ENV{PGDATA} = "$data";
-	print "\nSetting up new cluster\n\n";
-	standard_initdb() or exit 1;
-	print "\nRunning pg_upgrade\n\n";
-	@args = (
-		'pg_upgrade', '-d', "$data.old", '-D', $data, '-b', $bindir,
-		'--no-sync');
-	system(@args) == 0 or exit 1;
-	print "\nStarting new cluster\n\n";
-	@args = ('pg_ctl', '-l', "$logdir/postmaster2.log", 'start');
-	system(@args) == 0 or exit 1;
-	print "\nDumping new cluster\n\n";
-	@args = ('pg_dumpall', '-f', "$tmp_root/dump2.sql");
-	system(@args) == 0 or exit 1;
-	print "\nStopping new cluster\n\n";
-	system("pg_ctl stop") == 0 or exit 1;
-	print "\nDeleting old cluster\n\n";
-	system(".\\delete_old_cluster.bat") == 0 or exit 1;
-	print "\nComparing old and new cluster dumps\n\n";
-
-	@args = ('diff', '-q', "$tmp_root/dump1.sql", "$tmp_root/dump2.sql");
-	system(@args);
-	$status = $?;
-	if (!$status)
-	{
-		print "PASSED\n";
-	}
-	else
-	{
-		print "dumps not identical!\n";
-		exit(1);
-	}
+	InstallTemp();
+	# Tweak environment for the upgrade tests
+	$ENV{REGRESS_OUTPUTDIR} = "$topdir/src/bin/pg_upgrade";
+	my $mstat = tap_check("$topdir/src/bin/pg_upgrade");
+	exit $mstat if $mstat;
 	return;
 }
 
-- 
2.34.1



  [application/pgp-signature] signature.asc (833B, ../../[email protected]/3-signature.asc)
  download

^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* Re: Rewriting the test of pg_upgrade as a TAP test - take three - remastered set
@ 2022-01-11 07:14  Michael Paquier <[email protected]>
  parent: Michael Paquier <[email protected]>
  0 siblings, 1 reply; 7+ messages in thread

From: Michael Paquier @ 2022-01-11 07:14 UTC (permalink / raw)
  To: Andres Freund <[email protected]>; +Cc: Tom Lane <[email protected]>; Andrew Dunstan <[email protected]>; Postgres hackers <[email protected]>

On Wed, Jan 05, 2022 at 05:12:41PM +0900, Michael Paquier wrote:
> Rebased patch to cool down the CF bot, as per the addition of
> --no-sync to pg_upgrade.

The CF bot is unhappy, so here is a rebase, with some typo fixes
reported by Justin offlist.
--
Michael


Attachments:

  [text/x-diff] v6-0001-Switch-tests-of-pg_upgrade-to-use-TAP.patch (28.2K, ../../[email protected]/2-v6-0001-Switch-tests-of-pg_upgrade-to-use-TAP.patch)
  download | inline diff:
From 1d2dc68b8c27d9c328276ed21e57290f64bca586 Mon Sep 17 00:00:00 2001
From: Michael Paquier <[email protected]>
Date: Tue, 11 Jan 2022 16:13:02 +0900
Subject: [PATCH v6] Switch tests of pg_upgrade to use TAP

---
 src/bin/pg_upgrade/.gitignore            |   5 +
 src/bin/pg_upgrade/Makefile              |  23 +-
 src/bin/pg_upgrade/TESTING               |  33 ++-
 src/bin/pg_upgrade/t/001_basic.pl        |   9 +
 src/bin/pg_upgrade/t/002_pg_upgrade.pl   | 275 ++++++++++++++++++++++
 src/bin/pg_upgrade/test.sh               | 279 -----------------------
 src/test/perl/PostgreSQL/Test/Cluster.pm |  25 ++
 src/tools/msvc/vcregress.pl              |  94 +-------
 8 files changed, 355 insertions(+), 388 deletions(-)
 create mode 100644 src/bin/pg_upgrade/t/001_basic.pl
 create mode 100644 src/bin/pg_upgrade/t/002_pg_upgrade.pl
 delete mode 100644 src/bin/pg_upgrade/test.sh

diff --git a/src/bin/pg_upgrade/.gitignore b/src/bin/pg_upgrade/.gitignore
index 2d3bfeaa50..3b64522ab6 100644
--- a/src/bin/pg_upgrade/.gitignore
+++ b/src/bin/pg_upgrade/.gitignore
@@ -7,3 +7,8 @@
 /loadable_libraries.txt
 /log/
 /tmp_check/
+
+# Generated by pg_regress
+/sql/
+/expected/
+/results/
diff --git a/src/bin/pg_upgrade/Makefile b/src/bin/pg_upgrade/Makefile
index 44d06be5a6..35b6c123a5 100644
--- a/src/bin/pg_upgrade/Makefile
+++ b/src/bin/pg_upgrade/Makefile
@@ -28,6 +28,12 @@ OBJS = \
 override CPPFLAGS := -DDLSUFFIX=\"$(DLSUFFIX)\" -I$(srcdir) -I$(libpq_srcdir) $(CPPFLAGS)
 LDFLAGS_INTERNAL += -L$(top_builddir)/src/fe_utils -lpgfeutils $(libpq_pgport)
 
+# required for 002_pg_upgrade.pl
+REGRESS_SHLIB=$(abs_top_builddir)/src/test/regress/regress$(DLSUFFIX)
+export REGRESS_SHLIB
+REGRESS_OUTPUTDIR=$(abs_top_builddir)/src/bin/pg_upgrade
+export REGRESS_OUTPUTDIR
+
 all: pg_upgrade
 
 pg_upgrade: $(OBJS) | submake-libpq submake-libpgport submake-libpgfeutils
@@ -49,17 +55,8 @@ clean distclean maintainer-clean:
 	       pg_upgrade_dump_globals.sql \
 	       pg_upgrade_dump_*.custom pg_upgrade_*.log
 
-# When $(MAKE) is present, make automatically infers that this is a
-# recursive make. which is not actually what we want here, as that
-# e.g. prevents output synchronization from working (as make thinks
-# that the subsidiary make knows how to deal with that itself, but
-# we're invoking a shell script that doesn't know). Referencing
-# $(MAKE) indirectly avoids that behaviour.
-# See https://www.gnu.org/software/make/manual/html_node/MAKE-Variable.html#MAKE-Variable
-NOTSUBMAKEMAKE=$(MAKE)
+check:
+	$(prove_check)
 
-check: test.sh all temp-install
-	MAKE=$(NOTSUBMAKEMAKE) $(with_temp_install) bindir=$(abs_top_builddir)/tmp_install/$(bindir) EXTRA_REGRESS_OPTS="$(EXTRA_REGRESS_OPTS)" $(SHELL) $<
-
-# installcheck is not supported because there's no meaningful way to test
-# pg_upgrade against a single already-running server
+installcheck:
+	$(prove_installcheck)
diff --git a/src/bin/pg_upgrade/TESTING b/src/bin/pg_upgrade/TESTING
index 78b9747908..43a71566e2 100644
--- a/src/bin/pg_upgrade/TESTING
+++ b/src/bin/pg_upgrade/TESTING
@@ -2,21 +2,30 @@ THE SHORT VERSION
 -----------------
 
 On non-Windows machines, you can execute the testing process
-described below by running
+described below by running the following command in this directory:
 	make check
-in this directory.  This will run the shell script test.sh, performing
-an upgrade from the version in this source tree to a new instance of
-the same version.
 
-To test an upgrade from a different version, you must have a built
-source tree for the old version as well as this version, and you
-must have done "make install" for both versions.  Then do:
+This will run the TAP tests to run pg_upgrade, performing an upgrade
+from the version in this source tree to a  new instance of the same
+version.
+
+To test an upgrade from a different version, there are two options
+available:
+
+1) You have a built source tree for the old version as well as this
+version's binaries.  Then set up the following variables before
+launching the test:
 
 export oldsrc=...somewhere/postgresql	(old version's source tree)
-export oldbindir=...otherversion/bin	(old version's installed bin dir)
-export bindir=...thisversion/bin	(this version's installed bin dir)
-export libdir=...thisversion/lib	(this version's installed lib dir)
-sh test.sh
+export oldinstall=...otherversion/	(old version's install base path)
+
+2) You have a dump that can be used to set up the old version, as well
+as this version's binaries.  Then set up the following variables:
+export olddump=...somewhere/dump.sql	(old version's dump)
+export oldinstall=...otherversion/	(old version's install base path)
+
+Finally, the tests can be done by running
+	make check
 
 In this case, you will have to manually eyeball the resulting dump
 diff for version-specific differences, as explained below.
@@ -77,3 +86,5 @@ steps:
 
 7)  Diff the regression database dump file with the regression dump
     file loaded into the old server.
+
+The generated dump may be reusable with "olddump", as defined above.
diff --git a/src/bin/pg_upgrade/t/001_basic.pl b/src/bin/pg_upgrade/t/001_basic.pl
new file mode 100644
index 0000000000..75b0f98b08
--- /dev/null
+++ b/src/bin/pg_upgrade/t/001_basic.pl
@@ -0,0 +1,9 @@
+use strict;
+use warnings;
+
+use PostgreSQL::Test::Utils;
+use Test::More tests => 8;
+
+program_help_ok('pg_upgrade');
+program_version_ok('pg_upgrade');
+program_options_handling_ok('pg_upgrade');
diff --git a/src/bin/pg_upgrade/t/002_pg_upgrade.pl b/src/bin/pg_upgrade/t/002_pg_upgrade.pl
new file mode 100644
index 0000000000..e66879c6ea
--- /dev/null
+++ b/src/bin/pg_upgrade/t/002_pg_upgrade.pl
@@ -0,0 +1,275 @@
+# Set of tests for pg_upgrade, including cross-version checks.
+use strict;
+use warnings;
+
+use Cwd qw(abs_path getcwd);
+use File::Basename qw(dirname);
+
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More tests => 4;
+
+# Generate a database with a name made of a range of ASCII characters.
+sub generate_db
+{
+	my ($node, $from_char, $to_char) = @_;
+
+	my $dbname = '';
+	for my $i ($from_char .. $to_char)
+	{
+		next if $i == 7 || $i == 10 || $i == 13;    # skip BEL, LF, and CR
+		$dbname = $dbname . sprintf('%c', $i);
+	}
+	$node->run_log([ 'createdb', '--port', $node->port, $dbname ]);
+}
+
+# From now on, the test of pg_upgrade consists in setting up an instance.
+# This is the source instance used for the upgrade. Then a new and fresh
+# instance is created, and is used as the target instance for the
+# upgrade.  Before running an upgrade, a logical dump of the old instance
+# is taken, and a second logical dump of the new instance is taken after
+# the upgrade.  The upgrade test passes if there are no differences after
+# running pg_upgrade.
+
+# Testing upgrades with an older instance of PostgreSQL requires
+# setting up two environment variables, among the following:
+# - "oldsrc", to point to the code source of the older version.
+#   This is required to set up the old instance with pg_upgrade.
+# - "olddump", to point to a dump file that will be used to set
+#   up the old instance to upgrade from.
+# - "oldinstall", to point to the installation path of the older
+# version.
+
+# "oldsrc" and "olddump" cannot be used together.  Setting up
+# "olddump" and "oldinstall" will use the dump pointed to to
+# set up the old instance.  If "oldsrc" is used instead of "olddump",
+# the full set of regression tests of the old instance is run
+# instead.
+
+if (defined($ENV{oldsrc}) && defined($ENV{olddump}))
+{
+	die "oldsrc and olddump are both defined";
+}
+elsif (defined($ENV{oldsrc}))
+{
+	if (   (defined($ENV{oldsrc}) && !defined($ENV{oldinstall}))
+		|| (!defined($ENV{oldsrc}) && defined($ENV{oldinstall})))
+	{
+		# Not all variables are defined, so leave and die if test is
+		# done with an older installation.
+		die "oldsrc or oldinstall is undefined";
+	}
+}
+elsif (defined($ENV{olddump}))
+{
+	if (   (defined($ENV{olddump}) && !defined($ENV{oldinstall}))
+		|| (!defined($ENV{olddump}) && defined($ENV{oldinstall})))
+	{
+		# Not all variables are defined, so leave and die if test is
+		# done with an older installation.
+		die "olddump or oldinstall is undefined";
+	}
+}
+
+if ((defined($ENV{oldsrc}) || defined($ENV{olddump})) && $windows_os)
+{
+	# This configuration is not supported on Windows, as regress.so
+	# location diverges across the compilation methods used on this
+	# platform.
+	die "No support for older version tests on Windows";
+}
+
+# Default is the location of this source code for both nodes used with
+# the upgrade.
+my $newsrc = abs_path("../../..");
+my $oldsrc = $ENV{oldsrc} || $newsrc;
+$oldsrc = abs_path($oldsrc);
+
+# Temporary location for the dumps taken
+my $tempdir = PostgreSQL::Test::Utils::tempdir;
+
+# Initialize node to upgrade
+my $oldnode = PostgreSQL::Test::Cluster->new('old_node',
+	install_path => $ENV{oldinstall});
+
+$oldnode->init(extra => [ '--locale', 'C', '--encoding', 'LATIN1' ]);
+$oldnode->start;
+
+# Set up the data of the old instance with pg_regress or an old dump.
+if (defined($ENV{olddump}))
+{
+	# Use the dump specified.
+	my $olddumpfile = $ENV{olddump};
+	die "no dump file found!" unless -e $olddumpfile;
+
+	# Load the dump, and we are done here.
+	$oldnode->command_ok(
+		[
+			'psql',   '-X',           '-f', $olddumpfile,
+			'--port', $oldnode->port, 'regression'
+		]);
+}
+else
+{
+	# Default is to just use pg_regress to set up the old instance
+	# Creating databases with names covering most ASCII bytes
+	generate_db($oldnode, 1,  45);
+	generate_db($oldnode, 46, 90);
+	generate_db($oldnode, 91, 127);
+
+	# Run core regression tests on the old instance.
+	$oldnode->run_log([ "createdb", '--port', $oldnode->port, 'regression' ]);
+
+	# Grab any regression options that may be passed down by caller.
+	my $extra_opts_val = $ENV{EXTRA_REGRESS_OPT} || "";
+	my @extra_opts     = split(/\s+/, $extra_opts_val);
+
+	# --dlpath is needed to be able to find the location of regress.so and
+	# any libraries the regression tests required.  This needs to point to
+	# the old instance when using it.  In the default case, fallback to
+	# what the caller provided for REGRESS_SHLIB.
+	my $dlpath;
+	if (defined($ENV{oldinstall}))
+	{
+		$dlpath = "$oldsrc/src/test/regress";
+	}
+	else
+	{
+		$dlpath = dirname($ENV{REGRESS_SHLIB});
+	}
+	$dlpath = PostgreSQL::Test::Utils::perl2host($dlpath);
+
+	# --outputdir points to the path where to place the output files, which
+	# had better be this directory.
+	my $outputdir =
+	  PostgreSQL::Test::Utils::perl2host($ENV{REGRESS_OUTPUTDIR});
+
+	# --inputdir needs to point to the location of the input files, from the
+	# cluster to-be-upgraded.
+	my $inputdir =
+	  PostgreSQL::Test::Utils::perl2host("$oldsrc/src/test/regress");
+
+	my @regress_command = [
+		$ENV{PG_REGRESS}, '--make-testtablespace-dir',
+		'--schedule',     "$oldsrc/src/test/regress/parallel_schedule",
+		'--bindir',       $oldnode->config_data('--bindir'),
+		'--dlpath',       $dlpath,
+		'--port',         $oldnode->port,
+		'--outputdir',    $outputdir,
+		'--inputdir',     $inputdir,
+		'--use-existing'
+	];
+	@regress_command = (@regress_command, @extra_opts);
+
+	$oldnode->command_ok(@regress_command,
+		'regression test run on old instance');
+}
+
+# Before dumping, get rid of objects not existing or not supported in later
+# versions. This depends on the version of the old server used, and matters
+# only if different versions are used for the dump.
+if (defined($ENV{oldinstall}))
+{
+	# Note that upgrade_adapt.sql from the new version is used, to
+	# cope with an upgrade to this version.
+	$oldnode->run_log(
+		[
+			'psql', '-X', '-f',
+			PostgreSQL::Test::Utils::perl2host(
+				"$newsrc/src/bin/pg_upgrade/upgrade_adapt.sql"),
+			'--port',
+			$oldnode->port,
+			'regression'
+		]);
+}
+
+# Initialize a new node for the upgrade.  This is done early so as it is
+# possible to know with which node's PATH the initial dump needs to be
+# taken.
+my $newnode = PostgreSQL::Test::Cluster->new('new_node');
+$newnode->init(extra => [ '--locale=C', '--encoding=LATIN1' ]);
+my $newbindir = $newnode->config_data('--bindir');
+my $oldbindir = $oldnode->config_data('--bindir');
+
+# Take a dump before performing the upgrade as a base comparison. Note
+# that we need to use pg_dumpall from the new node here.
+$newnode->command_ok(
+	[
+		'pg_dumpall', '--no-sync',
+		'-d',         $oldnode->connstr('postgres'),
+		'-f',         "$tempdir/dump1.sql"
+	],
+	'dump before running pg_upgrade');
+
+# After dumping, update references to the old source tree's regress.so
+# to point to the new tree.
+if (defined($ENV{oldinstall}))
+{
+	# First, fetch all the references to libraries that are not part
+	# of the default path $libdir.
+	my $output = $oldnode->safe_psql('regression',
+		"SELECT DISTINCT probin::text FROM pg_proc WHERE probin NOT LIKE '\$libdir%';"
+	);
+	chomp($output);
+	my @libpaths = split("\n", $output);
+
+	my $dump_data = slurp_file("$tempdir/dump1.sql");
+
+	my $newregresssrc = "$newsrc/src/test/regress";
+	foreach (@libpaths)
+	{
+		my $libpath = $_;
+		$libpath = dirname($libpath);
+		$dump_data =~ s/$libpath/$newregresssrc/g;
+	}
+
+	open my $fh, ">", "$tempdir/dump1.sql" or die "could not open dump file";
+	print $fh $dump_data;
+	close $fh;
+
+	# This replaces any references to the old tree's regress.so
+	# the new tree's regress.so.  Any references that do *not*
+	# match $libdir are switched so as this request does not
+	# depend on the path of the old source tree.  This is useful
+	# when using an old dump.  Do the operation on all the databases
+	# that allow connections so as this includes the regression
+	# database and anything the user has set up.
+	$output = $oldnode->safe_psql('postgres',
+		"SELECT datname FROM pg_database WHERE datallowconn;");
+	chomp($output);
+	my @datnames = split("\n", $output);
+	foreach (@datnames)
+	{
+		my $datname = $_;
+		$oldnode->safe_psql(
+			$datname, "UPDATE pg_proc SET probin =
+		  regexp_replace(probin, '.*/', '$newregresssrc/')
+		  WHERE probin NOT LIKE '\$libdir/%'");
+	}
+}
+
+# Update the instance.
+$oldnode->stop;
+
+# Time for the real run.
+$newnode->command_ok(
+	[
+		'pg_upgrade', '--no-sync',        '-d', $oldnode->data_dir,
+		'-D',         $newnode->data_dir, '-b', $oldbindir,
+		'-B',         $newbindir,         '-p', $oldnode->port,
+		'-P',         $newnode->port,
+	],
+	'run of pg_upgrade for new instance');
+$newnode->start;
+
+# Take a second dump on the upgraded instance.
+$newnode->run_log(
+	[
+		'pg_dumpall', '--no-sync',
+		'-d',         $newnode->connstr('postgres'),
+		'-f',         "$tempdir/dump2.sql"
+	]);
+
+# Compare the two dumps, there should be no differences.
+command_ok([ 'diff', '-q', "$tempdir/dump1.sql", "$tempdir/dump2.sql" ],
+	'old and new dump match after pg_upgrade');
diff --git a/src/bin/pg_upgrade/test.sh b/src/bin/pg_upgrade/test.sh
deleted file mode 100644
index ef328b3062..0000000000
--- a/src/bin/pg_upgrade/test.sh
+++ /dev/null
@@ -1,279 +0,0 @@
-#!/bin/sh
-
-# src/bin/pg_upgrade/test.sh
-#
-# Test driver for pg_upgrade.  Initializes a new database cluster,
-# runs the regression tests (to put in some data), runs pg_dumpall,
-# runs pg_upgrade, runs pg_dumpall again, compares the dumps.
-#
-# Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
-# Portions Copyright (c) 1994, Regents of the University of California
-
-set -e
-
-: ${MAKE=make}
-
-# Guard against parallel make issues (see comments in pg_regress.c)
-unset MAKEFLAGS
-unset MAKELEVEL
-
-# Run a given "initdb" binary and overlay the regression testing
-# authentication configuration.
-standard_initdb() {
-	# To increase coverage of non-standard segment size and group access
-	# without increasing test runtime, run these tests with a custom setting.
-	# Also, specify "-A trust" explicitly to suppress initdb's warning.
-	# --allow-group-access and --wal-segsize have been added in v11.
-	"$1" -N --wal-segsize 1 --allow-group-access -A trust
-	if [ -n "$TEMP_CONFIG" -a -r "$TEMP_CONFIG" ]
-	then
-		cat "$TEMP_CONFIG" >> "$PGDATA/postgresql.conf"
-	fi
-	../../test/regress/pg_regress --config-auth "$PGDATA"
-}
-
-# What flavor of host are we on?
-# Treat MINGW* (msys1) and MSYS* (msys2) the same.
-testhost=`uname -s | sed 's/^MSYS/MINGW/'`
-
-# Establish how the server will listen for connections
-case $testhost in
-	MINGW*)
-		LISTEN_ADDRESSES="localhost"
-		PG_REGRESS_SOCKET_DIR=""
-		PGHOST=localhost
-		;;
-	*)
-		LISTEN_ADDRESSES=""
-		# Select a socket directory.  The algorithm is from the "configure"
-		# script; the outcome mimics pg_regress.c:make_temp_sockdir().
-		if [ x"$PG_REGRESS_SOCKET_DIR" = x ]; then
-			set +e
-			dir=`(umask 077 &&
-				  mktemp -d /tmp/pg_upgrade_check-XXXXXX) 2>/dev/null`
-			if [ ! -d "$dir" ]; then
-				dir=/tmp/pg_upgrade_check-$$-$RANDOM
-				(umask 077 && mkdir "$dir")
-				if [ ! -d "$dir" ]; then
-					echo "could not create socket temporary directory in \"/tmp\""
-					exit 1
-				fi
-			fi
-			set -e
-			PG_REGRESS_SOCKET_DIR=$dir
-			trap 'rm -rf "$PG_REGRESS_SOCKET_DIR"' 0
-			trap 'exit 3' 1 2 13 15
-		fi
-		PGHOST=$PG_REGRESS_SOCKET_DIR
-		;;
-esac
-
-POSTMASTER_OPTS="-F -c listen_addresses=\"$LISTEN_ADDRESSES\" -k \"$PG_REGRESS_SOCKET_DIR\""
-export PGHOST
-
-# don't rely on $PWD here, as old shells don't set it
-temp_root=`pwd`/tmp_check
-rm -rf "$temp_root"
-mkdir "$temp_root"
-
-: ${oldbindir=$bindir}
-
-: ${oldsrc=../../..}
-oldsrc=`cd "$oldsrc" && pwd`
-newsrc=`cd ../../.. && pwd`
-
-# We need to make pg_regress use psql from the desired installation
-# (likely a temporary one), because otherwise the installcheck run
-# below would try to use psql from the proper installation directory
-# of the target version, which might be outdated or not exist. But
-# don't override anything else that's already in EXTRA_REGRESS_OPTS.
-EXTRA_REGRESS_OPTS="$EXTRA_REGRESS_OPTS --bindir='$oldbindir'"
-export EXTRA_REGRESS_OPTS
-
-# While in normal cases this will already be set up, adding bindir to
-# path allows test.sh to be invoked with different versions as
-# described in ./TESTING
-PATH=$bindir:$PATH
-export PATH
-
-BASE_PGDATA="$temp_root/data"
-PGDATA="${BASE_PGDATA}.old"
-export PGDATA
-
-# Send installcheck outputs to a private directory.  This avoids conflict when
-# check-world runs pg_upgrade check concurrently with src/test/regress check.
-# To retrieve interesting files after a run, use pattern tmp_check/*/*.diffs.
-outputdir="$temp_root/regress"
-EXTRA_REGRESS_OPTS="$EXTRA_REGRESS_OPTS --outputdir=$outputdir"
-export EXTRA_REGRESS_OPTS
-mkdir "$outputdir"
-
-# pg_regress --make-tablespacedir would take care of that in 14~, but this is
-# still required for older versions where this option is not supported.
-if [ "$newsrc" != "$oldsrc" ]; then
-	mkdir "$outputdir"/testtablespace
-	mkdir "$outputdir"/sql
-	mkdir "$outputdir"/expected
-fi
-
-logdir=`pwd`/log
-rm -rf "$logdir"
-mkdir "$logdir"
-
-# Clear out any environment vars that might cause libpq to connect to
-# the wrong postmaster (cf pg_regress.c)
-#
-# Some shells, such as NetBSD's, return non-zero from unset if the variable
-# is already unset. Since we are operating under 'set -e', this causes the
-# script to fail. To guard against this, set them all to an empty string first.
-PGDATABASE="";        unset PGDATABASE
-PGUSER="";            unset PGUSER
-PGSERVICE="";         unset PGSERVICE
-PGSSLMODE="";         unset PGSSLMODE
-PGREQUIRESSL="";      unset PGREQUIRESSL
-PGCONNECT_TIMEOUT=""; unset PGCONNECT_TIMEOUT
-PGHOSTADDR="";        unset PGHOSTADDR
-
-# Select a non-conflicting port number, similarly to pg_regress.c
-PG_VERSION_NUM=`grep '#define PG_VERSION_NUM' "$newsrc"/src/include/pg_config.h | awk '{print $3}'`
-PGPORT=`expr $PG_VERSION_NUM % 16384 + 49152`
-export PGPORT
-
-i=0
-while psql -X postgres </dev/null 2>/dev/null
-do
-	i=`expr $i + 1`
-	if [ $i -eq 16 ]
-	then
-		echo port $PGPORT apparently in use
-		exit 1
-	fi
-	PGPORT=`expr $PGPORT + 1`
-	export PGPORT
-done
-
-# buildfarm may try to override port via EXTRA_REGRESS_OPTS ...
-EXTRA_REGRESS_OPTS="$EXTRA_REGRESS_OPTS --port=$PGPORT"
-export EXTRA_REGRESS_OPTS
-
-standard_initdb "$oldbindir"/initdb
-"$oldbindir"/pg_ctl start -l "$logdir/postmaster1.log" -o "$POSTMASTER_OPTS" -w
-
-# Create databases with names covering the ASCII bytes other than NUL, BEL,
-# LF, or CR.  BEL would ring the terminal bell in the course of this test, and
-# it is not otherwise a special case.  PostgreSQL doesn't support the rest.
-dbname1=`awk 'BEGIN { for (i= 1; i < 46; i++)
-	if (i != 7 && i != 10 && i != 13) printf "%c", i }' </dev/null`
-# Exercise backslashes adjacent to double quotes, a Windows special case.
-dbname1='\"\'$dbname1'\\"\\\'
-dbname2=`awk 'BEGIN { for (i = 46; i <  91; i++) printf "%c", i }' </dev/null`
-dbname3=`awk 'BEGIN { for (i = 91; i < 128; i++) printf "%c", i }' </dev/null`
-createdb "regression$dbname1" || createdb_status=$?
-createdb "regression$dbname2" || createdb_status=$?
-createdb "regression$dbname3" || createdb_status=$?
-
-# Extra options to apply to the dump.  This may be changed later.
-extra_dump_options=""
-
-if "$MAKE" -C "$oldsrc" installcheck-parallel; then
-	oldpgversion=`psql -X -A -t -d regression -c "SHOW server_version_num"`
-
-	# Before dumping, tweak the database of the old instance depending
-	# on its version.
-	if [ "$newsrc" != "$oldsrc" ]; then
-		# This SQL script has its own idea of the cleanup that needs to be
-		# done on the cluster to-be-upgraded, and includes version checks.
-		# Note that this uses the script stored on the new branch.
-		psql -X -d regression -f "$newsrc/src/bin/pg_upgrade/upgrade_adapt.sql" \
-			|| psql_fix_sql_status=$?
-
-		# Handling of --extra-float-digits gets messy after v12.
-		# Note that this changes the dumps from the old and new
-		# instances if involving an old cluster of v11 or older.
-		if [ $oldpgversion -lt 120000 ]; then
-			extra_dump_options="--extra-float-digits=0"
-		fi
-	fi
-
-	pg_dumpall $extra_dump_options --no-sync \
-		-f "$temp_root"/dump1.sql || pg_dumpall1_status=$?
-
-	if [ "$newsrc" != "$oldsrc" ]; then
-		# update references to old source tree's regress.so etc
-		fix_sql=""
-		case $oldpgversion in
-			*)
-				fix_sql="UPDATE pg_proc SET probin = replace(probin, '$oldsrc', '$newsrc') WHERE probin LIKE '$oldsrc%';"
-				;;
-		esac
-		psql -X -d regression -c "$fix_sql;" || psql_fix_sql_status=$?
-
-		mv "$temp_root"/dump1.sql "$temp_root"/dump1.sql.orig
-		sed "s;$oldsrc;$newsrc;g" "$temp_root"/dump1.sql.orig >"$temp_root"/dump1.sql
-	fi
-else
-	make_installcheck_status=$?
-fi
-"$oldbindir"/pg_ctl -m fast stop
-if [ -n "$createdb_status" ]; then
-	exit 1
-fi
-if [ -n "$make_installcheck_status" ]; then
-	exit 1
-fi
-if [ -n "$psql_fix_sql_status" ]; then
-	exit 1
-fi
-if [ -n "$pg_dumpall1_status" ]; then
-	echo "pg_dumpall of pre-upgrade database cluster failed"
-	exit 1
-fi
-
-PGDATA="$BASE_PGDATA"
-
-standard_initdb 'initdb'
-
-pg_upgrade $PG_UPGRADE_OPTS --no-sync -d "${PGDATA}.old" -D "$PGDATA" -b "$oldbindir" -p "$PGPORT" -P "$PGPORT"
-
-# make sure all directories and files have group permissions, on Unix hosts
-# Windows hosts don't support Unix-y permissions.
-case $testhost in
-	MINGW*|CYGWIN*) ;;
-	*)	if [ `find "$PGDATA" -type f ! -perm 640 | wc -l` -ne 0 ]; then
-			echo "files in PGDATA with permission != 640";
-			exit 1;
-		fi ;;
-esac
-
-case $testhost in
-	MINGW*|CYGWIN*) ;;
-	*)	if [ `find "$PGDATA" -type d ! -perm 750 | wc -l` -ne 0 ]; then
-			echo "directories in PGDATA with permission != 750";
-			exit 1;
-		fi ;;
-esac
-
-pg_ctl start -l "$logdir/postmaster2.log" -o "$POSTMASTER_OPTS" -w
-
-pg_dumpall $extra_dump_options --no-sync \
-	-f "$temp_root"/dump2.sql || pg_dumpall2_status=$?
-pg_ctl -m fast stop
-
-if [ -n "$pg_dumpall2_status" ]; then
-	echo "pg_dumpall of post-upgrade database cluster failed"
-	exit 1
-fi
-
-case $testhost in
-	MINGW*)	MSYS2_ARG_CONV_EXCL=/c cmd /c delete_old_cluster.bat ;;
-	*)	    sh ./delete_old_cluster.sh ;;
-esac
-
-if diff "$temp_root"/dump1.sql "$temp_root"/dump2.sql >/dev/null; then
-	echo PASSED
-	exit 0
-else
-	echo "Files $temp_root/dump1.sql and $temp_root/dump2.sql differ"
-	echo "dumps were not identical"
-	exit 1
-fi
diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm
index e18f27276c..541b4b6b98 100644
--- a/src/test/perl/PostgreSQL/Test/Cluster.pm
+++ b/src/test/perl/PostgreSQL/Test/Cluster.pm
@@ -327,6 +327,31 @@ sub install_path
 
 =pod
 
+=item $node->config_data($option)
+
+Grab some data from pg_config, with $option being the command switch
+used.
+
+=cut
+
+sub config_data
+{
+	my ($self, $option) = @_;
+	local %ENV = $self->_get_env();
+
+	my ($stdout, $stderr);
+	my $result =
+	  IPC::Run::run [ $self->installed_command('pg_config'), $option ],
+	  '>', \$stdout, '2>', \$stderr
+	  or die "could not execute pg_config";
+	chomp($stdout);
+	$stdout =~ s/\r$//;
+
+	return $stdout;
+}
+
+=pod
+
 =item $node->info()
 
 Return a string containing human-readable diagnostic information (paths, etc)
diff --git a/src/tools/msvc/vcregress.pl b/src/tools/msvc/vcregress.pl
index 7575acdfdf..b5c276fc7c 100644
--- a/src/tools/msvc/vcregress.pl
+++ b/src/tools/msvc/vcregress.pl
@@ -287,6 +287,10 @@ sub bincheck
 	foreach my $dir (@bin_dirs)
 	{
 		next unless -d "$dir/t";
+		# Do not consider pg_upgrade, as it is handled by
+		# upgradecheck.
+		next if ($dir =~ "/pg_upgrade/");
+
 		my $status = tap_check($dir);
 		$mstat ||= $status;
 	}
@@ -592,91 +596,11 @@ sub generate_db
 
 sub upgradecheck
 {
-	my $status;
-	my $cwd = getcwd();
-
-	# Much of this comes from the pg_upgrade test.sh script,
-	# but it only covers the --install case, and not the case
-	# where the old and new source or bin dirs are different.
-	# i.e. only this version to this version check. That's
-	# what pg_upgrade's "make check" does.
-
-	$ENV{PGHOST} = 'localhost';
-	$ENV{PGPORT} ||= 50432;
-	my $tmp_root = "$topdir/src/bin/pg_upgrade/tmp_check";
-	rmtree($tmp_root);
-	mkdir $tmp_root || die $!;
-	my $upg_tmp_install = "$tmp_root/install";    # unshared temp install
-	print "Setting up temp install\n\n";
-	Install($upg_tmp_install, "all", $config);
-
-	# Install does a chdir, so change back after that
-	chdir $cwd;
-	my ($bindir, $libdir, $oldsrc, $newsrc) =
-	  ("$upg_tmp_install/bin", "$upg_tmp_install/lib", $topdir, $topdir);
-	$ENV{PATH} = "$bindir;$ENV{PATH}";
-	my $data = "$tmp_root/data";
-	$ENV{PGDATA} = "$data.old";
-	my $outputdir          = "$tmp_root/regress";
-	my @EXTRA_REGRESS_OPTS = ("--outputdir=$outputdir");
-	mkdir "$outputdir" || die $!;
-
-	my $logdir = "$topdir/src/bin/pg_upgrade/log";
-	rmtree($logdir);
-	mkdir $logdir || die $!;
-	print "\nRunning initdb on old cluster\n\n";
-	standard_initdb() or exit 1;
-	print "\nStarting old cluster\n\n";
-	my @args = ('pg_ctl', 'start', '-l', "$logdir/postmaster1.log");
-	system(@args) == 0 or exit 1;
-
-	print "\nCreating databases with names covering most ASCII bytes\n\n";
-	generate_db("\\\"\\", 1,  45,  "\\\\\"\\\\\\");
-	generate_db('',       46, 90,  '');
-	generate_db('',       91, 127, '');
-
-	print "\nSetting up data for upgrading\n\n";
-	installcheck_internal('parallel', @EXTRA_REGRESS_OPTS);
-
-	# now we can chdir into the source dir
-	chdir "$topdir/src/bin/pg_upgrade";
-	print "\nDumping old cluster\n\n";
-	@args = ('pg_dumpall', '-f', "$tmp_root/dump1.sql");
-	system(@args) == 0 or exit 1;
-	print "\nStopping old cluster\n\n";
-	system("pg_ctl stop") == 0 or exit 1;
-	$ENV{PGDATA} = "$data";
-	print "\nSetting up new cluster\n\n";
-	standard_initdb() or exit 1;
-	print "\nRunning pg_upgrade\n\n";
-	@args = (
-		'pg_upgrade', '-d', "$data.old", '-D', $data, '-b', $bindir,
-		'--no-sync');
-	system(@args) == 0 or exit 1;
-	print "\nStarting new cluster\n\n";
-	@args = ('pg_ctl', '-l', "$logdir/postmaster2.log", 'start');
-	system(@args) == 0 or exit 1;
-	print "\nDumping new cluster\n\n";
-	@args = ('pg_dumpall', '-f', "$tmp_root/dump2.sql");
-	system(@args) == 0 or exit 1;
-	print "\nStopping new cluster\n\n";
-	system("pg_ctl stop") == 0 or exit 1;
-	print "\nDeleting old cluster\n\n";
-	system(".\\delete_old_cluster.bat") == 0 or exit 1;
-	print "\nComparing old and new cluster dumps\n\n";
-
-	@args = ('diff', '-q', "$tmp_root/dump1.sql", "$tmp_root/dump2.sql");
-	system(@args);
-	$status = $?;
-	if (!$status)
-	{
-		print "PASSED\n";
-	}
-	else
-	{
-		print "dumps not identical!\n";
-		exit(1);
-	}
+	InstallTemp();
+	# Tweak environment for the upgrade tests
+	$ENV{REGRESS_OUTPUTDIR} = "$topdir/src/bin/pg_upgrade";
+	my $mstat = tap_check("$topdir/src/bin/pg_upgrade");
+	exit $mstat if $mstat;
 	return;
 }
 
-- 
2.34.1



  [application/pgp-signature] signature.asc (833B, ../../[email protected]/3-signature.asc)
  download

^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* Re: Rewriting the test of pg_upgrade as a TAP test - take three - remastered set
@ 2022-01-15 05:52  Julien Rouhaud <[email protected]>
  parent: Michael Paquier <[email protected]>
  0 siblings, 1 reply; 7+ messages in thread

From: Julien Rouhaud @ 2022-01-15 05:52 UTC (permalink / raw)
  To: Michael Paquier <[email protected]>; +Cc: Andres Freund <[email protected]>; Tom Lane <[email protected]>; Andrew Dunstan <[email protected]>; Postgres hackers <[email protected]>

Hi,

On Tue, Jan 11, 2022 at 04:14:25PM +0900, Michael Paquier wrote:
> The CF bot is unhappy, so here is a rebase, with some typo fixes
> reported by Justin offlist.

The cfbot still complains about this patch on Windows:
https://cirrus-ci.com/task/6411385683836928
https://api.cirrus-ci.com/v1/artifact/task/6411385683836928/tap/src/bin/pg_upgrade/tmp_check/log/reg...

# Running: pg_upgrade --no-sync -d c:/cirrus/src/bin/pg_upgrade/tmp_check/t_002_pg_upgrade_old_node_data/pgdata -D c:/cirrus/src/bin/pg_upgrade/tmp_check/t_002_pg_upgrade_new_node_data/pgdata -b C:/cirrus/tmp_install/bin -B C:/cirrus/tmp_install/bin -p 56296 -P 56297

libpq environment variable PGHOST has a non-local server value: C:/Users/ContainerAdministrator/AppData/Local/Temp/FhBIlsw6SV
Failure, exiting
not ok 3 - run of pg_upgrade for new instance

#   Failed test 'run of pg_upgrade for new instance'
#   at t/002_pg_upgrade.pl line 255.
### Starting node "new_node"
# Running: pg_ctl -w -D c:/cirrus/src/bin/pg_upgrade/tmp_check/t_002_pg_upgrade_new_node_data/pgdata -l c:/cirrus/src/bin/pg_upgrade/tmp_check/log/002_pg_upgrade_new_node.log -o --cluster-name=new_node start
waiting for server to start.... done
server started
# Postmaster PID for node "new_node" is 5748
# Running: pg_dumpall --no-sync -d port=56297 host=C:/Users/ContainerAdministrator/AppData/Local/Temp/FhBIlsw6SV dbname='postgres' -f C:\cirrus\src\bin\pg_upgrade\tmp_check\tmp_test_X4aZ/dump2.sql
# Running: diff -q C:\cirrus\src\bin\pg_upgrade\tmp_check\tmp_test_X4aZ/dump1.sql C:\cirrus\src\bin\pg_upgrade\tmp_check\tmp_test_X4aZ/dump2.sql
Files C:\cirrus\src\bin\pg_upgrade\tmp_check\tmp_test_X4aZ/dump1.sql and C:\cirrus\src\bin\pg_upgrade\tmp_check\tmp_test_X4aZ/dump2.sql differ
not ok 4 - old and new dump match after pg_upgrade

#   Failed test 'old and new dump match after pg_upgrade'






^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* Re: Rewriting the test of pg_upgrade as a TAP test - take three - remastered set
@ 2022-01-18 02:20  Michael Paquier <[email protected]>
  parent: Julien Rouhaud <[email protected]>
  0 siblings, 1 reply; 7+ messages in thread

From: Michael Paquier @ 2022-01-18 02:20 UTC (permalink / raw)
  To: Julien Rouhaud <[email protected]>; +Cc: Andres Freund <[email protected]>; Tom Lane <[email protected]>; Andrew Dunstan <[email protected]>; Postgres hackers <[email protected]>

On Sat, Jan 15, 2022 at 01:52:39PM +0800, Julien Rouhaud wrote:
> libpq environment variable PGHOST has a non-local server value: C:/Users/ContainerAdministrator/AppData/Local/Temp/FhBIlsw6SV
> Failure, exiting
> not ok 3 - run of pg_upgrade for new instance

There are two things here, as far as I understand:
1) This is a valid Windows path.  So shouldn't we fix pg_upgrade's
server.c to be a bit more compliant with Windows paths?  The code
accepts only paths beginning with '/' as local paths, so this breaks.
2) It looks safer in the long run to disable completely PGHOST and
PGHOSTADDR when running the pg_upgrade command in the test, and we'd
better not use Cluster::command_ok() or we would fall down to each
node's local environment.  This could be done in the tests as of the
attached, I guess, and this would bypass the problem coming from 1).

The patch needed a refresh as --make-testtablespace-dir has been
removed as of d6d317d.
--
Michael


Attachments:

  [text/x-diff] v7-0001-Switch-tests-of-pg_upgrade-to-use-TAP.patch (28.6K, ../../YeYj4DU5qY%[email protected]/2-v7-0001-Switch-tests-of-pg_upgrade-to-use-TAP.patch)
  download | inline diff:
From 5b4c3f279781418aa4bc24689342b41926d681e4 Mon Sep 17 00:00:00 2001
From: Michael Paquier <[email protected]>
Date: Tue, 18 Jan 2022 11:13:09 +0900
Subject: [PATCH v7] Switch tests of pg_upgrade to use TAP

---
 src/bin/pg_upgrade/.gitignore            |   5 +
 src/bin/pg_upgrade/Makefile              |  23 +-
 src/bin/pg_upgrade/TESTING               |  33 ++-
 src/bin/pg_upgrade/t/001_basic.pl        |   9 +
 src/bin/pg_upgrade/t/002_pg_upgrade.pl   | 286 +++++++++++++++++++++++
 src/bin/pg_upgrade/test.sh               | 279 ----------------------
 src/test/perl/PostgreSQL/Test/Cluster.pm |  25 ++
 src/tools/msvc/vcregress.pl              |  94 +-------
 8 files changed, 366 insertions(+), 388 deletions(-)
 create mode 100644 src/bin/pg_upgrade/t/001_basic.pl
 create mode 100644 src/bin/pg_upgrade/t/002_pg_upgrade.pl
 delete mode 100644 src/bin/pg_upgrade/test.sh

diff --git a/src/bin/pg_upgrade/.gitignore b/src/bin/pg_upgrade/.gitignore
index 2d3bfeaa50..3b64522ab6 100644
--- a/src/bin/pg_upgrade/.gitignore
+++ b/src/bin/pg_upgrade/.gitignore
@@ -7,3 +7,8 @@
 /loadable_libraries.txt
 /log/
 /tmp_check/
+
+# Generated by pg_regress
+/sql/
+/expected/
+/results/
diff --git a/src/bin/pg_upgrade/Makefile b/src/bin/pg_upgrade/Makefile
index 44d06be5a6..35b6c123a5 100644
--- a/src/bin/pg_upgrade/Makefile
+++ b/src/bin/pg_upgrade/Makefile
@@ -28,6 +28,12 @@ OBJS = \
 override CPPFLAGS := -DDLSUFFIX=\"$(DLSUFFIX)\" -I$(srcdir) -I$(libpq_srcdir) $(CPPFLAGS)
 LDFLAGS_INTERNAL += -L$(top_builddir)/src/fe_utils -lpgfeutils $(libpq_pgport)
 
+# required for 002_pg_upgrade.pl
+REGRESS_SHLIB=$(abs_top_builddir)/src/test/regress/regress$(DLSUFFIX)
+export REGRESS_SHLIB
+REGRESS_OUTPUTDIR=$(abs_top_builddir)/src/bin/pg_upgrade
+export REGRESS_OUTPUTDIR
+
 all: pg_upgrade
 
 pg_upgrade: $(OBJS) | submake-libpq submake-libpgport submake-libpgfeutils
@@ -49,17 +55,8 @@ clean distclean maintainer-clean:
 	       pg_upgrade_dump_globals.sql \
 	       pg_upgrade_dump_*.custom pg_upgrade_*.log
 
-# When $(MAKE) is present, make automatically infers that this is a
-# recursive make. which is not actually what we want here, as that
-# e.g. prevents output synchronization from working (as make thinks
-# that the subsidiary make knows how to deal with that itself, but
-# we're invoking a shell script that doesn't know). Referencing
-# $(MAKE) indirectly avoids that behaviour.
-# See https://www.gnu.org/software/make/manual/html_node/MAKE-Variable.html#MAKE-Variable
-NOTSUBMAKEMAKE=$(MAKE)
+check:
+	$(prove_check)
 
-check: test.sh all temp-install
-	MAKE=$(NOTSUBMAKEMAKE) $(with_temp_install) bindir=$(abs_top_builddir)/tmp_install/$(bindir) EXTRA_REGRESS_OPTS="$(EXTRA_REGRESS_OPTS)" $(SHELL) $<
-
-# installcheck is not supported because there's no meaningful way to test
-# pg_upgrade against a single already-running server
+installcheck:
+	$(prove_installcheck)
diff --git a/src/bin/pg_upgrade/TESTING b/src/bin/pg_upgrade/TESTING
index 78b9747908..43a71566e2 100644
--- a/src/bin/pg_upgrade/TESTING
+++ b/src/bin/pg_upgrade/TESTING
@@ -2,21 +2,30 @@ THE SHORT VERSION
 -----------------
 
 On non-Windows machines, you can execute the testing process
-described below by running
+described below by running the following command in this directory:
 	make check
-in this directory.  This will run the shell script test.sh, performing
-an upgrade from the version in this source tree to a new instance of
-the same version.
 
-To test an upgrade from a different version, you must have a built
-source tree for the old version as well as this version, and you
-must have done "make install" for both versions.  Then do:
+This will run the TAP tests to run pg_upgrade, performing an upgrade
+from the version in this source tree to a  new instance of the same
+version.
+
+To test an upgrade from a different version, there are two options
+available:
+
+1) You have a built source tree for the old version as well as this
+version's binaries.  Then set up the following variables before
+launching the test:
 
 export oldsrc=...somewhere/postgresql	(old version's source tree)
-export oldbindir=...otherversion/bin	(old version's installed bin dir)
-export bindir=...thisversion/bin	(this version's installed bin dir)
-export libdir=...thisversion/lib	(this version's installed lib dir)
-sh test.sh
+export oldinstall=...otherversion/	(old version's install base path)
+
+2) You have a dump that can be used to set up the old version, as well
+as this version's binaries.  Then set up the following variables:
+export olddump=...somewhere/dump.sql	(old version's dump)
+export oldinstall=...otherversion/	(old version's install base path)
+
+Finally, the tests can be done by running
+	make check
 
 In this case, you will have to manually eyeball the resulting dump
 diff for version-specific differences, as explained below.
@@ -77,3 +86,5 @@ steps:
 
 7)  Diff the regression database dump file with the regression dump
     file loaded into the old server.
+
+The generated dump may be reusable with "olddump", as defined above.
diff --git a/src/bin/pg_upgrade/t/001_basic.pl b/src/bin/pg_upgrade/t/001_basic.pl
new file mode 100644
index 0000000000..75b0f98b08
--- /dev/null
+++ b/src/bin/pg_upgrade/t/001_basic.pl
@@ -0,0 +1,9 @@
+use strict;
+use warnings;
+
+use PostgreSQL::Test::Utils;
+use Test::More tests => 8;
+
+program_help_ok('pg_upgrade');
+program_version_ok('pg_upgrade');
+program_options_handling_ok('pg_upgrade');
diff --git a/src/bin/pg_upgrade/t/002_pg_upgrade.pl b/src/bin/pg_upgrade/t/002_pg_upgrade.pl
new file mode 100644
index 0000000000..fa8933095a
--- /dev/null
+++ b/src/bin/pg_upgrade/t/002_pg_upgrade.pl
@@ -0,0 +1,286 @@
+# Set of tests for pg_upgrade, including cross-version checks.
+use strict;
+use warnings;
+
+use Cwd qw(abs_path getcwd);
+use File::Basename qw(dirname);
+
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More tests => 4;
+
+# Generate a database with a name made of a range of ASCII characters.
+sub generate_db
+{
+	my ($node, $from_char, $to_char) = @_;
+
+	my $dbname = '';
+	for my $i ($from_char .. $to_char)
+	{
+		next if $i == 7 || $i == 10 || $i == 13;    # skip BEL, LF, and CR
+		$dbname = $dbname . sprintf('%c', $i);
+	}
+	$node->run_log([ 'createdb', '--port', $node->port, $dbname ]);
+}
+
+# From now on, the test of pg_upgrade consists in setting up an instance.
+# This is the source instance used for the upgrade. Then a new and fresh
+# instance is created, and is used as the target instance for the
+# upgrade.  Before running an upgrade, a logical dump of the old instance
+# is taken, and a second logical dump of the new instance is taken after
+# the upgrade.  The upgrade test passes if there are no differences after
+# running pg_upgrade.
+
+# Testing upgrades with an older instance of PostgreSQL requires
+# setting up two environment variables, among the following:
+# - "oldsrc", to point to the code source of the older version.
+#   This is required to set up the old instance with pg_upgrade.
+# - "olddump", to point to a dump file that will be used to set
+#   up the old instance to upgrade from.
+# - "oldinstall", to point to the installation path of the older
+# version.
+
+# "oldsrc" and "olddump" cannot be used together.  Setting up
+# "olddump" and "oldinstall" will use the dump pointed to to
+# set up the old instance.  If "oldsrc" is used instead of "olddump",
+# the full set of regression tests of the old instance is run
+# instead.
+
+if (defined($ENV{oldsrc}) && defined($ENV{olddump}))
+{
+	die "oldsrc and olddump are both defined";
+}
+elsif (defined($ENV{oldsrc}))
+{
+	if (   (defined($ENV{oldsrc}) && !defined($ENV{oldinstall}))
+		|| (!defined($ENV{oldsrc}) && defined($ENV{oldinstall})))
+	{
+		# Not all variables are defined, so leave and die if test is
+		# done with an older installation.
+		die "oldsrc or oldinstall is undefined";
+	}
+}
+elsif (defined($ENV{olddump}))
+{
+	if (   (defined($ENV{olddump}) && !defined($ENV{oldinstall}))
+		|| (!defined($ENV{olddump}) && defined($ENV{oldinstall})))
+	{
+		# Not all variables are defined, so leave and die if test is
+		# done with an older installation.
+		die "olddump or oldinstall is undefined";
+	}
+}
+
+if ((defined($ENV{oldsrc}) || defined($ENV{olddump})) && $windows_os)
+{
+	# This configuration is not supported on Windows, as regress.so
+	# location diverges across the compilation methods used on this
+	# platform.
+	die "No support for older version tests on Windows";
+}
+
+# Default is the location of this source code for both nodes used with
+# the upgrade.
+my $newsrc = abs_path("../../..");
+my $oldsrc = $ENV{oldsrc} || $newsrc;
+$oldsrc = abs_path($oldsrc);
+
+# Temporary location for the dumps taken
+my $tempdir = PostgreSQL::Test::Utils::tempdir;
+
+# Initialize node to upgrade
+my $oldnode = PostgreSQL::Test::Cluster->new('old_node',
+	install_path => $ENV{oldinstall});
+
+$oldnode->init(extra => [ '--locale', 'C', '--encoding', 'LATIN1' ]);
+$oldnode->start;
+
+# Set up the data of the old instance with pg_regress or an old dump.
+if (defined($ENV{olddump}))
+{
+	# Use the dump specified.
+	my $olddumpfile = $ENV{olddump};
+	die "no dump file found!" unless -e $olddumpfile;
+
+	# Load the dump, and we are done here.
+	$oldnode->command_ok(
+		[
+			'psql',   '-X',           '-f', $olddumpfile,
+			'--port', $oldnode->port, 'regression'
+		]);
+}
+else
+{
+	# Default is to just use pg_regress to set up the old instance
+	# Creating databases with names covering most ASCII bytes
+	generate_db($oldnode, 1,  45);
+	generate_db($oldnode, 46, 90);
+	generate_db($oldnode, 91, 127);
+
+	# Run core regression tests on the old instance.
+	$oldnode->run_log([ "createdb", '--port', $oldnode->port, 'regression' ]);
+
+	# Grab any regression options that may be passed down by caller.
+	my $extra_opts_val = $ENV{EXTRA_REGRESS_OPT} || "";
+	my @extra_opts     = split(/\s+/, $extra_opts_val);
+
+	# --dlpath is needed to be able to find the location of regress.so and
+	# any libraries the regression tests required.  This needs to point to
+	# the old instance when using it.  In the default case, fallback to
+	# what the caller provided for REGRESS_SHLIB.
+	my $dlpath;
+	if (defined($ENV{oldinstall}))
+	{
+		$dlpath = "$oldsrc/src/test/regress";
+	}
+	else
+	{
+		$dlpath = dirname($ENV{REGRESS_SHLIB});
+	}
+	$dlpath = PostgreSQL::Test::Utils::perl2host($dlpath);
+
+	# --outputdir points to the path where to place the output files, which
+	# had better be this directory.
+	my $outputdir =
+	  PostgreSQL::Test::Utils::perl2host($ENV{REGRESS_OUTPUTDIR});
+
+	# --inputdir needs to point to the location of the input files, from the
+	# cluster to-be-upgraded.
+	my $inputdir =
+	  PostgreSQL::Test::Utils::perl2host("$oldsrc/src/test/regress");
+
+	my @regress_command = [
+		$ENV{PG_REGRESS},
+		'--schedule',     "$oldsrc/src/test/regress/parallel_schedule",
+		'--bindir',       $oldnode->config_data('--bindir'),
+		'--dlpath',       $dlpath,
+		'--port',         $oldnode->port,
+		'--outputdir',    $outputdir,
+		'--inputdir',     $inputdir,
+		'--use-existing'
+	];
+	@regress_command = (@regress_command, @extra_opts);
+
+	$oldnode->command_ok(@regress_command,
+		'regression test run on old instance');
+}
+
+# Before dumping, get rid of objects not existing or not supported in later
+# versions. This depends on the version of the old server used, and matters
+# only if different versions are used for the dump.
+if (defined($ENV{oldinstall}))
+{
+	# Note that upgrade_adapt.sql from the new version is used, to
+	# cope with an upgrade to this version.
+	$oldnode->run_log(
+		[
+			'psql', '-X', '-f',
+			PostgreSQL::Test::Utils::perl2host(
+				"$newsrc/src/bin/pg_upgrade/upgrade_adapt.sql"),
+			'--port',
+			$oldnode->port,
+			'regression'
+		]);
+}
+
+# Initialize a new node for the upgrade.  This is done early so as it is
+# possible to know with which node's PATH the initial dump needs to be
+# taken.
+my $newnode = PostgreSQL::Test::Cluster->new('new_node');
+$newnode->init(extra => [ '--locale=C', '--encoding=LATIN1' ]);
+my $newbindir = $newnode->config_data('--bindir');
+my $oldbindir = $oldnode->config_data('--bindir');
+
+# Take a dump before performing the upgrade as a base comparison. Note
+# that we need to use pg_dumpall from the new node here.
+$newnode->command_ok(
+	[
+		'pg_dumpall', '--no-sync',
+		'-d',         $oldnode->connstr('postgres'),
+		'-f',         "$tempdir/dump1.sql"
+	],
+	'dump before running pg_upgrade');
+
+# After dumping, update references to the old source tree's regress.so
+# to point to the new tree.
+if (defined($ENV{oldinstall}))
+{
+	# First, fetch all the references to libraries that are not part
+	# of the default path $libdir.
+	my $output = $oldnode->safe_psql('regression',
+		"SELECT DISTINCT probin::text FROM pg_proc WHERE probin NOT LIKE '\$libdir%';"
+	);
+	chomp($output);
+	my @libpaths = split("\n", $output);
+
+	my $dump_data = slurp_file("$tempdir/dump1.sql");
+
+	my $newregresssrc = "$newsrc/src/test/regress";
+	foreach (@libpaths)
+	{
+		my $libpath = $_;
+		$libpath = dirname($libpath);
+		$dump_data =~ s/$libpath/$newregresssrc/g;
+	}
+
+	open my $fh, ">", "$tempdir/dump1.sql" or die "could not open dump file";
+	print $fh $dump_data;
+	close $fh;
+
+	# This replaces any references to the old tree's regress.so
+	# the new tree's regress.so.  Any references that do *not*
+	# match $libdir are switched so as this request does not
+	# depend on the path of the old source tree.  This is useful
+	# when using an old dump.  Do the operation on all the databases
+	# that allow connections so as this includes the regression
+	# database and anything the user has set up.
+	$output = $oldnode->safe_psql('postgres',
+		"SELECT datname FROM pg_database WHERE datallowconn;");
+	chomp($output);
+	my @datnames = split("\n", $output);
+	foreach (@datnames)
+	{
+		my $datname = $_;
+		$oldnode->safe_psql(
+			$datname, "UPDATE pg_proc SET probin =
+		  regexp_replace(probin, '.*/', '$newregresssrc/')
+		  WHERE probin NOT LIKE '\$libdir/%'");
+	}
+}
+
+# Update the instance.
+$oldnode->stop;
+
+# Time for the real run.
+# pg_upgrade would complain if PGHOST, so as there are no attempts to
+# connect to a different server than the upgraded ones.  So reset it
+# temporarily.  For the same reason, we should not rely on
+# PostgreSQL::Test::Cluster::command_ok() as this would load a node's
+# loal environment variables.
+my $pghost_local = $ENV{PGHOST};
+my $pghostaddr_local = $ENV{PGHOSTADDR};
+delete $ENV{PGHOST};
+delete $ENV{PGHOSTADDR};
+command_ok(
+	[
+		'pg_upgrade', '--no-sync',        '-d', $oldnode->data_dir,
+		'-D',         $newnode->data_dir, '-b', $oldbindir,
+		'-B',         $newbindir,         '-p', $oldnode->port,
+		'-P',         $newnode->port,
+	],
+	'run of pg_upgrade for new instance');
+$ENV{PGHOST} = $pghost_local;
+$ENV{PGHOSTADDR} = $pghostaddr_local;
+$newnode->start;
+
+# Take a second dump on the upgraded instance.
+$newnode->run_log(
+	[
+		'pg_dumpall', '--no-sync',
+		'-d',         $newnode->connstr('postgres'),
+		'-f',         "$tempdir/dump2.sql"
+	]);
+
+# Compare the two dumps, there should be no differences.
+command_ok([ 'diff', '-q', "$tempdir/dump1.sql", "$tempdir/dump2.sql" ],
+	'old and new dump match after pg_upgrade');
diff --git a/src/bin/pg_upgrade/test.sh b/src/bin/pg_upgrade/test.sh
deleted file mode 100644
index ef328b3062..0000000000
--- a/src/bin/pg_upgrade/test.sh
+++ /dev/null
@@ -1,279 +0,0 @@
-#!/bin/sh
-
-# src/bin/pg_upgrade/test.sh
-#
-# Test driver for pg_upgrade.  Initializes a new database cluster,
-# runs the regression tests (to put in some data), runs pg_dumpall,
-# runs pg_upgrade, runs pg_dumpall again, compares the dumps.
-#
-# Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
-# Portions Copyright (c) 1994, Regents of the University of California
-
-set -e
-
-: ${MAKE=make}
-
-# Guard against parallel make issues (see comments in pg_regress.c)
-unset MAKEFLAGS
-unset MAKELEVEL
-
-# Run a given "initdb" binary and overlay the regression testing
-# authentication configuration.
-standard_initdb() {
-	# To increase coverage of non-standard segment size and group access
-	# without increasing test runtime, run these tests with a custom setting.
-	# Also, specify "-A trust" explicitly to suppress initdb's warning.
-	# --allow-group-access and --wal-segsize have been added in v11.
-	"$1" -N --wal-segsize 1 --allow-group-access -A trust
-	if [ -n "$TEMP_CONFIG" -a -r "$TEMP_CONFIG" ]
-	then
-		cat "$TEMP_CONFIG" >> "$PGDATA/postgresql.conf"
-	fi
-	../../test/regress/pg_regress --config-auth "$PGDATA"
-}
-
-# What flavor of host are we on?
-# Treat MINGW* (msys1) and MSYS* (msys2) the same.
-testhost=`uname -s | sed 's/^MSYS/MINGW/'`
-
-# Establish how the server will listen for connections
-case $testhost in
-	MINGW*)
-		LISTEN_ADDRESSES="localhost"
-		PG_REGRESS_SOCKET_DIR=""
-		PGHOST=localhost
-		;;
-	*)
-		LISTEN_ADDRESSES=""
-		# Select a socket directory.  The algorithm is from the "configure"
-		# script; the outcome mimics pg_regress.c:make_temp_sockdir().
-		if [ x"$PG_REGRESS_SOCKET_DIR" = x ]; then
-			set +e
-			dir=`(umask 077 &&
-				  mktemp -d /tmp/pg_upgrade_check-XXXXXX) 2>/dev/null`
-			if [ ! -d "$dir" ]; then
-				dir=/tmp/pg_upgrade_check-$$-$RANDOM
-				(umask 077 && mkdir "$dir")
-				if [ ! -d "$dir" ]; then
-					echo "could not create socket temporary directory in \"/tmp\""
-					exit 1
-				fi
-			fi
-			set -e
-			PG_REGRESS_SOCKET_DIR=$dir
-			trap 'rm -rf "$PG_REGRESS_SOCKET_DIR"' 0
-			trap 'exit 3' 1 2 13 15
-		fi
-		PGHOST=$PG_REGRESS_SOCKET_DIR
-		;;
-esac
-
-POSTMASTER_OPTS="-F -c listen_addresses=\"$LISTEN_ADDRESSES\" -k \"$PG_REGRESS_SOCKET_DIR\""
-export PGHOST
-
-# don't rely on $PWD here, as old shells don't set it
-temp_root=`pwd`/tmp_check
-rm -rf "$temp_root"
-mkdir "$temp_root"
-
-: ${oldbindir=$bindir}
-
-: ${oldsrc=../../..}
-oldsrc=`cd "$oldsrc" && pwd`
-newsrc=`cd ../../.. && pwd`
-
-# We need to make pg_regress use psql from the desired installation
-# (likely a temporary one), because otherwise the installcheck run
-# below would try to use psql from the proper installation directory
-# of the target version, which might be outdated or not exist. But
-# don't override anything else that's already in EXTRA_REGRESS_OPTS.
-EXTRA_REGRESS_OPTS="$EXTRA_REGRESS_OPTS --bindir='$oldbindir'"
-export EXTRA_REGRESS_OPTS
-
-# While in normal cases this will already be set up, adding bindir to
-# path allows test.sh to be invoked with different versions as
-# described in ./TESTING
-PATH=$bindir:$PATH
-export PATH
-
-BASE_PGDATA="$temp_root/data"
-PGDATA="${BASE_PGDATA}.old"
-export PGDATA
-
-# Send installcheck outputs to a private directory.  This avoids conflict when
-# check-world runs pg_upgrade check concurrently with src/test/regress check.
-# To retrieve interesting files after a run, use pattern tmp_check/*/*.diffs.
-outputdir="$temp_root/regress"
-EXTRA_REGRESS_OPTS="$EXTRA_REGRESS_OPTS --outputdir=$outputdir"
-export EXTRA_REGRESS_OPTS
-mkdir "$outputdir"
-
-# pg_regress --make-tablespacedir would take care of that in 14~, but this is
-# still required for older versions where this option is not supported.
-if [ "$newsrc" != "$oldsrc" ]; then
-	mkdir "$outputdir"/testtablespace
-	mkdir "$outputdir"/sql
-	mkdir "$outputdir"/expected
-fi
-
-logdir=`pwd`/log
-rm -rf "$logdir"
-mkdir "$logdir"
-
-# Clear out any environment vars that might cause libpq to connect to
-# the wrong postmaster (cf pg_regress.c)
-#
-# Some shells, such as NetBSD's, return non-zero from unset if the variable
-# is already unset. Since we are operating under 'set -e', this causes the
-# script to fail. To guard against this, set them all to an empty string first.
-PGDATABASE="";        unset PGDATABASE
-PGUSER="";            unset PGUSER
-PGSERVICE="";         unset PGSERVICE
-PGSSLMODE="";         unset PGSSLMODE
-PGREQUIRESSL="";      unset PGREQUIRESSL
-PGCONNECT_TIMEOUT=""; unset PGCONNECT_TIMEOUT
-PGHOSTADDR="";        unset PGHOSTADDR
-
-# Select a non-conflicting port number, similarly to pg_regress.c
-PG_VERSION_NUM=`grep '#define PG_VERSION_NUM' "$newsrc"/src/include/pg_config.h | awk '{print $3}'`
-PGPORT=`expr $PG_VERSION_NUM % 16384 + 49152`
-export PGPORT
-
-i=0
-while psql -X postgres </dev/null 2>/dev/null
-do
-	i=`expr $i + 1`
-	if [ $i -eq 16 ]
-	then
-		echo port $PGPORT apparently in use
-		exit 1
-	fi
-	PGPORT=`expr $PGPORT + 1`
-	export PGPORT
-done
-
-# buildfarm may try to override port via EXTRA_REGRESS_OPTS ...
-EXTRA_REGRESS_OPTS="$EXTRA_REGRESS_OPTS --port=$PGPORT"
-export EXTRA_REGRESS_OPTS
-
-standard_initdb "$oldbindir"/initdb
-"$oldbindir"/pg_ctl start -l "$logdir/postmaster1.log" -o "$POSTMASTER_OPTS" -w
-
-# Create databases with names covering the ASCII bytes other than NUL, BEL,
-# LF, or CR.  BEL would ring the terminal bell in the course of this test, and
-# it is not otherwise a special case.  PostgreSQL doesn't support the rest.
-dbname1=`awk 'BEGIN { for (i= 1; i < 46; i++)
-	if (i != 7 && i != 10 && i != 13) printf "%c", i }' </dev/null`
-# Exercise backslashes adjacent to double quotes, a Windows special case.
-dbname1='\"\'$dbname1'\\"\\\'
-dbname2=`awk 'BEGIN { for (i = 46; i <  91; i++) printf "%c", i }' </dev/null`
-dbname3=`awk 'BEGIN { for (i = 91; i < 128; i++) printf "%c", i }' </dev/null`
-createdb "regression$dbname1" || createdb_status=$?
-createdb "regression$dbname2" || createdb_status=$?
-createdb "regression$dbname3" || createdb_status=$?
-
-# Extra options to apply to the dump.  This may be changed later.
-extra_dump_options=""
-
-if "$MAKE" -C "$oldsrc" installcheck-parallel; then
-	oldpgversion=`psql -X -A -t -d regression -c "SHOW server_version_num"`
-
-	# Before dumping, tweak the database of the old instance depending
-	# on its version.
-	if [ "$newsrc" != "$oldsrc" ]; then
-		# This SQL script has its own idea of the cleanup that needs to be
-		# done on the cluster to-be-upgraded, and includes version checks.
-		# Note that this uses the script stored on the new branch.
-		psql -X -d regression -f "$newsrc/src/bin/pg_upgrade/upgrade_adapt.sql" \
-			|| psql_fix_sql_status=$?
-
-		# Handling of --extra-float-digits gets messy after v12.
-		# Note that this changes the dumps from the old and new
-		# instances if involving an old cluster of v11 or older.
-		if [ $oldpgversion -lt 120000 ]; then
-			extra_dump_options="--extra-float-digits=0"
-		fi
-	fi
-
-	pg_dumpall $extra_dump_options --no-sync \
-		-f "$temp_root"/dump1.sql || pg_dumpall1_status=$?
-
-	if [ "$newsrc" != "$oldsrc" ]; then
-		# update references to old source tree's regress.so etc
-		fix_sql=""
-		case $oldpgversion in
-			*)
-				fix_sql="UPDATE pg_proc SET probin = replace(probin, '$oldsrc', '$newsrc') WHERE probin LIKE '$oldsrc%';"
-				;;
-		esac
-		psql -X -d regression -c "$fix_sql;" || psql_fix_sql_status=$?
-
-		mv "$temp_root"/dump1.sql "$temp_root"/dump1.sql.orig
-		sed "s;$oldsrc;$newsrc;g" "$temp_root"/dump1.sql.orig >"$temp_root"/dump1.sql
-	fi
-else
-	make_installcheck_status=$?
-fi
-"$oldbindir"/pg_ctl -m fast stop
-if [ -n "$createdb_status" ]; then
-	exit 1
-fi
-if [ -n "$make_installcheck_status" ]; then
-	exit 1
-fi
-if [ -n "$psql_fix_sql_status" ]; then
-	exit 1
-fi
-if [ -n "$pg_dumpall1_status" ]; then
-	echo "pg_dumpall of pre-upgrade database cluster failed"
-	exit 1
-fi
-
-PGDATA="$BASE_PGDATA"
-
-standard_initdb 'initdb'
-
-pg_upgrade $PG_UPGRADE_OPTS --no-sync -d "${PGDATA}.old" -D "$PGDATA" -b "$oldbindir" -p "$PGPORT" -P "$PGPORT"
-
-# make sure all directories and files have group permissions, on Unix hosts
-# Windows hosts don't support Unix-y permissions.
-case $testhost in
-	MINGW*|CYGWIN*) ;;
-	*)	if [ `find "$PGDATA" -type f ! -perm 640 | wc -l` -ne 0 ]; then
-			echo "files in PGDATA with permission != 640";
-			exit 1;
-		fi ;;
-esac
-
-case $testhost in
-	MINGW*|CYGWIN*) ;;
-	*)	if [ `find "$PGDATA" -type d ! -perm 750 | wc -l` -ne 0 ]; then
-			echo "directories in PGDATA with permission != 750";
-			exit 1;
-		fi ;;
-esac
-
-pg_ctl start -l "$logdir/postmaster2.log" -o "$POSTMASTER_OPTS" -w
-
-pg_dumpall $extra_dump_options --no-sync \
-	-f "$temp_root"/dump2.sql || pg_dumpall2_status=$?
-pg_ctl -m fast stop
-
-if [ -n "$pg_dumpall2_status" ]; then
-	echo "pg_dumpall of post-upgrade database cluster failed"
-	exit 1
-fi
-
-case $testhost in
-	MINGW*)	MSYS2_ARG_CONV_EXCL=/c cmd /c delete_old_cluster.bat ;;
-	*)	    sh ./delete_old_cluster.sh ;;
-esac
-
-if diff "$temp_root"/dump1.sql "$temp_root"/dump2.sql >/dev/null; then
-	echo PASSED
-	exit 0
-else
-	echo "Files $temp_root/dump1.sql and $temp_root/dump2.sql differ"
-	echo "dumps were not identical"
-	exit 1
-fi
diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm
index 7af0f8db13..7fb412d6a5 100644
--- a/src/test/perl/PostgreSQL/Test/Cluster.pm
+++ b/src/test/perl/PostgreSQL/Test/Cluster.pm
@@ -327,6 +327,31 @@ sub install_path
 
 =pod
 
+=item $node->config_data($option)
+
+Grab some data from pg_config, with $option being the command switch
+used.
+
+=cut
+
+sub config_data
+{
+	my ($self, $option) = @_;
+	local %ENV = $self->_get_env();
+
+	my ($stdout, $stderr);
+	my $result =
+	  IPC::Run::run [ $self->installed_command('pg_config'), $option ],
+	  '>', \$stdout, '2>', \$stderr
+	  or die "could not execute pg_config";
+	chomp($stdout);
+	$stdout =~ s/\r$//;
+
+	return $stdout;
+}
+
+=pod
+
 =item $node->info()
 
 Return a string containing human-readable diagnostic information (paths, etc)
diff --git a/src/tools/msvc/vcregress.pl b/src/tools/msvc/vcregress.pl
index 6dcd742fa6..e0797dc714 100644
--- a/src/tools/msvc/vcregress.pl
+++ b/src/tools/msvc/vcregress.pl
@@ -285,6 +285,10 @@ sub bincheck
 	foreach my $dir (@bin_dirs)
 	{
 		next unless -d "$dir/t";
+		# Do not consider pg_upgrade, as it is handled by
+		# upgradecheck.
+		next if ($dir =~ "/pg_upgrade/");
+
 		my $status = tap_check($dir);
 		$mstat ||= $status;
 	}
@@ -592,91 +596,11 @@ sub generate_db
 
 sub upgradecheck
 {
-	my $status;
-	my $cwd = getcwd();
-
-	# Much of this comes from the pg_upgrade test.sh script,
-	# but it only covers the --install case, and not the case
-	# where the old and new source or bin dirs are different.
-	# i.e. only this version to this version check. That's
-	# what pg_upgrade's "make check" does.
-
-	$ENV{PGHOST} = 'localhost';
-	$ENV{PGPORT} ||= 50432;
-	my $tmp_root = "$topdir/src/bin/pg_upgrade/tmp_check";
-	rmtree($tmp_root);
-	mkdir $tmp_root || die $!;
-	my $upg_tmp_install = "$tmp_root/install";    # unshared temp install
-	print "Setting up temp install\n\n";
-	Install($upg_tmp_install, "all", $config);
-
-	# Install does a chdir, so change back after that
-	chdir $cwd;
-	my ($bindir, $libdir, $oldsrc, $newsrc) =
-	  ("$upg_tmp_install/bin", "$upg_tmp_install/lib", $topdir, $topdir);
-	$ENV{PATH} = "$bindir;$ENV{PATH}";
-	my $data = "$tmp_root/data";
-	$ENV{PGDATA} = "$data.old";
-	my $outputdir          = "$tmp_root/regress";
-	my @EXTRA_REGRESS_OPTS = ("--outputdir=$outputdir");
-	mkdir "$outputdir" || die $!;
-
-	my $logdir = "$topdir/src/bin/pg_upgrade/log";
-	rmtree($logdir);
-	mkdir $logdir || die $!;
-	print "\nRunning initdb on old cluster\n\n";
-	standard_initdb() or exit 1;
-	print "\nStarting old cluster\n\n";
-	my @args = ('pg_ctl', 'start', '-l', "$logdir/postmaster1.log");
-	system(@args) == 0 or exit 1;
-
-	print "\nCreating databases with names covering most ASCII bytes\n\n";
-	generate_db("\\\"\\", 1,  45,  "\\\\\"\\\\\\");
-	generate_db('',       46, 90,  '');
-	generate_db('',       91, 127, '');
-
-	print "\nSetting up data for upgrading\n\n";
-	installcheck_internal('parallel', @EXTRA_REGRESS_OPTS);
-
-	# now we can chdir into the source dir
-	chdir "$topdir/src/bin/pg_upgrade";
-	print "\nDumping old cluster\n\n";
-	@args = ('pg_dumpall', '-f', "$tmp_root/dump1.sql");
-	system(@args) == 0 or exit 1;
-	print "\nStopping old cluster\n\n";
-	system("pg_ctl stop") == 0 or exit 1;
-	$ENV{PGDATA} = "$data";
-	print "\nSetting up new cluster\n\n";
-	standard_initdb() or exit 1;
-	print "\nRunning pg_upgrade\n\n";
-	@args = (
-		'pg_upgrade', '-d', "$data.old", '-D', $data, '-b', $bindir,
-		'--no-sync');
-	system(@args) == 0 or exit 1;
-	print "\nStarting new cluster\n\n";
-	@args = ('pg_ctl', '-l', "$logdir/postmaster2.log", 'start');
-	system(@args) == 0 or exit 1;
-	print "\nDumping new cluster\n\n";
-	@args = ('pg_dumpall', '-f', "$tmp_root/dump2.sql");
-	system(@args) == 0 or exit 1;
-	print "\nStopping new cluster\n\n";
-	system("pg_ctl stop") == 0 or exit 1;
-	print "\nDeleting old cluster\n\n";
-	system(".\\delete_old_cluster.bat") == 0 or exit 1;
-	print "\nComparing old and new cluster dumps\n\n";
-
-	@args = ('diff', '-q', "$tmp_root/dump1.sql", "$tmp_root/dump2.sql");
-	system(@args);
-	$status = $?;
-	if (!$status)
-	{
-		print "PASSED\n";
-	}
-	else
-	{
-		print "dumps not identical!\n";
-		exit(1);
-	}
+	InstallTemp();
+	# Tweak environment for the upgrade tests
+	$ENV{REGRESS_OUTPUTDIR} = "$topdir/src/bin/pg_upgrade";
+	my $mstat = tap_check("$topdir/src/bin/pg_upgrade");
+	exit $mstat if $mstat;
 	return;
 }
 
-- 
2.34.1



  [application/pgp-signature] signature.asc (833B, ../../YeYj4DU5qY%[email protected]/3-signature.asc)
  download

^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* Re: Rewriting the test of pg_upgrade as a TAP test - take three - remastered set
@ 2022-02-13 04:12  Andres Freund <[email protected]>
  parent: Michael Paquier <[email protected]>
  0 siblings, 1 reply; 7+ messages in thread

From: Andres Freund @ 2022-02-13 04:12 UTC (permalink / raw)
  To: Michael Paquier <[email protected]>; +Cc: Julien Rouhaud <[email protected]>; Tom Lane <[email protected]>; Andrew Dunstan <[email protected]>; Postgres hackers <[email protected]>

Hi,

On 2022-01-18 11:20:16 +0900, Michael Paquier wrote:
> On Sat, Jan 15, 2022 at 01:52:39PM +0800, Julien Rouhaud wrote:
> > libpq environment variable PGHOST has a non-local server value: C:/Users/ContainerAdministrator/AppData/Local/Temp/FhBIlsw6SV
> > Failure, exiting
> > not ok 3 - run of pg_upgrade for new instance
> 
> There are two things here, as far as I understand:
> 1) This is a valid Windows path.  So shouldn't we fix pg_upgrade's
> server.c to be a bit more compliant with Windows paths?  The code
> accepts only paths beginning with '/' as local paths, so this breaks.

It also doesn't handle @ correctly. Makes sense to fix. Should probably use
the same logic that libpq, psql, ... use?

			if (is_unixsock_path(ch->host))
				ch->type = CHT_UNIX_SOCKET;

that'd basically be the same amount of code. And easier to understand.

Greetings,

Andres Freund






^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* Re: Rewriting the test of pg_upgrade as a TAP test - take three - remastered set
@ 2022-02-14 08:01  Michael Paquier <[email protected]>
  parent: Andres Freund <[email protected]>
  0 siblings, 0 replies; 7+ messages in thread

From: Michael Paquier @ 2022-02-14 08:01 UTC (permalink / raw)
  To: Andres Freund <[email protected]>; +Cc: Julien Rouhaud <[email protected]>; Tom Lane <[email protected]>; Andrew Dunstan <[email protected]>; Postgres hackers <[email protected]>

On Sat, Feb 12, 2022 at 08:12:42PM -0800, Andres Freund wrote:
> It also doesn't handle @ correctly. Makes sense to fix. Should probably use
> the same logic that libpq, psql, ... use?
> 
> 			if (is_unixsock_path(ch->host))
> 				ch->type = CHT_UNIX_SOCKET;
> 
> that'd basically be the same amount of code. And easier to understand.

So, I am catching up with some parts of this thread, and I have
managed to miss is_unixsock_path().  Except if I am missing something
(now it is close to the end of the day here), a minimal change would
be something like that as we'd still want to allow the use of
localhost and others:
    if (value && strlen(value) > 0 &&
    /* check for 'local' host values */
        (strcmp(value, "localhost") != 0 && strcmp(value, "127.0.0.1") != 0 &&
-        strcmp(value, "::1") != 0 && value[0] != '/'))
+        strcmp(value, "::1") != 0 && !is_unixsock_path(value)))

Or perhaps we should restrict more the use of localhost values for
non-WIN32?  Opinions?
--
Michael


Attachments:

  [application/pgp-signature] signature.asc (833B, ../../YgoMQQgZrQihu%[email protected]/2-signature.asc)
  download

^ permalink  raw  reply  [nested|flat] 7+ messages in thread


end of thread, other threads:[~2022-02-14 08:01 UTC | newest]

Thread overview: 7+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2020-10-07 03:11 [PATCH v8 4/8] Propagate changes to indisclustered to child/parents Justin Pryzby <[email protected]>
2022-01-05 08:12 Re: Rewriting the test of pg_upgrade as a TAP test - take three - remastered set Michael Paquier <[email protected]>
2022-01-11 07:14 ` Re: Rewriting the test of pg_upgrade as a TAP test - take three - remastered set Michael Paquier <[email protected]>
2022-01-15 05:52   ` Re: Rewriting the test of pg_upgrade as a TAP test - take three - remastered set Julien Rouhaud <[email protected]>
2022-01-18 02:20     ` Re: Rewriting the test of pg_upgrade as a TAP test - take three - remastered set Michael Paquier <[email protected]>
2022-02-13 04:12       ` Re: Rewriting the test of pg_upgrade as a TAP test - take three - remastered set Andres Freund <[email protected]>
2022-02-14 08:01         ` Re: Rewriting the test of pg_upgrade as a TAP test - take three - remastered set Michael Paquier <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox