Files
secDre4mer 938db1c6c2 fix: use path instead of filepath
Currently, yaegi uses the `filepath` package to join paths.

However, this has issues: YAEGI uses an `fs.FS` internally for source code access, and `fs` specifies that `/` separated paths must be used. On Unix systems, this obviously makes no difference; but on Windows, with a non-default FS, this causes errors (since YAEGI creates `\` separated paths, but the FS expects `/` separated paths).

Furthermore, generally speaking, Golang import paths and the like are always `/` separated anyway, regardless of OS.

To clear this up, this PR changes path handling to `/` separated paths. This has the advantage of being accepted by all OS (even Windows will accept `/` separated paths). Paths passed by the user to `CompilePath` or similar are changed to `/` separators, if necessary.
2025-05-21 21:22:05 +02:00

193 lines
4.2 KiB
Go

package pkg
import (
"bytes"
"fmt"
"os"
"path/filepath"
"testing"
"github.com/traefik/yaegi/interp"
"github.com/traefik/yaegi/stdlib"
)
func TestPackages(t *testing.T) {
testCases := []struct {
desc string
goPath string
expected string
topImport string
evalFile string
}{
{
desc: "vendor",
goPath: "./_pkg/",
expected: "root Fromage",
},
{
desc: "sub-subpackage",
goPath: "./_pkg0/",
expected: "root Fromage Cheese",
},
{
desc: "subpackage",
goPath: "./_pkg1/",
expected: "root Fromage!",
},
{
desc: "multiple vendor folders",
goPath: "./_pkg2/",
expected: "root Fromage Cheese!",
},
{
desc: "multiple vendor folders and subpackage in vendor",
goPath: "./_pkg3/",
expected: "root Fromage Couteau Cheese!",
},
{
desc: "multiple vendor folders and multiple subpackages in vendor",
goPath: "./_pkg4/",
expected: "root Fromage Cheese Vin! Couteau",
},
{
desc: "vendor flat",
goPath: "./_pkg5/",
expected: "root Fromage Cheese Vin! Couteau",
},
{
desc: "fallback to GOPATH",
goPath: "./_pkg6/",
expected: "root Fromage Cheese Vin! Couteau",
},
{
desc: "recursive vendor",
goPath: "./_pkg7/",
expected: "root vin cheese fromage",
},
{
desc: "named subpackage",
goPath: "./_pkg8/",
expected: "root Fromage!",
},
{
desc: "at the project root",
goPath: "./_pkg10/",
expected: "root Fromage",
topImport: "github.com/foo",
},
{
desc: "eval main that has vendored dep",
goPath: "./_pkg11/",
expected: "Fromage",
evalFile: "./_pkg11/src/foo/foo.go",
},
{
desc: "vendor dir is a sibling or an uncle",
goPath: "./_pkg12/",
expected: "Yo hello",
topImport: "guthib.com/foo/pkg",
},
{
desc: "eval main with vendor as a sibling",
goPath: "./_pkg12/",
expected: "Yo hello",
evalFile: "./_pkg12/src/guthib.com/foo/main.go",
},
{
desc: "eval main with vendor",
goPath: "./_pkg13/",
expected: "foobar",
evalFile: "./_pkg13/src/guthib.com/foo/bar/main.go",
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
goPath, err := filepath.Abs(filepath.FromSlash(test.goPath))
if err != nil {
t.Fatal(err)
}
var stdout, stderr bytes.Buffer
i := interp.New(interp.Options{GoPath: goPath, Stdout: &stdout, Stderr: &stderr})
// Use binary standard library
if err := i.Use(stdlib.Symbols); err != nil {
t.Fatal(err)
}
var msg string
if test.evalFile != "" {
if _, err := i.EvalPath(filepath.FromSlash(test.evalFile)); err != nil {
fatalStderrf(t, "%v", err)
}
msg = stdout.String()
} else {
// Load pkg from sources
topImport := "github.com/foo/pkg"
if test.topImport != "" {
topImport = test.topImport
}
if _, err = i.Eval(fmt.Sprintf(`import %q`, topImport)); err != nil {
t.Fatal(err)
}
value, err := i.Eval(`pkg.NewSample()`)
if err != nil {
t.Fatal(err)
}
fn := value.Interface().(func() string)
msg = fn()
}
if msg != test.expected {
fatalStderrf(t, "Got %q, want %q", msg, test.expected)
}
})
}
}
func fatalStderrf(t *testing.T, format string, args ...interface{}) {
t.Helper()
fmt.Fprintf(os.Stderr, format+"\n", args...)
t.FailNow()
}
func TestPackagesError(t *testing.T) {
testCases := []struct {
desc string
goPath string
expected string
}{
{
desc: "different packages in the same directory",
goPath: "./_pkg9/",
expected: `1:21: import "github.com/foo/pkg" error: found packages pkg and pkgfalse in _pkg9/src/github.com/foo/pkg`,
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
// Init go interpreter
i := interp.New(interp.Options{GoPath: test.goPath})
// Use binary standard library
if err := i.Use(stdlib.Symbols); err != nil {
t.Fatal(err)
}
// Load pkg from sources
_, err := i.Eval(`import "github.com/foo/pkg"`)
if err == nil {
t.Fatalf("got no error, want %q", test.expected)
}
if err.Error() != test.expected {
t.Errorf("got %q, want %q", err.Error(), test.expected)
}
})
}
}