go.temporal.io/server@v1.23.0/common/quotas/clocked_rate_limiter_test.go (about) 1 // The MIT License 2 // 3 // Copyright (c) 2020 Temporal Technologies Inc. All rights reserved. 4 // 5 // Copyright (c) 2020 Uber Technologies, Inc. 6 // 7 // Permission is hereby granted, free of charge, to any person obtaining a copy 8 // of this software and associated documentation files (the "Software"), to deal 9 // in the Software without restriction, including without limitation the rights 10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 // copies of the Software, and to permit persons to whom the Software is 12 // furnished to do so, subject to the following conditions: 13 // 14 // The above copyright notice and this permission notice shall be included in 15 // all copies or substantial portions of the Software. 16 // 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 // THE SOFTWARE. 24 25 package quotas_test 26 27 import ( 28 "context" 29 "testing" 30 "time" 31 32 "github.com/stretchr/testify/assert" 33 "go.temporal.io/server/common/clock" 34 "go.temporal.io/server/common/quotas" 35 "golang.org/x/time/rate" 36 ) 37 38 func TestClockedRateLimiter_Allow_NoQuota(t *testing.T) { 39 t.Parallel() 40 41 ts := clock.NewRealTimeSource() 42 rl := quotas.NewClockedRateLimiter(rate.NewLimiter(0, 0), ts) 43 assert.False(t, rl.Allow()) 44 } 45 46 func TestClockedRateLimiter_Allow_OneBurst(t *testing.T) { 47 t.Parallel() 48 49 ts := clock.NewEventTimeSource() 50 rl := quotas.NewClockedRateLimiter(rate.NewLimiter(0, 1), ts) 51 assert.True(t, rl.Allow()) 52 assert.False(t, rl.Allow()) 53 } 54 55 func TestClockedRateLimiter_Allow_RPS_TooHigh(t *testing.T) { 56 t.Parallel() 57 58 ts := clock.NewEventTimeSource() 59 rl := quotas.NewClockedRateLimiter(rate.NewLimiter(1, 1), ts) 60 assert.True(t, rl.Allow()) 61 ts.Advance(999 * time.Millisecond) 62 assert.False(t, rl.Allow()) 63 } 64 65 func TestClockedRateLimiter_Allow_RPS_Ok(t *testing.T) { 66 t.Parallel() 67 68 ts := clock.NewEventTimeSource() 69 rl := quotas.NewClockedRateLimiter(rate.NewLimiter(1, 1), ts) 70 assert.True(t, rl.Allow()) 71 ts.Advance(time.Second) 72 assert.True(t, rl.Allow()) 73 } 74 75 func TestClockedRateLimiter_AllowN_Ok(t *testing.T) { 76 t.Parallel() 77 78 ts := clock.NewEventTimeSource() 79 rl := quotas.NewClockedRateLimiter(rate.NewLimiter(0, 10), ts) 80 assert.True(t, rl.AllowN(ts.Now(), 10)) 81 } 82 83 func TestClockedRateLimiter_AllowN_NotOk(t *testing.T) { 84 t.Parallel() 85 86 ts := clock.NewEventTimeSource() 87 rl := quotas.NewClockedRateLimiter(rate.NewLimiter(0, 10), ts) 88 assert.False(t, rl.AllowN(ts.Now(), 11)) 89 } 90 91 func TestClockedRateLimiter_Wait_NoBurst(t *testing.T) { 92 t.Parallel() 93 94 ts := clock.NewEventTimeSource() 95 rl := quotas.NewClockedRateLimiter(rate.NewLimiter(1, 0), ts) 96 ctx := context.Background() 97 assert.ErrorIs(t, rl.Wait(ctx), quotas.ErrRateLimiterReservationCannotBeMade) 98 } 99 100 func TestClockedRateLimiter_Wait_Ok(t *testing.T) { 101 t.Parallel() 102 103 ts := clock.NewEventTimeSource() 104 rl := quotas.NewClockedRateLimiter(rate.NewLimiter(1, 1), ts) 105 ctx := context.Background() 106 assert.NoError(t, rl.Wait(ctx)) 107 108 go func() { 109 ts.Advance(time.Second) 110 }() 111 assert.NoError(t, rl.Wait(ctx)) 112 } 113 114 func TestClockedRateLimiter_Wait_Canceled(t *testing.T) { 115 t.Parallel() 116 117 ts := clock.NewEventTimeSource() 118 rl := quotas.NewClockedRateLimiter(rate.NewLimiter(1, 1), ts) 119 ctx := context.Background() 120 121 ctx, cancel := context.WithCancel(ctx) 122 assert.NoError(t, rl.Wait(ctx)) 123 124 go func() { 125 ts.Advance(time.Millisecond * 999) 126 cancel() 127 }() 128 assert.ErrorIs(t, rl.Wait(ctx), quotas.ErrRateLimiterWaitInterrupted) 129 } 130 131 func TestClockedRateLimiter_Reserve(t *testing.T) { 132 t.Parallel() 133 134 ts := clock.NewEventTimeSource() 135 rl := quotas.NewClockedRateLimiter(rate.NewLimiter(1, 1), ts) 136 rl.Allow() 137 reservation := rl.Reserve() 138 assert.Equal(t, time.Second, reservation.DelayFrom(ts.Now())) 139 } 140 141 func TestClockedRateLimiter_Wait_DeadlineWouldExceed(t *testing.T) { 142 t.Parallel() 143 144 ts := clock.NewEventTimeSource() 145 rl := quotas.NewClockedRateLimiter(rate.NewLimiter(1, 1), ts) 146 rl.Allow() 147 148 ctx := context.Background() 149 150 ctx, cancel := context.WithDeadline(ctx, ts.Now().Add(500*time.Millisecond)) 151 t.Cleanup(cancel) 152 assert.ErrorIs(t, rl.Wait(ctx), quotas.ErrRateLimiterReservationWouldExceedContextDeadline) 153 }