Convert src/interfaces/libpq/test to a tap test.

The old form of the test needed a bunch of custom infrastructure. These days
tap tests provide the necessary infrastructure to do better.

We discussed whether to move this test to src/test/modules, alongside
libpq_pipeline, but concluded that the opposite direction would be
better. libpq_pipeline will be moved at a later date, once the buildfarm and
msvc build infrastructure is ready for it.

The invocation of the tap test will be added in the next commit. It involves
just enough buildsystem changes to be worth commiting separately. Can't happen
the other way round because prove errors out when invoked without tests.

Discussion: https://postgr.es/m/20220223203031.ezrd73ohvjgfksow@alap3.anarazel.de
This commit is contained in:
Andres Freund 2022-02-26 16:51:47 -08:00
parent 1155d8b8d5
commit ac25173cdb
7 changed files with 246 additions and 307 deletions

View file

@ -0,0 +1,244 @@
# Copyright (c) 2021-2022, PostgreSQL Global Development Group
use strict;
use warnings;
use PostgreSQL::Test::Utils;
use Test::More;
use IPC::Run;
# List of URIs tests. For each test the first element is the input string, the
# second the expected stdout and the third the expected stderr.
my @tests = (
[
q{postgresql://uri-user:secret@host:12345/db},
q{user='uri-user' password='secret' dbname='db' host='host' port='12345' (inet)},
q{},
],
[
q{postgresql://uri-user@host:12345/db},
q{user='uri-user' dbname='db' host='host' port='12345' (inet)}, q{},
],
[
q{postgresql://uri-user@host/db},
q{user='uri-user' dbname='db' host='host' (inet)}, q{},
],
[
q{postgresql://host:12345/db},
q{dbname='db' host='host' port='12345' (inet)}, q{},
],
[ q{postgresql://host/db}, q{dbname='db' host='host' (inet)}, q{}, ],
[
q{postgresql://uri-user@host:12345/},
q{user='uri-user' host='host' port='12345' (inet)},
q{},
],
[
q{postgresql://uri-user@host/},
q{user='uri-user' host='host' (inet)},
q{},
],
[ q{postgresql://uri-user@}, q{user='uri-user' (local)}, q{}, ],
[ q{postgresql://host:12345/}, q{host='host' port='12345' (inet)}, q{}, ],
[ q{postgresql://host:12345}, q{host='host' port='12345' (inet)}, q{}, ],
[ q{postgresql://host/db}, q{dbname='db' host='host' (inet)}, q{}, ],
[ q{postgresql://host/}, q{host='host' (inet)}, q{}, ],
[ q{postgresql://host}, q{host='host' (inet)}, q{}, ],
[ q{postgresql://}, q{(local)}, q{}, ],
[
q{postgresql://?hostaddr=127.0.0.1}, q{hostaddr='127.0.0.1' (inet)},
q{},
],
[
q{postgresql://example.com?hostaddr=63.1.2.4},
q{host='example.com' hostaddr='63.1.2.4' (inet)},
q{},
],
[ q{postgresql://%68ost/}, q{host='host' (inet)}, q{}, ],
[
q{postgresql://host/db?user=uri-user},
q{user='uri-user' dbname='db' host='host' (inet)},
q{},
],
[
q{postgresql://host/db?user=uri-user&port=12345},
q{user='uri-user' dbname='db' host='host' port='12345' (inet)},
q{},
],
[
q{postgresql://host/db?u%73er=someotheruser&port=12345},
q{user='someotheruser' dbname='db' host='host' port='12345' (inet)},
q{},
],
[
q{postgresql://host/db?u%7aer=someotheruser&port=12345}, q{},
q{uri-regress: invalid URI query parameter: "uzer"},
],
[
q{postgresql://host:12345?user=uri-user},
q{user='uri-user' host='host' port='12345' (inet)},
q{},
],
[
q{postgresql://host?user=uri-user},
q{user='uri-user' host='host' (inet)},
q{},
],
[ q{postgresql://host?}, q{host='host' (inet)}, q{}, ],
[
q{postgresql://[::1]:12345/db},
q{dbname='db' host='::1' port='12345' (inet)},
q{},
],
[ q{postgresql://[::1]/db}, q{dbname='db' host='::1' (inet)}, q{}, ],
[
q{postgresql://[2001:db8::1234]/}, q{host='2001:db8::1234' (inet)},
q{},
],
[
q{postgresql://[200z:db8::1234]/}, q{host='200z:db8::1234' (inet)},
q{},
],
[ q{postgresql://[::1]}, q{host='::1' (inet)}, q{}, ],
[ q{postgres://}, q{(local)}, q{}, ],
[ q{postgres:///}, q{(local)}, q{}, ],
[ q{postgres:///db}, q{dbname='db' (local)}, q{}, ],
[
q{postgres://uri-user@/db}, q{user='uri-user' dbname='db' (local)},
q{},
],
[
q{postgres://?host=/path/to/socket/dir},
q{host='/path/to/socket/dir' (local)},
q{},
],
[
q{postgresql://host?uzer=}, q{},
q{uri-regress: invalid URI query parameter: "uzer"},
],
[
q{postgre://},
q{},
q{uri-regress: missing "=" after "postgre://" in connection info string},
],
[
q{postgres://[::1},
q{},
q{uri-regress: end of string reached when looking for matching "]" in IPv6 host address in URI: "postgres://[::1"},
],
[
q{postgres://[]},
q{},
q{uri-regress: IPv6 host address may not be empty in URI: "postgres://[]"},
],
[
q{postgres://[::1]z},
q{},
q{uri-regress: unexpected character "z" at position 17 in URI (expected ":" or "/"): "postgres://[::1]z"},
],
[
q{postgresql://host?zzz},
q{},
q{uri-regress: missing key/value separator "=" in URI query parameter: "zzz"},
],
[
q{postgresql://host?value1&value2},
q{},
q{uri-regress: missing key/value separator "=" in URI query parameter: "value1"},
],
[
q{postgresql://host?key=key=value},
q{},
q{uri-regress: extra key/value separator "=" in URI query parameter: "key"},
],
[
q{postgres://host?dbname=%XXfoo}, q{},
q{uri-regress: invalid percent-encoded token: "%XXfoo"},
],
[
q{postgresql://a%00b},
q{},
q{uri-regress: forbidden value %00 in percent-encoded value: "a%00b"},
],
[
q{postgresql://%zz}, q{},
q{uri-regress: invalid percent-encoded token: "%zz"},
],
[
q{postgresql://%1}, q{},
q{uri-regress: invalid percent-encoded token: "%1"},
],
[
q{postgresql://%}, q{},
q{uri-regress: invalid percent-encoded token: "%"},
],
[ q{postgres://@host}, q{host='host' (inet)}, q{}, ],
[ q{postgres://host:/}, q{host='host' (inet)}, q{}, ],
[ q{postgres://:12345/}, q{port='12345' (local)}, q{}, ],
[
q{postgres://otheruser@?host=/no/such/directory},
q{user='otheruser' host='/no/such/directory' (local)},
q{},
],
[
q{postgres://otheruser@/?host=/no/such/directory},
q{user='otheruser' host='/no/such/directory' (local)},
q{},
],
[
q{postgres://otheruser@:12345?host=/no/such/socket/path},
q{user='otheruser' host='/no/such/socket/path' port='12345' (local)},
q{},
],
[
q{postgres://otheruser@:12345/db?host=/path/to/socket},
q{user='otheruser' dbname='db' host='/path/to/socket' port='12345' (local)},
q{},
],
[
q{postgres://:12345/db?host=/path/to/socket},
q{dbname='db' host='/path/to/socket' port='12345' (local)},
q{},
],
[
q{postgres://:12345?host=/path/to/socket},
q{host='/path/to/socket' port='12345' (local)},
q{},
],
[
q{postgres://%2Fvar%2Flib%2Fpostgresql/dbname},
q{dbname='dbname' host='/var/lib/postgresql' (local)},
q{},
]);
# test to run for each of the above test definitions
sub test_uri
{
local $Test::Builder::Level = $Test::Builder::Level + 1;
my $uri;
my %expect;
my %result;
($uri, $expect{stdout}, $expect{stderr}) = @$_;
$expect{'exit'} = $expect{stderr} eq '';
my $cmd = [ 'uri-regress', $uri ];
$result{exit} = IPC::Run::run $cmd, '>', \$result{stdout}, '2>',
\$result{stderr};
chomp($result{stdout});
chomp($result{stderr});
# use is_deeply so there's one test result for each test above, without
# loosing the information whether stdout/stderr mismatched.
is_deeply(\%result, \%expect, $uri);
}
foreach (@tests)
{
test_uri($_);
}
done_testing();

View file

@ -1,3 +1 @@
/uri-regress /uri-regress
/regress.diff
/regress.out

View file

@ -1,3 +1,5 @@
# src/interfaces/libpq/test/Makefile
subdir = src/interfaces/libpq/test subdir = src/interfaces/libpq/test
top_builddir = ../../../.. top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global include $(top_builddir)/src/Makefile.global
@ -13,10 +15,5 @@ PROGS = uri-regress
all: $(PROGS) all: $(PROGS)
installcheck: all
SRCDIR='$(top_srcdir)' SUBDIR='$(subdir)' \
$(PERL) $(top_srcdir)/$(subdir)/regress.pl
clean distclean maintainer-clean: clean distclean maintainer-clean:
rm -f $(PROGS) *.o rm -f $(PROGS) *.o
rm -f regress.out regress.diff

View file

@ -1,7 +0,0 @@
This is a testsuite for testing libpq URI connection string syntax.
To run the suite, use 'make installcheck' command. It works by
running 'regress.pl' from this directory with appropriate environment
set up, which in turn feeds up lines from 'regress.in' to
'uri-regress' test program and compares the output against the correct
one in 'expected.out' file.

View file

@ -1,171 +0,0 @@
trying postgresql://uri-user:secret@host:12345/db
user='uri-user' password='secret' dbname='db' host='host' port='12345' (inet)
trying postgresql://uri-user@host:12345/db
user='uri-user' dbname='db' host='host' port='12345' (inet)
trying postgresql://uri-user@host/db
user='uri-user' dbname='db' host='host' (inet)
trying postgresql://host:12345/db
dbname='db' host='host' port='12345' (inet)
trying postgresql://host/db
dbname='db' host='host' (inet)
trying postgresql://uri-user@host:12345/
user='uri-user' host='host' port='12345' (inet)
trying postgresql://uri-user@host/
user='uri-user' host='host' (inet)
trying postgresql://uri-user@
user='uri-user' (local)
trying postgresql://host:12345/
host='host' port='12345' (inet)
trying postgresql://host:12345
host='host' port='12345' (inet)
trying postgresql://host/db
dbname='db' host='host' (inet)
trying postgresql://host/
host='host' (inet)
trying postgresql://host
host='host' (inet)
trying postgresql://
(local)
trying postgresql://?hostaddr=127.0.0.1
hostaddr='127.0.0.1' (inet)
trying postgresql://example.com?hostaddr=63.1.2.4
host='example.com' hostaddr='63.1.2.4' (inet)
trying postgresql://%68ost/
host='host' (inet)
trying postgresql://host/db?user=uri-user
user='uri-user' dbname='db' host='host' (inet)
trying postgresql://host/db?user=uri-user&port=12345
user='uri-user' dbname='db' host='host' port='12345' (inet)
trying postgresql://host/db?u%73er=someotheruser&port=12345
user='someotheruser' dbname='db' host='host' port='12345' (inet)
trying postgresql://host/db?u%7aer=someotheruser&port=12345
uri-regress: invalid URI query parameter: "uzer"
trying postgresql://host:12345?user=uri-user
user='uri-user' host='host' port='12345' (inet)
trying postgresql://host?user=uri-user
user='uri-user' host='host' (inet)
trying postgresql://host?
host='host' (inet)
trying postgresql://[::1]:12345/db
dbname='db' host='::1' port='12345' (inet)
trying postgresql://[::1]/db
dbname='db' host='::1' (inet)
trying postgresql://[2001:db8::1234]/
host='2001:db8::1234' (inet)
trying postgresql://[200z:db8::1234]/
host='200z:db8::1234' (inet)
trying postgresql://[::1]
host='::1' (inet)
trying postgres://
(local)
trying postgres:///
(local)
trying postgres:///db
dbname='db' (local)
trying postgres://uri-user@/db
user='uri-user' dbname='db' (local)
trying postgres://?host=/path/to/socket/dir
host='/path/to/socket/dir' (local)
trying postgresql://host?uzer=
uri-regress: invalid URI query parameter: "uzer"
trying postgre://
uri-regress: missing "=" after "postgre://" in connection info string
trying postgres://[::1
uri-regress: end of string reached when looking for matching "]" in IPv6 host address in URI: "postgres://[::1"
trying postgres://[]
uri-regress: IPv6 host address may not be empty in URI: "postgres://[]"
trying postgres://[::1]z
uri-regress: unexpected character "z" at position 17 in URI (expected ":" or "/"): "postgres://[::1]z"
trying postgresql://host?zzz
uri-regress: missing key/value separator "=" in URI query parameter: "zzz"
trying postgresql://host?value1&value2
uri-regress: missing key/value separator "=" in URI query parameter: "value1"
trying postgresql://host?key=key=value
uri-regress: extra key/value separator "=" in URI query parameter: "key"
trying postgres://host?dbname=%XXfoo
uri-regress: invalid percent-encoded token: "%XXfoo"
trying postgresql://a%00b
uri-regress: forbidden value %00 in percent-encoded value: "a%00b"
trying postgresql://%zz
uri-regress: invalid percent-encoded token: "%zz"
trying postgresql://%1
uri-regress: invalid percent-encoded token: "%1"
trying postgresql://%
uri-regress: invalid percent-encoded token: "%"
trying postgres://@host
host='host' (inet)
trying postgres://host:/
host='host' (inet)
trying postgres://:12345/
port='12345' (local)
trying postgres://otheruser@?host=/no/such/directory
user='otheruser' host='/no/such/directory' (local)
trying postgres://otheruser@/?host=/no/such/directory
user='otheruser' host='/no/such/directory' (local)
trying postgres://otheruser@:12345?host=/no/such/socket/path
user='otheruser' host='/no/such/socket/path' port='12345' (local)
trying postgres://otheruser@:12345/db?host=/path/to/socket
user='otheruser' dbname='db' host='/path/to/socket' port='12345' (local)
trying postgres://:12345/db?host=/path/to/socket
dbname='db' host='/path/to/socket' port='12345' (local)
trying postgres://:12345?host=/path/to/socket
host='/path/to/socket' port='12345' (local)
trying postgres://%2Fvar%2Flib%2Fpostgresql/dbname
dbname='dbname' host='/var/lib/postgresql' (local)

View file

@ -1,57 +0,0 @@
postgresql://uri-user:secret@host:12345/db
postgresql://uri-user@host:12345/db
postgresql://uri-user@host/db
postgresql://host:12345/db
postgresql://host/db
postgresql://uri-user@host:12345/
postgresql://uri-user@host/
postgresql://uri-user@
postgresql://host:12345/
postgresql://host:12345
postgresql://host/db
postgresql://host/
postgresql://host
postgresql://
postgresql://?hostaddr=127.0.0.1
postgresql://example.com?hostaddr=63.1.2.4
postgresql://%68ost/
postgresql://host/db?user=uri-user
postgresql://host/db?user=uri-user&port=12345
postgresql://host/db?u%73er=someotheruser&port=12345
postgresql://host/db?u%7aer=someotheruser&port=12345
postgresql://host:12345?user=uri-user
postgresql://host?user=uri-user
postgresql://host?
postgresql://[::1]:12345/db
postgresql://[::1]/db
postgresql://[2001:db8::1234]/
postgresql://[200z:db8::1234]/
postgresql://[::1]
postgres://
postgres:///
postgres:///db
postgres://uri-user@/db
postgres://?host=/path/to/socket/dir
postgresql://host?uzer=
postgre://
postgres://[::1
postgres://[]
postgres://[::1]z
postgresql://host?zzz
postgresql://host?value1&value2
postgresql://host?key=key=value
postgres://host?dbname=%XXfoo
postgresql://a%00b
postgresql://%zz
postgresql://%1
postgresql://%
postgres://@host
postgres://host:/
postgres://:12345/
postgres://otheruser@?host=/no/such/directory
postgres://otheruser@/?host=/no/such/directory
postgres://otheruser@:12345?host=/no/such/socket/path
postgres://otheruser@:12345/db?host=/path/to/socket
postgres://:12345/db?host=/path/to/socket
postgres://:12345?host=/path/to/socket
postgres://%2Fvar%2Flib%2Fpostgresql/dbname

View file

@ -1,65 +0,0 @@
#!/usr/bin/perl
# Copyright (c) 2021-2022, PostgreSQL Global Development Group
use strict;
use warnings;
# use of SRCDIR/SUBDIR is required for supporting VPath builds
my $srcdir = $ENV{'SRCDIR'} or die 'SRCDIR environment variable is not set';
my $subdir = $ENV{'SUBDIR'} or die 'SUBDIR environment variable is not set';
my $regress_in = "$srcdir/$subdir/regress.in";
my $expected_out = "$srcdir/$subdir/expected.out";
# the output file should land in the build_dir of VPath, or just in
# the current dir, if VPath isn't used
my $regress_out = "regress.out";
# open input file first, so possible error isn't sent to redirected STDERR
open(my $regress_in_fh, "<", $regress_in)
or die "can't open $regress_in for reading: $!";
# save STDOUT/ERR and redirect both to regress.out
open(my $oldout_fh, ">&", \*STDOUT) or die "can't dup STDOUT: $!";
open(my $olderr_fh, ">&", \*STDERR) or die "can't dup STDERR: $!";
open(STDOUT, ">", $regress_out)
or die "can't open $regress_out for writing: $!";
open(STDERR, ">&", \*STDOUT) or die "can't dup STDOUT: $!";
# read lines from regress.in and run uri-regress on them
while (<$regress_in_fh>)
{
chomp;
print "trying $_\n";
system("./uri-regress \"$_\"");
print "\n";
}
# restore STDOUT/ERR so we can print the outcome to the user
open(STDERR, ">&", $olderr_fh)
or die; # can't complain as STDERR is still duped
open(STDOUT, ">&", $oldout_fh) or die "can't restore STDOUT: $!";
# just in case
close $regress_in_fh;
my $diff_status = system(
"diff -c \"$srcdir/$subdir/expected.out\" regress.out >regress.diff");
print "=" x 70, "\n";
if ($diff_status == 0)
{
print "All tests passed\n";
exit 0;
}
else
{
print <<EOF;
FAILED: the test result differs from the expected output
Review the difference in "$subdir/regress.diff"
EOF
exit 1;
}