test: 增加 repository 测试
This commit is contained in:
105
backend/internal/repository/redeem_cache_integration_test.go
Normal file
105
backend/internal/repository/redeem_cache_integration_test.go
Normal file
@@ -0,0 +1,105 @@
|
||||
//go:build integration
|
||||
|
||||
package repository
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type RedeemCacheSuite struct {
|
||||
IntegrationRedisSuite
|
||||
cache *redeemCache
|
||||
}
|
||||
|
||||
func (s *RedeemCacheSuite) SetupTest() {
|
||||
s.IntegrationRedisSuite.SetupTest()
|
||||
s.cache = NewRedeemCache(s.rdb).(*redeemCache)
|
||||
}
|
||||
|
||||
func (s *RedeemCacheSuite) TestGetRedeemAttemptCount_Missing() {
|
||||
missingUserID := int64(99999)
|
||||
_, err := s.cache.GetRedeemAttemptCount(s.ctx, missingUserID)
|
||||
require.Error(s.T(), err, "expected redis.Nil for missing rate-limit key")
|
||||
require.True(s.T(), errors.Is(err, redis.Nil))
|
||||
}
|
||||
|
||||
func (s *RedeemCacheSuite) TestIncrementAndGetRedeemAttemptCount() {
|
||||
userID := int64(1)
|
||||
key := fmt.Sprintf("%s%d", redeemRateLimitKeyPrefix, userID)
|
||||
|
||||
require.NoError(s.T(), s.cache.IncrementRedeemAttemptCount(s.ctx, userID), "IncrementRedeemAttemptCount")
|
||||
count, err := s.cache.GetRedeemAttemptCount(s.ctx, userID)
|
||||
require.NoError(s.T(), err, "GetRedeemAttemptCount")
|
||||
require.Equal(s.T(), 1, count, "count mismatch")
|
||||
|
||||
ttl, err := s.rdb.TTL(s.ctx, key).Result()
|
||||
require.NoError(s.T(), err, "TTL")
|
||||
s.AssertTTLWithin(ttl, 1*time.Second, redeemRateLimitDuration)
|
||||
}
|
||||
|
||||
func (s *RedeemCacheSuite) TestMultipleIncrements() {
|
||||
userID := int64(2)
|
||||
|
||||
require.NoError(s.T(), s.cache.IncrementRedeemAttemptCount(s.ctx, userID))
|
||||
require.NoError(s.T(), s.cache.IncrementRedeemAttemptCount(s.ctx, userID))
|
||||
require.NoError(s.T(), s.cache.IncrementRedeemAttemptCount(s.ctx, userID))
|
||||
|
||||
count, err := s.cache.GetRedeemAttemptCount(s.ctx, userID)
|
||||
require.NoError(s.T(), err)
|
||||
require.Equal(s.T(), 3, count, "count after 3 increments")
|
||||
}
|
||||
|
||||
func (s *RedeemCacheSuite) TestAcquireAndReleaseRedeemLock() {
|
||||
ok, err := s.cache.AcquireRedeemLock(s.ctx, "CODE", 10*time.Second)
|
||||
require.NoError(s.T(), err, "AcquireRedeemLock")
|
||||
require.True(s.T(), ok)
|
||||
|
||||
// Second acquire should fail
|
||||
ok, err = s.cache.AcquireRedeemLock(s.ctx, "CODE", 10*time.Second)
|
||||
require.NoError(s.T(), err, "AcquireRedeemLock 2")
|
||||
require.False(s.T(), ok, "expected lock to be held")
|
||||
|
||||
// Release
|
||||
require.NoError(s.T(), s.cache.ReleaseRedeemLock(s.ctx, "CODE"), "ReleaseRedeemLock")
|
||||
|
||||
// Now acquire should succeed
|
||||
ok, err = s.cache.AcquireRedeemLock(s.ctx, "CODE", 10*time.Second)
|
||||
require.NoError(s.T(), err, "AcquireRedeemLock after release")
|
||||
require.True(s.T(), ok)
|
||||
}
|
||||
|
||||
func (s *RedeemCacheSuite) TestAcquireRedeemLock_TTL() {
|
||||
lockKey := redeemLockKeyPrefix + "CODE2"
|
||||
lockTTL := 15 * time.Second
|
||||
|
||||
ok, err := s.cache.AcquireRedeemLock(s.ctx, "CODE2", lockTTL)
|
||||
require.NoError(s.T(), err, "AcquireRedeemLock CODE2")
|
||||
require.True(s.T(), ok)
|
||||
|
||||
ttl, err := s.rdb.TTL(s.ctx, lockKey).Result()
|
||||
require.NoError(s.T(), err, "TTL lock key")
|
||||
s.AssertTTLWithin(ttl, 1*time.Second, lockTTL)
|
||||
}
|
||||
|
||||
func (s *RedeemCacheSuite) TestReleaseRedeemLock_Idempotent() {
|
||||
// Release a lock that doesn't exist should not error
|
||||
require.NoError(s.T(), s.cache.ReleaseRedeemLock(s.ctx, "NONEXISTENT"))
|
||||
|
||||
// Acquire, release, release again
|
||||
ok, err := s.cache.AcquireRedeemLock(s.ctx, "IDEMPOTENT", 10*time.Second)
|
||||
require.NoError(s.T(), err)
|
||||
require.True(s.T(), ok)
|
||||
require.NoError(s.T(), s.cache.ReleaseRedeemLock(s.ctx, "IDEMPOTENT"))
|
||||
require.NoError(s.T(), s.cache.ReleaseRedeemLock(s.ctx, "IDEMPOTENT"), "second release should be idempotent")
|
||||
}
|
||||
|
||||
func TestRedeemCacheSuite(t *testing.T) {
|
||||
suite.Run(t, new(RedeemCacheSuite))
|
||||
}
|
||||
Reference in New Issue
Block a user