package business import ( "context" "testing" "time" ) func TestAlertAbsoluteThresholdBoundaries(t *testing.T) { days := 30 threshold := "2000" rule := &AlertRule{Type: "充值", Metric: 2, ConditionMode: 2, AmountDirection: 1, AmountThreshold: &threshold, StatPeriodDays: &days} if err := validateAlertRule(rule); err != nil { t.Fatal(err) } for _, tc := range []struct { direction int amount string want bool }{{1, "1999.99", false}, {1, "2000", true}, {1, "3000", true}, {2, "1999.99", true}, {2, "2000", false}} { rule.AmountDirection = tc.direction _, hit, err := triggerContent(rule, &AlertTriggerChannel{}, AlertComparison{Current: tc.amount}, time.Now()) if err != nil || hit != tc.want { t.Fatalf("%+v hit=%v err=%v", tc, hit, err) } } bad := "0.001" rule.AmountThreshold = &bad if validateAlertRule(rule) == nil { t.Fatal("不足一分的金额不能入库后被四舍五入为零") } rule.Metric = 1 if validateAlertRule(rule) == nil { t.Fatal("注册量不能使用充值绝对值条件") } } type governanceFake struct { AlertGovernanceRepo gap *AlertGap adds int target *AlertExemptionTarget } func (r *governanceFake) SaveGap(_ context.Context, g *AlertGap) error { r.gap = g; return nil } func (r *governanceFake) AddExemption(_ context.Context, _ UserScope, _ ChannelKey, build func(*AlertExemptionTarget) (*AlertExemption, error)) error { if _, err := build(r.target); err != nil { return err } r.adds++ return nil } func TestAlertGovernanceChecksLevelAndKeepsTenantGap(t *testing.T) { records, _ := alertRecordFixture() r := &governanceFake{target: &AlertExemptionTarget{Name: "渠道", Account: &Account{ID: 9, Level: 3, IDPath: "0,7,8"}}} uc := NewAlertGovernanceUsecase(r, records.accounts) if err := uc.SaveGap(accountContext(9, 903), true, 7); err != ErrAlertGovernanceLevel { t.Fatalf("越级间隔配置: %v", err) } if err := uc.SaveGap(accountContext(7, 901), true, 1000); err != nil || r.gap.OwnerID != 7 || r.gap.Days != 1000 { t.Fatal("间隔应归属当前一级商务且不限制为365天") } if err := uc.Add(accountContext(8, 902), ChannelKey{"lx", 1}, "备注"); err != ErrAlertGovernanceLevel { t.Fatal("下级不能加入免预警") } if err := uc.Add(accountContext(7, 901), ChannelKey{"lx", 1}, " "); err != ErrAlertRecordInput { t.Fatal("加入原因不能为空") } if err := uc.Add(accountContext(7, 901), ChannelKey{"lx", 1}, "长期合作"); err != nil || r.adds != 1 { t.Fatalf("加入失败: %v", err) } } func TestAlertRuleRejectsUnboundedDecimalAndIgnoresInactiveInputs(t *testing.T) { days := 7 for _, value := range []string{"1e10000000", "0.001", "NaN", "999999999999999999999999"} { rule := &AlertRule{Type: "充值", Metric: 2, ConditionMode: 2, StatPeriodDays: &days, AmountDirection: 1, AmountThreshold: &value} if validateAlertRule(rule) == nil { t.Fatalf("非法金额通过校验: %s", value) } } huge := "1e10000000" direction := 999999 rule := &AlertRule{Type: "登录", Metric: 3, UnloginDays: &days, MomDirection: &direction, MomThreshold: &huge, AmountThreshold: &huge} if err := validateAlertRule(rule); err != nil || rule.MomThreshold != nil || rule.MomDirection != nil || rule.AmountThreshold != nil { t.Fatalf("未使用字段不应绕过校验写入数据库: %+v %v", rule, err) } }