Rewrite ECPG regression test driver in C, by splitting the standard
authorMagnus Hagander <magnus@hagander.net>
Tue, 12 Jun 2007 11:07:34 +0000 (11:07 +0000)
committerMagnus Hagander <magnus@hagander.net>
Tue, 12 Jun 2007 11:07:34 +0000 (11:07 +0000)
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

21 files changed:
src/interfaces/ecpg/test/Makefile
src/interfaces/ecpg/test/ecpg_schedule [new file with mode: 0644]
src/interfaces/ecpg/test/expected/thread-thread.c
src/interfaces/ecpg/test/expected/thread-thread_2.stdout [moved from src/interfaces/ecpg/test/expected/thread-thread-thread.stdout with 100% similarity]
src/interfaces/ecpg/test/expected/thread-thread_implicit.c
src/interfaces/ecpg/test/expected/thread-thread_implicit_2.stdout [moved from src/interfaces/ecpg/test/expected/thread-thread_implicit-thread.stdout with 100% similarity]
src/interfaces/ecpg/test/pg_regress.sh [deleted file]
src/interfaces/ecpg/test/pg_regress_ecpg.c [new file with mode: 0644]
src/interfaces/ecpg/test/resultmap [new file with mode: 0644]
src/interfaces/ecpg/test/thread/thread.pgc
src/interfaces/ecpg/test/thread/thread_implicit.pgc
src/test/regress/GNUmakefile
src/test/regress/pg_regress.c
src/test/regress/pg_regress.h [new file with mode: 0644]
src/test/regress/pg_regress_main.c [new file with mode: 0644]
src/test/regress/resultmap
src/tools/msvc/Install.pm
src/tools/msvc/Mkvcbuild.pm
src/tools/msvc/clean.bat
src/tools/msvc/ecpg_regression.proj [new file with mode: 0644]
src/tools/msvc/vcregress.bat

index f68ae926da8ff3d4bce16b7ef50fbd4f131f84c7..4b9da21481c290139cffb6f812294a16cc6d64d5 100644 (file)
@@ -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 (file)
index 0000000..108881c
--- /dev/null
@@ -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
index 9555a79bfa58879c0a165cb1a1b97689f0552fac..36d920eb3cfdcfe0be7d60d56fb43b846ca720ae 100644 (file)
@@ -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 );
 }
index f48db90559a06bbc084ad8099e9260a6cba75690..bf20c51bb561249e6ee43d8b5d6122bef76ca85e 100644 (file)
@@ -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/pg_regress.sh b/src/interfaces/ecpg/test/pg_regress.sh
deleted file mode 100644 (file)
index a164953..0000000
+++ /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 <pgsql-bugs@postgresql.org>."
-}
-
-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 2>/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 (file)
index 0000000..c829653
--- /dev/null
@@ -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 (file)
index 0000000..b308fc9
--- /dev/null
@@ -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
index 726121d2ca28fe23d45cbc9064ce4694b91c263b..dd3a5d33ae4b4419bb45cfdc80943f275f7a3abf 100644 (file)
@@ -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 )
index 010a8e52051d5a58a6774fe465f4770758037142..299f8e611867fbb9144f36f316efc74f78f2edaf 100644 (file)
@@ -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 )
index 0c026c9bd86ef57a71d1dcbdde69176448e72ab7..52aa7c75bcaacb6275c9b1e185cd49673f45e2f7 100644 (file)
@@ -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
index 0103b8868a2ca2704c5fb499f7f635e557ca5dd4..100adbe4ddf2eaac99dcf663fe7f99695ee663d6 100644 (file)
  * 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 <ctype.h>
 #include <sys/stat.h>
 #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 (file)
index 0000000..c820c1f
--- /dev/null
@@ -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 <unistd.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;
+
+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 (file)
index 0000000..fea5c35
--- /dev/null
@@ -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);
+}
index 01fe0eb74bb8ff5283374c304dbb9bd8b2c99748..7bfcee29b4841beb296f8c681bf78e8087712f0d 100644 (file)
@@ -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
index 26ad8f4a4e24209695b6a92f01f584616eaa4a4a..e8980c2dd6f086fe765fae22d4ebc568c1d6c380 100644 (file)
@@ -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) . '/' . $_):$_;
index 35ccdcc4719307d868f551b0b55036d3d6792463..c71ea446bc6b2d59bb43eb9294fc9258352e8824 100644 (file)
@@ -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');
index 1f13c92b2492277dcd609fec1d0bfca86fbdef77..7d4a0a802e7630c2661b4868dc73b957248cdfcc 100755 (executable)
@@ -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 (file)
index 0000000..6634627
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="all">
+<!--
+  MSBuild project file to build ecpg regression tests
+-->
+
+ <PropertyGroup>
+  <TESTDIR>..\..\interfaces\ecpg\test</TESTDIR>
+  <CONFIG>Debug</CONFIG>
+  <OUTDIR>..\..\..\..\..\$(CONFIG)\</OUTDIR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(CONFIG)'=='DEBUG'">
+  <!-- set debug runtime library if necessary to be compatible with the LIB files generated -->
+  <DEBUGLIB>d</DEBUGLIB>
+ </PropertyGroup>
+
+ <ItemGroup>
+  <Pgc Include="$(TESTDIR)\**\*.pgc" Exclude="$(TESTDIR)\performance\perftest.pgc"/>
+ </ItemGroup>
+
+ <ItemGroup>
+  <OutputToDelete Include="$(TESTDIR)\**\*.exe" />
+  <OutputToDelete Include="$(TESTDIR)\**\*.exe.manifest" />
+  <OutputToDelete Include="$(TESTDIR)\**\*.obj" />
+  <OutputToDelete Include="$(TESTDIR)\**\*.c" Exclude="$(TESTDIR)\pg_regress_ecpg.c;$(TESTDIR)\expected\*.c" />
+ </ItemGroup>
+
+ <Target Name="all" Inputs="@(Pgc)" Outputs="%(RelativeDir)%(Filename).exe">
+  <!-- Set special parameters for some tests -->
+  <CreateProperty Value="-C INFORMIX" Condition="'%(Pgc.RelativeDir)'=='$(TESTDIR)\compat_informix\'">
+   <Output TaskParameter="Value" PropertyName="ECPGPARAM" />
+  </CreateProperty>
+  <CreateProperty Value="-C INFORMIX -r no_indicator" Condition="'%(Pgc.FileName)'=='rnull'">
+   <Output TaskParameter="Value" PropertyName="ECPGPARAM" />
+  </CreateProperty>
+
+  <!-- Run ECPG and the Visual C++ compiler on the files. Don't bother with dependency check between the steps -->
+  <Exec WorkingDirectory="%(Pgc.RelativeDir)" Command="$(OUTDIR)ecpg\ecpg -I ../../include --regression $(ECPGPARAM) -o %(Pgc.Filename).c %(Pgc.Filename).pgc" />
+  <Exec WorkingDirectorY="%(Pgc.RelativeDir)" Command="cl /nologo %(Pgc.FileName).c /TC /MD$(DEBUGLIB) /DENABLE_THREAD_SAFETY /DWIN32 /DWIN32_ONLY_COMPILER /I. /I..\..\include /I..\..\..\libpq /I..\..\..\..\include /link /defaultlib:$(OUTDIR)libecpg\libecpg.lib /defaultlib:$(OUTDIR)libecpg_compat\libecpg_compat.lib /defaultlib:$(OUTDIR)libpgtypes\libpgtypes.lib" />
+ </Target>
+
+ <!-- Clean up all output files -->
+ <Target Name="clean">
+  <Delete Files="@(OutputToDelete)" />
+ </Target>
+</Project>
index 879398996753353785ab7ba16622efc705020688..e3221b268f18476ade0e1595682408b5b818d277 100644 (file)
@@ -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 <check|installcheck> [schedule]"
+echo "Usage: vcregress <check|installcheck|plcheck|contribcheck|ecpgcheck> [schedule]"
 goto :eof