2015-03-20 21:11:11 +00:00
|
|
|
package terminal
|
2014-05-20 21:28:24 +00:00
|
|
|
|
2014-05-20 23:09:34 +00:00
|
|
|
import (
|
2015-05-04 22:31:13 +00:00
|
|
|
"fmt"
|
2016-02-13 20:00:21 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"net"
|
|
|
|
"os"
|
2015-09-29 16:40:12 +00:00
|
|
|
"path/filepath"
|
2016-02-13 20:00:21 +00:00
|
|
|
"strings"
|
2014-05-20 23:09:34 +00:00
|
|
|
"testing"
|
2015-09-29 16:40:12 +00:00
|
|
|
|
|
|
|
"github.com/derekparker/delve/proc/test"
|
2016-02-13 20:00:21 +00:00
|
|
|
"github.com/derekparker/delve/service"
|
2016-01-27 12:33:37 +00:00
|
|
|
"github.com/derekparker/delve/service/api"
|
2016-02-13 20:00:21 +00:00
|
|
|
"github.com/derekparker/delve/service/rpc"
|
2014-05-20 23:09:34 +00:00
|
|
|
)
|
2014-05-20 21:28:24 +00:00
|
|
|
|
2016-02-13 20:00:21 +00:00
|
|
|
type FakeTerminal struct {
|
2016-02-27 23:02:55 +00:00
|
|
|
*Term
|
|
|
|
t testing.TB
|
2016-02-13 20:00:21 +00:00
|
|
|
}
|
|
|
|
|
2016-02-27 23:02:55 +00:00
|
|
|
func (ft *FakeTerminal) Exec(cmdstr string) (outstr string, err error) {
|
2016-02-13 20:00:21 +00:00
|
|
|
cmdstr, args := parseCommand(cmdstr)
|
2016-02-27 23:02:55 +00:00
|
|
|
cmd := ft.cmds.Find(cmdstr)
|
2016-02-13 20:00:21 +00:00
|
|
|
|
|
|
|
outfh, err := ioutil.TempFile("", "cmdtestout")
|
|
|
|
if err != nil {
|
2016-02-27 23:02:55 +00:00
|
|
|
ft.t.Fatalf("could not create temporary file: %v", err)
|
2016-02-13 20:00:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
stdout, stderr := os.Stdout, os.Stderr
|
|
|
|
os.Stdout, os.Stderr = outfh, outfh
|
|
|
|
defer func() {
|
|
|
|
os.Stdout, os.Stderr = stdout, stderr
|
|
|
|
outfh.Close()
|
|
|
|
outbs, err1 := ioutil.ReadFile(outfh.Name())
|
|
|
|
if err1 != nil {
|
2016-02-27 23:02:55 +00:00
|
|
|
ft.t.Fatalf("could not read temporary output file: %v", err)
|
2016-02-13 20:00:21 +00:00
|
|
|
}
|
|
|
|
outstr = string(outbs)
|
|
|
|
os.Remove(outfh.Name())
|
|
|
|
}()
|
2016-02-27 23:02:55 +00:00
|
|
|
err = cmd(ft.Term, args)
|
2016-02-13 20:00:21 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2016-02-27 23:02:55 +00:00
|
|
|
func (ft *FakeTerminal) MustExec(cmdstr string) string {
|
|
|
|
outstr, err := ft.Exec(cmdstr)
|
2016-02-13 20:00:21 +00:00
|
|
|
if err != nil {
|
2016-02-27 23:02:55 +00:00
|
|
|
ft.t.Fatalf("Error executing <%s>: %v", cmdstr, err)
|
2016-02-13 20:00:21 +00:00
|
|
|
}
|
|
|
|
return outstr
|
|
|
|
}
|
|
|
|
|
|
|
|
func withTestTerminal(name string, t testing.TB, fn func(*FakeTerminal)) {
|
|
|
|
listener, err := net.Listen("tcp", "localhost:0")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("couldn't start listener: %s\n", err)
|
|
|
|
}
|
|
|
|
defer listener.Close()
|
|
|
|
server := rpc.NewServer(&service.Config{
|
|
|
|
Listener: listener,
|
|
|
|
ProcessArgs: []string{test.BuildFixture(name).Path},
|
|
|
|
}, false)
|
|
|
|
if err := server.Run(); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
client := rpc.NewClient(listener.Addr().String())
|
|
|
|
defer func() {
|
|
|
|
client.Detach(true)
|
|
|
|
}()
|
2016-02-27 23:02:55 +00:00
|
|
|
ft := &FakeTerminal{
|
|
|
|
t: t,
|
|
|
|
Term: New(client, nil),
|
|
|
|
}
|
|
|
|
fn(ft)
|
2016-02-13 20:00:21 +00:00
|
|
|
}
|
|
|
|
|
2014-05-20 21:28:24 +00:00
|
|
|
func TestCommandDefault(t *testing.T) {
|
|
|
|
var (
|
2014-11-14 05:51:32 +00:00
|
|
|
cmds = Commands{}
|
2014-05-20 21:28:24 +00:00
|
|
|
cmd = cmds.Find("non-existant-command")
|
|
|
|
)
|
|
|
|
|
2015-11-02 06:30:12 +00:00
|
|
|
err := cmd(nil, "")
|
2014-05-20 21:28:24 +00:00
|
|
|
if err == nil {
|
|
|
|
t.Fatal("cmd() did not default")
|
|
|
|
}
|
|
|
|
|
|
|
|
if err.Error() != "command not available" {
|
|
|
|
t.Fatal("wrong command output")
|
|
|
|
}
|
|
|
|
}
|
2014-05-20 23:09:34 +00:00
|
|
|
|
2014-05-21 15:15:58 +00:00
|
|
|
func TestCommandReplay(t *testing.T) {
|
2015-03-20 21:11:11 +00:00
|
|
|
cmds := DebugCommands(nil)
|
2015-11-02 06:30:12 +00:00
|
|
|
cmds.Register("foo", func(t *Term, args string) error { return fmt.Errorf("registered command") }, "foo command")
|
2014-05-21 15:15:58 +00:00
|
|
|
cmd := cmds.Find("foo")
|
|
|
|
|
2015-11-02 06:30:12 +00:00
|
|
|
err := cmd(nil, "")
|
2014-05-21 15:15:58 +00:00
|
|
|
if err.Error() != "registered command" {
|
|
|
|
t.Fatal("wrong command output")
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd = cmds.Find("")
|
2015-11-02 06:30:12 +00:00
|
|
|
err = cmd(nil, "")
|
2014-05-21 15:15:58 +00:00
|
|
|
if err.Error() != "registered command" {
|
|
|
|
t.Fatal("wrong command output")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandReplayWithoutPreviousCommand(t *testing.T) {
|
|
|
|
var (
|
2015-03-20 21:11:11 +00:00
|
|
|
cmds = DebugCommands(nil)
|
2014-05-21 15:15:58 +00:00
|
|
|
cmd = cmds.Find("")
|
2015-11-02 06:30:12 +00:00
|
|
|
err = cmd(nil, "")
|
2014-05-21 15:15:58 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Error("Null command not returned", err)
|
|
|
|
}
|
|
|
|
}
|
2015-05-30 07:23:41 +00:00
|
|
|
|
|
|
|
func TestCommandThread(t *testing.T) {
|
|
|
|
var (
|
|
|
|
cmds = DebugCommands(nil)
|
|
|
|
cmd = cmds.Find("thread")
|
|
|
|
)
|
|
|
|
|
2015-11-02 06:30:12 +00:00
|
|
|
err := cmd(nil, "")
|
2015-05-30 07:23:41 +00:00
|
|
|
if err == nil {
|
|
|
|
t.Fatal("thread terminal command did not default")
|
|
|
|
}
|
|
|
|
|
|
|
|
if err.Error() != "you must specify a thread" {
|
|
|
|
t.Fatal("wrong command output: ", err.Error())
|
|
|
|
}
|
|
|
|
}
|
2015-09-29 16:40:12 +00:00
|
|
|
|
|
|
|
func TestExecuteFile(t *testing.T) {
|
|
|
|
breakCount := 0
|
|
|
|
traceCount := 0
|
|
|
|
c := &Commands{
|
|
|
|
client: nil,
|
|
|
|
cmds: []command{
|
2015-11-02 06:30:12 +00:00
|
|
|
{aliases: []string{"trace"}, cmdFn: func(t *Term, args string) error {
|
2015-09-29 16:40:12 +00:00
|
|
|
traceCount++
|
|
|
|
return nil
|
|
|
|
}},
|
2015-11-02 06:30:12 +00:00
|
|
|
{aliases: []string{"break"}, cmdFn: func(t *Term, args string) error {
|
2015-09-29 16:40:12 +00:00
|
|
|
breakCount++
|
|
|
|
return nil
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
fixturesDir := test.FindFixturesDir()
|
|
|
|
|
|
|
|
err := c.executeFile(nil, filepath.Join(fixturesDir, "bpfile"))
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("executeFile: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if breakCount != 1 || traceCount != 1 {
|
|
|
|
t.Fatalf("Wrong counts break: %d trace: %d\n", breakCount, traceCount)
|
|
|
|
}
|
|
|
|
}
|
2016-01-27 12:33:37 +00:00
|
|
|
|
|
|
|
func TestIssue354(t *testing.T) {
|
2016-02-06 06:00:48 +00:00
|
|
|
printStack([]api.Stackframe{}, "")
|
2016-01-27 12:33:37 +00:00
|
|
|
printStack([]api.Stackframe{{api.Location{PC: 0, File: "irrelevant.go", Line: 10, Function: nil}, nil, nil}}, "")
|
|
|
|
}
|
2016-02-13 20:00:21 +00:00
|
|
|
|
|
|
|
func TestIssue411(t *testing.T) {
|
|
|
|
withTestTerminal("math", t, func(term *FakeTerminal) {
|
|
|
|
term.MustExec("break math.go:8")
|
|
|
|
term.MustExec("trace math.go:9")
|
|
|
|
term.MustExec("continue")
|
|
|
|
out := term.MustExec("next")
|
|
|
|
if !strings.HasPrefix(out, "> main.main()") {
|
|
|
|
t.Fatalf("Wrong output for next: <%s>", out)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|