// 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) { testenv.MustHaveGoBuild(t) var exeSuffix string if runtime.GOOS == "windows" { exeSuffix = ".exe" } goBin := filepath.Join(runtime.GOROOT(), "bin", "go"+exeSuffix) out, err := exec.Command("go", "tool", "nm", goBin).Output() if err != nil { t.Fatalf("go tool nm: %v", err) } 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 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("go", "tool", "asm", "-o", pclinetestBinary+".o", "pclinetest.asm") cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { t.Fatal(err) } cmd = exec.Command("go", "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) } }
// 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) } }
func TestDynlink(t *testing.T) { testenv.MustHaveGoBuild(t) if os.Getenv("GOHOSTARCH") != "" { // TODO: make this work? It was failing due to the // GOARCH= filtering above and skipping is easiest for // now. t.Skip("skipping when GOHOSTARCH is set") } testdata := parseTestData(t) asmout := asmOutput(t, testdata.input) parseOutput(t, testdata, asmout) for _, m := range testdata.marks { i := strings.Join(testdata.marker_to_input[m], "; ") o := strings.Join(testdata.marker_to_output[m], "; ") e := strings.Join(testdata.marker_to_expected[m], "; ") if o != e { if o == i { t.Errorf("%s was unchanged; should have become %s", i, e) } else { t.Errorf("%s became %s; should have become %s", i, o, e) } } else if i != e { t.Logf("%s correctly became %s", i, o) } } }
// 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") } }
func TestNoteReading(t *testing.T) { testenv.MustHaveGoBuild(t) // TODO: Replace with new test scaffolding by iant. d, err := ioutil.TempDir("", "go-test-") if err != nil { t.Fatal(err) } defer os.RemoveAll(d) out, err := exec.Command("go", "build", "-o", d+"/go.exe", "cmd/go").CombinedOutput() if err != nil { t.Fatalf("go build cmd/go: %v\n%s", err, out) } const buildID = "TestNoteReading-Build-ID" out, err = exec.Command(d+"/go.exe", "build", "-ldflags", "-buildid="+buildID, "-o", d+"/hello.exe", "../../../test/helloworld.go").CombinedOutput() if err != nil { t.Fatalf("go build hello: %v\n%s", err, out) } id, err := readBuildIDFromBinary(d + "/hello.exe") if err != nil { t.Fatalf("reading build ID from hello binary: %v", err) } if id != buildID { t.Fatalf("buildID in hello binary = %q, want %q", id, buildID) } }
// TestAssembly checks to make sure the assembly generated for // functions contains certain expected instructions. func TestAssembly(t *testing.T) { testenv.MustHaveGoBuild(t) if runtime.GOOS == "windows" { // TODO: remove if we can get "go tool compile -S" to work on windows. t.Skipf("skipping test: recursive windows compile not working") } dir, err := ioutil.TempDir("", "TestAssembly") if err != nil { t.Fatalf("could not create directory: %v", err) } defer os.RemoveAll(dir) for _, test := range asmTests { asm := compileToAsm(t, dir, test.arch, test.os, fmt.Sprintf(template, test.function)) // Get rid of code for "".init. Also gets rid of type algorithms & other junk. if i := strings.Index(asm, "\n\"\".init "); i >= 0 { asm = asm[:i+1] } for _, r := range test.regexps { if b, err := regexp.MatchString(r, asm); !b || err != nil { t.Errorf("expected:%s\ngo:%s\nasm:%s\n", r, test.function, asm) } } } }
func TestObjImporter(t *testing.T) { testenv.MustHaveGoBuild(t) // This test relies on gccgo being around, which it most likely will be if we // were compiled with gccgo. if runtime.Compiler != "gccgo" { t.Skip("This test needs gccgo") return } tmpdir, err := ioutil.TempDir("", "") if err != nil { t.Fatal(err) } initmap := make(map[*types.Package]InitData) imp := GetImporter([]string{tmpdir}, initmap) artmpdir, err := ioutil.TempDir("", "") if err != nil { t.Fatal(err) } arinitmap := make(map[*types.Package]InitData) arimp := GetImporter([]string{artmpdir}, arinitmap) for _, test := range importerTests { gofile := filepath.Join("testdata", test.pkgpath+".go") ofile := filepath.Join(tmpdir, test.pkgpath+".o") afile := filepath.Join(artmpdir, "lib"+test.pkgpath+".a") cmd := exec.Command("gccgo", "-fgo-pkgpath="+test.pkgpath, "-c", "-o", ofile, gofile) out, err := cmd.CombinedOutput() if err != nil { t.Logf("%s", out) t.Fatalf("gccgo %s failed: %s", gofile, err) } runImporterTest(t, imp, initmap, &test) cmd = exec.Command("ar", "cr", afile, ofile) out, err = cmd.CombinedOutput() if err != nil { t.Logf("%s", out) t.Fatalf("ar cr %s %s failed: %s", afile, ofile, err) } runImporterTest(t, arimp, arinitmap, &test) if err = os.Remove(ofile); err != nil { t.Fatal(err) } if err = os.Remove(afile); err != nil { t.Fatal(err) } } if err = os.Remove(tmpdir); err != nil { t.Fatal(err) } }
func TestStdlib(t *testing.T) { testenv.MustHaveGoBuild(t) start = time.Now() walkDirs(t, filepath.Join(runtime.GOROOT(), "src")) if testing.Verbose() { fmt.Println(pkgCount, "packages typechecked in", time.Since(start)) } }
func checkGdbEnvironment(t *testing.T) { testenv.MustHaveGoBuild(t) if runtime.GOOS == "darwin" { t.Skip("gdb does not work on darwin") } if final := os.Getenv("GOROOT_FINAL"); final != "" && runtime.GOROOT() != final { t.Skip("gdb test can fail with GOROOT_FINAL pending") } }
func TestGoxImporter(t *testing.T) { testenv.MustHaveGoBuild(t) initmap := make(map[*types.Package]InitData) imp := GetImporter([]string{"testdata"}, initmap) for _, test := range importerTests { runImporterTest(t, imp, initmap, &test) } }
func runTestProg(t *testing.T, binary, name string) string { testenv.MustHaveGoBuild(t) exe, err := buildTestProg(t, binary) if err != nil { t.Fatal(err) } got, _ := testEnv(exec.Command(exe, name)).CombinedOutput() return string(got) }
func TestStdFixed(t *testing.T) { testenv.MustHaveGoBuild(t) testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "fixedbugs"), "bug248.go", "bug302.go", "bug369.go", // complex test instructions - ignore "issue6889.go", // gc-specific test "issue7746.go", // large constants - consumes too much memory "issue11362.go", // canonical import path check ) }
// 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) } }
func TestStdFixed(t *testing.T) { testenv.MustHaveGoBuild(t) testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "fixedbugs"), "bug248.go", "bug302.go", "bug369.go", // complex test instructions - ignore "bug459.go", // possibly incorrect test - see issue 6703 (pending spec clarification) "issue3924.go", // possibly incorrect test - see issue 6671 (pending spec clarification) "issue6889.go", // gc-specific test "issue7746.go", // large constants - consumes too much memory ) }
func checkGdbEnvironment(t *testing.T) { testenv.MustHaveGoBuild(t) if runtime.GOOS == "darwin" { t.Skip("gdb does not work on darwin") } if runtime.GOOS == "linux" && runtime.GOARCH == "ppc64" { t.Skip("skipping gdb tests on linux/ppc64; see golang.org/issue/17366") } if final := os.Getenv("GOROOT_FINAL"); final != "" && runtime.GOROOT() != final { t.Skip("gdb test can fail with GOROOT_FINAL pending") } }
// TODO(gri) Remove this function once we switched to new export format by default. func compileNewExport(t *testing.T, dirname, filename string) string { testenv.MustHaveGoBuild(t) cmd := exec.Command("go", "tool", "compile", "-newexport", 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") }
func TestImportVendor(t *testing.T) { testenv.MustHaveGoBuild(t) // really must just have source ctxt := Default ctxt.GOPATH = "" p, err := ctxt.Import("golang.org/x/net/http2/hpack", filepath.Join(ctxt.GOROOT, "src/net/http"), AllowVendor) if err != nil { t.Fatalf("cannot find vendored golang.org/x/net/http2/hpack from net/http directory: %v", err) } want := "vendor/golang.org/x/net/http2/hpack" if p.ImportPath != want { t.Fatalf("Import succeeded but found %q, want %q", p.ImportPath, want) } }
func executeTest(t *testing.T, templ string, data interface{}, extra ...string) string { testenv.MustHaveGoBuild(t) checkStaleRuntime(t) st := template.Must(template.New("crashSource").Parse(templ)) 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") f, err := os.Create(src) if err != nil { t.Fatalf("failed to create file: %v", err) } err = st.Execute(f, data) if err != nil { f.Close() t.Fatalf("failed to execute template: %v", err) } if err := f.Close(); err != nil { t.Fatalf("failed to close file: %v", err) } for i := 0; i < len(extra); i += 2 { fname := extra[i] contents := extra[i+1] if d, _ := filepath.Split(fname); d != "" { if err := os.Mkdir(filepath.Join(dir, d), 0755); err != nil { t.Fatal(err) } } if err := ioutil.WriteFile(filepath.Join(dir, fname), []byte(contents), 0666); err != nil { t.Fatal(err) } } cmd := exec.Command("go", "build", "-o", "a.exe") cmd.Dir = dir out, err := testEnv(cmd).CombinedOutput() if err != nil { t.Fatalf("building source: %v\n%s", err, out) } got, _ := testEnv(exec.Command(filepath.Join(dir, "a.exe"))).CombinedOutput() return string(got) }
func TestImportVendorFailure(t *testing.T) { testenv.MustHaveGoBuild(t) // really must just have source ctxt := Default ctxt.GOPATH = "" p, err := ctxt.Import("x.com/y/z", filepath.Join(ctxt.GOROOT, "src/net/http"), AllowVendor) if err == nil { t.Fatalf("found made-up package x.com/y/z in %s", p.Dir) } e := err.Error() if !strings.Contains(e, " (vendor tree)") { t.Fatalf("error on failed import does not mention GOROOT/src/vendor directory:\n%s", e) } }
func TestStdTest(t *testing.T) { testenv.MustHaveGoBuild(t) // test/recover4.go is only built for Linux and Darwin. // TODO(gri) Remove once tests consider +build tags (issue 10370). if runtime.GOOS != "linux" && runtime.GOOS != "darwin" { return } testTestDir(t, filepath.Join(runtime.GOROOT(), "test"), "cmplxdivide.go", // also needs file cmplxdivide1.go - ignore "sigchld.go", // don't work on Windows; testTestDir should consult build tags ) }
func TestStdFixed(t *testing.T) { testenv.MustHaveGoBuild(t) if testing.Short() && testenv.Builder() == "" { t.Skip("skipping in short mode") } testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "fixedbugs"), "bug248.go", "bug302.go", "bug369.go", // complex test instructions - ignore "issue6889.go", // gc-specific test "issue7746.go", // large constants - consumes too much memory "issue11362.go", // canonical import path check "issue15002.go", // uses Mmap; testTestDir should consult build tags ) }
// 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("go", "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 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("go", "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 doTest(t *testing.T, filename string, kind string) { testenv.MustHaveGoBuild(t) var stdout, stderr bytes.Buffer cmd := exec.Command("go", 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 runTestProg(t *testing.T, binary, name string) string { testenv.MustHaveGoBuild(t) exe, err := buildTestProg(t, binary) if err != nil { t.Fatal(err) } cmd := testEnv(exec.Command(exe, name)) var b bytes.Buffer cmd.Stdout = &b cmd.Stderr = &b if err := cmd.Start(); err != nil { t.Fatalf("starting %s %s: %v", binary, name, err) } // If the process doesn't complete within 1 minute, // assume it is hanging and kill it to get a stack trace. p := cmd.Process done := make(chan bool) go func() { scale := 1 // This GOARCH/GOOS test is copied from cmd/dist/test.go. // TODO(iant): Have cmd/dist update the environment variable. if runtime.GOARCH == "arm" || runtime.GOOS == "windows" { scale = 2 } if s := os.Getenv("GO_TEST_TIMEOUT_SCALE"); s != "" { if sc, err := strconv.Atoi(s); err == nil { scale = sc } } select { case <-done: case <-time.After(time.Duration(scale) * time.Minute): p.Signal(sigquit) } }() if err := cmd.Wait(); err != nil { t.Logf("%s %s exit status: %v", binary, name, err) } close(done) return b.String() }
func TestSignalExitStatus(t *testing.T) { testenv.MustHaveGoBuild(t) exe, err := buildTestProg(t, "testprog") if err != nil { t.Fatal(err) } err = testEnv(exec.Command(exe, "SignalExitStatus")).Run() if err == nil { t.Error("test program succeeded unexpectedly") } else if ee, ok := err.(*exec.ExitError); !ok { t.Errorf("error (%v) has type %T; expected exec.ExitError", err, err) } else if ws, ok := ee.Sys().(syscall.WaitStatus); !ok { t.Errorf("error.Sys (%v) has type %T; expected syscall.WaitStatus", ee.Sys(), ee.Sys()) } else if !ws.Signaled() || ws.Signal() != syscall.SIGTERM { t.Errorf("got %v; expected SIGTERM", ee) } }
func TestImportVendorParentFailure(t *testing.T) { testenv.MustHaveGoBuild(t) // really must just have source ctxt := Default ctxt.GOPATH = "" // This import should fail because the vendor/golang.org/x/net/http2 directory has no source code. p, err := ctxt.Import("golang_org/x/net/http2", filepath.Join(ctxt.GOROOT, "src/net/http"), 0) if err == nil { t.Fatalf("found empty parent in %s", p.Dir) } if p != nil && p.Dir != "" { t.Fatalf("decided to use %s", p.Dir) } e := err.Error() if !strings.Contains(e, " (vendor tree)") { t.Fatalf("error on failed import does not mention GOROOT/src/vendor directory:\n%s", e) } }
func TestCheck(t *testing.T) { testenv.MustHaveGoBuild(t) // Declare builtins for testing. DefPredeclaredTestFuncs() // If explicit test files are specified, only check those. if files := *testFiles; files != "" { checkFiles(t, strings.Split(files, " ")) return } // Otherwise, run all the tests. for _, files := range tests { checkFiles(t, files) } }
// 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("go", "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("go", "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") } }