github.com/bytedance/gopkg@v0.0.0-20240514070511-01b2cbcf35e1/cloud/circuitbreaker/per_p_metricer_test.go (about)

     1  // Copyright 2021 ByteDance Inc.
     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 circuitbreaker
    16  
    17  import (
    18  	"math/rand"
    19  	"testing"
    20  	"time"
    21  )
    22  
    23  func BenchmarkPerPBuckets(b *testing.B) {
    24  	bk := newPerPBucket()
    25  	bk.Reset()
    26  	b.ResetTimer()
    27  	for i := 0; i < b.N; i++ {
    28  		bk.Fail()
    29  		bk.Timeout()
    30  		bk.Succeed()
    31  	}
    32  }
    33  
    34  // TestPerPMetricser1 tests basic functions
    35  func TestPerPMetricser1(t *testing.T) {
    36  	m := newPerPWindow()
    37  
    38  	// no data
    39  	deepEqual(t, m.ErrorRate(), float64(0))
    40  	deepEqual(t, m.ConseErrors(), int64(0))
    41  	deepEqual(t, m.Successes(), int64(0))
    42  	deepEqual(t, m.Failures(), int64(0))
    43  	deepEqual(t, m.Timeouts(), int64(0))
    44  
    45  	m.Fail()
    46  	m.Timeout()
    47  	m.Fail()
    48  	m.Timeout()
    49  	deepEqual(t, m.Failures(), int64(2))
    50  	deepEqual(t, m.Timeouts(), int64(2))
    51  	deepEqual(t, m.ErrorRate(), float64(1))
    52  	deepEqual(t, m.ConseErrors(), int64(4))
    53  	deepEqual(t, m.Successes(), int64(0))
    54  
    55  	m.Succeed()
    56  	deepEqual(t, m.ErrorRate(), float64(.8))
    57  	deepEqual(t, m.ConseErrors(), int64(0))
    58  	deepEqual(t, m.Successes(), int64(1))
    59  	deepEqual(t, m.Failures(), int64(2))
    60  	deepEqual(t, m.Timeouts(), int64(2))
    61  
    62  	s, f, tm := m.Counts()
    63  	deepEqual(t, s, int64(1))
    64  	deepEqual(t, f, int64(2))
    65  	deepEqual(t, tm, int64(2))
    66  
    67  	tot := 1000000
    68  	for i := 0; i < tot; i++ {
    69  		t := rand.Intn(3)
    70  		if t == 0 { // fail
    71  			m.Fail()
    72  		} else if t == 1 { // timeout
    73  			m.Timeout()
    74  		} else { // succeed
    75  			m.Succeed()
    76  		}
    77  	}
    78  
    79  	rate := m.ErrorRate()
    80  	assert(t, rate > .6 && rate < .7)
    81  	s = m.Successes()
    82  	assert(t, s > int64(tot/3-1000) && s < int64(tot/3+1000))
    83  	f = m.Failures()
    84  	assert(t, f > int64(tot/3-1000) && f < int64(tot/3+1000))
    85  	ts := m.Timeouts()
    86  	assert(t, ts > int64(tot/3-1000) && ts < int64(tot/3+1000))
    87  }
    88  
    89  // TestPerPMetricser2 tests functions about time
    90  func TestPerPMetricser2(t *testing.T) {
    91  	p, _ := NewPanel(nil, Options{BucketTime: time.Millisecond * 10, BucketNums: 100})
    92  	b := p.(*panel).getBreaker("test")
    93  	m := b.metricer
    94  	expire := time.Millisecond * 10 * 100
    95  
    96  	m.Succeed()
    97  	deepEqual(t, m.Successes(), int64(1))
    98  	deepEqual(t, m.Failures(), int64(0))
    99  	deepEqual(t, m.Timeouts(), int64(0))
   100  
   101  	time.Sleep(expire + time.Millisecond*10)
   102  	deepEqual(t, m.Successes(), int64(0))
   103  	deepEqual(t, m.Failures(), int64(0))
   104  	deepEqual(t, m.Timeouts(), int64(0))
   105  
   106  	for i := 0; i < 10; i++ {
   107  		m.Fail()
   108  	}
   109  	deepEqual(t, m.Successes(), int64(0))
   110  	deepEqual(t, m.Failures(), int64(10))
   111  	deepEqual(t, m.Timeouts(), int64(0))
   112  	deepEqual(t, m.ConseErrors(), int64(10))
   113  
   114  	time.Sleep(expire / 2)
   115  	for i := 0; i < 100; i++ {
   116  		m.Fail()
   117  	}
   118  	deepEqual(t, m.Successes(), int64(0))
   119  	deepEqual(t, m.Failures(), int64(110))
   120  	deepEqual(t, m.Timeouts(), int64(0))
   121  	deepEqual(t, m.ConseErrors(), int64(110))
   122  
   123  	time.Sleep(expire / 2)
   124  	deepEqual(t, m.Successes(), int64(0))
   125  	deepEqual(t, m.Failures(), int64(100))
   126  	deepEqual(t, m.Timeouts(), int64(0))
   127  	deepEqual(t, m.ConseErrors(), int64(110))
   128  
   129  	time.Sleep(expire / 2)
   130  	deepEqual(t, m.Successes(), int64(0))
   131  	deepEqual(t, m.Failures(), int64(0))
   132  	deepEqual(t, m.Timeouts(), int64(0))
   133  	deepEqual(t, m.ConseErrors(), int64(110))
   134  
   135  	m.Succeed()
   136  	deepEqual(t, m.Successes(), int64(1))
   137  	deepEqual(t, m.Failures(), int64(0))
   138  	deepEqual(t, m.Timeouts(), int64(0))
   139  	deepEqual(t, m.ConseErrors(), int64(0))
   140  }
   141  
   142  func BenchmarkPerPWindow(b *testing.B) {
   143  	m := newPerPWindow()
   144  	b.ResetTimer()
   145  	for i := 0; i < b.N; i++ {
   146  		m.Succeed()
   147  	}
   148  }
   149  
   150  func BenchmarkPerPWindowParallel(b *testing.B) {
   151  	m := newPerPWindow()
   152  	b.ResetTimer()
   153  	b.RunParallel(func(pb *testing.PB) {
   154  		for pb.Next() {
   155  			m.Succeed()
   156  		}
   157  	})
   158  }
   159  
   160  func BenchmarkPerPWindowParallel2Cores(b *testing.B) {
   161  	b.SetParallelism(2)
   162  	m := newPerPWindow()
   163  	b.ResetTimer()
   164  	b.RunParallel(func(pb *testing.PB) {
   165  		for pb.Next() {
   166  			m.Succeed()
   167  		}
   168  	})
   169  }