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  }