diff options
author | Magnus Hagander <magnus@hagander.net> | 2007-06-12 11:07:34 +0000 |
---|---|---|
committer | Magnus Hagander <magnus@hagander.net> | 2007-06-12 11:07:34 +0000 |
commit | 09922597c5f460ab02882716c371b2a5c47e742e (patch) | |
tree | 50c02e13bf202463570cf107fbcda70b42812bcc /src | |
parent | e514740e699d306b744849e43bcd2ef9728d464b (diff) | |
download | postgresql-09922597c5f460ab02882716c371b2a5c47e742e.tar.gz |
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
Diffstat (limited to 'src')
21 files changed, 817 insertions, 1023 deletions
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.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-thread.stdout b/src/interfaces/ecpg/test/expected/thread-thread_2.stdout index a9d787cc55..a9d787cc55 100644 --- a/src/interfaces/ecpg/test/expected/thread-thread-thread.stdout +++ b/src/interfaces/ecpg/test/expected/thread-thread_2.stdout 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-thread.stdout b/src/interfaces/ecpg/test/expected/thread-thread_implicit_2.stdout index a9d787cc55..a9d787cc55 100644 --- a/src/interfaces/ecpg/test/expected/thread-thread_implicit-thread.stdout +++ b/src/interfaces/ecpg/test/expected/thread-thread_implicit_2.stdout 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 <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 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 <ctype.h> #include <sys/stat.h> @@ -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)); @@ -189,6 +175,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. */ static void @@ -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; @@ -583,6 +611,35 @@ load_resultmap(void) } /* + * 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" */ static void @@ -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 @@ -944,43 +1001,6 @@ spawn_process(const char *cmdline) } /* - * 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 */ static long @@ -1062,6 +1082,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 */ static int @@ -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++; @@ -1535,6 +1640,63 @@ open_result_files(void) } 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) { printf(_("PostgreSQL regression test driver\n")); @@ -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 <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 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 @@ +<?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> 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 <check|installcheck> [schedule]" +echo "Usage: vcregress <check|installcheck|plcheck|contribcheck|ecpgcheck> [schedule]" goto :eof |