github.com/likebike/go--@v0.0.0-20190911215757-0bd925d16e96/go/src/runtime/runtime-lldb_test.go (about)

     1  // Copyright 2016 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package runtime_test
     6  
     7  import (
     8  	"internal/testenv"
     9  	"io/ioutil"
    10  	"os"
    11  	"os/exec"
    12  	"path/filepath"
    13  	"runtime"
    14  	"strings"
    15  	"testing"
    16  )
    17  
    18  var lldbPath string
    19  
    20  func checkLldbPython(t *testing.T) {
    21  	cmd := exec.Command("lldb", "-P")
    22  	out, err := cmd.CombinedOutput()
    23  	if err != nil {
    24  		t.Skipf("skipping due to issue running lldb: %v\n%s", err, out)
    25  	}
    26  	lldbPath = strings.TrimSpace(string(out))
    27  
    28  	cmd = exec.Command("/usr/bin/python2.7", "-c", "import sys;sys.path.append(sys.argv[1]);import lldb; print('go lldb python support')", lldbPath)
    29  	out, err = cmd.CombinedOutput()
    30  
    31  	if err != nil {
    32  		t.Skipf("skipping due to issue running python: %v\n%s", err, out)
    33  	}
    34  	if string(out) != "go lldb python support\n" {
    35  		t.Skipf("skipping due to lack of python lldb support: %s", out)
    36  	}
    37  
    38  	if runtime.GOOS == "darwin" {
    39  		// Try to see if we have debugging permissions.
    40  		cmd = exec.Command("/usr/sbin/DevToolsSecurity", "-status")
    41  		out, err = cmd.CombinedOutput()
    42  		if err != nil {
    43  			t.Skipf("DevToolsSecurity failed: %v", err)
    44  		} else if !strings.Contains(string(out), "enabled") {
    45  			t.Skip(string(out))
    46  		}
    47  		cmd = exec.Command("/usr/bin/groups")
    48  		out, err = cmd.CombinedOutput()
    49  		if err != nil {
    50  			t.Skipf("groups failed: %v", err)
    51  		} else if !strings.Contains(string(out), "_developer") {
    52  			t.Skip("Not in _developer group")
    53  		}
    54  	}
    55  }
    56  
    57  const lldbHelloSource = `
    58  package main
    59  import "fmt"
    60  func main() {
    61  	mapvar := make(map[string]string,5)
    62  	mapvar["abc"] = "def"
    63  	mapvar["ghi"] = "jkl"
    64  	intvar := 42
    65  	ptrvar := &intvar
    66  	fmt.Println("hi") // line 10
    67  	_ = ptrvar
    68  }
    69  `
    70  
    71  const lldbScriptSource = `
    72  import sys
    73  sys.path.append(sys.argv[1])
    74  import lldb
    75  import os
    76  
    77  TIMEOUT_SECS = 5
    78  
    79  debugger = lldb.SBDebugger.Create()
    80  debugger.SetAsync(True)
    81  target = debugger.CreateTargetWithFileAndArch("a.exe", None)
    82  if target:
    83    print "Created target"
    84    main_bp = target.BreakpointCreateByLocation("main.go", 10)
    85    if main_bp:
    86      print "Created breakpoint"
    87    process = target.LaunchSimple(None, None, os.getcwd())
    88    if process:
    89      print "Process launched"
    90      listener = debugger.GetListener()
    91      process.broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged)
    92      while True:
    93        event = lldb.SBEvent()
    94        if listener.WaitForEvent(TIMEOUT_SECS, event):
    95          if lldb.SBProcess.GetRestartedFromEvent(event):
    96            continue
    97          state = process.GetState()
    98          if state in [lldb.eStateUnloaded, lldb.eStateLaunching, lldb.eStateRunning]:
    99            continue
   100        else:
   101          print "Timeout launching"
   102        break
   103      if state == lldb.eStateStopped:
   104        for t in process.threads:
   105          if t.GetStopReason() == lldb.eStopReasonBreakpoint:
   106            print "Hit breakpoint"
   107            frame = t.GetFrameAtIndex(0)
   108            if frame:
   109              if frame.line_entry:
   110                print "Stopped at %s:%d" % (frame.line_entry.file.basename, frame.line_entry.line)
   111              if frame.function:
   112                print "Stopped in %s" % (frame.function.name,)
   113              var = frame.FindVariable('intvar')
   114              if var:
   115                print "intvar = %s" % (var.GetValue(),)
   116              else:
   117                print "no intvar"
   118      else:
   119        print "Process state", state
   120      process.Destroy()
   121  else:
   122    print "Failed to create target a.exe"
   123  
   124  lldb.SBDebugger.Destroy(debugger)
   125  sys.exit()
   126  `
   127  
   128  const expectedLldbOutput = `Created target
   129  Created breakpoint
   130  Process launched
   131  Hit breakpoint
   132  Stopped at main.go:10
   133  Stopped in main.main
   134  intvar = 42
   135  `
   136  
   137  func TestLldbPython(t *testing.T) {
   138  	testenv.MustHaveGoBuild(t)
   139  	if final := os.Getenv("GOROOT_FINAL"); final != "" && runtime.GOROOT() != final {
   140  		t.Skip("gdb test can fail with GOROOT_FINAL pending")
   141  	}
   142  
   143  	checkLldbPython(t)
   144  
   145  	dir, err := ioutil.TempDir("", "go-build")
   146  	if err != nil {
   147  		t.Fatalf("failed to create temp directory: %v", err)
   148  	}
   149  	defer os.RemoveAll(dir)
   150  
   151  	src := filepath.Join(dir, "main.go")
   152  	err = ioutil.WriteFile(src, []byte(lldbHelloSource), 0644)
   153  	if err != nil {
   154  		t.Fatalf("failed to create file: %v", err)
   155  	}
   156  
   157  	cmd := exec.Command(testenv.GoToolPath(t), "build", "-gcflags=all=-N -l", "-o", "a.exe")
   158  	cmd.Dir = dir
   159  	out, err := cmd.CombinedOutput()
   160  	if err != nil {
   161  		t.Fatalf("building source %v\n%s", err, out)
   162  	}
   163  
   164  	src = filepath.Join(dir, "script.py")
   165  	err = ioutil.WriteFile(src, []byte(lldbScriptSource), 0755)
   166  	if err != nil {
   167  		t.Fatalf("failed to create script: %v", err)
   168  	}
   169  
   170  	cmd = exec.Command("/usr/bin/python2.7", "script.py", lldbPath)
   171  	cmd.Dir = dir
   172  	got, _ := cmd.CombinedOutput()
   173  
   174  	if string(got) != expectedLldbOutput {
   175  		if strings.Contains(string(got), "Timeout launching") {
   176  			t.Skip("Timeout launching")
   177  		}
   178  		t.Fatalf("Unexpected lldb output:\n%s", got)
   179  	}
   180  }