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  }