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:
14
_test/m1/main.go
Normal file
14
_test/m1/main.go
Normal 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
17
_test/m1/main_test.go
Normal 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()
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
131
cmd/yaegi/test.go
Normal 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
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
@@ -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, "_")
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
82
stdlib/go1_14_testing.go
Normal 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() }
|
||||
24
stdlib/go1_14_testing_iotest.go
Normal file
24
stdlib/go1_14_testing_iotest.go
Normal 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),
|
||||
}
|
||||
}
|
||||
39
stdlib/go1_14_testing_quick.go
Normal file
39
stdlib/go1_14_testing_quick.go
Normal 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
84
stdlib/go1_15_testing.go
Normal 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() }
|
||||
24
stdlib/go1_15_testing_iotest.go
Normal file
24
stdlib/go1_15_testing_iotest.go
Normal 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),
|
||||
}
|
||||
}
|
||||
39
stdlib/go1_15_testing_quick.go
Normal file
39
stdlib/go1_15_testing_quick.go
Normal 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)
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user