rsc.io/go@v0.0.0-20150416155037-e040fd465409/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  	"io/ioutil"
    11  	"os"
    12  	"os/exec"
    13  	"path/filepath"
    14  	"regexp"
    15  	"strings"
    16  	"testing"
    17  )
    18  
    19  func TestOutput(t *testing.T) {
    20  	for _, test := range tests {
    21  		dir, err := ioutil.TempDir("", "go-build")
    22  		if err != nil {
    23  			t.Fatalf("failed to create temp directory: %v", err)
    24  		}
    25  		defer os.RemoveAll(dir)
    26  		source := "main.go"
    27  		if test.run == "test" {
    28  			source = "main_test.go"
    29  		}
    30  		src := filepath.Join(dir, source)
    31  		f, err := os.Create(src)
    32  		if err != nil {
    33  			t.Fatalf("failed to create file: %v", err)
    34  		}
    35  		_, err = f.WriteString(test.source)
    36  		if err != nil {
    37  			f.Close()
    38  			t.Fatalf("failed to write: %v", err)
    39  		}
    40  		if err := f.Close(); err != nil {
    41  			t.Fatalf("failed to close file: %v", err)
    42  		}
    43  		// Pass -l to the compiler to test stack traces.
    44  		cmd := exec.Command("go", test.run, "-race", "-gcflags=-l", src)
    45  		// GODEBUG spoils program output, GOMAXPROCS makes it flaky.
    46  		for _, env := range os.Environ() {
    47  			if strings.HasPrefix(env, "GODEBUG=") ||
    48  				strings.HasPrefix(env, "GOMAXPROCS=") ||
    49  				strings.HasPrefix(env, "GORACE=") {
    50  				continue
    51  			}
    52  			cmd.Env = append(cmd.Env, env)
    53  		}
    54  		cmd.Env = append(cmd.Env, "GORACE="+test.gorace)
    55  		got, _ := cmd.CombinedOutput()
    56  		if !regexp.MustCompile(test.re).MatchString(string(got)) {
    57  			t.Fatalf("failed test case %v, expect:\n%v\ngot:\n%s",
    58  				test.name, test.re, got)
    59  		}
    60  	}
    61  }
    62  
    63  var tests = []struct {
    64  	name   string
    65  	run    string
    66  	gorace string
    67  	source string
    68  	re     string
    69  }{
    70  	{"simple", "run", "atexit_sleep_ms=0", `
    71  package main
    72  import "time"
    73  func main() {
    74  	done := make(chan bool)
    75  	x := 0
    76  	startRacer(&x, done)
    77  	store(&x, 43)
    78  	<-done
    79  }
    80  func store(x *int, v int) {
    81  	*x = v
    82  }
    83  func startRacer(x *int, done chan bool) {
    84  	go racer(x, done)
    85  }
    86  func racer(x *int, done chan bool) {
    87  	time.Sleep(10*time.Millisecond)
    88  	store(x, 42)
    89  	done <- true
    90  }
    91  `, `==================
    92  WARNING: DATA RACE
    93  Write by goroutine [0-9]:
    94    main\.store\(\)
    95        .+/main\.go:12 \+0x[0-9,a-f]+
    96    main\.racer\(\)
    97        .+/main\.go:19 \+0x[0-9,a-f]+
    98  
    99  Previous write by main goroutine:
   100    main\.store\(\)
   101        .+/main\.go:12 \+0x[0-9,a-f]+
   102    main\.main\(\)
   103        .+/main\.go:8 \+0x[0-9,a-f]+
   104  
   105  Goroutine [0-9] \(running\) created at:
   106    main\.startRacer\(\)
   107        .+/main\.go:15 \+0x[0-9,a-f]+
   108    main\.main\(\)
   109        .+/main\.go:7 \+0x[0-9,a-f]+
   110  ==================
   111  Found 1 data race\(s\)
   112  exit status 66
   113  `},
   114  
   115  	{"exitcode", "run", "atexit_sleep_ms=0 exitcode=13", `
   116  package main
   117  func main() {
   118  	done := make(chan bool)
   119  	x := 0
   120  	go func() {
   121  		x = 42
   122  		done <- true
   123  	}()
   124  	x = 43
   125  	<-done
   126  }
   127  `, `exit status 13`},
   128  
   129  	{"strip_path_prefix", "run", "atexit_sleep_ms=0 strip_path_prefix=/main.", `
   130  package main
   131  func main() {
   132  	done := make(chan bool)
   133  	x := 0
   134  	go func() {
   135  		x = 42
   136  		done <- true
   137  	}()
   138  	x = 43
   139  	<-done
   140  }
   141  `, `
   142        go:7 \+0x[0-9,a-f]+
   143  `},
   144  
   145  	{"halt_on_error", "run", "atexit_sleep_ms=0 halt_on_error=1", `
   146  package main
   147  func main() {
   148  	done := make(chan bool)
   149  	x := 0
   150  	go func() {
   151  		x = 42
   152  		done <- true
   153  	}()
   154  	x = 43
   155  	<-done
   156  }
   157  `, `
   158  ==================
   159  exit status 66
   160  `},
   161  
   162  	{"test_fails_on_race", "test", "atexit_sleep_ms=0", `
   163  package main_test
   164  import "testing"
   165  func TestFail(t *testing.T) {
   166  	done := make(chan bool)
   167  	x := 0
   168  	go func() {
   169  		x = 42
   170  		done <- true
   171  	}()
   172  	x = 43
   173  	<-done
   174  }
   175  `, `
   176  ==================
   177  PASS
   178  Found 1 data race\(s\)
   179  FAIL`},
   180  }