2024-05-20 12:38:02 +00:00
|
|
|
package chain
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
2024-05-21 13:05:04 +00:00
|
|
|
func setupTest() (*InMemRequestsMapStorage, RequestLimiter) {
|
|
|
|
storage := NewInMemRequestsMapStorage()
|
2024-05-20 12:38:02 +00:00
|
|
|
rl := NewRequestLimiter(storage)
|
|
|
|
return storage, rl
|
|
|
|
}
|
|
|
|
|
2024-05-21 13:57:34 +00:00
|
|
|
func TestSetLimit(t *testing.T) {
|
2024-05-20 12:38:02 +00:00
|
|
|
storage, rl := setupTest()
|
|
|
|
|
|
|
|
// Define test inputs
|
|
|
|
tag := "testTag"
|
|
|
|
maxRequests := 10
|
|
|
|
interval := time.Second
|
|
|
|
|
2024-05-21 13:57:34 +00:00
|
|
|
// Call the SetLimit method
|
|
|
|
err := rl.SetLimit(tag, maxRequests, interval)
|
2024-05-20 12:38:02 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Verify that the data was saved to storage correctly
|
|
|
|
data, err := storage.Get(tag)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, tag, data.Tag)
|
|
|
|
require.Equal(t, interval, data.Period)
|
|
|
|
require.Equal(t, maxRequests, data.MaxReqs)
|
|
|
|
require.Equal(t, 0, data.NumReqs)
|
|
|
|
}
|
|
|
|
|
2024-05-21 13:57:34 +00:00
|
|
|
func TestGetLimit(t *testing.T) {
|
2024-05-20 12:38:02 +00:00
|
|
|
storage, rl := setupTest()
|
|
|
|
|
2024-05-21 13:57:34 +00:00
|
|
|
// Define test inputs
|
2024-05-22 07:23:44 +00:00
|
|
|
data := &LimitData{
|
2024-05-20 12:38:02 +00:00
|
|
|
Tag: "testTag",
|
|
|
|
Period: time.Second,
|
|
|
|
MaxReqs: 10,
|
|
|
|
NumReqs: 1,
|
|
|
|
}
|
2024-05-22 10:16:06 +00:00
|
|
|
err := storage.Set(data)
|
|
|
|
require.NoError(t, err)
|
2024-05-20 12:38:02 +00:00
|
|
|
|
2024-05-21 13:57:34 +00:00
|
|
|
// Call the GetLimit method
|
|
|
|
ret, err := rl.GetLimit(data.Tag)
|
2024-05-20 12:38:02 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Verify the returned data
|
|
|
|
require.Equal(t, data, ret)
|
|
|
|
}
|
|
|
|
|
2024-06-19 05:20:32 +00:00
|
|
|
func TestDeleteLimit(t *testing.T) {
|
|
|
|
storage, rl := setupTest()
|
|
|
|
|
|
|
|
// Define test inputs
|
|
|
|
tag := "testTag"
|
|
|
|
data := &LimitData{
|
|
|
|
Tag: tag,
|
|
|
|
Period: time.Second,
|
|
|
|
MaxReqs: 10,
|
|
|
|
NumReqs: 1,
|
|
|
|
}
|
|
|
|
err := storage.Set(data)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Call the DeleteLimit method
|
|
|
|
err = rl.DeleteLimit(tag)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Verify that the data was deleted from storage
|
|
|
|
limit, _ := storage.Get(tag)
|
|
|
|
require.Nil(t, limit)
|
|
|
|
|
|
|
|
// Test double delete
|
|
|
|
err = rl.DeleteLimit(tag)
|
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
2024-05-21 13:57:34 +00:00
|
|
|
func TestAllowWithinPeriod(t *testing.T) {
|
2024-05-20 12:38:02 +00:00
|
|
|
storage, rl := setupTest()
|
|
|
|
|
|
|
|
// Define test inputs
|
|
|
|
tag := "testTag"
|
|
|
|
maxRequests := 10
|
|
|
|
interval := time.Second
|
|
|
|
|
|
|
|
// Set up the storage with test data
|
2024-05-22 07:23:44 +00:00
|
|
|
data := &LimitData{
|
2024-05-20 12:38:02 +00:00
|
|
|
Tag: tag,
|
|
|
|
Period: interval,
|
|
|
|
CreatedAt: time.Now(),
|
|
|
|
MaxReqs: maxRequests,
|
|
|
|
}
|
2024-05-22 10:16:06 +00:00
|
|
|
err := storage.Set(data)
|
|
|
|
require.NoError(t, err)
|
2024-05-20 12:38:02 +00:00
|
|
|
|
2024-05-21 13:57:34 +00:00
|
|
|
// Call the Allow method
|
2024-05-20 12:38:02 +00:00
|
|
|
for i := 0; i < maxRequests; i++ {
|
2024-05-21 13:57:34 +00:00
|
|
|
allow, err := rl.Allow(tag)
|
2024-05-20 12:38:02 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Verify the result
|
2024-05-21 13:57:34 +00:00
|
|
|
require.True(t, allow)
|
2024-05-20 12:38:02 +00:00
|
|
|
}
|
|
|
|
|
2024-05-21 13:57:34 +00:00
|
|
|
// Call the Allow method again
|
|
|
|
allow, err := rl.Allow(tag)
|
2024-06-19 05:20:32 +00:00
|
|
|
require.ErrorIs(t, err, ErrRequestsOverLimit)
|
2024-05-21 13:57:34 +00:00
|
|
|
require.False(t, allow)
|
2024-05-20 12:38:02 +00:00
|
|
|
}
|
|
|
|
|
2024-05-21 13:57:34 +00:00
|
|
|
func TestAllowWhenPeriodPassed(t *testing.T) {
|
2024-05-20 12:38:02 +00:00
|
|
|
storage, rl := setupTest()
|
|
|
|
|
|
|
|
// Define test inputs
|
|
|
|
tag := "testTag"
|
|
|
|
maxRequests := 10
|
|
|
|
interval := time.Second
|
|
|
|
|
|
|
|
// Set up the storage with test data
|
2024-05-22 07:23:44 +00:00
|
|
|
data := &LimitData{
|
2024-05-20 12:38:02 +00:00
|
|
|
Tag: tag,
|
|
|
|
Period: interval,
|
|
|
|
CreatedAt: time.Now().Add(-interval),
|
|
|
|
MaxReqs: maxRequests,
|
|
|
|
NumReqs: maxRequests,
|
|
|
|
}
|
2024-05-22 10:16:06 +00:00
|
|
|
err := storage.Set(data)
|
|
|
|
require.NoError(t, err)
|
2024-05-20 12:38:02 +00:00
|
|
|
|
2024-05-21 13:57:34 +00:00
|
|
|
// Call the Allow method
|
|
|
|
allow, err := rl.Allow(tag)
|
2024-05-20 12:38:02 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Verify the result
|
2024-05-21 13:57:34 +00:00
|
|
|
require.True(t, allow)
|
2024-05-20 12:38:02 +00:00
|
|
|
}
|
2024-05-23 07:16:42 +00:00
|
|
|
|
|
|
|
func TestAllowRestrictInfinitelyWhenLimitReached(t *testing.T) {
|
|
|
|
storage, rl := setupTest()
|
|
|
|
|
|
|
|
// Define test inputs
|
|
|
|
tag := "testTag"
|
|
|
|
maxRequests := 10
|
|
|
|
|
|
|
|
// Set up the storage with test data
|
|
|
|
data := &LimitData{
|
|
|
|
Tag: tag,
|
|
|
|
Period: LimitInfinitely,
|
|
|
|
CreatedAt: time.Now(),
|
|
|
|
MaxReqs: maxRequests,
|
|
|
|
NumReqs: maxRequests,
|
|
|
|
}
|
|
|
|
err := storage.Set(data)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Call the Allow method
|
|
|
|
allow, err := rl.Allow(tag)
|
2024-06-19 05:20:32 +00:00
|
|
|
require.ErrorIs(t, err, ErrRequestsOverLimit)
|
2024-05-23 07:16:42 +00:00
|
|
|
|
|
|
|
// Verify the result
|
|
|
|
require.False(t, allow)
|
|
|
|
}
|
2024-05-23 10:01:55 +00:00
|
|
|
|
|
|
|
func TestAllowWhenLimitNotReachedForInfinitePeriod(t *testing.T) {
|
|
|
|
storage, rl := setupTest()
|
|
|
|
|
|
|
|
// Define test inputs
|
|
|
|
tag := "testTag"
|
|
|
|
maxRequests := 10
|
|
|
|
|
|
|
|
// Set up the storage with test data
|
|
|
|
data := &LimitData{
|
|
|
|
Tag: tag,
|
|
|
|
Period: LimitInfinitely,
|
|
|
|
CreatedAt: time.Now(),
|
|
|
|
MaxReqs: maxRequests,
|
|
|
|
NumReqs: maxRequests - 1,
|
|
|
|
}
|
|
|
|
err := storage.Set(data)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Call the Allow method
|
|
|
|
allow, err := rl.Allow(tag)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Verify the result
|
|
|
|
require.True(t, allow)
|
|
|
|
}
|