github.com/MetalBlockchain/metalgo@v1.11.9/network/p2p/throttler_test.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package p2p 5 6 import ( 7 "testing" 8 "time" 9 10 "github.com/stretchr/testify/require" 11 12 "github.com/MetalBlockchain/metalgo/ids" 13 ) 14 15 func TestSlidingWindowThrottlerHandle(t *testing.T) { 16 period := time.Minute 17 previousWindowStartTime := time.Time{} 18 currentWindowStartTime := previousWindowStartTime.Add(period) 19 20 nodeID := ids.GenerateTestNodeID() 21 22 type call struct { 23 time time.Time 24 throttled bool 25 } 26 27 tests := []struct { 28 name string 29 limit int 30 calls []call 31 }{ 32 { 33 name: "throttled in current window", 34 limit: 1, 35 calls: []call{ 36 { 37 time: currentWindowStartTime, 38 }, 39 { 40 time: currentWindowStartTime, 41 throttled: true, 42 }, 43 }, 44 }, 45 { 46 name: "throttled from previous window", 47 limit: 1, 48 calls: []call{ 49 { 50 time: previousWindowStartTime, 51 }, 52 { 53 time: currentWindowStartTime, 54 throttled: true, 55 }, 56 }, 57 }, 58 { 59 name: "throttled over multiple evaluation periods", 60 limit: 5, 61 calls: []call{ 62 { 63 time: currentWindowStartTime.Add(30 * time.Second), 64 }, 65 { 66 time: currentWindowStartTime.Add(period).Add(1 * time.Second), 67 }, 68 { 69 time: currentWindowStartTime.Add(period).Add(2 * time.Second), 70 }, 71 { 72 time: currentWindowStartTime.Add(period).Add(3 * time.Second), 73 }, 74 { 75 time: currentWindowStartTime.Add(period).Add(4 * time.Second), 76 }, 77 { 78 time: currentWindowStartTime.Add(period).Add(30 * time.Second), 79 }, 80 { 81 time: currentWindowStartTime.Add(period).Add(30 * time.Second), 82 throttled: true, 83 }, 84 { 85 time: currentWindowStartTime.Add(5 * period), 86 }, 87 }, 88 }, 89 { 90 name: "one hit per period", 91 limit: 2, 92 calls: []call{ 93 { 94 time: currentWindowStartTime, 95 }, 96 { 97 time: currentWindowStartTime.Add(period).Add(time.Second), 98 }, 99 { 100 time: currentWindowStartTime.Add(2 * period).Add(time.Second), 101 }, 102 { 103 time: currentWindowStartTime.Add(3 * period).Add(time.Second), 104 }, 105 { 106 time: currentWindowStartTime.Add(4 * period).Add(time.Second), 107 }, 108 }, 109 }, 110 { 111 // if too much time passes by, a current window might not be a 112 // valid previous window. 113 name: "current window needs to be reset", 114 limit: 1, 115 calls: []call{ 116 { 117 time: currentWindowStartTime, 118 }, 119 { 120 time: currentWindowStartTime.Add(10 * period), 121 }, 122 }, 123 }, 124 } 125 126 for _, tt := range tests { 127 t.Run(tt.name, func(t *testing.T) { 128 require := require.New(t) 129 throttler := NewSlidingWindowThrottler(period, tt.limit) 130 throttler.windows[throttler.current].start = currentWindowStartTime 131 throttler.windows[1-throttler.current].start = previousWindowStartTime 132 133 for _, call := range tt.calls { 134 throttler.clock.Set(call.time) 135 require.Equal(call.throttled, !throttler.Handle(nodeID)) 136 } 137 }) 138 } 139 }