mirror of
https://github.com/hanzoai/yaegi.git
synced 2026-10-01 00:49:47 +00:00
Per the standing fork rule, a hanzoai fork declares its OWN module path and
is required directly -- never resolved via a `replace` against the upstream
path. Keeping the upstream path meant every import line in every consumer
carried the upstream brand.
module github.com/traefik/yaegi -> module github.com/hanzoai/yaegi
Mechanical and behaviour-neutral: every occurrence is an import path
(package self-imports, cmd/, _test/ fixtures interpreted at test time, and
the guthib.com/<org>/{fromage,cheese,vin} fake vendor trees under
example/pkg, whose directory components were renamed in lockstep with the
import strings that reference them).
GOPATH-mode source-import tests (interp TestFile) resolve the module by its
path under $GOPATH/src, so the required checkout location moves with the
module path -- as README already documents. Verified green at
$GOPATH/src/github.com/hanzoai/yaegi.
LICENSE is untouched: "Copyright 2020 Traefik Labs SAS" is the Apache-2.0
attribution and is a legal obligation, not a brand leak.
Also drops the inherited CONTRIBUTING.md CLA clause, which named an
upstream agreement this fork does not administer.
133 lines
2.7 KiB
Go
133 lines
2.7 KiB
Go
package interp_test
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/hanzoai/yaegi/interp"
|
|
)
|
|
|
|
type Helloer interface {
|
|
Hello()
|
|
}
|
|
|
|
func Hi(h Helloer) {
|
|
println("In Hi:")
|
|
h.Hello()
|
|
}
|
|
|
|
// A Wrap represents the wrapper which allows to use objects created by
|
|
// the interpreter as Go interfaces (despite limitations in reflect which
|
|
// forbid dynamic method creation).
|
|
//
|
|
// All the struct fields are functions, where the fied name corresponds to
|
|
// the method name prefixed by "Do". The function signature must be the
|
|
// same as the interface one.
|
|
//
|
|
// A corresponding Wrap method Xyz which satisfies the interface must exist and
|
|
// must invoke the DoXyz function.
|
|
//
|
|
// To be usable, the interpreter should return a Wrap instance with the relevant
|
|
// function fields filled. The application can then invoke methods on it.
|
|
// The method calls will be forwarded to the interpreter.
|
|
//
|
|
// Only the Wrap type definition needs to be exported to the interpreter (not
|
|
// the interfaces and methods definitions).
|
|
type Wrap struct {
|
|
DoHello func() // related to the Hello() method.
|
|
// Other interface method wrappers...
|
|
}
|
|
|
|
func (w Wrap) Hello() { w.DoHello() }
|
|
|
|
func TestExportsSemantics(t *testing.T) {
|
|
Foo := &struct{}{}
|
|
|
|
t.Run("Correct", func(t *testing.T) {
|
|
t.Skip()
|
|
i := interp.New(interp.Options{})
|
|
|
|
err := i.Use(interp.Exports{
|
|
"foo/foo": {"Foo": reflect.ValueOf(Foo)},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
i.ImportUsed()
|
|
|
|
res, err := i.Eval("foo.Foo")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if res.Interface() != Foo {
|
|
t.Fatalf("expected foo.Foo to equal local Foo")
|
|
}
|
|
})
|
|
|
|
t.Run("Incorrect", func(t *testing.T) {
|
|
i := interp.New(interp.Options{})
|
|
|
|
err := i.Use(interp.Exports{
|
|
"foo": {"Foo": reflect.ValueOf(Foo)},
|
|
})
|
|
if err == nil {
|
|
t.Fatal("expected error for incorrect Use semantics")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestInterface(t *testing.T) {
|
|
i := interp.New(interp.Options{})
|
|
// export the Wrap type to the interpreter under virtual "wrap" package
|
|
err := i.Use(interp.Exports{
|
|
"wrap/wrap": {
|
|
"Wrap": reflect.ValueOf((*Wrap)(nil)),
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
eval(t, i, `
|
|
import "wrap"
|
|
|
|
type MyInt int
|
|
|
|
func (m MyInt) Hello() { println("hello from Myint", m) }
|
|
|
|
func NewMyInt(i int) wrap.Wrap {
|
|
m := MyInt(i)
|
|
return wrap.Wrap{DoHello: m.Hello}
|
|
}
|
|
`)
|
|
NewMyInt := eval(t, i, "NewMyInt").Interface().(func(int) Wrap)
|
|
w := NewMyInt(4)
|
|
Hi(w)
|
|
}
|
|
|
|
type T struct{}
|
|
|
|
func (t T) Bar(s ...string) {}
|
|
|
|
func TestCallBinVariadicMethod(t *testing.T) {
|
|
i := interp.New(interp.Options{})
|
|
err := i.Use(interp.Exports{
|
|
"mypkg/mypkg": {
|
|
"T": reflect.ValueOf((*T)(nil)),
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
eval(t, i, `
|
|
package p
|
|
|
|
import "mypkg"
|
|
|
|
func Foo(x mypkg.T) { x.Bar("s") }
|
|
`)
|
|
v := eval(t, i, "p.Foo")
|
|
bar := v.Interface().(func(t T))
|
|
bar(T{})
|
|
}
|