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, errors, file)
    64  	})
    65  }
    66  
    67  func expect(t *testing.T, errors []*regexp.Regexp, files ...string) {
    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(files[0], ".go"))
    75  	args := []string{"build", "-gcflags=-L -e", "-o=" + dst} // TODO(gri) no need for -gcflags=-L if go tool is adjusted
    76  	for _, file := range files {
    77  		args = append(args, path(file))
    78  	}
    79  	cmd := exec.Command("go", args...)
    80  	out, err := cmd.CombinedOutput()
    81  	if err == nil {
    82  		t.Errorf("expected cgo to fail but it succeeded")
    83  	}
    84  
    85  	lines := bytes.Split(out, []byte("\n"))
    86  	for _, re := range errors {
    87  		found := false
    88  		for _, line := range lines {
    89  			if re.Match(line) {
    90  				t.Logf("found match for %#q: %q", re, line)
    91  				found = true
    92  				break
    93  			}
    94  		}
    95  		if !found {
    96  			t.Errorf("expected error output to contain %#q", re)
    97  		}
    98  	}
    99  
   100  	if t.Failed() {
   101  		t.Logf("actual output:\n%s", out)
   102  	}
   103  }
   104  
   105  func sizeofLongDouble(t *testing.T) int {
   106  	testenv.MustHaveGoRun(t)
   107  	testenv.MustHaveCGO(t)
   108  	cmd := exec.Command("go", "run", path("long_double_size.go"))
   109  	out, err := cmd.CombinedOutput()
   110  	if err != nil {
   111  		t.Fatalf("%#q: %v:\n%s", strings.Join(cmd.Args, " "), err, out)
   112  	}
   113  
   114  	i, err := strconv.Atoi(strings.TrimSpace(string(out)))
   115  	if err != nil {
   116  		t.Fatalf("long_double_size.go printed invalid size: %s", out)
   117  	}
   118  	return i
   119  }
   120  
   121  func TestReportsTypeErrors(t *testing.T) {
   122  	for _, file := range []string{
   123  		"err1.go",
   124  		"err2.go",
   125  		"err5.go",
   126  		"issue11097a.go",
   127  		"issue11097b.go",
   128  		"issue18452.go",
   129  		"issue18889.go",
   130  		"issue28721.go",
   131  		"issue33061.go",
   132  		"issue50710.go",
   133  		"issue67517.go",
   134  		"issue67707.go",
   135  		"issue69176.go",
   136  	} {
   137  		check(t, file)
   138  	}
   139  
   140  	if sizeofLongDouble(t) > 8 {
   141  		for _, file := range []string{
   142  			"err4.go",
   143  			"issue28069.go",
   144  		} {
   145  			check(t, file)
   146  		}
   147  	}
   148  }
   149  
   150  func TestToleratesOptimizationFlag(t *testing.T) {
   151  	for _, cflags := range []string{
   152  		"",
   153  		"-O",
   154  	} {
   155  		cflags := cflags
   156  		t.Run(cflags, func(t *testing.T) {
   157  			testenv.MustHaveGoBuild(t)
   158  			testenv.MustHaveCGO(t)
   159  			t.Parallel()
   160  
   161  			cmd := exec.Command("go", "build", path("issue14669.go"))
   162  			cmd.Env = append(os.Environ(), "CGO_CFLAGS="+cflags)
   163  			out, err := cmd.CombinedOutput()
   164  			if err != nil {
   165  				t.Errorf("%#q: %v:\n%s", strings.Join(cmd.Args, " "), err, out)
   166  			}
   167  		})
   168  	}
   169  }
   170  
   171  func TestMallocCrashesOnNil(t *testing.T) {
   172  	testenv.MustHaveCGO(t)
   173  	testenv.MustHaveGoRun(t)
   174  	t.Parallel()
   175  
   176  	cmd := exec.Command("go", "run", path("malloc.go"))
   177  	out, err := cmd.CombinedOutput()
   178  	if err == nil {
   179  		t.Logf("%#q:\n%s", strings.Join(cmd.Args, " "), out)
   180  		t.Fatalf("succeeded unexpectedly")
   181  	}
   182  }
   183  
   184  func TestNotMatchedCFunction(t *testing.T) {
   185  	file := "notmatchedcfunction.go"
   186  	check(t, file)
   187  }
   188  
   189  func TestIncompatibleDeclarations(t *testing.T) {
   190  	testenv.MustHaveCGO(t)
   191  	testenv.MustHaveGoRun(t)
   192  	t.Parallel()
   193  	expect(t, []*regexp.Regexp{
   194  		regexp.MustCompile("inconsistent definitions for C[.]f"),
   195  		regexp.MustCompile("inconsistent definitions for C[.]g"),
   196  	}, "issue67699a.go", "issue67699b.go")
   197  }
   198  

View as plain text