lib/sync: Add option for sasha-s/go-deadlock
This commit is contained in:
127
vendor/github.com/sasha-s/go-deadlock/deadlock_test.go
generated
vendored
Normal file
127
vendor/github.com/sasha-s/go-deadlock/deadlock_test.go
generated
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
package deadlock
|
||||
|
||||
import (
|
||||
"log"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestNoDeadlocks(t *testing.T) {
|
||||
defer restore()()
|
||||
Opts.DeadlockTimeout = time.Millisecond * 5000
|
||||
var a RWMutex
|
||||
var b Mutex
|
||||
var c RWMutex
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < 10; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for k := 0; k < 5; k++ {
|
||||
func() {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
func() {
|
||||
b.Lock()
|
||||
defer b.Unlock()
|
||||
func() {
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
time.Sleep(time.Duration((1000 + rand.Intn(1000))) * time.Millisecond / 200)
|
||||
}()
|
||||
}()
|
||||
}()
|
||||
}
|
||||
}()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for k := 0; k < 5; k++ {
|
||||
func() {
|
||||
a.RLock()
|
||||
defer a.RUnlock()
|
||||
func() {
|
||||
b.Lock()
|
||||
defer b.Unlock()
|
||||
func() {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
time.Sleep(time.Duration((1000 + rand.Intn(1000))) * time.Millisecond / 200)
|
||||
}()
|
||||
}()
|
||||
}()
|
||||
}
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func TestLockOrder(t *testing.T) {
|
||||
defer restore()()
|
||||
Opts.DeadlockTimeout = 0
|
||||
var deadlocks uint32
|
||||
Opts.OnPotentialDeadlock = func() {
|
||||
atomic.AddUint32(&deadlocks, 1)
|
||||
}
|
||||
var a RWMutex
|
||||
var b Mutex
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
a.Lock()
|
||||
b.Lock()
|
||||
b.Unlock()
|
||||
a.Unlock()
|
||||
}()
|
||||
wg.Wait()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
b.Lock()
|
||||
a.RLock()
|
||||
a.RUnlock()
|
||||
b.Unlock()
|
||||
}()
|
||||
wg.Wait()
|
||||
if deadlocks != 1 {
|
||||
t.Fatalf("expected 1 deadlock, detected %d", deadlocks)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHardDeadlock(t *testing.T) {
|
||||
defer restore()()
|
||||
Opts.DisableLockOrderDetection = true
|
||||
Opts.DeadlockTimeout = time.Millisecond * 20
|
||||
var deadlocks uint32
|
||||
Opts.OnPotentialDeadlock = func() {
|
||||
atomic.AddUint32(&deadlocks, 1)
|
||||
}
|
||||
var mu Mutex
|
||||
mu.Lock()
|
||||
ch := make(chan struct{})
|
||||
go func() {
|
||||
defer close(ch)
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
}()
|
||||
select {
|
||||
case <-ch:
|
||||
case <-time.After(time.Millisecond * 100):
|
||||
}
|
||||
if deadlocks != 1 {
|
||||
t.Fatalf("expected 1 deadlock, detected %d", deadlocks)
|
||||
}
|
||||
log.Println("****************")
|
||||
mu.Unlock()
|
||||
}
|
||||
|
||||
func restore() func() {
|
||||
opts := Opts
|
||||
return func() {
|
||||
Opts = opts
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user