You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

172 lines
6.1 KiB

package comm
import (
"testing"
"yunyan/pb"
)
func TestComputeRates_Conversion(t *testing.T) {
r := DefaultComputeRates()
cases := []struct {
name string
got int64
want int64
}{
{"翻译 0 秒不计", r.ForTranslate(0), 0},
{"翻译 1 秒向上取整到 1 分钟", r.ForTranslate(1), 1},
{"翻译 60 秒 = 1", r.ForTranslate(60), 1},
{"翻译 61 秒 = 2", r.ForTranslate(61), 2},
{"会议 3600 秒 = 60", r.ForMeeting(3600), 60},
{"对话 1 字最低 1", r.ForAIChat(1), 1},
{"对话 100 字 = 1", r.ForAIChat(100), 1},
{"对话 101 字 = 2", r.ForAIChat(101), 2},
}
for _, c := range cases {
if c.got != c.want {
t.Errorf("%s: got %d want %d", c.name, c.got, c.want)
}
}
r2 := ComputeRates{Translate: 3, Meeting: 2, AIChat: 5}
if got := r2.ForTranslate(90); got != 6 {
t.Errorf("系数 3 × 2 分钟应为 6,got %d", got)
}
if got := r2.ForAIChat(250); got != 15 {
t.Errorf("系数 5 × 3 段应为 15,got %d", got)
}
}
func TestParseComputeRates_BadValuesFallBack(t *testing.T) {
r := ParseComputeRates(map[string]string{
ConfigKeyComputeRateTranslate: "0", // 非法 → 默认 1
ConfigKeyComputeRateMeeting: "abc", // 非法 → 默认 1
ConfigKeyComputeRateAIChat: "4",
ConfigKeyComputeGate: "1",
})
if r.Translate != 1 || r.Meeting != 1 || r.AIChat != 4 || !r.Gate {
t.Fatalf("unexpected %+v", r)
}
if r := ParseComputeRates(nil); r != DefaultComputeRates() {
t.Fatalf("空配置应回默认,got %+v", r)
}
}
func TestResolveVip(t *testing.T) {
now := int64(2_000_000_000) // 2033 年,减几十天也不会跌成负数(Usedtime<=0 视为未激活)
day := int64(86400)
dev := func(used int64, days, level int32) *pb.DBAuthCode {
return &pb.DBAuthCode{Code: "AA", Devicemac: "AA", Usedtime: used, Vipdays: days, Viplevel: level}
}
t.Run("无任何来源", func(t *testing.T) {
v := ResolveVip(&pb.DBUser{}, nil, now)
if v.Active(now) || v.Level != 0 {
t.Fatalf("%+v", v)
}
})
t.Run("只有自购且有效", func(t *testing.T) {
v := ResolveVip(&pb.DBUser{Viplv: 1, Vipexptime: now + day}, nil, now)
if !v.Active(now) || v.FromDevice || v.ExpTime != now+day {
t.Fatalf("%+v", v)
}
})
t.Run("自购过期、设备在期 → 来自设备", func(t *testing.T) {
v := ResolveVip(&pb.DBUser{Vipexptime: now - day}, []*pb.DBAuthCode{dev(now-10*day, 30, 1)}, now)
if !v.Active(now) || !v.FromDevice || v.ExpTime != now-10*day+30*day {
t.Fatalf("%+v", v)
}
})
t.Run("设备未激活不算", func(t *testing.T) {
v := ResolveVip(&pb.DBUser{}, []*pb.DBAuthCode{dev(0, 30, 1)}, now)
if v.Active(now) {
t.Fatalf("%+v", v)
}
})
t.Run("设备 VIP 期按日历天连续走,解绑不暂停:激活 40 天前送 30 天 → 已过期", func(t *testing.T) {
v := ResolveVip(&pb.DBUser{}, []*pb.DBAuthCode{dev(now-40*day, 30, 1)}, now)
if v.Active(now) {
t.Fatalf("%+v", v)
}
if v.ExpTime != now-10*day {
t.Fatalf("过期时仍应给出历史到期时间, %+v", v)
}
})
t.Run("两者都有效:等级高的赢;同级取最晚", func(t *testing.T) {
v := ResolveVip(&pb.DBUser{Viplv: 1, Vipexptime: now + 100*day}, []*pb.DBAuthCode{dev(now-day, 10, 2)}, now)
if v.Level != 2 || !v.FromDevice {
t.Fatalf("设备是 VIP-Pro 应优先, %+v", v)
}
v = ResolveVip(&pb.DBUser{Viplv: 1, Vipexptime: now + 100*day}, []*pb.DBAuthCode{dev(now-day, 10, 1)}, now)
if v.Level != 1 || v.FromDevice || v.ExpTime != now+100*day {
t.Fatalf("同级取到期最晚的自购, %+v", v)
}
})
t.Run("设备配了天数没配等级视为 1", func(t *testing.T) {
v := ResolveVip(&pb.DBUser{}, []*pb.DBAuthCode{dev(now-day, 10, 0)}, now)
if v.Level != 1 {
t.Fatalf("%+v", v)
}
})
}
func TestPlanComputeDeduction(t *testing.T) {
d := func(mac string, grant, used int64) *pb.DBAuthCode {
return &pb.DBAuthCode{Code: mac, Devicemac: mac, Computegrant: grant, Computeused: used}
}
t.Run("先扣设备,剩余最少的先扣", func(t *testing.T) {
cuts, user, over := planComputeDeduction(7, []*pb.DBAuthCode{d("big", 100, 0), d("small", 10, 7)}, 50)
if len(cuts) != 2 || cuts[0].d.Code != "small" || cuts[0].n != 3 || cuts[1].n != 4 || user != 0 || over != 0 {
t.Fatalf("cuts=%+v user=%d over=%d", cuts, user, over)
}
})
t.Run("设备不够扣用户", func(t *testing.T) {
cuts, user, over := planComputeDeduction(10, []*pb.DBAuthCode{d("a", 4, 0)}, 50)
if len(cuts) != 1 || cuts[0].n != 4 || user != 6 || over != 0 {
t.Fatalf("cuts=%+v user=%d over=%d", cuts, user, over)
}
})
t.Run("都不够记超额", func(t *testing.T) {
cuts, user, over := planComputeDeduction(10, []*pb.DBAuthCode{d("a", 4, 0)}, 2)
if len(cuts) != 1 || user != 2 || over != 4 {
t.Fatalf("cuts=%+v user=%d over=%d", cuts, user, over)
}
})
t.Run("用完的设备跳过", func(t *testing.T) {
cuts, user, _ := planComputeDeduction(1, []*pb.DBAuthCode{d("a", 4, 4)}, 5)
if len(cuts) != 0 || user != 1 {
t.Fatalf("cuts=%+v user=%d", cuts, user)
}
})
}
func TestParseOpsParams(t *testing.T) {
t.Run("空配置回默认", func(t *testing.T) {
if got := ParseOpsParams(nil); got != DefaultOpsParams() {
t.Fatalf("got %+v", got)
}
})
t.Run("0 是合法值,不回落默认", func(t *testing.T) {
got := ParseOpsParams(map[string]string{
ConfigKeyNewUserGiftVipDays: "0",
ConfigKeyNewUserGiftCompute: "0",
ConfigKeyVipWarnDays: "0",
ConfigKeyComputeWarn: "0",
})
if got.NewUserGiftVipDays != 0 || got.NewUserGiftCompute != 0 || got.VipWarnDays != 0 || got.ComputeWarn != 0 {
t.Fatalf("配 0 应保持 0(= 不送 / 不提示),got %+v", got)
}
})
t.Run("非法值回默认", func(t *testing.T) {
got := ParseOpsParams(map[string]string{
ConfigKeyNewUserGiftVipDays: "abc",
ConfigKeyNewUserGiftCompute: "-5",
})
if got.NewUserGiftVipDays != DefaultNewUserGiftVipDays || got.NewUserGiftCompute != DefaultNewUserGiftCompute {
t.Fatalf("got %+v", got)
}
})
t.Run("往返一致", func(t *testing.T) {
in := OpsParams{NewUserGiftVipDays: 15, NewUserGiftCompute: 250, VipWarnDays: 3, ComputeWarn: 50}
if got := ParseOpsParams(in.ToKV()); got != in {
t.Fatalf("got %+v want %+v", got, in)
}
})
}