github.com/alibaba/sentinel-golang@v1.0.4/core/stat/base/leap_array_test.go (about) 1 // Copyright 1999-2020 Alibaba Group Holding Ltd. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package base 16 17 import ( 18 "reflect" 19 "sync/atomic" 20 "testing" 21 "unsafe" 22 23 "github.com/alibaba/sentinel-golang/util" 24 "github.com/stretchr/testify/assert" 25 "github.com/stretchr/testify/mock" 26 ) 27 28 const ( 29 // timespan of per slot 30 BucketLengthInMs uint32 = 500 31 // the number of slots 32 SampleCount uint32 = 20 33 // interval(ms) of sliding window, 10s 34 IntervalInMs uint32 = 10 * 1000 35 ) 36 37 func Test_bucketWrapper_Size(t *testing.T) { 38 ww := &BucketWrap{ 39 BucketStart: util.CurrentTimeMillis(), 40 Value: atomic.Value{}, 41 } 42 if unsafe.Sizeof(*ww) != 24 { 43 t.Errorf("the size of BucketWrap is not equal 24.\n") 44 } 45 if unsafe.Sizeof(ww) != 8 { 46 t.Errorf("the size of BucketWrap pointer is not equal 8.\n") 47 } 48 } 49 50 // mock ArrayMock and implement BucketGenerator 51 type leapArrayMock struct { 52 mock.Mock 53 } 54 55 func (bla *leapArrayMock) NewEmptyBucket() interface{} { 56 return new(int64) 57 } 58 59 func (bla *leapArrayMock) ResetBucketTo(ww *BucketWrap, startTime uint64) *BucketWrap { 60 ww.BucketStart = startTime 61 ww.Value.Store(new(int64)) 62 return ww 63 } 64 65 func Test_leapArray_calculateTimeIdx_normal(t *testing.T) { 66 type fields struct { 67 bucketLengthInMs uint32 68 sampleCount uint32 69 intervalInMs uint32 70 array *AtomicBucketWrapArray 71 } 72 type args struct { 73 timeMillis uint64 74 } 75 tests := []struct { 76 name string 77 fields fields 78 args args 79 want int 80 }{ 81 { 82 name: "Test_leapArray_calculateTimeIdx_normal", 83 fields: fields{ 84 bucketLengthInMs: BucketLengthInMs, 85 sampleCount: SampleCount, 86 intervalInMs: IntervalInMs, 87 array: NewAtomicBucketWrapArray(int(SampleCount), BucketLengthInMs, &leapArrayMock{}), 88 }, 89 args: args{ 90 timeMillis: 1576296044907, 91 }, 92 want: 9, 93 }, 94 } 95 for _, tt := range tests { 96 t.Run(tt.name, func(t *testing.T) { 97 la := &LeapArray{ 98 bucketLengthInMs: tt.fields.bucketLengthInMs, 99 sampleCount: tt.fields.sampleCount, 100 intervalInMs: tt.fields.intervalInMs, 101 array: tt.fields.array, 102 updateLock: mutex{}, 103 } 104 if got := la.calculateTimeIdx(tt.args.timeMillis); got != tt.want { 105 t.Errorf("LeapArray.calculateTimeIdx() = %v, want %v", got, tt.want) 106 } 107 }) 108 } 109 } 110 111 func Test_calculateStartTime_normal(t *testing.T) { 112 type fields struct { 113 } 114 type args struct { 115 timeMillis uint64 116 bucketLengthInMs uint32 117 } 118 tests := []struct { 119 name string 120 fields fields 121 args args 122 want uint64 123 }{ 124 { 125 name: "Test_calculateStartTime_normal", 126 fields: fields{}, 127 args: args{ 128 timeMillis: 1576296044907, 129 bucketLengthInMs: BucketLengthInMs, 130 }, 131 want: 1576296044500, 132 }, 133 } 134 for _, tt := range tests { 135 t.Run(tt.name, func(t *testing.T) { 136 if got := calculateStartTime(tt.args.timeMillis, tt.args.bucketLengthInMs); got != tt.want { 137 t.Errorf("LeapArray.calculateStartTime() = %v, want %v", got, tt.want) 138 } 139 }) 140 } 141 } 142 143 func Test_leapArray_BucketStartCheck_normal(t *testing.T) { 144 now := uint64(1596199310000) 145 la := &LeapArray{ 146 bucketLengthInMs: BucketLengthInMs, 147 sampleCount: SampleCount, 148 intervalInMs: IntervalInMs, 149 array: NewAtomicBucketWrapArrayWithTime(int(SampleCount), BucketLengthInMs, now, &leapArrayMock{}), 150 updateLock: mutex{}, 151 } 152 got, err := la.currentBucketOfTime(now+801, new(leapArrayMock)) 153 if err != nil { 154 t.Errorf("LeapArray.currentBucketOfTime() error = %v\n", err) 155 return 156 } 157 if got.BucketStart != now+500 { 158 t.Errorf("BucketStart = %v, want %v", got.BucketStart, now+500) 159 } 160 if !reflect.DeepEqual(got, la.array.get(1)) { 161 t.Errorf("LeapArray.currentBucketOfTime() = %v, want %v", got, la.array.get(1)) 162 } 163 } 164 165 func Test_leapArray_valuesWithTime_normal(t *testing.T) { 166 type fields struct { 167 bucketLengthInMs uint32 168 sampleCount uint32 169 intervalInMs uint32 170 array *AtomicBucketWrapArray 171 } 172 type args struct { 173 timeMillis uint64 174 } 175 tests := []struct { 176 name string 177 fields fields 178 args args 179 want *BucketWrap 180 wantErr bool 181 }{ 182 { 183 name: "Test_leapArray_valuesWithTime_normal", 184 fields: fields{ 185 bucketLengthInMs: BucketLengthInMs, 186 sampleCount: SampleCount, 187 intervalInMs: IntervalInMs, 188 array: NewAtomicBucketWrapArrayWithTime(int(SampleCount), BucketLengthInMs, uint64(1596199310000), &leapArrayMock{}), 189 }, 190 args: args{ 191 timeMillis: 1576296049907, 192 }, 193 want: nil, 194 wantErr: false, 195 }, 196 } 197 // override start time 198 start := uint64(1576296040000) 199 for idx := 0; idx < tests[0].fields.array.length; idx++ { 200 ww := tests[0].fields.array.get(idx) 201 ww.BucketStart = start 202 start += 500 203 } 204 205 for _, tt := range tests { 206 t.Run(tt.name, func(t *testing.T) { 207 la := &LeapArray{ 208 bucketLengthInMs: tt.fields.bucketLengthInMs, 209 sampleCount: tt.fields.sampleCount, 210 intervalInMs: tt.fields.intervalInMs, 211 array: tt.fields.array, 212 updateLock: mutex{}, 213 } 214 got := la.valuesWithTime(tt.args.timeMillis) 215 for _, g := range got { 216 find := false 217 for i := 0; i < tests[0].fields.array.length; i++ { 218 w := tests[0].fields.array.get(i) 219 if w.BucketStart == g.BucketStart { 220 find = true 221 break 222 } 223 } 224 if !find { 225 t.Errorf("LeapArray.valuesWithTime() fail") 226 } 227 } 228 }) 229 } 230 } 231 232 func Test_leapArray_isBucketDeprecated_normal(t *testing.T) { 233 type fields struct { 234 bucketLengthInMs uint32 235 sampleCount uint32 236 intervalInMs uint32 237 array *AtomicBucketWrapArray 238 } 239 type args struct { 240 startTime uint64 241 ww *BucketWrap 242 } 243 tests := []struct { 244 name string 245 fields fields 246 args args 247 want bool 248 }{ 249 { 250 name: "Test_leapArray_isBucketDeprecated_normal", 251 fields: fields{ 252 bucketLengthInMs: BucketLengthInMs, 253 sampleCount: SampleCount, 254 intervalInMs: IntervalInMs, 255 array: NewAtomicBucketWrapArrayWithTime(int(SampleCount), BucketLengthInMs, uint64(1596199310000), &leapArrayMock{}), 256 }, 257 args: args{ 258 startTime: 1576296044907, 259 ww: &BucketWrap{ 260 BucketStart: 1576296004907, 261 }, 262 }, 263 want: true, 264 }, 265 } 266 267 for _, tt := range tests { 268 t.Run(tt.name, func(t *testing.T) { 269 la := &LeapArray{ 270 bucketLengthInMs: tt.fields.bucketLengthInMs, 271 sampleCount: tt.fields.sampleCount, 272 intervalInMs: tt.fields.intervalInMs, 273 array: tt.fields.array, 274 updateLock: mutex{}, 275 } 276 if got := la.isBucketDeprecated(tt.args.startTime, tt.args.ww); got != tt.want { 277 t.Errorf("LeapArray.isBucketDeprecated() = %v, want %v", got, tt.want) 278 } 279 }) 280 } 281 } 282 283 func TestNewLeapArray(t *testing.T) { 284 t.Run("TestNewLeapArray_Normal", func(t *testing.T) { 285 _, err := NewLeapArray(SampleCount, IntervalInMs, &leapArrayMock{}) 286 assert.Nil(t, err) 287 }) 288 289 t.Run("TestNewLeapArray_Generator_Nil", func(t *testing.T) { 290 leapArray, err := NewLeapArray(SampleCount, IntervalInMs, nil) 291 assert.Nil(t, leapArray) 292 assert.Error(t, err, "Invalid parameters, BucketGenerator is nil") 293 }) 294 295 t.Run("TestNewLeapArray_Invalid_Parameters", func(t *testing.T) { 296 leapArray, err := NewLeapArray(30, IntervalInMs, nil) 297 assert.Nil(t, leapArray) 298 assert.Error(t, err, "Invalid parameters, intervalInMs is 10000, sampleCount is 30") 299 }) 300 t.Run("TestNewLeapArray_Invalid_Parameters_sampleCount0", func(t *testing.T) { 301 leapArray, err := NewLeapArray(0, IntervalInMs, nil) 302 assert.Nil(t, leapArray) 303 assert.Error(t, err, "Invalid parameters, intervalInMs is 10000, sampleCount is 0") 304 }) 305 }