github.com/goproxy0/go@v0.0.0-20171111080102-49cc0c489d2c/src/internal/poll/fd_mutex_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 package poll_test 6 7 import ( 8 . "internal/poll" 9 "math/rand" 10 "runtime" 11 "testing" 12 "time" 13 ) 14 15 func TestMutexLock(t *testing.T) { 16 var mu FDMutex 17 18 if !mu.Incref() { 19 t.Fatal("broken") 20 } 21 if mu.Decref() { 22 t.Fatal("broken") 23 } 24 25 if !mu.RWLock(true) { 26 t.Fatal("broken") 27 } 28 if mu.RWUnlock(true) { 29 t.Fatal("broken") 30 } 31 32 if !mu.RWLock(false) { 33 t.Fatal("broken") 34 } 35 if mu.RWUnlock(false) { 36 t.Fatal("broken") 37 } 38 } 39 40 func TestMutexClose(t *testing.T) { 41 var mu FDMutex 42 if !mu.IncrefAndClose() { 43 t.Fatal("broken") 44 } 45 46 if mu.Incref() { 47 t.Fatal("broken") 48 } 49 if mu.RWLock(true) { 50 t.Fatal("broken") 51 } 52 if mu.RWLock(false) { 53 t.Fatal("broken") 54 } 55 if mu.IncrefAndClose() { 56 t.Fatal("broken") 57 } 58 } 59 60 func TestMutexCloseUnblock(t *testing.T) { 61 c := make(chan bool) 62 var mu FDMutex 63 mu.RWLock(true) 64 for i := 0; i < 4; i++ { 65 go func() { 66 if mu.RWLock(true) { 67 t.Error("broken") 68 return 69 } 70 c <- true 71 }() 72 } 73 // Concurrent goroutines must not be able to read lock the mutex. 74 time.Sleep(time.Millisecond) 75 select { 76 case <-c: 77 t.Fatal("broken") 78 default: 79 } 80 mu.IncrefAndClose() // Must unblock the readers. 81 for i := 0; i < 4; i++ { 82 select { 83 case <-c: 84 case <-time.After(10 * time.Second): 85 t.Fatal("broken") 86 } 87 } 88 if mu.Decref() { 89 t.Fatal("broken") 90 } 91 if !mu.RWUnlock(true) { 92 t.Fatal("broken") 93 } 94 } 95 96 func TestMutexPanic(t *testing.T) { 97 ensurePanics := func(f func()) { 98 defer func() { 99 if recover() == nil { 100 t.Fatal("does not panic") 101 } 102 }() 103 f() 104 } 105 106 var mu FDMutex 107 ensurePanics(func() { mu.Decref() }) 108 ensurePanics(func() { mu.RWUnlock(true) }) 109 ensurePanics(func() { mu.RWUnlock(false) }) 110 111 ensurePanics(func() { mu.Incref(); mu.Decref(); mu.Decref() }) 112 ensurePanics(func() { mu.RWLock(true); mu.RWUnlock(true); mu.RWUnlock(true) }) 113 ensurePanics(func() { mu.RWLock(false); mu.RWUnlock(false); mu.RWUnlock(false) }) 114 115 // ensure that it's still not broken 116 mu.Incref() 117 mu.Decref() 118 mu.RWLock(true) 119 mu.RWUnlock(true) 120 mu.RWLock(false) 121 mu.RWUnlock(false) 122 } 123 124 func TestMutexStress(t *testing.T) { 125 P := 8 126 N := int(1e6) 127 if testing.Short() { 128 P = 4 129 N = 1e4 130 } 131 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(P)) 132 done := make(chan bool) 133 var mu FDMutex 134 var readState [2]uint64 135 var writeState [2]uint64 136 for p := 0; p < P; p++ { 137 go func() { 138 r := rand.New(rand.NewSource(rand.Int63())) 139 for i := 0; i < N; i++ { 140 switch r.Intn(3) { 141 case 0: 142 if !mu.Incref() { 143 t.Error("broken") 144 return 145 } 146 if mu.Decref() { 147 t.Error("broken") 148 return 149 } 150 case 1: 151 if !mu.RWLock(true) { 152 t.Error("broken") 153 return 154 } 155 // Ensure that it provides mutual exclusion for readers. 156 if readState[0] != readState[1] { 157 t.Error("broken") 158 return 159 } 160 readState[0]++ 161 readState[1]++ 162 if mu.RWUnlock(true) { 163 t.Error("broken") 164 return 165 } 166 case 2: 167 if !mu.RWLock(false) { 168 t.Error("broken") 169 return 170 } 171 // Ensure that it provides mutual exclusion for writers. 172 if writeState[0] != writeState[1] { 173 t.Error("broken") 174 return 175 } 176 writeState[0]++ 177 writeState[1]++ 178 if mu.RWUnlock(false) { 179 t.Error("broken") 180 return 181 } 182 } 183 } 184 done <- true 185 }() 186 } 187 for p := 0; p < P; p++ { 188 <-done 189 } 190 if !mu.IncrefAndClose() { 191 t.Fatal("broken") 192 } 193 if !mu.Decref() { 194 t.Fatal("broken") 195 } 196 }