1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
|
# Check operation with multiple clusters
use strict;
use lib 't';
use TestLib;
use Socket;
use PgCommon;
use Test::More tests => 125;
# Replace all md5 and password authentication methods with 'trust' in given
# pg_hba.conf file.
sub hba_password_to_ident {
open F, $_[0] or die "open $_[0]: $!";
my $hba;
read F, $hba, 10000;
$hba =~ s/md5/trust/g;
$hba =~ s/password/trust/g;
close F;
open F, ">$_[0]" or die "open $_[0]: $!";
print F $hba;
close F;
chmod 0644, $_[0] or die "chmod $_[0]: $!";
}
# create fake socket at 5433 to verify that this port is skipped
socket (SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp')) or die "socket: $!";
bind (SOCK, sockaddr_in(5433, INADDR_ANY)) || die "bind: $! ";
# create clusters
is ((system "pg_createcluster $MAJORS[0] old >/dev/null"), 0, "pg_createcluster $MAJORS[0] old");
is ((system "pg_createcluster $MAJORS[-1] new1 >/dev/null"), 0, "pg_createcluster $MAJORS[-1] new1");
is ((system "pg_createcluster $MAJORS[-1] new2 -p 5440 >/dev/null"), 0, "pg_createcluster $MAJORS[-1] new2");
my $old = "$MAJORS[0]/old";
my $new1 = "$MAJORS[-1]/new1";
my $new2 = "$MAJORS[-1]/new2";
# disable password auth for network cluster selection tests
hba_password_to_ident "/etc/postgresql/$old/pg_hba.conf";
hba_password_to_ident "/etc/postgresql/$new1/pg_hba.conf";
hba_password_to_ident "/etc/postgresql/$new2/pg_hba.conf";
is ((system "pg_ctlcluster $MAJORS[0] old start >/dev/null"), 0, "starting cluster $old");
is ((system "pg_ctlcluster $MAJORS[-1] new1 start >/dev/null"), 0, "starting cluster $new1");
is ((system "pg_ctlcluster $MAJORS[-1] new2 start >/dev/null"), 0, "starting cluster $new2");
like_program_out 'postgres', 'pg_lsclusters -h | sort -k3', 0, qr/.*5432.*5434.*5440.*/s,
'clusters have the correct ports, skipping used 5433';
# move user_clusters aside for the test; this will ensure that client programs
# work correctly without any file at all
if (-f '/etc/postgresql-common/user_clusters') {
ok ((rename '/etc/postgresql-common/user_clusters',
'/etc/postgresql-common/user_clusters.psqltestsuite'),
'Temporarily moving away /etc/postgresql-common/user_clusters');
} else {
pass '/etc/postgresql-common/user_clusters does not exist';
}
# check basic cluster selection
like_program_out 0, 'createdb --version', 0, qr/^createdb \(PostgreSQL\) $MAJORS[0]/,
'pg_wrapper selects port 5432 as default cluster';
like_program_out 0, "createdb --cluster $new1 --version", 0,
qr/^createdb \(PostgreSQL\) $MAJORS[-1]/,
'pg_wrapper --cluster works';
like_program_out 0, "createdb --cluster $MAJORS[-1]/foo --version", 1,
qr/Cluster .* does not exist/,
'pg_wrapper --cluster errors out for invalid cluster';
# create a database in new1 and check that it doesn't appear in new2
is_program_out 'postgres', "createdb --cluster $new1 test", 0, ($MAJORS[-1] < 8.3 ? "CREATE DATABASE\n" : '');
like_program_out 'postgres', "psql -Atl --cluster $new1", 0,
qr/test\|postgres\|/,
'test db appears in cluster new1';
unlike_program_out 'postgres', "psql -Atl --cluster $new2", 0,
qr/test\|postgres\|/,
'test db does not appear in cluster new2';
unlike_program_out 'postgres', "psql -Atl", 0, qr/test\|postgres\|/,
'test db does not appear in default cluster';
# check network cluster selection
is_program_out 'postgres', "psql --cluster $MAJORS[0]/127.0.0.1: -Atc 'show port' template1", 0, "5432\n",
"psql --cluster $MAJORS[0]/127.0.0.1: defaults to port 5432";
like_program_out 'postgres', "createdb --cluster $MAJORS[-1]/127.0.0.1:5432 --version", 0,
qr/^createdb \(PostgreSQL\) $MAJORS[-1]/,
"createdb --cluster $MAJORS[-1]/127.0.0.1:5432 uses latest client version";
like_program_out 'postgres', "psql -Atl --cluster $MAJORS[-1]/localhost:5434", 0,
qr/test\|postgres\|/, "test db appears in cluster $MAJORS[-1]/localhost:5434";
unlike_program_out 'postgres', "psql -Atl --cluster $MAJORS[-1]/localhost:5440", 0,
qr/test\|postgres\|/, "test db does not appear in cluster $MAJORS[-1]/localhost:5440";
# check some erroneous cluster specifications
like_program_out 'postgres', "LC_MESSAGES=C psql -Atl --cluster $MAJORS[-1]/localhost:5435", 2,
qr/could not connect/, "psql --cluster $MAJORS[-1]/localhost:5435 fails due to nonexisting port";
like_program_out 'postgres', "LC_MESSAGES=C psql -Atl --cluster $MAJORS[-1]/localhost:a", 1,
qr/Cluster .* does not exist/, "psql --cluster $MAJORS[-1]/localhost:a fails due to invalid syntax";
like_program_out 'postgres', "LC_MESSAGES=C psql -Atl --cluster $MAJORS[-1]/doesnotexi.st", 1,
qr/Cluster .* does not exist/, "psql --cluster $MAJORS[-1]/doesnotexi.st fails due to invalid syntax";
like_program_out 'postgres', "psql -Atl --cluster 6.4/localhost:", 1,
qr/Invalid version/, "psql --cluster 6.4/localhost: fails due to invalid version";
# check that environment variables work
$ENV{'PGCLUSTER'} = $new1;
like_program_out 'postgres', "psql -Atl", 0, qr/test\|postgres\|/,
'PGCLUSTER selection (1)';
$ENV{'PGCLUSTER'} = $new2;
unlike_program_out 'postgres', "psql -Atl", 0, qr/test\|postgres\|/,
'PGCLUSTER selection (2)';
$ENV{'PGCLUSTER'} = 'foo';
like_program_out 'postgres', "psql -l", 1,
qr/Invalid version .* specified in PGCLUSTER/,
'invalid PGCLUSTER value';
$ENV{'PGCLUSTER'} = "$MAJORS[-1]/127.0.0.1:";
like_program_out 0, 'createdb --version', 0, qr/^createdb \(PostgreSQL\) $MAJORS[-1]/,
'PGCLUSTER network cluster selection (1)';
$ENV{'PGCLUSTER'} = "$MAJORS[-1]/localhost:5434";
like_program_out 'postgres', 'psql -Atl', 0,
qr/test\|postgres\|/, 'PGCLUSTER network cluster selection (2)';
$ENV{'PGCLUSTER'} = "$MAJORS[-1]/localhost:5440";
unlike_program_out 'postgres', 'psql -Atl', 0,
qr/test\|postgres\|/, 'PGCLUSTER network cluster selection (3)';
$ENV{'PGCLUSTER'} = "$MAJORS[-1]/localhost:5435";
like_program_out 'postgres', 'LC_MESSAGES=C psql -Atl', 2,
qr/could not connect/, "psql --cluster $MAJORS[-1]/localhost:5435 fails due to nonexisting port";
delete $ENV{'PGCLUSTER'};
# check that PGPORT works
$ENV{'PGPORT'} = '5434';
is_program_out 'postgres', 'psql -Atc "show port" template1', 0, "5434\n",
'PGPORT selection (1)';
$ENV{'PGPORT'} = '5432';
is_program_out 'postgres', 'psql -Atc "show port" template1', 0, "5432\n",
'PGPORT selection (2)';
$ENV{'PGCLUSTER'} = $new2;
delete $ENV{'PGPORT'};
$ENV{'PGPORT'} = '5432';
like_program_out 'postgres', 'createdb --version', 0, qr/^createdb \(PostgreSQL\) $MAJORS[-1]/,
'PGPORT+PGCLUSTER, PGCLUSTER selects version';
is_program_out 'postgres', 'psql -Atc "show port" template1', 0, "5432\n",
'PGPORT+PGCLUSTER, PGPORT selects port';
delete $ENV{'PGPORT'};
delete $ENV{'PGCLUSTER'};
# check that PGDATABASE works
$ENV{'PGDATABASE'} = 'test';
is_program_out 'postgres', "psql --cluster $new1 -Atc 'select current_database()'", 0, "test\n",
'PGDATABASE environment variable works';
delete $ENV{'PGDATABASE'};
# check cluster selection with an empty user_clusters
open F, '>/etc/postgresql-common/user_clusters' or die "Could not create user_clusters: $!";
close F;
chmod 0644, '/etc/postgresql-common/user_clusters';
like_program_out 0, 'createdb --version', 0, qr/^createdb \(PostgreSQL\) $MAJORS[0]/,
'pg_wrapper selects port 5432 as default cluster with empty user_clusters';
like_program_out 0, "createdb --cluster $new1 --version", 0,
qr/^createdb \(PostgreSQL\) $MAJORS[-1]/,
'pg_wrapper --cluster works with empty user_clusters';
# check default cluster selection with user_clusters
open F, '>/etc/postgresql-common/user_clusters' or die "Could not create user_clusters: $!";
print F "* * $MAJORS[-1] new1 *\n";
close F;
chmod 0644, '/etc/postgresql-common/user_clusters';
like_program_out 'postgres', 'createdb --version', 0, qr/^createdb \(PostgreSQL\) $MAJORS[-1]/,
"pg_wrapper selects correct cluster with user_clusters '* * $MAJORS[-1] new1 *'";
# check default database selection with user_clusters
open F, '>/etc/postgresql-common/user_clusters' or die "Could not create user_clusters: $!";
print F "* * $MAJORS[-1] new1 test\n";
close F;
chmod 0644, '/etc/postgresql-common/user_clusters';
is_program_out 'postgres', 'psql -Atc "select current_database()"', 0, "test\n",
"pg_wrapper selects correct database with user_clusters '* * $MAJORS[-1] new1 test'";
$ENV{'PGDATABASE'} = 'template1';
is_program_out 'postgres', "psql -Atc 'select current_database()'", 0, "template1\n",
'PGDATABASE environment variable is not overridden by user_clusters';
delete $ENV{'PGDATABASE'};
# check by-user cluster selection with user_clusters
# (also check invalid cluster reporting)
open F, '>/etc/postgresql-common/user_clusters' or die "Could not create user_clusters: $!";
print F "postgres * $MAJORS[-1] new1 *\nnobody * $MAJORS[0] old *\n* * 5.5 * *";
close F;
chmod 0644, '/etc/postgresql-common/user_clusters';
like_program_out 'postgres', 'createdb --version', 0, qr/^createdb \(PostgreSQL\) $MAJORS[-1]/,
'pg_wrapper selects correct cluster with per-user user_clusters';
like_program_out 'nobody', 'createdb --version', 0, qr/^createdb \(PostgreSQL\) $MAJORS[0]/,
'pg_wrapper selects correct cluster with per-user user_clusters';
like_program_out 0, 'createdb --version', 0, qr/user_clusters.*line 3.*version.*not exist/i,
'pg_wrapper warning for invalid per-user user_clusters line';
# check by-user network cluster selection with user_clusters
# (also check invalid cluster reporting)
open F, '>/etc/postgresql-common/user_clusters' or die "Could not create user_clusters: $!";
print F "postgres * $MAJORS[0] localhost: *\nnobody * $MAJORS[-1] new1 *\n* * $MAJORS[-1] localhost:a *";
close F;
chmod 0644, '/etc/postgresql-common/user_clusters';
like_program_out 'postgres', 'createdb --version', 0, qr/^createdb \(PostgreSQL\) $MAJORS[0]/,
'pg_wrapper selects correct version with per-user user_clusters';
like_program_out 'nobody', 'createdb --version', 0, qr/^createdb \(PostgreSQL\) $MAJORS[-1]/,
'pg_wrapper selects correct version with per-user user_clusters';
like_program_out 0, 'createdb --version', 0, qr/user_clusters.*line 3.*cluster.*not exist/i,
'pg_wrapper warning for invalid per-user user_clusters line';
# check PGHOST environment variable precedence
$ENV{'PGHOST'} = '127.0.0.2';
like_program_out 'postgres', 'psql -Atl', 2, qr/127.0.0.2/, '$PGHOST overrides user_clusters';
is_program_out 'postgres', "psql --cluster $MAJORS[-1]/localhost:5434 -Atc 'select current_database()' test",
0, "test\n", '--cluster overrides $PGHOST';
delete $ENV{'PGHOST'};
# check invalid user_clusters
open F, '>/etc/postgresql-common/user_clusters' or die "Could not create user_clusters: $!";
print F 'foo';
close F;
chmod 0644, '/etc/postgresql-common/user_clusters';
like_program_out 'postgres', 'createdb --version', 0, qr/ignoring invalid line 1/,
'pg_wrapper ignores invalid lines in user_clusters';
# remove test user_clusters
unlink '/etc/postgresql-common/user_clusters' or die
"unlink user_clusters: $!";
# check that pg_service.conf works
open F, '>/etc/postgresql-common/pg_service.conf' or die "Could not create pg_service.conf: $!";
print F "[old_t1]
user=postgres
dbname=template1
port=5432
[new1_test]
user=postgres
dbname=test
port=5434
# these do not exist
[new2_test]
user=postgres
dbname=test
port=5440
";
close F;
chmod 0644, '/etc/postgresql-common/pg_service.conf';
$ENV{'PGSERVICE'} = 'old_t1';
is_program_out 'postgres', "psql -Atc 'select current_database()'", 0,
"template1\n", 'pg_service conf selection 1';
$ENV{'PGSERVICE'} = 'new1_test';
is_program_out 'postgres', "psql -Atc 'select current_database()'", 0,
"test\n", 'pg_service conf selection 2';
$ENV{'PGSERVICE'} = 'new2_test';
like_program_out 'postgres', "psql -Atc 'select current_database()'", 2,
qr/FATAL.*test/, 'pg_service conf selection 3';
delete $ENV{'PGSERVICE'};
unlink '/etc/postgresql-common/pg_service.conf';
# check proper error message if no cluster could be determined as default for
# pg_wrapper
is ((system "pg_ctlcluster $MAJORS[0] old stop >/dev/null"), 0, "stopping cluster $old");
PgCommon::set_conf_value $MAJORS[0], 'old', 'postgresql.conf', 'port', '5435';
is ((system "pg_ctlcluster $MAJORS[0] old start >/dev/null"), 0, "restarting cluster $old");
like_program_out 'postgres', 'pg_lsclusters -h | sort -k3', 0, qr/.*5434.*5435.*5440.*/s,
'port of first cluster was successfully changed';
like_program_out 'postgres', "psql -l", 2,
qr/no.*default.*man pg_wrapper.*psql:.*\.s\.PGSQL.5432/is,
'proper pg_wrapper warning and psql error if no cluster is suitable as default target';
like_program_out 'postgres', "psql -Atl --cluster $new1", 0,
qr/test\|postgres\|/,
'--cluster selects appropriate cluster';
like_program_out 'postgres', "psql -Atl -p 5434", 0,
qr/test\|postgres\|/,
'-p selects appropriate cluster';
like_program_out 'postgres', "psql -Atlp 5434", 0,
qr/test\|postgres\|/,
'-Atlp selects appropriate cluster';
like_program_out 'postgres', "psql -Atl --port 5434", 0,
qr/test\|postgres\|/,
'--port selects appropriate cluster';
like_program_out 'postgres', "env PGPORT=5434 psql -Atl", 0,
qr/test\|postgres\|/,
'$PGPORT selects appropriate cluster';
# but specifying -p explicitly should work
# restore original user_clusters
if (-f '/etc/postgresql-common/user_clusters.psqltestsuite') {
ok ((rename '/etc/postgresql-common/user_clusters.psqltestsuite',
'/etc/postgresql-common/user_clusters'),
'Restoring original /etc/postgresql-common/user_clusters');
} else {
pass '/etc/postgresql-common/user_clusters did not exist, not restoring';
}
# clean up
is ((system "pg_dropcluster $MAJORS[-1] new1 --stop"), 0, "dropping $new1");
is ((system "pg_dropcluster $MAJORS[-1] new2 --stop"), 0, "dropping $new2");
is ((system "pg_dropcluster $MAJORS[0] old --stop"), 0, "dropping $old");
# unlike the others, this tests leaves TIME_WAIT on localhost behind (seen on CentOS; seen for PG <= 9.1)
note 'waiting for TCP ports to close';
for (1 .. 60) {
last if system 'netstat -avptn 2>/dev/null | grep -q ":543[2-9]\b"';
sleep 1;
}
check_clean;
# vim: filetype=perl
|