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