#!/usr/bin/env bash # Copyright 2009 The Go Authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. # Using all the *_test.go files in the current directory, write out a file # _testmain.go that runs all its tests. Compile everything and run the # tests. # If files are named on the command line, use them instead of *_test.go. # Makes egrep,grep work better in general if we put them # in ordinary C mode instead of what the current language is. unset LANG export LC_ALL=C export LC_CTYPE=C _GC=$GC # Make.inc will overwrite this if [ ! -f [Mm]akefile ]; then echo 'please create a Makefile for gotest; see http://golang.org/doc/code.html for details' 1>&2 exit 2 fi export GOROOT=${GOROOT:-"@@GOROOT@@"} eval $(gomake -j1 --no-print-directory -f "$GOROOT"/src/Make.inc go-env) if [ -z "$O" ]; then echo 'missing $O - maybe no Make.$GOARCH?' 1>&2 exit 2 fi E="$GORUN" # Allow overrides GC="${_GC:-$GC} -I _test" GL="${GL:-$LD} -L _test" AS="$AS" CC="$CC" LD="$LD" export GC GL O AS CC LD gofiles="" loop=true while $loop; do case "x$1" in x-*) loop=false ;; x) loop=false ;; *) gofiles="$gofiles $1" shift ;; esac done case "x$gofiles" in x) gofiles=$(echo -n $(ls *_test.go 2>/dev/null)) esac case "x$gofiles" in x) echo 'no test files found (*_test.go)' 1>&2 exit 2 esac # Run any commands given in sources, like # // gotest: $GC foo.go # to build any test-only dependencies. sed -n 's/^\/\/ gotest: //p' $gofiles | sh -e || exit 1 # Split $gofiles into external gofiles (those in *_test packages) # and internal ones (those in the main package). xgofiles=$(echo $(grep '^package[ ]' $gofiles /dev/null | grep ':.*_test' | sed 's/:.*//')) gofiles=$(echo $(grep '^package[ ]' $gofiles /dev/null | grep -v ':.*_test' | sed 's/:.*//')) # External $O file xofile="" havex=false if [ "x$xgofiles" != "x" ]; then xofile="_xtest_.$O" havex=true fi set -e gomake testpackage-clean gomake testpackage "GOTESTFILES=$gofiles" if $havex; then $GC -o $xofile $xgofiles fi # They all compile; now generate the code to call them. # Suppress output to stdout on Linux MAKEFLAGS= MAKELEVEL= # usage: nmgrep pattern file... nmgrep() { pat="$1" shift for i do # Package symbol "".Foo is pkg.Foo when imported in Go. # Figure out pkg. case "$i" in *.a) pkg=$(gopack p $i __.PKGDEF | sed -n 's/^package //p' | sed 's/ .*//' | sed 1q) ;; *) pkg=$(sed -n 's/^ .* in package "\(.*\)".*/\1/p' $i | sed 1q) ;; esac 6nm -s "$i" | egrep ' T .*\.'"$pat"'$' | sed 's/.* //; /\..*\./d; s/""\./'"$pkg"'./g' done } localname() { # The package main has been renamed to __main__ when imported. # Adjust its uses. echo $1 | sed 's/^main\./__main__./' } importpath=$(gomake -s importpath) { # test functions are named TestFoo # the grep -v eliminates methods and other special names # that have multiple dots. pattern='Test([^a-z].*)?' tests=$(nmgrep $pattern _test/$importpath.a $xofile) if [ "x$tests" = x ]; then echo 'gotest: error: no tests matching '$pattern in _test/$importpath.a $xofile 1>&2 exit 2 fi # benchmarks are named BenchmarkFoo. pattern='Benchmark([^a-z].*)?' benchmarks=$(nmgrep $pattern _test/$importpath.a $xofile) # package spec echo 'package main' echo # imports if echo "$tests" | egrep -v '_test\.' >/dev/null; then case "$importpath" in testing) ;; main) # Import path main is reserved, so import with # explicit reference to ./_test/main instead. # Also, the file we are writing defines a function named main, # so rename this import to __main__ to avoid name conflict. echo 'import __main__ "./_test/main"' ;; *) echo 'import "'$importpath'"' ;; esac fi if $havex; then echo 'import "./_xtest_"' fi echo 'import "testing"' echo 'import __regexp__ "regexp"' # rename in case tested package is called regexp # test array echo echo 'var tests = []testing.InternalTest{' for i in $tests do j=$(localname $i) echo ' {"'$i'", '$j'},' done echo '}' # benchmark array # The comment makes the multiline declaration # gofmt-safe even when there are no benchmarks. echo 'var benchmarks = []testing.InternalBenchmark{ //' for i in $benchmarks do j=$(localname $i) echo ' {"'$i'", '$j'},' done echo '}' # body echo echo 'func main() {' echo ' testing.Main(__regexp__.MatchString, tests)' echo ' testing.RunBenchmarks(__regexp__.MatchString, benchmarks)' echo '}' }>_testmain.go $GC _testmain.go $GL _testmain.$O $E ./$O.out "$@"