github.com/kubewharf/katalyst-core@v0.5.3/pkg/util/general/window_test.go (about) 1 /* 2 Copyright 2022 The Katalyst Authors. 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 general 18 19 import ( 20 "testing" 21 "time" 22 23 "github.com/stretchr/testify/assert" 24 "github.com/stretchr/testify/require" 25 "k8s.io/apimachinery/pkg/api/resource" 26 ) 27 28 func TestNewCappedSmoothWindow(t *testing.T) { 29 t.Parallel() 30 31 type args struct { 32 minStep resource.Quantity 33 maxStep resource.Quantity 34 smoothWindow SmoothWindow 35 } 36 tests := []struct { 37 name string 38 args args 39 }{ 40 { 41 name: "test-cpu", 42 args: args{ 43 minStep: resource.MustParse("0.3"), 44 maxStep: resource.MustParse("4"), 45 smoothWindow: NewAggregatorSmoothWindow(SmoothWindowOpts{WindowSize: 5, TTL: 100 * time.Millisecond, UsedMillValue: true, AggregateFunc: SmoothWindowAggFuncAvg}), 46 }, 47 }, 48 { 49 name: "test-memory", 50 args: args{ 51 minStep: resource.MustParse("300Mi"), 52 maxStep: resource.MustParse("5Gi"), 53 smoothWindow: NewAggregatorSmoothWindow(SmoothWindowOpts{WindowSize: 5, TTL: 100 * time.Millisecond, UsedMillValue: false, AggregateFunc: SmoothWindowAggFuncAvg}), 54 }, 55 }, 56 } 57 for _, tt := range tests { 58 tt := tt 59 t.Run(tt.name, func(t *testing.T) { 60 t.Parallel() 61 NewCappedSmoothWindow(tt.args.minStep, tt.args.maxStep, tt.args.smoothWindow) 62 }) 63 } 64 } 65 66 func TestCappedSmoothWindow_GetWindowedResources(t *testing.T) { 67 t.Parallel() 68 69 w := NewCappedSmoothWindow( 70 resource.MustParse("0.3"), 71 resource.MustParse("4"), 72 NewAggregatorSmoothWindow(SmoothWindowOpts{WindowSize: 3, TTL: 100 * time.Millisecond, UsedMillValue: true, AggregateFunc: SmoothWindowAggFuncAvg}), 73 ) 74 75 time.Sleep(10 * time.Millisecond) 76 v := w.GetWindowedResources(resource.MustParse("0.6")) 77 require.Nil(t, v) 78 79 time.Sleep(10 * time.Millisecond) 80 v = w.GetWindowedResources(resource.MustParse("0.8")) 81 require.Nil(t, v) 82 83 time.Sleep(10 * time.Millisecond) 84 v = w.GetWindowedResources(resource.MustParse("0.4")) 85 require.NotNil(t, v) 86 require.Zero(t, v.Cmp(resource.MustParse("0.6"))) 87 88 time.Sleep(10 * time.Millisecond) 89 v = w.GetWindowedResources(resource.MustParse("1.2")) 90 require.NotNil(t, v) 91 require.True(t, resource.MustParse("0.6").Equal(*v)) 92 93 time.Sleep(10 * time.Millisecond) 94 v = w.GetWindowedResources(resource.MustParse("1.4")) 95 require.NotNil(t, v) 96 require.Equal(t, int64(1000), v.MilliValue()) 97 98 time.Sleep(10 * time.Millisecond) 99 v = w.GetWindowedResources(resource.MustParse("15")) 100 require.NotNil(t, v) 101 require.Equal(t, int64(5000), v.MilliValue()) 102 103 time.Sleep(90 * time.Millisecond) 104 v = w.GetWindowedResources(resource.MustParse("0")) 105 require.NotNil(t, v) 106 require.Equal(t, int64(5000), v.MilliValue()) 107 108 time.Sleep(10 * time.Millisecond) 109 v = w.GetWindowedResources(resource.MustParse("0")) 110 require.NotNil(t, v) 111 require.Equal(t, int64(5000), v.MilliValue()) 112 113 time.Sleep(30 * time.Millisecond) 114 v = w.GetWindowedResources(resource.MustParse("0")) 115 require.NotNil(t, v) 116 require.Equal(t, int64(1000), v.MilliValue()) 117 } 118 119 func TestPercentileWithTTLSmoothWindow(t *testing.T) { 120 t.Parallel() 121 122 type args struct { 123 windowSize int 124 ttl time.Duration 125 percentile float64 126 values []resource.Quantity 127 } 128 tests := []struct { 129 name string 130 args args 131 wantValues []resource.Quantity 132 }{ 133 { 134 name: "p100(max)", 135 args: args{ 136 windowSize: 5, 137 ttl: 1 * time.Second, 138 percentile: 100, 139 values: []resource.Quantity{ 140 resource.MustParse("1"), 141 resource.MustParse("2"), 142 resource.MustParse("1.5"), 143 resource.MustParse("3"), 144 resource.MustParse("2"), 145 resource.MustParse("6"), 146 resource.MustParse("5"), 147 resource.MustParse("1"), 148 resource.MustParse("1"), 149 resource.MustParse("1"), 150 resource.MustParse("1"), 151 resource.MustParse("1"), 152 }, 153 }, 154 wantValues: []resource.Quantity{ 155 resource.MustParse("0"), 156 resource.MustParse("0"), 157 resource.MustParse("0"), 158 resource.MustParse("0"), 159 resource.MustParse("3"), 160 resource.MustParse("6"), 161 resource.MustParse("6"), 162 resource.MustParse("6"), 163 resource.MustParse("6"), 164 resource.MustParse("6"), 165 resource.MustParse("5"), 166 resource.MustParse("1"), 167 }, 168 }, 169 { 170 name: "p0(min)", 171 args: args{ 172 windowSize: 5, 173 ttl: 1 * time.Second, 174 percentile: 0.0, 175 values: []resource.Quantity{ 176 resource.MustParse("1"), 177 resource.MustParse("2"), 178 resource.MustParse("1.5"), 179 resource.MustParse("3"), 180 resource.MustParse("2"), 181 resource.MustParse("6"), 182 resource.MustParse("5"), 183 resource.MustParse("1"), 184 resource.MustParse("1"), 185 resource.MustParse("1"), 186 resource.MustParse("1"), 187 resource.MustParse("1"), 188 }, 189 }, 190 wantValues: []resource.Quantity{ 191 resource.MustParse("0"), 192 resource.MustParse("0"), 193 resource.MustParse("0"), 194 resource.MustParse("0"), 195 resource.MustParse("1"), 196 resource.MustParse("1.5"), 197 resource.MustParse("1.5"), 198 resource.MustParse("1"), 199 resource.MustParse("1"), 200 resource.MustParse("1"), 201 resource.MustParse("1"), 202 resource.MustParse("1"), 203 }, 204 }, 205 { 206 name: "p20", 207 args: args{ 208 windowSize: 10, 209 ttl: 111111 * time.Second, 210 percentile: 20, 211 values: []resource.Quantity{ 212 resource.MustParse("1"), 213 resource.MustParse("2"), 214 resource.MustParse("3"), 215 resource.MustParse("4"), 216 resource.MustParse("5"), 217 resource.MustParse("6"), 218 resource.MustParse("7"), 219 resource.MustParse("8"), 220 resource.MustParse("9"), 221 resource.MustParse("10"), 222 resource.MustParse("11"), 223 resource.MustParse("12"), 224 }, 225 }, 226 wantValues: []resource.Quantity{ 227 resource.MustParse("0"), 228 resource.MustParse("0"), 229 resource.MustParse("0"), 230 resource.MustParse("0"), 231 resource.MustParse("0"), 232 resource.MustParse("0"), 233 resource.MustParse("0"), 234 resource.MustParse("0"), 235 resource.MustParse("0"), 236 resource.MustParse("2"), 237 resource.MustParse("3"), 238 resource.MustParse("4"), 239 }, 240 }, 241 } 242 for _, tt := range tests { 243 tt := tt 244 t.Run(tt.name, func(t *testing.T) { 245 t.Parallel() 246 w := NewPercentileWithTTLSmoothWindow(tt.args.windowSize, tt.args.ttl, tt.args.percentile, true) 247 for i, v := range tt.args.values { 248 ret := w.GetWindowedResources(v) 249 if ret == nil { 250 require.Equal(t, tt.wantValues[i].MilliValue(), int64(0)) 251 } else { 252 require.Equal(t, tt.wantValues[i].MilliValue(), ret.MilliValue()) 253 } 254 } 255 }) 256 } 257 } 258 259 func TestWindowEmpty(t *testing.T) { 260 t.Parallel() 261 262 type args struct { 263 windowSize int 264 ttl time.Duration 265 percentile float64 266 samples []*sample 267 } 268 tests := []struct { 269 name string 270 args args 271 want bool 272 }{ 273 { 274 name: "empty", 275 args: args{ 276 windowSize: 10, 277 ttl: 111111 * time.Second, 278 percentile: 20, 279 samples: []*sample{}, 280 }, 281 want: true, 282 }, 283 { 284 name: "samples all expired", 285 args: args{ 286 windowSize: 10, 287 ttl: 111111 * time.Second, 288 percentile: 20, 289 samples: []*sample{ 290 { 291 resource.MustParse("1"), 292 time.Date(2000, 0, 0, 0, 0, 0, 0, time.UTC), 293 }, 294 }, 295 }, 296 want: true, 297 }, 298 { 299 name: "have valid sample", 300 args: args{ 301 windowSize: 10, 302 ttl: 111111 * time.Second, 303 percentile: 20, 304 samples: []*sample{ 305 { 306 resource.MustParse("1"), 307 time.Now(), 308 }, 309 }, 310 }, 311 want: false, 312 }, 313 } 314 for _, tt := range tests { 315 tt := tt 316 t.Run(tt.name, func(t *testing.T) { 317 t.Parallel() 318 319 w := NewPercentileWithTTLSmoothWindow(tt.args.windowSize, tt.args.ttl, tt.args.percentile, true) 320 window := w.(*percentileWithTTLSmoothWindow) 321 window.samples = tt.args.samples 322 323 assert.Equal(t, tt.want, window.Empty()) 324 window.Empty() 325 }) 326 } 327 }