| // Copyright 2011 The Go Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style | 
 | // license that can be found in the LICENSE file. | 
 |  | 
 | package race_test | 
 |  | 
 | import ( | 
 | 	"runtime" | 
 | 	"testing" | 
 | 	"time" | 
 | ) | 
 |  | 
 | func TestNoRaceChanSync(t *testing.T) { | 
 | 	v := 0 | 
 | 	c := make(chan int) | 
 | 	go func() { | 
 | 		v = 1 | 
 | 		c <- 0 | 
 | 	}() | 
 | 	<-c | 
 | 	v = 2 | 
 | } | 
 |  | 
 | func TestNoRaceChanSyncRev(t *testing.T) { | 
 | 	v := 0 | 
 | 	c := make(chan int) | 
 | 	go func() { | 
 | 		c <- 0 | 
 | 		v = 2 | 
 | 	}() | 
 | 	v = 1 | 
 | 	<-c | 
 | } | 
 |  | 
 | func TestNoRaceChanAsync(t *testing.T) { | 
 | 	v := 0 | 
 | 	c := make(chan int, 10) | 
 | 	go func() { | 
 | 		v = 1 | 
 | 		c <- 0 | 
 | 	}() | 
 | 	<-c | 
 | 	v = 2 | 
 | } | 
 |  | 
 | func TestRaceChanAsyncRev(t *testing.T) { | 
 | 	v := 0 | 
 | 	c := make(chan int, 10) | 
 | 	go func() { | 
 | 		c <- 0 | 
 | 		v = 1 | 
 | 	}() | 
 | 	v = 2 | 
 | 	<-c | 
 | } | 
 |  | 
 | func TestNoRaceChanAsyncCloseRecv(t *testing.T) { | 
 | 	v := 0 | 
 | 	c := make(chan int, 10) | 
 | 	go func() { | 
 | 		v = 1 | 
 | 		close(c) | 
 | 	}() | 
 | 	func() { | 
 | 		defer func() { | 
 | 			recover() | 
 | 			v = 2 | 
 | 		}() | 
 | 		<-c | 
 | 	}() | 
 | } | 
 |  | 
 | func TestNoRaceChanAsyncCloseRecv2(t *testing.T) { | 
 | 	v := 0 | 
 | 	c := make(chan int, 10) | 
 | 	go func() { | 
 | 		v = 1 | 
 | 		close(c) | 
 | 	}() | 
 | 	_, _ = <-c | 
 | 	v = 2 | 
 | } | 
 |  | 
 | func TestNoRaceChanAsyncCloseRecv3(t *testing.T) { | 
 | 	v := 0 | 
 | 	c := make(chan int, 10) | 
 | 	go func() { | 
 | 		v = 1 | 
 | 		close(c) | 
 | 	}() | 
 | 	for range c { | 
 | 	} | 
 | 	v = 2 | 
 | } | 
 |  | 
 | func TestNoRaceChanSyncCloseRecv(t *testing.T) { | 
 | 	v := 0 | 
 | 	c := make(chan int) | 
 | 	go func() { | 
 | 		v = 1 | 
 | 		close(c) | 
 | 	}() | 
 | 	func() { | 
 | 		defer func() { | 
 | 			recover() | 
 | 			v = 2 | 
 | 		}() | 
 | 		<-c | 
 | 	}() | 
 | } | 
 |  | 
 | func TestNoRaceChanSyncCloseRecv2(t *testing.T) { | 
 | 	v := 0 | 
 | 	c := make(chan int) | 
 | 	go func() { | 
 | 		v = 1 | 
 | 		close(c) | 
 | 	}() | 
 | 	_, _ = <-c | 
 | 	v = 2 | 
 | } | 
 |  | 
 | func TestNoRaceChanSyncCloseRecv3(t *testing.T) { | 
 | 	v := 0 | 
 | 	c := make(chan int) | 
 | 	go func() { | 
 | 		v = 1 | 
 | 		close(c) | 
 | 	}() | 
 | 	for range c { | 
 | 	} | 
 | 	v = 2 | 
 | } | 
 |  | 
 | func TestRaceChanSyncCloseSend(t *testing.T) { | 
 | 	v := 0 | 
 | 	c := make(chan int) | 
 | 	go func() { | 
 | 		v = 1 | 
 | 		close(c) | 
 | 	}() | 
 | 	func() { | 
 | 		defer func() { | 
 | 			recover() | 
 | 		}() | 
 | 		c <- 0 | 
 | 	}() | 
 | 	v = 2 | 
 | } | 
 |  | 
 | func TestRaceChanAsyncCloseSend(t *testing.T) { | 
 | 	v := 0 | 
 | 	c := make(chan int, 10) | 
 | 	go func() { | 
 | 		v = 1 | 
 | 		close(c) | 
 | 	}() | 
 | 	func() { | 
 | 		defer func() { | 
 | 			recover() | 
 | 		}() | 
 | 		for { | 
 | 			c <- 0 | 
 | 		} | 
 | 	}() | 
 | 	v = 2 | 
 | } | 
 |  | 
 | func TestRaceChanCloseClose(t *testing.T) { | 
 | 	compl := make(chan bool, 2) | 
 | 	v1 := 0 | 
 | 	v2 := 0 | 
 | 	c := make(chan int) | 
 | 	go func() { | 
 | 		defer func() { | 
 | 			if recover() != nil { | 
 | 				v2 = 2 | 
 | 			} | 
 | 			compl <- true | 
 | 		}() | 
 | 		v1 = 1 | 
 | 		close(c) | 
 | 	}() | 
 | 	go func() { | 
 | 		defer func() { | 
 | 			if recover() != nil { | 
 | 				v1 = 2 | 
 | 			} | 
 | 			compl <- true | 
 | 		}() | 
 | 		v2 = 1 | 
 | 		close(c) | 
 | 	}() | 
 | 	<-compl | 
 | 	<-compl | 
 | } | 
 |  | 
 | func TestRaceChanSendLen(t *testing.T) { | 
 | 	v := 0 | 
 | 	c := make(chan int, 10) | 
 | 	go func() { | 
 | 		v = 1 | 
 | 		c <- 1 | 
 | 	}() | 
 | 	for len(c) == 0 { | 
 | 		runtime.Gosched() | 
 | 	} | 
 | 	v = 2 | 
 | } | 
 |  | 
 | func TestRaceChanRecvLen(t *testing.T) { | 
 | 	v := 0 | 
 | 	c := make(chan int, 10) | 
 | 	c <- 1 | 
 | 	go func() { | 
 | 		v = 1 | 
 | 		<-c | 
 | 	}() | 
 | 	for len(c) != 0 { | 
 | 		runtime.Gosched() | 
 | 	} | 
 | 	v = 2 | 
 | } | 
 |  | 
 | func TestRaceChanSendSend(t *testing.T) { | 
 | 	compl := make(chan bool, 2) | 
 | 	v1 := 0 | 
 | 	v2 := 0 | 
 | 	c := make(chan int, 1) | 
 | 	go func() { | 
 | 		v1 = 1 | 
 | 		select { | 
 | 		case c <- 1: | 
 | 		default: | 
 | 			v2 = 2 | 
 | 		} | 
 | 		compl <- true | 
 | 	}() | 
 | 	go func() { | 
 | 		v2 = 1 | 
 | 		select { | 
 | 		case c <- 1: | 
 | 		default: | 
 | 			v1 = 2 | 
 | 		} | 
 | 		compl <- true | 
 | 	}() | 
 | 	<-compl | 
 | 	<-compl | 
 | } | 
 |  | 
 | func TestNoRaceChanPtr(t *testing.T) { | 
 | 	type msg struct { | 
 | 		x int | 
 | 	} | 
 | 	c := make(chan *msg) | 
 | 	go func() { | 
 | 		c <- &msg{1} | 
 | 	}() | 
 | 	m := <-c | 
 | 	m.x = 2 | 
 | } | 
 |  | 
 | func TestRaceChanWrongSend(t *testing.T) { | 
 | 	v1 := 0 | 
 | 	v2 := 0 | 
 | 	c := make(chan int, 2) | 
 | 	go func() { | 
 | 		v1 = 1 | 
 | 		c <- 1 | 
 | 	}() | 
 | 	go func() { | 
 | 		v2 = 2 | 
 | 		c <- 2 | 
 | 	}() | 
 | 	time.Sleep(1e7) | 
 | 	if <-c == 1 { | 
 | 		v2 = 3 | 
 | 	} else { | 
 | 		v1 = 3 | 
 | 	} | 
 | } | 
 |  | 
 | func TestRaceChanWrongClose(t *testing.T) { | 
 | 	v1 := 0 | 
 | 	v2 := 0 | 
 | 	c := make(chan int, 1) | 
 | 	go func() { | 
 | 		defer func() { | 
 | 			recover() | 
 | 		}() | 
 | 		v1 = 1 | 
 | 		c <- 1 | 
 | 	}() | 
 | 	go func() { | 
 | 		time.Sleep(1e7) | 
 | 		v2 = 2 | 
 | 		close(c) | 
 | 	}() | 
 | 	time.Sleep(2e7) | 
 | 	if _, who := <-c; who { | 
 | 		v2 = 2 | 
 | 	} else { | 
 | 		v1 = 2 | 
 | 	} | 
 | } | 
 |  | 
 | func TestRaceChanSendClose(t *testing.T) { | 
 | 	compl := make(chan bool, 2) | 
 | 	c := make(chan int, 1) | 
 | 	go func() { | 
 | 		defer func() { | 
 | 			recover() | 
 | 			compl <- true | 
 | 		}() | 
 | 		c <- 1 | 
 | 	}() | 
 | 	go func() { | 
 | 		time.Sleep(10 * time.Millisecond) | 
 | 		close(c) | 
 | 		compl <- true | 
 | 	}() | 
 | 	<-compl | 
 | 	<-compl | 
 | } | 
 |  | 
 | func TestRaceChanSendSelectClose(t *testing.T) { | 
 | 	compl := make(chan bool, 2) | 
 | 	c := make(chan int, 1) | 
 | 	c1 := make(chan int) | 
 | 	go func() { | 
 | 		defer func() { | 
 | 			recover() | 
 | 			compl <- true | 
 | 		}() | 
 | 		time.Sleep(10 * time.Millisecond) | 
 | 		select { | 
 | 		case c <- 1: | 
 | 		case <-c1: | 
 | 		} | 
 | 	}() | 
 | 	go func() { | 
 | 		close(c) | 
 | 		compl <- true | 
 | 	}() | 
 | 	<-compl | 
 | 	<-compl | 
 | } | 
 |  | 
 | func TestRaceSelectReadWriteAsync(t *testing.T) { | 
 | 	done := make(chan bool) | 
 | 	x := 0 | 
 | 	c1 := make(chan int, 10) | 
 | 	c2 := make(chan int, 10) | 
 | 	c3 := make(chan int) | 
 | 	c2 <- 1 | 
 | 	go func() { | 
 | 		select { | 
 | 		case c1 <- x: // read of x races with... | 
 | 		case c3 <- 1: | 
 | 		} | 
 | 		done <- true | 
 | 	}() | 
 | 	select { | 
 | 	case x = <-c2: // ... write to x here | 
 | 	case c3 <- 1: | 
 | 	} | 
 | 	<-done | 
 | } | 
 |  | 
 | func TestRaceSelectReadWriteSync(t *testing.T) { | 
 | 	done := make(chan bool) | 
 | 	x := 0 | 
 | 	c1 := make(chan int) | 
 | 	c2 := make(chan int) | 
 | 	c3 := make(chan int) | 
 | 	// make c1 and c2 ready for communication | 
 | 	go func() { | 
 | 		<-c1 | 
 | 	}() | 
 | 	go func() { | 
 | 		c2 <- 1 | 
 | 	}() | 
 | 	go func() { | 
 | 		select { | 
 | 		case c1 <- x: // read of x races with... | 
 | 		case c3 <- 1: | 
 | 		} | 
 | 		done <- true | 
 | 	}() | 
 | 	select { | 
 | 	case x = <-c2: // ... write to x here | 
 | 	case c3 <- 1: | 
 | 	} | 
 | 	<-done | 
 | } | 
 |  | 
 | func TestNoRaceSelectReadWriteAsync(t *testing.T) { | 
 | 	done := make(chan bool) | 
 | 	x := 0 | 
 | 	c1 := make(chan int) | 
 | 	c2 := make(chan int) | 
 | 	go func() { | 
 | 		select { | 
 | 		case c1 <- x: // read of x does not race with... | 
 | 		case c2 <- 1: | 
 | 		} | 
 | 		done <- true | 
 | 	}() | 
 | 	select { | 
 | 	case x = <-c1: // ... write to x here | 
 | 	case c2 <- 1: | 
 | 	} | 
 | 	<-done | 
 | } | 
 |  | 
 | func TestRaceChanReadWriteAsync(t *testing.T) { | 
 | 	done := make(chan bool) | 
 | 	c1 := make(chan int, 10) | 
 | 	c2 := make(chan int, 10) | 
 | 	c2 <- 10 | 
 | 	x := 0 | 
 | 	go func() { | 
 | 		c1 <- x // read of x races with... | 
 | 		done <- true | 
 | 	}() | 
 | 	x = <-c2 // ... write to x here | 
 | 	<-done | 
 | } | 
 |  | 
 | func TestRaceChanReadWriteSync(t *testing.T) { | 
 | 	done := make(chan bool) | 
 | 	c1 := make(chan int) | 
 | 	c2 := make(chan int) | 
 | 	// make c1 and c2 ready for communication | 
 | 	go func() { | 
 | 		<-c1 | 
 | 	}() | 
 | 	go func() { | 
 | 		c2 <- 10 | 
 | 	}() | 
 | 	x := 0 | 
 | 	go func() { | 
 | 		c1 <- x // read of x races with... | 
 | 		done <- true | 
 | 	}() | 
 | 	x = <-c2 // ... write to x here | 
 | 	<-done | 
 | } | 
 |  | 
 | func TestNoRaceChanReadWriteAsync(t *testing.T) { | 
 | 	done := make(chan bool) | 
 | 	c1 := make(chan int, 10) | 
 | 	x := 0 | 
 | 	go func() { | 
 | 		c1 <- x // read of x does not race with... | 
 | 		done <- true | 
 | 	}() | 
 | 	x = <-c1 // ... write to x here | 
 | 	<-done | 
 | } | 
 |  | 
 | func TestNoRaceProducerConsumerUnbuffered(t *testing.T) { | 
 | 	type Task struct { | 
 | 		f    func() | 
 | 		done chan bool | 
 | 	} | 
 |  | 
 | 	queue := make(chan Task) | 
 |  | 
 | 	go func() { | 
 | 		t := <-queue | 
 | 		t.f() | 
 | 		t.done <- true | 
 | 	}() | 
 |  | 
 | 	doit := func(f func()) { | 
 | 		done := make(chan bool, 1) | 
 | 		queue <- Task{f, done} | 
 | 		<-done | 
 | 	} | 
 |  | 
 | 	x := 0 | 
 | 	doit(func() { | 
 | 		x = 1 | 
 | 	}) | 
 | 	_ = x | 
 | } | 
 |  | 
 | func TestRaceChanItselfSend(t *testing.T) { | 
 | 	compl := make(chan bool, 1) | 
 | 	c := make(chan int, 10) | 
 | 	go func() { | 
 | 		c <- 0 | 
 | 		compl <- true | 
 | 	}() | 
 | 	c = make(chan int, 20) | 
 | 	<-compl | 
 | } | 
 |  | 
 | func TestRaceChanItselfRecv(t *testing.T) { | 
 | 	compl := make(chan bool, 1) | 
 | 	c := make(chan int, 10) | 
 | 	c <- 1 | 
 | 	go func() { | 
 | 		<-c | 
 | 		compl <- true | 
 | 	}() | 
 | 	time.Sleep(1e7) | 
 | 	c = make(chan int, 20) | 
 | 	<-compl | 
 | } | 
 |  | 
 | func TestRaceChanItselfNil(t *testing.T) { | 
 | 	c := make(chan int, 10) | 
 | 	go func() { | 
 | 		c <- 0 | 
 | 	}() | 
 | 	time.Sleep(1e7) | 
 | 	c = nil | 
 | 	_ = c | 
 | } | 
 |  | 
 | func TestRaceChanItselfClose(t *testing.T) { | 
 | 	compl := make(chan bool, 1) | 
 | 	c := make(chan int) | 
 | 	go func() { | 
 | 		close(c) | 
 | 		compl <- true | 
 | 	}() | 
 | 	c = make(chan int) | 
 | 	<-compl | 
 | } | 
 |  | 
 | func TestRaceChanItselfLen(t *testing.T) { | 
 | 	compl := make(chan bool, 1) | 
 | 	c := make(chan int) | 
 | 	go func() { | 
 | 		_ = len(c) | 
 | 		compl <- true | 
 | 	}() | 
 | 	c = make(chan int) | 
 | 	<-compl | 
 | } | 
 |  | 
 | func TestRaceChanItselfCap(t *testing.T) { | 
 | 	compl := make(chan bool, 1) | 
 | 	c := make(chan int) | 
 | 	go func() { | 
 | 		_ = cap(c) | 
 | 		compl <- true | 
 | 	}() | 
 | 	c = make(chan int) | 
 | 	<-compl | 
 | } | 
 |  | 
 | func TestRaceChanCloseLen(t *testing.T) { | 
 | 	v := 0 | 
 | 	c := make(chan int, 10) | 
 | 	c <- 0 | 
 | 	go func() { | 
 | 		v = 1 | 
 | 		close(c) | 
 | 	}() | 
 | 	time.Sleep(1e7) | 
 | 	_ = len(c) | 
 | 	v = 2 | 
 | } | 
 |  | 
 | func TestRaceChanCloseSend(t *testing.T) { | 
 | 	compl := make(chan bool, 1) | 
 | 	c := make(chan int, 10) | 
 | 	go func() { | 
 | 		close(c) | 
 | 		compl <- true | 
 | 	}() | 
 | 	c <- 0 | 
 | 	<-compl | 
 | } | 
 |  | 
 | func TestNoRaceChanMutex(t *testing.T) { | 
 | 	done := make(chan struct{}) | 
 | 	mtx := make(chan struct{}, 1) | 
 | 	data := 0 | 
 | 	go func() { | 
 | 		mtx <- struct{}{} | 
 | 		data = 42 | 
 | 		<-mtx | 
 | 		done <- struct{}{} | 
 | 	}() | 
 | 	mtx <- struct{}{} | 
 | 	data = 43 | 
 | 	<-mtx | 
 | 	<-done | 
 | } | 
 |  | 
 | func TestNoRaceSelectMutex(t *testing.T) { | 
 | 	done := make(chan struct{}) | 
 | 	mtx := make(chan struct{}, 1) | 
 | 	aux := make(chan bool) | 
 | 	data := 0 | 
 | 	go func() { | 
 | 		select { | 
 | 		case mtx <- struct{}{}: | 
 | 		case <-aux: | 
 | 		} | 
 | 		data = 42 | 
 | 		select { | 
 | 		case <-mtx: | 
 | 		case <-aux: | 
 | 		} | 
 | 		done <- struct{}{} | 
 | 	}() | 
 | 	select { | 
 | 	case mtx <- struct{}{}: | 
 | 	case <-aux: | 
 | 	} | 
 | 	data = 43 | 
 | 	select { | 
 | 	case <-mtx: | 
 | 	case <-aux: | 
 | 	} | 
 | 	<-done | 
 | } | 
 |  | 
 | func TestRaceChanSem(t *testing.T) { | 
 | 	done := make(chan struct{}) | 
 | 	mtx := make(chan bool, 2) | 
 | 	data := 0 | 
 | 	go func() { | 
 | 		mtx <- true | 
 | 		data = 42 | 
 | 		<-mtx | 
 | 		done <- struct{}{} | 
 | 	}() | 
 | 	mtx <- true | 
 | 	data = 43 | 
 | 	<-mtx | 
 | 	<-done | 
 | } | 
 |  | 
 | func TestNoRaceChanWaitGroup(t *testing.T) { | 
 | 	const N = 10 | 
 | 	chanWg := make(chan bool, N/2) | 
 | 	data := make([]int, N) | 
 | 	for i := 0; i < N; i++ { | 
 | 		chanWg <- true | 
 | 		go func(i int) { | 
 | 			data[i] = 42 | 
 | 			<-chanWg | 
 | 		}(i) | 
 | 	} | 
 | 	for i := 0; i < cap(chanWg); i++ { | 
 | 		chanWg <- true | 
 | 	} | 
 | 	for i := 0; i < N; i++ { | 
 | 		_ = data[i] | 
 | 	} | 
 | } | 
 |  | 
 | // Test that sender synchronizes with receiver even if the sender was blocked. | 
 | func TestNoRaceBlockedSendSync(t *testing.T) { | 
 | 	c := make(chan *int, 1) | 
 | 	c <- nil | 
 | 	go func() { | 
 | 		i := 42 | 
 | 		c <- &i | 
 | 	}() | 
 | 	// Give the sender time to actually block. | 
 | 	// This sleep is completely optional: race report must not be printed | 
 | 	// regardless of whether the sender actually blocks or not. | 
 | 	// It cannot lead to flakiness. | 
 | 	time.Sleep(10 * time.Millisecond) | 
 | 	<-c | 
 | 	p := <-c | 
 | 	if *p != 42 { | 
 | 		t.Fatal() | 
 | 	} | 
 | } | 
 |  | 
 | // The same as TestNoRaceBlockedSendSync above, but sender unblock happens in a select. | 
 | func TestNoRaceBlockedSelectSendSync(t *testing.T) { | 
 | 	c := make(chan *int, 1) | 
 | 	c <- nil | 
 | 	go func() { | 
 | 		i := 42 | 
 | 		c <- &i | 
 | 	}() | 
 | 	time.Sleep(10 * time.Millisecond) | 
 | 	<-c | 
 | 	select { | 
 | 	case p := <-c: | 
 | 		if *p != 42 { | 
 | 			t.Fatal() | 
 | 		} | 
 | 	case <-make(chan int): | 
 | 	} | 
 | } |