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

384 lines
8.8 KiB
Go

package licensing
import (
"testing"
)
type mockSource struct {
capabilities []string
limits map[string]int64
metersEnabled []string
planVersion string
subState SubscriptionState
trialStarted *int64
trialEnds *int64
}
func (m mockSource) Capabilities() []string { return m.capabilities }
func (m mockSource) Limits() map[string]int64 { return m.limits }
func (m mockSource) MetersEnabled() []string { return m.metersEnabled }
func (m mockSource) PlanVersion() string { return m.planVersion }
func (m mockSource) SubscriptionState() SubscriptionState { return m.subState }
func (m mockSource) TrialStartedAt() *int64 { return m.trialStarted }
func (m mockSource) TrialEndsAt() *int64 { return m.trialEnds }
func (m mockSource) OverflowGrantedAt() *int64 { return nil }
func TestEvaluator_HasCapability(t *testing.T) {
tests := []struct {
name string
source mockSource
key string
want bool
}{
{
name: "nil_evaluator_returns_false",
source: mockSource{},
key: "feature",
want: false,
},
{
name: "nil_source_returns_false",
source: mockSource{},
key: "feature",
want: false,
},
{
name: "finds_capability",
source: mockSource{capabilities: []string{"feature_a", "feature_b"}},
key: "feature_a",
want: true,
},
{
name: "missing_capability_returns_false",
source: mockSource{capabilities: []string{"feature_a"}},
key: "feature_b",
want: false,
},
{
name: "empty_capabilities_returns_false",
source: mockSource{capabilities: []string{}},
key: "feature_a",
want: false,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
e := NewEvaluator(tt.source)
got := e.HasCapability(tt.key)
if got != tt.want {
t.Errorf("HasCapability(%q) = %v, want %v", tt.key, got, tt.want)
}
})
}
}
func TestEvaluator_GetLimit(t *testing.T) {
tests := []struct {
name string
source mockSource
key string
wantValue int64
wantExists bool
}{
{
name: "nil_evaluator_returns_false",
source: mockSource{},
key: "max_monitored_systems",
wantValue: 0,
wantExists: false,
},
{
name: "finds_limit",
source: mockSource{limits: map[string]int64{"max_monitored_systems": 100}},
key: "max_monitored_systems",
wantValue: 100,
wantExists: true,
},
{
name: "missing_limit_returns_false",
source: mockSource{limits: map[string]int64{"max_monitored_systems": 100}},
key: "max_guests",
wantValue: 0,
wantExists: false,
},
{
name: "zero_limit_exists",
source: mockSource{limits: map[string]int64{"max_monitored_systems": 0}},
key: "max_monitored_systems",
wantValue: 0,
wantExists: true,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
e := NewEvaluator(tt.source)
gotVal, gotExists := e.GetLimit(tt.key)
if gotVal != tt.wantValue {
t.Errorf("GetLimit(%q).value = %v, want %v", tt.key, gotVal, tt.wantValue)
}
if gotExists != tt.wantExists {
t.Errorf("GetLimit(%q).exists = %v, want %v", tt.key, gotExists, tt.wantExists)
}
})
}
}
func TestEvaluator_CheckLimit(t *testing.T) {
source := mockSource{limits: map[string]int64{"max_monitored_systems": 100}}
e := NewEvaluator(source)
tests := []struct {
name string
key string
observed int64
want LimitCheckResult
}{
{
name: "well_under_limit",
key: "max_monitored_systems",
observed: 50,
want: LimitAllowed,
},
{
name: "at_90_percent",
key: "max_monitored_systems",
observed: 90,
want: LimitSoftBlock,
},
{
name: "at_limit",
key: "max_monitored_systems",
observed: 100,
want: LimitHardBlock,
},
{
name: "over_limit",
key: "max_monitored_systems",
observed: 150,
want: LimitHardBlock,
},
{
name: "undefined_limit_allows",
key: "max_guests",
observed: 1000,
want: LimitAllowed,
},
{
name: "zero_limit_allows",
key: "max_monitored_systems",
observed: 0,
want: LimitAllowed,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
got := e.CheckLimit(tt.key, tt.observed)
if got != tt.want {
t.Errorf("CheckLimit(%q, %d) = %v, want %v", tt.key, tt.observed, got, tt.want)
}
})
}
}
func TestEvaluator_MeterEnabled(t *testing.T) {
tests := []struct {
name string
source mockSource
key string
want bool
}{
{
name: "nil_source_returns_false",
source: mockSource{},
key: "meter_a",
want: false,
},
{
name: "finds_enabled_meter",
source: mockSource{metersEnabled: []string{"meter_a", "meter_b"}},
key: "meter_a",
want: true,
},
{
name: "missing_meter_returns_false",
source: mockSource{metersEnabled: []string{"meter_a"}},
key: "meter_b",
want: false,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
e := NewEvaluator(tt.source)
got := e.MeterEnabled(tt.key)
if got != tt.want {
t.Errorf("MeterEnabled(%q) = %v, want %v", tt.key, got, tt.want)
}
})
}
}
func TestEvaluator_PlanVersion(t *testing.T) {
tests := []struct {
name string
source mockSource
want string
}{
{
name: "nil_source_returns_empty",
source: mockSource{},
want: "",
},
{
name: "returns_plan_version",
source: mockSource{planVersion: "v2"},
want: "v2",
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
e := NewEvaluator(tt.source)
got := e.PlanVersion()
if got != tt.want {
t.Errorf("PlanVersion() = %v, want %v", got, tt.want)
}
})
}
}
func TestEvaluator_SubscriptionState(t *testing.T) {
tests := []struct {
name string
source mockSource
want SubscriptionState
}{
{
name: "empty_source_returns_empty",
source: mockSource{subState: ""},
want: "",
},
{
name: "returns_subscription_state",
source: mockSource{subState: SubStateGrace},
want: SubStateGrace,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
e := NewEvaluator(tt.source)
got := e.SubscriptionState()
if got != tt.want {
t.Errorf("SubscriptionState() = %v, want %v", got, tt.want)
}
})
}
}
func TestEvaluator_NilSource_ReturnsDefaults(t *testing.T) {
var e *Evaluator
if got := e.HasCapability("feature"); got != false {
t.Errorf("HasCapability() on nil = %v, want false", got)
}
if got, _ := e.GetLimit("max_monitored_systems"); got != 0 {
t.Errorf("GetLimit() on nil = %v, want 0", got)
}
if got := e.CheckLimit("max_monitored_systems", 50); got != LimitAllowed {
t.Errorf("CheckLimit() on nil = %v, want LimitAllowed", got)
}
if got := e.MeterEnabled("meter"); got != false {
t.Errorf("MeterEnabled() on nil = %v, want false", got)
}
if got := e.PlanVersion(); got != "" {
t.Errorf("PlanVersion() on nil = %v, want empty", got)
}
if got := e.SubscriptionState(); got != SubStateActive {
t.Errorf("SubscriptionState() on nil = %v, want SubStateActive", got)
}
if got := e.TrialStartedAt(); got != nil {
t.Errorf("TrialStartedAt() on nil = %v, want nil", got)
}
if got := e.TrialEndsAt(); got != nil {
t.Errorf("TrialEndsAt() on nil = %v, want nil", got)
}
}
func TestEvaluator_TrialStartedAt(t *testing.T) {
ts := int64(1700000000)
tests := []struct {
name string
source mockSource
want *int64
}{
{
name: "nil_source_returns_nil",
source: mockSource{},
want: nil,
},
{
name: "returns_trial_started",
source: mockSource{trialStarted: &ts},
want: &ts,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
e := NewEvaluator(tt.source)
got := e.TrialStartedAt()
if (got == nil) != (tt.want == nil) {
t.Errorf("TrialStartedAt() = %v, want %v", got, tt.want)
return
}
if got != nil && *got != *tt.want {
t.Errorf("TrialStartedAt() = %v, want %v", *got, *tt.want)
}
})
}
}
func TestEvaluator_TrialEndsAt(t *testing.T) {
ts := int64(1700000000)
tests := []struct {
name string
source mockSource
want *int64
}{
{
name: "nil_source_returns_nil",
source: mockSource{},
want: nil,
},
{
name: "returns_trial_ends",
source: mockSource{trialEnds: &ts},
want: &ts,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
e := NewEvaluator(tt.source)
got := e.TrialEndsAt()
if (got == nil) != (tt.want == nil) {
t.Errorf("TrialEndsAt() = %v, want %v", got, tt.want)
return
}
if got != nil && *got != *tt.want {
t.Errorf("TrialEndsAt() = %v, want %v", *got, *tt.want)
}
})
}
}