153 lines
4.4 KiB
Go
153 lines
4.4 KiB
Go
package domain
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func d(y int, m time.Month, day int) time.Time {
|
|
return time.Date(y, m, day, 0, 0, 0, 0, time.Local)
|
|
}
|
|
|
|
func TestDayDiff(t *testing.T) {
|
|
cases := []struct {
|
|
a, b time.Time
|
|
want int
|
|
}{
|
|
{d(2026, 1, 1), d(2026, 1, 1), 0},
|
|
{d(2026, 1, 1), d(2026, 1, 31), 30},
|
|
{d(2026, 2, 28), d(2026, 3, 1), 1},
|
|
{d(2024, 2, 28), d(2024, 3, 1), 2}, // 闰年
|
|
{d(2026, 12, 31), d(2027, 1, 1), 1},
|
|
{d(2026, 1, 10), d(2026, 1, 1), -9},
|
|
}
|
|
for _, c := range cases {
|
|
if got := DayDiff(c.a, c.b); got != c.want {
|
|
t.Errorf("DayDiff(%s,%s)=%d want %d", Date(c.a), Date(c.b), got, c.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestEvalDay(t *testing.T) {
|
|
today := d(2026, 10, 18)
|
|
cases := []struct {
|
|
name string
|
|
status string
|
|
end string
|
|
wantState string
|
|
wantLevel string
|
|
wantDays int
|
|
}{
|
|
{"进行中", "active", "2026-11-16", StateActive, LevelOK, 30},
|
|
{"今天到期", "active", "2026-10-18", StateActive, LevelToday, 1},
|
|
{"3天内", "active", "2026-10-20", StateActive, LevelWarn, 3},
|
|
{"已到期", "active", "2026-10-17", StateExpired, LevelExpired, 0},
|
|
{"暂停中", "paused", "2026-11-16", StatePaused, LevelNone, 30},
|
|
{"已结束", "closed", "2026-11-16", StateClosed, LevelNone, 30},
|
|
}
|
|
for _, c := range cases {
|
|
e := EvalSub(UnitDay, c.status, "2026-10-01", c.end, 0, 0, today, 3)
|
|
if e.State != c.wantState {
|
|
t.Errorf("%s: state=%s want %s", c.name, e.State, c.wantState)
|
|
}
|
|
if e.Level != c.wantLevel {
|
|
t.Errorf("%s: level=%s want %s", c.name, e.Level, c.wantLevel)
|
|
}
|
|
if e.RemainingDays != c.wantDays {
|
|
t.Errorf("%s: remaining=%d want %d", c.name, e.RemainingDays, c.wantDays)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestEvalDayNotStarted(t *testing.T) {
|
|
today := d(2026, 10, 18)
|
|
e := EvalSub(UnitDay, "active", "2026-10-20", "2026-11-18", 0, 0, today, 3)
|
|
if e.State != StatePending {
|
|
t.Fatalf("state=%s want pending", e.State)
|
|
}
|
|
if e.RemainingDays != 32 {
|
|
t.Fatalf("remaining=%d want 32", e.RemainingDays)
|
|
}
|
|
}
|
|
|
|
func TestEvalCount(t *testing.T) {
|
|
today := d(2026, 10, 18)
|
|
|
|
// 有次数、有有效期,10 天后到期 → 正常
|
|
e := EvalSub(UnitCount, "active", "2026-10-01", "2026-10-28", 10, 4, today, 3)
|
|
if e.State != StateActive || e.Level != LevelOK || e.RemainingCount != 6 {
|
|
t.Fatalf("got state=%s level=%s remain=%d", e.State, e.Level, e.RemainingCount)
|
|
}
|
|
|
|
// 有效期就是今天 → 今天到期(而不是误判成 warn/ok)
|
|
e = EvalSub(UnitCount, "active", "2026-10-01", "2026-10-18", 10, 4, today, 3)
|
|
if e.Level != LevelToday {
|
|
t.Fatalf("level=%s want today", e.Level)
|
|
}
|
|
|
|
// 只有次数,没有有效期 → 无预警等级
|
|
e = EvalSub(UnitCount, "active", "2026-10-01", "", 10, 4, today, 3)
|
|
if e.Level != LevelNone || e.DaysLeft != -1 {
|
|
t.Fatalf("level=%s daysLeft=%d", e.Level, e.DaysLeft)
|
|
}
|
|
|
|
// 次数用尽
|
|
e = EvalSub(UnitCount, "active", "2026-10-01", "", 10, 10, today, 3)
|
|
if e.State != StateUsedUp {
|
|
t.Fatalf("state=%s want usedup", e.State)
|
|
}
|
|
|
|
// 次数还有,但有效期已过
|
|
e = EvalSub(UnitCount, "active", "2026-10-01", "2026-10-10", 10, 4, today, 3)
|
|
if e.State != StateExpired {
|
|
t.Fatalf("state=%s want expired", e.State)
|
|
}
|
|
}
|
|
|
|
func TestPlanExtend(t *testing.T) {
|
|
today := d(2026, 10, 18)
|
|
|
|
// 未到期:从原结束日次日顺延,追加天数 = 新旧结束日之差
|
|
oldEnd := d(2026, 11, 16)
|
|
newEnd := d(2026, 12, 2)
|
|
p := PlanExtend(oldEnd, newEnd, today)
|
|
if Date(p.Base) != "2026-11-17" {
|
|
t.Fatalf("base=%s", Date(p.Base))
|
|
}
|
|
if p.Days != 16 {
|
|
t.Fatalf("days=%d want 16", p.Days)
|
|
}
|
|
|
|
// 已到期:从今天起算
|
|
oldEnd = d(2026, 10, 5)
|
|
newEnd = d(2026, 11, 3)
|
|
p = PlanExtend(oldEnd, newEnd, today)
|
|
if Date(p.Base) != "2026-10-18" {
|
|
t.Fatalf("base=%s", Date(p.Base))
|
|
}
|
|
if p.Days != 17 {
|
|
t.Fatalf("days=%d want 17", p.Days)
|
|
}
|
|
|
|
// 选的日期早于计算起点 → 无效
|
|
p = PlanExtend(d(2026, 11, 16), d(2026, 11, 10), today)
|
|
if !p.Backwards || p.Days != 0 {
|
|
t.Fatalf("backwards=%v days=%d", p.Backwards, p.Days)
|
|
}
|
|
}
|
|
|
|
func TestMonthHelpers(t *testing.T) {
|
|
if got := Date(MonthEnd(2026, time.February)); got != "2026-02-28" {
|
|
t.Fatalf("MonthEnd=%s", got)
|
|
}
|
|
if got := Date(MonthEnd(2024, time.February)); got != "2024-02-29" {
|
|
t.Fatalf("MonthEnd=%s", got)
|
|
}
|
|
if got := WeekdayIndex(d(2026, 10, 18)); got != 6 { // 周日
|
|
t.Fatalf("WeekdayIndex=%d want 6", got)
|
|
}
|
|
if got := WeekdayIndex(d(2026, 10, 19)); got != 0 { // 周一
|
|
t.Fatalf("WeekdayIndex=%d want 0", got)
|
|
}
|
|
}
|