github.com/likebike/go--@v0.0.0-20190911215757-0bd925d16e96/go/src/runtime/race/output_test.go (about)

     1  // Copyright 2013 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  // +build race
     6  
     7  package race_test
     8  
     9  import (
    10  	"internal/testenv"
    11  	"io/ioutil"
    12  	"os"
    13  	"os/exec"
    14  	"path/filepath"
    15  	"regexp"
    16  	"runtime"
    17  	"strings"
    18  	"testing"
    19  )
    20  
    21  func TestOutput(t *testing.T) {
    22  	pkgdir, err := ioutil.TempDir("", "go-build-race-output")
    23  	if err != nil {
    24  		t.Fatal(err)
    25  	}
    26  	defer os.RemoveAll(pkgdir)
    27  	out, err := exec.Command(testenv.GoToolPath(t), "install", "-race", "-pkgdir="+pkgdir, "-gcflags=all=-l", "testing").CombinedOutput()
    28  	if err != nil {
    29  		t.Fatalf("go install -race: %v\n%s", err, out)
    30  	}
    31  
    32  	for _, test := range tests {
    33  		if test.goos != "" && test.goos != runtime.GOOS {
    34  			t.Logf("test %v runs only on %v, skipping: ", test.name, test.goos)
    35  			continue
    36  		}
    37  		dir, err := ioutil.TempDir("", "go-build")
    38  		if err != nil {
    39  			t.Fatalf("failed to create temp directory: %v", err)
    40  		}
    41  		defer os.RemoveAll(dir)
    42  		source := "main.go"
    43  		if test.run == "test" {
    44  			source = "main_test.go"
    45  		}
    46  		src := filepath.Join(dir, source)
    47  		f, err := os.Create(src)
    48  		if err != nil {
    49  			t.Fatalf("failed to create file: %v", err)
    50  		}
    51  		_, err = f.WriteString(test.source)
    52  		if err != nil {
    53  			f.Close()
    54  			t.Fatalf("failed to write: %v", err)
    55  		}
    56  		if err := f.Close(); err != nil {
    57  			t.Fatalf("failed to close file: %v", err)
    58  		}
    59  		// Pass -l to the compiler to test stack traces.
    60  		cmd := exec.Command(testenv.GoToolPath(t), test.run, "-race", "-pkgdir="+pkgdir, "-gcflags=all=-l", src)
    61  		// GODEBUG spoils program output, GOMAXPROCS makes it flaky.
    62  		for _, env := range os.Environ() {
    63  			if strings.HasPrefix(env, "GODEBUG=") ||
    64  				strings.HasPrefix(env, "GOMAXPROCS=") ||
    65  				strings.HasPrefix(env, "GORACE=") {
    66  				continue
    67  			}
    68  			cmd.Env = append(cmd.Env, env)
    69  		}
    70  		cmd.Env = append(cmd.Env,
    71  			"GOMAXPROCS=1", // see comment in race_test.go
    72  			"GORACE="+test.gorace,
    73  		)
    74  		got, _ := cmd.CombinedOutput()
    75  		if !regexp.MustCompile(test.re).MatchString(string(got)) {
    76  			t.Fatalf("failed test case %v, expect:\n%v\ngot:\n%s",
    77  				test.name, test.re, got)
    78  		}
    79  	}
    80  }
    81  
    82  var tests = []struct {
    83  	name   string
    84  	run    string
    85  	goos   string
    86  	gorace string
    87  	source string
    88  	re     string
    89  }{
    90  	{"simple", "run", "", "atexit_sleep_ms=0", `
    91  package main
    92  import "time"
    93  func main() {
    94  	done := make(chan bool)
    95  	x := 0
    96  	startRacer(&x, done)
    97  	store(&x, 43)
    98  	<-done
    99  }
   100  func store(x *int, v int) {
   101  	*x = v
   102  }
   103  func startRacer(x *int, done chan bool) {
   104  	go racer(x, done)
   105  }
   106  func racer(x *int, done chan bool) {
   107  	time.Sleep(10*time.Millisecond)
   108  	store(x, 42)
   109  	done <- true
   110  }
   111  `, `==================
   112  WARNING: DATA RACE
   113  Write at 0x[0-9,a-f]+ by goroutine [0-9]:
   114    main\.store\(\)
   115        .+/main\.go:12 \+0x[0-9,a-f]+
   116    main\.racer\(\)
   117        .+/main\.go:19 \+0x[0-9,a-f]+
   118  
   119  Previous write at 0x[0-9,a-f]+ by main goroutine:
   120    main\.store\(\)
   121        .+/main\.go:12 \+0x[0-9,a-f]+
   122    main\.main\(\)
   123        .+/main\.go:8 \+0x[0-9,a-f]+
   124  
   125  Goroutine [0-9] \(running\) created at:
   126    main\.startRacer\(\)
   127        .+/main\.go:15 \+0x[0-9,a-f]+
   128    main\.main\(\)
   129        .+/main\.go:7 \+0x[0-9,a-f]+
   130  ==================
   131  Found 1 data race\(s\)
   132  exit status 66
   133  `},
   134  
   135  	{"exitcode", "run", "", "atexit_sleep_ms=0 exitcode=13", `
   136  package main
   137  func main() {
   138  	done := make(chan bool)
   139  	x := 0
   140  	go func() {
   141  		x = 42
   142  		done <- true
   143  	}()
   144  	x = 43
   145  	<-done
   146  }
   147  `, `exit status 13`},
   148  
   149  	{"strip_path_prefix", "run", "", "atexit_sleep_ms=0 strip_path_prefix=/main.", `
   150  package main
   151  func main() {
   152  	done := make(chan bool)
   153  	x := 0
   154  	go func() {
   155  		x = 42
   156  		done <- true
   157  	}()
   158  	x = 43
   159  	<-done
   160  }
   161  `, `
   162        go:7 \+0x[0-9,a-f]+
   163  `},
   164  
   165  	{"halt_on_error", "run", "", "atexit_sleep_ms=0 halt_on_error=1", `
   166  package main
   167  func main() {
   168  	done := make(chan bool)
   169  	x := 0
   170  	go func() {
   171  		x = 42
   172  		done <- true
   173  	}()
   174  	x = 43
   175  	<-done
   176  }
   177  `, `
   178  ==================
   179  exit status 66
   180  `},
   181  
   182  	{"test_fails_on_race", "test", "", "atexit_sleep_ms=0", `
   183  package main_test
   184  import "testing"
   185  func TestFail(t *testing.T) {
   186  	done := make(chan bool)
   187  	x := 0
   188  	_ = x
   189  	go func() {
   190  		x = 42
   191  		done <- true
   192  	}()
   193  	x = 43
   194  	<-done
   195  	t.Log(t.Failed())
   196  }
   197  `, `
   198  ==================
   199  --- FAIL: TestFail \(0...s\)
   200  .*main_test.go:14: true
   201  .*testing.go:.*: race detected during execution of test
   202  FAIL`},
   203  
   204  	{"slicebytetostring_pc", "run", "", "atexit_sleep_ms=0", `
   205  package main
   206  func main() {
   207  	done := make(chan string)
   208  	data := make([]byte, 10)
   209  	go func() {
   210  		done <- string(data)
   211  	}()
   212  	data[0] = 1
   213  	<-done
   214  }
   215  `, `
   216    runtime\.slicebytetostring\(\)
   217        .*/runtime/string\.go:.*
   218    main\.main\.func1\(\)
   219        .*/main.go:7`},
   220  
   221  	// Test for http://golang.org/issue/17190
   222  	{"external_cgo_thread", "run", "linux", "atexit_sleep_ms=0", `
   223  package main
   224  
   225  /*
   226  #include <pthread.h>
   227  typedef struct cb {
   228          int foo;
   229  } cb;
   230  extern void goCallback();
   231  static inline void *threadFunc(void *p) {
   232  	goCallback();
   233  	return 0;
   234  }
   235  static inline void startThread(cb* c) {
   236  	pthread_t th;
   237  	pthread_create(&th, 0, threadFunc, 0);
   238  }
   239  */
   240  import "C"
   241  
   242  import "time"
   243  
   244  var racy int
   245  
   246  //export goCallback
   247  func goCallback() {
   248  	racy++
   249  }
   250  
   251  func main() {
   252  	var c C.cb
   253  	C.startThread(&c)
   254  	time.Sleep(time.Second)
   255  	racy++
   256  }
   257  `, `==================
   258  WARNING: DATA RACE
   259  Read at 0x[0-9,a-f]+ by main goroutine:
   260    main\.main\(\)
   261        .*/main\.go:34 \+0x[0-9,a-f]+
   262  
   263  Previous write at 0x[0-9,a-f]+ by goroutine [0-9]:
   264    main\.goCallback\(\)
   265        .*/main\.go:27 \+0x[0-9,a-f]+
   266    main._cgoexpwrap_[0-9a-z]+_goCallback\(\)
   267        .*_cgo_gotypes\.go:[0-9]+ \+0x[0-9,a-f]+
   268  
   269  Goroutine [0-9] \(running\) created at:
   270    runtime\.newextram\(\)
   271        .*/runtime/proc.go:[0-9]+ \+0x[0-9,a-f]+
   272  ==================`},
   273  	{"second_test_passes", "test", "", "atexit_sleep_ms=0", `
   274  package main_test
   275  import "testing"
   276  func TestFail(t *testing.T) {
   277  	done := make(chan bool)
   278  	x := 0
   279  	_ = x
   280  	go func() {
   281  		x = 42
   282  		done <- true
   283  	}()
   284  	x = 43
   285  	<-done
   286  }
   287  
   288  func TestPass(t *testing.T) {
   289  }
   290  `, `
   291  ==================
   292  --- FAIL: TestFail \(0...s\)
   293  .*testing.go:.*: race detected during execution of test
   294  FAIL`},
   295  }