1use strict;
2use warnings;
3
4use PostgresNode;
5use TestLib;
6use Test::More;
7
8if ($^O eq 'msys' && `uname -or` =~ /^[2-9].*Msys/)
9{
10	plan skip_all => 'High bit name tests fail on Msys2';
11}
12else
13{
14	plan tests => 14;
15}
16
17# We're going to use byte sequences that aren't valid UTF-8 strings.  Use
18# LATIN1, which accepts any byte and has a conversion from each byte to UTF-8.
19$ENV{LC_ALL}           = 'C';
20$ENV{PGCLIENTENCODING} = 'LATIN1';
21
22# Create database and user names covering the range of LATIN1
23# characters, for use in a connection string by pg_dumpall.  Skip ','
24# because of pg_regress --create-role, skip [\n\r] because pg_dumpall
25# does not allow them.
26my $dbname1 =
27    generate_ascii_string(1, 9)
28  . generate_ascii_string(11, 12)
29  . generate_ascii_string(14, 33)
30  . ($TestLib::windows_os ? '' : '"x"')
31  .    # IPC::Run mishandles '"' on Windows
32  generate_ascii_string(35, 43)
33  . generate_ascii_string(45, 63);    # contains '='
34my $dbname2 =
35  generate_ascii_string(67, 129);     # skip 64-66 to keep length to 62
36my $dbname3 = generate_ascii_string(130, 192);
37my $dbname4 = generate_ascii_string(193, 255);
38
39my $node = get_new_node('main');
40$node->init(extra => [ '--locale=C', '--encoding=LATIN1' ]);
41
42# prep pg_hba.conf and pg_ident.conf
43$node->run_log(
44	[
45		$ENV{PG_REGRESS}, '--config-auth',
46		$node->data_dir,  '--create-role',
47		"$dbname1,$dbname2,$dbname3,$dbname4"
48	]);
49$node->start;
50
51my $backupdir = $node->backup_dir;
52my $discard   = "$backupdir/discard.sql";
53my $plain     = "$backupdir/plain.sql";
54my $dirfmt    = "$backupdir/dirfmt";
55
56foreach my $dbname ($dbname1, $dbname2, $dbname3, $dbname4, 'CamelCase')
57{
58	$node->run_log([ 'createdb', $dbname ]);
59	$node->run_log([ 'createuser', '-s', $dbname ]);
60}
61
62
63# For these tests, pg_dumpall -r is used because it produces a short
64# dump.
65$node->command_ok(
66	[
67		'pg_dumpall', '-r', '-f', $discard, '--dbname',
68		$node->connstr($dbname1),
69		'-U', $dbname4
70	],
71	'pg_dumpall with long ASCII name 1');
72$node->command_ok(
73	[
74		'pg_dumpall', '--no-sync', '-r', '-f', $discard, '--dbname',
75		$node->connstr($dbname2),
76		'-U', $dbname3
77	],
78	'pg_dumpall with long ASCII name 2');
79$node->command_ok(
80	[
81		'pg_dumpall', '--no-sync', '-r', '-f', $discard, '--dbname',
82		$node->connstr($dbname3),
83		'-U', $dbname2
84	],
85	'pg_dumpall with long ASCII name 3');
86$node->command_ok(
87	[
88		'pg_dumpall', '--no-sync', '-r', '-f', $discard, '--dbname',
89		$node->connstr($dbname4),
90		'-U', $dbname1
91	],
92	'pg_dumpall with long ASCII name 4');
93$node->command_ok(
94	[ 'pg_dumpall', '--no-sync', '-r', '-l', 'dbname=template1' ],
95	'pg_dumpall -l accepts connection string');
96
97$node->run_log([ 'createdb', "foo\n\rbar" ]);
98
99# not sufficient to use -r here
100$node->command_fails(
101	[ 'pg_dumpall', '--no-sync', '-f', $discard ],
102	'pg_dumpall with \n\r in database name');
103$node->run_log([ 'dropdb', "foo\n\rbar" ]);
104
105
106# make a table, so the parallel worker has something to dump
107$node->safe_psql($dbname1, 'CREATE TABLE t0()');
108
109# XXX no printed message when this fails, just SIGPIPE termination
110$node->command_ok(
111	[
112		'pg_dump', '-Fd', '--no-sync', '-j2', '-f', $dirfmt, '-U', $dbname1,
113		$node->connstr($dbname1)
114	],
115	'parallel dump');
116
117# recreate $dbname1 for restore test
118$node->run_log([ 'dropdb',   $dbname1 ]);
119$node->run_log([ 'createdb', $dbname1 ]);
120
121$node->command_ok(
122	[ 'pg_restore', '-v', '-d', 'template1', '-j2', '-U', $dbname1, $dirfmt ],
123	'parallel restore');
124
125$node->run_log([ 'dropdb', $dbname1 ]);
126
127$node->command_ok(
128	[
129		'pg_restore', '-C',  '-v', '-d',
130		'template1',  '-j2', '-U', $dbname1,
131		$dirfmt
132	],
133	'parallel restore with create');
134
135
136$node->command_ok([ 'pg_dumpall', '--no-sync', '-f', $plain, '-U', $dbname1 ],
137	'take full dump');
138system_log('cat', $plain);
139my ($stderr, $result);
140my $bootstrap_super = 'boot';
141my $restore_super   = qq{a'b\\c=d\\ne"f};
142
143
144# Restore full dump through psql using environment variables for
145# dbname/user connection parameters
146
147my $envar_node = get_new_node('destination_envar');
148$envar_node->init(
149	extra => [ '-U', $bootstrap_super, '--locale=C', '--encoding=LATIN1' ]);
150$envar_node->run_log(
151	[
152		$ENV{PG_REGRESS},      '--config-auth',
153		$envar_node->data_dir, '--create-role',
154		"$bootstrap_super,$restore_super"
155	]);
156$envar_node->start;
157
158# make superuser for restore
159$envar_node->run_log(
160	[ 'createuser', '-U', $bootstrap_super, '-s', $restore_super ]);
161
162{
163	local $ENV{PGPORT} = $envar_node->port;
164	local $ENV{PGUSER} = $restore_super;
165	$result = run_log([ 'psql', '-X', '-f', $plain ], '2>', \$stderr);
166}
167ok($result,
168	'restore full dump using environment variables for connection parameters'
169);
170is($stderr, '', 'no dump errors');
171
172
173# Restore full dump through psql using command-line options for
174# dbname/user connection parameters.  "\connect dbname=" forgets
175# user/port from command line.
176
177$restore_super =~ s/"//g
178  if $TestLib::windows_os;    # IPC::Run mishandles '"' on Windows
179my $cmdline_node = get_new_node('destination_cmdline');
180$cmdline_node->init(
181	extra => [ '-U', $bootstrap_super, '--locale=C', '--encoding=LATIN1' ]);
182$cmdline_node->run_log(
183	[
184		$ENV{PG_REGRESS},        '--config-auth',
185		$cmdline_node->data_dir, '--create-role',
186		"$bootstrap_super,$restore_super"
187	]);
188$cmdline_node->start;
189$cmdline_node->run_log(
190	[ 'createuser', '-U', $bootstrap_super, '-s', $restore_super ]);
191{
192	$result = run_log(
193		[
194			'psql',         '-p', $cmdline_node->port, '-U',
195			$restore_super, '-X', '-f',                $plain
196		],
197		'2>',
198		\$stderr);
199}
200ok($result,
201	'restore full dump with command-line options for connection parameters');
202is($stderr, '', 'no dump errors');
203