// Run this shell script, but do it in Go so it can be run by "go test". // // replace the word LINE with the line number < testdata/test.go > testdata/test_line.go // go build -o ./testcover // ./testcover -mode=count -var=CoverTest -o ./testdata/test_cover.go testdata/test_line.go // go run ./testdata/main.go ./testdata/test.go // func TestCover(t *testing.T) { testenv.MustHaveGoBuild(t) // Read in the test file (testTest) and write it, with LINEs specified, to coverInput. file, err := ioutil.ReadFile(testTest) if err != nil { t.Fatal(err) } lines := bytes.Split(file, []byte("\n")) for i, line := range lines { lines[i] = bytes.Replace(line, []byte("LINE"), []byte(fmt.Sprint(i+1)), -1) } if err := ioutil.WriteFile(coverInput, bytes.Join(lines, []byte("\n")), 0666); err != nil { t.Fatal(err) } // defer removal of test_line.go if !debug { defer os.Remove(coverInput) } // go build -o testcover cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", testcover) run(cmd, t) // defer removal of testcover defer os.Remove(testcover) // ./testcover -mode=count -var=thisNameMustBeVeryLongToCauseOverflowOfCounterIncrementStatementOntoNextLineForTest -o ./testdata/test_cover.go testdata/test_line.go cmd = exec.Command(testcover, "-mode=count", "-var=thisNameMustBeVeryLongToCauseOverflowOfCounterIncrementStatementOntoNextLineForTest", "-o", coverOutput, coverInput) run(cmd, t) // defer removal of ./testdata/test_cover.go if !debug { defer os.Remove(coverOutput) } // go run ./testdata/main.go ./testdata/test.go cmd = exec.Command(testenv.GoToolPath(t), "run", testMain, coverOutput) run(cmd, t) file, err = ioutil.ReadFile(coverOutput) if err != nil { t.Fatal(err) } // compiler directive must appear right next to function declaration. if got, err := regexp.MatchString(".*\n//go:nosplit\nfunc someFunction().*", string(file)); err != nil || !got { t.Errorf("misplaced compiler directive: got=(%v, %v); want=(true; nil)", got, err) } // No other comments should be present in generated code. c := ".*// This comment shouldn't appear in generated go code.*" if got, err := regexp.MatchString(c, string(file)); err != nil || got { t.Errorf("non compiler directive comment %q found. got=(%v, %v); want=(false; nil)", c, got, err) } }
// Test that pack-created archives can be understood by the tools. func TestHello(t *testing.T) { testenv.MustHaveGoBuild(t) dir := tmpDir(t) defer os.RemoveAll(dir) hello := filepath.Join(dir, "hello.go") prog := ` package main func main() { println("hello world") } ` err := ioutil.WriteFile(hello, []byte(prog), 0666) if err != nil { t.Fatal(err) } run := func(args ...string) string { return doRun(t, dir, args...) } goBin := testenv.GoToolPath(t) run(goBin, "build", "cmd/pack") // writes pack binary to dir run(goBin, "tool", "compile", "hello.go") run("./pack", "grc", "hello.a", "hello.o") run(goBin, "tool", "link", "-o", "a.out", "hello.a") out := run("./a.out") if out != "hello world\n" { t.Fatalf("incorrect output: %q, want %q", out, "hello world\n") } }
// TestLarge generates a very large file to verify that large // program builds successfully, in particular, too-far // conditional branches are fixed. func TestLarge(t *testing.T) { if testing.Short() { t.Skip("Skip in short mode") } testenv.MustHaveGoBuild(t) dir, err := ioutil.TempDir("", "testlarge") if err != nil { t.Fatalf("could not create directory: %v", err) } defer os.RemoveAll(dir) // generate a very large function buf := bytes.NewBuffer(make([]byte, 0, 7000000)) gen(buf) tmpfile := filepath.Join(dir, "x.s") err = ioutil.WriteFile(tmpfile, buf.Bytes(), 0644) if err != nil { t.Fatalf("can't write output: %v\n", err) } // build generated file cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile) cmd.Env = []string{"GOARCH=arm64", "GOOS=linux"} out, err := cmd.CombinedOutput() if err != nil { t.Errorf("Build failed: %v, output: %s", err, out) } }
// runTests assures that the package and its dependencies is // built with instrumentation enabled and returns the output of 'go test' // which includes possible data race reports from ThreadSanitizer. func runTests(t *testing.T) ([]byte, error) { tests, err := filepath.Glob("./testdata/*_test.go") if err != nil { return nil, err } args := []string{"test", "-race", "-v"} args = append(args, tests...) cmd := exec.Command(testenv.GoToolPath(t), args...) // The following flags turn off heuristics that suppress seemingly identical reports. // It is required because the tests contain a lot of data races on the same addresses // (the tests are simple and the memory is constantly reused). for _, env := range os.Environ() { if strings.HasPrefix(env, "GOMAXPROCS=") || strings.HasPrefix(env, "GODEBUG=") { continue } cmd.Env = append(cmd.Env, env) } // We set GOMAXPROCS=1 to prevent test flakiness. // There are two sources of flakiness: // 1. Some tests rely on particular execution order. // If the order is different, race does not happen at all. // 2. Ironically, ThreadSanitizer runtime contains a logical race condition // that can lead to false negatives if racy accesses happen literally at the same time. // Tests used to work reliably in the good old days of GOMAXPROCS=1. // So let's set it for now. A more reliable solution is to explicitly annotate tests // with required execution order by means of a special "invisible" synchronization primitive // (that's what is done for C++ ThreadSanitizer tests). This is issue #14119. cmd.Env = append(cmd.Env, "GOMAXPROCS=1", "GORACE=suppress_equal_stacks=0 suppress_equal_addresses=0 exitcode=0", ) return cmd.CombinedOutput() }
// Test that cmd/go doesn't link in the HTTP server. // // This catches accidental dependencies between the HTTP transport and // server code. func TestCmdGoNoHTTPServer(t *testing.T) { goBin := testenv.GoToolPath(t) out, err := exec.Command("go", "tool", "nm", goBin).CombinedOutput() if err != nil { t.Fatalf("go tool nm: %v: %s", err, out) } wantSym := map[string]bool{ // Verify these exist: (sanity checking this test) "net/http.(*Client).Get": true, "net/http.(*Transport).RoundTrip": true, // Verify these don't exist: "net/http.http2Server": false, "net/http.(*Server).Serve": false, "net/http.(*ServeMux).ServeHTTP": false, "net/http.DefaultServeMux": false, } for sym, want := range wantSym { got := bytes.Contains(out, []byte(sym)) if !want && got { t.Errorf("cmd/go unexpectedly links in HTTP server code; found symbol %q in cmd/go", sym) } if want && !got { t.Errorf("expected to find symbol %q in cmd/go; not found", sym) } } }
func asmOutput(t *testing.T, s string) []byte { tmpdir, err := ioutil.TempDir("", "progedittest") if err != nil { t.Fatal(err) } defer os.RemoveAll(tmpdir) tmpfile, err := os.Create(filepath.Join(tmpdir, "input.s")) if err != nil { t.Fatal(err) } defer tmpfile.Close() _, err = tmpfile.WriteString(s) if err != nil { t.Fatal(err) } cmd := exec.Command( testenv.GoToolPath(t), "tool", "asm", "-S", "-dynlink", "-o", filepath.Join(tmpdir, "output.6"), tmpfile.Name()) var env []string for _, v := range os.Environ() { if !strings.HasPrefix(v, "GOARCH=") { env = append(env, v) } } cmd.Env = append(env, "GOARCH=amd64") asmout, err := cmd.CombinedOutput() if err != nil { t.Fatalf("error %s output %s", err, asmout) } return asmout }
func TestNoRaceCgoSync(t *testing.T) { cmd := exec.Command(testenv.GoToolPath(t), "run", "-race", "cgo_test_main.go") cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { t.Fatalf("program exited with error: %v\n", err) } }
// Make sure "hello world" does not link in all the // fmt.scanf routines. See issue 6853. func TestScanfRemoval(t *testing.T) { testenv.MustHaveGoBuild(t) // Make a directory to work in. dir, err := ioutil.TempDir("", "issue6853a-") if err != nil { log.Fatalf("could not create directory: %v", err) } defer os.RemoveAll(dir) // Create source. src := filepath.Join(dir, "test.go") f, err := os.Create(src) if err != nil { log.Fatalf("could not create source file: %v", err) } f.Write([]byte(` package main import "fmt" func main() { fmt.Println("hello world") } `)) f.Close() // Name of destination. dst := filepath.Join(dir, "test") // Compile source. cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", dst, src) out, err := cmd.CombinedOutput() if err != nil { log.Fatalf("could not build target: %v", err) } // Check destination to see if scanf code was included. cmd = exec.Command(testenv.GoToolPath(t), "tool", "nm", dst) out, err = cmd.CombinedOutput() if err != nil { log.Fatalf("could not read target: %v", err) } if bytes.Contains(out, []byte("scanInt")) { log.Fatalf("scanf code not removed from helloworld") } }
// TestGdbBacktrace tests that gdb can unwind the stack correctly // using only the DWARF debug info. func TestGdbBacktrace(t *testing.T) { t.Parallel() checkGdbEnvironment(t) checkGdbVersion(t) if runtime.GOOS == "netbsd" { testenv.SkipFlaky(t, 15603) } dir, err := ioutil.TempDir("", "go-build") if err != nil { t.Fatalf("failed to create temp directory: %v", err) } defer os.RemoveAll(dir) // Build the source code. src := filepath.Join(dir, "main.go") err = ioutil.WriteFile(src, []byte(backtraceSource), 0644) if err != nil { t.Fatalf("failed to create file: %v", err) } cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", "a.exe") cmd.Dir = dir out, err := testEnv(cmd).CombinedOutput() if err != nil { t.Fatalf("building source %v\n%s", err, out) } // Execute gdb commands. args := []string{"-nx", "-batch", "-ex", "set startup-with-shell off", "-ex", "break main.eee", "-ex", "run", "-ex", "backtrace", "-ex", "continue", filepath.Join(dir, "a.exe"), } got, _ := exec.Command("gdb", args...).CombinedOutput() // Check that the backtrace matches the source code. bt := []string{ "eee", "ddd", "ccc", "bbb", "aaa", "main", } for i, name := range bt { s := fmt.Sprintf("#%v.*main\\.%v", i, name) re := regexp.MustCompile(s) if found := re.Find(got) != nil; !found { t.Errorf("could not find '%v' in backtrace", s) t.Fatalf("gdb output:\n%v", string(got)) } } }
func dotest(t *testing.T) { testenv.MustHaveGoBuild(t) // For now, only works on amd64 platforms. if runtime.GOARCH != "amd64" { t.Skipf("skipping on non-AMD64 system %s", runtime.GOARCH) } var err error pclineTempDir, err = ioutil.TempDir("", "pclinetest") if err != nil { t.Fatal(err) } // This command builds pclinetest from pclinetest.asm; // the resulting binary looks like it was built from pclinetest.s, // but we have renamed it to keep it away from the go tool. pclinetestBinary = filepath.Join(pclineTempDir, "pclinetest") cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-o", pclinetestBinary+".o", "pclinetest.asm") cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { t.Fatal(err) } // stamp .o file as being 'package main' so that go tool link will accept it data, err := ioutil.ReadFile(pclinetestBinary + ".o") if err != nil { t.Fatal(err) } i := bytes.IndexByte(data, '\n') if i < 0 { t.Fatal("bad binary") } data = append(append(data[:i:i], "\nmain"...), data[i:]...) if err := ioutil.WriteFile(pclinetestBinary+".o", data, 0666); err != nil { t.Fatal(err) } cmd = exec.Command(testenv.GoToolPath(t), "tool", "link", "-H", "linux", "-o", pclinetestBinary, pclinetestBinary+".o") cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { t.Fatal(err) } }
func testDisasm(t *testing.T, flags ...string) { tmp, exe := buildObjdump(t) defer os.RemoveAll(tmp) goarch := runtime.GOARCH if *target != "" { f := strings.Split(*target, "/") if len(f) != 2 { t.Fatalf("-target argument must be goos/goarch") } defer os.Setenv("GOOS", os.Getenv("GOOS")) defer os.Setenv("GOARCH", os.Getenv("GOARCH")) os.Setenv("GOOS", f[0]) os.Setenv("GOARCH", f[1]) goarch = f[1] } hello := filepath.Join(tmp, "hello.exe") args := []string{"build", "-o", hello} args = append(args, flags...) args = append(args, "testdata/fmthello.go") out, err := exec.Command(testenv.GoToolPath(t), args...).CombinedOutput() if err != nil { t.Fatalf("go build fmthello.go: %v\n%s", err, out) } need := []string{ "fmthello.go:6", "TEXT main.main(SB)", } switch goarch { case "amd64", "386": need = append(need, x86Need...) case "arm": need = append(need, armNeed...) case "ppc64", "ppc64le": need = append(need, ppcNeed...) } out, err = exec.Command(exe, "-s", "main.main", hello).CombinedOutput() if err != nil { t.Fatalf("objdump fmthello.exe: %v\n%s", err, out) } text := string(out) ok := true for _, s := range need { if !strings.Contains(text, s) { t.Errorf("disassembly missing '%s'", s) ok = false } } if !ok { t.Logf("full disassembly:\n%s", text) } }
func TestDWARF(t *testing.T) { if runtime.GOOS != "windows" { t.Skip("skipping windows only test") } tmpdir, err := ioutil.TempDir("", "TestDWARF") if err != nil { t.Fatal("TempDir failed: ", err) } defer os.RemoveAll(tmpdir) prog := ` package main func main() { } ` src := filepath.Join(tmpdir, "a.go") exe := filepath.Join(tmpdir, "a.exe") err = ioutil.WriteFile(src, []byte(prog), 0644) output, err := exec.Command(testenv.GoToolPath(t), "build", "-o", exe, src).CombinedOutput() if err != nil { t.Fatalf("building test executable failed: %s %s", err, output) } f, err := Open(exe) if err != nil { t.Fatal(err) } defer f.Close() d, err := f.DWARF() if err != nil { t.Fatal(err) } // look for main.main r := d.Reader() for { e, err := r.Next() if err != nil { t.Fatal("r.Next:", err) } if e == nil { break } if e.Tag == dwarf.TagSubprogram { for _, f := range e.Field { if f.Attr == dwarf.AttrName && e.Val(dwarf.AttrName) == "main.main" { return } } } } t.Fatal("main.main not found") }
func compile(t *testing.T, dirname, filename string) string { cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", filename) cmd.Dir = dirname out, err := cmd.CombinedOutput() if err != nil { t.Logf("%s", out) t.Fatalf("go tool compile %s failed: %s", filename, err) } // filename should end with ".go" return filepath.Join(dirname, filename[:len(filename)-2]+"o") }
// compile compiles the package pkg for architecture arch and // returns the generated assembly. dir is a scratch directory. func compileToAsm(t *testing.T, dir, goarch, goos, pkg string) string { // Create source. src := filepath.Join(dir, "test.go") f, err := os.Create(src) if err != nil { panic(err) } f.Write([]byte(pkg)) f.Close() // First, install any dependencies we need. This builds the required export data // for any packages that are imported. // TODO: extract dependencies automatically? var stdout, stderr bytes.Buffer cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", filepath.Join(dir, "encoding/binary.a"), "encoding/binary") cmd.Env = mergeEnvLists([]string{"GOARCH=" + goarch, "GOOS=" + goos}, os.Environ()) cmd.Stdout = &stdout cmd.Stderr = &stderr if err := cmd.Run(); err != nil { panic(err) } if s := stdout.String(); s != "" { panic(fmt.Errorf("Stdout = %s\nWant empty", s)) } if s := stderr.String(); s != "" { panic(fmt.Errorf("Stderr = %s\nWant empty", s)) } // Now, compile the individual file for which we want to see the generated assembly. cmd = exec.Command(testenv.GoToolPath(t), "tool", "compile", "-I", dir, "-S", "-o", filepath.Join(dir, "out.o"), src) cmd.Env = mergeEnvLists([]string{"GOARCH=" + goarch, "GOOS=" + goos}, os.Environ()) cmd.Stdout = &stdout cmd.Stderr = &stderr if err := cmd.Run(); err != nil { panic(err) } if s := stderr.String(); s != "" { panic(fmt.Errorf("Stderr = %s\nWant empty", s)) } return stdout.String() }
// TestGdbAutotmpTypes ensures that types of autotmp variables appear in .debug_info // See bug #17830. func TestGdbAutotmpTypes(t *testing.T) { t.Parallel() checkGdbEnvironment(t) checkGdbVersion(t) dir, err := ioutil.TempDir("", "go-build") if err != nil { t.Fatalf("failed to create temp directory: %v", err) } defer os.RemoveAll(dir) // Build the source code. src := filepath.Join(dir, "main.go") err = ioutil.WriteFile(src, []byte(autotmpTypeSource), 0644) if err != nil { t.Fatalf("failed to create file: %v", err) } cmd := exec.Command(testenv.GoToolPath(t), "build", "-gcflags=-N -l", "-o", "a.exe") cmd.Dir = dir out, err := testEnv(cmd).CombinedOutput() if err != nil { t.Fatalf("building source %v\n%s", err, out) } // Execute gdb commands. args := []string{"-nx", "-batch", "-ex", "set startup-with-shell off", "-ex", "break main.main", "-ex", "run", "-ex", "step", "-ex", "info types astruct", filepath.Join(dir, "a.exe"), } got, _ := exec.Command("gdb", args...).CombinedOutput() sgot := string(got) // Check that the backtrace matches the source code. types := []string{ "struct []main.astruct;", "struct bucket<string,main.astruct>;", "struct hash<string,main.astruct>;", "struct main.astruct;", "typedef struct hash<string,main.astruct> * map[string]main.astruct;", } for _, name := range types { if !strings.Contains(sgot, name) { t.Errorf("could not find %s in 'info typrs astruct' output", name) t.Fatalf("gdb output:\n%v", sgot) } } }
func TestOutput(t *testing.T) { for _, test := range tests { if test.goos != "" && test.goos != runtime.GOOS { t.Logf("test %v runs only on %v, skipping: ", test.name, test.goos) continue } dir, err := ioutil.TempDir("", "go-build") if err != nil { t.Fatalf("failed to create temp directory: %v", err) } defer os.RemoveAll(dir) source := "main.go" if test.run == "test" { source = "main_test.go" } src := filepath.Join(dir, source) f, err := os.Create(src) if err != nil { t.Fatalf("failed to create file: %v", err) } _, err = f.WriteString(test.source) if err != nil { f.Close() t.Fatalf("failed to write: %v", err) } if err := f.Close(); err != nil { t.Fatalf("failed to close file: %v", err) } // Pass -l to the compiler to test stack traces. cmd := exec.Command(testenv.GoToolPath(t), test.run, "-race", "-gcflags=-l", src) // GODEBUG spoils program output, GOMAXPROCS makes it flaky. for _, env := range os.Environ() { if strings.HasPrefix(env, "GODEBUG=") || strings.HasPrefix(env, "GOMAXPROCS=") || strings.HasPrefix(env, "GORACE=") { continue } cmd.Env = append(cmd.Env, env) } cmd.Env = append(cmd.Env, "GOMAXPROCS=1", // see comment in race_test.go "GORACE="+test.gorace, ) got, _ := cmd.CombinedOutput() if !regexp.MustCompile(test.re).MatchString(string(got)) { t.Fatalf("failed test case %v, expect:\n%v\ngot:\n%s", test.name, test.re, got) } } }
// Make sure -S prints assembly code. See issue 14515. func TestDashS(t *testing.T) { testenv.MustHaveGoBuild(t) // Make a directory to work in. dir, err := ioutil.TempDir("", "issue14515-") if err != nil { log.Fatalf("could not create directory: %v", err) } defer os.RemoveAll(dir) // Create source. src := filepath.Join(dir, "test.go") f, err := os.Create(src) if err != nil { log.Fatalf("could not create source file: %v", err) } f.Write([]byte(` package main import "fmt" func main() { fmt.Println("hello world") } `)) f.Close() // Compile source. cmd := exec.Command(testenv.GoToolPath(t), "build", "-gcflags", "-S", "-o", filepath.Join(dir, "test"), src) out, err := cmd.CombinedOutput() if err != nil { log.Fatalf("could not build target: %v", err) } patterns := []string{ // It is hard to look for actual instructions in an // arch-independent way. So we'll just look for // pseudo-ops that are arch-independent. "\tTEXT\t", "\tFUNCDATA\t", "\tPCDATA\t", } outstr := string(out) for _, p := range patterns { if !strings.Contains(outstr, p) { println(outstr) panic("can't find pattern " + p) } } }
func doTest(t *testing.T, filename string, kind string) { testenv.MustHaveGoBuild(t) var stdout, stderr bytes.Buffer cmd := exec.Command(testenv.GoToolPath(t), kind, filepath.Join("testdata", filename)) cmd.Stdout = &stdout cmd.Stderr = &stderr if err := cmd.Run(); err != nil { t.Fatalf("Failed: %v:\nOut: %s\nStderr: %s\n", err, &stdout, &stderr) } if s := stdout.String(); s != "" { t.Errorf("Stdout = %s\nWant empty", s) } if s := stderr.String(); strings.Contains(s, "SSA unimplemented") { t.Errorf("Unimplemented message found in stderr:\n%s", s) } }
func buildObjdump(t *testing.T) (tmp, exe string) { testenv.MustHaveGoBuild(t) tmp, err := ioutil.TempDir("", "TestObjDump") if err != nil { t.Fatal("TempDir failed: ", err) } exe = filepath.Join(tmp, "testobjdump.exe") out, err := exec.Command(testenv.GoToolPath(t), "build", "-o", exe, "cmd/objdump").CombinedOutput() if err != nil { os.RemoveAll(tmp) t.Fatalf("go build -o %v cmd/objdump: %v\n%s", exe, err, string(out)) } return }
func checkStaleRuntime(t *testing.T) { staleRuntimeOnce.Do(func() { // 'go run' uses the installed copy of runtime.a, which may be out of date. out, err := testEnv(exec.Command(testenv.GoToolPath(t), "list", "-f", "{{.Stale}}", "runtime")).CombinedOutput() if err != nil { staleRuntimeErr = fmt.Errorf("failed to execute 'go list': %v\n%v", err, string(out)) return } if string(out) != "false\n" { staleRuntimeErr = fmt.Errorf("Stale runtime.a. Run 'go install runtime'.") } }) if staleRuntimeErr != nil { t.Fatal(staleRuntimeErr) } }
func TestBuiltin(t *testing.T) { testenv.MustHaveGoRun(t) old, err := ioutil.ReadFile("builtin.go") if err != nil { t.Fatal(err) } new, err := exec.Command(testenv.GoToolPath(t), "run", "mkbuiltin.go", "-stdout").Output() if err != nil { t.Fatal(err) } if !bytes.Equal(old, new) { t.Fatal("builtin.go out of date; run mkbuiltin.go") } }
func Build(t *testing.T) { testenv.MustHaveGoBuild(t) MustHavePerl(t) if built { return } if failed { t.Skip("cannot run on this environment") } cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", binary) output, err := cmd.CombinedOutput() if err != nil { failed = true fmt.Fprintf(os.Stderr, "%s\n", output) t.Fatal(err) } built = true }
func TestLldbPython(t *testing.T) { testenv.MustHaveGoBuild(t) if final := os.Getenv("GOROOT_FINAL"); final != "" && runtime.GOROOT() != final { t.Skip("gdb test can fail with GOROOT_FINAL pending") } checkLldbPython(t) dir, err := ioutil.TempDir("", "go-build") if err != nil { t.Fatalf("failed to create temp directory: %v", err) } defer os.RemoveAll(dir) src := filepath.Join(dir, "main.go") err = ioutil.WriteFile(src, []byte(lldbHelloSource), 0644) if err != nil { t.Fatalf("failed to create file: %v", err) } cmd := exec.Command(testenv.GoToolPath(t), "build", "-gcflags", "-N -l", "-o", "a.exe") cmd.Dir = dir out, err := cmd.CombinedOutput() if err != nil { t.Fatalf("building source %v\n%s", err, out) } src = filepath.Join(dir, "script.py") err = ioutil.WriteFile(src, []byte(lldbScriptSource), 0755) if err != nil { t.Fatalf("failed to create script: %v", err) } cmd = exec.Command("/usr/bin/python2.7", "script.py", lldbPath) cmd.Dir = dir got, _ := cmd.CombinedOutput() if string(got) != expectedLldbOutput { if strings.Contains(string(got), "Timeout launching") { t.Skip("Timeout launching") } t.Fatalf("Unexpected lldb output:\n%s", got) } }
func testCgoPprof(t *testing.T, buildArg, runArg string) { if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" { t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH) } testenv.MustHaveGoRun(t) exe, err := buildTestProg(t, "testprogcgo", buildArg) if err != nil { t.Fatal(err) } got, err := testEnv(exec.Command(exe, runArg)).CombinedOutput() if err != nil { t.Fatal(err) } fn := strings.TrimSpace(string(got)) defer os.Remove(fn) cmd := testEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-top", "-nodecount=1", "-symbolize=force", exe, fn)) found := false for i, e := range cmd.Env { if strings.HasPrefix(e, "PPROF_TMPDIR=") { cmd.Env[i] = "PPROF_TMPDIR=" + os.TempDir() found = true break } } if !found { cmd.Env = append(cmd.Env, "PPROF_TMPDIR="+os.TempDir()) } top, err := cmd.CombinedOutput() t.Logf("%s", top) if err != nil { t.Fatal(err) } if !bytes.Contains(top, []byte("cpuHog")) { t.Error("missing cpuHog in pprof output") } }
func loadSyms(t *testing.T) map[string]string { cmd := exec.Command(testenv.GoToolPath(t), "tool", "nm", os.Args[0]) out, err := cmd.CombinedOutput() if err != nil { t.Fatalf("go tool nm %v: %v\n%s", os.Args[0], err, string(out)) } syms := make(map[string]string) scanner := bufio.NewScanner(bytes.NewReader(out)) for scanner.Scan() { f := strings.Fields(scanner.Text()) if len(f) < 3 { continue } syms[f[2]] = f[0] } if err := scanner.Err(); err != nil { t.Fatalf("error reading symbols: %v", err) } return syms }
// This is line 88. The test depends on that. func TestAddr2Line(t *testing.T) { testenv.MustHaveGoBuild(t) syms := loadSyms(t) tmpDir, err := ioutil.TempDir("", "TestAddr2Line") if err != nil { t.Fatal("TempDir failed: ", err) } defer os.RemoveAll(tmpDir) exepath := filepath.Join(tmpDir, "testaddr2line.exe") out, err := exec.Command(testenv.GoToolPath(t), "build", "-o", exepath, "cmd/addr2line").CombinedOutput() if err != nil { t.Fatalf("go build -o %v cmd/addr2line: %v\n%s", exepath, err, string(out)) } testAddr2Line(t, exepath, syms[symName]) testAddr2Line(t, exepath, "0x"+syms[symName]) }
func TestNM(t *testing.T) { testenv.MustHaveGoBuild(t) tmpDir, err := ioutil.TempDir("", "TestNM") if err != nil { t.Fatal("TempDir failed: ", err) } defer os.RemoveAll(tmpDir) testnmpath := filepath.Join(tmpDir, "testnm.exe") out, err := exec.Command(testenv.GoToolPath(t), "build", "-o", testnmpath, "cmd/nm").CombinedOutput() if err != nil { t.Fatalf("go build -o %v cmd/nm: %v\n%s", testnmpath, err, string(out)) } testfiles := []string{ "elf/testdata/gcc-386-freebsd-exec", "elf/testdata/gcc-amd64-linux-exec", "macho/testdata/gcc-386-darwin-exec", "macho/testdata/gcc-amd64-darwin-exec", // "pe/testdata/gcc-amd64-mingw-exec", // no symbols! "pe/testdata/gcc-386-mingw-exec", "plan9obj/testdata/amd64-plan9-exec", "plan9obj/testdata/386-plan9-exec", } for _, f := range testfiles { exepath := filepath.Join(runtime.GOROOT(), "src", "debug", f) cmd := exec.Command(testnmpath, exepath) out, err := cmd.CombinedOutput() if err != nil { t.Errorf("go tool nm %v: %v\n%s", exepath, err, string(out)) } } cmd := exec.Command(testnmpath, os.Args[0]) out, err = cmd.CombinedOutput() if err != nil { t.Fatalf("go tool nm %v: %v\n%s", os.Args[0], err, string(out)) } checkSymbols(t, out) }
func TestAbsolutePath(t *testing.T) { tmp, err := ioutil.TempDir("", "TestAbsolutePath") if err != nil { t.Fatal(err) } defer os.RemoveAll(tmp) file := filepath.Join(tmp, "a.go") err = ioutil.WriteFile(file, []byte{}, 0644) if err != nil { t.Fatal(err) } dir := filepath.Join(tmp, "dir") err = os.Mkdir(dir, 0777) if err != nil { t.Fatal(err) } wd, err := os.Getwd() if err != nil { t.Fatal(err) } defer os.Chdir(wd) // Chdir so current directory and a.go reside on the same drive. err = os.Chdir(dir) if err != nil { t.Fatal(err) } noVolume := file[len(filepath.VolumeName(file)):] wrongPath := filepath.Join(dir, noVolume) output, err := exec.Command(testenv.GoToolPath(t), "build", noVolume).CombinedOutput() if err == nil { t.Fatal("build should fail") } if strings.Contains(string(output), wrongPath) { t.Fatalf("wrong output found: %v %v", err, string(output)) } }
func buildTestProg(t *testing.T, binary string, flags ...string) (string, error) { checkStaleRuntime(t) testprog.Lock() defer testprog.Unlock() if testprog.dir == "" { dir, err := ioutil.TempDir("", "go-build") if err != nil { t.Fatalf("failed to create temp directory: %v", err) } testprog.dir = dir toRemove = append(toRemove, dir) } if testprog.target == nil { testprog.target = make(map[string]buildexe) } name := binary if len(flags) > 0 { name += "_" + strings.Join(flags, "_") } target, ok := testprog.target[name] if ok { return target.exe, target.err } exe := filepath.Join(testprog.dir, name+".exe") cmd := exec.Command(testenv.GoToolPath(t), append([]string{"build", "-o", exe}, flags...)...) cmd.Dir = "testdata/" + binary out, err := testEnv(cmd).CombinedOutput() if err != nil { exe = "" target.err = fmt.Errorf("building %s %v: %v\n%s", binary, flags, err, out) testprog.target[name] = target return "", target.err } target.exe = exe testprog.target[name] = target return exe, nil }
func TestMemPprof(t *testing.T) { testenv.MustHaveGoRun(t) exe, err := buildTestProg(t, "testprog") if err != nil { t.Fatal(err) } got, err := testEnv(exec.Command(exe, "MemProf")).CombinedOutput() if err != nil { t.Fatal(err) } fn := strings.TrimSpace(string(got)) defer os.Remove(fn) cmd := testEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-alloc_space", "-top", exe, fn)) found := false for i, e := range cmd.Env { if strings.HasPrefix(e, "PPROF_TMPDIR=") { cmd.Env[i] = "PPROF_TMPDIR=" + os.TempDir() found = true break } } if !found { cmd.Env = append(cmd.Env, "PPROF_TMPDIR="+os.TempDir()) } top, err := cmd.CombinedOutput() t.Logf("%s", top) if err != nil { t.Fatal(err) } if !bytes.Contains(top, []byte("MemProf")) { t.Error("missing MemProf in pprof output") } }