91 lines
1.3 KiB
Go
91 lines
1.3 KiB
Go
|
package locker
|
||
|
|
||
|
import (
|
||
|
"runtime"
|
||
|
"testing"
|
||
|
)
|
||
|
|
||
|
func TestLockCounter(t *testing.T) {
|
||
|
l := &lockCtr{}
|
||
|
l.inc()
|
||
|
|
||
|
if l.waiters != 1 {
|
||
|
t.Fatal("counter inc failed")
|
||
|
}
|
||
|
|
||
|
l.dec()
|
||
|
if l.waiters != 0 {
|
||
|
t.Fatal("counter dec failed")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestLockerLock(t *testing.T) {
|
||
|
l := New()
|
||
|
l.Lock("test")
|
||
|
ctr := l.locks["test"]
|
||
|
|
||
|
if ctr.count() != 0 {
|
||
|
t.Fatalf("expected waiters to be 0, got :%d", ctr.waiters)
|
||
|
}
|
||
|
|
||
|
chDone := make(chan struct{})
|
||
|
go func() {
|
||
|
l.Lock("test")
|
||
|
close(chDone)
|
||
|
}()
|
||
|
|
||
|
runtime.Gosched()
|
||
|
|
||
|
select {
|
||
|
case <-chDone:
|
||
|
t.Fatal("lock should not have returned while it was still held")
|
||
|
default:
|
||
|
}
|
||
|
|
||
|
if ctr.count() != 1 {
|
||
|
t.Fatalf("expected waiters to be 1, got: %d", ctr.count())
|
||
|
}
|
||
|
|
||
|
if err := l.Unlock("test"); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
runtime.Gosched()
|
||
|
|
||
|
select {
|
||
|
case <-chDone:
|
||
|
default:
|
||
|
// one more time just to be sure
|
||
|
runtime.Gosched()
|
||
|
select {
|
||
|
case <-chDone:
|
||
|
default:
|
||
|
t.Fatalf("lock should have completed")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ctr.count() != 0 {
|
||
|
t.Fatalf("expected waiters to be 0, got: %d", ctr.count())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestLockerUnlock(t *testing.T) {
|
||
|
l := New()
|
||
|
|
||
|
l.Lock("test")
|
||
|
l.Unlock("test")
|
||
|
|
||
|
chDone := make(chan struct{})
|
||
|
go func() {
|
||
|
l.Lock("test")
|
||
|
close(chDone)
|
||
|
}()
|
||
|
|
||
|
runtime.Gosched()
|
||
|
|
||
|
select {
|
||
|
case <-chDone:
|
||
|
default:
|
||
|
t.Fatalf("lock should not be blocked")
|
||
|
}
|
||
|
}
|