Daily bump.
[official-gcc.git] / libgo / testsuite / gotest
blob33c98d804d6e6c3d4f39fd2e7ee60c82d7ed8a61
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.
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.
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 LANG=C
14 LC_ALL=C
15 LC_CTYPE=C
16 export LANG LC_ALL LC_CTYPE
18 GC=${GC:-gccgo}
19 GL=${GL:-${GC-gccgo}}
20 GOLIBS=${GOLIBS:-}
21 export GC GL GOLIBS
23 NM=${NM:-nm}
25 # srcdir is where the source files are found. basedir is where the
26 # source file paths are relative to.
27 # gofiles are the test files. pkgfiles are the source files.
28 srcdir=.
29 basedir=.
30 goarch=""
31 gofiles=""
32 goos=""
33 pkgfiles=""
34 loop=true
35 keep=false
36 pkgpath=
37 prefix=
38 dejagnu=no
39 timeout=600
40 testname=""
41 bench=""
42 trace=false
43 while $loop; do
44 case "x$1" in
45 x--srcdir)
46 srcdir=$2
47 shift
48 shift
50 x--srcdir=*)
51 srcdir=`echo $1 | sed -e 's/^--srcdir=//'`
52 shift
54 x--basedir)
55 basedir=$2
56 shift
57 shift
59 x--basedir=*)
60 basedir=`echo $1 | sed -e 's/^--basedir=//'`
61 shift
63 x--goarch)
64 goarch=$2
65 shift
66 shift
68 x--goarch=*)
69 goarch=`echo $1 | sed -e 's/^--goarch=//'`
70 shift
72 x--goos)
73 goos=$2
74 shift
75 shift
77 x--goos=*)
78 goos=`echo $1 | sed -e 's/^--goos=//'`
79 shift
81 x--pkgpath)
82 pkgpath=$2
83 shift
84 shift
86 x--pkgpath=*)
87 pkgpath=`echo $1 | sed -e 's/^--pkgpath=//'`
88 shift
90 x--prefix)
91 prefix=$2
92 shift
93 shift
95 x--prefix=*)
96 prefix=`echo $1 | sed -e 's/^--prefix=//'`
97 shift
99 x--keep)
100 keep=true
101 shift
103 x--pkgfiles)
104 pkgfiles=$2
105 shift
106 shift
108 x--pkgfiles=*)
109 pkgfiles=`echo $1 | sed -e 's/^--pkgfiles=//'`
110 shift
112 x--dejagnu)
113 dejagnu=$2
114 shift
115 shift
117 x--dejagnu=*)
118 dejagnu=`echo $1 | sed -e 's/^--dejagnu=//'`
119 shift
121 x--timeout)
122 timeout=$2
123 shift
124 shift
126 x--timeout=*)
127 timeout=`echo $1 | sed -e 's/^--timeout=//'`
128 shift
130 x--testname)
131 testname=$2
132 shift
133 shift
135 x--testname=*)
136 testname=`echo $1 | sed -e 's/^--testname=//'`
137 shift
139 x--bench)
140 bench=$2
141 shift
142 shift
144 x--bench=*)
145 bench=`echo $1 | sed -e 's/^--bench=//'`
146 shift
148 x--trace)
149 trace=true
150 shift
152 x-*)
153 loop=false
156 loop=false
159 gofiles="$gofiles $1"
160 shift
162 esac
163 done
165 DIR=gotest$$
166 rm -rf $DIR
167 mkdir $DIR
169 cd $DIR
170 mkdir test
171 cd test
173 if test $keep = false; then
174 trap "cd ../..; rm -rf $DIR" 0 1 2 3 14 15
175 else
176 trap "cd ../..; echo Keeping $DIR" 0 1 2 3 14 15
179 case "$srcdir" in
183 srcdir="../../$srcdir"
185 esac
187 SRCDIR=$srcdir
188 export SRCDIR
190 case "$basedir" in
194 basedir="../../$basedir"
196 esac
198 # Link all the files/directories in srcdir into our working directory,
199 # so that the tests do not have to refer to srcdir to find test data.
200 ln -s $srcdir/* .
202 # Some tests refer to a ../testdata directory.
203 if test -e $srcdir/../testdata; then
204 rm -f ../testdata
205 abssrcdir=`cd $srcdir && pwd`
206 ln -s $abssrcdir/../testdata ../testdata
209 # Copy the .go files because io/utils_test.go expects a regular file.
210 case "x$gofiles" in
212 case "x$pkgfiles" in
214 for f in `cd $srcdir; ls *.go`; do
215 rm -f $f;
216 cp $srcdir/$f .
217 done
220 for f in $pkgfiles; do
221 case $f in
223 b=`basename $f`
224 rm -f $b
225 cp $f $b
228 if test -f $basedir/$f; then
229 b=`basename $f`
230 rm -f $b
231 cp $basedir/$f $b
232 elif test -f ../../$f; then
233 b=`basename $f`
234 rm -f $b
235 cp ../../$f $b
236 else
237 echo "file $f not found" 1>&2
238 exit 1
241 esac
242 done
243 for f in `cd $srcdir; ls *_test.go`; do
244 rm -f $f
245 cp $srcdir/$f .
246 done
248 esac
251 for f in $gofiles; do
252 b=`basename $f`
253 rm -f $b
254 cp $basedir/$f $b
255 done
256 case "x$pkgfiles" in
258 for f in `cd $srcdir; ls *.go | grep -v *_test.go`; do
259 rm -f $f
260 cp $srcdir/$f .
261 done
264 for f in $pkgfiles; do
265 case $f in
267 b=`basename $f`
268 rm -f $b
269 cp $f $b
272 if test -f $basedir/$f; then
273 b=`basename $f`
274 rm -f $b
275 cp $basedir/$f $b
276 elif test -f ../../$f; then
277 b=`basename $f`
278 rm -f $b
279 cp ../../$f $b
280 else
281 echo "file $f not found" 1>&2
282 exit 1
285 esac
286 done
288 esac
290 esac
292 gobuild() {
293 line=$(echo "$1" | sed -e 's|//go:build ||')
294 line=$(echo "$line" | sed -e 's/go1\.[0-9]\+/1/g' -e 's/goexperiment\./goexperiment/')
295 line=" $line "
296 wrap='[ ()!&|]'
297 for ones in $goarch $goos cgo gccgo goexperimentfieldtrack; do
298 line=$(echo "$line" | sed -e "s/\\(${wrap}\\)${ones}\\(${wrap}\\)/"'\11\2/g')
299 done
300 # 386 is a special case since it looks like a number to the shell.
301 # We need it to be 0 if it's not $goarch.
302 if test "$goarch" != "386"; then
303 line=$(echo "$line" | sed -e "s/\\(${wrap}\\)386\\(${wrap}\\)/\10\2/g")
305 return $((!($line)))
308 case "x$gofiles" in
310 for f in `ls *_test.go`; do
311 tag1=`echo $f | sed -e 's/^.*_\([^_]*\)_test.go$/\1/'`
312 tag2=`echo $f | sed -e 's/^.*_\([^_]*\)_[^_]*_test.go$/\1/'`
313 if test x$tag1 = x$f; then
314 tag1=
316 if test x$tag2 = x$f; then
317 tag2=
320 case "$tag1" in
321 "") ;;
322 $goarch) ;;
323 $goos) ;;
324 aix | android | darwin | dragonfly | freebsd | hurd | ios | illumos | js | linux | nacl | netbsd | openbsd | plan9 | solaris | windows | zos)
325 tag1=nonmatchingtag
327 386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | nios2 | ppc | ppc64 | ppc64le | riscv | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64 | wasm)
328 tag1=nonmatchingtag
331 # File name like x_amd64_random.go, where tag1=random.
332 # Don't match based on tag2.
333 tag2=
335 esac
337 case "$tag2" in
338 "") ;;
339 $goarch) ;;
340 $goos) ;;
341 aix | android | darwin | dragonfly | freebsd | hurd | ios | illumos | js | linux | nacl | netbsd | openbsd | plan9 | solaris | windows | zos)
342 tag2=nonmatchingtag
344 386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | nios2 | ppc | ppc64 | ppc64le | riscv | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64 | wasm)
345 tag2=nonmatchingtag
347 esac
349 if test x$tag1 = xnonmatchingtag -o x$tag2 = xnonmatchingtag; then
350 continue
353 # Check for go:build line
354 build=$(sed '/^package /q' < $f | grep '^//go:build ' | cat)
355 if test -n "$build"; then
356 if $(gobuild "$build"); then
357 gofiles="$gofiles $f"
359 continue
362 # No go:build line, check for +build lines.
363 tags=`sed '/^package /q' < $f | grep '^// *+build '`
364 omatch=true
365 first=true
366 match=false
367 for tag in $tags; do
368 case $tag in
369 "//")
371 "+build" | "//+build")
372 if test "$first" = "true"; then
373 first=false
374 elif test "$match" = "false"; then
375 omatch=false
377 match=false
379 $goos | $goarch | cgo | gccgo | goexperiment.fieldtrack | go1.[0-9] | go1.[0-9][0-9])
380 match=true
382 "!"$goos | "!"$goarch | "!cgo" | "!gccgo" | "!goexperiment.fieldtrack" | "!"go1.[0-9] | "!"go1.1[0-7])
384 *,*)
385 cmatch=true
386 for ctag in `echo $tag | sed -e 's/,/ /g'`; do
387 case $ctag in
388 $goos | $goarch | cgo | gccgo | goexperiment.fieldtrack | go1.[0-9] | go1.[0-9][0-9])
390 "!"$goos | "!"$goarch | "!cgo" | "!gccgo" | "!goexperiment.fieldtrack" | "!"go1.[0-9] | "!"go1.1[0-7])
391 cmatch=false
393 "!"*)
396 cmatch=false
398 esac
399 done
400 if test "$cmatch" = "true"; then
401 match=true
404 "!"*)
405 match=true
407 esac
408 done
410 if test "$match" = "false" -a "$first" = "false"; then
411 omatch=false
414 if test "$omatch" = "true"; then
415 gofiles="$gofiles $f"
417 done
420 xgofiles=$gofiles
421 gofiles=
422 for f in $xgofiles; do
423 gofiles="$gofiles `basename $f`"
424 done
425 esac
427 case "x$gofiles" in
429 echo 'no test files found' 1>&2
430 exit 1
432 esac
434 case "x$pkgfiles" in
436 pkgbasefiles=`ls *.go | grep -v _test.go 2>/dev/null`
439 for f in $pkgfiles; do
440 pkgbasefiles="$pkgbasefiles `basename $f`"
441 done
443 esac
445 case "x$pkgfiles" in
447 echo 'no source files found' 1>&2
448 exit 1
450 esac
452 # Split $gofiles into external gofiles (those in *_test packages)
453 # and internal ones (those in the main package).
454 xgofiles=
455 xpackage=
456 for f in $gofiles; do
457 package=`grep '^package[ ]' $f | sed 1q`
458 case "$package" in
459 *_test)
460 xpackage=`echo $package | sed -e 's/package[ ]//' -e 's/[ ]*$//'`
461 xgofiles="$xgofiles $f"
464 ngofiles="$ngofiles $f"
466 esac
467 done
468 gofiles=$ngofiles
470 # External $O file
471 xofile=""
472 havex=false
473 if [ "x$xgofiles" != "x" ]; then
474 xofile="_xtest_.o"
475 havex=true
478 testmain=
479 if $havex && fgrep 'func TestMain(' $xgofiles >/dev/null 2>&1; then
480 package=`grep '^package[ ]' $xgofiles | sed 1q | sed -e 's/.* //'`
481 testmain="${package}.TestMain"
482 elif test -n "$gofiles" && fgrep 'func TestMain(' $gofiles >/dev/null 2>&1; then
483 package=`grep '^package[ ]' $gofiles | sed 1q | sed -e 's/.* //'`
484 testmain="${package}.TestMain"
487 set -e
489 package=`echo ${srcdir} | sed -e 's|^.*libgo/go/||'`
491 pkgpatharg=
492 xpkgpatharg=
493 prefixarg=
494 if test -n "$pkgpath"; then
495 pkgpatharg="-fgo-pkgpath=$pkgpath"
496 xpkgpatharg="-fgo-pkgpath=${pkgpath}_test"
497 elif test -n "$prefix"; then
498 prefixarg="-fgo-prefix=$prefix"
501 if test "$trace" = "true"; then
502 echo $GC -g $pkgpatharg $prefixarg -c -I . -fno-toplevel-reorder -o _gotest_.o $gofiles $pkgbasefiles
504 $GC -g $pkgpatharg $prefixarg -c -I . -fno-toplevel-reorder -o _gotest_.o $gofiles $pkgbasefiles
506 if $havex; then
507 mkdir -p `dirname $package`
508 cp _gotest_.o `dirname $package`/lib`basename $package`.a
510 # Force the test version of the package to be imported first,
511 # so that its type definitions will be used, in case any new
512 # methods appear in export_test.go files.
513 echo "package $xpackage" > _first_test.go
514 echo 'import _ "'$package'"' >> _first_test.go
516 if test "$trace" = "true"; then
517 echo $GC -g $xpkgpatharg -c -I . -fno-toplevel-reorder -o $xofile _first_test.go $xgofiles
519 $GC -g $xpkgpatharg -c -I . -fno-toplevel-reorder -o $xofile _first_test.go $xgofiles
522 # They all compile; now generate the code to call them.
524 testname() {
525 # Remove the package from the name used with the -test option.
526 echo $1 | sed 's/^.*\.//'
529 localname() {
530 # The package main has been renamed to __main__ when imported.
531 # Adjust its uses.
532 # Also demangle underscores.
533 echo $1 | sed 's/^main\./__main__./' | sed 's/__/_/'
536 # Takes a list of tests derived from 'nm' output (whose symbols are mangled)
537 # and emits a demangled list of tests, using only the terminal package.
538 # Example:
540 # Original symbol: foo/bar/leaf.Mumble
541 # Mangled symbol: foo_1fbar_1leaf.Mumble
542 # Returned: leaf.Mumble
544 symtogo() {
545 result=""
546 for tp in $*; do
547 # Discard symbols with a leading dot.
548 # On AIX, this will remove function text symbols (with a leading dot).
549 # Therefore, only function descriptor symbols (without this leading dot)
550 # will be used to retrieve the go symbols, avoiding duplication.
551 if expr "$tp" : '^\.' >/dev/null 2>&1; then
552 continue
554 # Skip type descriptors. These are normally skipped because they
555 # are weak symbols, but if not using GNU nm we may see them here.
556 if expr "$tp" : '^type\.\.' >/dev/null 2>&1; then
557 continue
559 s=$(echo "$tp" | sed -e 's/_1/%/g' | sed -e 's/.*%//')
560 # Screen out methods (X.Y.Z).
561 if ! expr "$s" : '^[^.]*\.[^.]*$' >/dev/null 2>&1; then
562 continue
564 tname=$(testname $s)
565 # Skip TestMain.
566 if test x$tname = xTestMain; then
567 continue
569 # Check that the function is defined in a test file,
570 # not an ordinary non-test file.
571 if grep "^func $tname(" $gofiles $xgofiles >/dev/null 2>&1; then
572 echo "$s"
574 done
577 # Find Go benchmark/fuzz/example functions.
578 # The argument is the function name prefix.
579 findfuncs() {
580 pattern="$1([^a-z].*)?"
581 syms=$($NM -p -v _gotest_.o | egrep " $text .*\."$pattern'$' | fgrep -v ' __go_' | egrep -v '\.\.\w+$' | sed 's/.* //')
582 if $havex; then
583 xsyms=$($NM -p -v $xofile | egrep " $text .*\."$pattern'$' | fgrep -v ' __go_' | egrep -v '\.\.\w+$' | sed 's/.* //')
584 syms="$syms $xsyms"
586 symtogo "$syms"
589 # Takes an example name and puts any output into the file example.txt.
590 # It strips comment markers but does not otherwise change the output.
591 exampleoutput() {
592 n=$(testname $1)
593 for f in $gofiles $xgofiles; do
594 if ! grep "^func $n(" $f >/dev/null 2>&1; then
595 continue
597 # Copy the output comment, if any, into example.txt.
598 # Remove the comment markers.
599 sed -n "/^func $n(/,/^}$/ p" $f |
600 sed -n '\|// \([Uu]nordered \)\?[Oo]utput:|,$ p' |
601 sed -n '\|//| s|[ ]*// \?||p' > example.txt
602 # Check whether we found an output comment.
603 if ! sed -n '1p' < example.txt | grep '[Oo]utput:' >/dev/null 2>&1; then
604 rm -f example.txt
606 return
607 done
611 # On systems using PPC64 ELF ABI v1 function symbols show up
612 # as descriptors in the data section.
613 text="[TD]"
615 # test functions are named TestFoo
616 # the grep -v eliminates methods and other special names
617 # that have multiple dots.
618 pattern='Test([^a-z].*)?'
619 # The -p option tells GNU nm not to sort.
620 # The -v option tells Solaris nm to sort by value.
621 testsyms=$($NM -p -v _gotest_.o | egrep " $text .*\."$pattern'$' | fgrep -v ' __go_' | egrep -v '\.\.\w+$' | sed 's/.* //')
622 testxsyms=
623 if $havex; then
624 testxsyms=$($NM -p -v $xofile | egrep " $text .*\."$pattern'$' | fgrep -v ' __go_' | egrep -v '\.\.\w+$' | sed 's/.* //')
625 testsyms="$testsyms $testxsyms"
627 tests=$(symtogo "$testsyms")
628 if [ "x$tests" = x ]; then
629 echo 'gotest: warning: no tests matching '$pattern in _gotest_.o $xofile 1>&2
630 exit 2
633 benchmarks=$(findfuncs Benchmark)
634 fuzztargets=$(findfuncs Fuzz)
635 examples=$(findfuncs Example)
637 # package spec
638 echo 'package main'
639 echo
640 # imports
641 if echo "$tests" | egrep -v '_test\.' >/dev/null; then
642 echo 'import "./_gotest_"'
644 if $havex; then
645 needxtest=false
646 if test -n "$testxsyms"; then
647 needxtest=true
648 elif echo "$benchmarks" | grep '_test\.' >/dev/null; then
649 needxtest=true
650 else
651 # Check whether any example has output.
652 for i in $(echo "$examples" | grep '_test\.'); do
653 exampleoutput $i
654 if test -f example.txt; then
655 rm -f example.txt
656 needxtest=true
657 break
659 done
661 if test x$needxtest = xtrue; then
662 echo 'import "./_xtest_"'
663 else
664 echo 'import _ "./_xtest_"'
667 if test "$package" != "testing"; then
668 echo 'import "testing"'
670 echo 'import "testing/internal/testdeps"'
671 if ! test -n "$testmain"; then
672 echo 'import __os__ "os"'
674 # test array
675 echo
676 echo 'var tests = []testing.InternalTest {'
677 for i in $tests; do
678 n=$(testname $i)
679 j=$(localname $i)
680 echo ' {"'$n'", '$j'},'
681 done
682 echo '}'
684 # benchmark array
685 # The comment makes the multiline declaration
686 # gofmt-safe even when there are no benchmarks.
687 echo 'var benchmarks = []testing.InternalBenchmark{'
688 for i in $benchmarks; do
689 n=$(testname $i)
690 j=$(localname $i)
691 echo ' {"'$n'", '$j'},'
692 done
693 echo '}'
695 # fuzz array
696 echo 'var fuzzTargets = []testing.InternalFuzzTarget{'
697 for i in $fuzztargets; do
698 n=$(testname $i)
699 j=$(localname $i)
700 echo ' {"'$n'", '$j'},'
701 done
702 echo '}'
704 # examples array
705 echo 'var examples = []testing.InternalExample{'
706 for i in $examples; do
707 n=$(testname $i)
708 j=$(localname $i)
709 # Look for a //output comment.
710 hasoutput=false
711 unordered=false
712 output=
713 exampleoutput $i
714 if ! test -f example.txt; then
715 continue
717 # Check whether the output can be unordered.
718 unordered=false
719 if sed -n '1p' < example.txt | grep -i unordered >/dev/null 2>&1; then
720 unordered=true
722 # Remove the output header.
723 # Quote backslashes.
724 # Quote quotation characters.
725 # Turn tab into \t.
726 # Turn pairs of spaces into " \x20", because $() will
727 # drop duplicate spaces.
728 # Drop trailing spaces, and turn newlines into \n.
729 # Remove leading and trailing \n.
730 sed '1 s/\([Uu]nordered \)\?[Oo]utput:[ ]*//' < example.txt |
731 sed -e 's/\\/\\\\/g' \
732 -e 's/"/\\"/g' \
733 -e 's/ /\\t/g' \
734 -e 's/ / \\x20/g' \
735 -e 's/[ ]*$/\\n/g' |
736 tr -d '\n' |
737 sed -e 's/^\(\\n\)*//' \
738 -e 's/\(\\n\)*$//' > example2.txt
739 hasoutput=true
740 echo ' {"'$n'", '$j','
741 sed -e 's/^/ "/' -e 's/$/", /' < example2.txt
742 echo $unordered'},'
743 rm -f example.txt example2.txt
744 done
745 echo '}'
747 # body
748 echo \
750 func main() {
751 m := testing.MainStart(testdeps.TestDeps{}, tests, benchmarks, fuzzTargets, examples)
753 if test -n "$testmain"; then
754 echo " ${testmain}(m)"
755 else
756 echo ' __os__.Exit(m.Run())'
759 echo '}'
760 }>_testmain.go
762 case "x$dejagnu" in
763 xno)
764 if test "$trace" = "true"; then
765 echo ${GC} -g -c _testmain.go
767 ${GC} -g -c _testmain.go
769 if test "$trace" = "true"; then
770 echo ${GL} *.o ${GOLIBS}
772 ${GL} *.o ${GOLIBS}
774 set +e
775 if test "$bench" = ""; then
776 if test "$trace" = "true"; then
777 echo ./a.out -test.short -test.timeout=${timeout}s "$@"
779 ./a.out -test.short -test.timeout=${timeout}s "$@" &
780 pid=$!
781 (sleep `expr $timeout + 10`
782 echo > gotest-timeout
783 echo "timed out in gotest" 1>&2
784 kill -9 $pid) &
785 alarmpid=$!
786 wait $pid
787 status=$?
788 if ! test -f gotest-timeout; then
789 sleeppid=`ps -o pid,ppid,comm | grep " $alarmpid " | grep sleep | sed -e 's/ *\([0-9]*\) .*$/\1/'`
790 kill $alarmpid
791 wait $alarmpid
792 if test "$sleeppid" != ""; then
793 kill $sleeppid
796 else
797 if test "$trace" = "true"; then
798 echo ./a.out -test.run=^\$ -test.bench="${bench}" "$@"
800 ./a.out -test.run=^\$ -test.bench="${bench}" "$@"
801 status=$?
803 exit $status
805 xyes)
806 rm -rf ../../testsuite/*.o
807 files=`echo *`
808 for f in $files; do
809 if test "$f" = "_obj" || test "$f" = "_test"; then
810 continue
812 rm -rf ../../testsuite/$f
813 if test -f $f; then
814 cp $f ../../testsuite/
815 else
816 ln -s ../$DIR/test/$f ../../testsuite/
818 done
819 cd ../../testsuite
820 rm -rf _obj _test
821 mkdir _obj _test
822 if test "$testname" != ""; then
823 GOTESTNAME="$testname"
824 export GOTESTNAME
826 $MAKE check RUNTESTFLAGS="$RUNTESTFLAGS GOTEST_TMPDIR=$DIR/test"
827 # Useful when using make check-target-libgo
828 cat libgo.log >> libgo-all.log
829 cat libgo.sum >> libgo-all.sum
830 rm -rf $files
832 esac