2011-10-06 12:56:17 -06:00
|
|
|
// 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.
|
|
|
|
|
|
|
|
package testing
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"os"
|
2016-02-05 14:16:31 -07:00
|
|
|
"sort"
|
2011-12-15 15:43:58 -07:00
|
|
|
"strings"
|
2011-10-06 12:56:17 -06:00
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type InternalExample struct {
|
2016-02-05 14:16:31 -07:00
|
|
|
Name string
|
|
|
|
F func()
|
|
|
|
Output string
|
|
|
|
Unordered bool
|
2011-10-06 12:56:17 -06:00
|
|
|
}
|
|
|
|
|
2016-04-20 11:29:30 -06:00
|
|
|
// An internal function but exported because it is cross-package; part of the implementation
|
|
|
|
// of the "go test" command.
|
2012-02-26 18:49:10 -07:00
|
|
|
func RunExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ok bool) {
|
2016-04-20 11:29:30 -06:00
|
|
|
_, ok = runExamples(matchString, examples)
|
|
|
|
return ok
|
|
|
|
}
|
|
|
|
|
|
|
|
func runExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ran, ok bool) {
|
2011-10-06 12:56:17 -06:00
|
|
|
ok = true
|
|
|
|
|
2011-11-15 11:09:19 -07:00
|
|
|
var eg InternalExample
|
|
|
|
|
|
|
|
for _, eg = range examples {
|
2012-02-27 14:33:06 -07:00
|
|
|
matched, err := matchString(*match, eg.Name)
|
2012-02-26 18:49:10 -07:00
|
|
|
if err != nil {
|
2012-02-27 14:33:06 -07:00
|
|
|
fmt.Fprintf(os.Stderr, "testing: invalid regexp for -test.run: %s\n", err)
|
2012-02-26 18:49:10 -07:00
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
if !matched {
|
|
|
|
continue
|
|
|
|
}
|
2016-04-20 11:29:30 -06:00
|
|
|
ran = true
|
2013-01-17 16:28:18 -07:00
|
|
|
if !runExample(eg) {
|
|
|
|
ok = false
|
2011-10-06 12:56:17 -06:00
|
|
|
}
|
2013-01-17 16:28:18 -07:00
|
|
|
}
|
|
|
|
|
2016-04-20 11:29:30 -06:00
|
|
|
return ran, ok
|
2013-01-17 16:28:18 -07:00
|
|
|
}
|
|
|
|
|
2016-02-05 14:16:31 -07:00
|
|
|
func sortLines(output string) string {
|
|
|
|
lines := strings.Split(output, "\n")
|
|
|
|
sort.Strings(lines)
|
|
|
|
return strings.Join(lines, "\n")
|
|
|
|
}
|
|
|
|
|
2013-01-17 16:28:18 -07:00
|
|
|
func runExample(eg InternalExample) (ok bool) {
|
|
|
|
if *chatty {
|
2015-05-08 12:00:17 -06:00
|
|
|
fmt.Printf("=== RUN %s\n", eg.Name)
|
2013-01-17 16:28:18 -07:00
|
|
|
}
|
2011-10-06 12:56:17 -06:00
|
|
|
|
2013-01-17 16:28:18 -07:00
|
|
|
// Capture stdout.
|
|
|
|
stdout := os.Stdout
|
|
|
|
r, w, err := os.Pipe()
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintln(os.Stderr, err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
os.Stdout = w
|
|
|
|
outC := make(chan string)
|
|
|
|
go func() {
|
2018-03-26 00:56:39 -06:00
|
|
|
var buf strings.Builder
|
2014-12-19 18:31:16 -07:00
|
|
|
_, err := io.Copy(&buf, r)
|
2013-01-17 16:28:18 -07:00
|
|
|
r.Close()
|
2011-10-06 12:56:17 -06:00
|
|
|
if err != nil {
|
2013-01-17 16:28:18 -07:00
|
|
|
fmt.Fprintf(os.Stderr, "testing: copying pipe: %v\n", err)
|
2011-10-06 12:56:17 -06:00
|
|
|
os.Exit(1)
|
|
|
|
}
|
2013-01-17 16:28:18 -07:00
|
|
|
outC <- buf.String()
|
|
|
|
}()
|
2011-10-06 12:56:17 -06:00
|
|
|
|
2013-01-17 16:28:18 -07:00
|
|
|
start := time.Now()
|
2013-01-17 18:25:41 -07:00
|
|
|
ok = true
|
2011-10-06 12:56:17 -06:00
|
|
|
|
2013-01-17 16:28:18 -07:00
|
|
|
// Clean up in a deferred call so we can recover if the example panics.
|
|
|
|
defer func() {
|
2017-09-06 13:13:06 -06:00
|
|
|
dstr := fmtDuration(time.Since(start))
|
2013-01-17 16:28:18 -07:00
|
|
|
|
|
|
|
// Close pipe, restore stdout, get output.
|
2011-10-06 12:56:17 -06:00
|
|
|
w.Close()
|
2012-12-19 16:48:33 -07:00
|
|
|
os.Stdout = stdout
|
2011-10-06 12:56:17 -06:00
|
|
|
out := <-outC
|
|
|
|
|
2013-01-17 16:28:18 -07:00
|
|
|
var fail string
|
|
|
|
err := recover()
|
2016-02-05 14:16:31 -07:00
|
|
|
got := strings.TrimSpace(out)
|
|
|
|
want := strings.TrimSpace(eg.Output)
|
|
|
|
if eg.Unordered {
|
|
|
|
if sortLines(got) != sortLines(want) && err == nil {
|
|
|
|
fail = fmt.Sprintf("got:\n%s\nwant (unordered):\n%s\n", out, eg.Output)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if got != want && err == nil {
|
|
|
|
fail = fmt.Sprintf("got:\n%s\nwant:\n%s\n", got, want)
|
|
|
|
}
|
2013-01-17 16:28:18 -07:00
|
|
|
}
|
|
|
|
if fail != "" || err != nil {
|
2014-06-18 11:59:25 -06:00
|
|
|
fmt.Printf("--- FAIL: %s (%s)\n%s", eg.Name, dstr, fail)
|
2013-01-17 18:25:41 -07:00
|
|
|
ok = false
|
2011-10-06 12:56:17 -06:00
|
|
|
} else if *chatty {
|
2014-06-18 11:59:25 -06:00
|
|
|
fmt.Printf("--- PASS: %s (%s)\n", eg.Name, dstr)
|
2011-10-06 12:56:17 -06:00
|
|
|
}
|
2013-01-17 16:28:18 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}()
|
2011-10-06 12:56:17 -06:00
|
|
|
|
2013-01-17 16:28:18 -07:00
|
|
|
// Run example.
|
|
|
|
eg.F()
|
2011-10-06 12:56:17 -06:00
|
|
|
return
|
|
|
|
}
|