Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jvixY-0008OR-VZ for pgsql-hackers@arkaria.postgresql.org; Wed, 15 Jul 2020 15:04:37 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1jvixX-0007dp-S5 for pgsql-hackers@arkaria.postgresql.org; Wed, 15 Jul 2020 15:04:35 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jvixX-0007dg-CF for pgsql-hackers@lists.postgresql.org; Wed, 15 Jul 2020 15:04:35 +0000 Received: from mail-qt1-x842.google.com ([2607:f8b0:4864:20::842]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1jvixU-0003k0-9t for pgsql-hackers@postgresql.org; Wed, 15 Jul 2020 15:04:34 +0000 Received: by mail-qt1-x842.google.com with SMTP id o38so1905999qtf.6 for ; Wed, 15 Jul 2020 08:04:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=2ndquadrant-com.20150623.gappssmtp.com; s=20150623; h=from:subject:to:cc:references:autocrypt:message-id:date:user-agent :mime-version:in-reply-to:content-language; bh=s0uBKCwNJoPGUPB4Xi66C2u1Lg98dPYUK6AQWwEDpa0=; b=YWGk80Pumr5QcAgkzacpXxackqT+TfPI7B96plfDdaEB2IG30eCDSoiBlfyw+kWxKa SFA5rw530e76YaLuVtXG9H9SJkxJR342cLJd4kmlafRSnx44Ex5JP41/tHhlUVPo5OPB oUFzPoH+wny+O7Suj7tR+vAScc8Nc9oxBpqFbC2NLqwu4z8+Em7XQNxxv37S6PgaTgeM kOTS6UfViAQ4dRmixQNGF/Ypt2T5VhSJ9j9cpmjdFXTYaa7uX4nbXGeSXV95ObqVX3YR OnokCqKG3bZJhMgTdOXgh6FoWYRqkT7uMiBZHTwVCBSk+aG6ALod+pNW4pZrpCXOz9YV FalQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:subject:to:cc:references:autocrypt :message-id:date:user-agent:mime-version:in-reply-to :content-language; bh=s0uBKCwNJoPGUPB4Xi66C2u1Lg98dPYUK6AQWwEDpa0=; b=A7yenxr57Lk+zyfPc16qu2tOouANhc9F7DFsgZ3nkIB+/cjOjBqadtMyvnOVkBODnY nQqdu2qmzM/Qg42hBmInhLnL4Sg+P8xFCqVTO6swHPzl0keXA3YCMYSvU5JmCu/hmyEH hAbzs1BSThtlUBnpufaQ+K+Xb9pIlewSMMRi0ud7yAdWEjjH6WJteXIGFEBTOyDqqbTZ 4jylS6bYsnPRKjOkHYcgRO9bKKgxgwR6uoyIOQTsk50Eo/3mXjcE/sITqaWo/KLNx4L0 CwYOXr7Q1uMw9WgoMAPvdReGcFa2Xiw18VB25HZGL92k+l1qmQis2u+Xw41v7pA2MlAM FxsA== X-Gm-Message-State: AOAM530mPBD3vpYS5kh3fROPr3kcSsI7Pp1vo5ekpgGKcRCZauDUC60W zLFd1tZrB3bHreK9XGYTi23YuBAqLQ2rSggZxeGDtjoQ47FeTOIgVu6WsQyBYfTwbndU5qGVlyR wgusYEqIdPVvYz+vEKHA90Ku5HEmfKUc+77AJAHIigfh5vu7OJhCdtsUawkzWSbLmsvLSveN00H r1FFFjEVNjKdjX7nU= X-Google-Smtp-Source: ABdhPJx58E+RuCeN0KFE54N0cKNAUFoOw6crGqavVEQpSt7eRwts/b3dtIA8hVKcBtoI9guTNUjlcg== X-Received: by 2002:ac8:b4c:: with SMTP id m12mr114663qti.321.1594825470516; Wed, 15 Jul 2020 08:04:30 -0700 (PDT) Received: from ?IPv6:2600:1700:722:4630::43? ([2600:1700:722:4630::43]) by smtp.gmail.com with ESMTPSA id z187sm2670958qkb.102.2020.07.15.08.04.28 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 15 Jul 2020 08:04:29 -0700 (PDT) From: Andrew Dunstan X-Google-Original-From: Andrew Dunstan Subject: Re: TAP tests and symlinks on Windows To: Michael Paquier Cc: Peter Eisentraut , =?UTF-8?Q?Juan_Jos=c3=a9_Santamar=c3=ada_Flecha?= , =?UTF-8?Q?Dagfinn_Ilmari_Manns=c3=a5ker?= , pgsql-hackers References: <20200615062319.GF52676@paquier.xyz> <11c4ee09-3706-5912-ffd7-dc3657de7a5e@2ndQuadrant.com> <20200617074434.GB118592@paquier.xyz> <20200623105527.GA1974@paquier.xyz> <3ebcde2b-3b78-2e5f-9249-03c709dc23dd@2ndquadrant.com> <20200629075616.GC330401@paquier.xyz> <20200630121328.GB67289@paquier.xyz> <504f09d7-d600-44ca-a32b-0ed209cc2273@2ndquadrant.com> <19483ac1-0f31-cfd3-8ef7-5da0ac5a5f46@2ndQuadrant.com> <20200714052837.GH10826@paquier.xyz> Autocrypt: addr=andrew.dunstan@2ndQuadrant.com; prefer-encrypt=mutual; keydata= mQENBE7KWFkBCAClridxur2AIc7eW2AR7izbfp3EnNefie2HbLF0izW5Ik5UjX2HBXBx4syI gY6b0ugohXrr274+baoAlvSbq6cAoQuEVrk5IZFzt20b1Xkx65FwGSEj526yiKLocqkJceSq Xr9xcA5SGY+FZv441chh5SU92v4q6z+6LPpoHOh97ptAVXZYNTtU0LevyvD5lja0TzbvJm6C eFXitJfnm1pLEr0DGJCR/iUOl/N62Kh4855zZC7NHIjQHPOvV5Stz/l5ilDhvGVk+xkXFPys SjZoUr1rXhYLpiyi5sR0X9FHXT0KnGuz1F5ERO7ZTLSSQ6fJwPj6gOk9K+vvoKvoeql5ABEB AAG0L0FuZHJldyBEdW5zdGFuIDxhbmRyZXcuZHVuc3RhbkAybmRRdWFkcmFudC5jb20+iQFY BBMBAgBCAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgBYhBOQ+WEYd/Hy/RGkVpZn6f8tZ /DuBAhkBBQJd1pSYBQkSzqMsAAoJEJn6f8tZ/DuBJmEIAIVFBIC3qGqh+YTPVTkfowwxpHz0 tZSPjZ6GS/5y62kgoZrZOVXw+Rg2ceuMM3a+In/RRjTx4bembgYqRKgzXlDfiNBJeq5ioVuN H1faDKE2lm5a6QkRQ2JU6DKf60fqSJGP5LisCUr1V0wz6EnlO31ArrKtXCNB+yk0KDAS6o6I Ql4pkXpr+vq4iilwJmiJOqTBam0LmQE7ulYCCYU8Z6MkpiSl+dO7QSramcGyxauQRI3a7gcq dpo8Vrv3gFTQDeMYxk7cqZp08pIVH5XR0+LgBz4X84f59rA/VAKlC/r6CyEQk59rvDLxCMyP 2buoj51Z25N3MVghRDGcsU6mT7e5AQ0ETspYWQEIANGc4zQULOxhbqO2dyD51YhqCNRmm9oK Waqf+wmW4tpDe/VVcxAnNizd4LWCHfzpb5cHAtGkOPePMfzWVf6nvdF7d3eglbtf59+zG7O7 llV0xSSoFiieQBsrGvqDInXYX/4mRRXMtyhM353/tixC9RWLs1oofyYmCPPXXY7h9R7en3B8 BoVrRFcdzlIY/NFNhFGW/9dkEiGjgna2Rk6e15kln4ZvFBWUg23p93w/pqXcxY6+k/8TEk+C 4R+M6w7o2PLGOjdZ+kPiUcw5H85zf/yZJwQXzisXaNduwWB6Vads9YC9dj6kPR1c4VGRqAaY L++LAEOqrlvm2TvqQqZRtnEAEQEAAYkBJQQYAQIADwIbDAUCXdaUtAUJEs6jVQAKCRCZ+n/L Wfw7gQi5B/9sHbmRloZNCWWwZGm+O9iG/JGQxS0WWa4GaZqzqSTWOft2/gO0Bgag89r1djq4 PFgSZtzHvKQpqYz/7HkPrWh1jpcS83i/uYY1uyHXUUtpdEmn4buNObEtD0YNaJkGdhASsECq 6akw+u7WJYmAHs/SpR6ok6HqLw7JHDVc2h5dViLfTk0qrgDa7sq/LVMoJje5Ct/Ku3YaWAV6 YSmzoPP5BmPVFqP11OMQkCqurIu9vTLXKFWX623vCmqRDHJ6e5GCDHbH8USU+4wJBfPymZkd cA7NGm/mmWeJiWBFIDyjzYxrjku8ty9TZJVsaRXnS+OFQzXz9Eu2wTpKdHij46uY Message-ID: <5a0b2bea-16c1-6e24-246a-eceea5757b68@2ndQuadrant.com> Date: Wed, 15 Jul 2020 11:04:28 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.6.0 MIME-Version: 1.0 In-Reply-To: <20200714052837.GH10826@paquier.xyz> Content-Type: multipart/mixed; boundary="------------1504687341EC9F0E2075D03C" Content-Language: en-US List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk This is a multi-part message in MIME format. --------------1504687341EC9F0E2075D03C Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit On 7/14/20 1:31 AM, Michael Paquier wrote: > On Fri, Jul 10, 2020 at 07:58:02AM -0400, Andrew Dunstan wrote: >> After much frustration and gnashing of teeth here's a patch that allows >> almost all the TAP tests involving symlinks to work as expected on all >> Windows build environments, without requiring an additional Perl module. >> I have tested this on a system that is very similar to that running >> drongo and fairywren, with both msys2 and MSVC builds. > Thanks Andrew for looking at the part with MSYS. The tests pass for > me with MSVC. The trick with mklink is cool. I have not considered > that, and the test code gets simpler. > > + my $cmd = qq{mklink /j "$newname" "$oldname"}; > + if ($Config{osname} eq 'msys') > + { > + # need some indirection on msys > + $cmd = qq{echo '$cmd' | \$COMSPEC /Q}; > + } > + note("dir_symlink cmd: $cmd"); > + system($cmd); > From the quoting perspective, wouldn't it be simpler to build an array > with all those arguments and call system() with @cmd? This is the simplest invocation I found to be reliable on msys2 (and it took me a long time to find). If you have a tested alternative please let me know. > +# Create files that look like temporary relations to ensure they are ignored > +# in a tablespace. > +my @tempRelationFiles = qw(t888_888 t888888_888888_vm.1); > This variable conflicts with a previous declaration, creating a > warning. > > + skip "symlink check not implemented on Windows", 1 > + if ($windows_os); > opendir(my $dh, "$pgdata/pg_tblspc") or die; > I think that this would be cleaner with a SKIP block. I don't understand this comment. The skip statement here is in a SKIP block. In fact skip only works inside SKIP blocks. (perldoc Test::More for details). Maybe you got confused by the diff format. > > +Portably create a symlink for a director. On Windows this creates a junction. > +Elsewhere it just calls perl's builtin symlink. > s/director/directory/ > s/junction/junction point/ fixed. > > > The TAP tests require the Perl module IPC::Run. > This module is available from CPAN or an operating system package. > + On Windows, Win32API::File is also required . > > This part should be backpatched IMO. I will do this in  a separate backpatched commit. > > Some of the indentation is weird, this needs a cleanup with perltidy. Done. Revised patch attached. cheers andrew -- Andrew Dunstan https://www.2ndQuadrant.com PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services --------------1504687341EC9F0E2075D03C Content-Type: text/x-patch; charset=UTF-8; name="win-tap-symlink-3.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="win-tap-symlink-3.patch" diff --git a/src/bin/pg_basebackup/t/010_pg_basebackup.pl b/src/bin/pg_basebackup/t/010_pg_basebackup.pl index 208df557b8..f674a7c94e 100644 --- a/src/bin/pg_basebackup/t/010_pg_basebackup.pl +++ b/src/bin/pg_basebackup/t/010_pg_basebackup.pl @@ -211,87 +211,93 @@ $node->command_fails( 'pg_basebackup tar with long name fails'); unlink "$pgdata/$superlongname"; -# The following tests test symlinks. Windows doesn't have symlinks, so -# skip on Windows. +# The following tests are for symlinks. + +# Move pg_replslot out of $pgdata and create a symlink to it. +$node->stop; + +# Set umask so test directories and files are created with group permissions +umask(0027); + +# Enable group permissions on PGDATA +chmod_recursive("$pgdata", 0750, 0640); + +rename("$pgdata/pg_replslot", "$tempdir/pg_replslot") + or BAIL_OUT "could not move $pgdata/pg_replslot"; +dir_symlink("$tempdir/pg_replslot", "$pgdata/pg_replslot") + or BAIL_OUT "could not symlink to $pgdata/pg_replslot"; + +$node->start; + +# Create a temporary directory in the system location and symlink it +# to our physical temp location. That way we can use shorter names +# for the tablespace directories, which hopefully won't run afoul of +# the 99 character length limit. +my $shorter_tempdir = TestLib::tempdir_short . "/tempdir"; +dir_symlink "$tempdir", $shorter_tempdir; + +mkdir "$tempdir/tblspc1"; +my $realTsDir = TestLib::perl2host("$shorter_tempdir/tblspc1"); +my $real_tempdir = TestLib::perl2host($tempdir); +$node->safe_psql('postgres', + "CREATE TABLESPACE tblspc1 LOCATION '$realTsDir';"); +$node->safe_psql('postgres', + "CREATE TABLE test1 (a int) TABLESPACE tblspc1;"); +$node->command_ok( + [ 'pg_basebackup', '-D', "$real_tempdir/tarbackup2", '-Ft' ], + 'tar format with tablespaces'); +ok(-f "$tempdir/tarbackup2/base.tar", 'backup tar was created'); +my @tblspc_tars = glob "$tempdir/tarbackup2/[0-9]*.tar"; +is(scalar(@tblspc_tars), 1, 'one tablespace tar was created'); +rmtree("$tempdir/tarbackup2"); + +# Create an unlogged table to test that forks other than init are not copied. +$node->safe_psql('postgres', + 'CREATE UNLOGGED TABLE tblspc1_unlogged (id int) TABLESPACE tblspc1;'); + +my $tblspc1UnloggedPath = $node->safe_psql('postgres', + q{select pg_relation_filepath('tblspc1_unlogged')}); + +# Make sure main and init forks exist +ok( -f "$pgdata/${tblspc1UnloggedPath}_init", + 'unlogged init fork in tablespace'); +ok(-f "$pgdata/$tblspc1UnloggedPath", 'unlogged main fork in tablespace'); + +# Create files that look like temporary relations to ensure they are ignored +# in a tablespace. +@tempRelationFiles = qw(t888_888 t888888_888888_vm.1); +my $tblSpc1Id = basename( + dirname( + dirname( + $node->safe_psql( + 'postgres', q{select pg_relation_filepath('test1')})))); + +foreach my $filename (@tempRelationFiles) +{ + append_to_file( + "$shorter_tempdir/tblspc1/$tblSpc1Id/$postgresOid/$filename", + 'TEMP_RELATION'); +} + +$node->command_fails( + [ 'pg_basebackup', '-D', "$tempdir/backup1", '-Fp' ], + 'plain format with tablespaces fails without tablespace mapping'); + +$node->command_ok( + [ + 'pg_basebackup', '-D', + "$tempdir/backup1", '-Fp', + "-T$realTsDir=$real_tempdir/tbackup/tblspc1" + ], + 'plain format with tablespaces succeeds with tablespace mapping'); +ok(-d "$tempdir/tbackup/tblspc1", 'tablespace was relocated'); + +# This symlink check is not supported on Windows as -l +# doesn't work with junctions SKIP: { - skip "symlinks not supported on Windows", 18 if ($windows_os); - - # Move pg_replslot out of $pgdata and create a symlink to it. - $node->stop; - - # Set umask so test directories and files are created with group permissions - umask(0027); - - # Enable group permissions on PGDATA - chmod_recursive("$pgdata", 0750, 0640); - - rename("$pgdata/pg_replslot", "$tempdir/pg_replslot") - or BAIL_OUT "could not move $pgdata/pg_replslot"; - symlink("$tempdir/pg_replslot", "$pgdata/pg_replslot") - or BAIL_OUT "could not symlink to $pgdata/pg_replslot"; - - $node->start; - - # Create a temporary directory in the system location and symlink it - # to our physical temp location. That way we can use shorter names - # for the tablespace directories, which hopefully won't run afoul of - # the 99 character length limit. - my $shorter_tempdir = TestLib::tempdir_short . "/tempdir"; - symlink "$tempdir", $shorter_tempdir; - - mkdir "$tempdir/tblspc1"; - $node->safe_psql('postgres', - "CREATE TABLESPACE tblspc1 LOCATION '$shorter_tempdir/tblspc1';"); - $node->safe_psql('postgres', - "CREATE TABLE test1 (a int) TABLESPACE tblspc1;"); - $node->command_ok([ 'pg_basebackup', '-D', "$tempdir/tarbackup2", '-Ft' ], - 'tar format with tablespaces'); - ok(-f "$tempdir/tarbackup2/base.tar", 'backup tar was created'); - my @tblspc_tars = glob "$tempdir/tarbackup2/[0-9]*.tar"; - is(scalar(@tblspc_tars), 1, 'one tablespace tar was created'); - rmtree("$tempdir/tarbackup2"); - - # Create an unlogged table to test that forks other than init are not copied. - $node->safe_psql('postgres', - 'CREATE UNLOGGED TABLE tblspc1_unlogged (id int) TABLESPACE tblspc1;' - ); - - my $tblspc1UnloggedPath = $node->safe_psql('postgres', - q{select pg_relation_filepath('tblspc1_unlogged')}); - - # Make sure main and init forks exist - ok( -f "$pgdata/${tblspc1UnloggedPath}_init", - 'unlogged init fork in tablespace'); - ok(-f "$pgdata/$tblspc1UnloggedPath", 'unlogged main fork in tablespace'); - - # Create files that look like temporary relations to ensure they are ignored - # in a tablespace. - my @tempRelationFiles = qw(t888_888 t888888_888888_vm.1); - my $tblSpc1Id = basename( - dirname( - dirname( - $node->safe_psql( - 'postgres', q{select pg_relation_filepath('test1')})))); - - foreach my $filename (@tempRelationFiles) - { - append_to_file( - "$shorter_tempdir/tblspc1/$tblSpc1Id/$postgresOid/$filename", - 'TEMP_RELATION'); - } - - $node->command_fails( - [ 'pg_basebackup', '-D', "$tempdir/backup1", '-Fp' ], - 'plain format with tablespaces fails without tablespace mapping'); - - $node->command_ok( - [ - 'pg_basebackup', '-D', "$tempdir/backup1", '-Fp', - "-T$shorter_tempdir/tblspc1=$tempdir/tbackup/tblspc1" - ], - 'plain format with tablespaces succeeds with tablespace mapping'); - ok(-d "$tempdir/tbackup/tblspc1", 'tablespace was relocated'); + skip "symlink check not implemented on Windows", 1 + if ($windows_os); opendir(my $dh, "$pgdata/pg_tblspc") or die; ok( ( grep { -l "$tempdir/backup1/pg_tblspc/$_" @@ -300,65 +306,73 @@ SKIP: } readdir($dh)), "tablespace symlink was updated"); closedir $dh; +} + +# Group access should be enabled on all backup files +SKIP: +{ + skip "unix-style permissions not supported on Windows", 1 + if ($windows_os); - # Group access should be enabled on all backup files ok(check_mode_recursive("$tempdir/backup1", 0750, 0640), "check backup dir permissions"); +} + +# Unlogged relation forks other than init should not be copied +my ($tblspc1UnloggedBackupPath) = + $tblspc1UnloggedPath =~ /[^\/]*\/[^\/]*\/[^\/]*$/g; + +ok(-f "$tempdir/tbackup/tblspc1/${tblspc1UnloggedBackupPath}_init", + 'unlogged init fork in tablespace backup'); +ok(!-f "$tempdir/tbackup/tblspc1/$tblspc1UnloggedBackupPath", + 'unlogged main fork not in tablespace backup'); - # Unlogged relation forks other than init should not be copied - my ($tblspc1UnloggedBackupPath) = - $tblspc1UnloggedPath =~ /[^\/]*\/[^\/]*\/[^\/]*$/g; - - ok(-f "$tempdir/tbackup/tblspc1/${tblspc1UnloggedBackupPath}_init", - 'unlogged init fork in tablespace backup'); - ok(!-f "$tempdir/tbackup/tblspc1/$tblspc1UnloggedBackupPath", - 'unlogged main fork not in tablespace backup'); - - # Temp relations should not be copied. - foreach my $filename (@tempRelationFiles) - { - ok( !-f "$tempdir/tbackup/tblspc1/$tblSpc1Id/$postgresOid/$filename", - "[tblspc1]/$postgresOid/$filename not copied"); - - # Also remove temp relation files or tablespace drop will fail. - my $filepath = - "$shorter_tempdir/tblspc1/$tblSpc1Id/$postgresOid/$filename"; - - unlink($filepath) - or BAIL_OUT("unable to unlink $filepath"); - } - - ok( -d "$tempdir/backup1/pg_replslot", - 'pg_replslot symlink copied as directory'); - rmtree("$tempdir/backup1"); - - mkdir "$tempdir/tbl=spc2"; - $node->safe_psql('postgres', "DROP TABLE test1;"); - $node->safe_psql('postgres', "DROP TABLE tblspc1_unlogged;"); - $node->safe_psql('postgres', "DROP TABLESPACE tblspc1;"); - $node->safe_psql('postgres', - "CREATE TABLESPACE tblspc2 LOCATION '$shorter_tempdir/tbl=spc2';"); - $node->command_ok( - [ - 'pg_basebackup', '-D', "$tempdir/backup3", '-Fp', - "-T$shorter_tempdir/tbl\\=spc2=$tempdir/tbackup/tbl\\=spc2" - ], - 'mapping tablespace with = sign in path'); - ok(-d "$tempdir/tbackup/tbl=spc2", - 'tablespace with = sign was relocated'); - $node->safe_psql('postgres', "DROP TABLESPACE tblspc2;"); - rmtree("$tempdir/backup3"); - - mkdir "$tempdir/$superlongname"; - $node->safe_psql('postgres', - "CREATE TABLESPACE tblspc3 LOCATION '$tempdir/$superlongname';"); - $node->command_ok( - [ 'pg_basebackup', '-D', "$tempdir/tarbackup_l3", '-Ft' ], - 'pg_basebackup tar with long symlink target'); - $node->safe_psql('postgres', "DROP TABLESPACE tblspc3;"); - rmtree("$tempdir/tarbackup_l3"); +# Temp relations should not be copied. +foreach my $filename (@tempRelationFiles) +{ + ok(!-f "$tempdir/tbackup/tblspc1/$tblSpc1Id/$postgresOid/$filename", + "[tblspc1]/$postgresOid/$filename not copied"); + + # Also remove temp relation files or tablespace drop will fail. + my $filepath = + "$shorter_tempdir/tblspc1/$tblSpc1Id/$postgresOid/$filename"; + + unlink($filepath) + or BAIL_OUT("unable to unlink $filepath"); } +ok( -d "$tempdir/backup1/pg_replslot", + 'pg_replslot symlink copied as directory'); +rmtree("$tempdir/backup1"); + +mkdir "$tempdir/tbl=spc2"; +$realTsDir = TestLib::perl2host("$shorter_tempdir/tbl=spc2"); +$node->safe_psql('postgres', "DROP TABLE test1;"); +$node->safe_psql('postgres', "DROP TABLE tblspc1_unlogged;"); +$node->safe_psql('postgres', "DROP TABLESPACE tblspc1;"); +$node->safe_psql('postgres', + "CREATE TABLESPACE tblspc2 LOCATION '$realTsDir';"); +$realTsDir =~ s/=/\\=/; +$node->command_ok( + [ + 'pg_basebackup', '-D', + "$tempdir/backup3", '-Fp', + "-T$realTsDir=$real_tempdir/tbackup/tbl\\=spc2" + ], + 'mapping tablespace with = sign in path'); +ok(-d "$tempdir/tbackup/tbl=spc2", 'tablespace with = sign was relocated'); +$node->safe_psql('postgres', "DROP TABLESPACE tblspc2;"); +rmtree("$tempdir/backup3"); + +mkdir "$tempdir/$superlongname"; +$realTsDir = TestLib::perl2host("$shorter_tempdir/$superlongname"); +$node->safe_psql('postgres', + "CREATE TABLESPACE tblspc3 LOCATION '$realTsDir';"); +$node->command_ok([ 'pg_basebackup', '-D', "$tempdir/tarbackup_l3", '-Ft' ], + 'pg_basebackup tar with long symlink target'); +$node->safe_psql('postgres', "DROP TABLESPACE tblspc3;"); +rmtree("$tempdir/tarbackup_l3"); + $node->command_ok([ 'pg_basebackup', '-D', "$tempdir/backupR", '-R' ], 'pg_basebackup -R runs'); ok(-f "$tempdir/backupR/postgresql.auto.conf", 'postgresql.auto.conf exists'); @@ -496,7 +510,7 @@ my $file_corrupt2 = $node->safe_psql('postgres', # set page header and block sizes my $pageheader_size = 24; -my $block_size = $node->safe_psql('postgres', 'SHOW block_size;'); +my $block_size = $node->safe_psql('postgres', 'SHOW block_size;'); # induce corruption system_or_bail 'pg_ctl', '-D', $pgdata, 'stop'; diff --git a/src/bin/pg_dump/t/010_dump_connstr.pl b/src/bin/pg_dump/t/010_dump_connstr.pl index abdb07c558..5497e46056 100644 --- a/src/bin/pg_dump/t/010_dump_connstr.pl +++ b/src/bin/pg_dump/t/010_dump_connstr.pl @@ -5,7 +5,7 @@ use PostgresNode; use TestLib; use Test::More; -if ($^O eq 'msys' && `uname -or` =~ /^[2-9].*Msys/) +if ($TestLib::is_msys2) { plan skip_all => 'High bit name tests fail on Msys2'; } @@ -27,7 +27,7 @@ $ENV{PGCLIENTENCODING} = 'LATIN1'; # The odds of finding something interesting by testing all ASCII letters # seem too small to justify the cycles of testing a fifth name. my $dbname1 = - 'regression' + 'regression' . generate_ascii_string(1, 9) . generate_ascii_string(11, 12) . generate_ascii_string(14, 33) diff --git a/src/bin/pg_rewind/t/004_pg_xlog_symlink.pl b/src/bin/pg_rewind/t/004_pg_xlog_symlink.pl index 3813543ee1..fff4758508 100644 --- a/src/bin/pg_rewind/t/004_pg_xlog_symlink.pl +++ b/src/bin/pg_rewind/t/004_pg_xlog_symlink.pl @@ -6,16 +6,7 @@ use warnings; use File::Copy; use File::Path qw(rmtree); use TestLib; -use Test::More; -if ($windows_os) -{ - plan skip_all => 'symlinks not supported on Windows'; - exit; -} -else -{ - plan tests => 5; -} +use Test::More tests => 5; use FindBin; use lib $FindBin::RealBin; @@ -36,7 +27,7 @@ sub run_test # turn pg_wal into a symlink print("moving $test_primary_datadir/pg_wal to $primary_xlogdir\n"); move("$test_primary_datadir/pg_wal", $primary_xlogdir) or die; - symlink($primary_xlogdir, "$test_primary_datadir/pg_wal") or die; + dir_symlink($primary_xlogdir, "$test_primary_datadir/pg_wal") or die; RewindTest::start_primary(); diff --git a/src/test/perl/TestLib.pm b/src/test/perl/TestLib.pm index a7490d2ce7..cbe87f8684 100644 --- a/src/test/perl/TestLib.pm +++ b/src/test/perl/TestLib.pm @@ -67,6 +67,7 @@ our @EXPORT = qw( check_mode_recursive chmod_recursive check_pg_config + dir_symlink system_or_bail system_log run_log @@ -84,10 +85,12 @@ our @EXPORT = qw( command_checks_all $windows_os + $is_msys2 $use_unix_sockets ); -our ($windows_os, $use_unix_sockets, $tmp_check, $log_path, $test_logfile); +our ($windows_os, $is_msys2, $use_unix_sockets, $tmp_check, $log_path, + $test_logfile); BEGIN { @@ -114,6 +117,9 @@ BEGIN # Must be set early $windows_os = $Config{osname} eq 'MSWin32' || $Config{osname} eq 'msys'; + # Check if this environment is MSYS2. + $is_msys2 = $^O eq 'msys' && `uname -or` =~ /^[2-9].*Msys/; + if ($windows_os) { require Win32API::File; @@ -137,6 +143,10 @@ BEGIN Set to true when running under Windows, except on Cygwin. +=item C<$is_msys2> + +Set to true when running under MSYS2. + =back =cut @@ -152,7 +162,7 @@ INIT # TESTDIR environment variable, which is normally set by the invoking # Makefile. $tmp_check = $ENV{TESTDIR} ? "$ENV{TESTDIR}/tmp_check" : "tmp_check"; - $log_path = "$tmp_check/log"; + $log_path = "$tmp_check/log"; mkdir $tmp_check; mkdir $log_path; @@ -263,9 +273,10 @@ sub tempdir_short =item perl2host() -Translate a Perl file name to a host file name. Currently, this is a no-op +Translate a virtual file name to a host file name. Currently, this is a no-op except for the case of Perl=msys and host=mingw32. The subject need not -exist, but its parent directory must exist. +exist, but its parent or grandparent directory must exist unless cygpath is +available. =cut @@ -273,6 +284,17 @@ sub perl2host { my ($subject) = @_; return $subject unless $Config{osname} eq 'msys'; + if ($is_msys2) + { + # get absolute, windows type path + my $path = qx{cygpath -a -w "$subject"}; + if (!$?) + { + chomp $path; + return $path if $path; + } + # fall through if this didn't work. + } my $here = cwd; my $leaf; if (chdir $subject) @@ -283,7 +305,12 @@ sub perl2host { $leaf = '/' . basename $subject; my $parent = dirname $subject; - chdir $parent or die "could not chdir \"$parent\": $!"; + if (!chdir $parent) + { + $leaf = '/' . basename($parent) . $leaf; + $parent = dirname $parent; + chdir $parent or die "could not chdir \"$parent\": $!"; + } } # this odd way of calling 'pwd -W' is the only way that seems to work. @@ -602,6 +629,40 @@ sub check_pg_config =pod +=item dir_symlink(oldname, newname) + +Portably create a symlink for a directory. On Windows this creates a junction +point. Elsewhere it just calls perl's builtin symlink. + +=cut + +sub dir_symlink +{ + my $oldname = shift; + my $newname = shift; + if ($windows_os) + { + $oldname = perl2host($oldname); + $newname = perl2host($newname); + $oldname =~ s,/,\\,g; + $newname =~ s,/,\\,g; + my $cmd = qq{mklink /j "$newname" "$oldname"}; + if ($Config{osname} eq 'msys') + { + # need some indirection on msys + $cmd = qq{echo '$cmd' | \$COMSPEC /Q}; + } + system($cmd); + } + else + { + symlink $oldname, $newname; + } + die "No $newname" unless -e $newname; +} + +=pod + =back =head1 Test::More-LIKE METHODS @@ -664,7 +725,7 @@ sub command_exit_is # long as the process was not terminated by an exception. To work around # that, use $h->full_results on Windows instead. my $result = - ($Config{osname} eq "MSWin32") + ($Config{osname} eq "MSWin32") ? ($h->full_results)[0] : $h->result(0); is($result, $expected, $test_name); --------------1504687341EC9F0E2075D03C--