Rebase.
[official-gcc.git] / libgo / go / net / fd_mutex_test.go
blobc34ec59b996371a6dc63ee919905f68baf3594d6
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.
5 package net
7 import (
8 "math/rand"
9 "runtime"
10 "testing"
11 "time"
14 func TestMutexLock(t *testing.T) {
15 var mu fdMutex
17 if !mu.Incref() {
18 t.Fatal("broken")
20 if mu.Decref() {
21 t.Fatal("broken")
24 if !mu.RWLock(true) {
25 t.Fatal("broken")
27 if mu.RWUnlock(true) {
28 t.Fatal("broken")
31 if !mu.RWLock(false) {
32 t.Fatal("broken")
34 if mu.RWUnlock(false) {
35 t.Fatal("broken")
39 func TestMutexClose(t *testing.T) {
40 var mu fdMutex
41 if !mu.IncrefAndClose() {
42 t.Fatal("broken")
45 if mu.Incref() {
46 t.Fatal("broken")
48 if mu.RWLock(true) {
49 t.Fatal("broken")
51 if mu.RWLock(false) {
52 t.Fatal("broken")
54 if mu.IncrefAndClose() {
55 t.Fatal("broken")
59 func TestMutexCloseUnblock(t *testing.T) {
60 c := make(chan bool)
61 var mu fdMutex
62 mu.RWLock(true)
63 for i := 0; i < 4; i++ {
64 go func() {
65 if mu.RWLock(true) {
66 t.Error("broken")
67 return
69 c <- true
70 }()
72 // Concurrent goroutines must not be able to read lock the mutex.
73 time.Sleep(time.Millisecond)
74 select {
75 case <-c:
76 t.Fatal("broken")
77 default:
79 mu.IncrefAndClose() // Must unblock the readers.
80 for i := 0; i < 4; i++ {
81 select {
82 case <-c:
83 case <-time.After(10 * time.Second):
84 t.Fatal("broken")
87 if mu.Decref() {
88 t.Fatal("broken")
90 if !mu.RWUnlock(true) {
91 t.Fatal("broken")
95 func TestMutexPanic(t *testing.T) {
96 ensurePanics := func(f func()) {
97 defer func() {
98 if recover() == nil {
99 t.Fatal("does not panic")
105 var mu fdMutex
106 ensurePanics(func() { mu.Decref() })
107 ensurePanics(func() { mu.RWUnlock(true) })
108 ensurePanics(func() { mu.RWUnlock(false) })
110 ensurePanics(func() { mu.Incref(); mu.Decref(); mu.Decref() })
111 ensurePanics(func() { mu.RWLock(true); mu.RWUnlock(true); mu.RWUnlock(true) })
112 ensurePanics(func() { mu.RWLock(false); mu.RWUnlock(false); mu.RWUnlock(false) })
114 // ensure that it's still not broken
115 mu.Incref()
116 mu.Decref()
117 mu.RWLock(true)
118 mu.RWUnlock(true)
119 mu.RWLock(false)
120 mu.RWUnlock(false)
123 func TestMutexStress(t *testing.T) {
124 P := 8
125 N := int(1e6)
126 if testing.Short() {
127 P = 4
128 N = 1e4
130 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(P))
131 done := make(chan bool)
132 var mu fdMutex
133 var readState [2]uint64
134 var writeState [2]uint64
135 for p := 0; p < P; p++ {
136 go func() {
137 r := rand.New(rand.NewSource(rand.Int63()))
138 for i := 0; i < N; i++ {
139 switch r.Intn(3) {
140 case 0:
141 if !mu.Incref() {
142 t.Error("broken")
143 return
145 if mu.Decref() {
146 t.Error("broken")
147 return
149 case 1:
150 if !mu.RWLock(true) {
151 t.Error("broken")
152 return
154 // Ensure that it provides mutual exclusion for readers.
155 if readState[0] != readState[1] {
156 t.Error("broken")
157 return
159 readState[0]++
160 readState[1]++
161 if mu.RWUnlock(true) {
162 t.Error("broken")
163 return
165 case 2:
166 if !mu.RWLock(false) {
167 t.Error("broken")
168 return
170 // Ensure that it provides mutual exclusion for writers.
171 if writeState[0] != writeState[1] {
172 t.Error("broken")
173 return
175 writeState[0]++
176 writeState[1]++
177 if mu.RWUnlock(false) {
178 t.Error("broken")
179 return
183 done <- true
186 for p := 0; p < P; p++ {
187 <-done
189 if !mu.IncrefAndClose() {
190 t.Fatal("broken")
192 if !mu.Decref() {
193 t.Fatal("broken")