Files
moxa/cmd/yaegi/test.go
mpl 8916618a81 interp: API change for Symbols method
Often enough when debugging, one does not know exactly what argument
should be given to Symbols, as it's not always clear in which
scope/namespace the symbol one is looking for is stored in.

Therefore, this change enables the Symbols method to now take the empty
string as an argument, which results in all the known symbols to be
returned (keyed by import path).

As a consequence, when an non-empty argument is given, the returned
result should be similar to what we had before, except it is now
returned as the sole entry of an encompassing map.

In addition, the "binary" symbols (i.e. the ones ingested through a
Use call), are now also taken into account.
2020-10-15 10:02:04 +02:00

137 lines
3.7 KiB
Go

package main
import (
"errors"
"flag"
"fmt"
"go/build"
"os"
"regexp"
"strings"
"testing"
"github.com/traefik/yaegi/interp"
"github.com/traefik/yaegi/stdlib"
"github.com/traefik/yaegi/stdlib/syscall"
"github.com/traefik/yaegi/stdlib/unrestricted"
"github.com/traefik/yaegi/stdlib/unsafe"
)
func test(arg []string) (err error) {
var (
bench string
benchmem bool
benchtime string
count string
cpu string
failfast bool
run string
short bool
tags string
useUnrestricted bool
useUnsafe bool
useSyscall bool
timeout string
verbose bool
)
tflag := flag.NewFlagSet("test", flag.ContinueOnError)
tflag.StringVar(&bench, "bench", "", "Run only those benchmarks matching a regular expression.")
tflag.BoolVar(&benchmem, "benchmem", false, "Print memory allocation statistics for benchmarks.")
tflag.StringVar(&benchtime, "benchtime", "", "Run enough iterations of each benchmark to take t.")
tflag.StringVar(&count, "count", "", "Run each test and benchmark n times (default 1).")
tflag.StringVar(&cpu, "cpu", "", "Specify a list of GOMAXPROCS values for which the tests or benchmarks should be executed.")
tflag.BoolVar(&failfast, "failfast", false, "Do not start new tests after the first test failure.")
tflag.StringVar(&run, "run", "", "Run only those tests matching a regular expression.")
tflag.BoolVar(&short, "short", false, "Tell long-running tests to shorten their run time.")
tflag.StringVar(&tags, "tags", "", "Set a list of build tags.")
tflag.StringVar(&timeout, "timeout", "", "If a test binary runs longer than duration d, panic.")
tflag.BoolVar(&useUnrestricted, "unrestricted", false, "Include unrestricted symbols.")
tflag.BoolVar(&useUnsafe, "unsafe", false, "Include usafe symbols.")
tflag.BoolVar(&useSyscall, "syscall", false, "Include syscall symbols.")
tflag.BoolVar(&verbose, "v", false, "Verbose output: log all tests as they are run.")
tflag.Usage = func() {
fmt.Println("Usage: yaegi test [options] [path]")
fmt.Println("Options:")
tflag.PrintDefaults()
}
if err = tflag.Parse(arg); err != nil {
return err
}
args := tflag.Args()
path := "."
if len(args) > 0 {
path = args[0]
}
// Overwrite os.Args with correct flags to setup testing.Init.
tf := []string{""}
if bench != "" {
tf = append(tf, "-test.bench", bench)
}
if benchmem {
tf = append(tf, "-test.benchmem")
}
if benchtime != "" {
tf = append(tf, "-test.benchtime", benchtime)
}
if count != "" {
tf = append(tf, "-test.count", count)
}
if cpu != "" {
tf = append(tf, "-test.cpu", cpu)
}
if failfast {
tf = append(tf, "-test.failfast")
}
if run != "" {
tf = append(tf, "-test.run", run)
}
if short {
tf = append(tf, "-test.short")
}
if timeout != "" {
tf = append(tf, "-test.timeout", timeout)
}
if verbose {
tf = append(tf, "-test.v")
}
testing.Init()
os.Args = tf
flag.Parse()
i := interp.New(interp.Options{GoPath: build.Default.GOPATH, BuildTags: strings.Split(tags, ",")})
i.Use(stdlib.Symbols)
i.Use(interp.Symbols)
if useSyscall {
i.Use(syscall.Symbols)
}
if useUnrestricted {
i.Use(unrestricted.Symbols)
}
if useUnsafe {
i.Use(unsafe.Symbols)
}
if err = i.EvalTest(path); err != nil {
return err
}
benchmarks := []testing.InternalBenchmark{}
tests := []testing.InternalTest{}
syms, ok := i.Symbols(path)[path]
if !ok {
return errors.New("No tests found")
}
for name, sym := range syms {
switch fun := sym.Interface().(type) {
case func(*testing.B):
benchmarks = append(benchmarks, testing.InternalBenchmark{name, fun})
case func(*testing.T):
tests = append(tests, testing.InternalTest{name, fun})
}
}
testing.Main(regexp.MatchString, tests, benchmarks, nil)
return nil
}