diff options
Diffstat (limited to 'src/interfaces/libpq/test')
-rw-r--r-- | src/interfaces/libpq/test/.gitignore | 3 | ||||
-rw-r--r-- | src/interfaces/libpq/test/Makefile | 22 | ||||
-rw-r--r-- | src/interfaces/libpq/test/README | 7 | ||||
-rw-r--r-- | src/interfaces/libpq/test/expected.out | 171 | ||||
-rw-r--r-- | src/interfaces/libpq/test/regress.in | 57 | ||||
-rw-r--r-- | src/interfaces/libpq/test/regress.pl | 65 | ||||
-rw-r--r-- | src/interfaces/libpq/test/uri-regress.c | 84 |
7 files changed, 409 insertions, 0 deletions
diff --git a/src/interfaces/libpq/test/.gitignore b/src/interfaces/libpq/test/.gitignore new file mode 100644 index 0000000..5387b3b --- /dev/null +++ b/src/interfaces/libpq/test/.gitignore @@ -0,0 +1,3 @@ +/uri-regress +/regress.diff +/regress.out diff --git a/src/interfaces/libpq/test/Makefile b/src/interfaces/libpq/test/Makefile new file mode 100644 index 0000000..4832fab --- /dev/null +++ b/src/interfaces/libpq/test/Makefile @@ -0,0 +1,22 @@ +subdir = src/interfaces/libpq/test +top_builddir = ../../../.. +include $(top_builddir)/src/Makefile.global + +ifeq ($(PORTNAME), win32) +LDFLAGS += -lws2_32 +endif + +override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) +LDFLAGS_INTERNAL += $(libpq_pgport) + +PROGS = uri-regress + +all: $(PROGS) + +installcheck: all + SRCDIR='$(top_srcdir)' SUBDIR='$(subdir)' \ + $(PERL) $(top_srcdir)/$(subdir)/regress.pl + +clean distclean maintainer-clean: + rm -f $(PROGS) *.o + rm -f regress.out regress.diff diff --git a/src/interfaces/libpq/test/README b/src/interfaces/libpq/test/README new file mode 100644 index 0000000..a05eb6b --- /dev/null +++ b/src/interfaces/libpq/test/README @@ -0,0 +1,7 @@ +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. diff --git a/src/interfaces/libpq/test/expected.out b/src/interfaces/libpq/test/expected.out new file mode 100644 index 0000000..d375e82 --- /dev/null +++ b/src/interfaces/libpq/test/expected.out @@ -0,0 +1,171 @@ +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) + diff --git a/src/interfaces/libpq/test/regress.in b/src/interfaces/libpq/test/regress.in new file mode 100644 index 0000000..de034f3 --- /dev/null +++ b/src/interfaces/libpq/test/regress.in @@ -0,0 +1,57 @@ +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 diff --git a/src/interfaces/libpq/test/regress.pl b/src/interfaces/libpq/test/regress.pl new file mode 100644 index 0000000..de705cf --- /dev/null +++ b/src/interfaces/libpq/test/regress.pl @@ -0,0 +1,65 @@ +#!/usr/bin/perl + +# Copyright (c) 2021, 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; +} diff --git a/src/interfaces/libpq/test/uri-regress.c b/src/interfaces/libpq/test/uri-regress.c new file mode 100644 index 0000000..84fc52a --- /dev/null +++ b/src/interfaces/libpq/test/uri-regress.c @@ -0,0 +1,84 @@ +/* + * uri-regress.c + * A test program for libpq URI format + * + * This is a helper for libpq conninfo regression testing. It takes a single + * conninfo string as a parameter, parses it using PQconninfoParse, and then + * prints out the values from the parsed PQconninfoOption struct that differ + * from the defaults (obtained from PQconndefaults). + * + * Portions Copyright (c) 2012-2021, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/interfaces/libpq/test/uri-regress.c + */ + +#include "postgres_fe.h" + +#include "libpq-fe.h" + +int +main(int argc, char *argv[]) +{ + PQconninfoOption *opts; + PQconninfoOption *defs; + PQconninfoOption *opt; + PQconninfoOption *def; + char *errmsg = NULL; + bool local = true; + + if (argc != 2) + return 1; + + opts = PQconninfoParse(argv[1], &errmsg); + if (opts == NULL) + { + fprintf(stderr, "uri-regress: %s", errmsg); + return 1; + } + + defs = PQconndefaults(); + if (defs == NULL) + { + fprintf(stderr, "uri-regress: cannot fetch default options\n"); + return 1; + } + + /* + * Loop on the options, and print the value of each if not the default. + * + * XXX this coding assumes that PQconninfoOption structs always have the + * keywords in the same order. + */ + for (opt = opts, def = defs; opt->keyword; ++opt, ++def) + { + if (opt->val != NULL) + { + if (def->val == NULL || strcmp(opt->val, def->val) != 0) + printf("%s='%s' ", opt->keyword, opt->val); + + /* + * Try to detect if this is a Unix-domain socket or inet. This is + * a bit grotty but it's the same thing that libpq itself does. + * + * Note that we directly test for '/' instead of using + * is_absolute_path, as that would be considerably more messy. + * This would fail on Windows, but that platform doesn't have + * Unix-domain sockets anyway. + */ + if (*opt->val && + (strcmp(opt->keyword, "hostaddr") == 0 || + (strcmp(opt->keyword, "host") == 0 && *opt->val != '/'))) + { + local = false; + } + } + } + + if (local) + printf("(local)\n"); + else + printf("(inet)\n"); + + return 0; +} |