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.
31 // C compiler with args (from $(go env CC) $(go env GOGCCFLAGS)).
37 var GOOS, GOARCH, GOPATH string
40 var testWork bool // If true, preserve temporary directories.
42 func TestMain(m *testing.M) {
43 flag.BoolVar(&testWork, "testwork", false, "if true, log and preserve the test's temporary working directory")
45 if testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" {
46 fmt.Printf("SKIP - short mode and $GO_BUILDER_NAME not set\n")
49 log.SetFlags(log.Lshortfile)
53 func testMain(m *testing.M) int {
54 // We need a writable GOPATH in which to run the tests.
55 // Construct one in a temporary directory.
57 GOPATH, err = os.MkdirTemp("", "carchive_test")
64 defer os.RemoveAll(GOPATH)
66 os.Setenv("GOPATH", GOPATH)
68 // Copy testdata into GOPATH/src/testarchive, along with a go.mod file
69 // declaring the same path.
70 modRoot := filepath.Join(GOPATH, "src", "testcarchive")
71 if err := overlayDir(modRoot, "testdata"); err != nil {
74 if err := os.Chdir(modRoot); err != nil {
77 os.Setenv("PWD", modRoot)
78 if err := os.WriteFile("go.mod", []byte("module testcarchive\n"), 0666); err != nil {
83 GOARCH = goEnv("GOARCH")
84 bin = cmdToRun("./testp")
87 cc = []string{string(ccOut)}
89 out := goEnv("GOGCCFLAGS")
96 if quote == '\000' && unicode.IsSpace(c) {
98 cc = append(cc, s[start:i])
106 if quote == '\000' && !backslash && (c == '"' || c == '\'') {
109 } else if !backslash && quote == c {
111 } else if (quote == '\000' || quote == '"') && !backslash && c == '\\' {
119 cc = append(cc, s[start:])
123 // -Wl,-bnoobjreorder is mandatory to keep the same layout
125 cc = append(cc, "-Wl,-bnoobjreorder")
127 libbase := GOOS + "_" + GOARCH
128 if runtime.Compiler == "gccgo" {
129 libbase = "gccgo_" + libgodir + "_fPIC"
132 case "darwin", "ios":
133 if GOARCH == "arm64" {
136 case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris", "illumos":
140 libgodir = filepath.Join(GOPATH, "pkg", libbase, "testcarchive")
141 cc = append(cc, "-I", libgodir)
143 // Force reallocation (and avoid aliasing bugs) for parallel tests that append to cc.
144 cc = cc[:len(cc):len(cc)]
146 if GOOS == "windows" {
153 func goEnv(key string) string {
154 out, err := exec.Command("go", "env", key).Output()
156 if ee, ok := err.(*exec.ExitError); ok {
157 fmt.Fprintf(os.Stderr, "%s", ee.Stderr)
159 log.Panicf("go env %s failed:\n%s\n", key, err)
161 return strings.TrimSpace(string(out))
164 func cmdToRun(name string) []string {
165 execScript := "go_" + goEnv("GOOS") + "_" + goEnv("GOARCH") + "_exec"
166 executor, err := exec.LookPath(execScript)
168 return []string{name}
170 return []string{executor, name}
173 // genHeader writes a C header file for the C-exported declarations found in .go
174 // source files in dir.
176 // TODO(golang.org/issue/35715): This should be simpler.
177 func genHeader(t *testing.T, header, dir string) {
180 // The 'cgo' command generates a number of additional artifacts,
181 // but we're only interested in the header.
182 // Shunt the rest of the outputs to a temporary directory.
183 objDir, err := os.MkdirTemp(GOPATH, "_obj")
187 defer os.RemoveAll(objDir)
189 files, err := filepath.Glob(filepath.Join(dir, "*.go"))
194 cmd := exec.Command("go", "tool", "cgo",
196 "-exportheader", header)
197 cmd.Args = append(cmd.Args, files...)
199 if out, err := cmd.CombinedOutput(); err != nil {
205 func testInstall(t *testing.T, exe, libgoa, libgoh string, buildcmd ...string) {
207 cmd := exec.Command(buildcmd[0], buildcmd[1:]...)
209 if out, err := cmd.CombinedOutput(); err != nil {
220 ccArgs := append(cc, "-o", exe, "main.c")
221 if GOOS == "windows" {
222 ccArgs = append(ccArgs, "main_windows.c", libgoa, "-lntdll", "-lws2_32", "-lwinmm")
224 ccArgs = append(ccArgs, "main_unix.c", libgoa)
226 if runtime.Compiler == "gccgo" {
227 ccArgs = append(ccArgs, "-lgo")
230 if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
238 binArgs := append(cmdToRun(exe), "arg1", "arg2")
239 cmd = exec.Command(binArgs[0], binArgs[1:]...)
240 if runtime.Compiler == "gccgo" {
241 cmd.Env = append(os.Environ(), "GCCGO=1")
243 if out, err := cmd.CombinedOutput(); err != nil {
248 checkLineComments(t, libgoh)
251 var badLineRegexp = regexp.MustCompile(`(?m)^#line [0-9]+ "/.*$`)
253 // checkLineComments checks that the export header generated by
254 // -buildmode=c-archive doesn't have any absolute paths in the #line
255 // comments. We don't want those paths because they are unhelpful for
256 // the user and make the files change based on details of the location
258 func checkLineComments(t *testing.T, hdrname string) {
259 hdr, err := os.ReadFile(hdrname)
261 if !os.IsNotExist(err) {
266 if line := badLineRegexp.Find(hdr); line != nil {
267 t.Errorf("bad #line directive with absolute path in %s: %q", hdrname, line)
271 // checkArchive verifies that the created library looks OK.
272 // We just check a couple of things now, we can add more checks as needed.
273 func checkArchive(t *testing.T, arname string) {
277 case "aix", "darwin", "ios", "windows":
278 // We don't have any checks for non-ELF libraries yet.
279 if _, err := os.Stat(arname); err != nil {
280 t.Errorf("archive %s does not exist: %v", arname, err)
283 checkELFArchive(t, arname)
287 // checkELFArchive checks an ELF archive.
288 func checkELFArchive(t *testing.T, arname string) {
291 f, err := os.Open(arname)
293 t.Errorf("archive %s does not exist: %v", arname, err)
298 // TODO(iant): put these in a shared package? But where?
310 hdrlen = namelen + datelen + uidlen + gidlen + modelen + sizelen + fmaglen
323 var magbuf [len(magic)]byte
324 if _, err := io.ReadFull(f, magbuf[:]); err != nil {
325 t.Errorf("%s: archive too short", arname)
328 if string(magbuf[:]) != magic {
329 t.Errorf("%s: incorrect archive magic string %q", arname, magbuf)
332 off := int64(len(magic))
336 if _, err := f.Read(b[:]); err != nil {
340 t.Errorf("%s: error skipping alignment byte at %d: %v", arname, off, err)
345 var hdrbuf [hdrlen]byte
346 if _, err := io.ReadFull(f, hdrbuf[:]); err != nil {
350 t.Errorf("%s: error reading archive header at %d: %v", arname, off, err)
355 hdrslice := hdrbuf[:]
356 set := func(len int, ps *string) {
357 *ps = string(bytes.TrimSpace(hdrslice[:len]))
358 hdrslice = hdrslice[len:]
360 set(namelen, &hdr.name)
361 set(datelen, &hdr.date)
362 set(uidlen, &hdr.uid)
363 set(gidlen, &hdr.gid)
364 set(modelen, &hdr.mode)
365 set(sizelen, &hdr.size)
366 hdr.fmag = string(hdrslice[:fmaglen])
367 hdrslice = hdrslice[fmaglen:]
368 if len(hdrslice) != 0 {
369 t.Fatalf("internal error: len(hdrslice) == %d", len(hdrslice))
372 if hdr.fmag != fmag {
373 t.Errorf("%s: invalid fmagic value %q at %d", arname, hdr.fmag, off)
377 size, err := strconv.ParseInt(hdr.size, 10, 64)
379 t.Errorf("%s: error parsing size %q at %d: %v", arname, hdr.size, off, err)
386 case "__.SYMDEF", "/", "/SYM64/":
387 // The archive symbol map.
388 case "//", "ARFILENAMES/":
389 // The extended name table.
391 // This should be an ELF object.
392 checkELFArchiveObject(t, arname, off, io.NewSectionReader(f, off, size))
396 if _, err := f.Seek(off, os.SEEK_SET); err != nil {
397 t.Errorf("%s: failed to seek to %d: %v", arname, off, err)
402 // checkELFArchiveObject checks an object in an ELF archive.
403 func checkELFArchiveObject(t *testing.T, arname string, off int64, obj io.ReaderAt) {
406 ef, err := elf.NewFile(obj)
408 t.Errorf("%s: failed to open ELF file at %d: %v", arname, off, err)
413 // Verify section types.
414 for _, sec := range ef.Sections {
417 case ".text", ".data":
418 want = elf.SHT_PROGBITS
420 want = elf.SHT_NOBITS
422 want = elf.SHT_SYMTAB
424 want = elf.SHT_STRTAB
426 want = elf.SHT_INIT_ARRAY
428 want = elf.SHT_FINI_ARRAY
429 case ".preinit_array":
430 want = elf.SHT_PREINIT_ARRAY
432 if want != elf.SHT_NULL && sec.Type != want {
433 t.Errorf("%s: incorrect section type in elf file at %d for section %q: got %v want %v", arname, off, sec.Name, sec.Type, want)
438 func TestInstall(t *testing.T) {
440 defer os.RemoveAll(filepath.Join(GOPATH, "pkg"))
444 if runtime.Compiler == "gccgo" {
445 libgoa = "liblibgo.a"
448 // Generate the p.h header file.
450 // 'go install -i -buildmode=c-archive ./libgo' would do that too, but that
451 // would also attempt to install transitive standard-library dependencies to
452 // GOROOT, and we cannot assume that GOROOT is writable. (A non-root user may
453 // be running this test in a GOROOT owned by root.)
454 genHeader(t, "p.h", "./p")
456 testInstall(t, "./testp1"+exeSuffix,
457 filepath.Join(libgodir, libgoa),
458 filepath.Join(libgodir, "libgo.h"),
459 "go", "install", "-buildmode=c-archive", "./libgo")
461 // Test building libgo other than installing it.
462 // Header files are now present.
463 testInstall(t, "./testp2"+exeSuffix, "libgo.a", "libgo.h",
464 "go", "build", "-buildmode=c-archive", filepath.Join(".", "libgo", "libgo.go"))
466 testInstall(t, "./testp3"+exeSuffix, "libgo.a", "libgo.h",
467 "go", "build", "-buildmode=c-archive", "-o", "libgo.a", "./libgo")
470 func TestEarlySignalHandler(t *testing.T) {
472 case "darwin", "ios":
475 t.Skipf("skipping on %s/%s; see https://golang.org/issue/13701", GOOS, GOARCH)
478 t.Skip("skipping signal test on Windows")
483 os.Remove("libgo2.a")
484 os.Remove("libgo2.h")
485 os.Remove("testp" + exeSuffix)
486 os.RemoveAll(filepath.Join(GOPATH, "pkg"))
490 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "./libgo2")
491 if out, err := cmd.CombinedOutput(); err != nil {
495 checkLineComments(t, "libgo2.h")
496 checkArchive(t, "libgo2.a")
498 ccArgs := append(cc, "-o", "testp"+exeSuffix, "main2.c", "libgo2.a")
499 if runtime.Compiler == "gccgo" {
500 ccArgs = append(ccArgs, "-lgo")
502 if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
508 if runtime.GOOS == "darwin" {
511 cmd = exec.Command(bin[0], append(bin[1:], darwin)...)
513 if out, err := cmd.CombinedOutput(); err != nil {
519 func TestSignalForwarding(t *testing.T) {
520 checkSignalForwardingTest(t)
524 os.Remove("libgo2.a")
525 os.Remove("libgo2.h")
526 os.Remove("testp" + exeSuffix)
527 os.RemoveAll(filepath.Join(GOPATH, "pkg"))
531 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "./libgo2")
532 if out, err := cmd.CombinedOutput(); err != nil {
536 checkLineComments(t, "libgo2.h")
537 checkArchive(t, "libgo2.a")
539 ccArgs := append(cc, "-o", "testp"+exeSuffix, "main5.c", "libgo2.a")
540 if runtime.Compiler == "gccgo" {
541 ccArgs = append(ccArgs, "-lgo")
543 if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
548 cmd = exec.Command(bin[0], append(bin[1:], "1")...)
550 out, err := cmd.CombinedOutput()
551 t.Logf("%v\n%s", cmd.Args, out)
552 expectSignal(t, err, syscall.SIGSEGV)
554 // SIGPIPE is never forwarded on darwin. See golang.org/issue/33384.
555 if runtime.GOOS != "darwin" && runtime.GOOS != "ios" {
556 // Test SIGPIPE forwarding
557 cmd = exec.Command(bin[0], append(bin[1:], "3")...)
559 out, err = cmd.CombinedOutput()
563 expectSignal(t, err, syscall.SIGPIPE)
567 func TestSignalForwardingExternal(t *testing.T) {
568 if GOOS == "freebsd" || GOOS == "aix" {
569 t.Skipf("skipping on %s/%s; signal always goes to the Go runtime", GOOS, GOARCH)
570 } else if GOOS == "darwin" && GOARCH == "amd64" {
571 t.Skipf("skipping on %s/%s: runtime does not permit SI_USER SIGSEGV", GOOS, GOARCH)
573 checkSignalForwardingTest(t)
577 os.Remove("libgo2.a")
578 os.Remove("libgo2.h")
579 os.Remove("testp" + exeSuffix)
580 os.RemoveAll(filepath.Join(GOPATH, "pkg"))
584 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "./libgo2")
585 if out, err := cmd.CombinedOutput(); err != nil {
589 checkLineComments(t, "libgo2.h")
590 checkArchive(t, "libgo2.a")
592 ccArgs := append(cc, "-o", "testp"+exeSuffix, "main5.c", "libgo2.a")
593 if runtime.Compiler == "gccgo" {
594 ccArgs = append(ccArgs, "-lgo")
596 if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
601 // We want to send the process a signal and see if it dies.
602 // Normally the signal goes to the C thread, the Go signal
603 // handler picks it up, sees that it is running in a C thread,
604 // and the program dies. Unfortunately, occasionally the
605 // signal is delivered to a Go thread, which winds up
606 // discarding it because it was sent by another program and
607 // there is no Go handler for it. To avoid this, run the
608 // program several times in the hopes that it will eventually
611 for i := 0; i < tries; i++ {
612 cmd = exec.Command(bin[0], append(bin[1:], "2")...)
614 stderr, err := cmd.StderrPipe()
620 r := bufio.NewReader(stderr)
628 // Wait for trigger to ensure that the process is started.
629 ok, err := r.ReadString('\n')
632 if err != nil || ok != "OK\n" {
633 t.Fatalf("Did not receive OK signal")
636 // Give the program a chance to enter the sleep function.
637 time.Sleep(time.Millisecond)
639 cmd.Process.Signal(syscall.SIGSEGV)
647 if expectSignal(t, err, syscall.SIGSEGV) {
652 t.Errorf("program succeeded unexpectedly %d times", tries)
655 // checkSignalForwardingTest calls t.Skip if the SignalForwarding test
656 // doesn't work on this platform.
657 func checkSignalForwardingTest(t *testing.T) {
659 case "darwin", "ios":
662 t.Skipf("skipping on %s/%s; see https://golang.org/issue/13701", GOOS, GOARCH)
665 t.Skip("skipping signal test on Windows")
669 // expectSignal checks that err, the exit status of a test program,
670 // shows a failure due to a specific signal. Returns whether we found
671 // the expected signal.
672 func expectSignal(t *testing.T, err error, sig syscall.Signal) bool {
674 t.Error("test program succeeded unexpectedly")
675 } else if ee, ok := err.(*exec.ExitError); !ok {
676 t.Errorf("error (%v) has type %T; expected exec.ExitError", err, err)
677 } else if ws, ok := ee.Sys().(syscall.WaitStatus); !ok {
678 t.Errorf("error.Sys (%v) has type %T; expected syscall.WaitStatus", ee.Sys(), ee.Sys())
679 } else if !ws.Signaled() || ws.Signal() != sig {
680 t.Errorf("got %v; expected signal %v", ee, sig)
687 func TestOsSignal(t *testing.T) {
690 t.Skip("skipping signal test on Windows")
695 os.Remove("libgo3.a")
696 os.Remove("libgo3.h")
697 os.Remove("testp" + exeSuffix)
698 os.RemoveAll(filepath.Join(GOPATH, "pkg"))
702 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo3.a", "./libgo3")
703 if out, err := cmd.CombinedOutput(); err != nil {
707 checkLineComments(t, "libgo3.h")
708 checkArchive(t, "libgo3.a")
710 ccArgs := append(cc, "-o", "testp"+exeSuffix, "main3.c", "libgo3.a")
711 if runtime.Compiler == "gccgo" {
712 ccArgs = append(ccArgs, "-lgo")
714 if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
719 if out, err := exec.Command(bin[0], bin[1:]...).CombinedOutput(); err != nil {
725 func TestSigaltstack(t *testing.T) {
728 t.Skip("skipping signal test on Windows")
733 os.Remove("libgo4.a")
734 os.Remove("libgo4.h")
735 os.Remove("testp" + exeSuffix)
736 os.RemoveAll(filepath.Join(GOPATH, "pkg"))
740 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo4.a", "./libgo4")
741 if out, err := cmd.CombinedOutput(); err != nil {
745 checkLineComments(t, "libgo4.h")
746 checkArchive(t, "libgo4.a")
748 ccArgs := append(cc, "-o", "testp"+exeSuffix, "main4.c", "libgo4.a")
749 if runtime.Compiler == "gccgo" {
750 ccArgs = append(ccArgs, "-lgo")
752 if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
757 if out, err := exec.Command(bin[0], bin[1:]...).CombinedOutput(); err != nil {
763 const testar = `#!/usr/bin/env bash
764 while [[ $1 == -* ]] >/dev/null; do
768 echo "testar" > PWD/testar.ran
771 func TestExtar(t *testing.T) {
774 t.Skip("skipping signal test on Windows")
776 if runtime.Compiler == "gccgo" {
777 t.Skip("skipping -extar test when using gccgo")
779 if runtime.GOOS == "ios" {
780 t.Skip("shell scripts are not executable on iOS hosts")
785 os.Remove("libgo4.a")
786 os.Remove("libgo4.h")
788 os.Remove("testar.ran")
789 os.RemoveAll(filepath.Join(GOPATH, "pkg"))
794 dir, err := os.Getwd()
798 s := strings.Replace(testar, "PWD", dir, 1)
799 if err := os.WriteFile("testar", []byte(s), 0777); err != nil {
803 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-ldflags=-extar="+filepath.Join(dir, "testar"), "-o", "libgo4.a", "./libgo4")
804 if out, err := cmd.CombinedOutput(); err != nil {
808 checkLineComments(t, "libgo4.h")
810 if _, err := os.Stat("testar.ran"); err != nil {
811 if os.IsNotExist(err) {
812 t.Error("testar does not exist after go build")
814 t.Errorf("error checking testar: %v", err)
819 func TestPIE(t *testing.T) {
821 case "windows", "darwin", "ios", "plan9":
822 t.Skipf("skipping PIE test on %s", GOOS)
827 os.Remove("testp" + exeSuffix)
828 os.RemoveAll(filepath.Join(GOPATH, "pkg"))
832 // Generate the p.h header file.
834 // 'go install -i -buildmode=c-archive ./libgo' would do that too, but that
835 // would also attempt to install transitive standard-library dependencies to
836 // GOROOT, and we cannot assume that GOROOT is writable. (A non-root user may
837 // be running this test in a GOROOT owned by root.)
838 genHeader(t, "p.h", "./p")
840 cmd := exec.Command("go", "install", "-buildmode=c-archive", "./libgo")
841 if out, err := cmd.CombinedOutput(); err != nil {
847 if runtime.Compiler == "gccgo" {
848 libgoa = "liblibgo.a"
851 ccArgs := append(cc, "-fPIE", "-pie", "-o", "testp"+exeSuffix, "main.c", "main_unix.c", filepath.Join(libgodir, libgoa))
852 if runtime.Compiler == "gccgo" {
853 ccArgs = append(ccArgs, "-lgo")
855 if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
860 binArgs := append(bin, "arg1", "arg2")
861 cmd = exec.Command(binArgs[0], binArgs[1:]...)
862 if runtime.Compiler == "gccgo" {
863 cmd.Env = append(os.Environ(), "GCCGO=1")
865 if out, err := cmd.CombinedOutput(); err != nil {
871 f, err := elf.Open("testp" + exeSuffix)
873 t.Fatal("elf.Open failed: ", err)
876 if hasDynTag(t, f, elf.DT_TEXTREL) {
877 t.Errorf("%s has DT_TEXTREL flag", "testp"+exeSuffix)
882 func hasDynTag(t *testing.T, f *elf.File, tag elf.DynTag) bool {
883 ds := f.SectionByType(elf.SHT_DYNAMIC)
885 t.Error("no SHT_DYNAMIC section")
890 t.Errorf("can't read SHT_DYNAMIC contents: %v", err)
897 t = elf.DynTag(f.ByteOrder.Uint32(d[:4]))
900 t = elf.DynTag(f.ByteOrder.Uint64(d[:8]))
910 func TestSIGPROF(t *testing.T) {
912 case "windows", "plan9":
913 t.Skipf("skipping SIGPROF test on %s", GOOS)
914 case "darwin", "ios":
915 t.Skipf("skipping SIGPROF test on %s; see https://golang.org/issue/19320", GOOS)
922 os.Remove("testp6" + exeSuffix)
923 os.Remove("libgo6.a")
924 os.Remove("libgo6.h")
928 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo6.a", "./libgo6")
929 out, err := cmd.CombinedOutput()
930 t.Logf("%v\n%s", cmd.Args, out)
934 checkLineComments(t, "libgo6.h")
935 checkArchive(t, "libgo6.a")
937 ccArgs := append(cc, "-o", "testp6"+exeSuffix, "main6.c", "libgo6.a")
938 if runtime.Compiler == "gccgo" {
939 ccArgs = append(ccArgs, "-lgo")
941 out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
942 t.Logf("%v\n%s", ccArgs, out)
947 argv := cmdToRun("./testp6")
948 cmd = exec.Command(argv[0], argv[1:]...)
949 out, err = cmd.CombinedOutput()
950 t.Logf("%v\n%s", argv, out)
956 // TestCompileWithoutShared tests that if we compile code without the
957 // -shared option, we can put it into an archive. When we use the go
958 // tool with -buildmode=c-archive, it passes -shared to the compiler,
959 // so we override that. The go tool doesn't work this way, but Bazel
960 // will likely do it in the future. And it ought to work. This test
961 // was added because at one time it did not work on PPC Linux.
962 func TestCompileWithoutShared(t *testing.T) {
963 // For simplicity, reuse the signal forwarding test.
964 checkSignalForwardingTest(t)
968 os.Remove("libgo2.a")
969 os.Remove("libgo2.h")
973 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-gcflags=-shared=false", "-o", "libgo2.a", "./libgo2")
974 out, err := cmd.CombinedOutput()
975 t.Logf("%v\n%s", cmd.Args, out)
979 checkLineComments(t, "libgo2.h")
980 checkArchive(t, "libgo2.a")
982 exe := "./testnoshared" + exeSuffix
984 // In some cases, -no-pie is needed here, but not accepted everywhere. First try
985 // if -no-pie is accepted. See #22126.
986 ccArgs := append(cc, "-o", exe, "-no-pie", "main5.c", "libgo2.a")
987 if runtime.Compiler == "gccgo" {
988 ccArgs = append(ccArgs, "-lgo")
990 out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
991 t.Logf("%v\n%s", ccArgs, out)
993 // If -no-pie unrecognized, try -nopie if this is possibly clang
994 if err != nil && bytes.Contains(out, []byte("unknown")) && !strings.Contains(cc[0], "gcc") {
995 ccArgs = append(cc, "-o", exe, "-nopie", "main5.c", "libgo2.a")
996 out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
997 t.Logf("%v\n%s", ccArgs, out)
1000 // Don't use either -no-pie or -nopie
1001 if err != nil && bytes.Contains(out, []byte("unrecognized")) {
1002 ccArgs = append(cc, "-o", exe, "main5.c", "libgo2.a")
1003 out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
1004 t.Logf("%v\n%s", ccArgs, out)
1010 defer os.Remove(exe)
1013 binArgs := append(cmdToRun(exe), "1")
1014 out, err = exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput()
1015 t.Logf("%v\n%s", binArgs, out)
1016 expectSignal(t, err, syscall.SIGSEGV)
1018 // SIGPIPE is never forwarded on darwin. See golang.org/issue/33384.
1019 if runtime.GOOS != "darwin" && runtime.GOOS != "ios" {
1020 binArgs := append(cmdToRun(exe), "3")
1021 out, err = exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput()
1022 t.Logf("%v\n%s", binArgs, out)
1023 expectSignal(t, err, syscall.SIGPIPE)
1027 // Test that installing a second time recreates the header file.
1028 func TestCachedInstall(t *testing.T) {
1030 defer os.RemoveAll(filepath.Join(GOPATH, "pkg"))
1033 h := filepath.Join(libgodir, "libgo.h")
1035 buildcmd := []string{"go", "install", "-buildmode=c-archive", "./libgo"}
1037 cmd := exec.Command(buildcmd[0], buildcmd[1:]...)
1039 if out, err := cmd.CombinedOutput(); err != nil {
1044 if _, err := os.Stat(h); err != nil {
1045 t.Errorf("libgo.h not installed: %v", err)
1048 if err := os.Remove(h); err != nil {
1052 cmd = exec.Command(buildcmd[0], buildcmd[1:]...)
1054 if out, err := cmd.CombinedOutput(); err != nil {
1059 if _, err := os.Stat(h); err != nil {
1060 t.Errorf("libgo.h not installed in second run: %v", err)
1065 func TestManyCalls(t *testing.T) {
1070 os.Remove("testp7" + exeSuffix)
1071 os.Remove("libgo7.a")
1072 os.Remove("libgo7.h")
1076 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo7.a", "./libgo7")
1077 out, err := cmd.CombinedOutput()
1078 t.Logf("%v\n%s", cmd.Args, out)
1082 checkLineComments(t, "libgo7.h")
1083 checkArchive(t, "libgo7.a")
1085 ccArgs := append(cc, "-o", "testp7"+exeSuffix, "main7.c", "libgo7.a")
1086 if runtime.Compiler == "gccgo" {
1087 ccArgs = append(ccArgs, "-lgo")
1089 out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
1090 t.Logf("%v\n%s", ccArgs, out)
1095 argv := cmdToRun("./testp7")
1096 cmd = exec.Command(argv[0], argv[1:]...)
1097 sb := new(strings.Builder)
1100 if err := cmd.Start(); err != nil {
1104 timer := time.AfterFunc(time.Minute,
1106 t.Error("test program timed out")
1113 t.Logf("%v\n%s", cmd.Args, sb)
1120 func TestPreemption(t *testing.T) {
1121 if runtime.Compiler == "gccgo" {
1122 t.Skip("skipping asynchronous preemption test with gccgo")
1129 os.Remove("testp8" + exeSuffix)
1130 os.Remove("libgo8.a")
1131 os.Remove("libgo8.h")
1135 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo8.a", "./libgo8")
1136 out, err := cmd.CombinedOutput()
1137 t.Logf("%v\n%s", cmd.Args, out)
1141 checkLineComments(t, "libgo8.h")
1142 checkArchive(t, "libgo8.a")
1144 ccArgs := append(cc, "-o", "testp8"+exeSuffix, "main8.c", "libgo8.a")
1145 out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
1146 t.Logf("%v\n%s", ccArgs, out)
1151 argv := cmdToRun("./testp8")
1152 cmd = exec.Command(argv[0], argv[1:]...)
1153 sb := new(strings.Builder)
1156 if err := cmd.Start(); err != nil {
1160 timer := time.AfterFunc(time.Minute,
1162 t.Error("test program timed out")
1169 t.Logf("%v\n%s", cmd.Args, sb)