summaryrefslogtreecommitdiffstats
path: root/src/interfaces/libpq/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/libpq/test')
-rw-r--r--src/interfaces/libpq/test/.gitignore3
-rw-r--r--src/interfaces/libpq/test/Makefile22
-rw-r--r--src/interfaces/libpq/test/README7
-rw-r--r--src/interfaces/libpq/test/expected.out171
-rw-r--r--src/interfaces/libpq/test/regress.in57
-rw-r--r--src/interfaces/libpq/test/regress.pl65
-rw-r--r--src/interfaces/libpq/test/uri-regress.c84
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;
+}