Pulse/pkg/licensing/subscription_test.go
2026-03-18 16:06:30 +00:00

203 lines
5.4 KiB
Go

package licensing
import (
"testing"
)
func TestCanTransition_ValidTransitions(t *testing.T) {
for transition := range validTransitions {
transition := transition
t.Run(string(transition.From)+"_to_"+string(transition.To), func(t *testing.T) {
if !CanTransition(transition.From, transition.To) {
t.Fatalf("expected transition %s -> %s to be valid", transition.From, transition.To)
}
})
}
}
func TestCanTransition_InvalidTransitions(t *testing.T) {
tests := []struct {
name string
from SubscriptionState
to SubscriptionState
}{
{name: "trial_to_grace", from: SubStateTrial, to: SubStateGrace},
{name: "trial_to_suspended", from: SubStateTrial, to: SubStateSuspended},
{name: "active_to_trial", from: SubStateActive, to: SubStateTrial},
{name: "active_to_expired", from: SubStateActive, to: SubStateExpired},
{name: "grace_to_suspended", from: SubStateGrace, to: SubStateSuspended},
{name: "grace_to_trial", from: SubStateGrace, to: SubStateTrial},
{name: "expired_to_grace", from: SubStateExpired, to: SubStateGrace},
{name: "expired_to_trial", from: SubStateExpired, to: SubStateTrial},
{name: "expired_to_suspended", from: SubStateExpired, to: SubStateSuspended},
{name: "suspended_to_grace", from: SubStateSuspended, to: SubStateGrace},
{name: "suspended_to_trial", from: SubStateSuspended, to: SubStateTrial},
}
states := []SubscriptionState{
SubStateTrial,
SubStateActive,
SubStateGrace,
SubStateExpired,
SubStateSuspended,
}
for _, state := range states {
tests = append(tests, struct {
name string
from SubscriptionState
to SubscriptionState
}{
name: string(state) + "_to_itself",
from: state,
to: state,
})
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
if CanTransition(tt.from, tt.to) {
t.Fatalf("expected transition %s -> %s to be invalid", tt.from, tt.to)
}
})
}
}
func TestValidTransitionsFrom(t *testing.T) {
tests := []struct {
from SubscriptionState
expected map[SubscriptionState]struct{}
}{
{
from: SubStateTrial,
expected: map[SubscriptionState]struct{}{
SubStateActive: {},
SubStateExpired: {},
},
},
{
from: SubStateActive,
expected: map[SubscriptionState]struct{}{
SubStateGrace: {},
SubStateSuspended: {},
},
},
{
from: SubStateGrace,
expected: map[SubscriptionState]struct{}{
SubStateActive: {},
SubStateExpired: {},
},
},
{
from: SubStateExpired,
expected: map[SubscriptionState]struct{}{
SubStateActive: {},
},
},
{
from: SubStateSuspended,
expected: map[SubscriptionState]struct{}{
SubStateActive: {},
SubStateExpired: {},
},
},
}
for _, tt := range tests {
tt := tt
t.Run(string(tt.from), func(t *testing.T) {
got := ValidTransitionsFrom(tt.from)
gotSet := make(map[SubscriptionState]struct{}, len(got))
for _, target := range got {
gotSet[target] = struct{}{}
}
if len(gotSet) != len(tt.expected) {
t.Fatalf("unexpected number of transitions for %s: got=%d want=%d", tt.from, len(gotSet), len(tt.expected))
}
for expectedTarget := range tt.expected {
if _, ok := gotSet[expectedTarget]; !ok {
t.Fatalf("missing expected transition for %s -> %s", tt.from, expectedTarget)
}
}
})
}
}
func TestGetBehavior(t *testing.T) {
tests := []struct {
state SubscriptionState
operations OperationClass
featuresAvailable bool
showWarning bool
}{
{
state: SubStateTrial,
operations: OpFull,
featuresAvailable: true,
showWarning: false,
},
{
state: SubStateActive,
operations: OpFull,
featuresAvailable: true,
showWarning: false,
},
{
state: SubStateGrace,
operations: OpFull,
featuresAvailable: true,
showWarning: true,
},
{
state: SubStateExpired,
operations: OpDegraded,
featuresAvailable: false,
showWarning: true,
},
{
state: SubStateSuspended,
operations: OpLocked,
featuresAvailable: false,
showWarning: true,
},
}
for _, tt := range tests {
tt := tt
t.Run(string(tt.state), func(t *testing.T) {
got := GetBehavior(tt.state)
if got.State != tt.state {
t.Fatalf("unexpected state in behavior: got=%s want=%s", got.State, tt.state)
}
if got.Operations != tt.operations {
t.Fatalf("unexpected operations for %s: got=%s want=%s", tt.state, got.Operations, tt.operations)
}
if got.FeaturesAvailable != tt.featuresAvailable {
t.Fatalf("unexpected features flag for %s: got=%t want=%t", tt.state, got.FeaturesAvailable, tt.featuresAvailable)
}
if got.ShowWarning != tt.showWarning {
t.Fatalf("unexpected warning flag for %s: got=%t want=%t", tt.state, got.ShowWarning, tt.showWarning)
}
})
}
}
func TestGetBehavior_UnknownState(t *testing.T) {
got := GetBehavior(SubscriptionState("unknown_state"))
expected := StateBehaviors[SubStateExpired]
if got != expected {
t.Fatalf("expected unknown state fallback to expired behavior: got=%+v want=%+v", got, expected)
}
}
func TestDefaultDowngradePolicy(t *testing.T) {
if DefaultDowngradePolicy.SoftHideGraceDays != 30 {
t.Fatalf("unexpected SoftHideGraceDays: got=%d want=30", DefaultDowngradePolicy.SoftHideGraceDays)
}
if DefaultDowngradePolicy.HardDeleteAfterDays != 60 {
t.Fatalf("unexpected HardDeleteAfterDays: got=%d want=60", DefaultDowngradePolicy.HardDeleteAfterDays)
}
}