github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/link/internal/ld/ld_test.go (about) 1 // Copyright 2018 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. 4 5 package ld 6 7 import ( 8 "fmt" 9 "github.com/gagliardetto/golang-go/not-internal/testenv" 10 "io/ioutil" 11 "os" 12 "os/exec" 13 "path/filepath" 14 "runtime" 15 "strings" 16 "testing" 17 ) 18 19 func TestUndefinedRelocErrors(t *testing.T) { 20 t.Parallel() 21 testenv.MustHaveGoBuild(t) 22 dir, err := ioutil.TempDir("", "go-build") 23 if err != nil { 24 t.Fatal(err) 25 } 26 defer os.RemoveAll(dir) 27 28 out, err := exec.Command(testenv.GoToolPath(t), "build", "./testdata/issue10978").CombinedOutput() 29 if err == nil { 30 t.Fatal("expected build to fail") 31 } 32 33 wantErrors := map[string]int{ 34 // Main function has dedicated error message. 35 "function main is undeclared in the main package": 1, 36 37 // Single error reporting per each symbol. 38 // This way, duplicated messages are not reported for 39 // multiple relocations with a same name. 40 "main.defined1: relocation target main.undefined not defined": 1, 41 "main.defined2: relocation target main.undefined not defined": 1, 42 } 43 unexpectedErrors := map[string]int{} 44 45 for _, l := range strings.Split(string(out), "\n") { 46 if strings.HasPrefix(l, "#") || l == "" { 47 continue 48 } 49 matched := "" 50 for want := range wantErrors { 51 if strings.Contains(l, want) { 52 matched = want 53 break 54 } 55 } 56 if matched != "" { 57 wantErrors[matched]-- 58 } else { 59 unexpectedErrors[l]++ 60 } 61 } 62 63 for want, n := range wantErrors { 64 switch { 65 case n > 0: 66 t.Errorf("unmatched error: %s (x%d)", want, n) 67 case n < 0: 68 t.Errorf("extra errors: %s (x%d)", want, -n) 69 } 70 } 71 for unexpected, n := range unexpectedErrors { 72 t.Errorf("unexpected error: %s (x%d)", unexpected, n) 73 } 74 } 75 76 const carchiveSrcText = ` 77 package main 78 79 //export GoFunc 80 func GoFunc() { 81 println(42) 82 } 83 84 func main() { 85 } 86 ` 87 88 func TestArchiveBuildInvokeWithExec(t *testing.T) { 89 t.Parallel() 90 testenv.MustHaveGoBuild(t) 91 testenv.MustHaveCGO(t) 92 93 // run this test on just a small set of platforms (no need to test it 94 // across the board given the nature of the test). 95 pair := runtime.GOOS + "-" + runtime.GOARCH 96 switch pair { 97 case "darwin-amd64", "darwin-arm64", "linux-amd64", "freebsd-amd64": 98 default: 99 t.Skip("no need for test on " + pair) 100 } 101 switch runtime.GOOS { 102 case "openbsd", "windows": 103 t.Skip("c-archive unsupported") 104 } 105 dir, err := ioutil.TempDir("", "go-build") 106 if err != nil { 107 t.Fatal(err) 108 } 109 defer os.RemoveAll(dir) 110 111 srcfile := filepath.Join(dir, "test.go") 112 arfile := filepath.Join(dir, "test.a") 113 if err := ioutil.WriteFile(srcfile, []byte(carchiveSrcText), 0666); err != nil { 114 t.Fatal(err) 115 } 116 117 ldf := fmt.Sprintf("-ldflags=-v -tmpdir=%s", dir) 118 argv := []string{"build", "-buildmode=c-archive", "-o", arfile, ldf, srcfile} 119 out, err := exec.Command(testenv.GoToolPath(t), argv...).CombinedOutput() 120 if err != nil { 121 t.Fatalf("build failure: %s\n%s\n", err, string(out)) 122 } 123 124 found := false 125 const want = "invoking archiver with syscall.Exec" 126 for _, l := range strings.Split(string(out), "\n") { 127 if strings.HasPrefix(l, want) { 128 found = true 129 break 130 } 131 } 132 133 if !found { 134 t.Errorf("expected '%s' in -v output, got:\n%s\n", want, string(out)) 135 } 136 }