package s3lifecycle import ( "testing" "time" ) func TestEventLogHorizon_PerActionIsIndependent(t *testing.T) { // A multi-action rule's horizon is computed per kind: the gate runs on // each compiled action separately, so EXPIRATION_DAYS at 90d does NOT // share a horizon with its sibling ABORT_MPU at 7d. rule := &Rule{ExpirationDays: 90, AbortMPUDaysAfterInitiation: 7, NoncurrentVersionExpirationDays: 30} cases := []struct { kind ActionKind want time.Duration }{ {ActionKindExpirationDays, DaysToDuration(90)}, {ActionKindAbortMPU, DaysToDuration(7)}, {ActionKindNoncurrentDays, DaysToDuration(30)}, {ActionKindExpirationDate, 0}, } for _, c := range cases { t.Run(c.kind.String(), func(t *testing.T) { if got := EventLogHorizon(rule, c.kind); got != c.want { t.Fatalf("want %v, got %v", c.want, got) } }) } } func TestEventLogHorizon_NewerNoncurrentCountOnlyIsSmallDelay(t *testing.T) { rule := &Rule{NewerNoncurrentVersions: 5} if got := EventLogHorizon(rule, ActionKindNewerNoncurrent); got != SmallDelay { t.Fatalf("want SmallDelay, got %v", got) } } func TestEventLogHorizon_NewerNoncurrentWithDaysIsZero(t *testing.T) { // Pure NEWER_NONCURRENT only when NoncurrentDays is unset; otherwise the // rule produces a NONCURRENT_DAYS action and asking for NEWER_NONCURRENT // returns 0 (not declared by this rule). rule := &Rule{NoncurrentVersionExpirationDays: 30, NewerNoncurrentVersions: 5} if got := EventLogHorizon(rule, ActionKindNewerNoncurrent); got != 0 { t.Fatalf("NEWER_NONCURRENT not declared when paired with days, got %v", got) } // The actual action this rule declares is NONCURRENT_DAYS — verify horizon there. if got := EventLogHorizon(rule, ActionKindNoncurrentDays); got != DaysToDuration(30) { t.Fatalf("NoncurrentDays horizon, want 30d, got %v", got) } } func TestEventLogHorizon_ExpiredDeleteMarkerIsSmallDelay(t *testing.T) { rule := &Rule{ExpiredObjectDeleteMarker: true} if got := EventLogHorizon(rule, ActionKindExpiredDeleteMarker); got != SmallDelay { t.Fatalf("want SmallDelay, got %v", got) } } func TestEventLogHorizon_DateKindReturnsZero(t *testing.T) { rule := &Rule{ExpirationDate: mustTime(t, "2025-06-15T00:00:00Z")} if got := EventLogHorizon(rule, ActionKindExpirationDate); got != 0 { t.Fatalf("date kind bypasses gate, got %v", got) } } func TestEventLogHorizon_NilRule(t *testing.T) { if got := EventLogHorizon(nil, ActionKindExpirationDays); got != 0 { t.Fatalf("nil rule should return 0, got %v", got) } } func TestEventLogHorizon_KindNotDeclaredReturnsZero(t *testing.T) { // Asking for a kind the rule doesn't declare returns 0; the gate then // trivially passes for that compiled action (which doesn't exist). rule := &Rule{ExpirationDays: 30} if got := EventLogHorizon(rule, ActionKindAbortMPU); got != 0 { t.Fatalf("want 0 for undeclared kind, got %v", got) } }