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  }