wings/system/locker_test.go

149 lines
3.4 KiB
Go
Raw Normal View History

package system
import (
"context"
"testing"
"time"
"emperror.dev/errors"
. "github.com/franela/goblin"
)
func TestPower(t *testing.T) {
g := Goblin(t)
g.Describe("Locker", func() {
var l *Locker
g.BeforeEach(func() {
l = NewLocker()
})
g.Describe("PowerLocker#IsLocked", func() {
g.It("should return false when the channel is empty", func() {
g.Assert(cap(l.ch)).Equal(1)
g.Assert(l.IsLocked()).IsFalse()
})
g.It("should return true when the channel is at capacity", func() {
l.ch <- true
g.Assert(l.IsLocked()).IsTrue()
<-l.ch
g.Assert(l.IsLocked()).IsFalse()
// We don't care what the channel value is, just that there is
// something in it.
l.ch <- false
g.Assert(l.IsLocked()).IsTrue()
g.Assert(cap(l.ch)).Equal(1)
})
})
g.Describe("PowerLocker#Acquire", func() {
g.It("should acquire a lock when channel is empty", func() {
err := l.Acquire()
g.Assert(err).IsNil()
g.Assert(cap(l.ch)).Equal(1)
g.Assert(len(l.ch)).Equal(1)
})
g.It("should return an error when the channel is full", func() {
l.ch <- true
err := l.Acquire()
g.Assert(err).IsNotNil()
g.Assert(errors.Is(err, ErrLockerLocked)).IsTrue()
g.Assert(cap(l.ch)).Equal(1)
g.Assert(len(l.ch)).Equal(1)
})
})
g.Describe("PowerLocker#TryAcquire", func() {
g.It("should acquire a lock when channel is empty", func() {
g.Timeout(time.Second)
err := l.TryAcquire(context.Background())
g.Assert(err).IsNil()
g.Assert(cap(l.ch)).Equal(1)
g.Assert(len(l.ch)).Equal(1)
g.Assert(l.IsLocked()).IsTrue()
})
g.It("should block until context is canceled if channel is full", func() {
g.Timeout(time.Second)
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*500)
defer cancel()
l.ch <- true
err := l.TryAcquire(ctx)
g.Assert(err).IsNotNil()
g.Assert(errors.Is(err, context.DeadlineExceeded)).IsTrue()
g.Assert(cap(l.ch)).Equal(1)
g.Assert(len(l.ch)).Equal(1)
g.Assert(l.IsLocked()).IsTrue()
})
g.It("should block until lock can be acquired", func() {
g.Timeout(time.Second)
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*200)
defer cancel()
l.Acquire()
go func() {
time.AfterFunc(time.Millisecond * 50, func() {
l.Release()
})
}()
err := l.TryAcquire(ctx)
g.Assert(err).IsNil()
g.Assert(cap(l.ch)).Equal(1)
g.Assert(len(l.ch)).Equal(1)
g.Assert(l.IsLocked()).IsTrue()
})
})
g.Describe("PowerLocker#Release", func() {
g.It("should release when channel is full", func() {
l.Acquire()
g.Assert(l.IsLocked()).IsTrue()
l.Release()
g.Assert(cap(l.ch)).Equal(1)
g.Assert(len(l.ch)).Equal(0)
g.Assert(l.IsLocked()).IsFalse()
})
g.It("should release when channel is empty", func() {
g.Assert(l.IsLocked()).IsFalse()
l.Release()
g.Assert(cap(l.ch)).Equal(1)
g.Assert(len(l.ch)).Equal(0)
g.Assert(l.IsLocked()).IsFalse()
})
})
g.Describe("PowerLocker#Destroy", func() {
g.It("should unlock and close the channel", func() {
l.Acquire()
g.Assert(l.IsLocked()).IsTrue()
l.Destroy()
g.Assert(l.IsLocked()).IsFalse()
defer func() {
r := recover()
g.Assert(r).IsNotNil()
g.Assert(r.(error).Error()).Equal("send on closed channel")
}()
l.Acquire()
})
})
})
}