blob: c34ec59b996371a6dc63ee919905f68baf3594d6 [file] [log] [blame]
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +04001// 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
5package net
6
7import (
8 "math/rand"
9 "runtime"
10 "testing"
11 "time"
12)
13
14func TestMutexLock(t *testing.T) {
15 var mu fdMutex
16
17 if !mu.Incref() {
18 t.Fatal("broken")
19 }
20 if mu.Decref() {
21 t.Fatal("broken")
22 }
23
24 if !mu.RWLock(true) {
25 t.Fatal("broken")
26 }
27 if mu.RWUnlock(true) {
28 t.Fatal("broken")
29 }
30
31 if !mu.RWLock(false) {
32 t.Fatal("broken")
33 }
34 if mu.RWUnlock(false) {
35 t.Fatal("broken")
36 }
37}
38
39func TestMutexClose(t *testing.T) {
40 var mu fdMutex
41 if !mu.IncrefAndClose() {
42 t.Fatal("broken")
43 }
44
45 if mu.Incref() {
46 t.Fatal("broken")
47 }
48 if mu.RWLock(true) {
49 t.Fatal("broken")
50 }
51 if mu.RWLock(false) {
52 t.Fatal("broken")
53 }
54 if mu.IncrefAndClose() {
55 t.Fatal("broken")
56 }
57}
58
59func 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) {
Mikio Haraf0433e42014-03-15 13:43:02 +090066 t.Error("broken")
67 return
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +040068 }
69 c <- true
70 }()
71 }
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:
78 }
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")
85 }
86 }
87 if mu.Decref() {
88 t.Fatal("broken")
89 }
90 if !mu.RWUnlock(true) {
91 t.Fatal("broken")
92 }
93}
94
95func TestMutexPanic(t *testing.T) {
96 ensurePanics := func(f func()) {
97 defer func() {
98 if recover() == nil {
99 t.Fatal("does not panic")
100 }
101 }()
102 f()
103 }
104
105 var mu fdMutex
106 ensurePanics(func() { mu.Decref() })
107 ensurePanics(func() { mu.RWUnlock(true) })
108 ensurePanics(func() { mu.RWUnlock(false) })
109
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) })
113
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)
121}
122
123func TestMutexStress(t *testing.T) {
124 P := 8
125 N := int(1e6)
126 if testing.Short() {
127 P = 4
128 N = 1e4
129 }
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() {
Mikio Haraf0433e42014-03-15 13:43:02 +0900142 t.Error("broken")
143 return
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400144 }
145 if mu.Decref() {
Mikio Haraf0433e42014-03-15 13:43:02 +0900146 t.Error("broken")
147 return
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400148 }
149 case 1:
150 if !mu.RWLock(true) {
Mikio Haraf0433e42014-03-15 13:43:02 +0900151 t.Error("broken")
152 return
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400153 }
154 // Ensure that it provides mutual exclusion for readers.
155 if readState[0] != readState[1] {
Mikio Haraf0433e42014-03-15 13:43:02 +0900156 t.Error("broken")
157 return
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400158 }
159 readState[0]++
160 readState[1]++
161 if mu.RWUnlock(true) {
Mikio Haraf0433e42014-03-15 13:43:02 +0900162 t.Error("broken")
163 return
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400164 }
165 case 2:
166 if !mu.RWLock(false) {
Mikio Haraf0433e42014-03-15 13:43:02 +0900167 t.Error("broken")
168 return
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400169 }
170 // Ensure that it provides mutual exclusion for writers.
171 if writeState[0] != writeState[1] {
Mikio Haraf0433e42014-03-15 13:43:02 +0900172 t.Error("broken")
173 return
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400174 }
175 writeState[0]++
176 writeState[1]++
177 if mu.RWUnlock(false) {
Mikio Haraf0433e42014-03-15 13:43:02 +0900178 t.Error("broken")
179 return
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +0400180 }
181 }
182 }
183 done <- true
184 }()
185 }
186 for p := 0; p < P; p++ {
187 <-done
188 }
189 if !mu.IncrefAndClose() {
190 t.Fatal("broken")
191 }
192 if !mu.Decref() {
193 t.Fatal("broken")
194 }
195}