*: Add --tty flag for debug / exec

This flag allows users on UNIX systems to set the tty for the program
being debugged by Delve. This is useful for debugging command line
applications which need access to their own TTY, and also for
controlling the output of the debugged programs so that IDEs may open a
dedicated terminal to show the output for the process.
This commit is contained in:
Derek Parker
2020-04-04 15:19:35 -07:00
parent c3a4d726e2
commit 3e60ae202b
23 changed files with 170 additions and 25 deletions

View File

@ -3,18 +3,25 @@
package debugger
import (
"bytes"
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
"testing"
"github.com/creack/pty"
"github.com/go-delve/delve/pkg/gobuild"
protest "github.com/go-delve/delve/pkg/proc/test"
"github.com/go-delve/delve/service/api"
)
func TestDebugger_LaunchNoExecutablePerm(t *testing.T) {
defer func() {
os.Setenv("GOOS", runtime.GOOS)
os.Setenv("GOARCH", runtime.GOARCH)
}()
fixturesDir := protest.FindFixturesDir()
buildtestdir := filepath.Join(fixturesDir, "buildtest")
debugname := "debug"
@ -29,10 +36,10 @@ func TestDebugger_LaunchNoExecutablePerm(t *testing.T) {
}
os.Setenv("GOOS", switchOS[runtime.GOOS])
exepath := filepath.Join(buildtestdir, debugname)
defer os.Remove(exepath)
if err := gobuild.GoBuild(debugname, []string{buildtestdir}, fmt.Sprintf("-o %s", exepath)); err != nil {
t.Fatalf("go build error %v", err)
}
defer os.Remove(exepath)
if err := os.Chmod(exepath, 0644); err != nil {
t.Fatal(err)
}
@ -45,3 +52,46 @@ func TestDebugger_LaunchNoExecutablePerm(t *testing.T) {
t.Fatalf("expected error \"%s\" got \"%v\"", api.ErrNotExecutable, err)
}
}
func TestDebugger_LaunchWithTTY(t *testing.T) {
if os.Getenv("TRAVIS") == "true" {
if _, err := exec.LookPath("lsof"); err != nil {
t.Skip("skipping test in CI, system does not contain lsof")
}
}
// Ensure no env meddling is leftover from previous tests.
os.Setenv("GOOS", runtime.GOOS)
os.Setenv("GOARCH", runtime.GOARCH)
p, tty, err := pty.Open()
if err != nil {
t.Fatal(err)
}
defer p.Close()
defer tty.Close()
fixturesDir := protest.FindFixturesDir()
buildtestdir := filepath.Join(fixturesDir, "buildtest")
debugname := "debugtty"
exepath := filepath.Join(buildtestdir, debugname)
if err := gobuild.GoBuild(debugname, []string{buildtestdir}, fmt.Sprintf("-o %s", exepath)); err != nil {
t.Fatalf("go build error %v", err)
}
defer os.Remove(exepath)
var backend string
protest.DefaultTestBackend(&backend)
conf := &Config{TTY: tty.Name(), Backend: backend}
pArgs := []string{exepath}
d, err := New(conf, pArgs)
if err != nil {
t.Fatal(err)
}
cmd := exec.Command("lsof", "-p", fmt.Sprintf("%d", d.ProcessPid()))
result, err := cmd.CombinedOutput()
if err != nil {
t.Fatal(err)
}
if !bytes.Contains(result, []byte(tty.Name())) {
t.Fatal("process open file list does not contain expected tty")
}
}