131 lines
5.4 KiB
Go
131 lines
5.4 KiB
Go
package business
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"kra/pkg/task"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func reportPtr(n int64) *int64 { return &n }
|
|
func TestReportBuildIdentityRulesAndAnonymousLogins(t *testing.T) {
|
|
input := &ReportInput{Users: map[ReportUserKey]ReportUser{}, Games: map[AnalyticsKey]string{{SourceDB: "lx", ID: 1}: "游戏"}}
|
|
for _, u := range []ReportUser{{ReportUserKey: ReportUserKey{"lx", 1}, ParentID: reportPtr(0), PromoteID: reportPtr(10), IDCard: " aaX "}, {ReportUserKey: ReportUserKey{"hw", 1}, ParentID: reportPtr(0), PromoteID: reportPtr(20), IDCard: "b"}, {ReportUserKey: ReportUserKey{"lx", 2}, ParentID: reportPtr(0), PromoteID: reportPtr(10), IDCard: "aax"}, {ReportUserKey: ReportUserKey{"lx", 3}, ParentID: reportPtr(1), PromoteID: reportPtr(10), IDCard: "sub"}, {ReportUserKey: ReportUserKey{"lx", 4}, PromoteID: reportPtr(10)}, {ReportUserKey: ReportUserKey{"lx", 5}, ParentID: reportPtr(0), PromoteID: reportPtr(10)}} {
|
|
input.Users[u.ReportUserKey] = u
|
|
}
|
|
event := func(id int64) ReportEvent {
|
|
return ReportEvent{SourceDB: "lx", UserID: reportPtr(id), PromoteID: reportPtr(10), GameID: reportPtr(1)}
|
|
}
|
|
input.Registers = []ReportEvent{event(1), event(2), event(5)}
|
|
missing := event(2)
|
|
missing.SourceDB = ""
|
|
missing.PromoteID = nil
|
|
ambiguous := event(1)
|
|
ambiguous.SourceDB = ""
|
|
input.Actives = []ReportEvent{event(1), missing, ambiguous, event(3), event(4)}
|
|
for _, id := range []int64{1, 3, 99} {
|
|
p := event(id)
|
|
p.Amount = "10"
|
|
input.Payments = append(input.Payments, p)
|
|
}
|
|
noUser := event(1)
|
|
noUser.UserID = nil
|
|
noUser.Amount = "1"
|
|
input.Payments = append(input.Payments, noUser)
|
|
rows, err := compileReport(DailyReport, input)
|
|
if err != nil || len(rows) != 2 {
|
|
t.Fatalf("汇总分组错误: %+v %v", rows, err)
|
|
}
|
|
for _, row := range rows {
|
|
if row.Pay != "31.00" || row.GameName != "游戏" || row.Counts.NewPay != 1 {
|
|
t.Fatalf("金额、名称或新增付费错误: %+v", row)
|
|
}
|
|
if row.Mode == 0 && (row.Counts.Register != 3 || row.Counts.Active != 2 || row.Counts.Pay != 3) {
|
|
t.Fatalf("账号口径未保留主账号登录/原始付费账号: %+v", row)
|
|
}
|
|
if row.Mode == 1 && (row.Counts.Register != 1 || row.Counts.Active != 1 || row.Counts.Pay != 2) {
|
|
t.Fatalf("身份证口径、空证件或末尾 X 归一错误: %+v", row)
|
|
}
|
|
}
|
|
input.Registers = []ReportEvent{event(2)}
|
|
input.Payments = []ReportEvent{event(1)}
|
|
input.Payments[0].Amount = "10"
|
|
rows, err = compileReport(DailyReport, input)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, row := range rows {
|
|
if row.Counts.NewPay != 0 {
|
|
t.Fatal("新增付费必须先取原始账号交集,不能把相同证件的其他付费账号算入")
|
|
}
|
|
}
|
|
server := event(3)
|
|
server.ServerNum = " 001 "
|
|
input.Registers = []ReportEvent{server}
|
|
input.Actives = []ReportEvent{server}
|
|
input.Payments = []ReportEvent{server}
|
|
input.Payments[0].Amount = "20"
|
|
rows, err = compileReport(ServerReport, input)
|
|
if err != nil || len(rows) != 2 {
|
|
t.Fatal("区服汇总失败")
|
|
}
|
|
for _, row := range rows {
|
|
if row.ServerNum != "001" || row.Counts.Register != 1 || row.Counts.Active != 1 || row.Counts.Pay != 1 || len(row.Keys[4]) != 0 {
|
|
t.Fatal("区服创角/活跃不能套用主账号限制,也不能生成新增付费指标")
|
|
}
|
|
}
|
|
}
|
|
|
|
type reportBuildFake struct{ days []string }
|
|
|
|
type failingReportCommit struct{}
|
|
|
|
func (failingReportCommit) Rebuild(_ context.Context, _ ReportBuildKind, _ time.Time, compile func(*ReportInput) ([]*ReportBuiltRow, error)) error {
|
|
_, err := compile(&ReportInput{Registers: []ReportEvent{{SourceDB: "lx", UserID: reportPtr(1), PromoteID: reportPtr(1), GameID: reportPtr(1)}}})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return errors.New("commit failed")
|
|
}
|
|
|
|
func TestReportBuildDetailsDoNotClaimRolledBackRows(t *testing.T) {
|
|
ctx, output := task.WithOutput(context.Background())
|
|
uc := NewReportBuildUsecase(failingReportCommit{})
|
|
if err := uc.Run(ctx, DailyReport, "backfill", "2026-11-03", "2026-11-03"); err == nil {
|
|
t.Fatal("commit error was lost")
|
|
}
|
|
text := output.String()
|
|
if !strings.Contains(text, "2026-11-03 未提交") || !strings.Contains(text, "已提交日期=0;汇总行=0;身份键=0") {
|
|
t.Fatalf("rollback was reported as success: %s", text)
|
|
}
|
|
}
|
|
|
|
func (r *reportBuildFake) Rebuild(_ context.Context, _ ReportBuildKind, day time.Time, _ func(*ReportInput) ([]*ReportBuiltRow, error)) error {
|
|
r.days = append(r.days, day.Format("2006-01-02"))
|
|
return nil
|
|
}
|
|
func TestReportBuildBackfillRangeAndCancellation(t *testing.T) {
|
|
r := &reportBuildFake{}
|
|
uc := NewReportBuildUsecase(r)
|
|
uc.now = func() time.Time { return time.Date(2026, 11, 4, 9, 0, 0, 0, portraitLocation) }
|
|
pauses := 0
|
|
uc.pause = func(context.Context) error { pauses++; return nil }
|
|
if err := uc.Run(context.Background(), DailyReport, "backfill", "2026-10-31", "2026-11-02"); err != nil || len(r.days) != 3 || pauses != 2 || r.days[2] != "2026-11-02" {
|
|
t.Fatal("回跑日期应闭区间且仅日间暂停")
|
|
}
|
|
if err := uc.Run(context.Background(), DailyReport, "backfill", "bad", ""); err != ErrAnalyticsDate {
|
|
t.Fatal("非法日期未拒绝")
|
|
}
|
|
if err := uc.Run(context.Background(), DailyReport, "backfill", "2026-11-05", "2026-11-04"); err != ErrAnalyticsDateOrder {
|
|
t.Fatal("倒置区间未拒绝")
|
|
}
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel()
|
|
count := len(r.days)
|
|
if err := uc.Run(ctx, ServerReport, "today", "", ""); err != context.Canceled || len(r.days) != count {
|
|
t.Fatal("取消后仍重建报表")
|
|
}
|
|
}
|