summaryrefslogtreecommitdiff
path: root/src/cmd/go/test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/go/test.go')
-rw-r--r--src/cmd/go/test.go815
1 files changed, 815 insertions, 0 deletions
diff --git a/src/cmd/go/test.go b/src/cmd/go/test.go
new file mode 100644
index 000000000..870ab190f
--- /dev/null
+++ b/src/cmd/go/test.go
@@ -0,0 +1,815 @@
+// Copyright 2011 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.
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "go/ast"
+ "go/build"
+ "go/doc"
+ "go/parser"
+ "go/token"
+ "os"
+ "os/exec"
+ "path"
+ "path/filepath"
+ "runtime"
+ "sort"
+ "strings"
+ "text/template"
+ "time"
+ "unicode"
+ "unicode/utf8"
+)
+
+// Break init loop.
+func init() {
+ cmdTest.Run = runTest
+}
+
+var cmdTest = &Command{
+ CustomFlags: true,
+ UsageLine: "test [-c] [-i] [build flags] [packages] [flags for test binary]",
+ Short: "test packages",
+ Long: `
+'Go test' automates testing the packages named by the import paths.
+It prints a summary of the test results in the format:
+
+ ok archive/tar 0.011s
+ FAIL archive/zip 0.022s
+ ok compress/gzip 0.033s
+ ...
+
+followed by detailed output for each failed package.
+
+'Go test' recompiles each package along with any files with names matching
+the file pattern "*_test.go". These additional files can contain test functions,
+benchmark functions, and example functions. See 'go help testfunc' for more.
+
+By default, go test needs no arguments. It compiles and tests the package
+with source in the current directory, including tests, and runs the tests.
+
+The package is built in a temporary directory so it does not interfere with the
+non-test installation.
+
+In addition to the build flags, the flags handled by 'go test' itself are:
+
+ -c Compile the test binary to pkg.test but do not run it.
+
+ -i
+ Install packages that are dependencies of the test.
+ Do not run the test.
+
+The test binary also accepts flags that control execution of the test; these
+flags are also accessible by 'go test'. See 'go help testflag' for details.
+
+For more about build flags, see 'go help build'.
+For more about specifying packages, see 'go help packages'.
+
+See also: go build, go vet.
+`,
+}
+
+var helpTestflag = &Command{
+ UsageLine: "testflag",
+ Short: "description of testing flags",
+ Long: `
+The 'go test' command takes both flags that apply to 'go test' itself
+and flags that apply to the resulting test binary.
+
+The test binary, called pkg.test, where pkg is the name of the
+directory containing the package sources, has its own flags:
+
+ -test.v
+ Verbose output: log all tests as they are run.
+
+ -test.run pattern
+ Run only those tests and examples matching the regular
+ expression.
+
+ -test.bench pattern
+ Run benchmarks matching the regular expression.
+ By default, no benchmarks run.
+
+ -test.cpuprofile cpu.out
+ Write a CPU profile to the specified file before exiting.
+
+ -test.memprofile mem.out
+ Write a memory profile to the specified file when all tests
+ are complete.
+
+ -test.memprofilerate n
+ Enable more precise (and expensive) memory profiles by setting
+ runtime.MemProfileRate. See 'godoc runtime MemProfileRate'.
+ To profile all memory allocations, use -test.memprofilerate=1
+ and set the environment variable GOGC=off to disable the
+ garbage collector, provided the test can run in the available
+ memory without garbage collection.
+
+ -test.parallel n
+ Allow parallel execution of test functions that call t.Parallel.
+ The value of this flag is the maximum number of tests to run
+ simultaneously; by default, it is set to the value of GOMAXPROCS.
+
+ -test.short
+ Tell long-running tests to shorten their run time.
+ It is off by default but set during all.bash so that installing
+ the Go tree can run a sanity check but not spend time running
+ exhaustive tests.
+
+ -test.timeout t
+ If a test runs longer than t, panic.
+
+ -test.benchtime n
+ Run enough iterations of each benchmark to take n seconds.
+ The default is 1 second.
+
+ -test.cpu 1,2,4
+ Specify a list of GOMAXPROCS values for which the tests or
+ benchmarks should be executed. The default is the current value
+ of GOMAXPROCS.
+
+For convenience, each of these -test.X flags of the test binary is
+also available as the flag -X in 'go test' itself. Flags not listed
+here are passed through unaltered. For instance, the command
+
+ go test -x -v -cpuprofile=prof.out -dir=testdata -update
+
+will compile the test binary and then run it as
+
+ pkg.test -test.v -test.cpuprofile=prof.out -dir=testdata -update
+`,
+}
+
+var helpTestfunc = &Command{
+ UsageLine: "testfunc",
+ Short: "description of testing functions",
+ Long: `
+The 'go test' command expects to find test, benchmark, and example functions
+in the "*_test.go" files corresponding to the package under test.
+
+A test function is one named TestXXX (where XXX is any alphanumeric string
+not starting with a lower case letter) and should have the signature,
+
+ func TestXXX(t *testing.T) { ... }
+
+A benchmark function is one named BenchmarkXXX and should have the signature,
+
+ func BenchmarkXXX(b *testing.B) { ... }
+
+An example function is similar to a test function but, instead of using *testing.T
+to report success or failure, prints output to os.Stdout and os.Stderr.
+That output is compared against the function's "Output:" comment, which
+must be the last comment in the function body (see example below). An
+example with no such comment, or with no text after "Output:" is compiled
+but not executed.
+
+Godoc displays the body of ExampleXXX to demonstrate the use
+of the function, constant, or variable XXX. An example of a method M with
+receiver type T or *T is named ExampleT_M. There may be multiple examples
+for a given function, constant, or variable, distinguished by a trailing _xxx,
+where xxx is a suffix not beginning with an upper case letter.
+
+Here is an example of an example:
+
+ func ExamplePrintln() {
+ Println("The output of\nthis example.")
+ // Output: The output of
+ // this example.
+ }
+
+The entire test file is presented as the example when it contains a single
+example function, at least one other function, type, variable, or constant
+declaration, and no test or benchmark functions.
+
+See the documentation of the testing package for more information.
+`,
+}
+
+var (
+ testC bool // -c flag
+ testI bool // -i flag
+ testV bool // -v flag
+ testFiles []string // -file flag(s) TODO: not respected
+ testTimeout string // -timeout flag
+ testArgs []string
+ testBench bool
+ testStreamOutput bool // show output as it is generated
+ testShowPass bool // show passing output
+
+ testKillTimeout = 10 * time.Minute
+)
+
+func runTest(cmd *Command, args []string) {
+ var pkgArgs []string
+ pkgArgs, testArgs = testFlags(args)
+
+ pkgs := packagesForBuild(pkgArgs)
+ if len(pkgs) == 0 {
+ fatalf("no packages to test")
+ }
+
+ if testC && len(pkgs) != 1 {
+ fatalf("cannot use -c flag with multiple packages")
+ }
+
+ // If a test timeout was given and is parseable, set our kill timeout
+ // to that timeout plus one minute. This is a backup alarm in case
+ // the test wedges with a goroutine spinning and its background
+ // timer does not get a chance to fire.
+ if dt, err := time.ParseDuration(testTimeout); err == nil {
+ testKillTimeout = dt + 1*time.Minute
+ }
+
+ // show passing test output (after buffering) with -v flag.
+ // must buffer because tests are running in parallel, and
+ // otherwise the output will get mixed.
+ testShowPass = testV
+
+ // stream test output (no buffering) when no package has
+ // been given on the command line (implicit current directory)
+ // or when benchmarking.
+ // Also stream if we're showing output anyway with a
+ // single package under test. In that case, streaming the
+ // output produces the same result as not streaming,
+ // just more immediately.
+ testStreamOutput = len(pkgArgs) == 0 || testBench ||
+ (len(pkgs) <= 1 && testShowPass)
+
+ var b builder
+ b.init()
+
+ if testI {
+ buildV = testV
+
+ deps := map[string]bool{
+ // Dependencies for testmain.
+ "testing": true,
+ "regexp": true,
+ }
+ for _, p := range pkgs {
+ // Dependencies for each test.
+ for _, path := range p.Imports {
+ deps[path] = true
+ }
+ for _, path := range p.TestImports {
+ deps[path] = true
+ }
+ for _, path := range p.XTestImports {
+ deps[path] = true
+ }
+ }
+
+ // translate C to runtime/cgo
+ if deps["C"] {
+ delete(deps, "C")
+ deps["runtime/cgo"] = true
+ if buildContext.GOOS == runtime.GOOS && buildContext.GOARCH == runtime.GOARCH {
+ deps["cmd/cgo"] = true
+ }
+ }
+ // Ignore pseudo-packages.
+ delete(deps, "unsafe")
+
+ all := []string{}
+ for path := range deps {
+ all = append(all, path)
+ }
+ sort.Strings(all)
+
+ a := &action{}
+ for _, p := range packagesForBuild(all) {
+ a.deps = append(a.deps, b.action(modeInstall, modeInstall, p))
+ }
+ b.do(a)
+ if !testC {
+ return
+ }
+ b.init()
+ }
+
+ var builds, runs, prints []*action
+
+ // Prepare build + run + print actions for all packages being tested.
+ for _, p := range pkgs {
+ buildTest, runTest, printTest, err := b.test(p)
+ if err != nil {
+ str := err.Error()
+ if strings.HasPrefix(str, "\n") {
+ str = str[1:]
+ }
+ if p.ImportPath != "" {
+ errorf("# %s\n%s", p.ImportPath, str)
+ } else {
+ errorf("%s", str)
+ }
+ continue
+ }
+ builds = append(builds, buildTest)
+ runs = append(runs, runTest)
+ prints = append(prints, printTest)
+ }
+
+ // Ultimately the goal is to print the output.
+ root := &action{deps: prints}
+
+ // Force the printing of results to happen in order,
+ // one at a time.
+ for i, a := range prints {
+ if i > 0 {
+ a.deps = append(a.deps, prints[i-1])
+ }
+ }
+
+ // If we are benchmarking, force everything to
+ // happen in serial. Could instead allow all the
+ // builds to run before any benchmarks start,
+ // but try this for now.
+ if testBench {
+ for i, a := range builds {
+ if i > 0 {
+ // Make build of test i depend on
+ // completing the run of test i-1.
+ a.deps = append(a.deps, runs[i-1])
+ }
+ }
+ }
+
+ // If we are building any out-of-date packages other
+ // than those under test, warn.
+ okBuild := map[*Package]bool{}
+ for _, p := range pkgs {
+ okBuild[p] = true
+ }
+
+ warned := false
+ for _, a := range actionList(root) {
+ if a.p != nil && a.f != nil && !okBuild[a.p] && !a.p.fake && !a.p.local {
+ okBuild[a.p] = true // don't warn again
+ if !warned {
+ fmt.Fprintf(os.Stderr, "warning: building out-of-date packages:\n")
+ warned = true
+ }
+ fmt.Fprintf(os.Stderr, "\t%s\n", a.p.ImportPath)
+ }
+ }
+ if warned {
+ args := strings.Join(pkgArgs, " ")
+ if args != "" {
+ args = " " + args
+ }
+ fmt.Fprintf(os.Stderr, "installing these packages with 'go test -i%s' will speed future tests.\n\n", args)
+ }
+
+ b.do(root)
+}
+
+func (b *builder) test(p *Package) (buildAction, runAction, printAction *action, err error) {
+ if len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 {
+ build := &action{p: p}
+ run := &action{p: p}
+ print := &action{f: (*builder).notest, p: p, deps: []*action{build}}
+ return build, run, print, nil
+ }
+
+ // Build Package structs describing:
+ // ptest - package + test files
+ // pxtest - package of external test files
+ // pmain - pkg.test binary
+ var ptest, pxtest, pmain *Package
+
+ var imports, ximports []*Package
+ var stk importStack
+ stk.push(p.ImportPath + "_test")
+ for _, path := range p.TestImports {
+ p1 := loadImport(path, p.Dir, &stk, p.build.TestImportPos[path])
+ if p1.Error != nil {
+ return nil, nil, nil, p1.Error
+ }
+ imports = append(imports, p1)
+ }
+ for _, path := range p.XTestImports {
+ if path == p.ImportPath {
+ continue
+ }
+ p1 := loadImport(path, p.Dir, &stk, p.build.XTestImportPos[path])
+ if p1.Error != nil {
+ return nil, nil, nil, p1.Error
+ }
+ ximports = append(ximports, p1)
+ }
+ stk.pop()
+
+ // Use last element of import path, not package name.
+ // They differ when package name is "main".
+ _, elem := path.Split(p.ImportPath)
+ testBinary := elem + ".test"
+
+ // The ptest package needs to be importable under the
+ // same import path that p has, but we cannot put it in
+ // the usual place in the temporary tree, because then
+ // other tests will see it as the real package.
+ // Instead we make a _test directory under the import path
+ // and then repeat the import path there. We tell the
+ // compiler and linker to look in that _test directory first.
+ //
+ // That is, if the package under test is unicode/utf8,
+ // then the normal place to write the package archive is
+ // $WORK/unicode/utf8.a, but we write the test package archive to
+ // $WORK/unicode/utf8/_test/unicode/utf8.a.
+ // We write the external test package archive to
+ // $WORK/unicode/utf8/_test/unicode/utf8_test.a.
+ testDir := filepath.Join(b.work, filepath.FromSlash(p.ImportPath+"/_test"))
+ ptestObj := buildToolchain.pkgpath(testDir, p)
+
+ // Create the directory for the .a files.
+ ptestDir, _ := filepath.Split(ptestObj)
+ if err := b.mkdir(ptestDir); err != nil {
+ return nil, nil, nil, err
+ }
+ if err := writeTestmain(filepath.Join(testDir, "_testmain.go"), p); err != nil {
+ return nil, nil, nil, err
+ }
+
+ // Test package.
+ if len(p.TestGoFiles) > 0 {
+ ptest = new(Package)
+ *ptest = *p
+ ptest.GoFiles = nil
+ ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...)
+ ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...)
+ ptest.target = ""
+ ptest.Imports = stringList(p.Imports, p.TestImports)
+ ptest.imports = append(append([]*Package{}, p.imports...), imports...)
+ ptest.pkgdir = testDir
+ ptest.fake = true
+ ptest.forceLibrary = true
+ ptest.Stale = true
+ ptest.build = new(build.Package)
+ *ptest.build = *p.build
+ m := map[string][]token.Position{}
+ for k, v := range p.build.ImportPos {
+ m[k] = append(m[k], v...)
+ }
+ for k, v := range p.build.TestImportPos {
+ m[k] = append(m[k], v...)
+ }
+ ptest.build.ImportPos = m
+ } else {
+ ptest = p
+ }
+
+ // External test package.
+ if len(p.XTestGoFiles) > 0 {
+ pxtest = &Package{
+ Name: p.Name + "_test",
+ ImportPath: p.ImportPath + "_test",
+ localPrefix: p.localPrefix,
+ Root: p.Root,
+ Dir: p.Dir,
+ GoFiles: p.XTestGoFiles,
+ Imports: p.XTestImports,
+ build: &build.Package{
+ ImportPos: p.build.XTestImportPos,
+ },
+ imports: append(ximports, ptest),
+ pkgdir: testDir,
+ fake: true,
+ Stale: true,
+ }
+ }
+
+ // Action for building pkg.test.
+ pmain = &Package{
+ Name: "main",
+ Dir: testDir,
+ GoFiles: []string{"_testmain.go"},
+ ImportPath: "testmain",
+ Root: p.Root,
+ imports: []*Package{ptest},
+ build: &build.Package{Name: "main"},
+ fake: true,
+ Stale: true,
+ }
+ if pxtest != nil {
+ pmain.imports = append(pmain.imports, pxtest)
+ }
+
+ // The generated main also imports testing and regexp.
+ stk.push("testmain")
+ ptesting := loadImport("testing", "", &stk, nil)
+ if ptesting.Error != nil {
+ return nil, nil, nil, ptesting.Error
+ }
+ pregexp := loadImport("regexp", "", &stk, nil)
+ if pregexp.Error != nil {
+ return nil, nil, nil, pregexp.Error
+ }
+ pmain.imports = append(pmain.imports, ptesting, pregexp)
+ computeStale(pmain)
+
+ if ptest != p {
+ a := b.action(modeBuild, modeBuild, ptest)
+ a.objdir = testDir + string(filepath.Separator)
+ a.objpkg = ptestObj
+ a.target = ptestObj
+ a.link = false
+ }
+
+ if pxtest != nil {
+ a := b.action(modeBuild, modeBuild, pxtest)
+ a.objdir = testDir + string(filepath.Separator)
+ a.objpkg = buildToolchain.pkgpath(testDir, pxtest)
+ a.target = a.objpkg
+ }
+
+ a := b.action(modeBuild, modeBuild, pmain)
+ a.objdir = testDir + string(filepath.Separator)
+ a.objpkg = filepath.Join(testDir, "main.a")
+ a.target = filepath.Join(testDir, testBinary) + exeSuffix
+ pmainAction := a
+
+ if testC {
+ // -c flag: create action to copy binary to ./test.out.
+ runAction = &action{
+ f: (*builder).install,
+ deps: []*action{pmainAction},
+ p: pmain,
+ target: testBinary + exeSuffix,
+ }
+ printAction = &action{p: p, deps: []*action{runAction}} // nop
+ } else {
+ // run test
+ runAction = &action{
+ f: (*builder).runTest,
+ deps: []*action{pmainAction},
+ p: p,
+ ignoreFail: true,
+ }
+ cleanAction := &action{
+ f: (*builder).cleanTest,
+ deps: []*action{runAction},
+ p: p,
+ }
+ printAction = &action{
+ f: (*builder).printTest,
+ deps: []*action{cleanAction},
+ p: p,
+ }
+ }
+
+ return pmainAction, runAction, printAction, nil
+}
+
+// runTest is the action for running a test binary.
+func (b *builder) runTest(a *action) error {
+ args := stringList(a.deps[0].target, testArgs)
+ a.testOutput = new(bytes.Buffer)
+
+ if buildN || buildX {
+ b.showcmd("", "%s", strings.Join(args, " "))
+ if buildN {
+ return nil
+ }
+ }
+
+ if a.failed {
+ // We were unable to build the binary.
+ a.failed = false
+ fmt.Fprintf(a.testOutput, "FAIL\t%s [build failed]\n", a.p.ImportPath)
+ setExitStatus(1)
+ return nil
+ }
+
+ cmd := exec.Command(args[0], args[1:]...)
+ cmd.Dir = a.p.Dir
+ var buf bytes.Buffer
+ if testStreamOutput {
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ } else {
+ cmd.Stdout = &buf
+ cmd.Stderr = &buf
+ }
+
+ t0 := time.Now()
+ err := cmd.Start()
+
+ // This is a last-ditch deadline to detect and
+ // stop wedged test binaries, to keep the builders
+ // running.
+ tick := time.NewTimer(testKillTimeout)
+ if err == nil {
+ done := make(chan error)
+ go func() {
+ done <- cmd.Wait()
+ }()
+ select {
+ case err = <-done:
+ // ok
+ case <-tick.C:
+ cmd.Process.Kill()
+ err = <-done
+ fmt.Fprintf(&buf, "*** Test killed: ran too long.\n")
+ }
+ tick.Stop()
+ }
+ out := buf.Bytes()
+ t1 := time.Now()
+ t := fmt.Sprintf("%.3fs", t1.Sub(t0).Seconds())
+ if err == nil {
+ if testShowPass {
+ a.testOutput.Write(out)
+ }
+ fmt.Fprintf(a.testOutput, "ok \t%s\t%s\n", a.p.ImportPath, t)
+ return nil
+ }
+
+ setExitStatus(1)
+ if len(out) > 0 {
+ a.testOutput.Write(out)
+ // assume printing the test binary's exit status is superfluous
+ } else {
+ fmt.Fprintf(a.testOutput, "%s\n", err)
+ }
+ fmt.Fprintf(a.testOutput, "FAIL\t%s\t%s\n", a.p.ImportPath, t)
+
+ return nil
+}
+
+// cleanTest is the action for cleaning up after a test.
+func (b *builder) cleanTest(a *action) error {
+ if buildWork {
+ return nil
+ }
+ run := a.deps[0]
+ testDir := filepath.Join(b.work, filepath.FromSlash(run.p.ImportPath+"/_test"))
+ os.RemoveAll(testDir)
+ return nil
+}
+
+// printTest is the action for printing a test result.
+func (b *builder) printTest(a *action) error {
+ clean := a.deps[0]
+ run := clean.deps[0]
+ os.Stdout.Write(run.testOutput.Bytes())
+ run.testOutput = nil
+ return nil
+}
+
+// notest is the action for testing a package with no test files.
+func (b *builder) notest(a *action) error {
+ fmt.Printf("? \t%s\t[no test files]\n", a.p.ImportPath)
+ return nil
+}
+
+// isTest tells whether name looks like a test (or benchmark, according to prefix).
+// It is a Test (say) if there is a character after Test that is not a lower-case letter.
+// We don't want TesticularCancer.
+func isTest(name, prefix string) bool {
+ if !strings.HasPrefix(name, prefix) {
+ return false
+ }
+ if len(name) == len(prefix) { // "Test" is ok
+ return true
+ }
+ rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
+ return !unicode.IsLower(rune)
+}
+
+// writeTestmain writes the _testmain.go file for package p to
+// the file named out.
+func writeTestmain(out string, p *Package) error {
+ t := &testFuncs{
+ Package: p,
+ }
+ for _, file := range p.TestGoFiles {
+ if err := t.load(filepath.Join(p.Dir, file), "_test", &t.NeedTest); err != nil {
+ return err
+ }
+ }
+ for _, file := range p.XTestGoFiles {
+ if err := t.load(filepath.Join(p.Dir, file), "_xtest", &t.NeedXtest); err != nil {
+ return err
+ }
+ }
+
+ f, err := os.Create(out)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ if err := testmainTmpl.Execute(f, t); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+type testFuncs struct {
+ Tests []testFunc
+ Benchmarks []testFunc
+ Examples []testFunc
+ Package *Package
+ NeedTest bool
+ NeedXtest bool
+}
+
+type testFunc struct {
+ Package string // imported package name (_test or _xtest)
+ Name string // function name
+ Output string // output, for examples
+}
+
+var testFileSet = token.NewFileSet()
+
+func (t *testFuncs) load(filename, pkg string, seen *bool) error {
+ f, err := parser.ParseFile(testFileSet, filename, nil, parser.ParseComments)
+ if err != nil {
+ return expandScanner(err)
+ }
+ for _, d := range f.Decls {
+ n, ok := d.(*ast.FuncDecl)
+ if !ok {
+ continue
+ }
+ if n.Recv != nil {
+ continue
+ }
+ name := n.Name.String()
+ switch {
+ case isTest(name, "Test"):
+ t.Tests = append(t.Tests, testFunc{pkg, name, ""})
+ *seen = true
+ case isTest(name, "Benchmark"):
+ t.Benchmarks = append(t.Benchmarks, testFunc{pkg, name, ""})
+ *seen = true
+ }
+ }
+ for _, e := range doc.Examples(f) {
+ if e.Output == "" {
+ // Don't run examples with no output.
+ continue
+ }
+ t.Examples = append(t.Examples, testFunc{pkg, "Example" + e.Name, e.Output})
+ *seen = true
+ }
+ return nil
+}
+
+var testmainTmpl = template.Must(template.New("main").Parse(`
+package main
+
+import (
+ "regexp"
+ "testing"
+
+{{if .NeedTest}}
+ _test {{.Package.ImportPath | printf "%q"}}
+{{end}}
+{{if .NeedXtest}}
+ _xtest {{.Package.ImportPath | printf "%s_test" | printf "%q"}}
+{{end}}
+)
+
+var tests = []testing.InternalTest{
+{{range .Tests}}
+ {"{{.Name}}", {{.Package}}.{{.Name}}},
+{{end}}
+}
+
+var benchmarks = []testing.InternalBenchmark{
+{{range .Benchmarks}}
+ {"{{.Name}}", {{.Package}}.{{.Name}}},
+{{end}}
+}
+
+var examples = []testing.InternalExample{
+{{range .Examples}}
+ {"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}},
+{{end}}
+}
+
+var matchPat string
+var matchRe *regexp.Regexp
+
+func matchString(pat, str string) (result bool, err error) {
+ if matchRe == nil || matchPat != pat {
+ matchPat = pat
+ matchRe, err = regexp.Compile(matchPat)
+ if err != nil {
+ return
+ }
+ }
+ return matchRe.MatchString(str), nil
+}
+
+func main() {
+ testing.Main(matchString, tests, benchmarks, examples)
+}
+
+`))