github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/pkg/backoff/backoff_test.go (about) 1 // Copyright 2019 PingCAP, 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 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package backoff 15 16 import ( 17 "math" 18 "testing" 19 "time" 20 21 "github.com/pingcap/tiflow/dm/pkg/terror" 22 "github.com/stretchr/testify/require" 23 ) 24 25 func TestNewBackoff(t *testing.T) { 26 t.Parallel() 27 var ( 28 backoffFactor float64 = 2 29 backoffMin = 1 * time.Second 30 backoffMax = 5 * time.Minute 31 backoffJitter = true 32 bf *Backoff 33 err error 34 ) 35 testCases := []struct { 36 factor float64 37 jitter bool 38 min time.Duration 39 max time.Duration 40 hasErr bool 41 }{ 42 {backoffFactor, backoffJitter, backoffMin, backoffMax, false}, 43 {0, backoffJitter, backoffMin, backoffMax, true}, 44 {-1, backoffJitter, backoffMin, backoffMax, true}, 45 {backoffFactor, backoffJitter, -1, backoffMax, true}, 46 {backoffFactor, backoffJitter, backoffMin, -1, true}, 47 {backoffFactor, backoffJitter, backoffMin, backoffMin - 1, true}, 48 } 49 for _, tc := range testCases { 50 bf, err = NewBackoff(tc.factor, tc.jitter, tc.min, tc.max) 51 if tc.hasErr { 52 require.Nil(t, bf) 53 require.True(t, terror.ErrBackoffArgsNotValid.Equal(err)) 54 } else { 55 require.NoError(t, err) 56 } 57 } 58 } 59 60 func TestExponentialBackoff(t *testing.T) { 61 t.Parallel() 62 var ( 63 min = 1 * time.Millisecond 64 max = 1 * time.Second 65 factor float64 = 2 66 ) 67 b := &Backoff{ 68 Min: min, 69 Max: max, 70 Factor: factor, 71 } 72 73 for i := 0; i < 10; i++ { 74 expected := min * time.Duration(math.Pow(factor, float64(i))) 75 require.Equal(t, expected, b.Duration()) 76 } 77 b.Rollback() 78 require.Equal(t, 512*min, b.Current()) 79 b.Forward() 80 for i := 0; i < 10; i++ { 81 require.Equal(t, max, b.Duration()) 82 } 83 b.Reset() 84 require.Equal(t, min, b.Duration()) 85 } 86 87 func checkBetween(t *testing.T, value, low, high time.Duration) { 88 t.Helper() 89 require.True(t, value > low) 90 require.True(t, value < high) 91 } 92 93 func TestBackoffJitter(t *testing.T) { 94 t.Parallel() 95 var ( 96 min = 1 * time.Millisecond 97 max = 1 * time.Second 98 factor float64 = 2 99 ) 100 b := &Backoff{ 101 Min: min, 102 Max: max, 103 Factor: factor, 104 Jitter: true, 105 } 106 require.Equal(t, min, b.Duration()) 107 checkBetween(t, b.Duration(), min, 2*min) 108 checkBetween(t, b.Duration(), 2*min, 4*min) 109 checkBetween(t, b.Duration(), 4*min, 8*min) 110 b.Reset() 111 require.Equal(t, min, b.Duration()) 112 } 113 114 func TestFixedBackoff(t *testing.T) { 115 t.Parallel() 116 var ( 117 min = 100 * time.Millisecond 118 max = 100 * time.Millisecond 119 factor float64 = 2 120 ) 121 b := &Backoff{ 122 Min: min, 123 Max: max, 124 Factor: factor, 125 } 126 for i := 0; i < 10; i++ { 127 require.Equal(t, max, b.Duration()) 128 } 129 } 130 131 func TestOverflowBackoff(t *testing.T) { 132 t.Parallel() 133 testCases := []struct { 134 min time.Duration 135 max time.Duration 136 factor float64 137 }{ 138 {time.Duration(math.MaxInt64/2 + math.MaxInt64/4 + 2), time.Duration(math.MaxInt64), 2}, 139 {time.Duration(math.MaxInt64/2 + 1), time.Duration(math.MaxInt64), 2}, 140 {time.Duration(math.MaxInt64), time.Duration(math.MaxInt64), 2}, 141 } 142 for _, tc := range testCases { 143 b := &Backoff{ 144 Min: tc.min, 145 Max: tc.max, 146 Factor: tc.factor, 147 } 148 require.Equal(t, tc.min, b.Duration()) 149 require.Equal(t, tc.max, b.Duration()) 150 } 151 } 152 153 func TestForward(t *testing.T) { 154 t.Parallel() 155 var ( 156 factor float64 = 2 157 min = 1 * time.Second 158 max = 5 * time.Second 159 n = 10 160 ) 161 b := &Backoff{ 162 Min: min, 163 Max: max, 164 Factor: factor, 165 } 166 for i := 0; i < n; i++ { 167 b.Forward() 168 } 169 require.Equal(t, n, b.cwnd) 170 b.Reset() 171 require.Equal(t, 0, b.cwnd) 172 for i := 0; i < n; i++ { 173 b.BoundaryForward() 174 } 175 require.Equal(t, 3, b.cwnd) 176 }