1
0
mirror of https://github.com/golang/go synced 2024-11-18 07:24:45 -07:00
go/src/net/fd_mutex_test.go
Mikio Hara ac2f84d524 net: make unexposed methods start with lowercase letters
This change makes unexposed methods start with lowercase letters for
avoiding unnecessary confusion because the net package uses many
embedding structures and intrefaces for controlling exposure of APIs.

Note that this change leaves DNS-related methods as they are.

Change-Id: I253758d1659175c5d0af6b2efcd30ce83f46543d
Reviewed-on: https://go-review.googlesource.com/20784
Run-TryBot: Mikio Hara <mikioh.mikioh@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-17 21:43:41 +00:00

196 lines
3.4 KiB
Go

// Copyright 2013 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 net
import (
"math/rand"
"runtime"
"testing"
"time"
)
func TestMutexLock(t *testing.T) {
var mu fdMutex
if !mu.incref() {
t.Fatal("broken")
}
if mu.decref() {
t.Fatal("broken")
}
if !mu.rwlock(true) {
t.Fatal("broken")
}
if mu.rwunlock(true) {
t.Fatal("broken")
}
if !mu.rwlock(false) {
t.Fatal("broken")
}
if mu.rwunlock(false) {
t.Fatal("broken")
}
}
func TestMutexClose(t *testing.T) {
var mu fdMutex
if !mu.increfAndClose() {
t.Fatal("broken")
}
if mu.incref() {
t.Fatal("broken")
}
if mu.rwlock(true) {
t.Fatal("broken")
}
if mu.rwlock(false) {
t.Fatal("broken")
}
if mu.increfAndClose() {
t.Fatal("broken")
}
}
func TestMutexCloseUnblock(t *testing.T) {
c := make(chan bool)
var mu fdMutex
mu.rwlock(true)
for i := 0; i < 4; i++ {
go func() {
if mu.rwlock(true) {
t.Error("broken")
return
}
c <- true
}()
}
// Concurrent goroutines must not be able to read lock the mutex.
time.Sleep(time.Millisecond)
select {
case <-c:
t.Fatal("broken")
default:
}
mu.increfAndClose() // Must unblock the readers.
for i := 0; i < 4; i++ {
select {
case <-c:
case <-time.After(10 * time.Second):
t.Fatal("broken")
}
}
if mu.decref() {
t.Fatal("broken")
}
if !mu.rwunlock(true) {
t.Fatal("broken")
}
}
func TestMutexPanic(t *testing.T) {
ensurePanics := func(f func()) {
defer func() {
if recover() == nil {
t.Fatal("does not panic")
}
}()
f()
}
var mu fdMutex
ensurePanics(func() { mu.decref() })
ensurePanics(func() { mu.rwunlock(true) })
ensurePanics(func() { mu.rwunlock(false) })
ensurePanics(func() { mu.incref(); mu.decref(); mu.decref() })
ensurePanics(func() { mu.rwlock(true); mu.rwunlock(true); mu.rwunlock(true) })
ensurePanics(func() { mu.rwlock(false); mu.rwunlock(false); mu.rwunlock(false) })
// ensure that it's still not broken
mu.incref()
mu.decref()
mu.rwlock(true)
mu.rwunlock(true)
mu.rwlock(false)
mu.rwunlock(false)
}
func TestMutexStress(t *testing.T) {
P := 8
N := int(1e6)
if testing.Short() {
P = 4
N = 1e4
}
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(P))
done := make(chan bool)
var mu fdMutex
var readState [2]uint64
var writeState [2]uint64
for p := 0; p < P; p++ {
go func() {
r := rand.New(rand.NewSource(rand.Int63()))
for i := 0; i < N; i++ {
switch r.Intn(3) {
case 0:
if !mu.incref() {
t.Error("broken")
return
}
if mu.decref() {
t.Error("broken")
return
}
case 1:
if !mu.rwlock(true) {
t.Error("broken")
return
}
// Ensure that it provides mutual exclusion for readers.
if readState[0] != readState[1] {
t.Error("broken")
return
}
readState[0]++
readState[1]++
if mu.rwunlock(true) {
t.Error("broken")
return
}
case 2:
if !mu.rwlock(false) {
t.Error("broken")
return
}
// Ensure that it provides mutual exclusion for writers.
if writeState[0] != writeState[1] {
t.Error("broken")
return
}
writeState[0]++
writeState[1]++
if mu.rwunlock(false) {
t.Error("broken")
return
}
}
}
done <- true
}()
}
for p := 0; p < P; p++ {
<-done
}
if !mu.increfAndClose() {
t.Fatal("broken")
}
if !mu.decref() {
t.Fatal("broken")
}
}