simCardStatistics_test.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package simCardQueue
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fwh-toolbox-server/domain"
  6. "io"
  7. "net/http"
  8. "strings"
  9. "testing"
  10. "github.com/hibiken/asynq"
  11. )
  12. type roundTripFunc func(*http.Request) (*http.Response, error)
  13. func (fn roundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) { return fn(req) }
  14. func TestAccumulateSimCardStatistics(t *testing.T) {
  15. stats := domain.SimCardDailyStatistics{Date: "2026-09-24"}
  16. zero := 0.0
  17. previous := 200.0 * 1024
  18. // Thresholds are strict; cards without a previous snapshot count only toward totals.
  19. accumulateSimCardStatistics(&stats, 200*1024, &zero)
  20. accumulateSimCardStatistics(&stats, 1024*1024, &previous)
  21. accumulateSimCardStatistics(&stats, 2*1024*1024, nil)
  22. accumulateSimCardStatistics(&stats, 3*1024*1024, &zero)
  23. if stats.CardCount != 4 || stats.TotalOver200MB != 3 || stats.TotalOver1GB != 2 || stats.TotalOver2GB != 1 {
  24. t.Fatalf("unexpected total statistics: %+v", stats)
  25. }
  26. if stats.MaxTotalKB != 3*1024*1024 || stats.IncrementCardCount != 3 {
  27. t.Fatalf("unexpected maxima or comparison count: %+v", stats)
  28. }
  29. if stats.IncrementOver20MB != 3 || stats.IncrementOver50MB != 3 || stats.IncrementOver200MB != 2 {
  30. t.Fatalf("unexpected increment statistics: %+v", stats)
  31. }
  32. if stats.MaxIncrementKB == nil || *stats.MaxIncrementKB != 3*1024*1024 {
  33. t.Fatalf("unexpected maximum increment: %+v", stats.MaxIncrementKB)
  34. }
  35. if !strings.Contains(formatSimCardStatistics(stats), "最大增量:3072.00 MB") {
  36. t.Fatal("report does not show maximum increment")
  37. }
  38. }
  39. func TestPostSimCardStatistics(t *testing.T) {
  40. client := &http.Client{Transport: roundTripFunc(func(r *http.Request) (*http.Response, error) {
  41. if r.Method != http.MethodPost || r.Header.Get("Content-Type") != "application/json" {
  42. t.Errorf("unexpected request: %s %s", r.Method, r.Header.Get("Content-Type"))
  43. }
  44. if r.URL.Query().Get("timestamp") == "" || r.URL.Query().Get("sign") == "" || r.URL.Query().Get("access_token") != "test" {
  45. t.Errorf("signature or access token missing: %s", r.URL.RawQuery)
  46. }
  47. var message struct {
  48. MsgType string `json:"msgtype"`
  49. Markdown struct {
  50. Text string `json:"text"`
  51. } `json:"markdown"`
  52. }
  53. if err := json.NewDecoder(r.Body).Decode(&message); err != nil {
  54. t.Error(err)
  55. }
  56. if message.MsgType != "markdown" || !strings.Contains(message.Markdown.Text, "2026-09-24") {
  57. t.Errorf("unexpected message: %+v", message)
  58. }
  59. return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader(`{"errcode":0,"errmsg":"ok"}`))}, nil
  60. })}
  61. stats := domain.SimCardDailyStatistics{Date: "2026-09-24"}
  62. if err := postSimCardStatistics(context.Background(), client, "https://oapi.dingtalk.com/robot/send?access_token=test", "secret", stats); err != nil {
  63. t.Fatal(err)
  64. }
  65. }
  66. func TestPostSimCardStatisticsRejectsBotError(t *testing.T) {
  67. client := &http.Client{Transport: roundTripFunc(func(r *http.Request) (*http.Response, error) {
  68. return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader(`{"errcode":310000,"errmsg":"rejected"}`))}, nil
  69. })}
  70. if err := postSimCardStatistics(context.Background(), client, "https://oapi.dingtalk.com/robot/send", "", domain.SimCardDailyStatistics{}); err == nil {
  71. t.Fatal("DingTalk error response must be retried")
  72. }
  73. }
  74. func TestUnconfiguredWebhookSkipsStatistics(t *testing.T) {
  75. processor := &SimCardProcessor{}
  76. if err := processor.enqueueSimCardReportIfComplete("2026-09-24"); err != nil {
  77. t.Fatal(err)
  78. }
  79. if err := processor.handleSimCardDailyReport(context.Background(), asynq.NewTask(taskTypeSimCardDailyReport, []byte("2026-09-24"))); err != nil {
  80. t.Fatal(err)
  81. }
  82. }
  83. func TestAccumulateSimCardStatisticsMissingPrevious(t *testing.T) {
  84. stats := domain.SimCardDailyStatistics{}
  85. accumulateSimCardStatistics(&stats, 300*1024, nil)
  86. if stats.IncrementCardCount != 0 || stats.MaxIncrementKB != nil {
  87. t.Fatalf("missing previous day must not create an increment: %+v", stats)
  88. }
  89. }
  90. func TestAccumulateSimCardStatisticsCounterReset(t *testing.T) {
  91. stats := domain.SimCardDailyStatistics{}
  92. previous := 2.0 * 1024 * 1024
  93. accumulateSimCardStatistics(&stats, 60*1024, &previous)
  94. if stats.MaxIncrementKB == nil || *stats.MaxIncrementKB != 60*1024 || stats.IncrementOver50MB != 1 {
  95. t.Fatalf("reset counter should use current accumulated usage: %+v", stats)
  96. }
  97. }