Documentation ¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var Deps = []string{
"bytes",
"flag",
"fmt",
"io",
"os",
"os/exec",
"path",
"sort",
"strconv",
"testing",
"testing/internal/testdeps",
"time",
}
View Source
var Template = template.Must(template.New("").Parse(`// Code generated by 'gophertest'. DO NOT EDIT.
package main
import (
"bytes"
"flag"
"fmt"
"io"
"os"
"os/exec"
"path"
"sort"
"strconv"
"testing"
"testing/internal/testdeps"
"time"
{{range .Targets}}
{{if .ImportTest}}
{{.TestName}} {{.ImportPath | printf "%q"}}
{{end}}
{{if .ImportXTest}}
{{.XTestName}} {{.ImportPath | printf "%s_test" | printf "%q"}}
{{end}}
{{end}}
)
const pkgEnvName = "GOPHERTEST_PKG"
const concurrentEnvName = "GOPHERTEST_CONCURRENT"
type target struct {
name string
importPath string
directory string
tests []testing.InternalTest
benchmarks []testing.InternalBenchmark
examples []testing.InternalExample
initFunc func()
xInitFunc func()
testMain func(*testing.M)
complexity int64
}
var selectedTarget *target
var targets = []target{
{{range .Targets}}
target{
name: {{.Name | printf "%q"}},
importPath: {{.ImportPath | printf "%q"}},
directory: {{.Directory | printf "%q"}},
initFunc: {{.InitFunc}},
xInitFunc: {{.XInitFunc}},
testMain: {{.Main}},
complexity: {{.TestComplexity}},
tests: []testing.InternalTest{
{{range .Tests}}
{"{{.Name}}", {{.Package}}.{{.Name}}},
{{end}}
},
benchmarks: []testing.InternalBenchmark{
{{range .Benchmarks}}
{"{{.Name}}", {{.Package}}.{{.Name}}},
{{end}}
},
},
{{end}}
}
func init() {
var err error
pkg := os.Getenv(pkgEnvName)
if pkg == "" {
bin := os.Args[0]
binDir := path.Dir(bin)
for _, t := range targets {
if binDir == t.directory {
selectedTarget = &t
break
}
}
}
if selectedTarget == nil && pkg == "" {
concurrent := 1
if s := os.Getenv(concurrentEnvName); s != "" {
concurrent, err = strconv.Atoi(s)
if err != nil {
fmt.Fprintf(os.Stderr, "error parsing %q: %v", concurrentEnvName, err)
os.Exit(1)
}
}
fs := flag.NewFlagSet("gophertest", flag.ExitOnError)
fs.IntVar(&concurrent, "c", concurrent, "test concurrency")
fs.Usage = func() {
fmt.Fprintf(fs.Output(), "gophertest: all arguments after -- are passed to the tests\n")
fs.PrintDefaults()
}
fs.Parse(os.Args[1:])
args := fs.Args()
if concurrent < 0 {
concurrent = 1
}
if concurrent > 1 {
sort.Slice(targets, func(i, j int) bool {
// Sort from most complex to least.
return targets[i].complexity > targets[j].complexity
})
}
all(concurrent, args)
}
if selectedTarget == nil && pkg != "" {
for _, t := range targets {
if t.importPath == pkg {
selectedTarget = &t
break
}
}
}
if selectedTarget == nil {
selectedTarget = &target{
importPath: pkg,
initFunc: func(){},
xInitFunc: func(){},
testMain: defaultMain,
}
}
testdeps.ImportPath = selectedTarget.importPath
}
func defaultMain(m *testing.M) {
os.Exit(m.Run())
}
func main() {
selectedTarget.initFunc()
selectedTarget.xInitFunc()
m := testing.MainStart(testdeps.TestDeps{}, selectedTarget.tests, selectedTarget.benchmarks, nil)
selectedTarget.testMain(m)
}
func all(concurrent int, args []string) {
bin := os.Args[0]
if !path.IsAbs(bin) {
cwd, err := os.Getwd()
if err != nil {
fmt.Fprintf(os.Stderr, "%v", err)
os.Exit(1)
}
bin = path.Join(cwd, bin)
}
slot := make(chan struct{}, concurrent)
for i := 0; i < concurrent; i++ {
slot <- struct{}{}
}
mutex := make(chan struct{}, 1)
mutex <- struct{}{}
exitCode := 0
for _, v := range targets {
t := v
<-slot
os.Setenv(pkgEnvName, t.importPath)
cmdArgs := []string{}
for _, arg := range args {
cmdArgs = append(cmdArgs, os.ExpandEnv(arg))
}
wd, err := os.Stat(t.directory)
if err != nil {
fmt.Fprintf(os.Stderr, "%v", err)
os.Exit(1)
} else if !wd.IsDir() {
fmt.Fprintf(os.Stderr, "%q is not a directory", t.directory)
os.Exit(1)
}
testBin := path.Join(t.directory, fmt.Sprintf("%s.test", t.name))
_, err = os.Stat(testBin)
if os.IsNotExist(err) {
} else if err != nil {
fmt.Fprintf(os.Stderr, "%v", err)
os.Exit(1)
} else {
err = os.Remove(testBin)
if err != nil {
fmt.Fprintf(os.Stderr, "%v", err)
os.Exit(1)
}
}
err = os.Symlink(bin, testBin)
if err != nil {
fmt.Fprintf(os.Stderr, "%v", err)
os.Exit(1)
}
cmd := exec.Command(testBin, cmdArgs...)
cmd.Dir = t.directory
cmd.Env = os.Environ()
buffer := &bytes.Buffer{}
if concurrent == 1 {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
} else {
cmd.Stdout = buffer
cmd.Stderr = buffer
}
go func() {
defer func() {
err := os.Remove(testBin)
if err != nil {
fmt.Fprintf(os.Stderr, "%v", err)
os.Exit(1)
}
}()
start := time.Now()
err := cmd.Run()
failed := false
if exitErr, ok := err.(*exec.ExitError); ok {
failed = exitErr.ExitCode() != 0
} else if err != nil {
fmt.Fprintf(os.Stderr, "%v", err)
os.Exit(1)
}
duration := time.Since(start).Round(time.Millisecond)
<-mutex
status := "ok"
if failed {
status = "fail"
exitCode++
}
_, err = io.Copy(os.Stdout, buffer)
if err != nil {
fmt.Fprintf(os.Stderr, "%v", err)
os.Exit(1)
}
fmt.Fprintf(os.Stdout, "%-4s\t%s\t%.3fs\n", status, t.importPath, duration.Seconds())
mutex <- struct{}{}
slot <- struct{}{}
}()
}
for i := 0; i < concurrent; i++ {
<-slot
}
os.Exit(exitCode)
}
`))
Functions ¶
This section is empty.
Types ¶
Click to show internal directories.
Click to hide internal directories.