github.com/ava-labs/avalanchego@v1.11.11/network/throttling/dial_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 throttling
     5  
     6  import (
     7  	"context"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/stretchr/testify/require"
    12  )
    13  
    14  // Test that the DialThrottler returned by NewDialThrottler works
    15  func TestDialThrottler(t *testing.T) {
    16  	require := require.New(t)
    17  
    18  	startTime := time.Now()
    19  	// Allows 5 per second
    20  	throttler := NewDialThrottler(5)
    21  	// Use all 5
    22  	for i := 0; i < 5; i++ {
    23  		acquiredChan := make(chan struct{}, 1)
    24  		// Should return immediately because < 5 taken this second
    25  		go func() {
    26  			require.NoError(throttler.Acquire(context.Background()))
    27  			acquiredChan <- struct{}{}
    28  		}()
    29  		select {
    30  		case <-time.After(10 * time.Millisecond):
    31  			require.FailNow("should have acquired immediately")
    32  		case <-acquiredChan:
    33  		}
    34  		close(acquiredChan)
    35  	}
    36  
    37  	acquiredChan := make(chan struct{}, 1)
    38  	go func() {
    39  		// Should block because 5 already taken within last second
    40  		require.NoError(throttler.Acquire(context.Background()))
    41  		acquiredChan <- struct{}{}
    42  	}()
    43  
    44  	select {
    45  	case <-time.After(25 * time.Millisecond):
    46  	case <-acquiredChan:
    47  		require.FailNow("should not have been able to acquire immediately")
    48  	}
    49  
    50  	// Wait until the 6th Acquire() has returned. The time at which
    51  	// that returns should be no more than 1s after the time at which
    52  	// the first Acquire() returned.
    53  	<-acquiredChan
    54  	close(acquiredChan)
    55  	// Use 1.05 seconds instead of 1 second to give some "wiggle room"
    56  	// so test doesn't flake
    57  	require.LessOrEqual(time.Since(startTime), 1050*time.Millisecond)
    58  }
    59  
    60  // Test that Acquire honors its specification about its context being canceled
    61  func TestDialThrottlerCancel(t *testing.T) {
    62  	require := require.New(t)
    63  
    64  	// Allows 5 per second
    65  	throttler := NewDialThrottler(5)
    66  	// Use all 5
    67  	for i := 0; i < 5; i++ {
    68  		acquiredChan := make(chan struct{}, 1)
    69  		// Should return immediately because < 5 taken this second
    70  		go func() {
    71  			require.NoError(throttler.Acquire(context.Background()))
    72  			acquiredChan <- struct{}{}
    73  		}()
    74  		select {
    75  		case <-time.After(10 * time.Millisecond):
    76  			require.FailNow("should have acquired immediately")
    77  		case <-acquiredChan:
    78  		}
    79  		close(acquiredChan)
    80  	}
    81  
    82  	acquiredChan := make(chan struct{}, 1)
    83  	ctx, cancel := context.WithCancel(context.Background())
    84  	go func() {
    85  		// Should block because 5 already taken within last second
    86  		err := throttler.Acquire(ctx)
    87  		// Should error because we call cancel() below
    88  		require.ErrorIs(err, context.Canceled)
    89  		acquiredChan <- struct{}{}
    90  	}()
    91  
    92  	// Cancel the 6th acquire
    93  	cancel()
    94  	select {
    95  	case <-acquiredChan:
    96  	case <-time.After(10 * time.Millisecond):
    97  		require.FailNow("Acquire should have returned immediately upon context cancellation")
    98  	}
    99  	close(acquiredChan)
   100  }
   101  
   102  // Test that the Throttler return by NewNoThrottler never blocks on Acquire()
   103  func TestNoDialThrottler(t *testing.T) {
   104  	require := require.New(t)
   105  
   106  	throttler := NewNoDialThrottler()
   107  	for i := 0; i < 250; i++ {
   108  		startTime := time.Now()
   109  		require.NoError(throttler.Acquire(context.Background())) // Should always immediately return
   110  		require.WithinDuration(time.Now(), startTime, 25*time.Millisecond)
   111  	}
   112  }