On Thu, Jan 30, 2020 at 7:36 AM Mark Dilger
<mark.dil...@enterprisedb.com> wrote:
>
>
>
> > On Jan 29, 2020, at 1:02 PM, Andrew Dunstan 
> > <andrew.duns...@2ndquadrant.com> wrote:
> >
> > On Wed, Jan 29, 2020 at 4:32 PM Andrew Dunstan
> > <andrew.duns...@2ndquadrant.com> wrote:
> >>
> >>
> >> On 1/28/20 5:28 PM, Mark Dilger wrote:
> >>>
> >>>
> >>>> +# There doesn't seem to be any easy way to get TestLib to use the 
> >>>> binaries from
> >>>> +# our directory, so we hack up a path to our binary and run that
> >>>> directly.  This
> >>>> +# seems brittle enough that some other solution should be found, if 
> >>>> possible.
> >>>> +
> >>>> +my $test_json = join('/', $ENV{TESTDIR}, 'test_json');
> >>>>
> >>>> I don't know what the right thing to do here is. Perhaps someone more
> >>>> familiar with TAP testing can comment.
> >>> Yeah, I was hoping that might get a comment from Andrew.  I think if it 
> >>> works as-is on windows, we could just use it this way until it causes a 
> >>> problem on some platform or other.  It’s not a runtime issue, being only 
> >>> a build-time test, and only then when tap tests are enabled *and* running 
> >>> check-world, so nobody should really be adversely affected.  I’ll likely 
> >>> get around to testing this on Windows, but I don’t have any Windows 
> >>> environments set up yet, as that is still on my todo list.
> >>>
> >>
> >>
> >> I think using TESTDIR is Ok,
> >
> >
> > I've changed my mind, I don't think that will work for MSVC, the
> > executable gets built elsewhere for that. I'll try to come up with
> > something portable.
>
> I’m just now working on getting my Windows VMs set up with Visual Studio and 
> whatnot, per the wiki instructions, so I don’t need to burden you with this 
> sort of Windows task in the future.  If there are any gotchas not mentioned 
> on the wiki, I’d appreciate pointers about how to avoid them.  I’ll try to 
> help devise a solution, or test what you come up with, once I’m properly set 
> up for that.
>
> For no particular reason, I chose Windows Server 2019 and Windows 10 Pro.
>


One VM should be sufficient. Either W10Pro os WS2019 would be fine. I
have buildfarm animals running on both.

Here's what I got working after a lot of trial and error. (This will
require a tiny change in the buildfarm script to make the animals test
it). Note that there is one test that I couldn't get working, so I
skipped it. If you can find out why it fails so much the better ... it
seems to be related to how the command processor handles quotes.

cheers

andrew


-- 
Andrew Dunstan                https://www.2ndQuadrant.com
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
diff --git a/src/Makefile b/src/Makefile
index bcdbd9588a..ccd4bab0de 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -2,7 +2,8 @@
 #
 # Makefile for src
 #
-# Copyright (c) 1994, Regents of the University of California
+# Portions Copyright (c) 1994, Regents of the University of California
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
 #
 # src/Makefile
 #
@@ -27,6 +28,7 @@ SUBDIRS = \
 	bin \
 	pl \
 	makefiles \
+	test/bin \
 	test/regress \
 	test/isolation \
 	test/perl
diff --git a/src/test/Makefile b/src/test/Makefile
index efb206aa75..6c3a1d4c27 100644
--- a/src/test/Makefile
+++ b/src/test/Makefile
@@ -12,7 +12,7 @@ subdir = src/test
 top_builddir = ../..
 include $(top_builddir)/src/Makefile.global
 
-SUBDIRS = perl regress isolation modules authentication recovery subscription
+SUBDIRS = bin perl regress isolation modules authentication recovery subscription
 
 # Test suites that are not safe by default but can be run if selected
 # by the user via the whitespace-separated list in variable
@@ -40,10 +40,10 @@ endif
 ALWAYS_SUBDIRS = $(filter-out $(SUBDIRS),examples kerberos ldap locale thread ssl)
 
 # We want to recurse to all subdirs for all standard targets, except that
-# installcheck and install should not recurse into the subdirectory "modules".
+# installcheck and install should not recurse into "modules" or "bin"
 
 recurse_alldirs_targets := $(filter-out installcheck install, $(standard_targets))
-installable_dirs := $(filter-out modules, $(SUBDIRS))
+installable_dirs := $(filter-out modules bin, $(SUBDIRS))
 
 $(call recurse,$(recurse_alldirs_targets))
 $(call recurse,installcheck, $(installable_dirs))
diff --git a/src/test/bin/.gitignore b/src/test/bin/.gitignore
new file mode 100644
index 0000000000..6709c749d8
--- /dev/null
+++ b/src/test/bin/.gitignore
@@ -0,0 +1 @@
+test_json
diff --git a/src/test/bin/Makefile b/src/test/bin/Makefile
new file mode 100644
index 0000000000..113ce04cba
--- /dev/null
+++ b/src/test/bin/Makefile
@@ -0,0 +1,43 @@
+#-------------------------------------------------------------------------
+#
+# Makefile for src/test/bin
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/bin/bin/Makefile
+#
+#-------------------------------------------------------------------------
+
+PGFILEDESC = "bin - the PostgreSQL standalone code binaries for testing"
+PGAPPICON=win32
+
+subdir = src/test/bin
+top_builddir = ../../..
+include $(top_builddir)/src/Makefile.global
+
+# make this available to TAP test scripts
+export with_readline
+
+REFDOCDIR= $(top_srcdir)/doc/src/sgml/ref
+
+override CPPFLAGS := -I. -I$(srcdir) -I$(libpq_srcdir) $(CPPFLAGS)
+LDFLAGS_INTERNAL += -L$(top_builddir)/src/fe_utils -lpgfeutils $(libpq_pgport)
+
+OBJS = \
+	$(WIN32RES) \
+	test_json.o
+
+PROGRAMS = test_json
+
+all: test_json
+
+test_json: test_json.o $(WIN32RES) | submake-libpq submake-libpgport submake-libpgfeutils
+	$(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
+
+check:
+	PATH="$(abs_top_builddir)/src/test/bin:$$PATH" $(prove_check)
+
+clean distclean maintainer-clean:
+	rm -f test_json$(X) $(OBJS)
+	rm -rf tmp_check
diff --git a/src/test/bin/README b/src/test/bin/README
new file mode 100644
index 0000000000..239bd8456f
--- /dev/null
+++ b/src/test/bin/README
@@ -0,0 +1,11 @@
+src/test/bin/README
+
+Binary executable tests
+=======================
+
+This directory contains programs that are built and executed for testing
+purposes, but never installed. It may be used, for example, to test that code
+in src/common works in frontend environments.
+
+These test programs are part of the tap-test suite.  Configure with tap tests
+enabled or these tests will be skipped.
diff --git a/src/test/bin/t/001_test_json.pl b/src/test/bin/t/001_test_json.pl
new file mode 100644
index 0000000000..50b06e0726
--- /dev/null
+++ b/src/test/bin/t/001_test_json.pl
@@ -0,0 +1,72 @@
+# Basic logical replication test
+use strict;
+use warnings;
+use TestLib qw(command_like $windows_os);
+
+use Test::More tests => 83;
+
+my $exe = $windows_os ? ".exe" : "";
+
+# We don't install test_json, so we pick it up from the
+# place it  gets built, $ENV{TESTDIR} except for MSVC
+
+my $binloc = ".";
+my $using_msvc = 0;
+
+if (-e "../../../test_json.vcxproj") # MSVC
+{
+	$using_msvc = 1;
+	if (-d "../../../Debug/test_json")
+	{
+		$binloc = "../../../Debug/test_json";
+	}
+	else
+	{
+		$binloc = "../../../Release/test_json";
+	}
+}
+elsif (exists $ENV{TESTDIR})
+{
+	$binloc = $ENV{TESTDIR};
+}
+
+my $test_json = "$binloc/test_json$exe";
+
+ok(-f $test_json, "test_json file exists");
+ok(-x $test_json, "test_json file is executable");
+
+# Verify some valid JSON is accepted by our parser
+command_like( [$test_json, q/null/       ], qr{\bVALID\b}, "null");
+command_like( [$test_json, q/{}/         ], qr{\bVALID\b}, "empty object");
+command_like( [$test_json, q/[]/         ], qr{\bVALID\b}, "empty array");
+command_like( [$test_json, q/-12345/     ], qr{\bVALID\b}, "negative integer");
+command_like( [$test_json, q/-1/         ], qr{\bVALID\b}, "negative integer");
+command_like( [$test_json, q/0/          ], qr{\bVALID\b}, "zero");
+command_like( [$test_json, q/1/          ], qr{\bVALID\b}, "positive integer");
+command_like( [$test_json, q/12345/      ], qr{\bVALID\b}, "positive integer");
+command_like( [$test_json, q/-1.23456789/], qr{\bVALID\b}, "negative float");
+command_like( [$test_json, q/1.23456789/ ], qr{\bVALID\b}, "positive float");
+command_like( [$test_json, q/{"a": "b"}/ ], qr{\bVALID\b}, "object");
+command_like( [$test_json, q/["a", "b"]/ ], qr{\bVALID\b}, "array");
+SKIP:
+{
+	skip "text string test confuses processor on MSVC", 3 if $using_msvc;
+
+	command_like( [$test_json, q/"pigs feet"/], qr{\bVALID\b}, 'text string');
+}
+
+# Verify some invalid JSON is rejected by our parser
+command_like( [$test_json, q/{/          ], qr{^\s*The input string ended unexpectedly\.\s*$}ms, 'unclosed object');
+command_like( [$test_json, q/[/          ], qr{^\s*The input string ended unexpectedly\.\s*$}ms, 'unclosed array');
+command_like( [$test_json, q/(/          ], qr{^\s*Token "\(" is invalid\.\s*$}ms, 'unclosed parenthesis');
+command_like( [$test_json, q/}/          ], qr{^\s*Expected JSON value, but found "\}"\.\s*$}ms, 'unopened object');
+command_like( [$test_json, q/]/          ], qr{^\s*Expected JSON value, but found "\]"\.\s*$}ms, 'unopened array');
+command_like( [$test_json, q/)/          ], qr{^\s*Token "\)" is invalid\.\s*$}ms, 'unopened parenthesis');
+command_like( [$test_json, q/{{{}}/      ], qr{^\s*Expected string or "\}", but found "\{"\.\s*$}ms, 'unbalanced object curlies');
+command_like( [$test_json, q/{{}}}/      ], qr{^\s*Expected string or "\}", but found "\{"\.\s*$}ms, 'unbalanced object curlies');
+command_like( [$test_json, q/[[[]]/      ], qr{^\s*The input string ended unexpectedly\.\s*$}ms, 'unbalanced array braces');
+command_like( [$test_json, q/[[]]]/      ], qr{^\s*Expected end of input, but found "\]"\.\s*$}ms, 'unbalanced array braces');
+command_like( [$test_json, q/((())/      ], qr{^\s*Token "\(" is invalid\.\s*$}ms, 'unbalanced array braces');
+command_like( [$test_json, q/(()))/      ], qr{^\s*Token "\(" is invalid\.\s*$}ms, 'unbalanced array braces');
+command_like( [$test_json, q/1 7 13/     ], qr{^\s*Expected end of input, but found "7"\.\s*$}ms, 'integer sequence');
+command_like( [$test_json, q/{"a", "b"}/ ], qr{^\s*Expected ":", but found ","\.\s*$}ms, 'mixed object and array syntax');
diff --git a/src/test/bin/test_json.c b/src/test/bin/test_json.c
new file mode 100644
index 0000000000..86ad9e7e2b
--- /dev/null
+++ b/src/test/bin/test_json.c
@@ -0,0 +1,62 @@
+/*
+ *	pg_test_json.c
+ *		tests validity of json strings against parser implementation.
+ */
+
+#include "postgres_fe.h"
+
+#include "common/jsonapi.h"
+#include "libpq-fe.h"
+
+static const char *progname;
+
+static void parse_json(const char *str);
+
+int
+main(int argc, char *argv[])
+{
+	int			argidx;
+
+	progname = get_progname(argv[0]);
+
+	if (argc > 1)
+	{
+		if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
+		{
+			printf(_("Usage: %s jsonstr [, ...]\n"), progname);
+			exit(0);
+		}
+		if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
+		{
+			puts("pg_test_json (PostgreSQL) " PG_VERSION);
+			exit(0);
+		}
+	}
+
+	for (argidx = 1; argidx < argc; argidx++)
+		parse_json(argv[argidx]);
+
+	return 0;
+}
+
+static void
+parse_json(const char *str)
+{
+	char *json;
+	JsonLexContext *lex;
+	int client_encoding;
+	JsonParseErrorType parse_result;
+
+	client_encoding = PQenv2encoding();
+
+	json = strdup(str);
+	lex = makeJsonLexContextCstringLen(json, strlen(json), client_encoding, true /* need_escapes */);
+	parse_result = pg_parse_json(lex, &nullSemAction);
+	if (JSON_SUCCESS == parse_result)
+		fprintf(stdout, _("VALID\n"));
+	else
+	{
+		const char *errstr = json_errdetail(parse_result, lex);
+		fprintf(stdout, _("%s\n"), errstr);
+	}
+}
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index a43e31c60e..12204b2b5c 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -814,6 +814,30 @@ sub mkvcbuild
 		$proj->AddLibrary('ws2_32.lib');
 	}
 
+	# test programs in src/test/bin
+	$mf = Project::read_file('src/test/bin/Makefile');
+	$mf =~ s{\\\r?\n}{}g;
+	$mf =~ m{PROGRAMS\s*=\s*(.*)$}m
+	  || die 'Could not match in src/test/bin/Makefile' . "\n";
+	foreach my $prg (split /\s+/, $1)
+	{
+		my $proj = $solution->AddProject($prg, 'exe', 'test/bin');
+		$mf =~ m{$prg\s*:\s*(.*)$}m
+		  || die 'Could not find test define for $prg' . "\n";
+		my @files = split /\s+/, $1;
+		foreach my $f (@files)
+		{
+			$f =~ s/\.o$/\.c/;
+			if ($f =~ /\.c$/)
+			{
+				$proj->AddFile('src/test/bin/' . $f);
+			}
+		}
+		$proj->AddIncludeDir('src/interfaces/libpq');
+		$proj->AddReference($libpq, $libpgfeutils, $libpgcommon, $libpgport);
+		$proj->AddDirResourceFile('src/test/bin');
+	}
+
 	# Regression DLL and EXE
 	my $regress = $solution->AddProject('regress', 'dll', 'misc');
 	$regress->AddFile('src/test/regress/regress.c');
diff --git a/src/tools/msvc/clean.bat b/src/tools/msvc/clean.bat
index 672bb2d650..c7b25d4bd8 100755
--- a/src/tools/msvc/clean.bat
+++ b/src/tools/msvc/clean.bat
@@ -27,6 +27,7 @@ if exist src\pl\plperl\win32ver.rc del /q src\pl\plperl\win32ver.rc
 if exist src\pl\plpgsql\src\win32ver.rc del /q src\pl\plpgsql\src\win32ver.rc
 if exist src\pl\plpython\win32ver.rc del /q src\pl\plpython\win32ver.rc
 if exist src\pl\tcl\win32ver.rc del /q src\pl\tcl\win32ver.rc
+if exist src\test\bin\win32ver.rc del /q src\test\bin\win32ver.rc
 if exist src\test\isolation\win32ver.rc del /q src\test\isolation\win32ver.rc
 if exist src\test\regress\win32ver.rc del /q src\test\regress\win32ver.rc
 if exist src\timezone\win32ver.rc del /q src\timezone\win32ver.rc

Reply via email to