github.com/stingnevermore/go@v0.0.0-20180120041312-3810f5bfed72/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 }