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