Skip to content

Commit 213eef2

Browse files
committed
added unit tests for apa autoscaling
1 parent b712186 commit 213eef2

File tree

1 file changed

+181
-0
lines changed

1 file changed

+181
-0
lines changed
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
/*
2+
Copyright 2024 The Aibrix Team.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package algorithm
18+
19+
import (
20+
"testing"
21+
22+
"github.com/vllm-project/aibrix/pkg/controller/podautoscaler/common"
23+
)
24+
25+
func TestApaScalingAlgorithm_ComputeTargetReplicas(t *testing.T) {
26+
algorithm := &ApaScalingAlgorithm{}
27+
28+
tests := []struct {
29+
name string
30+
currentPodCount float64
31+
context *common.MockScalingContext
32+
expected int32
33+
description string
34+
}{
35+
{
36+
name: "no_scaling_within_tolerance",
37+
currentPodCount: 3.0,
38+
context: &common.MockScalingContext{
39+
TargetValue: 50.0,
40+
UpFluctuationTolerance: 0.1, // 10% tolerance
41+
DownFluctuationTolerance: 0.2, // 20% tolerance
42+
MaxScaleUpRate: 2.0, // Can scale up by 100%
43+
MaxScaleDownRate: 2.0, // Can scale down by 50%
44+
CurrentUsePerPod: 50.0, // Exactly at target
45+
MinReplicas: 1,
46+
MaxReplicas: 10,
47+
},
48+
expected: 3,
49+
description: "Should not scale when current use per pod equals target value",
50+
},
51+
{
52+
name: "no_scaling_within_up_tolerance",
53+
currentPodCount: 3.0,
54+
context: &common.MockScalingContext{
55+
TargetValue: 50.0,
56+
UpFluctuationTolerance: 0.1, // 10% tolerance
57+
DownFluctuationTolerance: 0.2, // 20% tolerance
58+
MaxScaleUpRate: 2.0,
59+
MaxScaleDownRate: 2.0,
60+
CurrentUsePerPod: 54.0, // 54/50 = 1.08, within 1+0.1=1.1 tolerance
61+
MinReplicas: 1,
62+
MaxReplicas: 10,
63+
},
64+
expected: 3,
65+
description: "Should not scale when within up tolerance (8% above target)",
66+
},
67+
{
68+
name: "no_scaling_within_down_tolerance",
69+
currentPodCount: 3.0,
70+
context: &common.MockScalingContext{
71+
TargetValue: 50.0,
72+
UpFluctuationTolerance: 0.1, // 10% tolerance
73+
DownFluctuationTolerance: 0.2, // 20% tolerance
74+
MaxScaleUpRate: 2.0,
75+
MaxScaleDownRate: 2.0,
76+
CurrentUsePerPod: 42.0, // 42/50 = 0.84, within 1-0.2=0.8 tolerance
77+
MinReplicas: 1,
78+
MaxReplicas: 10,
79+
},
80+
expected: 3,
81+
description: "Should not scale when within down tolerance (16% below target)",
82+
},
83+
{
84+
name: "scale_up_beyond_tolerance",
85+
currentPodCount: 3.0,
86+
context: &common.MockScalingContext{
87+
TargetValue: 50.0,
88+
UpFluctuationTolerance: 0.1, // 10% tolerance
89+
DownFluctuationTolerance: 0.2, // 20% tolerance
90+
MaxScaleUpRate: 2.0, // Can scale up by 100%
91+
MaxScaleDownRate: 2.0,
92+
CurrentUsePerPod: 60.0, // 60/50 = 1.2, exceeds 1+0.1=1.1 tolerance
93+
MinReplicas: 1,
94+
MaxReplicas: 10,
95+
},
96+
expected: 4, // ceil(3 * (60/50)) = ceil(3.6) = 4
97+
description: "Should scale up when current use exceeds up tolerance threshold",
98+
},
99+
{
100+
name: "scale_down_beyond_tolerance",
101+
currentPodCount: 5.0,
102+
context: &common.MockScalingContext{
103+
TargetValue: 50.0,
104+
UpFluctuationTolerance: 0.1, // 10% tolerance
105+
DownFluctuationTolerance: 0.2, // 20% tolerance
106+
MaxScaleUpRate: 2.0,
107+
MaxScaleDownRate: 2.0, // Can scale down by 50%
108+
CurrentUsePerPod: 30.0, // 30/50 = 0.6, below 1-0.2=0.8 tolerance
109+
MinReplicas: 1,
110+
MaxReplicas: 10,
111+
},
112+
expected: 3, // ceil(5 * (30/50)) = ceil(3.0) = 3
113+
description: "Should scale down when current use falls below down tolerance threshold",
114+
},
115+
{
116+
name: "scale_up_limited_by_max_scale_up_rate",
117+
currentPodCount: 3.0,
118+
context: &common.MockScalingContext{
119+
TargetValue: 50.0,
120+
UpFluctuationTolerance: 0.1, // 10% tolerance
121+
DownFluctuationTolerance: 0.2, // 20% tolerance
122+
MaxScaleUpRate: 1.5, // Can only scale up by 50%
123+
MaxScaleDownRate: 2.0,
124+
CurrentUsePerPod: 100.0, // 100/50 = 2.0, would need 6 pods but limited
125+
MinReplicas: 1,
126+
MaxReplicas: 10,
127+
},
128+
expected: 5, // ceil(1.5 * 3) = ceil(4.5) = 5 (limited by max scale up rate)
129+
description: "Should be limited by max scale up rate",
130+
},
131+
{
132+
name: "scale_down_limited_by_max_scale_down_rate",
133+
currentPodCount: 6.0,
134+
context: &common.MockScalingContext{
135+
TargetValue: 50.0,
136+
UpFluctuationTolerance: 0.1, // 10% tolerance
137+
DownFluctuationTolerance: 0.2, // 20% tolerance
138+
MaxScaleUpRate: 2.0,
139+
MaxScaleDownRate: 3.0, // Can scale down to 1/3 = 33% of current (6/3=2 minimum)
140+
CurrentUsePerPod: 10.0, // 10/50 = 0.2, would need 1.2 pods but limited
141+
MinReplicas: 1,
142+
MaxReplicas: 10,
143+
},
144+
expected: 2, // floor(6/3) = floor(2) = 2
145+
description: "Should be limited by max scale down rate",
146+
},
147+
{
148+
name: "extreme_scale_up_case",
149+
currentPodCount: 2.0,
150+
context: &common.MockScalingContext{
151+
TargetValue: 10.0,
152+
UpFluctuationTolerance: 0.1, // 10% tolerance
153+
DownFluctuationTolerance: 0.2, // 20% tolerance
154+
MaxScaleUpRate: 3.0, // Can scale up by 200%
155+
MaxScaleDownRate: 2.0,
156+
CurrentUsePerPod: 50.0, // 50/10 = 5.0, would need 10 pods
157+
MinReplicas: 1,
158+
MaxReplicas: 20,
159+
},
160+
expected: 6, // ceil(3.0 * 2) = 6 (limited by max scale up rate)
161+
description: "Should handle extreme scale up scenarios with rate limiting",
162+
},
163+
}
164+
165+
for _, tt := range tests {
166+
t.Run(tt.name, func(t *testing.T) {
167+
result := algorithm.ComputeTargetReplicas(tt.currentPodCount, tt.context)
168+
if result != tt.expected {
169+
t.Errorf("ComputeTargetReplicas() = %d, expected %d. %s", result, tt.expected, tt.description)
170+
t.Logf("Current pod count: %.1f", tt.currentPodCount)
171+
t.Logf("Current use per pod: %.1f", tt.context.CurrentUsePerPod)
172+
t.Logf("Target value: %.1f", tt.context.TargetValue)
173+
t.Logf("Up tolerance: %.3f", tt.context.UpFluctuationTolerance)
174+
t.Logf("Down tolerance: %.3f", tt.context.DownFluctuationTolerance)
175+
t.Logf("Ratio (current/expected): %.6f", tt.context.CurrentUsePerPod/tt.context.TargetValue)
176+
t.Logf("Up threshold: %.6f", 1+tt.context.UpFluctuationTolerance)
177+
t.Logf("Down threshold: %.6f", 1-tt.context.DownFluctuationTolerance)
178+
}
179+
})
180+
}
181+
}

0 commit comments

Comments
 (0)