package service import ( "context" "errors" "testing" "time" "affiliate_dash/internal/model" "affiliate_dash/internal/testdb" ) func TestAutoPurchaseCooldown_ManualAttemptDoesNotBlock(t *testing.T) { now := time.Now() manualJustNow := now.Add(-time.Minute) autoLongAgo := now.Add(-30 * time.Minute) cfg := &model.RockConfig{ PurchaseCooldownMinutes: 10, LastAttemptAt: &manualJustNow, // 刚刚手动采购过 LastAutoAttemptAt: &autoLongAgo, // 上一次自动尝试已过冷却 } if remain := rockAutoPurchaseCooldownRemaining(cfg, now); remain != 0 { t.Fatalf("手动采购不应阻塞自动补货,剩余冷却 %v", remain) } } func TestAutoPurchaseCooldown_UsesLastAutoAttempt(t *testing.T) { now := time.Now() recentAuto := now.Add(-2 * time.Minute) cfg := &model.RockConfig{ PurchaseCooldownMinutes: 10, LastAutoAttemptAt: &recentAuto, } remain := rockAutoPurchaseCooldownRemaining(cfg, now) if remain < 7*time.Minute || remain > 8*time.Minute { t.Fatalf("剩余冷却时间不符: %v", remain) } } func TestAutoPurchaseCooldown_BlockedAttemptWritesNoLog(t *testing.T) { db := testdb.New(t, &model.RockConfig{}, &model.RockPurchaseLog{}) svc := NewRockService(db, NewRockClient("https://example.com")) ctx := context.Background() if _, err := svc.GetConfig(ctx); err != nil { t.Fatalf("初始化配置失败: %v", err) } recent := time.Now().Add(-time.Minute) if err := db.Model(&model.RockConfig{}).Where("id = ?", 1). Updates(map[string]interface{}{ "purchase_cooldown_minutes": 10, "last_auto_attempt_at": recent, }).Error; err != nil { t.Fatalf("写入冷却时间失败: %v", err) } if _, err := svc.PurchaseTokens(ctx, 10, true); !errors.Is(err, ErrAutoPurchaseCooldown) { t.Fatalf("应命中自动采购冷却,实际 err=%v", err) } var count int64 if err := db.Model(&model.RockPurchaseLog{}).Count(&count).Error; err != nil { t.Fatalf("统计采购流水失败: %v", err) } if count != 0 { t.Fatalf("冷却拦截不应生成采购流水,实际 %d 条", count) } } func TestGetStats_ExposesAutoPurchaseCooldown(t *testing.T) { db := newRockTestDB(t) svc := NewRockService(db, NewRockClient("https://example.com")) ctx := context.Background() if _, err := svc.GetConfig(ctx); err != nil { t.Fatalf("初始化配置失败: %v", err) } recent := time.Now().Add(-time.Minute) if err := db.Model(&model.RockConfig{}).Where("id = ?", 1). Updates(map[string]interface{}{ "auto_purchase_enabled": true, "purchase_cooldown_minutes": 10, "last_auto_attempt_at": recent, }).Error; err != nil { t.Fatalf("写入冷却配置失败: %v", err) } stats, err := svc.GetStats(ctx) if err != nil { t.Fatalf("查询统计失败: %v", err) } if stats.AutoPurchaseCooldownSeconds <= 0 { t.Fatalf("应返回剩余冷却秒数: %+v", stats) } if stats.NextAutoPurchaseAt == "" { t.Fatalf("应返回下次可自动补货时间: %+v", stats) } }