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  }