mirror of https://github.com/gofiber/fiber.git
128 lines
2.2 KiB
Go
128 lines
2.2 KiB
Go
package idempotency_test
|
|
|
|
import (
|
|
"strconv"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/gofiber/fiber/v3/middleware/idempotency"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// go test -run Test_MemoryLock
|
|
func Test_MemoryLock(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
l := idempotency.NewMemoryLock()
|
|
|
|
{
|
|
err := l.Lock("a")
|
|
require.NoError(t, err)
|
|
}
|
|
{
|
|
done := make(chan struct{})
|
|
go func() {
|
|
defer close(done)
|
|
|
|
err := l.Lock("a")
|
|
assert.NoError(t, err)
|
|
}()
|
|
|
|
select {
|
|
case <-done:
|
|
t.Fatal("lock acquired again")
|
|
case <-time.After(time.Second):
|
|
}
|
|
}
|
|
|
|
{
|
|
err := l.Lock("b")
|
|
require.NoError(t, err)
|
|
}
|
|
{
|
|
err := l.Unlock("b")
|
|
require.NoError(t, err)
|
|
}
|
|
{
|
|
err := l.Lock("b")
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
{
|
|
err := l.Unlock("c")
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
{
|
|
err := l.Lock("d")
|
|
require.NoError(t, err)
|
|
}
|
|
}
|
|
|
|
func Benchmark_MemoryLock(b *testing.B) {
|
|
keys := make([]string, b.N)
|
|
for i := range keys {
|
|
keys[i] = strconv.Itoa(i)
|
|
}
|
|
|
|
lock := idempotency.NewMemoryLock()
|
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
key := keys[i]
|
|
if err := lock.Lock(key); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
if err := lock.Unlock(key); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func Benchmark_MemoryLock_Parallel(b *testing.B) {
|
|
// In order to prevent using repeated keys I pre-allocate keys
|
|
keys := make([]string, 1_000_000)
|
|
for i := range keys {
|
|
keys[i] = strconv.Itoa(i)
|
|
}
|
|
|
|
b.Run("UniqueKeys", func(b *testing.B) {
|
|
lock := idempotency.NewMemoryLock()
|
|
var keyI atomic.Int32
|
|
b.RunParallel(func(p *testing.PB) {
|
|
for p.Next() {
|
|
i := int(keyI.Add(1)) % len(keys)
|
|
key := keys[i]
|
|
if err := lock.Lock(key); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
if err := lock.Unlock(key); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("RepeatedKeys", func(b *testing.B) {
|
|
lock := idempotency.NewMemoryLock()
|
|
var keyI atomic.Int32
|
|
b.RunParallel(func(p *testing.PB) {
|
|
for p.Next() {
|
|
// Division by 3 ensures that index will be repreated exactly 3 times
|
|
i := int(keyI.Add(1)) / 3 % len(keys)
|
|
key := keys[i]
|
|
if err := lock.Lock(key); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
if err := lock.Unlock(key); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
})
|
|
})
|
|
}
|