| | |
| | |
| | |
| |
|
| | package rand_test |
| |
|
| | import ( |
| | "fmt" |
| | "internal/race" |
| | "internal/testenv" |
| | . "math/rand" |
| | "os" |
| | "runtime" |
| | "strconv" |
| | "sync" |
| | "testing" |
| | ) |
| |
|
| | |
| | func TestDefaultRace(t *testing.T) { |
| | |
| | |
| | |
| | if testing.Short() && !race.Enabled { |
| | t.Skip("skipping starting another executable in short mode") |
| | } |
| |
|
| | const env = "GO_RAND_TEST_HELPER_CODE" |
| | if v := os.Getenv(env); v != "" { |
| | doDefaultTest(t, v) |
| | return |
| | } |
| |
|
| | t.Parallel() |
| |
|
| | for i := 0; i < 6; i++ { |
| | t.Run(strconv.Itoa(i), func(t *testing.T) { |
| | t.Parallel() |
| | cmd := testenv.Command(t, testenv.Executable(t), "-test.run=^TestDefaultRace$") |
| | cmd = testenv.CleanCmdEnv(cmd) |
| | cmd.Env = append(cmd.Env, fmt.Sprintf("GO_RAND_TEST_HELPER_CODE=%d", i/2)) |
| | if i%2 != 0 { |
| | cmd.Env = append(cmd.Env, "GODEBUG=randautoseed=0") |
| | } |
| | out, err := cmd.CombinedOutput() |
| | if len(out) > 0 { |
| | t.Logf("%s", out) |
| | } |
| | if err != nil { |
| | t.Error(err) |
| | } |
| | }) |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | func doDefaultTest(t *testing.T, v string) { |
| | code, err := strconv.Atoi(v) |
| | if err != nil { |
| | t.Fatalf("internal error: unrecognized code %q", v) |
| | } |
| |
|
| | goroutines := runtime.GOMAXPROCS(0) |
| | if goroutines < 4 { |
| | goroutines = 4 |
| | } |
| |
|
| | ch := make(chan uint64, goroutines*3) |
| | var wg sync.WaitGroup |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | switch code { |
| | case 0: |
| | |
| | wg.Add(goroutines) |
| | for i := 0; i < goroutines; i++ { |
| | go func(s int64) { |
| | defer wg.Done() |
| | Seed(s) |
| | }(int64(i) + 100) |
| | } |
| | wg.Add(goroutines) |
| | for i := 0; i < goroutines; i++ { |
| | go func() { |
| | defer wg.Done() |
| | ch <- Uint64() |
| | }() |
| | } |
| | case 1: |
| | |
| | wg.Add(goroutines) |
| | for i := 0; i < goroutines; i++ { |
| | go func() { |
| | defer wg.Done() |
| | ch <- Uint64() |
| | }() |
| | } |
| | case 2: |
| | |
| | |
| | ch <- Uint64() |
| | wg.Add(goroutines) |
| | for i := 0; i < goroutines; i++ { |
| | go func(s int64) { |
| | defer wg.Done() |
| | Seed(s) |
| | }(int64(i) + 100) |
| | } |
| | wg.Add(goroutines) |
| | for i := 0; i < goroutines; i++ { |
| | go func() { |
| | defer wg.Done() |
| | ch <- Uint64() |
| | }() |
| | } |
| | default: |
| | t.Fatalf("internal error: unrecognized code %d", code) |
| | } |
| |
|
| | go func() { |
| | wg.Wait() |
| | close(ch) |
| | }() |
| |
|
| | m := make(map[uint64]bool) |
| | for i := range ch { |
| | if m[i] { |
| | t.Errorf("saw %d twice", i) |
| | } |
| | m[i] = true |
| | } |
| | } |
| |
|