From 09922597c5f460ab02882716c371b2a5c47e742e Mon Sep 17 00:00:00 2001 From: Magnus Hagander Date: Tue, 12 Jun 2007 11:07:34 +0000 Subject: Rewrite ECPG regression test driver in C, by splitting the standard regression driver into two parts and reusing half of it. Required to run ECPG tests without a shell on MSVC builds. Fix ECPG thread tests for MSVC build (incl output files). Joachim Wieland and Magnus Hagander --- src/interfaces/ecpg/test/Makefile | 48 +- src/interfaces/ecpg/test/ecpg_schedule | 40 + .../ecpg/test/expected/thread-thread-thread.stdout | 1 - src/interfaces/ecpg/test/expected/thread-thread.c | 26 +- .../ecpg/test/expected/thread-thread_2.stdout | 1 + .../expected/thread-thread_implicit-thread.stdout | 1 - .../ecpg/test/expected/thread-thread_implicit.c | 26 +- .../test/expected/thread-thread_implicit_2.stdout | 1 + src/interfaces/ecpg/test/pg_regress.sh | 811 --------------------- src/interfaces/ecpg/test/pg_regress_ecpg.c | 177 +++++ src/interfaces/ecpg/test/resultmap | 3 + src/interfaces/ecpg/test/thread/thread.pgc | 4 + .../ecpg/test/thread/thread_implicit.pgc | 4 + src/test/regress/GNUmakefile | 6 +- src/test/regress/pg_regress.c | 451 ++++++++---- src/test/regress/pg_regress.h | 59 ++ src/test/regress/pg_regress_main.c | 78 ++ src/test/regress/resultmap | 22 +- src/tools/msvc/Install.pm | 4 +- src/tools/msvc/Mkvcbuild.pm | 12 +- src/tools/msvc/clean.bat | 6 +- src/tools/msvc/ecpg_regression.proj | 46 ++ src/tools/msvc/vcregress.bat | 17 +- 23 files changed, 819 insertions(+), 1025 deletions(-) create mode 100644 src/interfaces/ecpg/test/ecpg_schedule delete mode 100644 src/interfaces/ecpg/test/expected/thread-thread-thread.stdout create mode 100644 src/interfaces/ecpg/test/expected/thread-thread_2.stdout delete mode 100644 src/interfaces/ecpg/test/expected/thread-thread_implicit-thread.stdout create mode 100644 src/interfaces/ecpg/test/expected/thread-thread_implicit_2.stdout delete mode 100644 src/interfaces/ecpg/test/pg_regress.sh create mode 100644 src/interfaces/ecpg/test/pg_regress_ecpg.c create mode 100644 src/interfaces/ecpg/test/resultmap create mode 100644 src/test/regress/pg_regress.h create mode 100644 src/test/regress/pg_regress_main.c create mode 100644 src/tools/msvc/ecpg_regression.proj (limited to 'src') diff --git a/src/interfaces/ecpg/test/Makefile b/src/interfaces/ecpg/test/Makefile index f68ae926da..4b9da21481 100644 --- a/src/interfaces/ecpg/test/Makefile +++ b/src/interfaces/ecpg/test/Makefile @@ -1,4 +1,4 @@ -# $PostgreSQL: pgsql/src/interfaces/ecpg/test/Makefile,v 1.67 2007/03/29 12:02:24 meskes Exp $ +# $PostgreSQL: pgsql/src/interfaces/ecpg/test/Makefile,v 1.68 2007/06/12 11:07:30 mha Exp $ subdir = src/interfaces/ecpg/test top_builddir = ../../../.. @@ -8,12 +8,12 @@ include $(top_builddir)/src/Makefile.global # this is also defined in test/connect/Makefile TEMP_PORT = 5$(DEF_PGPORT) +# where to find psql for testing an existing installation +PSQLDIR = $(bindir) + # default encoding MULTIBYTE = SQL_ASCII -# threading -THREAD := $(shell grep -q "define ENABLE_THREAD_SAFETY" ../include/ecpg_config.h && echo "--enable-threading") - # locale NOLOCALE = ifdef NO_LOCALE @@ -26,6 +26,15 @@ else abs_builddir := $(shell pwd -W) endif +# stuff to pass into build of pg_regress +EXTRADEFS = '-DHOST_TUPLE="$(host_tuple)"' \ + '-DMAKEPROG="$(MAKE)"' \ + '-DSHELLPROG="$(SHELL)"' \ + '-DDLSUFFIX="$(DLSUFFIX)"' + +REGRESSINCLUDES = "-I$(top_builddir)/src/test/regress" +REGRESSDRIVER = "$(top_builddir)/src/test/regress/pg_regress.o" + all install installdirs uninstall distprep: $(MAKE) -C connect $@ $(MAKE) -C expected $@ @@ -45,20 +54,21 @@ clean distclean maintainer-clean: $(MAKE) -C compat_informix $@ $(MAKE) -C thread $@ rm -rf tmp_check results log - rm -f pg_regress regression.diffs + rm -f pg_regress regression.diffs pg_regress_ecpg.o + +# Build regression test driver + +all: pg_regress$(X) + +pg_regress$(X): pg_regress_ecpg.o + $(CC) $(CFLAGS) $^ $(REGRESSDRIVER) $(LDFLAGS) $(LIBS) -o $@ -all: pg_regress +# dependencies ensure that path changes propagate +pg_regress_ecpg.o: pg_regress_ecpg.c $(top_builddir)/src/port/pg_config_paths.h + $(CC) $(CFLAGS) $(CPPFLAGS) -I$(top_builddir)/src/port $(REGRESSINCLUDES) $(EXTRADEFS) -c -o $@ $< -pg_regress: pg_regress.sh $(top_builddir)/src/Makefile.global - sed -e 's,@bindir@,$(bindir),g' \ - -e 's,@libdir@,$(libdir),g' \ - -e 's,@pkglibdir@,$(pkglibdir),g' \ - -e 's,@datadir@,$(datadir),g' \ - -e 's/@VERSION@/$(VERSION)/g' \ - -e 's/@host_tuple@/$(host_tuple)/g' \ - -e 's,@GMAKE@,$(MAKE),g' \ - -e 's/@enable_shared@/$(enable_shared)/g' \ - $< >$@ +$(top_builddir)/src/port/pg_config_paths.h: $(top_builddir)/src/Makefile.global + $(MAKE) -C $(top_builddir)/src/port pg_config_paths.h # When doing a VPATH build, copy over the .pgc, .stdout and .stderr # files so that the driver script can find them. We have to use an @@ -78,11 +88,11 @@ endif check: all - sh ./pg_regress --dbname=regress1 --temp-install --top-builddir=$(top_builddir) --temp-port=$(TEMP_PORT) --multibyte=$(MULTIBYTE) --load-language=plpgsql $(NOLOCALE) $(THREAD) + ./pg_regress --dbname=regress1,connectdb --top-builddir=$(top_builddir) --temp-install=./tmp_check --temp-port=$(TEMP_PORT) --multibyte=$(MULTIBYTE) --load-language=plpgsql $(NOLOCALE) $(THREAD) --schedule=$(srcdir)/ecpg_schedule --create-role=connectuser,connectdb # the same options, but with --listen-on-tcp checktcp: all - sh ./pg_regress --dbname=regress1 --temp-install --top-builddir=$(top_builddir) --temp-port=$(TEMP_PORT) --multibyte=$(MULTIBYTE) --load-language=plpgsql $(NOLOCALE) --listen-on-tcp $(THREAD) + ./pg_regress --dbname=regress1,connectdb --top-builddir=$(top_builddir) --temp-install=./tmp_check --temp-port=$(TEMP_PORT) --multibyte=$(MULTIBYTE) --load-language=plpgsql $(NOLOCALE) $(THREAD) --schedule=$(srcdir)/ecpg_schedule_tcp --create-role=connectuser,connectdb --host=localhost installcheck: all - sh ./pg_regress --dbname=regress1 --top-builddir=$(top_builddir) --load-language=plpgsql $(NOLOCALE) + ./pg_regress --psqldir=$(PSQLDIR) --dbname=regress1,connectdb --top-builddir=$(top_builddir) --multibyte=$(MULTIBYTE) --load-language=plpgsql $(NOLOCALE) $(THREAD) --schedule=$(srcdir)/ecpg_schedule --create-role=connectuser,connectdb diff --git a/src/interfaces/ecpg/test/ecpg_schedule b/src/interfaces/ecpg/test/ecpg_schedule new file mode 100644 index 0000000000..108881c49e --- /dev/null +++ b/src/interfaces/ecpg/test/ecpg_schedule @@ -0,0 +1,40 @@ +test: compat_informix/dec_test +test: compat_informix/charfuncs +test: compat_informix/rfmtdate +test: compat_informix/rfmtlong +test: compat_informix/rnull +test: compat_informix/test_informix +test: compat_informix/test_informix2 +test: connect/test2 +test: connect/test3 +test: connect/test4 +test: connect/test5 +test: pgtypeslib/dt_test +test: pgtypeslib/dt_test2 +test: pgtypeslib/num_test +test: pgtypeslib/num_test2 +test: preproc/comment +test: preproc/define +test: preproc/init +test: preproc/type +test: preproc/variable +test: preproc/whenever +test: sql/array +test: sql/binary +test: sql/code100 +test: sql/copystdout +test: sql/define +test: sql/desc +test: sql/dynalloc +test: sql/dynalloc2 +test: sql/dyntest +test: sql/execute +test: sql/fetch +test: sql/func +test: sql/indicators +test: sql/quote +test: sql/show +test: sql/insupd +test: sql/parser +test: thread/thread +test: thread/thread_implicit diff --git a/src/interfaces/ecpg/test/expected/thread-thread-thread.stdout b/src/interfaces/ecpg/test/expected/thread-thread-thread.stdout deleted file mode 100644 index a9d787cc55..0000000000 --- a/src/interfaces/ecpg/test/expected/thread-thread-thread.stdout +++ /dev/null @@ -1 +0,0 @@ -Success. diff --git a/src/interfaces/ecpg/test/expected/thread-thread.c b/src/interfaces/ecpg/test/expected/thread-thread.c index 9555a79bfa..36d920eb3c 100644 --- a/src/interfaces/ecpg/test/expected/thread-thread.c +++ b/src/interfaces/ecpg/test/expected/thread-thread.c @@ -153,15 +153,19 @@ void *test_thread(void *arg) /* build up connection name, and connect to database */ +#ifndef WIN32_ONLY_COMPILER snprintf(l_connection, sizeof(l_connection), "thread_%03ld", threadnum); +#else + _snprintf(l_connection, sizeof(l_connection), "thread_%03ld", threadnum); +#endif /* exec sql whenever sqlerror sqlprint ; */ -#line 107 "thread.pgc" +#line 111 "thread.pgc" { ECPGconnect(__LINE__, 0, "regress1" , NULL, NULL , l_connection, 0); -#line 108 "thread.pgc" +#line 112 "thread.pgc" if (sqlca.sqlcode < 0) sqlprint();} -#line 108 "thread.pgc" +#line 112 "thread.pgc" if( sqlca.sqlcode != 0 ) { @@ -169,10 +173,10 @@ if (sqlca.sqlcode < 0) sqlprint();} return( NULL ); } { ECPGtrans(__LINE__, l_connection, "begin transaction "); -#line 114 "thread.pgc" +#line 118 "thread.pgc" if (sqlca.sqlcode < 0) sqlprint();} -#line 114 "thread.pgc" +#line 118 "thread.pgc" /* insert into test_thread table */ @@ -183,10 +187,10 @@ if (sqlca.sqlcode < 0) sqlprint();} ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_int,&(l_i),(long)1,(long)1,sizeof(int), ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT); -#line 119 "thread.pgc" +#line 123 "thread.pgc" if (sqlca.sqlcode < 0) sqlprint();} -#line 119 "thread.pgc" +#line 123 "thread.pgc" if( sqlca.sqlcode != 0 ) printf("%s: ERROR: insert failed!\n", l_connection); @@ -194,16 +198,16 @@ if (sqlca.sqlcode < 0) sqlprint();} /* all done */ { ECPGtrans(__LINE__, l_connection, "commit"); -#line 125 "thread.pgc" +#line 129 "thread.pgc" if (sqlca.sqlcode < 0) sqlprint();} -#line 125 "thread.pgc" +#line 129 "thread.pgc" { ECPGdisconnect(__LINE__, l_connection); -#line 126 "thread.pgc" +#line 130 "thread.pgc" if (sqlca.sqlcode < 0) sqlprint();} -#line 126 "thread.pgc" +#line 130 "thread.pgc" return( NULL ); } diff --git a/src/interfaces/ecpg/test/expected/thread-thread_2.stdout b/src/interfaces/ecpg/test/expected/thread-thread_2.stdout new file mode 100644 index 0000000000..a9d787cc55 --- /dev/null +++ b/src/interfaces/ecpg/test/expected/thread-thread_2.stdout @@ -0,0 +1 @@ +Success. diff --git a/src/interfaces/ecpg/test/expected/thread-thread_implicit-thread.stdout b/src/interfaces/ecpg/test/expected/thread-thread_implicit-thread.stdout deleted file mode 100644 index a9d787cc55..0000000000 --- a/src/interfaces/ecpg/test/expected/thread-thread_implicit-thread.stdout +++ /dev/null @@ -1 +0,0 @@ -Success. diff --git a/src/interfaces/ecpg/test/expected/thread-thread_implicit.c b/src/interfaces/ecpg/test/expected/thread-thread_implicit.c index f48db90559..bf20c51bb5 100644 --- a/src/interfaces/ecpg/test/expected/thread-thread_implicit.c +++ b/src/interfaces/ecpg/test/expected/thread-thread_implicit.c @@ -154,15 +154,19 @@ void *test_thread(void *arg) /* build up connection name, and connect to database */ +#ifndef WIN32_ONLY_COMPILER snprintf(l_connection, sizeof(l_connection), "thread_%03ld", threadnum); +#else + _snprintf(l_connection, sizeof(l_connection), "thread_%03ld", threadnum); +#endif /* exec sql whenever sqlerror sqlprint ; */ -#line 108 "thread_implicit.pgc" +#line 112 "thread_implicit.pgc" { ECPGconnect(__LINE__, 0, "regress1" , NULL, NULL , l_connection, 0); -#line 109 "thread_implicit.pgc" +#line 113 "thread_implicit.pgc" if (sqlca.sqlcode < 0) sqlprint();} -#line 109 "thread_implicit.pgc" +#line 113 "thread_implicit.pgc" if( sqlca.sqlcode != 0 ) { @@ -170,10 +174,10 @@ if (sqlca.sqlcode < 0) sqlprint();} return( NULL ); } { ECPGtrans(__LINE__, NULL, "begin transaction "); -#line 115 "thread_implicit.pgc" +#line 119 "thread_implicit.pgc" if (sqlca.sqlcode < 0) sqlprint();} -#line 115 "thread_implicit.pgc" +#line 119 "thread_implicit.pgc" /* insert into test_thread table */ @@ -184,10 +188,10 @@ if (sqlca.sqlcode < 0) sqlprint();} ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_int,&(l_i),(long)1,(long)1,sizeof(int), ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT); -#line 120 "thread_implicit.pgc" +#line 124 "thread_implicit.pgc" if (sqlca.sqlcode < 0) sqlprint();} -#line 120 "thread_implicit.pgc" +#line 124 "thread_implicit.pgc" if( sqlca.sqlcode != 0 ) printf("%s: ERROR: insert failed!\n", l_connection); @@ -195,16 +199,16 @@ if (sqlca.sqlcode < 0) sqlprint();} /* all done */ { ECPGtrans(__LINE__, NULL, "commit"); -#line 126 "thread_implicit.pgc" +#line 130 "thread_implicit.pgc" if (sqlca.sqlcode < 0) sqlprint();} -#line 126 "thread_implicit.pgc" +#line 130 "thread_implicit.pgc" { ECPGdisconnect(__LINE__, l_connection); -#line 127 "thread_implicit.pgc" +#line 131 "thread_implicit.pgc" if (sqlca.sqlcode < 0) sqlprint();} -#line 127 "thread_implicit.pgc" +#line 131 "thread_implicit.pgc" return( NULL ); } diff --git a/src/interfaces/ecpg/test/expected/thread-thread_implicit_2.stdout b/src/interfaces/ecpg/test/expected/thread-thread_implicit_2.stdout new file mode 100644 index 0000000000..a9d787cc55 --- /dev/null +++ b/src/interfaces/ecpg/test/expected/thread-thread_implicit_2.stdout @@ -0,0 +1 @@ +Success. diff --git a/src/interfaces/ecpg/test/pg_regress.sh b/src/interfaces/ecpg/test/pg_regress.sh deleted file mode 100644 index a164953ed8..0000000000 --- a/src/interfaces/ecpg/test/pg_regress.sh +++ /dev/null @@ -1,811 +0,0 @@ -#! /bin/sh -# $PostgreSQL: pgsql/src/interfaces/ecpg/test/pg_regress.sh,v 1.19 2007/03/29 12:02:24 meskes Exp $ - -me=`basename $0` - -message(){ - _dashes='==============' # 14 - _spaces=' ' # 38 - _msg=`echo "$1$_spaces" | cut -c 1-38` - echo "$_dashes $_msg $_dashes" -} - -build_help(){ -help="\ -PostgreSQL regression test driver - -Usage: $me [options...] [extra tests...] - -Options: - --dbname=DB use database DB (default \`regression') - --debug turn on debug mode in programs that are run - --inputdir=DIR take input files from DIR (default \`.') - --load-language=lang load the named language before running the - tests; can appear multiple times - --max-connections=N maximum number of concurrent connections - (default is 0 meaning unlimited) - --multibyte=ENCODING use ENCODING as the multibyte encoding, and - also run a test by the same name - --outputdir=DIR place output files in DIR (default \`.') - --temp-install[=DIR] create a temporary installation (in DIR) - --no-locale use C locale -$1 -Options for \`temp-install' mode: - --top-builddir=DIR (relative) path to top level build directory - --temp-port=PORT port number to start temp postmaster on - --listen-on-tcp listen on the tcp port as well - --enable-threading expect threading to be enabled - -Options for using an existing installation: - --host=HOST use postmaster running on HOST - --port=PORT use postmaster running at PORT - --user=USER connect as USER - -The exit status is 0 if all tests passed, 1 if some tests failed, and 2 -if the tests could not be run for some reason. - -Report bugs to ." -} - -init_vars(){ - : ${TMPDIR=/tmp} - TMPFILE=$TMPDIR/pg_regress.$$ - - # ---------- - # Initialize default settings - # ---------- - - : ${inputdir=.} - : ${outputdir=.} - - libdir='@libdir@' - bindir='@bindir@' - datadir='@datadir@' - host_platform='@host_tuple@' - enable_shared='@enable_shared@' - VERSION=@VERSION@ - - unset mode - unset schedule - unset debug - unset nolocale - unset top_builddir - unset temp_install - unset multibyte - - dbname=regression - hostname=localhost - maxconnections=0 - temp_port=65432 - load_langs="" - listen_on_tcp=no - enable_threading=no - - : ${GMAKE='@GMAKE@'} -} - -parse_general_options(){ -# ---------- -# Parse command line options -# ---------- - -while [ "$#" -gt 0 ] -do - case $1 in - --help|-\?) - echo "$help" - exit 0;; - --version) - echo "pg_regress (PostgreSQL $VERSION)" - exit 0;; - --dbname=*) - dbname=`expr "x$1" : "x--dbname=\(.*\)"` - shift;; - --debug) - debug=yes - shift;; - --inputdir=*) - inputdir=`expr "x$1" : "x--inputdir=\(.*\)"` - shift;; - --listen-on-tcp) - listen_on_tcp=yes - shift;; - --enable-threading) - enable_threading=yes - shift;; - --load-language=*) - lang=`expr "x$1" : "x--load-language=\(.*\)"` - load_langs="$load_langs $lang" - unset lang - shift;; - --multibyte=*) - multibyte=`expr "x$1" : "x--multibyte=\(.*\)"` - shift;; - --no-locale) - nolocale=yes - shift;; - --temp-install) - temp_install=./tmp_check - shift;; - --temp-install=*) - temp_install=`expr "x$1" : "x--temp-install=\(.*\)"` - shift;; - --max-connections=*) - maxconnections=`expr "x$1" : "x--max-connections=\(.*\)"` - shift;; - --outputdir=*) - outputdir=`expr "x$1" : "x--outputdir=\(.*\)"` - shift;; - --top-builddir=*) - top_builddir=`expr "x$1" : "x--top-builddir=\(.*\)"` - shift;; - --temp-port=*) - temp_port=`expr "x$1" : "x--temp-port=\(.*\)"` - shift;; - --host=*) - PGHOST=`expr "x$1" : "x--host=\(.*\)"` - export PGHOST - unset PGHOSTADDR - shift;; - --port=*) - PGPORT=`expr "x$1" : "x--port=\(.*\)"` - export PGPORT - shift;; - --user=*) - PGUSER=`expr "x$1" : "x--user=\(.*\)"` - export PGUSER - shift;; - -*) - # on error, this will not return but exit - parse_special_options "$1" - shift;; - *) - extra_tests="$extra_tests $1" - shift;; - esac -done -} - - - -setup_environment_variables(){ - - # This function has two parts. Part 1 sets/unsets environment variables - # independently of what options the script receives. - # Part 2 later sets environment variables with respect to the - # options given. - - # ======= - # PART 1: Options independent stuff goes here - # ======= - - - # ---------- - # Unset locale settings - # ---------- - - unset LC_COLLATE LC_CTYPE LC_MONETARY LC_MESSAGES LC_NUMERIC LC_TIME LC_ALL LANG LANGUAGE - - # On Windows the default locale may not be English, so force it - case $host_platform in - *-*-cygwin*|*-*-mingw32*) - LANG=en - export LANG - ;; - esac - - # ---------- - # On some platforms we can't use Unix sockets. - # ---------- - - case $host_platform in - *-*-cygwin* | *-*-mingw32*) - listen_on_tcp=yes - esac - - # ---------- - # Set up diff to ignore horizontal white space differences. - # ---------- - - case $host_platform in - *-*-sco3.2v5*) - DIFFFLAGS=-b;; - *) - DIFFFLAGS=-w;; - esac - - # ---------- - # Check for echo -n vs echo \c - # ---------- - - if echo '\c' | grep c >/dev/null 2>&1; then - ECHO_N='echo -n' - ECHO_C='' - else - ECHO_N='echo' - ECHO_C='\c' - fi - - # ---------- - # Set backend timezone and datestyle explicitly - # - # To pass the horology test in its current form, the postmaster must be - # started with PGDATESTYLE=ISO, while the frontend must be started with - # PGDATESTYLE=Postgres. We set the postmaster values here and change - # to the frontend settings after the postmaster has been started. - # ---------- - - PGTZ='PST8PDT'; export PGTZ - PGDATESTYLE='ISO, MDY'; export PGDATESTYLE - - # ---------- - # Set up SQL shell for the test. - # ---------- - - psql_test_options="-a -q -X $psql_options" - - - - # ======= - # PART 2: Options dependent stuff goes here - # ======= - - LOGDIR=$outputdir/log - - # ---------- - # warn of Cygwin likely failure if maxconnections = 0 - # and we are running parallel tests - # ---------- - - case $host_platform in - *-*-cygwin*) - case "$schedule" in - *parallel_schedule*) - if [ $maxconnections -eq 0 ] ; then - echo Using unlimited parallel connections is likely to fail or hang on Cygwin. - echo Try \"$me --max-connections=n\" or \"gmake MAX_CONNECTIONS=n check\" - echo with n = 5 or 10 if this happens. - echo - fi - ;; - esac - ;; - esac - - # ---------- - # Set up multibyte environment - # ---------- - - if [ -n "$multibyte" ]; then - PGCLIENTENCODING=$multibyte - export PGCLIENTENCODING - encoding_opt="-E $multibyte" - else - unset PGCLIENTENCODING - fi -} - -do_temp_install(){ - if echo x"$temp_install" | grep -v '^x/' >/dev/null 2>&1; then - temp_install="`pwd`/$temp_install" - fi - - bindir=$temp_install/install/$bindir - libdir=$temp_install/install/$libdir - datadir=$temp_install/install/$datadir - PGDATA=$temp_install/data - - if [ "$unix_sockets" = no ]; then - PGHOST=$hostname - export PGHOST - unset PGHOSTADDR - else - unset PGHOST - unset PGHOSTADDR - fi - - # since Makefile isn't very bright, check for out-of-range temp_port - if [ "$temp_port" -ge 1024 -a "$temp_port" -le 65535 ] ; then - PGPORT=$temp_port - else - PGPORT=65432 - fi - export PGPORT - - # Get rid of environment stuff that might cause psql to misbehave - # while contacting our temp installation - unset PGDATABASE PGUSER PGSERVICE PGSSLMODE PGREQUIRESSL PGCONNECT_TIMEOUT - - # ---------- - # Set up shared library paths, needed by psql and pg_encoding - # (if you run multibyte). LD_LIBRARY_PATH covers many platforms. - # DYLD_LIBRARY_PATH works on Darwin, and maybe other Mach-based systems. - # LIBPATH is for AIX. - # Feel free to account for others as well. - # ---------- - - if [ -n "$LD_LIBRARY_PATH" ]; then - LD_LIBRARY_PATH="$libdir:$LD_LIBRARY_PATH" - else - LD_LIBRARY_PATH=$libdir - fi - export LD_LIBRARY_PATH - - if [ -n "$DYLD_LIBRARY_PATH" ]; then - DYLD_LIBRARY_PATH="$libdir:$DYLD_LIBRARY_PATH" - else - DYLD_LIBRARY_PATH=$libdir - fi - export DYLD_LIBRARY_PATH - - if [ -n "$LIBPATH" ]; then - LIBPATH="$libdir:$LIBPATH" - else - LIBPATH=$libdir - fi - export LIBPATH - - # ---------- - # Windows needs shared libraries in PATH. (Only those linked into - # executables, not dlopen'ed ones) - # ---------- - case $host_platform in - *-*-cygwin*|*-*-mingw32*) - PATH=$libdir:$PATH - export PATH - ;; - esac - - if [ -d "$temp_install" ]; then - message "removing existing temp installation" - rm -rf "$temp_install" - fi - - message "creating temporary installation" - if [ ! -d "$LOGDIR" ]; then - mkdir -p "$LOGDIR" || { (exit 2); exit; } - fi - $GMAKE -C "$top_builddir" DESTDIR="$temp_install/install" install with_perl=no with_python=no >"$LOGDIR/install.log" 2>&1 - - if [ $? -ne 0 ] - then - echo - echo "$me: installation failed" - echo "Examine $LOGDIR/install.log for the reason." - echo - (exit 2); exit - fi - - message "initializing database system" - [ "$debug" = yes ] && initdb_options="--debug" - [ "$nolocale" = yes ] && initdb_options="$initdb_options --no-locale" - "$bindir/initdb" -D "$PGDATA" -L "$datadir" --noclean $initdb_options >"$LOGDIR/initdb.log" 2>&1 - - if [ $? -ne 0 ] - then - echo - echo "$me: initdb failed" - echo "Examine $LOGDIR/initdb.log for the reason." - echo - (exit 2); exit - fi - - - # ---------- - # Start postmaster - # ---------- - - message "starting postmaster" - [ "$debug" = yes ] && postmaster_options="$postmaster_options -d 5" - if [ "$listen_on_tcp" = yes ]; then - postmaster_options="$postmaster_options -c listen_addresses=$hostname" - else - postmaster_options="$postmaster_options -c listen_addresses=" - fi - "$bindir/postmaster" -D "$PGDATA" -F $postmaster_options >"$LOGDIR/postmaster.log" 2>&1 & - postmaster_pid=$! - - # Wait till postmaster is able to accept connections (normally only - # a second or so, but Cygwin is reportedly *much* slower). Don't - # wait forever, however. - i=0 - max=60 - until "$bindir/psql" -X $psql_options postgres /dev/null - do - i=`expr $i + 1` - if [ $i -ge $max ] - then - break - fi - if kill -0 $postmaster_pid >/dev/null 2>&1 - then - : still starting up - else - break - fi - sleep 1 - done - - if kill -0 $postmaster_pid >/dev/null 2>&1 - then - echo "running on port $PGPORT with pid $postmaster_pid" - else - echo - echo "$me: postmaster did not start" - echo "Examine $LOGDIR/postmaster.log for the reason." - echo - (exit 2); exit - fi -} - -dont_temp_install(){ - # ---------- - # Windows needs shared libraries in PATH. (Only those linked into - # executables, not dlopen'ed ones) - # ---------- - case $host_platform in - *-*-cygwin*|*-*-mingw32*) - PATH=$libdir:$PATH - export PATH - ;; - esac - - if [ -n "$PGPORT" ]; then - port_info="port $PGPORT" - else - port_info="default port" - fi - - if [ -n "$PGHOST" ]; then - echo "(using postmaster on $PGHOST, $port_info)" - else - if [ "$unix_sockets" = no ]; then - echo "(using postmaster on localhost, $port_info)" - else - echo "(using postmaster on Unix socket, $port_info)" - fi - fi -} - -setup_client_environment_variables(){ - PGDATESTYLE='Postgres' - export PGDATESTYLE -} - -# ---------- -# Exit trap to remove temp file and shut down postmaster -# ---------- - -# Note: There are some stupid shells (even among recent ones) that -# ignore the argument to exit (as in `exit 1') if there is an exit -# trap. The trap (and thus the shell script) will then always exit -# with the result of the last shell command before the `exit'. Hence -# we have to write `(exit x); exit' below this point. - -exit_trap(){ - savestatus=$1 - if [ -n "$postmaster_pid" ]; then - kill -2 "$postmaster_pid" - wait "$postmaster_pid" - unset postmaster_pid - fi - rm -f "$TMPFILE" && exit $savestatus -} - -sig_trap() { - savestatus=$1 - echo; echo "caught signal" - if [ -n "$postmaster_pid" ]; then - echo "signalling fast shutdown to postmaster with pid $postmaster_pid" - kill -2 "$postmaster_pid" - wait "$postmaster_pid" - unset postmaster_pid - fi - (exit $savestatus); exit -} - -setup_database(){ - # this receives the name of the database to set up as its argument - "$bindir/psql" -q -X $psql_options -c "\ - alter database \"$1\" set lc_messages to 'C'; - alter database \"$1\" set lc_monetary to 'C'; - alter database \"$1\" set lc_numeric to 'C'; - alter database \"$1\" set lc_time to 'C';" "$1" - if [ $? -ne 0 ]; then - echo "$me: could not set database default locales" - (exit 2); exit - fi - - # ---------- - # Install any requested PL languages - # ---------- - - if [ "$enable_shared" = yes ]; then - for lang in xyzzy $load_langs ; do - if [ "$lang" != "xyzzy" ]; then - message "installing $lang" - "$bindir/createlang" $psql_options $lang "$1" - if [ $? -ne 0 ] && [ $? -ne 2 ]; then - echo "$me: createlang $lang failed" - (exit 2); exit - fi - fi - done - fi -} - -drop_database(){ - message "dropping database \"$1\"" - "$bindir/dropdb" $psql_options "$1" -} - -create_database(){ - # ---------- - # We use template0 so that any installation-local cruft in template1 - # will not mess up the tests. - # ---------- - - message "creating database \"$1\"" - "$bindir/createdb" $encoding_opt $psql_options --template template0 "$1" - if [ $? -ne 0 ]; then - echo "$me: createdb failed" - (exit 2); exit - fi - - setup_database "$1" -} - -database_cleanup(){ - # ---------- - # Remove regressuser* and regressgroup* user accounts. - # ---------- - - message "dropping regression test user accounts" - "$bindir/psql" -q -X $psql_options -c 'DROP GROUP regressgroup1; DROP GROUP regressgroup2; DROP USER regressuser1, regressuser2, regressuser3, regressuser4;' $dbname 2>/dev/null - if [ $? -eq 2 ]; then - echo "$me: could not drop user accounts" - (exit 2); exit - fi -} - -postmaster_shutdown(){ - # ---------- - # Server shutdown - # ---------- - - if [ -n "$postmaster_pid" ]; then - message "shutting down postmaster" - "$bindir/pg_ctl" -s -D "$PGDATA" stop - wait "$postmaster_pid" - unset postmaster_pid - fi -} - -evaluate(){ - # ---------- - # Evaluation - # ---------- - - count_total=`cat "$result_summary_file" | grep '\.\.\.' | wc -l | sed 's/ //g'` - count_ok=`cat "$result_summary_file" | grep '\.\.\. ok' | wc -l | sed 's/ //g'` - count_failed=`cat "$result_summary_file" | grep '\.\.\. FAILED' | wc -l | sed 's/ //g'` - count_ignored=`cat "$result_summary_file" | grep '\.\.\. failed (ignored)' | wc -l | sed 's/ //g'` - - echo - if [ $count_total -eq $count_ok ]; then - msg="All $count_total tests passed." - result=0 - elif [ $count_failed -eq 0 ]; then - msg="$count_ok of $count_total tests passed, $count_ignored failed test(s) ignored." - result=0 - elif [ $count_ignored -eq 0 ]; then - msg="$count_failed of $count_total tests failed." - result=1 - else - msg="`expr $count_failed + $count_ignored` of $count_total tests failed, $count_ignored of these failures ignored." - result=1 - fi - - dashes=`echo " $msg " | sed 's/./=/g'` - echo "$dashes" - echo " $msg " - echo "$dashes" - echo - - if [ -s "$diff_file" ]; then - echo "The differences that caused some tests to fail can be viewed in the" - echo "file \`$diff_file'. A copy of the test summary that you see" - echo "above is saved in the file \`$result_summary_file'." - echo - else - rm -f "$diff_file" "$result_summary_file" - fi -} - -additional_regress_options="" - -build_help "$additional_regress_options" -init_vars - -parse_special_options(){ -# no special options so far - case $1 in - -*) - echo "$me: invalid argument $1" 1>&2 - exit 2;; - esac -} - -# this will call parse_special_options from above -parse_general_options $* - -# ---------- -# Set up the environment variables (some of them depend on the parameters) -# ---------- -setup_environment_variables - -trap 'exit_trap $?' 0 -trap 'sig_trap $?' 1 2 13 15 - -if [ x"$temp_install" != x"" ] -then - do_temp_install - #PGPORT=$temp_port; export PGPORT -else # not temp-install - dont_temp_install -fi - -# ---------- -# Postmaster is started, now we can change some environment variables for the -# client -# ---------- - -setup_client_environment_variables - -# set up the dbs we use for ecpg regression tests -drop_database "$dbname" -create_database "$dbname" -drop_database connectdb -create_database connectdb - -# ---------- -# Let's go -# ---------- - -message "running regression test queries" - -outputdir="results" - -if [ ! -d "$outputdir" ]; then - mkdir -p "$outputdir" || { (exit 2); exit; } -fi -#result_summary_file=$outputdir/regression.out -#diff_file=$outputdir/regression.diffs - -#cat /dev/null >"$result_summary_file" -#cat /dev/null >"$diff_file" - -# we also have different users for ecpg regression diffs (need them for testing -# connects) -echo "$bindir/createuser" $psql_options -R -S -D -q regressuser1 -"$bindir/createuser" $psql_options -R -S -D -q regressuser1 -if [ $? -ne 0 ]; then - echo Could not create user regressuser1 -fi -echo "$bindir/createuser" $psql_options -R -S -D -q connectuser -"$bindir/createuser" $psql_options -R -S -D -q connectuser -if [ $? -ne 0 ]; then - echo Could not create user connectuser -fi -# to test username = dbname -echo "$bindir/createuser" $psql_options -R -S -D -q connectdb -"$bindir/createuser" $psql_options -R -S -D -q connectdb -if [ $? -ne 0 ]; then - echo Could not create user connectdb -fi - -# this variable prevents that the PID gets included in the logfiles -#ECPG_REGRESSION=1; export ECPG_REGRESSION -LD_LIBRARY_PATH=$libdir:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH - -DIFFPRETTYFLAGS="$DIFFFLAGS -C3" -FAILNUM="" - -rm -f regression.diffs - -for i in \ - connect/*.pgc \ - compat_informix/*.pgc \ - preproc/*.pgc \ - pgtypeslib/*.pgc \ - sql/*.pgc \ - thread/*.pgc; do - - formatted=`echo $i | awk '{printf "%-38.38s", $1;}'` - $ECHO_N "testing $formatted ... $ECHO_C" - - # connect/test1.pgc uses tcp to connect to the server. We run this test - # only if called with --listen-on-tcp - if [ $listen_on_tcp = no ] && [ "$i" = "connect/test1.pgc" ]; then - echo skipped - continue; - fi - - runprg=`echo $i | sed -e 's,\.pgc$,,'` - outprg=`echo $runprg | sed -e's/\//-/'` - - case $host_platform in - *-*-mingw32*) - PLATFORM_TAG="-MinGW32" - ;; - *-*-openbsd3.8) - # OpenBSD 3.8 is buggy: - # http://archives.postgresql.org/pgsql-hackers/2006-09/msg00593.php - PLATFORM_TAG="-OpenBSD3.8.broken" - ;; - esac - - outfile_stderr="$outputdir/$outprg.stderr" - outfile_stdout="$outputdir/$outprg.stdout" - outfile_source="$outputdir/$outprg.c" - cp $runprg.c "$outfile_source" - # echo "$runprg > $outfile_stdout 2> $outfile_stderr" - $runprg > "$outfile_stdout" 2> "$outfile_stderr" - - mv "$outfile_source" "$outfile_source.tmp" - cat "$outfile_source.tmp" | sed -e 's,^\(#line [0-9]*\) ".*/\([^/]*\)",\1 "\2",' > "$outfile_source" - rm "$outfile_source.tmp" - - if [ "$enable_threading" = yes ] && [ "${i%%/*}" = "thread" ]; then - expectedoutprg="expected/$outprg-thread" - else - expectedoutprg="expected/$outprg" - fi - - expected_stdout="$expectedoutprg$PLATFORM_TAG.stdout" - if [ ! -f "$expected_stdout" ]; then - expected_stdout="$expectedoutprg.stdout" - fi - # threading has log output disabled - expected_stderr="expected/$outprg$PLATFORM_TAG.stderr" - if [ ! -f "$expected_stderr" ]; then - expected_stderr="expected/$outprg.stderr" - fi - # the source should be identical on all platforms - expected_source="expected/$outprg.c" - - DIFFER="" - diff $DIFFFLAGS "$expected_stderr" "$outfile_stderr" > /dev/null 2>&1 - if [ $? != 0 ]; then - DIFFER="$DIFFER, log" - diff $DIFFPRETTYFLAGS "$expected_stderr" "$outfile_stderr" >> regression.diffs 2>&1 - fi - - diff $DIFFFLAGS "$expected_stdout" "$outfile_stdout" > /dev/null 2>&1 - if [ $? != 0 ]; then - DIFFER="$DIFFER, output" - diff $DIFFPRETTYFLAGS "$expected_stdout" "$outfile_stdout" >> regression.diffs 2>&1 - fi - - diff $DIFFFLAGS "$expected_source" "$outputdir"/$outprg.c > /dev/null 2>&1 - if [ $? != 0 ]; then - DIFFER="$DIFFER, source" - diff $DIFFPRETTYFLAGS "$expected_source" "$outputdir"/$outprg.c >> regression.diffs 2>&1 - fi - - DIFFER=`echo $DIFFER | sed -e 's/^, //'` - if [ "x$DIFFER" = "x" ]; then - echo ok - else - echo "FAILED ($DIFFER)" - # some sh's don't know about $((x+1)) - FAILNUM=x$FAILNUM - fi -done - -postmaster_shutdown - -# FAILNUM is empty if no test has failed -[ x"$FAILNUM" = x"" ] && exit 0 -(exit 1); exit - diff --git a/src/interfaces/ecpg/test/pg_regress_ecpg.c b/src/interfaces/ecpg/test/pg_regress_ecpg.c new file mode 100644 index 0000000000..c829653f52 --- /dev/null +++ b/src/interfaces/ecpg/test/pg_regress_ecpg.c @@ -0,0 +1,177 @@ +/*------------------------------------------------------------------------- + * + * pg_regress_ecpg --- regression test driver for ecpg + * + * This is a C implementation of the previous shell script for running + * the regression tests, and should be mostly compatible with it. + * Initial author of C translation: Magnus Hagander + * + * This code is released under the terms of the PostgreSQL License. + * + * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * $PostgreSQL: pgsql/src/interfaces/ecpg/test/pg_regress_ecpg.c,v 1.1 2007/06/12 11:07:30 mha Exp $ + * + *------------------------------------------------------------------------- + */ + +#include "pg_regress.h" + +#define LINEBUFSIZE 300 +static void +ecpg_filter(const char *sourcefile, const char *outfile) +{ + /* + * Create a filtered copy of sourcefile, replacing + * #line x "./../bla/foo.h" + * with + * #line x "foo.h" + */ + FILE *s, *t; + char linebuf[LINEBUFSIZE]; + + s = fopen(sourcefile, "r"); + if (!s) + { + fprintf(stderr, "Could not open file %s for reading\n", sourcefile); + exit_nicely(2); + } + t = fopen(outfile, "w"); + if (!t) + { + fprintf(stderr, "Could not open file %s for writing\n", outfile); + exit_nicely(2); + } + + while (fgets(linebuf, LINEBUFSIZE, s)) + { + /* check for "#line " in the beginning */ + if (strstr(linebuf, "#line ") == linebuf) + { + char *p = strchr(linebuf, '"'); + char *n; + int plen = 1; + while (*p && (*(p + plen) == '.' || strchr(p + plen, '/') != NULL)) + { + plen++; + } + /* plen is one more than the number of . and / characters */ + if (plen > 1) + { + n = (char *) malloc(plen); + strncpy(n, p+1, plen - 1); + n[plen-1] = '\0'; + replace_string(linebuf, n, ""); + } + } + fputs(linebuf, t); + } + fclose(s); + fclose(t); +} + +/* + * start an ecpg test process for specified file (including redirection), + * and return process ID + */ + +static PID_TYPE +ecpg_start_test(const char *testname, + _stringlist **resultfiles, + _stringlist **expectfiles, + _stringlist **tags) +{ + PID_TYPE pid; + char inprg[MAXPGPATH]; + char insource[MAXPGPATH]; + char *outfile_stdout, expectfile_stdout[MAXPGPATH]; + char *outfile_stderr, expectfile_stderr[MAXPGPATH]; + char *outfile_source, expectfile_source[MAXPGPATH]; + char cmd[MAXPGPATH * 3]; + char *testname_dash; + + snprintf(inprg, sizeof(inprg), "%s/%s", inputdir, testname); + + testname_dash = strdup(testname); + replace_string(testname_dash, "/", "-"); + snprintf(expectfile_stdout, sizeof(expectfile_stdout), + "%s/expected/%s.stdout", + outputdir, testname_dash); + snprintf(expectfile_stderr, sizeof(expectfile_stderr), + "%s/expected/%s.stderr", + outputdir, testname_dash); + snprintf(expectfile_source, sizeof(expectfile_source), + "%s/expected/%s.c", + outputdir, testname_dash); + + /* + * We can use replace_string() here because the replacement string does + * not occupy more space than the replaced one. + */ + outfile_stdout = strdup(expectfile_stdout); + replace_string(outfile_stdout, "/expected/", "/results/"); + outfile_stderr = strdup(expectfile_stderr); + replace_string(outfile_stderr, "/expected/", "/results/"); + outfile_source = strdup(expectfile_source); + replace_string(outfile_source, "/expected/", "/results/"); + + add_stringlist_item(resultfiles, outfile_stdout); + add_stringlist_item(expectfiles, expectfile_stdout); + add_stringlist_item(tags, "stdout"); + + add_stringlist_item(resultfiles, outfile_stderr); + add_stringlist_item(expectfiles, expectfile_stderr); + add_stringlist_item(tags, "stderr"); + + add_stringlist_item(resultfiles, outfile_source); + add_stringlist_item(expectfiles, expectfile_source); + add_stringlist_item(tags, "source"); + + snprintf(insource, sizeof(insource), "%s.c", testname); + ecpg_filter(insource, outfile_source); + + snprintf(inprg, sizeof(inprg), "%s/%s", inputdir, testname); + + snprintf(cmd, sizeof(cmd), + SYSTEMQUOTE "\"%s\" >\"%s\" 2>\"%s\"" SYSTEMQUOTE, + inprg, + outfile_stdout, + outfile_stderr); + + pid = spawn_process(cmd); + + if (pid == INVALID_PID) + { + fprintf(stderr, _("could not start process for test %s\n"), + testname); + exit_nicely(2); + } + + free(outfile_stdout); + free(outfile_stderr); + free(outfile_source); + + return pid; +} + +static void +ecpg_init(void) +{ + /* no reason to set -w for ecpg checks, except for when on windows */ + if (strstr(host_platform, "-win32")) + basic_diff_opts = "-w"; + else + basic_diff_opts = ""; + if (strstr(host_platform, "-win32")) + pretty_diff_opts = "-C3 -w"; + else + pretty_diff_opts = "-C3"; +} + +int +main(int argc, char *argv[]) +{ + return regression_main(argc, argv, ecpg_init, ecpg_start_test); +} + diff --git a/src/interfaces/ecpg/test/resultmap b/src/interfaces/ecpg/test/resultmap new file mode 100644 index 0000000000..b308fc9a3e --- /dev/null +++ b/src/interfaces/ecpg/test/resultmap @@ -0,0 +1,3 @@ +compat_informix/dec_test:stdout:i.86-pc-win32vc=compat_informix-dec_test-MinGW32.stdout +pgtypeslib/num_test:stdout:i.86-pc-win32vc=pgtypeslib-num_test-MinGW32.stdout +pgtypeslib/num_test2:stdout:i.86-pc-win32vc=pgtypeslib-num_test2-MinGW32.stdout diff --git a/src/interfaces/ecpg/test/thread/thread.pgc b/src/interfaces/ecpg/test/thread/thread.pgc index 726121d2ca..dd3a5d33ae 100644 --- a/src/interfaces/ecpg/test/thread/thread.pgc +++ b/src/interfaces/ecpg/test/thread/thread.pgc @@ -103,7 +103,11 @@ void *test_thread(void *arg) EXEC SQL END DECLARE SECTION; /* build up connection name, and connect to database */ +#ifndef WIN32_ONLY_COMPILER snprintf(l_connection, sizeof(l_connection), "thread_%03ld", threadnum); +#else + _snprintf(l_connection, sizeof(l_connection), "thread_%03ld", threadnum); +#endif EXEC SQL WHENEVER sqlerror sqlprint; EXEC SQL CONNECT TO REGRESSDB1 AS :l_connection; if( sqlca.sqlcode != 0 ) diff --git a/src/interfaces/ecpg/test/thread/thread_implicit.pgc b/src/interfaces/ecpg/test/thread/thread_implicit.pgc index 010a8e5205..299f8e6118 100644 --- a/src/interfaces/ecpg/test/thread/thread_implicit.pgc +++ b/src/interfaces/ecpg/test/thread/thread_implicit.pgc @@ -104,7 +104,11 @@ void *test_thread(void *arg) EXEC SQL END DECLARE SECTION; /* build up connection name, and connect to database */ +#ifndef WIN32_ONLY_COMPILER snprintf(l_connection, sizeof(l_connection), "thread_%03ld", threadnum); +#else + _snprintf(l_connection, sizeof(l_connection), "thread_%03ld", threadnum); +#endif EXEC SQL WHENEVER sqlerror sqlprint; EXEC SQL CONNECT TO REGRESSDB1 AS :l_connection; if( sqlca.sqlcode != 0 ) diff --git a/src/test/regress/GNUmakefile b/src/test/regress/GNUmakefile index 0c026c9bd8..52aa7c75bc 100644 --- a/src/test/regress/GNUmakefile +++ b/src/test/regress/GNUmakefile @@ -6,7 +6,7 @@ # Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # -# $PostgreSQL: pgsql/src/test/regress/GNUmakefile,v 1.67 2007/03/13 22:56:48 tgl Exp $ +# $PostgreSQL: pgsql/src/test/regress/GNUmakefile,v 1.68 2007/06/12 11:07:32 mha Exp $ # #------------------------------------------------------------------------- @@ -51,7 +51,7 @@ EXTRADEFS = '-DHOST_TUPLE="$(host_tuple)"' \ all: submake-libpgport pg_regress$(X) -pg_regress$(X): pg_regress.o +pg_regress$(X): pg_regress.o pg_regress_main.o $(CC) $(CFLAGS) $^ $(LDFLAGS) $(LIBS) -o $@ # dependencies ensure that path changes propagate @@ -165,7 +165,7 @@ clean distclean maintainer-clean: clean-lib # things built by `all' target rm -f $(NAME)$(DLSUFFIX) $(OBJS) $(MAKE) -C $(contribdir)/spi clean - rm -f $(output_files) $(input_files) pg_regress.o pg_regress$(X) + rm -f $(output_files) $(input_files) pg_regress_main.o pg_regress.o pg_regress$(X) # things created by various check targets rm -rf testtablespace rm -rf results tmp_check log diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c index 0103b8868a..100adbe4dd 100644 --- a/src/test/regress/pg_regress.c +++ b/src/test/regress/pg_regress.c @@ -11,12 +11,12 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/test/regress/pg_regress.c,v 1.32 2007/05/31 15:13:06 petere Exp $ + * $PostgreSQL: pgsql/src/test/regress/pg_regress.c,v 1.33 2007/06/12 11:07:34 mha Exp $ * *------------------------------------------------------------------------- */ -#include "postgres_fe.h" +#include "pg_regress.h" #include #include @@ -32,26 +32,11 @@ #include "getopt_long.h" #include "pg_config_paths.h" -#ifndef WIN32 -#define PID_TYPE pid_t -#define INVALID_PID (-1) -#else -#define PID_TYPE HANDLE -#define INVALID_PID INVALID_HANDLE_VALUE -#endif - - -/* simple list of strings */ -typedef struct _stringlist -{ - char *str; - struct _stringlist *next; -} _stringlist; - /* for resultmap we need a list of pairs of strings */ typedef struct _resultmap { char *test; + char *type; char *resultfile; struct _resultmap *next; } _resultmap; @@ -63,10 +48,10 @@ typedef struct _resultmap * In non-temp_install mode, the only thing we need is the location of psql, * which we expect to find in psqldir, or in the PATH if psqldir isn't given. */ -static char *bindir = PGBINDIR; -static char *libdir = LIBDIR; -static char *datadir = PGSHAREDIR; -static char *host_platform = HOST_TUPLE; +char *bindir = PGBINDIR; +char *libdir = LIBDIR; +char *datadir = PGSHAREDIR; +char *host_platform = HOST_TUPLE; #ifndef WIN32_ONLY_COMPILER static char *makeprog = MAKEPROG; #endif @@ -76,14 +61,15 @@ static char *shellprog = SHELLPROG; #endif /* currently we can use the same diff switches on all platforms */ -static const char *basic_diff_opts = "-w"; -static const char *pretty_diff_opts = "-w -C3"; +const char *basic_diff_opts = "-w"; +const char *pretty_diff_opts = "-w -C3"; /* options settable from command line */ -static char *dbname = "regression"; -static bool debug = false; -static char *inputdir = "."; -static char *outputdir = "."; +_stringlist *dblist = NULL; +bool debug = false; +char *inputdir = "."; +char *outputdir = "."; +char *psqldir = NULL; static _stringlist *loadlanguage = NULL; static int max_connections = 0; static char *encoding = NULL; @@ -93,11 +79,11 @@ static char *temp_install = NULL; static char *top_builddir = NULL; static int temp_port = 65432; static bool nolocale = false; -static char *psqldir = NULL; static char *hostname = NULL; static int port = -1; static char *user = NULL; static char *srcdir = NULL; +static _stringlist *extraroles = NULL; /* internal variables */ static const char *progname; @@ -170,7 +156,7 @@ unlimit_core_size(void) /* * Add an item at the end of a stringlist. */ -static void +void add_stringlist_item(_stringlist ** listhead, const char *str) { _stringlist *newentry = malloc(sizeof(_stringlist)); @@ -188,6 +174,37 @@ add_stringlist_item(_stringlist ** listhead, const char *str) } } +/* + * Free a stringlist. + */ +static void +free_stringlist(_stringlist **listhead) +{ + if (listhead == NULL || *listhead == NULL) + return; + if ((*listhead)->next != NULL) + free_stringlist(&((*listhead)->next)); + free((*listhead)->str); + free(*listhead); + *listhead = NULL; +} + +/* + * Split a delimited string into a stringlist + */ +static void +split_to_stringlist(const char *s, const char *delim, _stringlist **listhead) +{ + char *sc = strdup(s); + char *token = strtok(sc, delim); + while (token) + { + add_stringlist_item(listhead, token); + token = strtok(NULL, delim); + } + free(sc); +} + /* * Print a progress banner on stdout. */ @@ -265,7 +282,7 @@ stop_postmaster(void) * Always exit through here, not through plain exit(), to ensure we make * an effort to shut down a temp postmaster */ -static void +void exit_nicely(int code) { stop_postmaster(); @@ -349,7 +366,7 @@ string_matches_pattern(const char *str, const char *pattern) * Replace all occurances of a string in a string with a different string. * NOTE: Assumes there is enough room in the target buffer! */ -static void +void replace_string(char *string, char *replace, char *replacement) { char *ptr; @@ -537,6 +554,7 @@ load_resultmap(void) while (fgets(buf, sizeof(buf), f)) { char *platform; + char *file_type; char *expected; int i; @@ -546,7 +564,16 @@ load_resultmap(void) buf[--i] = '\0'; /* parse out the line fields */ - platform = strchr(buf, '/'); + file_type = strchr(buf, ':'); + if (!file_type) + { + fprintf(stderr, _("incorrectly formatted resultmap entry: %s\n"), + buf); + exit_nicely(2); + } + *file_type++ = '\0'; + + platform = strchr(file_type, ':'); if (!platform) { fprintf(stderr, _("incorrectly formatted resultmap entry: %s\n"), @@ -574,6 +601,7 @@ load_resultmap(void) _resultmap *entry = malloc(sizeof(_resultmap)); entry->test = strdup(buf); + entry->type = strdup(file_type); entry->resultfile = strdup(expected); entry->next = resultmap; resultmap = entry; @@ -582,6 +610,35 @@ load_resultmap(void) fclose(f); } +/* + * Check in resultmap if we should be looking at a different file + */ +static +const char *get_expectfile(const char *testname, const char *file) +{ + char *file_type; + _resultmap *rm; + + /* + * Determine the file type from the file name. This is just what is + * following the last dot in the file name. + */ + if (!file || !(file_type = strrchr(file, '.'))) + return NULL; + + file_type++; + + for (rm = resultmap; rm != NULL; rm = rm->next) + { + if (strcmp(testname, rm->test) == 0 && strcmp(file_type, rm->type) == 0) + { + return rm->resultfile; + } + } + + return NULL; +} + /* * Handy subroutine for setting an environment variable "var" to "val" */ @@ -704,7 +761,7 @@ initialize_environment(void) /* psql will be installed into temp-install bindir */ psqldir = bindir; - + /* * Set up shared library paths to include the temp install. * @@ -820,7 +877,7 @@ psql_command(const char *database, const char *query,...) * * Returns the process ID (or HANDLE) so we can wait for it later */ -static PID_TYPE +PID_TYPE spawn_process(const char *cmdline) { #ifndef WIN32 @@ -943,43 +1000,6 @@ spawn_process(const char *cmdline) #endif } -/* - * start a psql test process for specified file (including redirection), - * and return process ID - */ -static PID_TYPE -psql_start_test(const char *testname) -{ - PID_TYPE pid; - char infile[MAXPGPATH]; - char outfile[MAXPGPATH]; - char psql_cmd[MAXPGPATH * 3]; - - snprintf(infile, sizeof(infile), "%s/sql/%s.sql", - inputdir, testname); - snprintf(outfile, sizeof(outfile), "%s/results/%s.out", - outputdir, testname); - - snprintf(psql_cmd, sizeof(psql_cmd), - SYSTEMQUOTE "\"%s%spsql\" -X -a -q -d \"%s\" < \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE, - psqldir ? psqldir : "", - psqldir ? "/" : "", - dbname, - infile, - outfile); - - pid = spawn_process(psql_cmd); - - if (pid == INVALID_PID) - { - fprintf(stderr, _("could not start process for test %s\n"), - testname); - exit_nicely(2); - } - - return pid; -} - /* * Count bytes in file */ @@ -1061,6 +1081,26 @@ make_directory(const char *dir) } } +/* + * In: filename.ext, Return: filename_i.ext, where 0 < i <= 9 + */ +static char * +get_alternative_expectfile(const char *expectfile, int i) +{ + char *last_dot; + int ssize = strlen(expectfile) + 2 + 1; + char *tmp = (char *)malloc(ssize); + char *s = (char *)malloc(ssize); + strcpy(tmp, expectfile); + last_dot = strrchr(tmp,'.'); + if (!last_dot) + return NULL; + *last_dot = '\0'; + snprintf(s, ssize, "%s_%d.%s", tmp, i, last_dot+1); + free(tmp); + return s; +} + /* * Run a "diff" command and also check that it didn't crash */ @@ -1098,42 +1138,38 @@ run_diff(const char *cmd, const char *filename) * In the true case, the diff is appended to the diffs file. */ static bool -results_differ(const char *testname) +results_differ(const char *testname, const char *resultsfile, const char *default_expectfile) { - const char *expectname; - char resultsfile[MAXPGPATH]; char expectfile[MAXPGPATH]; char diff[MAXPGPATH]; char cmd[MAXPGPATH * 3]; char best_expect_file[MAXPGPATH]; - _resultmap *rm; FILE *difffile; int best_line_count; int i; int l; + const char *platform_expectfile; - /* Check in resultmap if we should be looking at a different file */ - expectname = testname; - for (rm = resultmap; rm != NULL; rm = rm->next) + /* + * We can pass either the resultsfile or the expectfile, they should + * have the same type (filename.type) anyway. + */ + platform_expectfile = get_expectfile(testname, resultsfile); + + strcpy(expectfile, default_expectfile); + if (platform_expectfile) { - if (strcmp(testname, rm->test) == 0) - { - expectname = rm->resultfile; - break; - } + /* + * Replace everything afer the last slash in expectfile with what the + * platform_expectfile contains. + */ + char *p = strrchr(expectfile, '/'); + if (p) + strcpy(++p, platform_expectfile); } - /* Name of test results file */ - snprintf(resultsfile, sizeof(resultsfile), "%s/results/%s.out", - outputdir, testname); - - /* Name of expected-results file */ - snprintf(expectfile, sizeof(expectfile), "%s/expected/%s.out", - inputdir, expectname); - /* Name to use for temporary diff file */ - snprintf(diff, sizeof(diff), "%s/results/%s.diff", - outputdir, testname); + snprintf(diff, sizeof(diff), "%s.diff", resultsfile); /* OK, run the diff */ snprintf(cmd, sizeof(cmd), @@ -1153,14 +1189,15 @@ results_differ(const char *testname) for (i = 0; i <= 9; i++) { - snprintf(expectfile, sizeof(expectfile), "%s/expected/%s_%d.out", - inputdir, expectname, i); - if (!file_exists(expectfile)) + char *alt_expectfile; + + alt_expectfile = get_alternative_expectfile(expectfile, i); + if (!file_exists(alt_expectfile)) continue; snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "diff %s \"%s\" \"%s\" > \"%s\"" SYSTEMQUOTE, - basic_diff_opts, expectfile, resultsfile, diff); + basic_diff_opts, alt_expectfile, resultsfile, diff); if (run_diff(cmd, diff) == 0) { @@ -1173,8 +1210,9 @@ results_differ(const char *testname) { /* This diff was a better match than the last one */ best_line_count = l; - strcpy(best_expect_file, expectfile); + strcpy(best_expect_file, alt_expectfile); } + free(alt_expectfile); } /* @@ -1182,14 +1220,11 @@ results_differ(const char *testname) * haven't found a complete match yet. */ - if (strcmp(expectname, testname) != 0) + if (platform_expectfile) { - snprintf(expectfile, sizeof(expectfile), "%s/expected/%s.out", - inputdir, testname); - snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "diff %s \"%s\" \"%s\" > \"%s\"" SYSTEMQUOTE, - basic_diff_opts, expectfile, resultsfile, diff); + basic_diff_opts, default_expectfile, resultsfile, diff); if (run_diff(cmd, diff) == 0) { @@ -1203,7 +1238,7 @@ results_differ(const char *testname) { /* This diff was a better match than the last one */ best_line_count = l; - strcpy(best_expect_file, expectfile); + strcpy(best_expect_file, default_expectfile); } } @@ -1302,16 +1337,23 @@ wait_for_tests(PID_TYPE * pids, char **names, int num_tests) * Run all the tests specified in one schedule file */ static void -run_schedule(const char *schedule) +run_schedule(const char *schedule, test_function tfunc) { #define MAX_PARALLEL_TESTS 100 char *tests[MAX_PARALLEL_TESTS]; + _stringlist *resultfiles[MAX_PARALLEL_TESTS]; + _stringlist *expectfiles[MAX_PARALLEL_TESTS]; + _stringlist *tags[MAX_PARALLEL_TESTS]; PID_TYPE pids[MAX_PARALLEL_TESTS]; _stringlist *ignorelist = NULL; char scbuf[1024]; FILE *scf; int line_num = 0; + memset(resultfiles,0,sizeof(_stringlist *) * MAX_PARALLEL_TESTS); + memset(expectfiles,0,sizeof(_stringlist *) * MAX_PARALLEL_TESTS); + memset(tags,0,sizeof(_stringlist *) * MAX_PARALLEL_TESTS); + scf = fopen(schedule, "r"); if (!scf) { @@ -1330,6 +1372,15 @@ run_schedule(const char *schedule) line_num++; + for (i = 0; i < MAX_PARALLEL_TESTS; i++) + { + if (resultfiles[i] == NULL) + break; + free_stringlist(&resultfiles[i]); + free_stringlist(&expectfiles[i]); + free_stringlist(&tags[i]); + } + /* strip trailing whitespace, especially the newline */ i = strlen(scbuf); while (i > 0 && isspace((unsigned char) scbuf[i - 1])) @@ -1394,7 +1445,7 @@ run_schedule(const char *schedule) if (num_tests == 1) { status(_("test %-20s ... "), tests[0]); - pids[0] = psql_start_test(tests[0]); + pids[0] = (tfunc)(tests[0], &resultfiles[0], &expectfiles[0], &tags[0]); wait_for_tests(pids, NULL, 1); /* status line is finished below */ } @@ -1411,7 +1462,7 @@ run_schedule(const char *schedule) wait_for_tests(pids + oldest, tests + oldest, i - oldest); oldest = i; } - pids[i] = psql_start_test(tests[i]); + pids[i] = (tfunc)(tests[i], &resultfiles[i], &expectfiles[i], &tags[i]); } wait_for_tests(pids + oldest, tests + oldest, i - oldest); status_end(); @@ -1421,7 +1472,7 @@ run_schedule(const char *schedule) status(_("parallel group (%d tests): "), num_tests); for (i = 0; i < num_tests; i++) { - pids[i] = psql_start_test(tests[i]); + pids[i] = (tfunc)(tests[i], &resultfiles[i], &expectfiles[i], &tags[i]); } wait_for_tests(pids, tests, num_tests); status_end(); @@ -1430,10 +1481,36 @@ run_schedule(const char *schedule) /* Check results for all tests */ for (i = 0; i < num_tests; i++) { + _stringlist *rl, *el, *tl; + bool differ = false; + if (num_tests > 1) status(_(" %-20s ... "), tests[i]); - if (results_differ(tests[i])) + /* + * Advance over all three lists simultaneously. + * + * Compare resultfiles[j] with expectfiles[j] always. + * Tags are optional but if there are tags, the tag list has the + * same length as the other two lists. + */ + for (rl = resultfiles[i], el = expectfiles[i], tl = tags[i]; + rl != NULL; /* rl and el have the same length */ + rl = rl->next, el = el->next) + { + bool newdiff; + if (tl) + tl = tl->next; /* tl has the same lengt has rl and el if it exists */ + + newdiff = results_differ(tests[i], rl->str, el->str); + if (newdiff && tl) + { + printf("%s ", tl->str); + } + differ |= newdiff; + } + + if (differ) { bool ignore = false; _stringlist *sl; @@ -1474,15 +1551,43 @@ run_schedule(const char *schedule) * Run a single test */ static void -run_single_test(const char *test) +run_single_test(const char *test, test_function tfunc) { PID_TYPE pid; + _stringlist *resultfiles; + _stringlist *expectfiles; + _stringlist *tags; + _stringlist *rl, *el, *tl; + bool differ = false; status(_("test %-20s ... "), test); - pid = psql_start_test(test); + pid = (tfunc)(test, &resultfiles, &expectfiles, &tags); wait_for_tests(&pid, NULL, 1); - if (results_differ(test)) + /* + * Advance over all three lists simultaneously. + * + * Compare resultfiles[j] with expectfiles[j] always. + * Tags are optional but if there are tags, the tag list has the + * same length as the other two lists. + */ + for (rl = resultfiles, el = expectfiles, tl = tags; + rl != NULL; /* rl and el have the same length */ + rl = rl->next, el = el->next) + { + bool newdiff; + if (tl) + tl = tl->next; /* tl has the same lengt has rl and el if it exists */ + + newdiff = results_differ(test, rl->str, el->str); + if (newdiff && tl) + { + printf("%s ", tl->str); + } + differ |= newdiff; + } + + if (differ) { status(_("FAILED")); fail_count++; @@ -1534,6 +1639,63 @@ open_result_files(void) make_directory(file); } +static void +drop_database_if_exists(const char *dbname) +{ + header(_("dropping database \"%s\""), dbname); + psql_command("postgres", "DROP DATABASE IF EXISTS \"%s\"", dbname); +} + +static void +create_database(const char *dbname) +{ + _stringlist *sl; + /* + * We use template0 so that any installation-local cruft in template1 will + * not mess up the tests. + */ + header(_("creating database \"%s\""), dbname); + if (encoding) + psql_command("postgres", "CREATE DATABASE \"%s\" TEMPLATE=template0 ENCODING='%s'", dbname, encoding); + else + psql_command("postgres", "CREATE DATABASE \"%s\" TEMPLATE=template0", dbname); + psql_command(dbname, + "ALTER DATABASE \"%s\" SET lc_messages TO 'C';" + "ALTER DATABASE \"%s\" SET lc_monetary TO 'C';" + "ALTER DATABASE \"%s\" SET lc_numeric TO 'C';" + "ALTER DATABASE \"%s\" SET lc_time TO 'C';" + "ALTER DATABASE \"%s\" SET timezone_abbreviations TO 'Default';", + dbname, dbname, dbname, dbname, dbname); + + /* + * Install any requested procedural languages + */ + for (sl = loadlanguage; sl != NULL; sl = sl->next) + { + header(_("installing %s"), sl->str); + psql_command(dbname, "CREATE LANGUAGE \"%s\"", sl->str); + } +} + +static void +drop_role_if_exists(const char *rolename) +{ + header(_("dropping role \"%s\""), rolename); + psql_command("postgres", "DROP ROLE IF EXISTS \"%s\"", rolename); +} + +static void +create_role(const char *rolename, const _stringlist *granted_dbs) +{ + header(_("creating role \"%s\""), rolename); + psql_command("postgres", "CREATE ROLE \"%s\" WITH LOGIN", rolename); + for (; granted_dbs != NULL; granted_dbs = granted_dbs->next) + { + psql_command("postgres", "GRANT ALL ON DATABASE \"%s\" TO \"%s\"", + granted_dbs->str, rolename); + } +} + static void help(void) { @@ -1547,6 +1709,7 @@ help(void) printf(_(" --inputdir=DIR take input files from DIR (default \".\")\n")); printf(_(" --load-language=lang load the named language before running the\n")); printf(_(" tests; can appear multiple times\n")); + printf(_(" --create-role=ROLE create the specified role before testing\n")); printf(_(" --max-connections=N maximum number of concurrent connections\n")); printf(_(" (default is 0 meaning unlimited)\n")); printf(_(" --multibyte=ENCODING use ENCODING as the multibyte encoding\n")); @@ -1574,7 +1737,7 @@ help(void) } int -main(int argc, char *argv[]) +regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc) { _stringlist *sl; int c; @@ -1602,6 +1765,7 @@ main(int argc, char *argv[]) {"user", required_argument, NULL, 15}, {"psqldir", required_argument, NULL, 16}, {"srcdir", required_argument, NULL, 17}, + {"create-role", required_argument, NULL, 18}, {NULL, 0, NULL, 0} }; @@ -1613,6 +1777,12 @@ main(int argc, char *argv[]) hostname = "localhost"; #endif + /* + * We call the initialization function here because that way we can set + * default parameters and let them be overwritten by the commandline. + */ + ifunc(); + while ((c = getopt_long(argc, argv, "hV", long_options, &option_index)) != -1) { switch (c) @@ -1624,7 +1794,7 @@ main(int argc, char *argv[]) printf("pg_regress (PostgreSQL %s)\n", PG_VERSION); exit_nicely(0); case 1: - dbname = strdup(optarg); + split_to_stringlist(strdup(optarg), ", ", &dblist); break; case 2: debug = true; @@ -1697,6 +1867,9 @@ main(int argc, char *argv[]) case 17: srcdir = strdup(optarg); break; + case 18: + split_to_stringlist(strdup(optarg), ", ", &extraroles); + break; default: /* getopt_long already emitted a complaint */ fprintf(stderr, _("\nTry \"%s -h\" for more information.\n"), @@ -1865,45 +2038,21 @@ main(int argc, char *argv[]) { /* * Using an existing installation, so may need to get rid of - * pre-existing database. + * pre-existing database(s) and role(s) */ - header(_("dropping database \"%s\""), dbname); - psql_command("postgres", "DROP DATABASE IF EXISTS \"%s\"", dbname); + for (sl = dblist; sl; sl = sl->next) + drop_database_if_exists(sl->str); + for (sl = extraroles; sl; sl = sl->next) + drop_role_if_exists(sl->str); } /* - * Create the test database - * - * We use template0 so that any installation-local cruft in template1 will - * not mess up the tests. + * Create the test database(s) and role(s) */ - header(_("creating database \"%s\""), dbname); - if (encoding) - psql_command("postgres", - "CREATE DATABASE \"%s\" TEMPLATE=template0 ENCODING='%s'", - dbname, encoding); - else - /* use installation default */ - psql_command("postgres", - "CREATE DATABASE \"%s\" TEMPLATE=template0", - dbname); - - psql_command(dbname, - "ALTER DATABASE \"%s\" SET lc_messages TO 'C';" - "ALTER DATABASE \"%s\" SET lc_monetary TO 'C';" - "ALTER DATABASE \"%s\" SET lc_numeric TO 'C';" - "ALTER DATABASE \"%s\" SET lc_time TO 'C';" - "ALTER DATABASE \"%s\" SET timezone_abbreviations TO 'Default';", - dbname, dbname, dbname, dbname, dbname); - - /* - * Install any requested PL languages - */ - for (sl = loadlanguage; sl != NULL; sl = sl->next) - { - header(_("installing %s"), sl->str); - psql_command(dbname, "CREATE LANGUAGE \"%s\"", sl->str); - } + for (sl = dblist; sl; sl = sl->next) + create_database(sl->str); + for (sl = extraroles; sl; sl = sl->next) + create_role(sl->str, dblist); /* * Ready to run the tests @@ -1912,12 +2061,12 @@ main(int argc, char *argv[]) for (sl = schedulelist; sl != NULL; sl = sl->next) { - run_schedule(sl->str); + run_schedule(sl->str, tfunc); } for (sl = extra_tests; sl != NULL; sl = sl->next) { - run_single_test(sl->str); + run_single_test(sl->str, tfunc); } /* diff --git a/src/test/regress/pg_regress.h b/src/test/regress/pg_regress.h new file mode 100644 index 0000000000..c820c1fbeb --- /dev/null +++ b/src/test/regress/pg_regress.h @@ -0,0 +1,59 @@ +/*------------------------------------------------------------------------- + * pg_regress.h --- regression test driver + * + * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * $PostgreSQL: pgsql/src/test/regress/pg_regress.h,v 1.1 2007/06/12 11:07:34 mha Exp $ + *------------------------------------------------------------------------- + */ + +#include "postgres_fe.h" +#include + +#ifndef WIN32 +#define PID_TYPE pid_t +#define INVALID_PID (-1) +#else +#define PID_TYPE HANDLE +#define INVALID_PID INVALID_HANDLE_VALUE +#endif + +/* simple list of strings */ +typedef struct _stringlist +{ + char *str; + struct _stringlist *next; +} _stringlist; + +typedef PID_TYPE (*test_function)(const char *, + _stringlist **, + _stringlist **, + _stringlist **); +typedef void (*init_function)(void); + +extern char *bindir; +extern char *libdir; +extern char *datadir; +extern char *host_platform; + +extern _stringlist *dblist; +extern bool debug; +extern char *inputdir; +extern char *outputdir; +/* + * This should not be global but every module should be able to read command + * line parameters. + */ +extern char *psqldir; + +extern const char *basic_diff_opts; +extern const char *pretty_diff_opts; + +int regression_main(int argc, char *argv[], + init_function ifunc, test_function tfunc); +void add_stringlist_item(_stringlist ** listhead, const char *str); +PID_TYPE spawn_process(const char *cmdline); +void exit_nicely(int code); +void replace_string(char *string, char *replace, char *replacement); + diff --git a/src/test/regress/pg_regress_main.c b/src/test/regress/pg_regress_main.c new file mode 100644 index 0000000000..fea5c35f59 --- /dev/null +++ b/src/test/regress/pg_regress_main.c @@ -0,0 +1,78 @@ +/*------------------------------------------------------------------------- + * + * pg_regress_main --- regression test for the main backend + * + * This is a C implementation of the previous shell script for running + * the regression tests, and should be mostly compatible with it. + * Initial author of C translation: Magnus Hagander + * + * This code is released under the terms of the PostgreSQL License. + * + * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * $PostgreSQL: pgsql/src/test/regress/pg_regress_main.c,v 1.1 2007/06/12 11:07:34 mha Exp $ + * + *------------------------------------------------------------------------- + */ + +#include "pg_regress.h" + +/* + * start a psql test process for specified file (including redirection), + * and return process ID + */ +static PID_TYPE +psql_start_test(const char *testname, + _stringlist **resultfiles, + _stringlist **expectfiles, + _stringlist **tags) +{ + PID_TYPE pid; + char infile[MAXPGPATH]; + char outfile[MAXPGPATH]; + char expectfile[MAXPGPATH]; + char psql_cmd[MAXPGPATH * 3]; + + snprintf(infile, sizeof(infile), "%s/sql/%s.sql", + inputdir, testname); + snprintf(outfile, sizeof(outfile), "%s/results/%s.out", + outputdir, testname); + snprintf(expectfile, sizeof(expectfile), "%s/expected/%s.out", + inputdir, testname); + + add_stringlist_item(resultfiles, outfile); + add_stringlist_item(expectfiles, expectfile); + + snprintf(psql_cmd, sizeof(psql_cmd), + SYSTEMQUOTE "\"%s%spsql\" -X -a -q -d \"%s\" < \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE, + psqldir ? psqldir : "", + psqldir ? "/" : "", + dblist->str, + infile, + outfile); + + pid = spawn_process(psql_cmd); + + if (pid == INVALID_PID) + { + fprintf(stderr, _("could not start process for test %s\n"), + testname); + exit_nicely(2); + } + + return pid; +} + +static void +psql_init(void) +{ + /* set default regression database name */ + add_stringlist_item(&dblist, "regression"); +} + +int +main(int argc, char *argv[]) +{ + return regression_main(argc, argv, psql_init, psql_start_test); +} diff --git a/src/test/regress/resultmap b/src/test/regress/resultmap index 01fe0eb74b..7bfcee29b4 100644 --- a/src/test/regress/resultmap +++ b/src/test/regress/resultmap @@ -1,11 +1,11 @@ -float4/i.86-pc-mingw32=float4-exp-three-digits -float4/i.86-pc-win32vc=float4-exp-three-digits -float8/i.86-.*-freebsd=float8-small-is-zero -float8/i.86-.*-openbsd=float8-small-is-zero -float8/i.86-.*-netbsd=float8-small-is-zero -float8/m68k-.*-netbsd=float8-small-is-zero -float8/i.86-pc-mingw32=float8-exp-three-digits-win32 -float8/i.86-pc-win32vc=float8-exp-three-digits-win32 -float8/i.86-pc-cygwin=float8-small-is-zero -int8/i.86-pc-mingw32=int8-exp-three-digits -int8/i.86-pc-win32vc=int8-exp-three-digits \ No newline at end of file +float4:out:i.86-pc-mingw32=float4-exp-three-digits.out +float4:out:i.86-pc-win32vc=float4-exp-three-digits.out +float8:out:i.86-.*-freebsd=float8-small-is-zero.out +float8:out:i.86-.*-openbsd=float8-small-is-zero.out +float8:out:i.86-.*-netbsd=float8-small-is-zero.out +float8:out:m68k-.*-netbsd=float8-small-is-zero.out +float8:out:i.86-pc-mingw32=float8-exp-three-digits-win32.out +float8:out:i.86-pc-win32vc=float8-exp-three-digits-win32.out +float8:out:i.86-pc-cygwin=float8-small-is-zero.out +int8:out:i.86-pc-mingw32=int8-exp-three-digits.out +int8:out:i.86-pc-win32vc=int8-exp-three-digits.out diff --git a/src/tools/msvc/Install.pm b/src/tools/msvc/Install.pm index 26ad8f4a4e..e8980c2dd6 100644 --- a/src/tools/msvc/Install.pm +++ b/src/tools/msvc/Install.pm @@ -3,7 +3,7 @@ package Install; # # Package that provides 'make install' functionality for msvc builds # -# $PostgreSQL: pgsql/src/tools/msvc/Install.pm,v 1.15 2007/05/13 15:33:07 mha Exp $ +# $PostgreSQL: pgsql/src/tools/msvc/Install.pm,v 1.16 2007/06/12 11:07:34 mha Exp $ # use strict; use warnings; @@ -25,6 +25,7 @@ sub Install require 'config.pl'; chdir("../../..") if (-f "../../../configure"); + chdir("../../../..") if (-f "../../../../configure"); my $conf = ""; if (-d "debug") { @@ -115,6 +116,7 @@ sub CopySetOfFiles { chomp; next if /regress/; # Skip temporary install in regression subdir + next if /ecpg.test/; # Skip temporary install in regression subdir my $tgt = $target . basename($_); print "."; my $src = $norecurse?(dirname($spec) . '/' . $_):$_; diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index 35ccdcc471..c71ea446bc 100644 --- a/src/tools/msvc/Mkvcbuild.pm +++ b/src/tools/msvc/Mkvcbuild.pm @@ -3,7 +3,7 @@ package Mkvcbuild; # # Package that generates build files for msvc build # -# $PostgreSQL: pgsql/src/tools/msvc/Mkvcbuild.pm,v 1.11 2007/04/27 16:45:54 mha Exp $ +# $PostgreSQL: pgsql/src/tools/msvc/Mkvcbuild.pm,v 1.12 2007/06/12 11:07:34 mha Exp $ # use Carp; use Win32; @@ -154,6 +154,15 @@ sub mkvcbuild $ecpg->AddDefine('PATCHLEVEL=1'); $ecpg->AddReference($libpgport); + my $pgregress_ecpg = $solution->AddProject('pg_regress_ecpg','exe','misc'); + $pgregress_ecpg->AddFile('src\interfaces\ecpg\test\pg_regress_ecpg.c'); + $pgregress_ecpg->AddFile('src\test\regress\pg_regress.c'); + $pgregress_ecpg->AddIncludeDir('src\port'); + $pgregress_ecpg->AddIncludeDir('src\test\regress'); + $pgregress_ecpg->AddDefine('HOST_TUPLE="i686-pc-win32vc"'); + $pgregress_ecpg->AddDefine('FRONTEND'); + $pgregress_ecpg->AddReference($libpgport); + # src/bin my $initdb = AddSimpleFrontend('initdb', 1); $initdb->AddLibrary('wsock32.lib ws2_32.lib'); @@ -315,6 +324,7 @@ sub mkvcbuild my $pgregress = $solution->AddProject('pg_regress','exe','misc'); $pgregress->AddFile('src\test\regress\pg_regress.c'); + $pgregress->AddFile('src\test\regress\pg_regress_main.c'); $pgregress->AddIncludeDir('src\port'); $pgregress->AddDefine('HOST_TUPLE="i686-pc-win32vc"'); $pgregress->AddDefine('FRONTEND'); diff --git a/src/tools/msvc/clean.bat b/src/tools/msvc/clean.bat index 1f13c92b24..7d4a0a802e 100755 --- a/src/tools/msvc/clean.bat +++ b/src/tools/msvc/clean.bat @@ -1,5 +1,5 @@ @echo off -REM $PostgreSQL: pgsql/src/tools/msvc/clean.bat,v 1.4 2007/03/23 09:53:33 mha Exp $ +REM $PostgreSQL: pgsql/src/tools/msvc/clean.bat,v 1.5 2007/06/12 11:07:34 mha Exp $ set D=%CD% if exist ..\msvc if exist ..\..\..\src cd ..\..\.. @@ -59,6 +59,10 @@ call :del tsearch2\tsearch2.sql call :del tsearch2\uninstall_tsearch2.sql cd %D% + +REM Clean up ecpg regression test files +msbuild ecpg_regression.proj /t:clean /v:q + goto :eof diff --git a/src/tools/msvc/ecpg_regression.proj b/src/tools/msvc/ecpg_regression.proj new file mode 100644 index 0000000000..6634627f2b --- /dev/null +++ b/src/tools/msvc/ecpg_regression.proj @@ -0,0 +1,46 @@ + + + + + + ..\..\interfaces\ecpg\test + Debug + ..\..\..\..\..\$(CONFIG)\ + + + + d + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tools/msvc/vcregress.bat b/src/tools/msvc/vcregress.bat index 8793989967..e3221b268f 100644 --- a/src/tools/msvc/vcregress.bat +++ b/src/tools/msvc/vcregress.bat @@ -1,5 +1,5 @@ @echo off -REM $PostgreSQL: pgsql/src/tools/msvc/vcregress.bat,v 1.11 2007/04/21 20:58:05 mha Exp $ +REM $PostgreSQL: pgsql/src/tools/msvc/vcregress.bat,v 1.12 2007/06/12 11:07:34 mha Exp $ SETLOCAL SET STARTDIR=%CD% @@ -11,6 +11,7 @@ if /I "%1"=="check" SET what=CHECK if /I "%1"=="installcheck" SET what=INSTALLCHECK if /I "%1"=="plcheck" SET what=PLCHECK if /I "%1"=="contribcheck" SET what=CONTRIBCHECK +if /I "%1"=="ecpgcheck" SET what=ECPGCHECK if "%what%"=="" goto usage SET CONFIG=Debug @@ -28,10 +29,20 @@ SET SCHEDULE=parallel SET TEMPPORT=54321 IF NOT "%2"=="" SET SCHEDULE=%2 -SET PERL5LIB=..\..\tools\msvc +IF "%what%"=="ECPGCHECK" ( + cd "%STARTDIR%" + msbuild ecpg_regression.proj /p:config=%CONFIG% + if errorlevel 1 exit /b 1 + cd "%TOPDIR%" + cd src\interfaces\ecpg\test + SET SCHEDULE=ecpg +) + +SET PERL5LIB=%TOPDIR%\src\tools\msvc if "%what%"=="INSTALLCHECK" ..\..\..\%CONFIG%\pg_regress\pg_regress --psqldir="..\..\..\%CONFIG%\psql" --schedule=%SCHEDULE%_schedule --multibyte=SQL_ASCII --load-language=plpgsql --no-locale if "%what%"=="CHECK" ..\..\..\%CONFIG%\pg_regress\pg_regress --psqldir="..\..\..\%CONFIG%\psql" --schedule=%SCHEDULE%_schedule --multibyte=SQL_ASCII --load-language=plpgsql --no-locale --temp-install=./tmp_check --top-builddir="%TOPDIR%" --temp-port=%TEMPPORT% +if "%what%"=="ECPGCHECK" ..\..\..\..\%CONFIG%\pg_regress_ecpg\pg_regress_ecpg --psqldir="..\..\..\%CONFIG%\psql" --dbname=regress1,connectdb --create-role=connectuser,connectdb --schedule=%SCHEDULE%_schedule --multibyte=SQL_ASCII --load-language=plpgsql --no-locale --temp-install=./tmp_check --top-builddir="%TOPDIR%" --temp-port=%TEMPPORT% if "%what%"=="PLCHECK" call :plcheck if "%what%"=="CONTRIBCHECK" call :contribcheck SET E=%ERRORLEVEL% @@ -40,7 +51,7 @@ cd "%STARTDIR%" exit /b %E% :usage -echo "Usage: vcregress [schedule]" +echo "Usage: vcregress [schedule]" goto :eof -- cgit v1.2.1