Retro68/gcc/libgo/go/internal/poll/fd_mutex_test.go

223 lines
3.9 KiB
Go
Raw Normal View History

2014-09-21 17:33:12 +00:00
// 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.
2018-12-28 15:30:48 +00:00
package poll_test
2014-09-21 17:33:12 +00:00
import (
2018-12-28 15:30:48 +00:00
. "internal/poll"
2014-09-21 17:33:12 +00:00
"math/rand"
"runtime"
2019-06-02 15:48:37 +00:00
"strings"
2014-09-21 17:33:12 +00:00
"testing"
"time"
)
func TestMutexLock(t *testing.T) {
2018-12-28 15:30:48 +00:00
var mu FDMutex
2014-09-21 17:33:12 +00:00
2018-12-28 15:30:48 +00:00
if !mu.Incref() {
2014-09-21 17:33:12 +00:00
t.Fatal("broken")
}
2018-12-28 15:30:48 +00:00
if mu.Decref() {
2014-09-21 17:33:12 +00:00
t.Fatal("broken")
}
2018-12-28 15:30:48 +00:00
if !mu.RWLock(true) {
2014-09-21 17:33:12 +00:00
t.Fatal("broken")
}
2018-12-28 15:30:48 +00:00
if mu.RWUnlock(true) {
2014-09-21 17:33:12 +00:00
t.Fatal("broken")
}
2018-12-28 15:30:48 +00:00
if !mu.RWLock(false) {
2014-09-21 17:33:12 +00:00
t.Fatal("broken")
}
2018-12-28 15:30:48 +00:00
if mu.RWUnlock(false) {
2014-09-21 17:33:12 +00:00
t.Fatal("broken")
}
}
func TestMutexClose(t *testing.T) {
2018-12-28 15:30:48 +00:00
var mu FDMutex
if !mu.IncrefAndClose() {
2014-09-21 17:33:12 +00:00
t.Fatal("broken")
}
2018-12-28 15:30:48 +00:00
if mu.Incref() {
2014-09-21 17:33:12 +00:00
t.Fatal("broken")
}
2018-12-28 15:30:48 +00:00
if mu.RWLock(true) {
2014-09-21 17:33:12 +00:00
t.Fatal("broken")
}
2018-12-28 15:30:48 +00:00
if mu.RWLock(false) {
2014-09-21 17:33:12 +00:00
t.Fatal("broken")
}
2018-12-28 15:30:48 +00:00
if mu.IncrefAndClose() {
2014-09-21 17:33:12 +00:00
t.Fatal("broken")
}
}
func TestMutexCloseUnblock(t *testing.T) {
c := make(chan bool, 4)
2018-12-28 15:30:48 +00:00
var mu FDMutex
mu.RWLock(true)
2014-09-21 17:33:12 +00:00
for i := 0; i < 4; i++ {
go func() {
2018-12-28 15:30:48 +00:00
if mu.RWLock(true) {
2015-08-28 15:33:40 +00:00
t.Error("broken")
return
2014-09-21 17:33:12 +00:00
}
c <- true
}()
}
// Concurrent goroutines must not be able to read lock the mutex.
time.Sleep(time.Millisecond)
select {
case <-c:
t.Fatal("broken")
default:
}
2018-12-28 15:30:48 +00:00
mu.IncrefAndClose() // Must unblock the readers.
2014-09-21 17:33:12 +00:00
for i := 0; i < 4; i++ {
select {
case <-c:
case <-time.After(10 * time.Second):
t.Fatal("broken")
}
}
2018-12-28 15:30:48 +00:00
if mu.Decref() {
2014-09-21 17:33:12 +00:00
t.Fatal("broken")
}
2018-12-28 15:30:48 +00:00
if !mu.RWUnlock(true) {
2014-09-21 17:33:12 +00:00
t.Fatal("broken")
}
}
func TestMutexPanic(t *testing.T) {
ensurePanics := func(f func()) {
defer func() {
if recover() == nil {
t.Fatal("does not panic")
}
}()
f()
}
2018-12-28 15:30:48 +00:00
var mu FDMutex
ensurePanics(func() { mu.Decref() })
ensurePanics(func() { mu.RWUnlock(true) })
ensurePanics(func() { mu.RWUnlock(false) })
2014-09-21 17:33:12 +00:00
2018-12-28 15:30:48 +00:00
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) })
2014-09-21 17:33:12 +00:00
// ensure that it's still not broken
2018-12-28 15:30:48 +00:00
mu.Incref()
mu.Decref()
mu.RWLock(true)
mu.RWUnlock(true)
mu.RWLock(false)
mu.RWUnlock(false)
2014-09-21 17:33:12 +00:00
}
2019-06-02 15:48:37 +00:00
func TestMutexOverflowPanic(t *testing.T) {
defer func() {
r := recover()
if r == nil {
t.Fatal("did not panic")
}
msg, ok := r.(string)
if !ok {
t.Fatalf("unexpected panic type %T", r)
}
if !strings.Contains(msg, "too many") || strings.Contains(msg, "inconsistent") {
t.Fatalf("wrong panic message %q", msg)
}
}()
var mu1 FDMutex
for i := 0; i < 1<<21; i++ {
mu1.Incref()
}
}
2014-09-21 17:33:12 +00:00
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, P)
2018-12-28 15:30:48 +00:00
var mu FDMutex
2014-09-21 17:33:12 +00:00
var readState [2]uint64
var writeState [2]uint64
for p := 0; p < P; p++ {
go func() {
defer func() {
done <- !t.Failed()
}()
2014-09-21 17:33:12 +00:00
r := rand.New(rand.NewSource(rand.Int63()))
for i := 0; i < N; i++ {
switch r.Intn(3) {
case 0:
2018-12-28 15:30:48 +00:00
if !mu.Incref() {
2015-08-28 15:33:40 +00:00
t.Error("broken")
return
2014-09-21 17:33:12 +00:00
}
2018-12-28 15:30:48 +00:00
if mu.Decref() {
2015-08-28 15:33:40 +00:00
t.Error("broken")
return
2014-09-21 17:33:12 +00:00
}
case 1:
2018-12-28 15:30:48 +00:00
if !mu.RWLock(true) {
2015-08-28 15:33:40 +00:00
t.Error("broken")
return
2014-09-21 17:33:12 +00:00
}
// Ensure that it provides mutual exclusion for readers.
if readState[0] != readState[1] {
2015-08-28 15:33:40 +00:00
t.Error("broken")
return
2014-09-21 17:33:12 +00:00
}
readState[0]++
readState[1]++
2018-12-28 15:30:48 +00:00
if mu.RWUnlock(true) {
2015-08-28 15:33:40 +00:00
t.Error("broken")
return
2014-09-21 17:33:12 +00:00
}
case 2:
2018-12-28 15:30:48 +00:00
if !mu.RWLock(false) {
2015-08-28 15:33:40 +00:00
t.Error("broken")
return
2014-09-21 17:33:12 +00:00
}
// Ensure that it provides mutual exclusion for writers.
if writeState[0] != writeState[1] {
2015-08-28 15:33:40 +00:00
t.Error("broken")
return
2014-09-21 17:33:12 +00:00
}
writeState[0]++
writeState[1]++
2018-12-28 15:30:48 +00:00
if mu.RWUnlock(false) {
2015-08-28 15:33:40 +00:00
t.Error("broken")
return
2014-09-21 17:33:12 +00:00
}
}
}
}()
}
for p := 0; p < P; p++ {
if !<-done {
t.FailNow()
}
2014-09-21 17:33:12 +00:00
}
2018-12-28 15:30:48 +00:00
if !mu.IncrefAndClose() {
2014-09-21 17:33:12 +00:00
t.Fatal("broken")
}
2018-12-28 15:30:48 +00:00
if !mu.Decref() {
2014-09-21 17:33:12 +00:00
t.Fatal("broken")
}
}