Source file
src/cmd/addr2line/addr2line_test.go
1
2
3
4
5 package main
6
7 import (
8 "bufio"
9 "bytes"
10 "internal/testenv"
11 "os"
12 "path/filepath"
13 "runtime"
14 "strings"
15 "testing"
16 )
17
18
19
20 func TestMain(m *testing.M) {
21 if os.Getenv("GO_ADDR2LINETEST_IS_ADDR2LINE") != "" {
22 main()
23 os.Exit(0)
24 }
25
26 os.Setenv("GO_ADDR2LINETEST_IS_ADDR2LINE", "1")
27 os.Exit(m.Run())
28 }
29
30 func loadSyms(t *testing.T, dbgExePath string) map[string]string {
31 cmd := testenv.Command(t, testenv.GoToolPath(t), "tool", "nm", dbgExePath)
32 out, err := cmd.CombinedOutput()
33 if err != nil {
34 t.Fatalf("%v: %v\n%s", cmd, err, string(out))
35 }
36 syms := make(map[string]string)
37 scanner := bufio.NewScanner(bytes.NewReader(out))
38 for scanner.Scan() {
39 f := strings.Fields(scanner.Text())
40 if len(f) < 3 {
41 continue
42 }
43 syms[f[2]] = f[0]
44 }
45 if err := scanner.Err(); err != nil {
46 t.Fatalf("error reading symbols: %v", err)
47 }
48 return syms
49 }
50
51 func runAddr2Line(t *testing.T, dbgExePath, addr string) (funcname, path, lineno string) {
52 cmd := testenv.Command(t, testenv.Executable(t), dbgExePath)
53 cmd.Stdin = strings.NewReader(addr)
54 out, err := cmd.CombinedOutput()
55 if err != nil {
56 t.Fatalf("go tool addr2line %v: %v\n%s", os.Args[0], err, string(out))
57 }
58 f := strings.Split(string(out), "\n")
59 if len(f) < 3 && f[2] == "" {
60 t.Fatal("addr2line output must have 2 lines")
61 }
62 funcname = f[0]
63 pathAndLineNo := f[1]
64 f = strings.Split(pathAndLineNo, ":")
65 if runtime.GOOS == "windows" && len(f) == 3 {
66
67 f = []string{f[0] + ":" + f[1], f[2]}
68 }
69 if len(f) != 2 {
70 t.Fatalf("no line number found in %q", pathAndLineNo)
71 }
72 return funcname, f[0], f[1]
73 }
74
75 const symName = "cmd/addr2line.TestAddr2Line"
76
77 func testAddr2Line(t *testing.T, dbgExePath, addr string) {
78 funcName, srcPath, srcLineNo := runAddr2Line(t, dbgExePath, addr)
79 if symName != funcName {
80 t.Fatalf("expected function name %v; got %v", symName, funcName)
81 }
82 fi1, err := os.Stat("addr2line_test.go")
83 if err != nil {
84 t.Fatalf("Stat failed: %v", err)
85 }
86
87
88 srcPath = filepath.FromSlash(srcPath)
89 fi2, err := os.Stat(srcPath)
90 if err != nil {
91 t.Fatalf("Stat failed: %v", err)
92 }
93 if !os.SameFile(fi1, fi2) {
94 t.Fatalf("addr2line_test.go and %s are not same file", srcPath)
95 }
96 if want := "102"; srcLineNo != want {
97 t.Fatalf("line number = %v; want %s", srcLineNo, want)
98 }
99 }
100
101
102 func TestAddr2Line(t *testing.T) {
103 testenv.MustHaveGoBuild(t)
104
105 tmpDir := t.TempDir()
106
107
108
109 exepath := filepath.Join(tmpDir, "testaddr2line_test.exe")
110 out, err := testenv.Command(t, testenv.GoToolPath(t), "test", "-c", "-o", exepath, "cmd/addr2line").CombinedOutput()
111 if err != nil {
112 t.Fatalf("go test -c -o %v cmd/addr2line: %v\n%s", exepath, err, string(out))
113 }
114
115 syms := loadSyms(t, exepath)
116
117 testAddr2Line(t, exepath, syms[symName])
118 testAddr2Line(t, exepath, "0x"+syms[symName])
119 }
120
View as plain text