feature: test subcommand to run test and benchmark functions

This change allows the interpreter to execute tests and benchmarks
functions provided by packages.

The test subcommand is similar to the "go test" command and
all the relevant flags have been kept.

The ability to evaluate a directory or a package has also been added.

A new method Symbol to access exported symbol values of an interpreted
package has been added. This method is used by the test subcommand.

An EvalTest method has been added to evaluate all Go files, including "*_test.go".

The testing packages from the standard library have been added to stdlib used
symbols.
This commit is contained in:
Marc Vertes
2020-09-14 11:14:04 +02:00
committed by GitHub
parent f1f3ca7e06
commit 151699ef9f
21 changed files with 577 additions and 79 deletions

14
_test/m1/main.go Normal file
View File

@@ -0,0 +1,14 @@
package main
import (
"fmt"
"testing"
)
func main() {
fmt.Println("vim-go")
}
func TestWeird(t *testing.T) {
fmt.Println("in TestWeird")
}

17
_test/m1/main_test.go Normal file
View File

@@ -0,0 +1,17 @@
package main
import (
"fmt"
"math/rand"
"testing"
)
func TestMain(t *testing.T) {
fmt.Println("in test")
}
func BenchmarkMain(b *testing.B) {
for i := 0; i < b.N; i++ {
rand.Int()
}
}

View File

@@ -108,9 +108,9 @@ func main() {
var oFile string
if pkgIdent == "syscall" {
oFile = strings.Replace(importPath, "/", "_", -1) + "_" + goos + "_" + goarch + ".go"
oFile = strings.ReplaceAll(importPath, "/", "_") + "_" + goos + "_" + goarch + ".go"
} else {
oFile = strings.Replace(importPath, "/", "_", -1) + ".go"
oFile = strings.ReplaceAll(importPath, "/", "_") + ".go"
}
prefix := runtime.Version()

View File

@@ -58,7 +58,7 @@ func extractCmd(arg []string) error {
continue
}
oFile := strings.Replace(importPath, "/", "_", -1) + ".go"
oFile := strings.ReplaceAll(importPath, "/", "_") + ".go"
f, err := os.Create(oFile)
if err != nil {
return err

View File

@@ -36,7 +36,7 @@ func help(arg []string) error {
case Run:
return run([]string{"-h"})
case Test:
return fmt.Errorf("help: test not implemented")
return test([]string{"-h"})
default:
return fmt.Errorf("help: invalid yaegi command: %v", cmd)
}

View File

@@ -57,11 +57,13 @@ func run(arg []string) error {
if cmd != "" {
_, err = i.Eval(cmd)
showError(err)
}
if len(args) == 0 {
if interactive || cmd == "" {
_, err = i.REPL()
showError(err)
}
return err
}
@@ -71,40 +73,27 @@ func run(arg []string) error {
os.Args = arg[1:]
flag.CommandLine = flag.NewFlagSet(path, flag.ExitOnError)
if isPackageName(path) {
err = runPackage(i, path)
if isFile(path) {
err = runFile(i, path)
} else {
if isDir(path) {
err = runDir(i, path)
} else {
err = runFile(i, path)
}
_, err = i.EvalPath(path)
}
showError(err)
if err != nil {
return err
}
if interactive {
_, err = i.REPL()
showError(err)
}
return err
}
func isPackageName(path string) bool {
return !strings.HasPrefix(path, "/") && !strings.HasPrefix(path, "./") && !strings.HasPrefix(path, "../") && !strings.HasSuffix(path, ".go")
}
func isDir(path string) bool {
fi, err := os.Lstat(path)
return err == nil && fi.IsDir()
}
func runPackage(i *interp.Interpreter, path string) error {
return fmt.Errorf("runPackage not implemented")
}
func runDir(i *interp.Interpreter, path string) error {
return fmt.Errorf("runDir not implemented")
func isFile(path string) bool {
fi, err := os.Stat(path)
return err == nil && fi.Mode().IsRegular()
}
func runFile(i *interp.Interpreter, path string) error {
@@ -117,15 +106,20 @@ func runFile(i *interp.Interpreter, path string) error {
// Allow executable go scripts, Have the same behavior as in interactive mode.
s = strings.Replace(s, "#!", "//", 1)
_, err = i.Eval(s)
} else {
// Files not starting with "#!" are supposed to be pure Go, directly Evaled.
_, err := i.EvalPath(path)
if err != nil {
fmt.Println(err)
if p, ok := err.(interp.Panic); ok {
fmt.Println(string(p.Stack))
}
}
return err
}
// Files not starting with "#!" are supposed to be pure Go, directly Evaled.
_, err = i.EvalPath(path)
return err
}
func showError(err error) {
if err == nil {
return
}
fmt.Fprintln(os.Stderr, err)
if p, ok := err.(interp.Panic); ok {
fmt.Fprintln(os.Stderr, string(p.Stack))
}
}

131
cmd/yaegi/test.go Normal file
View File

@@ -0,0 +1,131 @@
package main
import (
"flag"
"fmt"
"go/build"
"os"
"regexp"
"strings"
"testing"
"github.com/containous/yaegi/interp"
"github.com/containous/yaegi/stdlib"
"github.com/containous/yaegi/stdlib/syscall"
"github.com/containous/yaegi/stdlib/unrestricted"
"github.com/containous/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{}
for name, sym := range i.Symbols(path) {
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
}

View File

@@ -118,7 +118,7 @@ func main() {
case Run:
err = run(os.Args[2:])
case Test:
err = fmt.Errorf("test not implemented")
err = test(os.Args[2:])
default:
// If no command is given, fallback to default "run" command.
// This allows scripts starting with "#!/usr/bin/env yaegi",

View File

@@ -5,6 +5,7 @@ import (
"go/build"
"go/parser"
"path"
"path/filepath"
"strconv"
"strings"
)
@@ -129,12 +130,15 @@ func goMinorVersion(ctx *build.Context) int {
}
// skipFile returns true if file should be skipped.
func skipFile(ctx *build.Context, p string) bool {
func skipFile(ctx *build.Context, p string, skipTest bool) bool {
if !strings.HasSuffix(p, ".go") {
return true
}
p = strings.TrimSuffix(path.Base(p), ".go")
if strings.HasSuffix(p, "_test") {
if pp := filepath.Base(p); strings.HasPrefix(pp, "_") || strings.HasPrefix(pp, ".") {
return true
}
if skipTest && strings.HasSuffix(p, "_test") {
return true
}
i := strings.Index(p, "_")

View File

@@ -74,7 +74,7 @@ func TestBuildFile(t *testing.T) {
for _, test := range tests {
test := test
t.Run(test.src, func(t *testing.T) {
if r := skipFile(&ctx, test.src); r != test.res {
if r := skipFile(&ctx, test.src, NoTest); r != test.res {
t.Errorf("got %v, want %v", r, test.res)
}
})

View File

@@ -19,7 +19,7 @@ func (n *node) astDot(out io.Writer, name string) {
var label string
switch n.kind {
case basicLit, identExpr:
label = strings.Replace(n.ident, "\"", "\\\"", -1)
label = strings.ReplaceAll(n.ident, "\"", "\\\"")
default:
if n.action != aNop {
label = n.action.String()

View File

@@ -216,7 +216,7 @@ func (interp *Interpreter) gta(root *node, rpath, importPath string) ([]*node, e
err = n.cfgErrorf("%s redeclared in this block", name)
return false
}
} else if pkgName, err = interp.importSrc(rpath, ipath); err == nil {
} else if pkgName, err = interp.importSrc(rpath, ipath, NoTest); err == nil {
sc.types = interp.universe.types
switch name {
case "_": // no import of symbols

View File

@@ -157,6 +157,11 @@ const (
// source file has not been specified for an Eval.
// TODO(mpl): something even more special as a name?
DefaultSourceName = "_.go"
// Test is the value to pass to EvalPath to activate evaluation of test functions.
Test = false
// NoTest is the value to pass to EvalPath to skip evaluation of test functions.
NoTest = true
)
// Symbols exposes interpreter values.
@@ -361,25 +366,21 @@ func (interp *Interpreter) resizeFrame() {
interp.frame.data = data
}
func (interp *Interpreter) main() *node {
interp.mutex.RLock()
defer interp.mutex.RUnlock()
if m, ok := interp.scopes[mainID]; ok && m.sym[mainID] != nil {
return m.sym[mainID].node
}
return nil
}
// Eval evaluates Go code represented as a string. Eval returns the last result
// computed by the interpreter, and a non nil error in case of failure.
func (interp *Interpreter) Eval(src string) (res reflect.Value, err error) {
return interp.eval(src, "", true)
}
// EvalPath evaluates Go code located at path. EvalPath returns the last result
// computed by the interpreter, and a non nil error in case of failure.
// EvalPath evaluates Go code located at path and returns the last result computed
// by the interpreter, and a non nil error in case of failure.
// The main function of the main package is executed if present.
func (interp *Interpreter) EvalPath(path string) (res reflect.Value, err error) {
// TODO(marc): implement eval of a directory, package and tests.
if !isFile(path) {
_, err := interp.importSrc(mainID, path, NoTest)
return res, err
}
b, err := ioutil.ReadFile(path)
if err != nil {
return res, err
@@ -387,6 +388,49 @@ func (interp *Interpreter) EvalPath(path string) (res reflect.Value, err error)
return interp.eval(string(b), path, false)
}
// EvalTest evaluates Go code located at path, including test files with "_test.go" suffix.
// A non nil error is returned in case of failure.
// The main function, test functions and benchmark functions are internally compiled but not
// executed. Test functions can be retrieved using the Symbol() method.
func (interp *Interpreter) EvalTest(path string) error {
_, err := interp.importSrc(mainID, path, Test)
return err
}
// Symbols returns a map of interpreter exported symbol values for the given path.
func (interp *Interpreter) Symbols(path string) map[string]reflect.Value {
m := map[string]reflect.Value{}
interp.mutex.RLock()
if interp.scopes[path] == nil {
interp.mutex.RUnlock()
return m
}
sym := interp.scopes[path].sym
interp.mutex.RUnlock()
for n, s := range sym {
if !canExport(n) {
// Skip private non-exported symbols.
continue
}
switch s.kind {
case constSym:
m[n] = s.rval
case funcSym:
m[n] = genFunctionWrapper(s.node)(interp.frame)
case varSym:
m[n] = interp.frame.data[s.index]
}
}
return m
}
func isFile(path string) bool {
fi, err := os.Stat(path)
return err == nil && fi.Mode().IsRegular()
}
func (interp *Interpreter) eval(src, name string, inc bool) (res reflect.Value, err error) {
if name != "" {
interp.name = name
@@ -426,7 +470,7 @@ func (interp *Interpreter) eval(src, name string, inc bool) (res reflect.Value,
return res, err
}
// Annotate AST with CFG infos
// Annotate AST with CFG informations.
initNodes, err := interp.cfg(root, pkgName)
if err != nil {
if interp.cfgDot {
@@ -439,25 +483,25 @@ func (interp *Interpreter) eval(src, name string, inc bool) (res reflect.Value,
return res, err
}
// Add main to list of functions to run, after all inits
if m := interp.main(); m != nil {
initNodes = append(initNodes, m)
}
if root.kind != fileStmt {
// REPL may skip package statement
// REPL may skip package statement.
setExec(root.start)
}
interp.mutex.Lock()
gs := interp.scopes[pkgName]
if interp.universe.sym[pkgName] == nil {
// Make the package visible under a path identical to its name
// TODO(mpl): srcPkg is supposed to be keyed by importPath. Verify it is necessary, and implement.
interp.srcPkg[pkgName] = interp.scopes[pkgName].sym
// Make the package visible under a path identical to its name.
interp.srcPkg[pkgName] = gs.sym
interp.universe.sym[pkgName] = &symbol{kind: pkgSym, typ: &itype{cat: srcPkgT, path: pkgName}}
interp.pkgNames[pkgName] = pkgName
}
interp.mutex.Unlock()
// Add main to list of functions to run, after all inits.
if m := gs.sym[mainID]; pkgName == mainID && m != nil {
initNodes = append(initNodes, m.node)
}
if interp.cfgDot {
dotCmd := interp.dotCmd
if dotCmd == "" {
@@ -470,21 +514,21 @@ func (interp *Interpreter) eval(src, name string, inc bool) (res reflect.Value,
return res, err
}
// Generate node exec closures
// Generate node exec closures.
if err = genRun(root); err != nil {
return res, err
}
// Init interpreter execution memory frame
// Init interpreter execution memory frame.
interp.frame.setrunid(interp.runid())
interp.frame.mutex.Lock()
interp.resizeFrame()
interp.frame.mutex.Unlock()
// Execute node closures
// Execute node closures.
interp.run(root, nil)
// Wire and execute global vars
// Wire and execute global vars.
n, err := genGlobalVars([]*node{root}, interp.scopes[pkgName])
if err != nil {
return res, err
@@ -497,7 +541,7 @@ func (interp *Interpreter) eval(src, name string, inc bool) (res reflect.Value,
v := genValue(root)
res = v(interp.frame)
// If result is an interpreter node, wrap it in a runtime callable function
// If result is an interpreter node, wrap it in a runtime callable function.
if res.IsValid() {
if n, ok := res.Interface().(*node); ok {
res = genFunctionWrapper(n)(interp.frame)

View File

@@ -11,7 +11,7 @@ import (
// importSrc calls gta on the source code for the package identified by
// importPath. rPath is the relative path to the directory containing the source
// code for the package. It can also be "main" as a special value.
func (interp *Interpreter) importSrc(rPath, importPath string) (string, error) {
func (interp *Interpreter) importSrc(rPath, importPath string, skipTest bool) (string, error) {
var dir string
var err error
@@ -68,7 +68,7 @@ func (interp *Interpreter) importSrc(rPath, importPath string) (string, error) {
// Parse source files.
for _, file := range files {
name := file.Name()
if skipFile(&interp.context, name) {
if skipFile(&interp.context, name, skipTest) {
continue
}
@@ -95,7 +95,7 @@ func (interp *Interpreter) importSrc(rPath, importPath string) (string, error) {
}
if pkgName == "" {
pkgName = pname
} else if pkgName != pname {
} else if pkgName != pname && skipTest {
return "", fmt.Errorf("found packages %s and %s in %s", pkgName, pname, dir)
}
rootNodes = append(rootNodes, root)
@@ -116,7 +116,7 @@ func (interp *Interpreter) importSrc(rPath, importPath string) (string, error) {
}
}
// Generate control flow graphs
// Generate control flow graphs.
for _, root := range rootNodes {
var nodes []*node
if nodes, err = interp.cfg(root, importPath); err != nil {
@@ -128,7 +128,8 @@ func (interp *Interpreter) importSrc(rPath, importPath string) (string, error) {
// Register source package in the interpreter. The package contains only
// the global symbols in the package scope.
interp.mutex.Lock()
interp.srcPkg[importPath] = interp.scopes[importPath].sym
gs := interp.scopes[importPath]
interp.srcPkg[importPath] = gs.sym
interp.pkgNames[importPath] = pkgName
interp.frame.mutex.Lock()
@@ -136,7 +137,7 @@ func (interp *Interpreter) importSrc(rPath, importPath string) (string, error) {
interp.frame.mutex.Unlock()
interp.mutex.Unlock()
// Once all package sources have been parsed, execute entry points then init functions
// Once all package sources have been parsed, execute entry points then init functions.
for _, n := range rootNodes {
if err = genRun(n); err != nil {
return "", err
@@ -144,16 +145,16 @@ func (interp *Interpreter) importSrc(rPath, importPath string) (string, error) {
interp.run(n, nil)
}
// Wire and execute global vars
n, err := genGlobalVars(rootNodes, interp.scopes[importPath])
// Wire and execute global vars in global scope gs.
n, err := genGlobalVars(rootNodes, gs)
if err != nil {
return "", err
}
interp.run(n, nil)
// Add main to list of functions to run, after all inits
if m := interp.main(); m != nil {
initNodes = append(initNodes, m)
// Add main to list of functions to run, after all inits.
if m := gs.sym[mainID]; pkgName == mainID && m != nil && skipTest {
initNodes = append(initNodes, m.node)
}
for _, n := range initNodes {

82
stdlib/go1_14_testing.go Normal file
View File

@@ -0,0 +1,82 @@
// Code generated by 'github.com/containous/yaegi/extract testing'. DO NOT EDIT.
// +build go1.14,!go1.15
package stdlib
import (
"reflect"
"testing"
)
func init() {
Symbols["testing"] = map[string]reflect.Value{
// function, constant and variable definitions
"AllocsPerRun": reflect.ValueOf(testing.AllocsPerRun),
"Benchmark": reflect.ValueOf(testing.Benchmark),
"CoverMode": reflect.ValueOf(testing.CoverMode),
"Coverage": reflect.ValueOf(testing.Coverage),
"Init": reflect.ValueOf(testing.Init),
"Main": reflect.ValueOf(testing.Main),
"MainStart": reflect.ValueOf(testing.MainStart),
"RegisterCover": reflect.ValueOf(testing.RegisterCover),
"RunBenchmarks": reflect.ValueOf(testing.RunBenchmarks),
"RunExamples": reflect.ValueOf(testing.RunExamples),
"RunTests": reflect.ValueOf(testing.RunTests),
"Short": reflect.ValueOf(testing.Short),
"Verbose": reflect.ValueOf(testing.Verbose),
// type definitions
"B": reflect.ValueOf((*testing.B)(nil)),
"BenchmarkResult": reflect.ValueOf((*testing.BenchmarkResult)(nil)),
"Cover": reflect.ValueOf((*testing.Cover)(nil)),
"CoverBlock": reflect.ValueOf((*testing.CoverBlock)(nil)),
"InternalBenchmark": reflect.ValueOf((*testing.InternalBenchmark)(nil)),
"InternalExample": reflect.ValueOf((*testing.InternalExample)(nil)),
"InternalTest": reflect.ValueOf((*testing.InternalTest)(nil)),
"M": reflect.ValueOf((*testing.M)(nil)),
"PB": reflect.ValueOf((*testing.PB)(nil)),
"T": reflect.ValueOf((*testing.T)(nil)),
"TB": reflect.ValueOf((*testing.TB)(nil)),
// interface wrapper definitions
"_TB": reflect.ValueOf((*_testing_TB)(nil)),
}
}
// _testing_TB is an interface wrapper for TB type
type _testing_TB struct {
WCleanup func(a0 func())
WError func(args []interface{})
WErrorf func(format string, args []interface{})
WFail func()
WFailNow func()
WFailed func() bool
WFatal func(args []interface{})
WFatalf func(format string, args []interface{})
WHelper func()
WLog func(args []interface{})
WLogf func(format string, args []interface{})
WName func() string
WSkip func(args []interface{})
WSkipNow func()
WSkipf func(format string, args []interface{})
WSkipped func() bool
}
func (W _testing_TB) Cleanup(a0 func()) { W.WCleanup(a0) }
func (W _testing_TB) Error(args []interface{}) { W.WError(args) }
func (W _testing_TB) Errorf(format string, args []interface{}) { W.WErrorf(format, args) }
func (W _testing_TB) Fail() { W.WFail() }
func (W _testing_TB) FailNow() { W.WFailNow() }
func (W _testing_TB) Failed() bool { return W.WFailed() }
func (W _testing_TB) Fatal(args []interface{}) { W.WFatal(args) }
func (W _testing_TB) Fatalf(format string, args []interface{}) { W.WFatalf(format, args) }
func (W _testing_TB) Helper() { W.WHelper() }
func (W _testing_TB) Log(args []interface{}) { W.WLog(args) }
func (W _testing_TB) Logf(format string, args []interface{}) { W.WLogf(format, args) }
func (W _testing_TB) Name() string { return W.WName() }
func (W _testing_TB) Skip(args []interface{}) { W.WSkip(args) }
func (W _testing_TB) SkipNow() { W.WSkipNow() }
func (W _testing_TB) Skipf(format string, args []interface{}) { W.WSkipf(format, args) }
func (W _testing_TB) Skipped() bool { return W.WSkipped() }

View File

@@ -0,0 +1,24 @@
// Code generated by 'github.com/containous/yaegi/extract testing/iotest'. DO NOT EDIT.
// +build go1.14,!go1.15
package stdlib
import (
"reflect"
"testing/iotest"
)
func init() {
Symbols["testing/iotest"] = map[string]reflect.Value{
// function, constant and variable definitions
"DataErrReader": reflect.ValueOf(iotest.DataErrReader),
"ErrTimeout": reflect.ValueOf(&iotest.ErrTimeout).Elem(),
"HalfReader": reflect.ValueOf(iotest.HalfReader),
"NewReadLogger": reflect.ValueOf(iotest.NewReadLogger),
"NewWriteLogger": reflect.ValueOf(iotest.NewWriteLogger),
"OneByteReader": reflect.ValueOf(iotest.OneByteReader),
"TimeoutReader": reflect.ValueOf(iotest.TimeoutReader),
"TruncateWriter": reflect.ValueOf(iotest.TruncateWriter),
}
}

View File

@@ -0,0 +1,39 @@
// Code generated by 'github.com/containous/yaegi/extract testing/quick'. DO NOT EDIT.
// +build go1.14,!go1.15
package stdlib
import (
"math/rand"
"reflect"
"testing/quick"
)
func init() {
Symbols["testing/quick"] = map[string]reflect.Value{
// function, constant and variable definitions
"Check": reflect.ValueOf(quick.Check),
"CheckEqual": reflect.ValueOf(quick.CheckEqual),
"Value": reflect.ValueOf(quick.Value),
// type definitions
"CheckEqualError": reflect.ValueOf((*quick.CheckEqualError)(nil)),
"CheckError": reflect.ValueOf((*quick.CheckError)(nil)),
"Config": reflect.ValueOf((*quick.Config)(nil)),
"Generator": reflect.ValueOf((*quick.Generator)(nil)),
"SetupError": reflect.ValueOf((*quick.SetupError)(nil)),
// interface wrapper definitions
"_Generator": reflect.ValueOf((*_testing_quick_Generator)(nil)),
}
}
// _testing_quick_Generator is an interface wrapper for Generator type
type _testing_quick_Generator struct {
WGenerate func(rand *rand.Rand, size int) reflect.Value
}
func (W _testing_quick_Generator) Generate(rand *rand.Rand, size int) reflect.Value {
return W.WGenerate(rand, size)
}

84
stdlib/go1_15_testing.go Normal file
View File

@@ -0,0 +1,84 @@
// Code generated by 'github.com/containous/yaegi/extract testing'. DO NOT EDIT.
// +build go1.15,!go1.16
package stdlib
import (
"reflect"
"testing"
)
func init() {
Symbols["testing"] = map[string]reflect.Value{
// function, constant and variable definitions
"AllocsPerRun": reflect.ValueOf(testing.AllocsPerRun),
"Benchmark": reflect.ValueOf(testing.Benchmark),
"CoverMode": reflect.ValueOf(testing.CoverMode),
"Coverage": reflect.ValueOf(testing.Coverage),
"Init": reflect.ValueOf(testing.Init),
"Main": reflect.ValueOf(testing.Main),
"MainStart": reflect.ValueOf(testing.MainStart),
"RegisterCover": reflect.ValueOf(testing.RegisterCover),
"RunBenchmarks": reflect.ValueOf(testing.RunBenchmarks),
"RunExamples": reflect.ValueOf(testing.RunExamples),
"RunTests": reflect.ValueOf(testing.RunTests),
"Short": reflect.ValueOf(testing.Short),
"Verbose": reflect.ValueOf(testing.Verbose),
// type definitions
"B": reflect.ValueOf((*testing.B)(nil)),
"BenchmarkResult": reflect.ValueOf((*testing.BenchmarkResult)(nil)),
"Cover": reflect.ValueOf((*testing.Cover)(nil)),
"CoverBlock": reflect.ValueOf((*testing.CoverBlock)(nil)),
"InternalBenchmark": reflect.ValueOf((*testing.InternalBenchmark)(nil)),
"InternalExample": reflect.ValueOf((*testing.InternalExample)(nil)),
"InternalTest": reflect.ValueOf((*testing.InternalTest)(nil)),
"M": reflect.ValueOf((*testing.M)(nil)),
"PB": reflect.ValueOf((*testing.PB)(nil)),
"T": reflect.ValueOf((*testing.T)(nil)),
"TB": reflect.ValueOf((*testing.TB)(nil)),
// interface wrapper definitions
"_TB": reflect.ValueOf((*_testing_TB)(nil)),
}
}
// _testing_TB is an interface wrapper for TB type
type _testing_TB struct {
WCleanup func(a0 func())
WError func(args []interface{})
WErrorf func(format string, args []interface{})
WFail func()
WFailNow func()
WFailed func() bool
WFatal func(args []interface{})
WFatalf func(format string, args []interface{})
WHelper func()
WLog func(args []interface{})
WLogf func(format string, args []interface{})
WName func() string
WSkip func(args []interface{})
WSkipNow func()
WSkipf func(format string, args []interface{})
WSkipped func() bool
WTempDir func() string
}
func (W _testing_TB) Cleanup(a0 func()) { W.WCleanup(a0) }
func (W _testing_TB) Error(args []interface{}) { W.WError(args) }
func (W _testing_TB) Errorf(format string, args []interface{}) { W.WErrorf(format, args) }
func (W _testing_TB) Fail() { W.WFail() }
func (W _testing_TB) FailNow() { W.WFailNow() }
func (W _testing_TB) Failed() bool { return W.WFailed() }
func (W _testing_TB) Fatal(args []interface{}) { W.WFatal(args) }
func (W _testing_TB) Fatalf(format string, args []interface{}) { W.WFatalf(format, args) }
func (W _testing_TB) Helper() { W.WHelper() }
func (W _testing_TB) Log(args []interface{}) { W.WLog(args) }
func (W _testing_TB) Logf(format string, args []interface{}) { W.WLogf(format, args) }
func (W _testing_TB) Name() string { return W.WName() }
func (W _testing_TB) Skip(args []interface{}) { W.WSkip(args) }
func (W _testing_TB) SkipNow() { W.WSkipNow() }
func (W _testing_TB) Skipf(format string, args []interface{}) { W.WSkipf(format, args) }
func (W _testing_TB) Skipped() bool { return W.WSkipped() }
func (W _testing_TB) TempDir() string { return W.WTempDir() }

View File

@@ -0,0 +1,24 @@
// Code generated by 'github.com/containous/yaegi/extract testing/iotest'. DO NOT EDIT.
// +build go1.15,!go1.16
package stdlib
import (
"reflect"
"testing/iotest"
)
func init() {
Symbols["testing/iotest"] = map[string]reflect.Value{
// function, constant and variable definitions
"DataErrReader": reflect.ValueOf(iotest.DataErrReader),
"ErrTimeout": reflect.ValueOf(&iotest.ErrTimeout).Elem(),
"HalfReader": reflect.ValueOf(iotest.HalfReader),
"NewReadLogger": reflect.ValueOf(iotest.NewReadLogger),
"NewWriteLogger": reflect.ValueOf(iotest.NewWriteLogger),
"OneByteReader": reflect.ValueOf(iotest.OneByteReader),
"TimeoutReader": reflect.ValueOf(iotest.TimeoutReader),
"TruncateWriter": reflect.ValueOf(iotest.TruncateWriter),
}
}

View File

@@ -0,0 +1,39 @@
// Code generated by 'github.com/containous/yaegi/extract testing/quick'. DO NOT EDIT.
// +build go1.15,!go1.16
package stdlib
import (
"math/rand"
"reflect"
"testing/quick"
)
func init() {
Symbols["testing/quick"] = map[string]reflect.Value{
// function, constant and variable definitions
"Check": reflect.ValueOf(quick.Check),
"CheckEqual": reflect.ValueOf(quick.CheckEqual),
"Value": reflect.ValueOf(quick.Value),
// type definitions
"CheckEqualError": reflect.ValueOf((*quick.CheckEqualError)(nil)),
"CheckError": reflect.ValueOf((*quick.CheckError)(nil)),
"Config": reflect.ValueOf((*quick.Config)(nil)),
"Generator": reflect.ValueOf((*quick.Generator)(nil)),
"SetupError": reflect.ValueOf((*quick.SetupError)(nil)),
// interface wrapper definitions
"_Generator": reflect.ValueOf((*_testing_quick_Generator)(nil)),
}
}
// _testing_quick_Generator is an interface wrapper for Generator type
type _testing_quick_Generator struct {
WGenerate func(rand *rand.Rand, size int) reflect.Value
}
func (W _testing_quick_Generator) Generate(rand *rand.Rand, size int) reflect.Value {
return W.WGenerate(rand, size)
}

View File

@@ -47,5 +47,6 @@ func init() {
//go:generate ../cmd/goexports/goexports path path/filepath reflect regexp regexp/syntax
//go:generate ../cmd/goexports/goexports runtime runtime/debug runtime/pprof runtime/trace
//go:generate ../cmd/goexports/goexports sort strconv strings sync sync/atomic
//go:generate ../cmd/goexports/goexports testing testing/iotest testing/quick
//go:generate ../cmd/goexports/goexports text/scanner text/tabwriter text/template text/template/parse
//go:generate ../cmd/goexports/goexports time unicode unicode/utf16 unicode/utf8