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

feat(gnovm): enable debugger for gno test #3380

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion gnovm/cmd/gno/lint.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error {
io.ErrPrintfln("%s: module is draft, skipping type check", pkgPath)
}

tm := test.Machine(gs, goio.Discard, memPkg.Path)
tm := test.Machine(gs, goio.Discard, memPkg.Path, false)

defer tm.Release()

// Check package
Expand Down
17 changes: 17 additions & 0 deletions gnovm/cmd/gno/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ type testCfg struct {
updateGoldenTests bool
printRuntimeMetrics bool
printEvents bool
debug bool
debugAddr string
}

func newTestCmd(io commands.IO) *commands.Command {
Expand Down Expand Up @@ -143,6 +145,20 @@ func (c *testCfg) RegisterFlags(fs *flag.FlagSet) {
false,
"print emitted events",
)

fs.BoolVar(
&c.debug,
"debug",
false,
"enable interactive debugger using stdin and stdout",
)

fs.StringVar(
&c.debugAddr,
"debug-addr",
"",
"enable interactive debugger using tcp address in the form [host]:port",
)
}

func execTest(cfg *testCfg, args []string, io commands.IO) error {
Expand Down Expand Up @@ -187,6 +203,7 @@ func execTest(cfg *testCfg, args []string, io commands.IO) error {
opts.Verbose = cfg.verbose
opts.Metrics = cfg.printRuntimeMetrics
opts.Events = cfg.printEvents
opts.Debug = cfg.debug

buildErrCount := 0
testErrCount := 0
Expand Down
22 changes: 11 additions & 11 deletions gnovm/pkg/gnolang/debugger.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,19 @@
out io.Writer // debugger output, defaults to Stdout
scanner *bufio.Scanner // to parse input per line

state DebugState // current state of debugger
lastCmd string // last debugger command
lastArg string // last debugger command arguments
loc Location // source location of the current machine instruction
prevLoc Location // source location of the previous machine instruction
breakpoints []Location // list of breakpoints set by user, as source locations
call []Location // for function tracking, ideally should be provided by machine frame
frameLevel int // frame level of the current machine instruction
getSrc func(string) string // helper to access source from repl or others
state DebugState // current state of debugger
lastCmd string // last debugger command
lastArg string // last debugger command arguments
loc Location // source location of the current machine instruction
prevLoc Location // source location of the previous machine instruction
breakpoints []Location // list of breakpoints set by user, as source locations
call []Location // for function tracking, ideally should be provided by machine frame
frameLevel int // frame level of the current machine instruction
getSrc func(string, string) string // helper to access source from repl or others
}

// Enable makes the debugger d active, using in as input reader, out as output writer and f as a source helper.
func (d *Debugger) Enable(in io.Reader, out io.Writer, f func(string) string) {
func (d *Debugger) Enable(in io.Reader, out io.Writer, f func(string, string) string) {

Check warning on line 58 in gnovm/pkg/gnolang/debugger.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/debugger.go#L58

Added line #L58 was not covered by tests
d.in = in
d.out = out
d.enabled = true
Expand Down Expand Up @@ -505,7 +505,7 @@
if err != nil {
// Use optional getSrc helper as fallback to get source.
if m.Debugger.getSrc != nil {
src = m.Debugger.getSrc(loc.File)
src = m.Debugger.getSrc(loc.PkgPath, loc.File)

Check warning on line 508 in gnovm/pkg/gnolang/debugger.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/debugger.go#L508

Added line #L508 was not covered by tests
}
if src == "" {
return err
Expand Down
2 changes: 1 addition & 1 deletion gnovm/pkg/repl/repl.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@
r.state.id++

if r.debug {
r.state.machine.Debugger.Enable(os.Stdin, os.Stdout, func(file string) string {
r.state.machine.Debugger.Enable(os.Stdin, os.Stdout, func(ppath, file string) string {

Check warning on line 159 in gnovm/pkg/repl/repl.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/repl/repl.go#L159

Added line #L159 was not covered by tests
return r.state.files[file]
})
r.debug = false
Expand Down
1 change: 1 addition & 0 deletions gnovm/pkg/test/filetest.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ func (opts *TestOptions) runFiletest(filename string, source []byte) (string, er
Store: opts.TestStore.BeginTransaction(cw, cw, nil),
Context: ctx,
MaxAllocBytes: maxAlloc,
Debug: opts.Debug,
})
defer m.Release()
result := opts.runTest(m, pkgPath, filename, source)
Expand Down
29 changes: 24 additions & 5 deletions gnovm/pkg/test/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,12 @@
}

// Machine is a minimal machine, set up with just the Store, Output and Context.
func Machine(testStore gno.Store, output io.Writer, pkgPath string) *gno.Machine {
func Machine(testStore gno.Store, output io.Writer, pkgPath string, debug bool) *gno.Machine {
return gno.NewMachineWithOptions(gno.MachineOptions{
Store: testStore,
Output: output,
Context: Context(pkgPath, nil),
Debug: debug,
})
}

Expand Down Expand Up @@ -107,6 +108,8 @@
Output io.Writer
// Used for os.Stderr, and for printing errors.
Error io.Writer
// Debug enables the interactive debugger on gno tests.
Debug bool

// Not set by NewTestOptions:

Expand Down Expand Up @@ -292,9 +295,8 @@
// reset store ops, if any - we only need them for some filetests.
opts.TestStore.SetLogStoreOps(false)

// Check if we already have the package - it may have been eagerly
// loaded.
m = Machine(gs, opts.WriterForStore(), memPkg.Path)
// Check if we already have the package - it may have been eagerly loaded.
m = Machine(gs, opts.WriterForStore(), memPkg.Path, opts.Debug)
m.Alloc = alloc
if opts.TestStore.GetMemPackage(memPkg.Path) == nil {
m.RunMemPackage(memPkg, true)
Expand All @@ -314,14 +316,31 @@
// - Run the test files before this for loop (but persist it to store;
// RunFiles doesn't do that currently)
// - Wrap here.
m = Machine(gs, opts.Output, memPkg.Path)
m = Machine(gs, opts.Output, memPkg.Path, opts.Debug)
m.Alloc = alloc
m.SetActivePackage(pv)

testingpv := m.Store.GetPackage("testing", false)
testingtv := gno.TypedValue{T: &gno.PackageType{}, V: testingpv}
testingcx := &gno.ConstExpr{TypedValue: testingtv}

if opts.Debug {
fileContent := func(ppath, name string) string {
p := filepath.Join(opts.RootDir, ppath, name)
b, err := os.ReadFile(p)
if err != nil {
p = filepath.Join(opts.RootDir, "gnovm", "stdlibs", ppath, name)
b, err = os.ReadFile(p)
}
if err != nil {
p = filepath.Join(opts.RootDir, "examples", ppath, name)
b, err = os.ReadFile(p)
}
return string(b)

Check warning on line 339 in gnovm/pkg/test/test.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/test/test.go#L328-L339

Added lines #L328 - L339 were not covered by tests
}
m.Debugger.Enable(os.Stdin, os.Stdout, fileContent)

Check warning on line 341 in gnovm/pkg/test/test.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/test/test.go#L341

Added line #L341 was not covered by tests
}

eval := m.Eval(gno.Call(
gno.Sel(testingcx, "RunTest"), // Call testing.RunTest
gno.Str(opts.RunFlag), // run flag
Expand Down
Loading