k8s.io/client-go@v0.22.2/util/flowcontrol/backoff_test.go (about) 1 /* 2 Copyright 2015 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package flowcontrol 18 19 import ( 20 "testing" 21 "time" 22 23 "k8s.io/apimachinery/pkg/util/clock" 24 ) 25 26 func TestSlowBackoff(t *testing.T) { 27 id := "_idSlow" 28 tc := clock.NewFakeClock(time.Now()) 29 step := time.Second 30 maxDuration := 50 * step 31 32 b := NewFakeBackOff(step, maxDuration, tc) 33 cases := []time.Duration{0, 1, 2, 4, 8, 16, 32, 50, 50, 50} 34 for ix, c := range cases { 35 tc.Step(step) 36 w := b.Get(id) 37 if w != c*step { 38 t.Errorf("input: '%d': expected %s, got %s", ix, c*step, w) 39 } 40 b.Next(id, tc.Now()) 41 } 42 43 //Now confirm that the Reset cancels backoff. 44 b.Next(id, tc.Now()) 45 b.Reset(id) 46 if b.Get(id) != 0 { 47 t.Errorf("Reset didn't clear the backoff.") 48 } 49 50 } 51 52 func TestBackoffReset(t *testing.T) { 53 id := "_idReset" 54 tc := clock.NewFakeClock(time.Now()) 55 step := time.Second 56 maxDuration := step * 5 57 b := NewFakeBackOff(step, maxDuration, tc) 58 startTime := tc.Now() 59 60 // get to backoff = maxDuration 61 for i := 0; i <= int(maxDuration/step); i++ { 62 tc.Step(step) 63 b.Next(id, tc.Now()) 64 } 65 66 // backoff should be capped at maxDuration 67 if !b.IsInBackOffSince(id, tc.Now()) { 68 t.Errorf("expected to be in Backoff got %s", b.Get(id)) 69 } 70 71 lastUpdate := tc.Now() 72 tc.Step(2*maxDuration + step) // time += 11s, 11 > 2*maxDuration 73 if b.IsInBackOffSince(id, lastUpdate) { 74 t.Errorf("expected to not be in Backoff after reset (start=%s, now=%s, lastUpdate=%s), got %s", startTime, tc.Now(), lastUpdate, b.Get(id)) 75 } 76 } 77 78 func TestBackoffHighWaterMark(t *testing.T) { 79 id := "_idHiWaterMark" 80 tc := clock.NewFakeClock(time.Now()) 81 step := time.Second 82 maxDuration := 5 * step 83 b := NewFakeBackOff(step, maxDuration, tc) 84 85 // get to backoff = maxDuration 86 for i := 0; i <= int(maxDuration/step); i++ { 87 tc.Step(step) 88 b.Next(id, tc.Now()) 89 } 90 91 // backoff high watermark expires after 2*maxDuration 92 tc.Step(maxDuration + step) 93 b.Next(id, tc.Now()) 94 95 if b.Get(id) != maxDuration { 96 t.Errorf("expected Backoff to stay at high watermark %s got %s", maxDuration, b.Get(id)) 97 } 98 } 99 100 func TestBackoffGC(t *testing.T) { 101 id := "_idGC" 102 tc := clock.NewFakeClock(time.Now()) 103 step := time.Second 104 maxDuration := 5 * step 105 106 b := NewFakeBackOff(step, maxDuration, tc) 107 108 for i := 0; i <= int(maxDuration/step); i++ { 109 tc.Step(step) 110 b.Next(id, tc.Now()) 111 } 112 lastUpdate := tc.Now() 113 tc.Step(maxDuration + step) 114 b.GC() 115 _, found := b.perItemBackoff[id] 116 if !found { 117 t.Errorf("expected GC to skip entry, elapsed time=%s maxDuration=%s", tc.Since(lastUpdate), maxDuration) 118 } 119 120 tc.Step(maxDuration + step) 121 b.GC() 122 r, found := b.perItemBackoff[id] 123 if found { 124 t.Errorf("expected GC of entry after %s got entry %v", tc.Since(lastUpdate), r) 125 } 126 } 127 128 func TestIsInBackOffSinceUpdate(t *testing.T) { 129 id := "_idIsInBackOffSinceUpdate" 130 tc := clock.NewFakeClock(time.Now()) 131 step := time.Second 132 maxDuration := 10 * step 133 b := NewFakeBackOff(step, maxDuration, tc) 134 startTime := tc.Now() 135 136 cases := []struct { 137 tick time.Duration 138 inBackOff bool 139 value int 140 }{ 141 {tick: 0, inBackOff: false, value: 0}, 142 {tick: 1, inBackOff: false, value: 1}, 143 {tick: 2, inBackOff: true, value: 2}, 144 {tick: 3, inBackOff: false, value: 2}, 145 {tick: 4, inBackOff: true, value: 4}, 146 {tick: 5, inBackOff: true, value: 4}, 147 {tick: 6, inBackOff: true, value: 4}, 148 {tick: 7, inBackOff: false, value: 4}, 149 {tick: 8, inBackOff: true, value: 8}, 150 {tick: 9, inBackOff: true, value: 8}, 151 {tick: 10, inBackOff: true, value: 8}, 152 {tick: 11, inBackOff: true, value: 8}, 153 {tick: 12, inBackOff: true, value: 8}, 154 {tick: 13, inBackOff: true, value: 8}, 155 {tick: 14, inBackOff: true, value: 8}, 156 {tick: 15, inBackOff: false, value: 8}, 157 {tick: 16, inBackOff: true, value: 10}, 158 {tick: 17, inBackOff: true, value: 10}, 159 {tick: 18, inBackOff: true, value: 10}, 160 {tick: 19, inBackOff: true, value: 10}, 161 {tick: 20, inBackOff: true, value: 10}, 162 {tick: 21, inBackOff: true, value: 10}, 163 {tick: 22, inBackOff: true, value: 10}, 164 {tick: 23, inBackOff: true, value: 10}, 165 {tick: 24, inBackOff: true, value: 10}, 166 {tick: 25, inBackOff: false, value: 10}, 167 {tick: 26, inBackOff: true, value: 10}, 168 {tick: 27, inBackOff: true, value: 10}, 169 {tick: 28, inBackOff: true, value: 10}, 170 {tick: 29, inBackOff: true, value: 10}, 171 {tick: 30, inBackOff: true, value: 10}, 172 {tick: 31, inBackOff: true, value: 10}, 173 {tick: 32, inBackOff: true, value: 10}, 174 {tick: 33, inBackOff: true, value: 10}, 175 {tick: 34, inBackOff: true, value: 10}, 176 {tick: 35, inBackOff: false, value: 10}, 177 {tick: 56, inBackOff: false, value: 0}, 178 {tick: 57, inBackOff: false, value: 1}, 179 } 180 181 for _, c := range cases { 182 tc.SetTime(startTime.Add(c.tick * step)) 183 if c.inBackOff != b.IsInBackOffSinceUpdate(id, tc.Now()) { 184 t.Errorf("expected IsInBackOffSinceUpdate %v got %v at tick %s", c.inBackOff, b.IsInBackOffSinceUpdate(id, tc.Now()), c.tick*step) 185 } 186 187 if c.inBackOff && (time.Duration(c.value)*step != b.Get(id)) { 188 t.Errorf("expected backoff value=%s got %s at tick %s", time.Duration(c.value)*step, b.Get(id), c.tick*step) 189 } 190 191 if !c.inBackOff { 192 b.Next(id, tc.Now()) 193 } 194 } 195 }