Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(gnovm): PrevRealm in _test files #896

Merged
merged 17 commits into from
Aug 6, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions examples/gno.land/r/demo/tests/tests.gno
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package tests
import (
"std"

"gno.land/r/demo/tests/subtests"
rsubtests "gno.land/r/demo/tests/subtests"
)

var counter int
Expand Down Expand Up @@ -78,8 +78,8 @@ func GetPrevRealm() std.Realm {
return std.PrevRealm()
}

func GetPSubtestsPrevRealm() std.Realm {
return subtests.GetPrevRealm()
func GetRSubtestsPrevRealm() std.Realm {
tbruyelle marked this conversation as resolved.
Show resolved Hide resolved
return rsubtests.GetPrevRealm()
}

func Exec(fn func()) {
Expand Down
16 changes: 16 additions & 0 deletions examples/gno.land/r/demo/tests/tests_test.gno
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package tests

import (
"std"
"testing"

"gno.land/p/demo/testutils"
Expand Down Expand Up @@ -30,3 +31,18 @@ func TestAssertOriginCall(t *testing.T) {
AssertOriginCall()
}()
}

func TestPrevRealm(t *testing.T) {
var (
user1Addr = std.DerivePkgAddr("user1.gno")
rTestsAddr = std.DerivePkgAddr("gno.land/r/demo/tests")
)
// When a single realm in the frames, PrevRealm returns the user
if addr := GetPrevRealm().Addr(); addr != user1Addr {
t.Errorf("want GetPrevRealm().Addr==%s, got %s", user1Addr, addr)
}
// When 2 or more realms in the frames, PrevRealm returns the second to last
if addr := GetRSubtestsPrevRealm().Addr(); addr != rTestsAddr {
t.Errorf("want GetRSubtestsPrevRealm().Addr==%s, got %s", rTestsAddr, addr)
}
}
2 changes: 1 addition & 1 deletion gnovm/cmd/gno/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func testMainCaseRun(t *testing.T, tc []testMainCase) {
require.False(t, recoverShouldBeEmpty, "should panic")
require.True(t, errShouldBeEmpty, "should not return an error")
if test.recoverShouldContain != "" {
require.Contains(t, output, test.recoverShouldContain, "recover should contain")
require.Regexpf(t, test.recoverShouldContain, output, "recover should contain")
}
if test.recoverShouldBe != "" {
require.Equal(t, test.recoverShouldBe, output, "recover should be")
Expand Down
25 changes: 18 additions & 7 deletions gnovm/cmd/gno/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@ import (
"text/template"
"time"

"go.uber.org/multierr"

gno "github.com/gnolang/gno/gnovm/pkg/gnolang"
"github.com/gnolang/gno/gnovm/pkg/gnomod"
"github.com/gnolang/gno/gnovm/tests"
"github.com/gnolang/gno/tm2/pkg/commands"
"github.com/gnolang/gno/tm2/pkg/errors"
"github.com/gnolang/gno/tm2/pkg/random"
"github.com/gnolang/gno/tm2/pkg/std"
"github.com/gnolang/gno/tm2/pkg/testutils"
"go.uber.org/multierr"
)

type testCfg struct {
Expand Down Expand Up @@ -240,11 +243,9 @@ func gnoTestPkg(
stdin = io.In
stdout = io.Out
stderr = io.Err
errs error
)

filter := splitRegexp(runFlag)
var errs error

mode := tests.ImportModeStdlibsOnly
if cfg.withNativeFallback {
// XXX: display a warn?
Expand All @@ -267,14 +268,23 @@ func gnoTestPkg(

// testing with *_test.gno
if len(unittestFiles) > 0 {
memPkg := gno.ReadMemPackage(pkgPath, pkgPath)
// Determine gnoPkgPath by reading gno.mod
var gnoPkgPath string
modfile, err := gnomod.ParseAt(pkgPath)
if err == nil {
gnoPkgPath = modfile.Module.Mod.Path
} else {
// unable to read pkgPath from gno.mod, generate a random realm path
gnoPkgPath = gno.GnoRealmPkgsPrefixBefore + random.RandStr(8)
}
memPkg := gno.ReadMemPackage(pkgPath, gnoPkgPath)

// tfiles, ifiles := gno.ParseMemPackageTests(memPkg)
tfiles, ifiles := parseMemPackageTests(memPkg)

// run test files in pkg
{
m := tests.TestMachine(testStore, stdout, "main")
m := tests.TestMachine(testStore, stdout, gnoPkgPath)
if printRuntimeMetrics {
// from tm2/pkg/sdk/vm/keeper.go
// XXX: make maxAllocTx configurable.
Expand Down Expand Up @@ -305,6 +315,7 @@ func gnoTestPkg(

// testing with *_filetest.gno
{
filter := splitRegexp(runFlag)
for _, testFile := range filetestFiles {
testFileName := filepath.Base(testFile)
testName := "file/" + testFileName
Expand Down Expand Up @@ -377,7 +388,7 @@ func runTestFiles(
}

m.RunFiles(files.Files...)
n := gno.MustParseFile("testmain.go", testmain)
n := gno.MustParseFile("main_test.gno", testmain)
m.RunFiles(n)

for _, test := range testFuncs.Tests {
Expand Down
6 changes: 3 additions & 3 deletions gnovm/cmd/gno/test_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,19 +153,19 @@ func TestTest(t *testing.T) {
},
{
args: []string{"test", "--verbose", "../../tests/integ/native-lib"},
recoverShouldContain: "./../../tests/integ/native-lib/contract.gno:1: unknown import path net",
recoverShouldContain: "gno.land/r/\\w{8}/contract.gno:1: unknown import path net",
},
{
args: []string{"test", "--verbose", "--with-native-fallback", "../../tests/integ/native-lib"},
stderrShouldContain: "ok ./../../tests/integ/native-lib",
},
{
args: []string{"test", "--verbose", "../../tests/integ/unknown-lib"},
recoverShouldContain: "./../../tests/integ/unknown-lib/contract.gno:1: unknown import path foobarbaz",
recoverShouldContain: "gno.land/r/\\w{8}/contract.gno:1: unknown import path foobarbaz",
},
{
args: []string{"test", "--verbose", "--with-native-fallback", "../../tests/integ/unknown-lib"},
recoverShouldContain: "./../../tests/integ/unknown-lib/contract.gno:1: unknown import path foobarbaz",
recoverShouldContain: "gno.land/r/\\w{8}/contract.gno:1: unknown import path foobarbaz",
},
{
args: []string{"test", "--verbose", "--print-runtime-metrics", "../../../examples/gno.land/p/demo/ufmt"},
Expand Down
3 changes: 3 additions & 0 deletions gnovm/pkg/doc/dirs.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ func newDirs(dirs []string, modDirs []string) *bfsDirs {

// tries to parse gno mod file given the filename, using Parse and Validate from
// the gnomod package
//
// TODO(tb): replace by `gnomod.ParseAt` ? The key difference is the latter
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, and later, gnomod.ParseAt can also support new ways to guess a module when there is no gno.mod file.

// looks for gno.mod in parent directories, while this function doesn't.
func parseGnoMod(fname string) (*gnomod.File, error) {
file, err := os.Stat(fname)
if err != nil {
Expand Down
6 changes: 5 additions & 1 deletion gnovm/pkg/gnolang/realm.go
Original file line number Diff line number Diff line change
Expand Up @@ -1121,6 +1121,10 @@ func copyValueWithRefs(parent Object, val Value) Value {
}
case *FuncValue:
source := toRefNode(cv.Source)
if strings.HasSuffix(source.Location.File, "_test.gno") {
Copy link
Member

@moul moul Aug 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if strings.HasSuffix(source.Location.File, "_test.gno") {
func (v Val) InTestFile() bool {return strings.HasSuffix(source.Location.File, "_test.gno")}
if val.InTestFile()) {

can be done later

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have to change it now. I created an issue so that we can track it for later discussion.

Dose this mean if someone deployed a realm package with a source file named xyz_test.gno it will be ignored by the VM? If that is the case, it means we should include this file naming convention to the VM specs.

Also If we do not allow _test.gno files in the realm package, we should guarded it before we parse the file and load it to VM, instead of at the persistent stage.

If this purely serves the purpose for off chain realm testing, would sticking with realm file test be a better option?

// Ignore _test files
return nil
}
var closure Value
if cv.Closure != nil {
closure = toRefValue(parent, cv.Closure)
Expand Down Expand Up @@ -1502,7 +1506,7 @@ func isUnsaved(oo Object) bool {

func IsRealmPath(pkgPath string) bool {
// TODO: make it more distinct to distinguish from normal paths.
if strings.HasPrefix(pkgPath, "gno.land/r/") {
if strings.HasPrefix(pkgPath, GnoRealmPkgsPrefixBefore) {
return true
} else {
return false
Expand Down
34 changes: 34 additions & 0 deletions gnovm/pkg/gnomod/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,47 @@ package gnomod

import (
"fmt"
"os"
"path"
"path/filepath"
"reflect"
"strings"

"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
)

// ParseAt parses, validates and returns a gno.mod file located at dir or at
// dir's parents.
func ParseAt(dir string) (*File, error) {
ferr := func(err error) (*File, error) {
return nil, fmt.Errorf("parsing gno.mod at %s: %w", dir, err)
}

// FindRootDir requires absolute path, make sure its the case
absDir, err := filepath.Abs(dir)
if err != nil {
return ferr(err)
}
rd, err := FindRootDir(absDir)
if err != nil {
return ferr(err)
}
fname := path.Join(rd, "gno.mod")
tbruyelle marked this conversation as resolved.
Show resolved Hide resolved
b, err := os.ReadFile(fname)
if err != nil {
return ferr(err)
}
gm, err := Parse(fname, b)
if err != nil {
return ferr(err)
}
if err := gm.Validate(); err != nil {
return ferr(err)
}
return gm, nil
}

// Parse parses and returns a gno.mod file.
//
// - file is the name of the file, used in positions and errors.
Expand Down
2 changes: 1 addition & 1 deletion gnovm/tests/files/zrealm_crossrealm11.gno
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func main() {
},
{
callStackAdd: " -> r/demo/tests -> r/demo/tests/subtests",
callerFn: rtests.GetPSubtestsPrevRealm,
callerFn: rtests.GetRSubtestsPrevRealm,
},
{
callStackAdd: " -> p/demo/tests -> r/demo/tests",
Expand Down
2 changes: 1 addition & 1 deletion gnovm/tests/files/zrealm_tests0.gno
Original file line number Diff line number Diff line change
Expand Up @@ -972,7 +972,7 @@ func main() {
// },
// "FileName": "tests.gno",
// "IsMethod": false,
// "Name": "GetPSubtestsPrevRealm",
// "Name": "GetRSubtestsPrevRealm",
// "PkgPath": "gno.land/r/demo/tests",
// "Source": {
// "@type": "/gno.RefNode",
Expand Down
3 changes: 2 additions & 1 deletion gnovm/tests/imports.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri
Output: stdout,
Store: store,
})
return m2.RunMemPackage(memPkg, true)
save := pkgPath != "testing" // never save the "testing" package
return m2.RunMemPackage(memPkg, save)
}
}

Expand Down
Loading