Source file src/cmd/cgo/internal/testerrors/errors_test.go

     1  // Copyright 2017 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 errorstest
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"internal/testenv"
    11  	"os"
    12  	"os/exec"
    13  	"path/filepath"
    14  	"regexp"
    15  	"strconv"
    16  	"strings"
    17  	"testing"
    18  )
    19  
    20  func path(file string) string {
    21  	return filepath.Join("testdata", file)
    22  }
    23  
    24  func check(t *testing.T, file string) {
    25  	t.Run(file, func(t *testing.T) {
    26  		testenv.MustHaveGoBuild(t)
    27  		testenv.MustHaveCGO(t)
    28  		t.Parallel()
    29  
    30  		contents, err := os.ReadFile(path(file))
    31  		if err != nil {
    32  			t.Fatal(err)
    33  		}
    34  		var errors []*regexp.Regexp
    35  		for i, line := range bytes.Split(contents, []byte("\n")) {
    36  			if bytes.HasSuffix(line, []byte("ERROR HERE")) {
    37  				re := regexp.MustCompile(regexp.QuoteMeta(fmt.Sprintf("%s:%d:", file, i+1)))
    38  				errors = append(errors, re)
    39  				continue
    40  			}
    41  
    42  			if _, frag, ok := bytes.Cut(line, []byte("ERROR HERE: ")); ok {
    43  				re, err := regexp.Compile(fmt.Sprintf(":%d:.*%s", i+1, frag))
    44  				if err != nil {
    45  					t.Errorf("Invalid regexp after `ERROR HERE: `: %#q", frag)
    46  					continue
    47  				}
    48  				errors = append(errors, re)
    49  			}
    50  
    51  			if _, frag, ok := bytes.Cut(line, []byte("ERROR MESSAGE: ")); ok {
    52  				re, err := regexp.Compile(string(frag))
    53  				if err != nil {
    54  					t.Errorf("Invalid regexp after `ERROR MESSAGE: `: %#q", frag)
    55  					continue
    56  				}
    57  				errors = append(errors, re)
    58  			}
    59  		}
    60  		if len(errors) == 0 {
    61  			t.Fatalf("cannot find ERROR HERE")
    62  		}
    63  		expect(t, file, errors)
    64  	})
    65  }
    66  
    67  func expect(t *testing.T, file string, errors []*regexp.Regexp) {
    68  	dir, err := os.MkdirTemp("", filepath.Base(t.Name()))
    69  	if err != nil {
    70  		t.Fatal(err)
    71  	}
    72  	defer os.RemoveAll(dir)
    73  
    74  	dst := filepath.Join(dir, strings.TrimSuffix(file, ".go"))
    75  	cmd := exec.Command("go", "build", "-gcflags=-L -e", "-o="+dst, path(file)) // TODO(gri) no need for -gcflags=-L if go tool is adjusted
    76  	out, err := cmd.CombinedOutput()
    77  	if err == nil {
    78  		t.Errorf("expected cgo to fail but it succeeded")
    79  	}
    80  
    81  	lines := bytes.Split(out, []byte("\n"))
    82  	for _, re := range errors {
    83  		found := false
    84  		for _, line := range lines {
    85  			if re.Match(line) {
    86  				t.Logf("found match for %#q: %q", re, line)
    87  				found = true
    88  				break
    89  			}
    90  		}
    91  		if !found {
    92  			t.Errorf("expected error output to contain %#q", re)
    93  		}
    94  	}
    95  
    96  	if t.Failed() {
    97  		t.Logf("actual output:\n%s", out)
    98  	}
    99  }
   100  
   101  func sizeofLongDouble(t *testing.T) int {
   102  	testenv.MustHaveGoRun(t)
   103  	testenv.MustHaveCGO(t)
   104  	cmd := exec.Command("go", "run", path("long_double_size.go"))
   105  	out, err := cmd.CombinedOutput()
   106  	if err != nil {
   107  		t.Fatalf("%#q: %v:\n%s", strings.Join(cmd.Args, " "), err, out)
   108  	}
   109  
   110  	i, err := strconv.Atoi(strings.TrimSpace(string(out)))
   111  	if err != nil {
   112  		t.Fatalf("long_double_size.go printed invalid size: %s", out)
   113  	}
   114  	return i
   115  }
   116  
   117  func TestReportsTypeErrors(t *testing.T) {
   118  	for _, file := range []string{
   119  		"err1.go",
   120  		"err2.go",
   121  		"err5.go",
   122  		"issue11097a.go",
   123  		"issue11097b.go",
   124  		"issue18452.go",
   125  		"issue18889.go",
   126  		"issue28721.go",
   127  		"issue33061.go",
   128  		"issue50710.go",
   129  		"issue67517.go",
   130  		"issue67707.go",
   131  	} {
   132  		check(t, file)
   133  	}
   134  
   135  	if sizeofLongDouble(t) > 8 {
   136  		for _, file := range []string{
   137  			"err4.go",
   138  			"issue28069.go",
   139  		} {
   140  			check(t, file)
   141  		}
   142  	}
   143  }
   144  
   145  func TestToleratesOptimizationFlag(t *testing.T) {
   146  	for _, cflags := range []string{
   147  		"",
   148  		"-O",
   149  	} {
   150  		cflags := cflags
   151  		t.Run(cflags, func(t *testing.T) {
   152  			testenv.MustHaveGoBuild(t)
   153  			testenv.MustHaveCGO(t)
   154  			t.Parallel()
   155  
   156  			cmd := exec.Command("go", "build", path("issue14669.go"))
   157  			cmd.Env = append(os.Environ(), "CGO_CFLAGS="+cflags)
   158  			out, err := cmd.CombinedOutput()
   159  			if err != nil {
   160  				t.Errorf("%#q: %v:\n%s", strings.Join(cmd.Args, " "), err, out)
   161  			}
   162  		})
   163  	}
   164  }
   165  
   166  func TestMallocCrashesOnNil(t *testing.T) {
   167  	testenv.MustHaveCGO(t)
   168  	testenv.MustHaveGoRun(t)
   169  	t.Parallel()
   170  
   171  	cmd := exec.Command("go", "run", path("malloc.go"))
   172  	out, err := cmd.CombinedOutput()
   173  	if err == nil {
   174  		t.Logf("%#q:\n%s", strings.Join(cmd.Args, " "), out)
   175  		t.Fatalf("succeeded unexpectedly")
   176  	}
   177  }
   178  
   179  func TestNotMatchedCFunction(t *testing.T) {
   180  	file := "notmatchedcfunction.go"
   181  	check(t, file)
   182  }
   183  

View as plain text