mirror of
https://github.com/golang/go
synced 2024-11-20 04:14:49 -07:00
ead08e91f6
For example, testing the current directory: $ go test -run XXX testing: warning: no tests to run PASS ok testing 0.013s $ And in a summary: $ go test -run XXX testing ok testing 0.013s [no tests to run] $ These make it easy to spot when the -run regexp hasn't matched anything or there are no tests. Previously the message was printed in the "current directory" case when there were no tests at all, but not for no matches, and either way was not surfaced in the directory list summary form. Fixes #15211. Change-Id: I1c82a423d6bd429fb991c9ca964c9d26c96fd3c5 Reviewed-on: https://go-review.googlesource.com/22341 Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
125 lines
2.5 KiB
Go
125 lines
2.5 KiB
Go
// 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 (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type InternalExample struct {
|
|
Name string
|
|
F func()
|
|
Output string
|
|
Unordered bool
|
|
}
|
|
|
|
// An internal function but exported because it is cross-package; part of the implementation
|
|
// of the "go test" command.
|
|
func RunExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ok bool) {
|
|
_, ok = runExamples(matchString, examples)
|
|
return ok
|
|
}
|
|
|
|
func runExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ran, ok bool) {
|
|
ok = true
|
|
|
|
var eg InternalExample
|
|
|
|
for _, eg = range examples {
|
|
matched, err := matchString(*match, eg.Name)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "testing: invalid regexp for -test.run: %s\n", err)
|
|
os.Exit(1)
|
|
}
|
|
if !matched {
|
|
continue
|
|
}
|
|
ran = true
|
|
if !runExample(eg) {
|
|
ok = false
|
|
}
|
|
}
|
|
|
|
return ran, ok
|
|
}
|
|
|
|
func sortLines(output string) string {
|
|
lines := strings.Split(output, "\n")
|
|
sort.Strings(lines)
|
|
return strings.Join(lines, "\n")
|
|
}
|
|
|
|
func runExample(eg InternalExample) (ok bool) {
|
|
if *chatty {
|
|
fmt.Printf("=== RUN %s\n", eg.Name)
|
|
}
|
|
|
|
// 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() {
|
|
var buf bytes.Buffer
|
|
_, err := io.Copy(&buf, r)
|
|
r.Close()
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "testing: copying pipe: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
outC <- buf.String()
|
|
}()
|
|
|
|
start := time.Now()
|
|
ok = true
|
|
|
|
// Clean up in a deferred call so we can recover if the example panics.
|
|
defer func() {
|
|
dstr := fmtDuration(time.Now().Sub(start))
|
|
|
|
// Close pipe, restore stdout, get output.
|
|
w.Close()
|
|
os.Stdout = stdout
|
|
out := <-outC
|
|
|
|
var fail string
|
|
err := recover()
|
|
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)
|
|
}
|
|
}
|
|
if fail != "" || err != nil {
|
|
fmt.Printf("--- FAIL: %s (%s)\n%s", eg.Name, dstr, fail)
|
|
ok = false
|
|
} else if *chatty {
|
|
fmt.Printf("--- PASS: %s (%s)\n", eg.Name, dstr)
|
|
}
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}()
|
|
|
|
// Run example.
|
|
eg.F()
|
|
return
|
|
}
|