siteinfosync_test.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. package tools
  2. import (
  3. "testing"
  4. "time"
  5. "go.mongodb.org/mongo-driver/bson/primitive"
  6. "fwh-toolbox-server/domain"
  7. )
  8. func syncRecord(p domain.Progress, created, completed time.Time) *domain.SiteInfoUpdateRecord {
  9. id := primitive.NewObjectID()
  10. return &domain.SiteInfoUpdateRecord{Id: &id, Progress: p, CreateTime: created, UpdateTime: completed, Total: 100}
  11. }
  12. func TestSiteInfoSyncDecide(t *testing.T) {
  13. now := time.Date(2026, 10, 29, 12, 0, 0, 0, time.UTC)
  14. ago := func(h float64) time.Time { return now.Add(-time.Duration(h * float64(time.Hour))) }
  15. freshDone := syncRecord(domain.ProgressComplete, ago(3), ago(1))
  16. oldDone := syncRecord(domain.ProgressComplete, ago(50), ago(48))
  17. cases := []struct {
  18. name string
  19. latest, last *domain.SiteInfoUpdateRecord
  20. force bool
  21. state string
  22. action string
  23. }{
  24. {"从未同步", nil, nil, false, syncStateNever, "triggered"},
  25. {"pending 刚请求", syncRecord(domain.ProgressPending, ago(0.1), ago(0.1)), oldDone, false, syncStateSyncing, "tracking"},
  26. {"running 2 小时仍在同步", syncRecord(domain.ProgressRunning, ago(2), ago(2)), oldDone, false, syncStateSyncing, "tracking"},
  27. {"同步中 force 也不重复触发", syncRecord(domain.ProgressRunning, ago(2), ago(2)), oldDone, true, syncStateSyncing, "tracking"},
  28. {"running 超过 6 小时疑似中断", syncRecord(domain.ProgressRunning, ago(7), ago(7)), oldDone, false, syncStateStale, "skipped_stale"},
  29. {"疑似中断 force 重新触发", syncRecord(domain.ProgressRunning, ago(7), ago(7)), oldDone, true, syncStateStale, "triggered"},
  30. {"24 小时内已成功", freshDone, freshDone, false, syncStateIdle, "skipped_fresh"},
  31. {"24 小时内已成功 force", freshDone, freshDone, true, syncStateIdle, "triggered"},
  32. {"成功已超过 24 小时", oldDone, oldDone, false, syncStateIdle, "triggered"},
  33. {"上次失败", syncRecord(domain.ProgressError, ago(1), ago(1)), freshDone, false, syncStateIdle, "triggered"},
  34. }
  35. for _, c := range cases {
  36. s := evalSiteInfoSync(c.latest, c.last, now)
  37. if s.State != c.state {
  38. t.Errorf("%s: state = %s,期望 %s", c.name, s.State, c.state)
  39. }
  40. if action, _ := s.decideRefresh(c.force); action != c.action {
  41. t.Errorf("%s: action = %s,期望 %s", c.name, action, c.action)
  42. }
  43. if _, ok := refreshMessages[c.action]; !ok {
  44. t.Errorf("%s: action %s 缺少提示文案", c.name, c.action)
  45. }
  46. if v := s.view(); v["advice"] == "" {
  47. t.Errorf("%s: advice 为空", c.name)
  48. }
  49. }
  50. }