未验证 提交 95e7cafd 编写于 作者: Á Álex Sáez 提交者: GitHub

terminal/command: Add 'reload' command (#1971)

* terminal/command: Add 'reload' command

These changes add the 'reload' command, which allows us to rebuild the project
and start the debugging session again. Currently, if the project's code is
updated while debugging it, Delve shows the new source code, but it's still
running the old one. With 'reload', the whole binary is rebuilt, and the
process starts again.

Fixes #1551

* Remove unnecessary print

Changes to be committed:
      modified:   pkg/terminal/command.go

* Add tests and refactor the code

Changes to be committed:
      modified:   cmd/dlv/cmds/commands.go
      modified:   go.mod
      modified:   pkg/terminal/command.go
      modified:   service/config.go
      modified:   service/debugger/debugger.go
      modified:   service/test/integration2_test.go

* Fix typo in the comment

Changes to be committed:
      modified:   service/debugger/debugger.go

* Fix typo in the name of the variables

The variables are local therefore the capitalization is not needed

Changes to be committed:
      modified:   cmd/dlv/cmds/commands.go

* Call GoTestBuild

Also, remove the := to avoid redeclaration

* Change the Kind in the tests

Change from debugger.ExecutingGeneratedTest to
debugger.ExecutingGeneratedFile for consistency.
We are generating a real binary instead of a test
one so ExecutingGeneratedFile makes more sense here.

Changes to be committed:
      modified:   service/test/integration2_test.go

* Avoid breakpoints based on addresses

Changes to be committed:
      modified:   service/debugger/debugger.go

* Update the rebuild behaviour

There are a few cases where we can't rebuild the binary because we don't
know how it was build.

Changes to be committed:
      modified:   service/debugger/debugger.go

* Fix typos and update documentation

Changes to be committed:
      modified:   Documentation/cli/README.md
      modified:   pkg/terminal/command.go
      modified:   service/config.go
      modified:   service/debugger/debugger.go

* Fix typo

* Remove variables

They were added to the debugger.Config

* Rename variable

Rename Kind to ExecuteKind to make it more accurate

Changes to be committed:
      modified:   cmd/dlv/cmds/commands.go
      modified:   service/debugger/debugger.go
      modified:   service/test/integration2_test.go
上级 292f5c69
......@@ -13,6 +13,7 @@ Command | Description
[call](#call) | Resumes process, injecting a function call (EXPERIMENTAL!!!)
[continue](#continue) | Run until breakpoint or program termination.
[next](#next) | Step over to next source line.
[rebuild](#rebuild) | Rebuild the target executable and restarts it. It does not work if the executable was not built by delve.
[restart](#restart) | Restart process.
[rev](#rev) | Reverses the execution of the target program for the command specified.
[rewind](#rewind) | Run backwards until breakpoint or program termination.
......@@ -394,6 +395,10 @@ See [Documentation/cli/expr.md](//github.com/go-delve/delve/tree/master/Document
Aliases: p
## rebuild
Rebuild the target executable and restarts it. It does not work if the executable was not built by delve.
## regs
Print contents of CPU registers.
......
......@@ -51,7 +51,7 @@ threads() | Equivalent to API call [ListThreads](https://godoc.org/github.com/go
types(Filter) | Equivalent to API call [ListTypes](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.ListTypes)
process_pid() | Equivalent to API call [ProcessPid](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.ProcessPid)
recorded() | Equivalent to API call [Recorded](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.Recorded)
restart(Position, ResetArgs, NewArgs, Rerecord) | Equivalent to API call [Restart](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.Restart)
restart(Position, ResetArgs, NewArgs, Rerecord, Rebuild) | Equivalent to API call [Restart](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.Restart)
set_expr(Scope, Symbol, Value) | Equivalent to API call [Set](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.Set)
stacktrace(Id, Depth, Full, Defers, Opts, Cfg) | Equivalent to API call [Stacktrace](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.Stacktrace)
state(NonBlocking) | Equivalent to API call [State](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.State)
......
......@@ -210,7 +210,7 @@ or later, -gcflags="-N -l" on earlier versions of Go.`,
return nil
},
Run: func(cmd *cobra.Command, args []string) {
os.Exit(execute(0, args, conf, "", executingExistingFile))
os.Exit(execute(0, args, conf, "", debugger.ExecutingExistingFile, args, buildFlags))
},
}
execCommand.Flags().StringVar(&tty, "tty", "", "TTY to use for the target program")
......@@ -312,7 +312,7 @@ https://github.com/mozilla/rr
},
Run: func(cmd *cobra.Command, args []string) {
backend = "rr"
os.Exit(execute(0, []string{}, conf, args[0], executingOther))
os.Exit(execute(0, []string{}, conf, args[0], debugger.ExecutingOther, args, buildFlags))
},
}
rootCommand.AddCommand(replayCommand)
......@@ -441,7 +441,7 @@ func debugCmd(cmd *cobra.Command, args []string) {
}
defer gobuild.Remove(debugname)
processArgs := append([]string{debugname}, targetArgs...)
return execute(0, processArgs, conf, "", executingGeneratedFile)
return execute(0, processArgs, conf, "", debugger.ExecutingGeneratedFile, dlvArgs, buildFlags)
}()
os.Exit(status)
}
......@@ -591,7 +591,7 @@ func testCmd(cmd *cobra.Command, args []string) {
defer gobuild.Remove(debugname)
processArgs := append([]string{debugname}, targetArgs...)
return execute(0, processArgs, conf, "", executingGeneratedTest)
return execute(0, processArgs, conf, "", debugger.ExecutingGeneratedTest, dlvArgs, buildFlags)
}()
os.Exit(status)
}
......@@ -602,11 +602,11 @@ func attachCmd(cmd *cobra.Command, args []string) {
fmt.Fprintf(os.Stderr, "Invalid pid: %s\n", args[0])
os.Exit(1)
}
os.Exit(execute(pid, args[1:], conf, "", executingOther))
os.Exit(execute(pid, args[1:], conf, "", debugger.ExecutingOther, args, buildFlags))
}
func coreCmd(cmd *cobra.Command, args []string) {
os.Exit(execute(0, []string{args[0]}, conf, args[1], executingOther))
os.Exit(execute(0, []string{args[0]}, conf, args[1], debugger.ExecutingOther, args, buildFlags))
}
func connectCmd(cmd *cobra.Command, args []string) {
......@@ -615,7 +615,7 @@ func connectCmd(cmd *cobra.Command, args []string) {
fmt.Fprint(os.Stderr, "An empty address was provided. You must provide an address as the first argument.\n")
os.Exit(1)
}
os.Exit(connect(addr, nil, conf, executingOther))
os.Exit(connect(addr, nil, conf, debugger.ExecutingOther))
}
// waitForDisconnectSignal is a blocking function that waits for either
......@@ -656,7 +656,7 @@ func splitArgs(cmd *cobra.Command, args []string) ([]string, []string) {
return args, []string{}
}
func connect(addr string, clientConn net.Conn, conf *config.Config, kind executeKind) int {
func connect(addr string, clientConn net.Conn, conf *config.Config, kind debugger.ExecuteKind) int {
// Create and start a terminal - attach to running instance
var client *rpc2.RPCClient
if clientConn != nil {
......@@ -687,16 +687,7 @@ func connect(addr string, clientConn net.Conn, conf *config.Config, kind execute
return status
}
type executeKind int
const (
executingExistingFile = executeKind(iota)
executingGeneratedFile
executingGeneratedTest
executingOther
)
func execute(attachPid int, processArgs []string, conf *config.Config, coreFile string, kind executeKind) int {
func execute(attachPid int, processArgs []string, conf *config.Config, coreFile string, kind debugger.ExecuteKind, dlvArgs []string, buildFlags string) int {
if err := logflags.Setup(log, logOutput, logDest); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
return 1
......@@ -760,6 +751,9 @@ func execute(attachPid int, processArgs []string, conf *config.Config, coreFile
Backend: backend,
CoreFile: coreFile,
Foreground: headless && tty == "",
Packages: dlvArgs,
BuildFlags: buildFlags,
ExecuteKind: kind,
DebugInfoDirectories: conf.DebugInfoDirectories,
CheckGoVersion: checkGoVersion,
TTY: tty,
......@@ -773,10 +767,10 @@ func execute(attachPid int, processArgs []string, conf *config.Config, coreFile
if err := server.Run(); err != nil {
if err == api.ErrNotExecutable {
switch kind {
case executingGeneratedFile:
case debugger.ExecutingGeneratedFile:
fmt.Fprintln(os.Stderr, "Can not debug non-main package")
return 1
case executingExistingFile:
case debugger.ExecutingExistingFile:
fmt.Fprintf(os.Stderr, "%s is not executable\n", processArgs[0])
return 1
default:
......
......@@ -48,8 +48,12 @@ golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSF
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191127201027-ecd32218bd7f h1:3MlESg/jvTr87F4ttA/q4B+uhe/q6qleC9/DP+IwQmY=
golang.org/x/tools v0.0.0-20191127201027-ecd32218bd7f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200415034506-5d8e1897c761 h1:FVw4lelfGRNPqB3C8qX1m+QyeM2vzToIwlFhEZX42y8=
golang.org/x/tools v0.0.0-20200415034506-5d8e1897c761/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
......
......@@ -143,6 +143,7 @@ For live targets the command takes the following forms:
If newargv is omitted the process is restarted (or re-recorded) with the same argument vector.
If -noargs is specified instead, the argument vector is cleared.
`},
{aliases: []string{"rebuild"}, group: runCmds, cmdFn: c.rebuild, allowedPrefixes: revPrefix, helpMsg: "Rebuild the target executable and restarts it. It does not work if the executable was not built by delve."},
{aliases: []string{"continue", "c"}, group: runCmds, cmdFn: c.cont, allowedPrefixes: revPrefix, helpMsg: "Run until breakpoint or program termination."},
{aliases: []string{"step", "s"}, group: runCmds, cmdFn: c.step, allowedPrefixes: revPrefix, helpMsg: "Single step through program."},
{aliases: []string{"step-instruction", "si"}, group: runCmds, allowedPrefixes: revPrefix, cmdFn: c.stepInstruction, helpMsg: "Single step a single cpu instruction."},
......@@ -1028,7 +1029,7 @@ func restartLive(t *Term, ctx callContext, args string) error {
}
func restartIntl(t *Term, rerecord bool, restartPos string, resetArgs bool, newArgv []string) error {
discarded, err := t.client.RestartFrom(rerecord, restartPos, resetArgs, newArgv)
discarded, err := t.client.RestartFrom(rerecord, restartPos, resetArgs, newArgv, false)
if err != nil {
return err
}
......@@ -1073,6 +1074,18 @@ func printcontextNoState(t *Term) {
printcontext(t, state)
}
func (c *Commands) rebuild(t *Term, ctx callContext, args string) error {
if ctx.Prefix == revPrefix {
return c.rewind(t, ctx, args)
}
defer t.onStop()
discarded, err := t.client.Restart(true)
if len(discarded) > 0 {
fmt.Printf("not all breakpoints could be restored.")
}
return err
}
func (c *Commands) cont(t *Term, ctx callContext, args string) error {
if ctx.Prefix == revPrefix {
return c.rewind(t, ctx, args)
......
......@@ -1091,6 +1091,12 @@ func (env *Env) starlarkPredeclare() starlark.StringDict {
return starlark.None, decorateError(thread, err)
}
}
if len(args) > 4 && args[4] != starlark.None {
err := unmarshalStarlarkValue(args[4], &rpcArgs.Rebuild, "Rebuild")
if err != nil {
return starlark.None, decorateError(thread, err)
}
}
for _, kv := range kwargs {
var err error
switch kv[0].(starlark.String) {
......@@ -1102,6 +1108,8 @@ func (env *Env) starlarkPredeclare() starlark.StringDict {
err = unmarshalStarlarkValue(kv[1], &rpcArgs.NewArgs, "NewArgs")
case "Rerecord":
err = unmarshalStarlarkValue(kv[1], &rpcArgs.Rerecord, "Rerecord")
case "Rebuild":
err = unmarshalStarlarkValue(kv[1], &rpcArgs.Rebuild, "Rebuild")
default:
err = fmt.Errorf("unknown argument %q", kv[0])
}
......
......@@ -18,10 +18,10 @@ type Client interface {
// Detach detaches the debugger, optionally killing the process.
Detach(killProcess bool) error
// Restarts program.
Restart() ([]api.DiscardedBreakpoint, error)
// Restarts program. Set true if you want to rebuild the process we are debugging.
Restart(rebuild bool) ([]api.DiscardedBreakpoint, error)
// Restarts program from the specified position.
RestartFrom(rerecord bool, pos string, resetArgs bool, newArgs []string) ([]api.DiscardedBreakpoint, error)
RestartFrom(rerecord bool, pos string, resetArgs bool, newArgs []string, rebuild bool) ([]api.DiscardedBreakpoint, error)
// GetState returns the current debugger state.
GetState() (*api.DebuggerState, error)
......
......@@ -16,6 +16,7 @@ import (
"time"
"github.com/go-delve/delve/pkg/dwarf/op"
"github.com/go-delve/delve/pkg/gobuild"
"github.com/go-delve/delve/pkg/goversion"
"github.com/go-delve/delve/pkg/locspec"
"github.com/go-delve/delve/pkg/logflags"
......@@ -63,6 +64,15 @@ type Debugger struct {
recordMutex sync.Mutex
}
type ExecuteKind int
const (
ExecutingExistingFile = ExecuteKind(iota)
ExecutingGeneratedFile
ExecutingGeneratedTest
ExecutingOther
)
// Config provides the configuration to start a Debugger.
//
// Only one of ProcessArgs or AttachPid should be specified. If ProcessArgs is
......@@ -98,6 +108,15 @@ type Config struct {
// TTY is passed along to the target process on creation. Used to specify a
// TTY for that process.
TTY string
// Packages contains the packages that we are debugging.
Packages []string
// BuildFlags contains the flags passed to the compiler.
BuildFlags string
// ExecuteKind contains the kind of the executed program.
ExecuteKind ExecuteKind
}
// New creates a new Debugger. ProcessArgs specify the commandline arguments for the
......@@ -390,7 +409,7 @@ func (d *Debugger) detach(kill bool) error {
// If the target process is a recording it will restart it from the given
// position. If pos starts with 'c' it's a checkpoint ID, otherwise it's an
// event number. If resetArgs is true, newArgs will replace the process args.
func (d *Debugger) Restart(rerecord bool, pos string, resetArgs bool, newArgs []string) ([]api.DiscardedBreakpoint, error) {
func (d *Debugger) Restart(rerecord bool, pos string, resetArgs bool, newArgs []string, rebuild bool) ([]api.DiscardedBreakpoint, error) {
d.targetMutex.Lock()
defer d.targetMutex.Unlock()
......@@ -421,6 +440,25 @@ func (d *Debugger) Restart(rerecord bool, pos string, resetArgs bool, newArgs []
}
var p *proc.Target
var err error
if rebuild {
switch d.config.ExecuteKind {
case ExecutingGeneratedFile:
err = gobuild.GoBuild(d.processArgs[0], d.config.Packages, d.config.BuildFlags)
if err != nil {
return nil, fmt.Errorf("could not rebuild process: %s", err)
}
case ExecutingGeneratedTest:
err = gobuild.GoTestBuild(d.processArgs[0], d.config.Packages, d.config.BuildFlags)
if err != nil {
return nil, fmt.Errorf("could not rebuild process: %s", err)
}
default:
// We cannot build a process that we didn't start, because we don't know how it was built.
return nil, fmt.Errorf("cannot rebuild a binary")
}
}
if recorded {
run, stop, err2 := gdbserial.RecordAsync(d.processArgs, d.config.WorkingDir, false)
if err2 != nil {
......@@ -450,6 +488,10 @@ func (d *Debugger) Restart(rerecord bool, pos string, resetArgs bool, newArgs []
}
createLogicalBreakpoint(p, addrs, oldBp)
} else {
// Avoid setting a breakpoint based on address when rebuilding
if rebuild {
continue
}
newBp, err := p.SetBreakpoint(oldBp.Addr, proc.UserBreakpoint, nil)
if err != nil {
return nil, err
......
......@@ -46,7 +46,7 @@ func (s *RPCServer) Restart(arg1 interface{}, arg2 *int) error {
if s.config.Debugger.AttachPid != 0 {
return errors.New("cannot restart process Delve did not create")
}
_, err := s.debugger.Restart(false, "", false, nil)
_, err := s.debugger.Restart(false, "", false, nil, false)
return err
}
......
......@@ -60,15 +60,15 @@ func (c *RPCClient) Detach(kill bool) error {
return c.call("Detach", DetachIn{kill}, out)
}
func (c *RPCClient) Restart() ([]api.DiscardedBreakpoint, error) {
func (c *RPCClient) Restart(rebuild bool) ([]api.DiscardedBreakpoint, error) {
out := new(RestartOut)
err := c.call("Restart", RestartIn{"", false, nil, false}, out)
err := c.call("Restart", RestartIn{"", false, nil, false, rebuild}, out)
return out.DiscardedBreakpoints, err
}
func (c *RPCClient) RestartFrom(rerecord bool, pos string, resetArgs bool, newArgs []string) ([]api.DiscardedBreakpoint, error) {
func (c *RPCClient) RestartFrom(rerecord bool, pos string, resetArgs bool, newArgs []string, rebuild bool) ([]api.DiscardedBreakpoint, error) {
out := new(RestartOut)
err := c.call("Restart", RestartIn{pos, resetArgs, newArgs, rerecord}, out)
err := c.call("Restart", RestartIn{pos, resetArgs, newArgs, rerecord, rebuild}, out)
return out.DiscardedBreakpoints, err
}
......
......@@ -76,6 +76,9 @@ type RestartIn struct {
// When Rerecord is set the target will be rerecorded
Rerecord bool
// When Rebuild is set the process will be build again
Rebuild bool
}
type RestartOut struct {
......@@ -90,7 +93,7 @@ func (s *RPCServer) Restart(arg RestartIn, cb service.RPCCallback) {
}
var out RestartOut
var err error
out.DiscardedBreakpoints, err = s.debugger.Restart(arg.Rerecord, arg.Position, arg.ResetArgs, arg.NewArgs)
out.DiscardedBreakpoints, err = s.debugger.Restart(arg.Rerecord, arg.Position, arg.ResetArgs, arg.NewArgs, arg.Rebuild)
cb.Return(out, err)
}
......
......@@ -3,6 +3,7 @@ package service_test
import (
"flag"
"fmt"
"io/ioutil"
"math/rand"
"net"
"net/rpc"
......@@ -74,6 +75,9 @@ func startServer(name string, buildFlags protest.BuildFlags, t *testing.T) (clie
Debugger: debugger.Config{
Backend: testBackend,
CheckGoVersion: true,
Packages: []string{fixture.Source},
BuildFlags: "", // build flags can be an empty string here because the only test that uses it, does not set special flags.
ExecuteKind: debugger.ExecutingGeneratedFile,
},
})
if err := server.Run(); err != nil {
......@@ -109,7 +113,8 @@ func TestRunWithInvalidPath(t *testing.T) {
ProcessArgs: []string{"invalid_path"},
APIVersion: 2,
Debugger: debugger.Config{
Backend: testBackend,
Backend: testBackend,
ExecuteKind: debugger.ExecutingGeneratedFile,
},
})
if err := server.Run(); err == nil {
......@@ -124,7 +129,7 @@ func TestRestart_afterExit(t *testing.T) {
if !state.Exited {
t.Fatal("expected initial process to have exited")
}
if _, err := c.Restart(); err != nil {
if _, err := c.Restart(false); err != nil {
t.Fatal(err)
}
if c.ProcessPid() == origPid {
......@@ -154,7 +159,7 @@ func TestRestart_breakpointPreservation(t *testing.T) {
}
t.Log("Restart")
c.Restart()
c.Restart(false)
stateCh = c.Continue()
state = <-stateCh
if state.CurrentThread.Breakpoint.Name != "firstbreakpoint" || !state.CurrentThread.Breakpoint.Tracepoint {
......@@ -178,7 +183,7 @@ func TestRestart_duringStop(t *testing.T) {
if state.CurrentThread.Breakpoint == nil {
t.Fatal("did not hit breakpoint")
}
if _, err := c.Restart(); err != nil {
if _, err := c.Restart(false); err != nil {
t.Fatal(err)
}
if c.ProcessPid() == origPid {
......@@ -194,6 +199,72 @@ func TestRestart_duringStop(t *testing.T) {
})
}
// This source is a slightly modified version of
// _fixtures/testenv.go. The only difference is that
// the name of the environment variable we are trying to
// read is named differently, so we can assert the code
// was actually changed in the test.
const modifiedSource = `package main
import (
"fmt"
"os"
"runtime"
)
func main() {
x := os.Getenv("SOMEMODIFIEDVAR")
runtime.Breakpoint()
fmt.Printf("SOMEMODIFIEDVAR=%s\n", x)
}
`
func TestRestart_rebuild(t *testing.T) {
// In the original fixture file the env var tested for is SOMEVAR.
os.Setenv("SOMEVAR", "bah")
withTestClient2Extended("testenv", t, 0, func(c service.Client, f protest.Fixture) {
<-c.Continue()
var1, err := c.EvalVariable(api.EvalScope{GoroutineID: -1}, "x", normalLoadConfig)
assertNoError(err, t, "EvalVariable")
if var1.Value != "bah" {
t.Fatalf("expected 'bah' got %q", var1.Value)
}
fi, err := os.Stat(f.Source)
assertNoError(err, t, "Stat fixture.Source")
originalSource, err := ioutil.ReadFile(f.Source)
assertNoError(err, t, "Reading original source")
// Ensure we write the original source code back after the test exits.
defer ioutil.WriteFile(f.Source, originalSource, fi.Mode())
// Write modified source code to the fixture file.
err = ioutil.WriteFile(f.Source, []byte(modifiedSource), fi.Mode())
assertNoError(err, t, "Writing modified source")
// First set our new env var and ensure later that the
// modified source code picks it up.
os.Setenv("SOMEMODIFIEDVAR", "foobar")
// Restart the program, rebuilding from source.
_, err = c.Restart(true)
assertNoError(err, t, "Restart(true)")
<-c.Continue()
var1, err = c.EvalVariable(api.EvalScope{GoroutineID: -1}, "x", normalLoadConfig)
assertNoError(err, t, "EvalVariable")
if var1.Value != "foobar" {
t.Fatalf("expected 'foobar' got %q", var1.Value)
}
})
}
func TestClientServer_exit(t *testing.T) {
protest.AllowRecording(t)
withTestClient2("continuetestprog", t, func(c service.Client) {
......@@ -1350,7 +1421,7 @@ func TestClientServer_RestartBreakpointPosition(t *testing.T) {
}
_, err = c.Halt()
assertNoError(err, t, "Halt")
_, err = c.Restart()
_, err = c.Restart(false)
assertNoError(err, t, "Restart")
bps, err := c.ListBreakpoints()
assertNoError(err, t, "ListBreakpoints")
......@@ -1574,7 +1645,8 @@ func TestAcceptMulticlient(t *testing.T) {
AcceptMulti: true,
DisconnectChan: disconnectChan,
Debugger: debugger.Config{
Backend: testBackend,
Backend: testBackend,
ExecuteKind: debugger.ExecutingGeneratedTest,
},
})
if err := server.Run(); err != nil {
......@@ -1826,7 +1898,7 @@ func TestRerecord(t *testing.T) {
t0 := gett()
_, err = c.RestartFrom(false, "", false, nil)
_, err = c.RestartFrom(false, "", false, nil, false)
assertNoError(err, t, "First restart")
t1 := gett()
......@@ -1836,7 +1908,7 @@ func TestRerecord(t *testing.T) {
time.Sleep(2 * time.Second) // make sure that we're not running inside the same second
_, err = c.RestartFrom(true, "", false, nil)
_, err = c.RestartFrom(true, "", false, nil, false)
assertNoError(err, t, "Second restart")
t2 := gett()
......@@ -1901,7 +1973,7 @@ func TestStopRecording(t *testing.T) {
// try rerecording
go func() {
c.RestartFrom(true, "", false, nil)
c.RestartFrom(true, "", false, nil, false)
}()
time.Sleep(time.Second) // hopefully the re-recording started...
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册