src/cmd/addr2line/addr2line_test.go GO 120 lines View on github.com → Search inside
1// Copyright 2014 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.45package main67import (8	"bufio"9	"bytes"10	"internal/testenv"11	"os"12	"path/filepath"13	"runtime"14	"strings"15	"testing"16)1718// TestMain executes the test binary as the addr2line command if19// GO_ADDR2LINETEST_IS_ADDR2LINE is set, and runs the tests otherwise.20func TestMain(m *testing.M) {21	if os.Getenv("GO_ADDR2LINETEST_IS_ADDR2LINE") != "" {22		main()23		os.Exit(0)24	}2526	os.Setenv("GO_ADDR2LINETEST_IS_ADDR2LINE", "1") // Set for subprocesses to inherit.27	os.Exit(m.Run())28}2930func 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			continue42		}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 syms49}5051func 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		// Reattach drive letter.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}7475const symName = "cmd/addr2line.TestAddr2Line"7677func 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	}8687	// Debug paths are stored slash-separated, so convert to system-native.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}100101// This is line 101. The test depends on that.102func TestAddr2Line(t *testing.T) {103	testenv.MustHaveGoBuild(t)104105	tmpDir := t.TempDir()106107	// Build copy of test binary with debug symbols,108	// since the one running now may not have them.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	}114115	syms := loadSyms(t, exepath)116117	testAddr2Line(t, exepath, syms[symName])118	testAddr2Line(t, exepath, "0x"+syms[symName])119}

Code quality findings 2

Map created without size hint before being populated in a loop; provide capacity hint to reduce allocations
info performance map-without-size-hint
syms := make(map[string]string)
Can cause issues on Windows consider filepath.Join instead
info correctness path-join-windows
exepath := filepath.Join(tmpDir, "testaddr2line_test.exe")

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.