github.com/alibaba/sentinel-golang@v1.0.4/core/stat/base/bucket_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 "fmt" 19 "math/rand" 20 "sync" 21 "sync/atomic" 22 "testing" 23 24 "github.com/alibaba/sentinel-golang/core/base" 25 "github.com/alibaba/sentinel-golang/util" 26 "github.com/stretchr/testify/assert" 27 ) 28 29 //Test sliding windows create buckets 30 func Test_NewBucketLeapArray(t *testing.T) { 31 slidingWindow := NewBucketLeapArray(SampleCount, IntervalInMs) 32 now := util.CurrentTimeMillis() 33 34 br, err := slidingWindow.data.currentBucketOfTime(now, slidingWindow) 35 if br == nil || br.Value.Load() == nil { 36 t.Errorf("Unexcepted error") 37 return 38 } 39 if err != nil { 40 t.Errorf("Unexcepted error") 41 } 42 if br.BucketStart != (now - now%uint64(BucketLengthInMs)) { 43 t.Errorf("Unexcepted error, bucket length is not same") 44 } 45 if br.Value.Load() == nil { 46 t.Errorf("Unexcepted error, Value is nil") 47 } 48 if slidingWindow.Count(base.MetricEventPass) != 0 { 49 t.Errorf("Unexcepted error, pass Value is invalid") 50 } 51 } 52 53 func Test_UpdateBucket_Concurrent(t *testing.T) { 54 slidingWindow := NewBucketLeapArray(SampleCount, IntervalInMs) 55 56 const GoroutineNum = 3000 57 now := uint64(1976296040000) // start time is 1576296044500, [1576296040000, 1576296050000] 58 59 var cnt = uint64(0) 60 for t := now; t < now+uint64(IntervalInMs); { 61 slidingWindow.addCountWithTime(t, base.MetricEventComplete, 1) 62 slidingWindow.addCountWithTime(t, base.MetricEventPass, 1) 63 slidingWindow.addCountWithTime(t, base.MetricEventBlock, 1) 64 slidingWindow.addCountWithTime(t, base.MetricEventError, 1) 65 slidingWindow.addCountWithTime(t, base.MetricEventRt, 10) 66 t = t + 500 67 } 68 for _, b := range slidingWindow.Values(uint64(1976296049500)) { 69 bucket, ok := b.Value.Load().(*MetricBucket) 70 assert.True(t, ok) 71 assert.True(t, bucket.Get(base.MetricEventComplete) == 1) 72 assert.True(t, bucket.Get(base.MetricEventPass) == 1) 73 assert.True(t, bucket.Get(base.MetricEventBlock) == 1) 74 assert.True(t, bucket.Get(base.MetricEventError) == 1) 75 assert.True(t, bucket.Get(base.MetricEventRt) == 10) 76 } 77 78 wg := &sync.WaitGroup{} 79 wg.Add(GoroutineNum - 20) 80 for i := 0; i < GoroutineNum-20; i++ { 81 go coroutineTask(wg, slidingWindow, now, &cnt) 82 } 83 wg.Wait() 84 85 success := slidingWindow.CountWithTime(now+9999, base.MetricEventComplete) 86 pass := slidingWindow.CountWithTime(now+9999, base.MetricEventPass) 87 block := slidingWindow.CountWithTime(now+9999, base.MetricEventBlock) 88 errNum := slidingWindow.CountWithTime(now+9999, base.MetricEventError) 89 rt := slidingWindow.CountWithTime(now+9999, base.MetricEventRt) 90 if success == GoroutineNum && pass == GoroutineNum && block == GoroutineNum && errNum == GoroutineNum && rt == GoroutineNum*10 { 91 fmt.Printf("Success %d, pass %d, block %d, error %d, rt %d\n", success, pass, block, errNum, rt) 92 } else { 93 fmt.Printf("Success %d, pass %d, block %d, error %d, rt %d\n", success, pass, block, errNum, rt) 94 t.Errorf("Concurrency error\n") 95 } 96 } 97 98 func coroutineTask(wg *sync.WaitGroup, slidingWindow *BucketLeapArray, now uint64, counter *uint64) { 99 inc := rand.Uint64() % 10000 100 slidingWindow.addCountWithTime(now+inc, base.MetricEventComplete, 1) 101 slidingWindow.addCountWithTime(now+inc, base.MetricEventPass, 1) 102 slidingWindow.addCountWithTime(now+inc, base.MetricEventBlock, 1) 103 slidingWindow.addCountWithTime(now+inc, base.MetricEventError, 1) 104 slidingWindow.addCountWithTime(now+inc, base.MetricEventRt, 10) 105 106 atomic.AddUint64(counter, 1) 107 wg.Done() 108 } 109 110 func TestBucketLeapArray_resetBucketTo(t *testing.T) { 111 bla := NewBucketLeapArray(SampleCount, IntervalInMs) 112 idx := 19 113 oldBucketWrap := bla.data.array.get(idx) 114 oldBucket := oldBucketWrap.Value.Load() 115 if oldBucket == nil { 116 t.Errorf("BucketLeapArray init error.") 117 } 118 bucket, ok := oldBucket.(*MetricBucket) 119 if !ok { 120 t.Errorf("Fail to assert bucket to MetricBucket.") 121 } 122 bucket.Add(base.MetricEventPass, 100) 123 bucket.Add(base.MetricEventBlock, 100) 124 125 wantStartTime := util.CurrentTimeMillis() + 1000 126 got := bla.ResetBucketTo(oldBucketWrap, wantStartTime) 127 newBucket := got.Value.Load() 128 if newBucket == nil { 129 t.Errorf("got bucket is nil.") 130 } 131 newRealBucket, ok := newBucket.(*MetricBucket) 132 if !ok { 133 t.Errorf("Fail to assert bucket to MetricBucket.") 134 } 135 if newRealBucket.Get(base.MetricEventPass) != 0 { 136 t.Errorf("BucketLeapArray.ResetBucketTo() execute fail.") 137 } 138 if newRealBucket.Get(base.MetricEventBlock) != 0 { 139 t.Errorf("BucketLeapArray.ResetBucketTo() execute fail.") 140 } 141 } 142 143 func TestAddCount(t *testing.T) { 144 bla := NewBucketLeapArray(SampleCount, IntervalInMs) 145 bla.AddCount(base.MetricEventPass, 1) 146 passCount := bla.Count(base.MetricEventPass) 147 assert.True(t, passCount == 1) 148 } 149 150 func TestUpdateConcurrency(t *testing.T) { 151 bla := NewBucketLeapArray(SampleCount, IntervalInMs) 152 bla.UpdateConcurrency(1) 153 bla.UpdateConcurrency(3) 154 bla.UpdateConcurrency(2) 155 mc := bla.MaxConcurrency() 156 assert.True(t, mc == 3) 157 } 158 159 func TestMinRt(t *testing.T) { 160 t.Run("TestMinRt_Default", func(t *testing.T) { 161 bla := NewBucketLeapArray(SampleCount, IntervalInMs) 162 minRt := bla.MinRt() 163 assert.True(t, minRt == base.DefaultStatisticMaxRt) 164 }) 165 166 t.Run("TestMinRt", func(t *testing.T) { 167 bla := NewBucketLeapArray(SampleCount, IntervalInMs) 168 bla.AddCount(base.MetricEventRt, 100) 169 minRt := bla.MinRt() 170 assert.True(t, minRt == 100) 171 }) 172 } 173 174 func TestGetIntervalInSecond(t *testing.T) { 175 bla := NewBucketLeapArray(SampleCount, IntervalInMs) 176 second := bla.GetIntervalInSecond() 177 assert.True(t, util.Float64Equals(float64(IntervalInMs)/1000.0, second)) 178 } 179 180 func TestDataType(t *testing.T) { 181 bla := NewBucketLeapArray(SampleCount, IntervalInMs) 182 dataType := bla.DataType() 183 assert.True(t, dataType == "MetricBucket") 184 }