re PR go/68980 (ps -o cmd in gotest isn't portable)
[platform/upstream/gcc.git] / libgo / testsuite / gotest
1 #!/bin/sh
2 # Copyright 2009 The Go Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style
4 # license that can be found in the LICENSE file.
5
6 # Using all the *_test.go files in the current directory, write out a file
7 # _testmain.go that runs all its tests. Compile everything and run the
8 # tests.
9 # If files are named on the command line, use them instead of *_test.go.
10
11 # Makes egrep,grep work better in general if we put them
12 # in ordinary C mode instead of what the current language is.
13 unset LANG
14 export LC_ALL=C
15 export LC_CTYPE=C
16
17 GC=${GC:-gccgo}
18 GL=${GL:-${GC-gccgo}}
19 GOLIBS=${GOLIBS:-}
20 export GC GL GOLIBS
21
22 NM=${NM:-nm}
23
24 # srcdir is where the source files are found.  basedir is where the
25 # source file paths are relative to.
26 # gofiles are the test files.  pkgfiles are the source files.
27 srcdir=.
28 basedir=.
29 goarch=""
30 gofiles=""
31 goos=""
32 pkgfiles=""
33 loop=true
34 keep=false
35 pkgpath=
36 prefix=
37 dejagnu=no
38 timeout=240
39 testname=""
40 bench=""
41 trace=false
42 while $loop; do
43         case "x$1" in
44         x--srcdir)
45                 srcdir=$2
46                 shift
47                 shift
48                 ;;
49         x--srcdir=*)
50                 srcdir=`echo $1 | sed -e 's/^--srcdir=//'`
51                 shift
52                 ;;
53         x--basedir)
54                 basedir=$2
55                 shift
56                 shift
57                 ;;
58         x--basedir=*)
59                 basedir=`echo $1 | sed -e 's/^--basedir=//'`
60                 shift
61                 ;;
62         x--goarch)
63                 goarch=$2
64                 shift
65                 shift
66                 ;;
67         x--goarch=*)
68                 goarch=`echo $1 | sed -e 's/^--goarch=//'`
69                 shift
70                 ;;
71         x--goos)
72                 goos=$2
73                 shift
74                 shift
75                 ;;
76         x--goos=*)
77                 goos=`echo $1 | sed -e 's/^--goos=//'`
78                 shift
79                 ;;
80         x--pkgpath)
81                 pkgpath=$2
82                 shift
83                 shift
84                 ;;
85         x--pkgpath=*)
86                 pkgpath=`echo $1 | sed -e 's/^--pkgpath=//'`
87                 shift
88                 ;;
89         x--prefix)
90                 prefix=$2
91                 shift
92                 shift
93                 ;;
94         x--prefix=*)
95                 prefix=`echo $1 | sed -e 's/^--prefix=//'`
96                 shift
97                 ;;
98         x--keep)
99                 keep=true
100                 shift
101                 ;;
102         x--pkgfiles)
103                 pkgfiles=$2
104                 shift
105                 shift
106                 ;;
107         x--pkgfiles=*)
108                 pkgfiles=`echo $1 | sed -e 's/^--pkgfiles=//'`
109                 shift
110                 ;;
111         x--dejagnu)
112                 dejagnu=$2
113                 shift
114                 shift
115                 ;;
116         x--dejagnu=*)
117                 dejagnu=`echo $1 | sed -e 's/^--dejagnu=//'`
118                 shift
119                 ;;
120         x--timeout)
121                 timeout=$2
122                 shift
123                 shift
124                 ;;
125         x--timeout=*)
126                 timeout=`echo $1 | sed -e 's/^--timeout=//'`
127                 shift
128                 ;;
129         x--testname)
130                 testname=$2
131                 shift
132                 shift
133                 ;;
134         x--testname=*)
135                 testname=`echo $1 | sed -e 's/^--testname=//'`
136                 shift
137                 ;;
138         x--bench)
139                 bench=$2
140                 shift
141                 shift
142                 ;;
143         x--bench=*)
144                 bench=`echo $1 | sed -e 's/^--bench=//'`
145                 shift
146                 ;;
147         x--trace)
148                 trace=true
149                 shift
150                 ;;
151         x-*)
152                 loop=false
153                 ;;
154         x)
155                 loop=false
156                 ;;
157         *)
158                 gofiles="$gofiles $1"
159                 shift
160                 ;;
161         esac
162 done
163
164 DIR=gotest$$
165 rm -rf $DIR
166 mkdir $DIR
167
168 cd $DIR
169 mkdir test
170 cd test
171
172 if test $keep = false; then
173   trap "cd ../..; rm -rf $DIR" 0 1 2 3 14 15
174 else
175   trap "cd ../..; echo Keeping $DIR" 0 1 2 3 14 15
176 fi
177
178 case "$srcdir" in
179         /*)
180                 ;;
181         *)
182                 srcdir="../../$srcdir"
183                 ;;
184 esac
185
186 SRCDIR=$srcdir
187 export SRCDIR
188
189 case "$basedir" in
190         /*)
191                 ;;
192         *)
193                 basedir="../../$basedir"
194                 ;;
195 esac
196
197 # Link all the files/directories in srcdir into our working directory,
198 # so that the tests do not have to refer to srcdir to find test data.
199 ln -s $srcdir/* .
200
201 # Some tests refer to a ../testdata directory.
202 if test -e $srcdir/../testdata; then
203   rm -f ../testdata
204   abssrcdir=`cd $srcdir && pwd`
205   ln -s $abssrcdir/../testdata ../testdata
206 fi
207
208 # Copy the .go files because io/utils_test.go expects a regular file.
209 case "x$gofiles" in
210 x)
211         case "x$pkgfiles" in
212         x)
213                 for f in `cd $srcdir; ls *.go`; do
214                     rm -f $f;
215                     cp $srcdir/$f .
216                 done
217                 ;;
218         *)
219                 for f in $pkgfiles; do
220                     if test -f $basedir/$f; then
221                         b=`basename $f`
222                         rm -f $b
223                         cp $basedir/$f $b
224                     elif test -f ../../$f; then
225                         b=`basename $f`
226                         rm -f $b
227                         cp ../../$f $b
228                     else
229                         echo "file $f not found" 1>&2
230                         exit 1
231                     fi
232                 done
233                 for f in `cd $srcdir; ls *_test.go`; do
234                     rm -f $f
235                     cp $srcdir/$f .
236                 done
237                 ;;
238         esac
239         ;;
240 *)
241         for f in $gofiles; do
242             b=`basename $f`
243             rm -f $b
244             cp $basedir/$f $b
245         done
246         case "x$pkgfiles" in
247         x)
248                 for f in `cd $srcdir; ls *.go | grep -v *_test.go`; do
249                     rm -f $f
250                     cp $srcdir/$f .
251                 done
252                 ;;
253         *)
254                 for f in $pkgfiles; do
255                     if test -f $basedir/$f; then
256                         b=`basename $f`
257                         rm -f $b
258                         cp $basedir/$f $b
259                     elif test -f ../../$f; then
260                         b=`basename $f`
261                         rm -f $b
262                         cp ../../$f $b
263                     else
264                         echo "file $f not found" 1>&2
265                         exit 1
266                     fi
267                 done
268                 ;;
269         esac
270         ;;
271 esac
272
273 # Some tests expect the _obj directory created by the gc Makefiles.
274 mkdir _obj
275
276 # Some tests expect the _test directory created by the gc Makefiles.
277 mkdir _test
278
279 case "x$gofiles" in
280 x)
281         for f in `ls *_test.go`; do
282             tag1=`echo $f | sed -e 's/^.*_\([^_]*\)_test.go$/\1/'`
283             tag2=`echo $f | sed -e 's/^.*_\([^_]*\)_[^_]*_test.go$/\1/'`
284             if test x$tag1 = x$f; then
285                 tag1=
286             fi
287             if test x$tag2 = x$f; then
288                 tag2=
289             fi
290
291             case "$tag1" in
292             "") ;;
293             $goarch) ;;
294             $goos) ;;
295             android | darwin | dragonfly | freebsd | linux | nacl | netbsd | openbsd | plan9 | solaris | windows)
296                 tag1=nonmatchingtag
297                 ;;
298             386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | m68k | ppc64 | ppc64le | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | mipso32 | mipsn32 | mipsn64 | mipso64 | ppc | s390 | s390x | sparc | sparc64)
299                 tag1=nonmatchingtag
300                 ;;
301             esac
302
303             case "$tag2" in
304             "") ;;
305             $goarch) ;;
306             $goos) ;;
307             android | darwin | dragonfly | freebsd | linux | nacl | netbsd | openbsd | plan9 | solaris | windows)
308                 tag2=nonmatchingtag
309                 ;;
310             386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | m68k | ppc64 | ppc64le | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | mipso32 | mipsn32 | mipsn64 | mipso64 | ppc | s390 | s390x | sparc | sparc64)
311                 tag2=nonmatchingtag
312                 ;;
313             esac
314
315             if test x$tag1 != xnonmatchingtag -a x$tag2 != xnonmatchingtag; then
316                 taglines=`sed '/^package /q' < $f | fgrep '// +build '`
317                 if test "$taglines" = ""; then
318                     omatch=true
319                 else
320                     omatch=false
321                 fi
322                 for tags in $taglines; do
323                     match=false
324                     for tag in $tags; do
325                         reverse=false
326                         case $tag in
327                         "!"*)
328                             reverse=true
329                             tag=`echo $tag | sed -e 's/^!//'`
330                             ;;
331                         esac
332
333                         case $tag in
334                         "//" | "+build")
335                             ;;
336                         $goos | $goarch | cgo)
337                             match=true
338                             ;;
339                         *,*)
340                             match=true
341                             for ctag in `echo $tag | sed -e 's/,/ /g'`; do
342                                 case $ctag in
343                                 $goos | $goarch | cgo)
344                                     ;;
345                                 *)
346                                     match=false
347                                     ;;
348                                 esac
349                             done
350                             ;;
351                         esac
352
353                         if test "$reverse" = true; then
354                             if test "$match" = true; then
355                                 match=false
356                             else
357                                 match=true
358                             fi
359                         fi
360                     done
361                     if test "$match" = "true"; then
362                         omatch=true
363                     fi
364                 done
365
366                 if test "$omatch" = "true"; then
367                     gofiles="$gofiles $f"
368                 fi
369             fi
370         done
371         ;;
372 *)
373         xgofiles=$gofiles
374         gofiles=
375         for f in $xgofiles; do
376             gofiles="$gofiles `basename $f`"
377         done
378 esac
379
380 case "x$gofiles" in
381 x)
382         echo 'no test files found' 1>&2
383         exit 1
384         ;;
385 esac
386
387 # Run any commands given in sources, like
388 #   // gotest: $GC foo.go
389 # to build any test-only dependencies.
390 holdGC="$GC"
391 GC="$GC -g -c -I ."
392 sed -n 's/^\/\/ gotest: //p' $gofiles | sh
393 GC="$holdGC"
394
395 case "x$pkgfiles" in
396 x)
397         pkgbasefiles=`ls *.go | grep -v _test.go 2>/dev/null`
398         ;;
399 *)
400         for f in $pkgfiles; do
401             pkgbasefiles="$pkgbasefiles `basename $f`"
402         done
403         ;;
404 esac
405
406 case "x$pkgfiles" in
407 x)
408         echo 'no source files found' 1>&2
409         exit 1
410         ;;
411 esac
412
413 # Split $gofiles into external gofiles (those in *_test packages)
414 # and internal ones (those in the main package).
415 xgofiles=
416 for f in $gofiles; do
417     package=`grep '^package[    ]' $f | sed 1q`
418     case "$package" in
419     *_test)
420         xgofiles="$xgofiles $f"
421         ;;
422     *)
423         ngofiles="$ngofiles $f"
424         ;;
425     esac
426 done
427 gofiles=$ngofiles
428
429 # External $O file
430 xofile=""
431 havex=false
432 if [ "x$xgofiles" != "x" ]; then
433         xofile="_xtest_.o"
434         havex=true
435 fi
436
437 testmain=
438 if $havex && fgrep 'func TestMain(' $xgofiles >/dev/null 2>&1; then
439   package=`grep '^package[      ]' $xgofiles | sed 1q | sed -e 's/.* //'`
440   testmain="${package}.TestMain"
441 elif test -n "$gofiles" && fgrep 'func TestMain(' $gofiles >/dev/null 2>&1; then
442   package=`grep '^package[      ]' $gofiles | sed 1q | sed -e 's/.* //'`
443   testmain="${package}.TestMain"
444 fi
445
446 set -e
447
448 package=`echo ${srcdir} | sed -e 's|^.*libgo/go/||'`
449
450 pkgpatharg=
451 xpkgpatharg=
452 prefixarg=
453 if test -n "$pkgpath"; then
454         pkgpatharg="-fgo-pkgpath=$pkgpath"
455         xpkgpatharg="-fgo-pkgpath=${pkgpath}_test"
456 elif test -n "$prefix"; then
457         prefixarg="-fgo-prefix=$prefix"
458 fi
459
460 if test "$trace" = "true"; then
461   echo $GC -g $pkgpatharg $prefixarg -c -I . -fno-toplevel-reorder -o _gotest_.o $gofiles $pkgbasefiles
462 fi
463 $GC -g $pkgpatharg $prefixarg -c -I . -fno-toplevel-reorder -o _gotest_.o $gofiles $pkgbasefiles
464
465 if $havex; then
466         mkdir -p `dirname $package`
467         cp _gotest_.o `dirname $package`/lib`basename $package`.a
468         if test "$trace" = "true"; then
469             echo $GC -g $xpkgpatharg -c -I . -fno-toplevel-reorder -o $xofile $xgofiles
470         fi
471         $GC -g $xpkgpatharg -c -I . -fno-toplevel-reorder -o $xofile $xgofiles
472 fi
473
474 # They all compile; now generate the code to call them.
475
476 testname() {
477         # Remove the package from the name used with the -test option.
478         echo $1 | sed 's/^.*\.//'
479 }
480
481 localname() {
482         # The package main has been renamed to __main__ when imported.
483         # Adjust its uses.
484         echo $1 | sed 's/^main\./__main__./'
485 }
486
487 {
488         text="T"
489         case "$goarch" in
490         ppc64*) text="[TD]" ;;
491         esac
492
493         symtogo='sed -e s/_test/XXXtest/ -e s/.*_\([^_]*\.\)/\1/ -e s/XXXtest/_test/'
494
495         # test functions are named TestFoo
496         # the grep -v eliminates methods and other special names
497         # that have multiple dots.
498         pattern='Test([^a-z].*)?'
499         # The -p option tells GNU nm not to sort.
500         # The -v option tells Solaris nm to sort by value.
501         tests=$($NM -p -v _gotest_.o $xofile | egrep " $text .*\."$pattern'$' | grep -v '\..*\..*\.' | fgrep -v '$' | fgrep -v ' __go_' | sed 's/.* //' | $symtogo)
502         if [ "x$tests" = x ]; then
503                 echo 'gotest: warning: no tests matching '$pattern in _gotest_.o $xofile 1>&2
504                 exit 2
505         fi
506         # benchmarks are named BenchmarkFoo.
507         pattern='Benchmark([^a-z].*)?'
508         benchmarks=$($NM -p -v _gotest_.o $xofile | egrep " $text .*\."$pattern'$' | grep -v '\..*\..*\.' | fgrep -v '$' | fgrep -v ' __go_' | sed 's/.* //' | $symtogo)
509
510         # examples are named ExampleFoo
511         pattern='Example([^a-z].*)?'
512         examples=$($NM -p -v _gotest_.o $xofile | egrep " $text .*\."$pattern'$' | grep -v '\..*\..*\.' | fgrep -v '$' | fgrep -v ' __go_' | sed 's/.* //' | $symtogo)
513
514         # package spec
515         echo 'package main'
516         echo
517         # imports
518         if echo "$tests" | egrep -v '_test\.' >/dev/null; then
519                 echo 'import "./_gotest_"'
520         fi
521         if $havex; then
522                 echo 'import "./_xtest_"'
523         fi
524         echo 'import "testing"'
525         echo 'import __regexp__ "regexp"' # rename in case tested package is called regexp
526         if ! test -n "$testmain"; then
527                 echo 'import __os__ "os"'
528         fi
529         # test array
530         echo
531         echo 'var tests = []testing.InternalTest {'
532         for i in $tests
533         do
534                 n=$(testname $i)
535                 if test "$n" != "TestMain"; then
536                         j=$(localname $i)
537                         echo '  {"'$n'", '$j'},'
538                 fi
539         done
540         echo '}'
541
542         # benchmark array
543         # The comment makes the multiline declaration
544         # gofmt-safe even when there are no benchmarks.
545         echo 'var benchmarks = []testing.InternalBenchmark{ //'
546         for i in $benchmarks
547         do
548                 n=$(testname $i)
549                 j=$(localname $i)
550                 echo '  {"'$n'", '$j'},'
551         done
552         echo '}'
553
554         # examples array
555         echo 'var examples = []testing.InternalExample{ //'
556         # This doesn't work because we don't pick up the output.
557         #for i in $examples
558         #do
559         #       n=$(testname $i)
560         #       j=$(localname $i)
561         #       echo '  {"'$n'", '$j', ""},'
562         #done
563         echo '}'
564
565         # body
566         echo \
567 '
568 var matchPat string
569 var matchRe *__regexp__.Regexp
570
571 func matchString(pat, str string) (result bool, err error) {
572         if matchRe == nil || matchPat != pat {
573                 matchPat = pat
574                 matchRe, err = __regexp__.Compile(matchPat)
575                 if err != nil {
576                         return
577                 }
578         }
579         return matchRe.MatchString(str), nil
580 }
581
582 func main() {
583         m := testing.MainStart(matchString, tests, benchmarks, examples)
584 '
585         if test -n "$testmain"; then
586                 echo "  ${testmain}(m)"
587         else
588                 echo '  __os__.Exit(m.Run())'
589         fi
590
591         echo '}'
592 }>_testmain.go
593
594 case "x$dejagnu" in
595 xno)
596         if test "$trace" = "true"; then
597             echo ${GC} -g -c _testmain.go
598         fi
599         ${GC} -g -c _testmain.go
600
601         if test "$trace" = "true"; then
602             echo ${GL} *.o ${GOLIBS}
603         fi
604         ${GL} *.o ${GOLIBS}
605
606         set +e
607         if test "$bench" = ""; then
608                 if test "$trace" = "true"; then
609                     echo ./a.out -test.short -test.timeout=${timeout}s "$@"
610                 fi
611                 ./a.out -test.short -test.timeout=${timeout}s "$@" &
612                 pid=$!
613                 (sleep `expr $timeout + 10`
614                     echo > gotest-timeout
615                     echo "timed out in gotest" 1>&2
616                     kill -9 $pid) &
617                 alarmpid=$!
618                 wait $pid
619                 status=$?
620                 if ! test -f gotest-timeout; then
621                     sleeppid=`ps -o pid,ppid,comm | grep " $alarmpid " | grep sleep | sed -e 's/ *\([0-9]*\) .*$/\1/'`
622                     kill $alarmpid
623                     wait $alarmpid
624                     if test "$sleeppid" != ""; then
625                         kill $sleeppid
626                     fi
627                 fi
628         else
629                 if test "$trace" = "true"; then
630                     echo ./a.out -test.run=^\$ -test.bench="${bench}" "$@"
631                 fi
632                 ./a.out -test.run=^\$ -test.bench="${bench}" "$@"
633                 status=$?
634         fi
635         exit $status
636         ;;
637 xyes)
638         rm -rf ../../testsuite/*.o
639         files=`echo *`
640         for f in $files; do
641                 if test "$f" = "_obj" || test "$f" = "_test"; then
642                         continue
643                 fi
644                 rm -rf ../../testsuite/$f
645                 if test -f $f; then
646                         cp $f ../../testsuite/
647                 else
648                         ln -s ../$DIR/test/$f ../../testsuite/
649                 fi
650         done
651         cd ../../testsuite
652         rm -rf _obj _test
653         mkdir _obj _test
654         if test "$testname" != ""; then
655             GOTESTNAME="$testname"
656             export GOTESTNAME
657         fi
658         $MAKE check RUNTESTFLAGS="$RUNTESTFLAGS GOTEST_TMPDIR=$DIR/test"
659         # Useful when using make check-target-libgo
660         cat libgo.log >> libgo-all.log
661         cat libgo.sum >> libgo-all.sum
662         rm -rf $files
663         ;;
664 esac