116 lines
3.2 KiB
Go
116 lines
3.2 KiB
Go
package service
|
||
|
||
import (
|
||
"context"
|
||
"errors"
|
||
"testing"
|
||
|
||
"github.com/redis/go-redis/v9"
|
||
|
||
"github.com/topfans/backend/services/moderationService/config"
|
||
)
|
||
|
||
// auto_hide_service_test.go - Lua 脚本逻辑测试(spec §7.2)
|
||
|
||
// TestLuaScript 嵌入的 Lua 脚本存在且非空
|
||
func TestLuaScript(t *testing.T) {
|
||
if autoHideLuaScript == "" {
|
||
t.Fatal("autoHideLuaScript must be embedded")
|
||
}
|
||
// 验证 Lua 包含关键逻辑:SETNX, INCR, EXPIRE, threshold
|
||
requiredKeywords := []string{"SET", "INCR", "EXPIRE"}
|
||
for _, kw := range requiredKeywords {
|
||
if !contains(autoHideLuaScript, kw) {
|
||
t.Errorf("Lua script missing keyword: %s", kw)
|
||
}
|
||
}
|
||
}
|
||
|
||
// TestTryTrigger_LockFailure 测试锁抢占失败场景
|
||
// 应用层短锁覆盖整个 auto-hide 流程(spec §6.4)
|
||
func TestTryTrigger_LockFailure(t *testing.T) {
|
||
rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"})
|
||
defer rdb.Close()
|
||
ctx := context.Background()
|
||
svc := &AutoHideService{redis: rdb, cfg: config.Default}
|
||
|
||
// 用 miniredis 或真实 Redis:先 acquire lock
|
||
lockKey := "test:mod:report:lock:asset:999"
|
||
rdb.SetNX(ctx, lockKey, "1", config.Default.LockTTL)
|
||
|
||
// 再调用应该返回 (false, 0, nil) — 锁失败不触发
|
||
triggered, _, err := svc.TryTrigger(ctx, "asset", 999, 100)
|
||
if err != nil {
|
||
t.Skipf("redis not available: %v", err)
|
||
}
|
||
if triggered {
|
||
t.Errorf("expected triggered=false when lock held")
|
||
}
|
||
rdb.Del(ctx, lockKey)
|
||
}
|
||
|
||
// TestResetCounter_EmptyKeys 测试重置计数器在空 keys 场景
|
||
func TestResetCounter_EmptyKeys(t *testing.T) {
|
||
rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"})
|
||
defer rdb.Close()
|
||
ctx := context.Background()
|
||
svc := &AutoHideService{redis: rdb, cfg: config.Default}
|
||
|
||
err := svc.ResetCounter(ctx, "asset", 888)
|
||
if err != nil && !errors.Is(err, redis.Nil) {
|
||
t.Logf("ResetCounter err (acceptable for empty): %v", err)
|
||
}
|
||
}
|
||
|
||
// TestResetCounter_WithExistingKeys 测试有 keys 时的清理
|
||
func TestResetCounter_WithExistingKeys(t *testing.T) {
|
||
rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"})
|
||
defer rdb.Close()
|
||
ctx := context.Background()
|
||
svc := &AutoHideService{redis: rdb, cfg: config.Default}
|
||
|
||
// pre-populate
|
||
prefix := config.Default.RedisKeyPrefix + ":user:asset:777:"
|
||
for _, uid := range []int64{101, 102, 103} {
|
||
key := prefix + itoa(uid)
|
||
rdb.Set(ctx, key, "1", config.Default.UserMarkerTTL)
|
||
}
|
||
counterKey := config.Default.RedisKeyPrefix + ":counter:asset:777"
|
||
rdb.Set(ctx, counterKey, "3", config.Default.CounterTTL)
|
||
|
||
err := svc.ResetCounter(ctx, "asset", 777)
|
||
if err != nil && !errors.Is(err, redis.Nil) {
|
||
t.Logf("ResetCounter err: %v", err)
|
||
}
|
||
|
||
// verify counter + user markers cleared
|
||
if exists, _ := rdb.Exists(ctx, counterKey).Result(); exists != 0 {
|
||
t.Errorf("counter key not cleared")
|
||
}
|
||
for _, uid := range []int64{101, 102, 103} {
|
||
key := prefix + itoa(uid)
|
||
if exists, _ := rdb.Exists(ctx, key).Result(); exists != 0 {
|
||
t.Errorf("user marker %d not cleared", uid)
|
||
}
|
||
}
|
||
}
|
||
|
||
func itoa(i int64) string {
|
||
if i == 0 {
|
||
return "0"
|
||
}
|
||
negative := i < 0
|
||
if negative {
|
||
i = -i
|
||
}
|
||
digits := []byte{}
|
||
for i > 0 {
|
||
digits = append([]byte{byte('0' + i%10)}, digits...)
|
||
i /= 10
|
||
}
|
||
if negative {
|
||
digits = append([]byte{'-'}, digits...)
|
||
}
|
||
return string(digits)
|
||
}
|