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