]> granicus.if.org Git - postgresql/blob - src/test/regress/pg_regress.sh
From Jason Tishler <jt@dothill.com>
[postgresql] / src / test / regress / pg_regress.sh
1 #! /bin/sh
2 # $Header: /cvsroot/pgsql/src/test/regress/Attic/pg_regress.sh,v 1.18 2001/01/19 23:43:36 petere Exp $
3
4 me=`basename $0`
5 : ${TMPDIR=/tmp}
6 TMPFILE=$TMPDIR/pg_regress.$$
7
8 help="\
9 PostgreSQL regression test driver
10
11 Usage: $me [options...] [extra tests...]
12
13 Options:
14   --debug                   turn on debug mode in programs that are run
15   --inputdir=DIR            take input files from DIR (default \`.')
16   --multibyte=ENCODING      use ENCODING as the multibyte encoding, and
17                             also run a test by the same name
18   --outputdir=DIR           place output files in DIR (default \`.')
19   --schedule=FILE           use test ordering schedule from FILE
20                             (may be used multiple times to concatenate)
21   --temp-install[=DIR]      create a temporary installation (in DIR)
22
23 Options for \`temp-install' mode:
24   --top-builddir=DIR        (relative) path to top level build directory
25
26 Options for using an existing installation:
27   --host=HOST               use postmaster running on HOST
28   --port=PORT               use postmaster running at PORT
29   --user=USER               connect as USER
30
31 The exit status is 0 if all tests passed, 1 if some tests failed, and 2
32 if the tests could not be run for some reason.
33
34 Report bugs to <pgsql-bugs@postgresql.org>."
35
36
37 message(){
38     _dashes='==============' # 14
39     _spaces='                                      ' # 38
40     _msg=`echo "$1$_spaces" | cut -c 1-38`
41     echo "$_dashes $_msg $_dashes"
42 }
43
44
45 # ----------
46 # Unset locale settings
47 # ----------
48
49 unset LC_COLLATE LC_CTYPE LC_MONETARY LC_MESSAGES LC_NUMERIC LC_TIME LC_ALL LANG LANGUAGE
50
51
52 # ----------
53 # Check for echo -n vs echo \c
54 # ----------
55
56 if echo '\c' | grep c >/dev/null 2>&1; then
57     ECHO_N='echo -n'
58     ECHO_C=''
59 else
60     ECHO_N='echo'
61     ECHO_C='\c'
62 fi
63
64
65 # ----------
66 # Initialize default settings
67 # ----------
68
69 : ${inputdir=.}
70 : ${outputdir=.}
71
72 libdir='@libdir@'
73 bindir='@bindir@'
74 datadir='@datadir@'
75 host_platform='@host_tuple@'
76 enable_shared='@enable_shared@'
77 GCC=@GCC@
78
79 if [ "$GCC" = yes ]; then
80     compiler=gcc
81 else
82     compiler=cc
83 fi
84
85 unset mode
86 unset schedule
87 unset debug
88 unset top_builddir
89 unset temp_install
90 unset multibyte
91
92 dbname=regression
93 hostname=localhost
94
95 : ${GMAKE='@GMAKE@'}
96
97
98 # ----------
99 # Parse command line options
100 # ----------
101
102 while [ "$#" -gt 0 ]
103 do
104     case $1 in
105         --help|-\?)
106                 echo "$help"
107                 exit 0;;
108         --version)
109                 echo "pg_regress (PostgreSQL @VERSION@)"
110                 exit 0;;
111         --debug)
112                 debug=yes
113                 shift;;
114         --inputdir=*)
115                 inputdir=`expr "x$1" : "x--inputdir=\(.*\)"`
116                 shift;;
117         --multibyte=*)
118                 multibyte=`expr "x$1" : "x--multibyte=\(.*\)"`
119                 shift;;
120         --temp-install)
121                 temp_install=./tmp_check
122                 shift;;
123         --temp-install=*)
124                 temp_install=`expr "x$1" : "x--temp-install=\(.*\)"`
125                 shift;;
126         --outputdir=*)
127                 outputdir=`expr "x$1" : "x--outputdir=\(.*\)"`
128                 shift;;
129         --schedule=*)
130                 foo=`expr "x$1" : "x--schedule=\(.*\)"`
131                 schedule="$schedule $foo"
132                 shift;;
133         --top-builddir=*)
134                 top_builddir=`expr "x$1" : "x--top-builddir=\(.*\)"`
135                 shift;;
136         --host=*)
137                 PGHOST=`expr "x$1" : "x--host=\(.*\)"`
138                 export PGHOST
139                 shift;;
140         --port=*)
141                 PGPORT=`expr "x$1" : "x--port=\(.*\)"`
142                 export PGPORT
143                 shift;;
144         --user=*)
145                 PGUSER=`expr "x$1" : "x--user=\(.*\)"`
146                 export PGUSER
147                 shift;;
148         -*)
149                 echo "$me: invalid argument $1" 1>&2
150                 exit 2;;
151         *)
152                 extra_tests="$extra_tests $1"
153                 shift;;
154     esac
155 done
156
157
158 # ----------
159 # When on QNX or BeOS, don't use Unix sockets.
160 # ----------
161
162 case $host_platform in
163     *-*-qnx* | *beos*)
164         unix_sockets=no;;
165     *)
166         unix_sockets=yes;;
167 esac
168
169
170 # ----------
171 # Set up diff to ignore horizontal white space differences.
172 # ----------
173
174 case $host_platform in
175     *-*-qnx*)
176         DIFFFLAGS=-b;;
177     *)
178         DIFFFLAGS=-w;;
179 esac
180
181
182 # ----------
183 # Set backend timezone and datestyle explicitly
184 #
185 # To pass the horology test in its current form, the postmaster must be
186 # started with PGDATESTYLE=ISO, while the frontend must be started with
187 # PGDATESTYLE=Postgres.  We set the postmaster values here and change
188 # to the frontend settings after the postmaster has been started.
189 # ----------
190
191 PGTZ='PST8PDT'; export PGTZ
192 PGDATESTYLE='ISO,US'; export PGDATESTYLE
193
194
195 # ----------
196 # Exit trap to remove temp file and shut down postmaster
197 # ----------
198
199 # Note:  There are some stupid shells (even among recent ones) that
200 # ignore the argument to exit (as in `exit 1') if there is an exit
201 # trap.  The trap (and thus the shell script) will then always exit
202 # with the result of the last shell command before the `exit'.  Hence
203 # we have to write `(exit x); exit' below this point.
204
205 trap '
206     savestatus=$?
207     if [ -n "$postmaster_pid" ]; then
208         kill -2 "$postmaster_pid"
209         wait "$postmaster_pid"
210         unset postmaster_pid
211     fi
212     rm -f "$TMPFILE" && exit $savestatus
213 ' 0
214
215 trap '
216     savestatus=$?
217     echo; echo "caught signal"
218     if [ -n "$postmaster_pid" ]; then
219         echo "signalling fast shutdown to postmaster with pid $postmaster_pid"
220         kill -2 "$postmaster_pid"
221         wait "$postmaster_pid"
222         unset postmaster_pid
223     fi
224     (exit $savestatus); exit
225 ' 1 2 13 15
226
227
228
229 # ----------
230 # Scan resultmap file to find which platform-specific expected files to use.
231 # The format of each line of the file is
232 #         testname/hostplatformpattern=substitutefile
233 # where the hostplatformpattern is evaluated per the rules of expr(1),
234 # namely, it is a standard regular expression with an implicit ^ at the start.
235 # What hostplatformpattern will be matched against is the config.guess output
236 # followed by either ':gcc' or ':cc' (independent of the actual name of the
237 # compiler executable).
238 #
239 # The tempfile hackery is needed because some shells will run the loop
240 # inside a subshell, whereupon shell variables set therein aren't seen
241 # outside the loop :-(
242 # ----------
243
244 cat /dev/null >$TMPFILE
245 if [ -f "$inputdir/resultmap" ]
246 then
247     while read LINE
248     do
249         HOSTPAT=`expr "$LINE" : '.*/\(.*\)='`
250         if [ `expr "$host_platform:$compiler" : "$HOSTPAT"` -ne 0 ]
251         then
252             # remove hostnamepattern from line so that there are no shell
253             # wildcards in SUBSTLIST; else later 'for' could expand them!
254             TESTNAME=`expr "$LINE" : '\(.*\)/'`
255             SUBST=`echo "$LINE" | sed 's/^.*=//'`
256             echo "$TESTNAME=$SUBST" >> $TMPFILE
257         fi
258     done <"$inputdir/resultmap"
259 fi
260 SUBSTLIST=`cat $TMPFILE`
261 rm -f $TMPFILE
262
263
264 LOGDIR=$outputdir/log
265
266 if [ x"$temp_install" != x"" ]
267 then
268     if echo x"$temp_install" | grep -v '^x/' >/dev/null 2>&1; then
269         temp_install="`pwd`/$temp_install"
270     fi
271
272     bindir=$temp_install/install/$bindir
273     libdir=$temp_install/install/$libdir
274     datadir=$temp_install/install/$datadir
275     PGDATA=$temp_install/data
276
277     if [ "$unix_sockets" = no ]; then
278         PGHOST=$hostname
279         export PGHOST
280     else
281         unset PGHOST
282     fi
283     PGPORT=65432
284     export PGPORT
285
286     # ----------
287     # Set up shared library paths, needed by psql and pg_encoding
288     # (if you run multibyte).  LD_LIBRARY_PATH covers many platforms,
289     # feel free to account for others as well.
290     # ----------
291
292     if [ -n "$LD_LIBRARY_PATH" ]; then
293         LD_LIBRARY_PATH="$libdir:$LD_LIBRARY_PATH"
294     else
295         LD_LIBRARY_PATH=$libdir
296     fi
297     export LD_LIBRARY_PATH
298
299     # ----------
300     # Windows needs shared libraries in PATH. (Only those linked into
301     # executables, not dlopen'ed ones)
302     # ----------
303     case $host_platform in *-*-cygwin*)
304         PATH=$libdir:$PATH
305         export PATH
306         ;;
307     esac
308
309     if [ -d "$temp_install" ]; then
310         message "removing existing temp installation"
311         rm -rf "$temp_install"
312     fi
313
314     message "creating temporary installation"
315     if [ ! -d "$LOGDIR" ]; then
316         mkdir -p "$LOGDIR" || { (exit 2); exit; }
317     fi
318     $GMAKE -C "$top_builddir" DESTDIR="$temp_install/install" install with_perl=no with_python=no >"$LOGDIR/install.log" 2>&1
319
320     if [ $? -ne 0 ]
321     then
322         echo
323         echo "$me: installation failed"
324         echo "Examine $LOGDIR/install.log for the reason."
325         echo
326         (exit 2); exit
327     fi
328
329
330     message "initializing database system"
331     [ "$debug" = yes ] && initdb_options='--debug'
332     "$bindir/initdb" -D "$PGDATA" -L "$datadir" --noclean $initdb_options >"$LOGDIR/initdb.log" 2>&1
333
334     if [ $? -ne 0 ]
335     then
336         echo
337         echo "$me: initdb failed"
338         echo "Examine $LOGDIR/initdb.log for the reason."
339         echo
340         (exit 2); exit
341     fi
342
343
344     # ----------
345     # Start postmaster
346     # ----------
347
348     message "starting postmaster"
349     [ "$debug" = yes ] && postmaster_options="$postmaster_options -d 5"
350     [ "$unix_sockets" = no ] && postmaster_options="$postmaster_options -i"
351     "$bindir/postmaster" -D "$PGDATA" -F $postmaster_options >"$LOGDIR/postmaster.log" 2>&1 &
352     postmaster_pid=$!
353
354     if kill -0 $postmaster_pid >/dev/null 2>&1
355     then
356         echo "running on port $PGPORT with pid $postmaster_pid"
357     else
358         echo
359         echo "$me: postmaster did not start"
360         echo "Examine $LOGDIR/postmaster.log for the reason."
361         echo
362         (exit 2); exit
363     fi
364
365     # give postmaster some time to pass WAL recovery
366     sleep 3
367
368 else # not temp-install
369
370     # If Unix sockets are not available, use the local host by default.
371     if [ "$unix_sockets" = no ]; then
372         PGHOST=$hostname
373         export PGHOST
374     fi
375
376     if [ -n "$PGPORT" ]; then
377         port_info="port $PGPORT"
378     else
379         port_info="default port"
380     fi
381
382     if [ -n "$PGHOST" ]; then
383         echo "(using postmaster on $PGHOST, $port_info)"
384     else
385         echo "(using postmaster on Unix socket, $port_info)"
386     fi
387     message "dropping database \"$dbname\""
388     "$bindir/dropdb" $psql_options "$dbname"
389     # errors can be ignored
390 fi
391
392
393 # ----------
394 # Set up SQL shell for the test.
395 # ----------
396
397 PSQL="$bindir/psql -a -q -X $psql_options"
398
399
400 # ----------
401 # Set frontend timezone and datestyle explicitly
402 # ----------
403
404 PGTZ='PST8PDT'; export PGTZ
405 PGDATESTYLE='Postgres,US'; export PGDATESTYLE
406
407
408 # ----------
409 # Set up multibyte environment
410 # ----------
411
412 if [ -n "$multibyte" ]; then
413     PGCLIENTENCODING=$multibyte
414     export PGCLIENTENCODING
415     encoding_opt="-E $multibyte"
416 else
417     unset PGCLIENTENCODING
418 fi
419
420
421 # ----------
422 # Create the regression database
423 # ----------
424
425 message "creating database \"$dbname\""
426 "$bindir/createdb" $encoding_opt $psql_options "$dbname"
427 if [ $? -ne 0 ]; then
428     echo "$me: createdb failed"
429     (exit 2); exit
430 fi
431
432
433 # ----------
434 # Install the PL/pgSQL language in it
435 # ----------
436
437 if [ "$enable_shared" = yes ]; then
438         message "installing PL/pgSQL"
439         "$bindir/createlang" -L "$libdir" $psql_options plpgsql $dbname
440         if [ $? -ne 0 ] && [ $? -ne 2 ]; then
441             echo "$me: createlang failed"
442             (exit 2); exit
443         fi
444 fi
445
446
447 # ----------
448 # Let's go
449 # ----------
450
451 message "running regression test queries"
452
453 if [ ! -d "$outputdir/results" ]; then
454     mkdir -p "$outputdir/results" || { (exit 2); exit; }
455 fi
456 result_summary_file=$outputdir/regression.out
457 diff_file=$outputdir/regression.diffs
458
459 cat /dev/null >"$result_summary_file"
460 cat /dev/null >"$diff_file"
461
462 lno=0
463 (
464     [ "$enable_shared" != yes ] && echo "ignore: plpgsql"
465     cat $schedule </dev/null
466     for x in $extra_tests; do
467         echo "test: $x"
468     done
469 ) | sed 's/[    ]*#.*//g' | \
470 while read line
471 do
472     # Count line numbers
473     lno=`expr $lno + 1`
474     [ -z "$line" ] && continue
475
476     set X $line; shift
477
478     if [ x"$1" = x"ignore:" ]; then
479         shift
480         ignore_list="$ignore_list $@"
481         continue
482     elif [ x"$1" != x"test:" ]; then
483         echo "$me:$schedule:$lno: syntax error"
484         (exit 2); exit
485     fi
486
487     shift
488
489     # ----------
490     # Start tests
491     # ----------
492
493     if [ $# -eq 1 ]; then
494         # Run a single test
495         formatted=`echo $1 | awk '{printf "%-20.20s", $1;}'`
496         $ECHO_N "test $formatted ... $ECHO_C"
497
498         $PSQL -d "$dbname" <"$inputdir/sql/$1.sql" >"$outputdir/results/$1.out" 2>&1
499     else
500         # Start a parallel group
501         $ECHO_N "parallel group ($# tests): $ECHO_C"
502         for name do
503             ( $PSQL -d $dbname <"$inputdir/sql/$name.sql" >"$outputdir/results/$name.out" 2>&1
504               $ECHO_N " $name$ECHO_C"
505             ) &
506         done
507         wait
508         echo
509     fi
510
511     # ----------
512     # Run diff
513     # (We do not want to run the diffs immediately after each test,
514     # because they would certainly get corrupted if run in parallel
515     # subshells.)
516     # ----------
517
518     for name do
519         if [ $# -ne 1 ]; then
520             formatted=`echo "$name" | awk '{printf "%-20.20s", $1;}'`
521             $ECHO_N "     $formatted ... $ECHO_C"
522         fi
523
524         # Check list extracted from resultmap to see if we should compare
525         # to a system-specific expected file.
526         # There shouldn't be multiple matches, but take the last if there are.
527
528         EXPECTED="$inputdir/expected/${name}.out"
529         for LINE in $SUBSTLIST
530         do
531             if [ `expr "$LINE" : "$name="` -ne 0 ]
532             then
533                 SUBST=`echo "$LINE" | sed 's/^.*=//'`
534                 EXPECTED="$inputdir/expected/${SUBST}.out"
535             fi
536         done
537
538         diff $DIFFFLAGS $EXPECTED $outputdir/results/${name}.out >/dev/null 2>&1
539         case $? in
540             0)
541                 echo "ok";;
542             1)
543                 ( diff $DIFFFLAGS -C3 $EXPECTED $outputdir/results/${name}.out
544                   echo
545                   echo "======================================================================"
546                   echo ) >> "$diff_file"
547                 if echo " $ignore_list " | grep " $name " >/dev/null 2>&1 ; then
548                     echo "failed (ignored)"
549                 else
550                     echo "FAILED"
551                 fi
552                 ;;
553             2)
554                 # desaster struck
555                 echo "trouble" 1>&2
556                 (exit 2); exit;;
557         esac
558     done
559 done | tee "$result_summary_file" 2>&1
560
561 [ $? -ne 0 ] && exit
562
563 # ----------
564 # Server shutdown
565 # ----------
566
567 if [ -n "$postmaster_pid" ]; then
568     message "shutting down postmaster"
569     kill -15 "$postmaster_pid"
570     unset postmaster_pid
571 fi
572
573 rm -f "$TMPFILE"
574
575
576 # ----------
577 # Evaluation
578 # ----------
579
580 count_total=`cat "$result_summary_file" | grep '\.\.\.' | wc -l | sed 's/ //g'`
581 count_ok=`cat "$result_summary_file" | grep '\.\.\. ok' | wc -l | sed 's/ //g'`
582 count_failed=`cat "$result_summary_file" | grep '\.\.\. FAILED' | wc -l | sed 's/ //g'`
583 count_ignored=`cat "$result_summary_file" | grep '\.\.\. failed (ignored)' | wc -l | sed 's/ //g'`
584
585 echo
586 if [ $count_total -eq $count_ok ]; then
587     msg="All $count_total tests passed."
588     result=0
589 elif [ $count_failed -eq 0 ]; then
590     msg="$count_ok of $count_total tests passed, $count_ignored failed test(s) ignored."
591     result=0
592 elif [ $count_ignored -eq 0 ]; then
593     msg="$count_failed of $count_total tests failed."
594     result=1
595 else
596     msg="$count_failed of $count_total tests failed, $count_ignored failed test(s) ignored."
597     result=1
598 fi
599
600 dashes=`echo " $msg " | sed 's/./=/g'`
601 echo "$dashes"
602 echo " $msg "
603 echo "$dashes"
604 echo
605
606 if [ -s "$diff_file" ]; then
607     echo "The differences that caused some tests to fail can be viewed in the"
608     echo "file \`$diff_file'.  A copy of the test summary that you see"
609     echo "above is saved in the file \`$result_summary_file'."
610     echo
611 else
612     rm -f "$diff_file" "$result_summary_file"
613 fi
614
615
616 (exit $result); exit