mirror of
https://github.com/gofiber/fiber.git
synced 2025-07-27 12:40:11 +00:00
panic: runtime error: index out of range [1] with length 1 goroutine 67 [running]: github.com/gofiber/fiber/v3/middleware/idempotency_test.Benchmark_MemoryLock(0xc00012c2c8) /home/runner/work/fiber/fiber/middleware/idempotency/locker_test.go:74 +0x23d testing.(*B).runN(0xc00012c2c8, 0x1) /opt/hostedtoolcache/go/1.24.4/x64/src/testing/benchmark.go:219 +0x190 testing.(*B).run1.func1() /opt/hostedtoolcache/go/1.24.4/x64/src/testing/benchmark.go:245 +0x48 created by testing.(*B).run1 in goroutine 1 /opt/hostedtoolcache/go/1.24.4/x64/src/testing/benchmark.go:238 +0x90 exit status 2
130 lines
2.3 KiB
Go
130 lines
2.3 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, 50_000_000)
|
|
for i := range keys {
|
|
keys[i] = strconv.Itoa(i)
|
|
}
|
|
|
|
lock := idempotency.NewMemoryLock()
|
|
|
|
for i := 0; b.Loop(); 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.ReportAllocs()
|
|
b.ResetTimer()
|
|
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.ReportAllocs()
|
|
b.ResetTimer()
|
|
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)
|
|
}
|
|
}
|
|
})
|
|
})
|
|
}
|