github.com/alibaba/sentinel-golang@v1.0.4/core/stat/base/sliding_window_metric_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  	"testing"
    19  
    20  	"github.com/alibaba/sentinel-golang/core/base"
    21  	"github.com/alibaba/sentinel-golang/util"
    22  	"github.com/stretchr/testify/assert"
    23  )
    24  
    25  func TestSlidingWindowMetric_getBucketStartRange(t *testing.T) {
    26  	type args struct {
    27  		sampleCount      uint32
    28  		intervalInMs     uint32
    29  		realSampleCount  uint32
    30  		realIntervalInMs uint32
    31  		now              uint64
    32  	}
    33  	tests := []struct {
    34  		name      string
    35  		args      args
    36  		wantStart uint64
    37  		wantEnd   uint64
    38  	}{
    39  		{
    40  			name: "TestSlidingWindowMetric_getBucketStartRange-1",
    41  			args: args{
    42  				sampleCount:      4,
    43  				intervalInMs:     2000,
    44  				realSampleCount:  20,
    45  				realIntervalInMs: 10000,
    46  				// array start time:1578416550000
    47  				// bucket start time:1578416556500
    48  				now: 1578416556900, //
    49  			},
    50  			wantStart: 1578416555000,
    51  			wantEnd:   1578416556500,
    52  		},
    53  		{
    54  			name: "TestSlidingWindowMetric_getBucketStartRange-2",
    55  			args: args{
    56  				sampleCount:      2,
    57  				intervalInMs:     1000,
    58  				realSampleCount:  20,
    59  				realIntervalInMs: 10000,
    60  				// array start time:1578416550000
    61  				// bucket start time:1578416556500
    62  				now: 1578416556900, //
    63  			},
    64  			wantStart: 1578416556000,
    65  			wantEnd:   1578416556500,
    66  		},
    67  		{
    68  			name: "TestSlidingWindowMetric_getBucketStartRange-3",
    69  			args: args{
    70  				sampleCount:      1,
    71  				intervalInMs:     2000,
    72  				realSampleCount:  10,
    73  				realIntervalInMs: 10000,
    74  				// array start time:1578416550000
    75  				// bucket start time:1578416556500
    76  				now: 1578416556900, //
    77  			},
    78  			wantStart: 1578416555000,
    79  			wantEnd:   1578416556000,
    80  		},
    81  		{
    82  			name: "TestSlidingWindowMetric_getBucketStartRange-4",
    83  			args: args{
    84  				sampleCount:      1,
    85  				intervalInMs:     10000,
    86  				realSampleCount:  10,
    87  				realIntervalInMs: 20000,
    88  				// array start time:1578416550000
    89  				// bucket start time:1578416556500
    90  				now: 1578416556900, //
    91  			},
    92  			wantStart: 1578416548000,
    93  			wantEnd:   1578416556000,
    94  		},
    95  		{
    96  			name: "TestSlidingWindowMetric_getBucketStartRange-5",
    97  			args: args{
    98  				sampleCount:      2,
    99  				intervalInMs:     1000,
   100  				realSampleCount:  20,
   101  				realIntervalInMs: 10000,
   102  				// array start time:1578416550000
   103  				// bucket start time:1578416556500
   104  				now: 1578416556500, //
   105  			},
   106  			wantStart: 1578416556000,
   107  			wantEnd:   1578416556500,
   108  		},
   109  	}
   110  	for _, tt := range tests {
   111  		t.Run(tt.name, func(t *testing.T) {
   112  			m, err := NewSlidingWindowMetric(tt.args.sampleCount, tt.args.intervalInMs, NewBucketLeapArray(tt.args.realSampleCount, tt.args.realIntervalInMs))
   113  			assert.True(t, err == nil)
   114  
   115  			gotStart, gotEnd := m.getBucketStartRange(tt.args.now)
   116  			if gotStart != tt.wantStart {
   117  				t.Errorf("SlidingWindowMetric.getBucketStartRange() gotStart = %v, want %v", gotStart, tt.wantStart)
   118  			}
   119  			if gotEnd != tt.wantEnd {
   120  				t.Errorf("SlidingWindowMetric.getBucketStartRange() gotEnd = %v, want %v", gotEnd, tt.wantEnd)
   121  			}
   122  		})
   123  	}
   124  }
   125  
   126  func Test_NewSlidingWindowMetric(t *testing.T) {
   127  	got, err := NewSlidingWindowMetric(4, 2000, NewBucketLeapArray(SampleCount, IntervalInMs))
   128  	assert.True(t, err == nil && got != nil)
   129  	got, err = NewSlidingWindowMetric(0, 0, NewBucketLeapArray(SampleCount, IntervalInMs))
   130  	assert.True(t, got == nil && err != nil)
   131  	got, err = NewSlidingWindowMetric(4, 2001, NewBucketLeapArray(SampleCount, IntervalInMs))
   132  	assert.True(t, got == nil && err != nil)
   133  	got, err = NewSlidingWindowMetric(2, 2002, NewBucketLeapArray(SampleCount, IntervalInMs))
   134  	assert.True(t, got == nil && err != nil)
   135  	got, err = NewSlidingWindowMetric(4, 200000, NewBucketLeapArray(SampleCount, IntervalInMs))
   136  	assert.True(t, got == nil && err != nil)
   137  }
   138  
   139  func TestSlidingWindowMetric_GetIntervalSumWithTime(t *testing.T) {
   140  	type fields struct {
   141  		sampleCount  uint32
   142  		intervalInMs uint32
   143  		real         *BucketLeapArray
   144  	}
   145  	type args struct {
   146  		event base.MetricEvent
   147  		now   uint64
   148  	}
   149  	tests := []struct {
   150  		name   string
   151  		fields fields
   152  		args   args
   153  		want   int64
   154  	}{
   155  		{
   156  			name: "",
   157  			fields: fields{
   158  				sampleCount:  2,
   159  				intervalInMs: 2000,
   160  				real:         NewBucketLeapArray(SampleCount, IntervalInMs),
   161  			},
   162  			args: args{
   163  				event: base.MetricEventPass,
   164  				now:   1678416556599,
   165  			},
   166  			want: 2000,
   167  		},
   168  	}
   169  	for _, tt := range tests {
   170  		t.Run(tt.name, func(t *testing.T) {
   171  			for i := 0; i < 500; i++ {
   172  				tt.fields.real.addCountWithTime(tt.args.now, tt.args.event, 1)
   173  			}
   174  			for i := 0; i < int(tt.fields.intervalInMs); i++ {
   175  				tt.fields.real.addCountWithTime(tt.args.now-100-uint64(i), tt.args.event, 1)
   176  			}
   177  			m, _ := NewSlidingWindowMetric(tt.fields.sampleCount, tt.fields.intervalInMs, tt.fields.real)
   178  			if got := m.getSumWithTime(tt.args.now, tt.args.event); got != tt.want {
   179  				t.Errorf("SlidingWindowMetric.getSumWithTime() = %v, want %v", got, tt.want)
   180  			}
   181  		})
   182  	}
   183  }
   184  
   185  func TestGetSum(t *testing.T) {
   186  	got, err := NewSlidingWindowMetric(4, 2000, NewBucketLeapArray(SampleCount, IntervalInMs))
   187  	assert.True(t, err == nil && got != nil)
   188  	passSum := got.GetSum(base.MetricEventPass)
   189  	assert.True(t, passSum == 0)
   190  }
   191  
   192  func TestGetQPS(t *testing.T) {
   193  	got, err := NewSlidingWindowMetric(4, 2000, NewBucketLeapArray(SampleCount, IntervalInMs))
   194  	assert.True(t, err == nil && got != nil)
   195  	qps := got.GetQPS(base.MetricEventPass)
   196  	assert.True(t, util.Float64Equals(qps, 0.0))
   197  }
   198  
   199  func TestGetPreviousQPS(t *testing.T) {
   200  	got, err := NewSlidingWindowMetric(4, 2000, NewBucketLeapArray(SampleCount, IntervalInMs))
   201  	assert.True(t, err == nil && got != nil)
   202  	previousQPS := got.GetPreviousQPS(base.MetricEventPass)
   203  	assert.True(t, util.Float64Equals(previousQPS, 0.0))
   204  }
   205  
   206  func TestGetQPSWithTime(t *testing.T) {
   207  	got, err := NewSlidingWindowMetric(4, 2000, NewBucketLeapArray(SampleCount, IntervalInMs))
   208  	assert.True(t, err == nil && got != nil)
   209  	qps := got.getQPSWithTime(util.CurrentTimeMillis(), base.MetricEventPass)
   210  	assert.True(t, util.Float64Equals(qps, 0.0))
   211  }
   212  
   213  func TestGetMaxOfSingleBucket(t *testing.T) {
   214  	got, err := NewSlidingWindowMetric(4, 2000, NewBucketLeapArray(SampleCount, IntervalInMs))
   215  	assert.True(t, err == nil && got != nil)
   216  	got.real.AddCount(base.MetricEventPass, 100)
   217  	max := got.GetMaxOfSingleBucket(base.MetricEventPass)
   218  	assert.True(t, max == 100)
   219  }
   220  
   221  func TestMinRT(t *testing.T) {
   222  	got, err := NewSlidingWindowMetric(4, 2000, NewBucketLeapArray(SampleCount, IntervalInMs))
   223  	assert.True(t, err == nil && got != nil)
   224  	minRt := got.MinRT()
   225  	assert.True(t, util.Float64Equals(minRt, float64(base.DefaultStatisticMaxRt)))
   226  }
   227  
   228  func TestMaxConcurrency(t *testing.T) {
   229  	got, err := NewSlidingWindowMetric(4, 2000, NewBucketLeapArray(SampleCount, IntervalInMs))
   230  	assert.True(t, err == nil && got != nil)
   231  	got.real.UpdateConcurrency(1)
   232  	got.real.UpdateConcurrency(3)
   233  	got.real.UpdateConcurrency(2)
   234  	mc := got.MaxConcurrency()
   235  	assert.True(t, mc == int32(3))
   236  }
   237  
   238  func TestAvgRT(t *testing.T) {
   239  	got, err := NewSlidingWindowMetric(4, 2000, NewBucketLeapArray(SampleCount, IntervalInMs))
   240  	assert.True(t, err == nil && got != nil)
   241  	got.real.AddCount(base.MetricEventRt, 100)
   242  	got.real.AddCount(base.MetricEventComplete, 100)
   243  	avgRT := got.AvgRT()
   244  	assert.True(t, util.Float64Equals(avgRT, 1.0))
   245  }
   246  
   247  func TestMetricItemFromBuckets(t *testing.T) {
   248  	got, err := NewSlidingWindowMetric(4, 2000, NewBucketLeapArray(SampleCount, IntervalInMs))
   249  	assert.True(t, err == nil && got != nil)
   250  	got.real.AddCount(base.MetricEventPass, 100)
   251  	item := got.metricItemFromBuckets(util.CurrentTimeMillis(), got.real.data.array.data)
   252  	assert.True(t, item.PassQps == 100)
   253  }
   254  
   255  func TestMetricItemFromBucket(t *testing.T) {
   256  	mb := NewMetricBucket()
   257  	mb.addCount(base.MetricEventPass, 100)
   258  	wrap := &BucketWrap{}
   259  	wrap.Value.Store(mb)
   260  	got := &SlidingWindowMetric{}
   261  	item := got.metricItemFromBucket(wrap)
   262  	assert.True(t, item.PassQps == 100)
   263  }
   264  
   265  func TestSecondMetricsOnCondition(t *testing.T) {
   266  	got, err := NewSlidingWindowMetric(4, 2000, NewBucketLeapArray(SampleCount, IntervalInMs))
   267  	assert.True(t, err == nil && got != nil)
   268  	start, end := got.getBucketStartRange(util.CurrentTimeMillis())
   269  	items := got.SecondMetricsOnCondition(func(ws uint64) bool {
   270  		return ws >= start && ws <= end
   271  	})
   272  	assert.True(t, len(items) == 1)
   273  }