Skip to content

Commit 645e1ef

Browse files
committed
Validate config path at new SlidingWindowAutoscaler creation
1 parent 04ebd16 commit 645e1ef

File tree

8 files changed

+210
-185
lines changed

8 files changed

+210
-185
lines changed

algorithm/algorithm_test.go

Lines changed: 71 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"time"
2222

2323
"github.com/Fedosin/libkpa/api"
24+
libkpaconfig "github.com/Fedosin/libkpa/config"
2425
)
2526

2627
// mockMetricSnapshot implements api.MetricSnapshot for testing
@@ -36,22 +37,6 @@ func (m *mockMetricSnapshot) PanicValue() float64 { return m.panicValue }
3637
func (m *mockMetricSnapshot) ReadyPodCount() int32 { return m.readyPodCount }
3738
func (m *mockMetricSnapshot) Timestamp() time.Time { return m.timestamp }
3839

39-
// Test fixtures
40-
func defaultConfig() api.AutoscalerConfig {
41-
return api.AutoscalerConfig{
42-
MaxScaleUpRate: 1000.0,
43-
MaxScaleDownRate: 2.0,
44-
TargetValue: 100.0,
45-
PanicThreshold: 2.0, // 200%
46-
PanicWindowPercentage: 10.0,
47-
StableWindow: 60 * time.Second,
48-
ScaleDownDelay: 0,
49-
MinScale: 0,
50-
MaxScale: 0,
51-
ActivationScale: 1,
52-
}
53-
}
54-
5540
// Tests for SlidingWindowAutoscaler
5641
func TestNewSlidingWindowAutoscaler(t *testing.T) {
5742
tests := []struct {
@@ -62,17 +47,20 @@ func TestNewSlidingWindowAutoscaler(t *testing.T) {
6247
{
6348
name: "with scale down delay",
6449
config: func() api.AutoscalerConfig {
65-
c := defaultConfig()
50+
c := libkpaconfig.NewDefaultAutoscalerConfig()
6651
c.ScaleDownDelay = 10 * time.Second
67-
return c
52+
return *c
6853
}(),
6954
wantPanic: false,
7055
},
7156
}
7257

7358
for _, tt := range tests {
7459
t.Run(tt.name, func(t *testing.T) {
75-
autoscaler := NewSlidingWindowAutoscaler(tt.config)
60+
autoscaler, err := NewSlidingWindowAutoscaler(tt.config)
61+
if err != nil {
62+
t.Fatalf("unexpected error: %v", err)
63+
}
7664
if autoscaler == nil {
7765
t.Fatal("expected non-nil autoscaler")
7866
}
@@ -81,7 +69,11 @@ func TestNewSlidingWindowAutoscaler(t *testing.T) {
8169
}
8270

8371
func TestSlidingWindowAutoscaler_Scale_NoData(t *testing.T) {
84-
autoscaler := NewSlidingWindowAutoscaler(defaultConfig())
72+
autoscaler, err := NewSlidingWindowAutoscaler(*libkpaconfig.NewDefaultAutoscalerConfig())
73+
if err != nil {
74+
t.Fatalf("unexpected error: %v", err)
75+
}
76+
8577
now := time.Now()
8678

8779
// Test with negative stable value
@@ -120,7 +112,7 @@ func TestSlidingWindowAutoscaler_Scale_BasicScaling(t *testing.T) {
120112
}{
121113
{
122114
name: "scale up based on stable value",
123-
config: defaultConfig(),
115+
config: *libkpaconfig.NewDefaultAutoscalerConfig(),
124116
snapshot: mockMetricSnapshot{
125117
stableValue: 250, // 2.5x target
126118
panicValue: 250,
@@ -130,7 +122,7 @@ func TestSlidingWindowAutoscaler_Scale_BasicScaling(t *testing.T) {
130122
},
131123
{
132124
name: "scale down based on stable value",
133-
config: defaultConfig(),
125+
config: *libkpaconfig.NewDefaultAutoscalerConfig(),
134126
snapshot: mockMetricSnapshot{
135127
stableValue: 50, // 0.5x target
136128
panicValue: 50,
@@ -141,7 +133,7 @@ func TestSlidingWindowAutoscaler_Scale_BasicScaling(t *testing.T) {
141133
{
142134
name: "respect min scale",
143135
config: func() api.AutoscalerConfig {
144-
c := defaultConfig()
136+
c := *libkpaconfig.NewDefaultAutoscalerConfig()
145137
c.MinScale = 3
146138
return c
147139
}(),
@@ -155,7 +147,7 @@ func TestSlidingWindowAutoscaler_Scale_BasicScaling(t *testing.T) {
155147
{
156148
name: "respect max scale",
157149
config: func() api.AutoscalerConfig {
158-
c := defaultConfig()
150+
c := *libkpaconfig.NewDefaultAutoscalerConfig()
159151
c.MaxScale = 10
160152
return c
161153
}(),
@@ -169,7 +161,7 @@ func TestSlidingWindowAutoscaler_Scale_BasicScaling(t *testing.T) {
169161
{
170162
name: "activation scale",
171163
config: func() api.AutoscalerConfig {
172-
c := defaultConfig()
164+
c := *libkpaconfig.NewDefaultAutoscalerConfig()
173165
c.ActivationScale = 3
174166
return c
175167
}(),
@@ -180,25 +172,10 @@ func TestSlidingWindowAutoscaler_Scale_BasicScaling(t *testing.T) {
180172
},
181173
expectedPodCount: 3, // activation scale
182174
},
183-
{
184-
name: "zero target value",
185-
config: func() api.AutoscalerConfig {
186-
c := defaultConfig()
187-
c.TargetValue = 0
188-
c.MaxScale = 100
189-
return c
190-
}(),
191-
snapshot: mockMetricSnapshot{
192-
stableValue: 50,
193-
panicValue: 50,
194-
readyPodCount: 1,
195-
},
196-
expectedPodCount: -1, // should return invalid recommendation
197-
},
198175
{
199176
name: "total target value - basic scaling",
200177
config: func() api.AutoscalerConfig {
201-
c := defaultConfig()
178+
c := *libkpaconfig.NewDefaultAutoscalerConfig()
202179
c.TargetValue = 0 // Use TotalTargetValue instead
203180
c.TotalTargetValue = 1000.0 // Total across all pods
204181
return c
@@ -213,7 +190,7 @@ func TestSlidingWindowAutoscaler_Scale_BasicScaling(t *testing.T) {
213190
{
214191
name: "total target value - scale down",
215192
config: func() api.AutoscalerConfig {
216-
c := defaultConfig()
193+
c := *libkpaconfig.NewDefaultAutoscalerConfig()
217194
c.TargetValue = 0
218195
c.TotalTargetValue = 1000.0
219196
return c
@@ -228,7 +205,7 @@ func TestSlidingWindowAutoscaler_Scale_BasicScaling(t *testing.T) {
228205
{
229206
name: "total target value with activation scale",
230207
config: func() api.AutoscalerConfig {
231-
c := defaultConfig()
208+
c := *libkpaconfig.NewDefaultAutoscalerConfig()
232209
c.TargetValue = 0
233210
c.TotalTargetValue = 1000.0
234211
c.ActivationScale = 3
@@ -241,26 +218,15 @@ func TestSlidingWindowAutoscaler_Scale_BasicScaling(t *testing.T) {
241218
},
242219
expectedPodCount: 3, // activation scale
243220
},
244-
{
245-
name: "prefer TargetValue over TotalTargetValue",
246-
config: func() api.AutoscalerConfig {
247-
c := defaultConfig()
248-
c.TargetValue = 100.0 // Per-pod target
249-
c.TotalTargetValue = 1000.0 // Should be ignored
250-
return c
251-
}(),
252-
snapshot: mockMetricSnapshot{
253-
stableValue: 250, // 2.5x per-pod target
254-
panicValue: 250,
255-
readyPodCount: 2,
256-
},
257-
expectedPodCount: 3, // ceil(250/100) = 3, not ceil(250/1000)
258-
},
259221
}
260222

261223
for _, tt := range tests {
262224
t.Run(tt.name, func(t *testing.T) {
263-
autoscaler := NewSlidingWindowAutoscaler(tt.config)
225+
autoscaler, err := NewSlidingWindowAutoscaler(tt.config)
226+
if err != nil {
227+
t.Fatalf("unexpected error: %v", err)
228+
}
229+
264230
now := time.Now()
265231
tt.snapshot.timestamp = now
266232

@@ -284,8 +250,12 @@ func TestSlidingWindowAutoscaler_Scale_BasicScaling(t *testing.T) {
284250
}
285251

286252
func TestSlidingWindowAutoscaler_Scale_PanicMode(t *testing.T) {
287-
config := defaultConfig()
288-
autoscaler := NewSlidingWindowAutoscaler(config)
253+
config := *libkpaconfig.NewDefaultAutoscalerConfig()
254+
autoscaler, err := NewSlidingWindowAutoscaler(config)
255+
if err != nil {
256+
t.Fatalf("unexpected error: %v", err)
257+
}
258+
289259
now := time.Now()
290260

291261
// Test entering panic mode
@@ -333,10 +303,14 @@ func TestSlidingWindowAutoscaler_Scale_PanicMode(t *testing.T) {
333303
}
334304

335305
func TestSlidingWindowAutoscaler_Scale_PanicMode_TotalTargetValue(t *testing.T) {
336-
config := defaultConfig()
306+
config := *libkpaconfig.NewDefaultAutoscalerConfig()
337307
config.TargetValue = 0
338308
config.TotalTargetValue = 1000.0
339-
autoscaler := NewSlidingWindowAutoscaler(config)
309+
autoscaler, err := NewSlidingWindowAutoscaler(config)
310+
if err != nil {
311+
t.Fatalf("unexpected error: %v", err)
312+
}
313+
340314
now := time.Now()
341315

342316
// Test entering panic mode with total target value
@@ -357,11 +331,15 @@ func TestSlidingWindowAutoscaler_Scale_PanicMode_TotalTargetValue(t *testing.T)
357331
}
358332

359333
func TestSlidingWindowAutoscaler_Scale_RateLimits(t *testing.T) {
360-
config := defaultConfig()
334+
config := *libkpaconfig.NewDefaultAutoscalerConfig()
361335
config.MaxScaleUpRate = 2.0 // Can double
362336
config.MaxScaleDownRate = 2.0 // Can halve
363337

364-
autoscaler := NewSlidingWindowAutoscaler(config)
338+
autoscaler, err := NewSlidingWindowAutoscaler(config)
339+
if err != nil {
340+
t.Fatalf("unexpected error: %v", err)
341+
}
342+
365343
now := time.Now()
366344

367345
// Test scale up rate limit
@@ -392,14 +370,17 @@ func TestSlidingWindowAutoscaler_Scale_RateLimits(t *testing.T) {
392370
}
393371

394372
func TestSlidingWindowAutoscaler_Update(t *testing.T) {
395-
autoscaler := NewSlidingWindowAutoscaler(defaultConfig())
373+
autoscaler, err := NewSlidingWindowAutoscaler(*libkpaconfig.NewDefaultAutoscalerConfig())
374+
if err != nil {
375+
t.Fatalf("unexpected error: %v", err)
376+
}
396377

397-
newConfig := defaultConfig()
378+
newConfig := *libkpaconfig.NewDefaultAutoscalerConfig()
398379
newConfig.TargetValue = 200
399380
newConfig.MaxScale = 50
400381
newConfig.ScaleDownDelay = 5 * time.Second
401382

402-
err := autoscaler.Update(newConfig)
383+
err = autoscaler.Update(newConfig)
403384
if err != nil {
404385
t.Fatalf("unexpected error: %v", err)
405386
}
@@ -417,10 +398,14 @@ func TestSlidingWindowAutoscaler_Update(t *testing.T) {
417398
}
418399

419400
func TestSlidingWindowAutoscaler_Scale_ScaleToZero(t *testing.T) {
420-
config := defaultConfig()
401+
config := *libkpaconfig.NewDefaultAutoscalerConfig()
421402
config.MinScale = 0
422403

423-
autoscaler := NewSlidingWindowAutoscaler(config)
404+
autoscaler, err := NewSlidingWindowAutoscaler(config)
405+
if err != nil {
406+
t.Fatalf("unexpected error: %v", err)
407+
}
408+
424409
now := time.Now()
425410

426411
// Test scaling to zero with no load
@@ -438,10 +423,14 @@ func TestSlidingWindowAutoscaler_Scale_ScaleToZero(t *testing.T) {
438423
}
439424

440425
func TestSlidingWindowAutoscaler_Scale_ActivationScaleWithZeroMetrics(t *testing.T) {
441-
config := defaultConfig()
426+
config := *libkpaconfig.NewDefaultAutoscalerConfig()
442427
config.ActivationScale = 3
443428

444-
autoscaler := NewSlidingWindowAutoscaler(config)
429+
autoscaler, err := NewSlidingWindowAutoscaler(config)
430+
if err != nil {
431+
t.Fatalf("unexpected error: %v", err)
432+
}
433+
445434
now := time.Now()
446435

447436
// Test that activation scale doesn't apply when metrics are zero
@@ -459,7 +448,11 @@ func TestSlidingWindowAutoscaler_Scale_ActivationScaleWithZeroMetrics(t *testing
459448
}
460449

461450
func TestSlidingWindowAutoscaler_Scale_ReadyPodCountZero(t *testing.T) {
462-
autoscaler := NewSlidingWindowAutoscaler(defaultConfig())
451+
autoscaler, err := NewSlidingWindowAutoscaler(*libkpaconfig.NewDefaultAutoscalerConfig())
452+
if err != nil {
453+
t.Fatalf("unexpected error: %v", err)
454+
}
455+
463456
now := time.Now()
464457

465458
// Test with zero ready pods (should default to 1 to avoid division by zero)
@@ -482,7 +475,7 @@ func TestSlidingWindowAutoscaler_Scale_ReadyPodCountZero(t *testing.T) {
482475

483476
// Tests for PanicModeCalculator
484477
func TestNewPanicModeCalculator(t *testing.T) {
485-
config := defaultConfig()
478+
config := *libkpaconfig.NewDefaultAutoscalerConfig()
486479
calculator := NewPanicModeCalculator(&config)
487480

488481
if calculator == nil {
@@ -528,7 +521,7 @@ func TestPanicModeCalculator_CalculatePanicWindow(t *testing.T) {
528521

529522
for _, tt := range tests {
530523
t.Run(tt.name, func(t *testing.T) {
531-
config := defaultConfig()
524+
config := *libkpaconfig.NewDefaultAutoscalerConfig()
532525
config.StableWindow = tt.stableWindow
533526
config.PanicWindowPercentage = tt.panicPercent
534527

@@ -543,7 +536,7 @@ func TestPanicModeCalculator_CalculatePanicWindow(t *testing.T) {
543536
}
544537

545538
func TestPanicModeCalculator_ShouldEnterPanicMode(t *testing.T) {
546-
config := defaultConfig()
539+
config := *libkpaconfig.NewDefaultAutoscalerConfig()
547540
config.PanicThreshold = 2.0 // 200%
548541
calculator := NewPanicModeCalculator(&config)
549542

@@ -590,7 +583,7 @@ func TestPanicModeCalculator_ShouldEnterPanicMode(t *testing.T) {
590583
}
591584

592585
func TestPanicModeCalculator_ShouldExitPanicMode(t *testing.T) {
593-
config := defaultConfig()
586+
config := *libkpaconfig.NewDefaultAutoscalerConfig()
594587
config.StableWindow = 60 * time.Second
595588
calculator := NewPanicModeCalculator(&config)
596589

@@ -638,7 +631,7 @@ func TestPanicModeCalculator_ShouldExitPanicMode(t *testing.T) {
638631
}
639632

640633
func TestPanicModeCalculator_CalculateDesiredPods(t *testing.T) {
641-
config := defaultConfig()
634+
config := *libkpaconfig.NewDefaultAutoscalerConfig()
642635
calculator := NewPanicModeCalculator(&config)
643636

644637
tests := []struct {

0 commit comments

Comments
 (0)