]> granicus.if.org Git - postgresql/blobdiff - src/test/regress/pg_regress.sh
copydir() and rmtree() need to use lstat, not stat, to behave as expected
[postgresql] / src / test / regress / pg_regress.sh
index 01cc436afe877e78401e510038d29af6dc69c014..f56b737d0bcb5dd74f787e6ad413a0d82c745007 100644 (file)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# $Header: /cvsroot/pgsql/src/test/regress/Attic/pg_regress.sh,v 1.8 2000/10/22 22:15:09 petere Exp $
+# $PostgreSQL: pgsql/src/test/regress/pg_regress.sh,v 1.65 2006/07/18 00:32:41 tgl Exp $
 
 me=`basename $0`
 : ${TMPDIR=/tmp}
@@ -11,17 +11,24 @@ 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 \`.')
   --schedule=FILE           use test ordering schedule from FILE
                             (may be used multiple times to concatenate)
   --temp-install[=DIR]      create a temporary installation (in DIR)
+  --no-locale               use C locale
 
 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
 
 Options for using an existing installation:
   --host=HOST               use postmaster running on HOST
@@ -48,6 +55,14 @@ message(){
 
 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
+
 
 # ----------
 # Check for echo -n vs echo \c
@@ -73,19 +88,28 @@ libdir='@libdir@'
 bindir='@bindir@'
 datadir='@datadir@'
 host_platform='@host_tuple@'
+enable_shared='@enable_shared@'
+GCC=@GCC@
+
+if [ "$GCC" = yes ]; then
+    compiler=gcc
+else
+    compiler=cc
+fi
 
 unset mode
 unset schedule
 unset debug
+unset nolocale
 unset top_builddir
 unset temp_install
 unset multibyte
 
-export PGHOST
-export PGPORT
-
 dbname=regression
 hostname=localhost
+maxconnections=0
+temp_port=65432
+load_langs=""
 
 : ${GMAKE='@GMAKE@'}
 
@@ -103,21 +127,35 @@ do
         --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;;
+        --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;;
@@ -128,11 +166,17 @@ do
         --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=\(.*\)"`
@@ -147,13 +191,32 @@ do
     esac
 done
 
-
 # ----------
-# When on Windows, QNX or BeOS, don't use Unix sockets.
+# warn of Cygwin likely failure if maxconnections = 0
+# and we are running parallel tests
 # ----------
 
 case $host_platform in
-    *-*-cygwin* | *-*-qnx* | *beos*)
+    *-*-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
+
+
+# ----------
+# On some platforms we can't use Unix sockets.
+# ----------
+case $host_platform in
+    *-*-cygwin* | *-*-mingw32*)
         unix_sockets=no;;
     *)
         unix_sockets=yes;;
@@ -165,7 +228,7 @@ esac
 # ----------
 
 case $host_platform in
-    *-*-qnx*)
+    *-*-sco3.2v5*)
         DIFFFLAGS=-b;;
     *)
         DIFFFLAGS=-w;;
@@ -182,7 +245,7 @@ esac
 # ----------
 
 PGTZ='PST8PDT'; export PGTZ
-PGDATESTYLE='ISO,US'; export PGDATESTYLE
+PGDATESTYLE='ISO, MDY'; export PGDATESTYLE
 
 
 # ----------
@@ -195,18 +258,20 @@ PGDATESTYLE='ISO,US'; export PGDATESTYLE
 # with the result of the last shell command before the `exit'.  Hence
 # we have to write `(exit x); exit' below this point.
 
-trap '
-    savestatus=$?
+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
-' 0
+}
+
+trap 'exit_trap $?' 0
 
-trap '
-    savestatus=$?
+sig_trap() {
+    savestatus=$1
     echo; echo "caught signal"
     if [ -n "$postmaster_pid" ]; then
         echo "signalling fast shutdown to postmaster with pid $postmaster_pid"
@@ -215,16 +280,21 @@ trap '
         unset postmaster_pid
     fi
     (exit $savestatus); exit
-' 1 2 13 15
+}
+
+trap 'sig_trap $?' 1 2 13 15
 
 
 
 # ----------
 # Scan resultmap file to find which platform-specific expected files to use.
 # The format of each line of the file is
-#               testname/hostplatformpattern=substitutefile
+#         testname/hostplatformpattern=substitutefile
 # where the hostplatformpattern is evaluated per the rules of expr(1),
 # namely, it is a standard regular expression with an implicit ^ at the start.
+# What hostplatformpattern will be matched against is the config.guess output
+# followed by either ':gcc' or ':cc' (independent of the actual name of the
+# compiler executable).
 #
 # The tempfile hackery is needed because some shells will run the loop
 # inside a subshell, whereupon shell variables set therein aren't seen
@@ -232,18 +302,21 @@ trap '
 # ----------
 
 cat /dev/null >$TMPFILE
-while read LINE
-do
-    HOSTPAT=`expr "$LINE" : '.*/\(.*\)='`
-    if [ `expr "$host_platform" : "$HOSTPAT"` -ne 0 ]
-    then
-        # remove hostnamepattern from line so that there are no shell
-        # wildcards in SUBSTLIST; else later 'for' could expand them!
-        TESTNAME=`expr "$LINE" : '\(.*\)/'`
-        SUBST=`echo "$LINE" | sed 's/^.*=//'`
-        echo "$TESTNAME=$SUBST" >> $TMPFILE
-    fi
-done <"$inputdir/resultmap"
+if [ -f "$inputdir/resultmap" ]
+then
+    while read LINE
+    do
+        HOSTPAT=`expr "$LINE" : '.*/\(.*\)='`
+        if [ `expr "$host_platform:$compiler" : "$HOSTPAT"` -ne 0 ]
+        then
+            # remove hostnamepattern from line so that there are no shell
+            # wildcards in SUBSTLIST; else later 'for' could expand them!
+            TESTNAME=`expr "$LINE" : '\(.*\)/'`
+            SUBST=`echo "$LINE" | sed 's/^.*=//'`
+            echo "$TESTNAME=$SUBST" >> $TMPFILE
+        fi
+    done <"$inputdir/resultmap"
+fi
 SUBSTLIST=`cat $TMPFILE`
 rm -f $TMPFILE
 
@@ -256,21 +329,37 @@ then
         temp_install="`pwd`/$temp_install"
     fi
 
-    bindir=$temp_install/$bindir
-    libdir=$temp_install/$libdir
-    datadir=$temp_install/$datadir
+    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
-    PGPORT=65432
+
+    # 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,
-    # feel free to account for others as well.
+    # (if you run multibyte).  LD_LIBRARY_PATH covers many platforms.
+    # DYLD_LIBRARY_PATH works on Darwin, and maybe other Mach-based systems.
+    # Feel free to account for others as well.
     # ----------
 
     if [ -n "$LD_LIBRARY_PATH" ]; then
@@ -280,6 +369,23 @@ then
     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
+
+    # ----------
+    # 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"
@@ -290,7 +396,7 @@ then
     if [ ! -d "$LOGDIR" ]; then
         mkdir -p "$LOGDIR" || { (exit 2); exit; }
     fi
-    $GMAKE -C "$top_builddir" DESTDIR="$temp_install" install >"$LOGDIR/install.log" 2>&1
+    $GMAKE -C "$top_builddir" DESTDIR="$temp_install/install" install with_perl=no with_python=no >"$LOGDIR/install.log" 2>&1
 
     if [ $? -ne 0 ]
     then
@@ -301,9 +407,9 @@ then
         (exit 2); exit
     fi
 
-
     message "initializing database system"
-    [ "$debug" = yes ] && initdb_options='--debug'
+    [ "$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 ]
@@ -322,10 +428,35 @@ then
 
     message "starting postmaster"
     [ "$debug" = yes ] && postmaster_options="$postmaster_options -d 5"
-    [ "$unix_sockets" = no ] && postmaster_options="$postmaster_options -i"
+    if [ "$unix_sockets" = no ]; 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"
@@ -337,13 +468,18 @@ then
         (exit 2); exit
     fi
 
-    # give postmaster some time to pass WAL recovery
-    sleep 3
-
 else # not temp-install
 
-    # If Unix sockets are not available, use the local host by default.
-    [ "$unix_sockets" = no ] && ${PGHOST=$hostname}
+    # ----------
+    # 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"
@@ -354,10 +490,15 @@ else # not temp-install
     if [ -n "$PGHOST" ]; then
         echo "(using postmaster on $PGHOST, $port_info)"
     else
-        echo "(using postmaster on Unix socket, $port_info)"
+        if [ "$unix_sockets" = no ]; then
+            echo "(using postmaster on localhost, $port_info)"
+        else
+            echo "(using postmaster on Unix socket, $port_info)"
+        fi
     fi
+
     message "dropping database \"$dbname\""
-    "$bindir/dropdb" $psql_options "$dbname" >/dev/null 2>&1
+    "$bindir/dropdb" $psql_options "$dbname"
     # errors can be ignored
 fi
 
@@ -366,7 +507,7 @@ fi
 # Set up SQL shell for the test.
 # ----------
 
-PSQL="$bindir/psql -a -q -X $psql_options"
+psql_test_options="-a -q -X $psql_options"
 
 
 # ----------
@@ -374,7 +515,7 @@ PSQL="$bindir/psql -a -q -X $psql_options"
 # ----------
 
 PGTZ='PST8PDT'; export PGTZ
-PGDATESTYLE='Postgres,US'; export PGDATESTYLE
+PGDATESTYLE='Postgres, MDY'; export PGDATESTYLE
 
 
 # ----------
@@ -392,31 +533,44 @@ fi
 
 # ----------
 # Create the regression database
+# We use template0 so that any installation-local cruft in template1
+# will not mess up the tests.
 # ----------
 
 message "creating database \"$dbname\""
-"$bindir/createdb" $encoding_opt $psql_options "$dbname"
+"$bindir/createdb" $encoding_opt $psql_options --template template0 "$dbname"
 if [ $? -ne 0 ]; then
     echo "$me: createdb failed"
     (exit 2); exit
 fi
 
+"$bindir/psql" -q -X $psql_options -c "\
+alter database \"$dbname\" set lc_messages to 'C';
+alter database \"$dbname\" set lc_monetary to 'C';
+alter database \"$dbname\" set lc_numeric to 'C';
+alter database \"$dbname\" set lc_time to 'C';" "$dbname"
+if [ $? -ne 0 ]; then
+    echo "$me: could not set database default locales"
+    (exit 2); exit
+fi
+
 
 # ----------
-# Install the PL/pgSQL language in it
+# Install any requested PL languages
 # ----------
 
-case $host_platform in
-    *-*-qnx*) : ;;
-    *)
-        message "installing PL/pgSQL"
-        "$bindir/createlang" -L "$libdir" $psql_options plpgsql $dbname
-        if [ $? -ne 0 ] && [ $? -ne 2 ]; then
-            echo "$me: createlang failed"
-            (exit 2); exit
+if [ "$enable_shared" = yes ]; then
+    for lang in xyzzy $load_langs ; do    
+        if [ "$lang" != "xyzzy" ]; then
+            message "installing $lang"
+            "$bindir/createlang" $psql_options $lang $dbname
+            if [ $? -ne 0 ] && [ $? -ne 2 ]; then
+                echo "$me: createlang $lang failed"
+                (exit 2); exit
+            fi
         fi
-        ;;
-esac
+    done
+fi
 
 
 # ----------
@@ -436,7 +590,8 @@ cat /dev/null >"$diff_file"
 
 lno=0
 (
-    cat $schedule
+    [ "$enable_shared" != yes ] && echo "ignore: plpgsql"
+    cat $schedule </dev/null
     for x in $extra_tests; do
         echo "test: $x"
     done
@@ -468,15 +623,24 @@ do
         # Run a single test
         formatted=`echo $1 | awk '{printf "%-20.20s", $1;}'`
         $ECHO_N "test $formatted ... $ECHO_C"
-
-        $PSQL -d "$dbname" <"$inputdir/sql/$1.sql" >"$outputdir/results/$1.out" 2>&1
+        ( "$bindir/psql" $psql_test_options -d "$dbname" <"$inputdir/sql/$1.sql" >"$outputdir/results/$1.out" 2>&1 )&
+        wait
     else
         # Start a parallel group
-        $ECHO_N "parallel group ($# tests): " $ECHO_C
+        $ECHO_N "parallel group ($# tests): $ECHO_C"
+        if [ $maxconnections -gt 0 ] ; then
+            connnum=0
+            test $# -gt $maxconnections && $ECHO_N "(in groups of $maxconnections) $ECHO_C"
+        fi
         for name do
-            ( $PSQL -d $dbname <"$inputdir/sql/$name.sql" >"$outputdir/results/$name.out" 2>&1
+            ( 
+              "$bindir/psql" $psql_test_options -d "$dbname" <"$inputdir/sql/$name.sql" >"$outputdir/results/$name.out" 2>&1
               $ECHO_N " $name$ECHO_C"
             ) &
+            if [ $maxconnections -gt 0 ] ; then
+                connnum=`expr \( $connnum + 1 \) % $maxconnections`
+                test $connnum -eq 0 && wait
+            fi
         done
         wait
         echo
@@ -499,22 +663,44 @@ do
         # to a system-specific expected file.
         # There shouldn't be multiple matches, but take the last if there are.
 
-        EXPECTED="$inputdir/expected/${name}.out"
+        EXPECTED="$inputdir/expected/${name}"
         for LINE in $SUBSTLIST
         do
             if [ `expr "$LINE" : "$name="` -ne 0 ]
             then
                 SUBST=`echo "$LINE" | sed 's/^.*=//'`
-                EXPECTED="$inputdir/expected/${SUBST}.out"
+                EXPECTED="$inputdir/expected/${SUBST}"
             fi
         done
 
-        diff $DIFFFLAGS $EXPECTED $outputdir/results/${name}.out >/dev/null 2>&1
-        case $? in
+        # If there are multiple equally valid result files, loop to get the right one.
+        # If none match, diff against the closest one.
+
+        bestfile=
+        bestdiff=
+        result=2
+        for thisfile in $EXPECTED.out ${EXPECTED}_[0-9].out; do
+            [ ! -r "$thisfile" ] && continue
+            diff $DIFFFLAGS $thisfile $outputdir/results/${name}.out >/dev/null 2>&1
+            result=$?
+            case $result in
+                0) break;;
+                1) thisdiff=`diff $DIFFFLAGS $thisfile $outputdir/results/${name}.out | wc -l`
+                   if [ -z "$bestdiff" ] || [ "$thisdiff" -lt "$bestdiff" ]; then
+                       bestdiff=$thisdiff; bestfile=$thisfile
+                   fi
+                   continue;;
+                2) break;;
+            esac
+        done
+
+        # Now print the result.
+
+        case $result in
             0)
                 echo "ok";;
             1)
-                ( diff $DIFFFLAGS -C3 $EXPECTED $outputdir/results/${name}.out
+                ( diff $DIFFFLAGS -C3 $bestfile $outputdir/results/${name}.out
                   echo
                   echo "======================================================================"
                   echo ) >> "$diff_file"
@@ -525,7 +711,7 @@ do
                 fi
                 ;;
             2)
-                # desaster struck
+                # disaster struck
                 echo "trouble" 1>&2
                 (exit 2); exit;;
         esac
@@ -540,7 +726,8 @@ done | tee "$result_summary_file" 2>&1
 
 if [ -n "$postmaster_pid" ]; then
     message "shutting down postmaster"
-    kill -15 "$postmaster_pid"
+    "$bindir/pg_ctl" -s -D "$PGDATA" stop
+    wait "$postmaster_pid"
     unset postmaster_pid
 fi
 
@@ -567,7 +754,7 @@ elif [ $count_ignored -eq 0 ]; then
     msg="$count_failed of $count_total tests failed."
     result=1
 else
-    msg="$count_failed of $count_total tests failed, $count_ignored failed test(s) ignored."
+    msg="`expr $count_failed + $count_ignored` of $count_total tests failed, $count_ignored of these failures ignored."
     result=1
 fi