golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/quic/pacer_test.go (about)

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build go1.21
     6  
     7  package quic
     8  
     9  import (
    10  	"testing"
    11  	"time"
    12  )
    13  
    14  func TestPacerStartup(t *testing.T) {
    15  	p := &pacerTest{
    16  		cwnd:             10000,
    17  		rtt:              100 * time.Millisecond,
    18  		timerGranularity: 1 * time.Millisecond,
    19  	}
    20  	p.init(t)
    21  	t.Logf("# initial burst permits sending ten packets")
    22  	for i := 0; i < 10; i++ {
    23  		p.sendPacket(1000)
    24  	}
    25  
    26  	t.Logf("# empty bucket allows for one more packet")
    27  	p.sendPacket(1000)
    28  
    29  	t.Logf("# sending 1000 byte packets with 8ms interval:")
    30  	t.Logf("#   (smoothed_rtt * packet_size / congestion_window) / 1.25")
    31  	t.Logf("#   (100ms * 1000 / 10000) / 1.25 = 8ms")
    32  	p.wantSendDelay(8 * time.Millisecond)
    33  	p.advance(8 * time.Millisecond)
    34  	p.sendPacket(1000)
    35  	p.wantSendDelay(8 * time.Millisecond)
    36  
    37  	t.Logf("# accumulate enough window for two packets")
    38  	p.advance(16 * time.Millisecond)
    39  	p.sendPacket(1000)
    40  	p.sendPacket(1000)
    41  	p.wantSendDelay(8 * time.Millisecond)
    42  
    43  	t.Logf("# window does not grow to more than burst limit")
    44  	p.advance(1 * time.Second)
    45  	for i := 0; i < 11; i++ {
    46  		p.sendPacket(1000)
    47  	}
    48  	p.wantSendDelay(8 * time.Millisecond)
    49  }
    50  
    51  func TestPacerTimerGranularity(t *testing.T) {
    52  	p := &pacerTest{
    53  		cwnd:             10000,
    54  		rtt:              100 * time.Millisecond,
    55  		timerGranularity: 1 * time.Millisecond,
    56  	}
    57  	p.init(t)
    58  	t.Logf("# consume initial burst")
    59  	for i := 0; i < 11; i++ {
    60  		p.sendPacket(1000)
    61  	}
    62  	p.wantSendDelay(8 * time.Millisecond)
    63  
    64  	t.Logf("# small advance in time does not permit sending")
    65  	p.advance(4 * time.Millisecond)
    66  	p.wantSendDelay(4 * time.Millisecond)
    67  
    68  	t.Logf("# advancing to within timerGranularity of next send permits send")
    69  	p.advance(3 * time.Millisecond)
    70  	p.wantSendDelay(0)
    71  
    72  	t.Logf("# early send adds skipped delay (1ms) to next send (8ms)")
    73  	p.sendPacket(1000)
    74  	p.wantSendDelay(9 * time.Millisecond)
    75  }
    76  
    77  func TestPacerChangingRate(t *testing.T) {
    78  	p := &pacerTest{
    79  		cwnd:             10000,
    80  		rtt:              100 * time.Millisecond,
    81  		timerGranularity: 0,
    82  	}
    83  	p.init(t)
    84  	t.Logf("# consume initial burst")
    85  	for i := 0; i < 11; i++ {
    86  		p.sendPacket(1000)
    87  	}
    88  	p.wantSendDelay(8 * time.Millisecond)
    89  	p.advance(8 * time.Millisecond)
    90  
    91  	t.Logf("# set congestion window to 20000, 1000 byte interval is 4ms")
    92  	p.cwnd = 20000
    93  	p.sendPacket(1000)
    94  	p.wantSendDelay(4 * time.Millisecond)
    95  	p.advance(4 * time.Millisecond)
    96  
    97  	t.Logf("# set rtt to 200ms, 1000 byte interval is 8ms")
    98  	p.rtt = 200 * time.Millisecond
    99  	p.sendPacket(1000)
   100  	p.wantSendDelay(8 * time.Millisecond)
   101  	p.advance(8 * time.Millisecond)
   102  
   103  	t.Logf("# set congestion window to 40000, 1000 byte interval is 4ms")
   104  	p.cwnd = 40000
   105  	p.advance(8 * time.Millisecond)
   106  	p.sendPacket(1000)
   107  	p.sendPacket(1000)
   108  	p.sendPacket(1000)
   109  	p.wantSendDelay(4 * time.Millisecond)
   110  }
   111  
   112  func TestPacerTimeReverses(t *testing.T) {
   113  	p := &pacerTest{
   114  		cwnd:             10000,
   115  		rtt:              100 * time.Millisecond,
   116  		timerGranularity: 0,
   117  	}
   118  	p.init(t)
   119  	t.Logf("# consume initial burst")
   120  	for i := 0; i < 11; i++ {
   121  		p.sendPacket(1000)
   122  	}
   123  	p.wantSendDelay(8 * time.Millisecond)
   124  	t.Logf("# reverse time")
   125  	p.advance(-4 * time.Millisecond)
   126  	p.sendPacket(1000)
   127  	p.wantSendDelay(8 * time.Millisecond)
   128  	p.advance(8 * time.Millisecond)
   129  	p.sendPacket(1000)
   130  	p.wantSendDelay(8 * time.Millisecond)
   131  }
   132  
   133  func TestPacerZeroRTT(t *testing.T) {
   134  	p := &pacerTest{
   135  		cwnd:             10000,
   136  		rtt:              0,
   137  		timerGranularity: 0,
   138  	}
   139  	p.init(t)
   140  	t.Logf("# with rtt 0, the pacer does not limit sending")
   141  	for i := 0; i < 20; i++ {
   142  		p.sendPacket(1000)
   143  	}
   144  	p.advance(1 * time.Second)
   145  	for i := 0; i < 20; i++ {
   146  		p.sendPacket(1000)
   147  	}
   148  }
   149  
   150  func TestPacerZeroCongestionWindow(t *testing.T) {
   151  	p := &pacerTest{
   152  		cwnd:             10000,
   153  		rtt:              100 * time.Millisecond,
   154  		timerGranularity: 0,
   155  	}
   156  	p.init(t)
   157  	p.cwnd = 0
   158  	t.Logf("# with cwnd 0, the pacer does not limit sending")
   159  	for i := 0; i < 20; i++ {
   160  		p.sendPacket(1000)
   161  	}
   162  }
   163  
   164  type pacerTest struct {
   165  	t                *testing.T
   166  	p                pacerState
   167  	timerGranularity time.Duration
   168  	cwnd             int
   169  	rtt              time.Duration
   170  	now              time.Time
   171  }
   172  
   173  func newPacerTest(t *testing.T, congestionWindow int, rtt time.Duration) *pacerTest {
   174  	p := &pacerTest{
   175  		now:  time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC),
   176  		cwnd: congestionWindow,
   177  		rtt:  rtt,
   178  	}
   179  	p.p.init(p.now, congestionWindow, p.timerGranularity)
   180  	return p
   181  }
   182  
   183  func (p *pacerTest) init(t *testing.T) {
   184  	p.t = t
   185  	p.now = time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)
   186  	p.p.init(p.now, p.cwnd, p.timerGranularity)
   187  	t.Logf("# initial congestion window: %v", p.cwnd)
   188  	t.Logf("# timer granularity: %v", p.timerGranularity)
   189  }
   190  
   191  func (p *pacerTest) advance(d time.Duration) {
   192  	p.t.Logf("advance time %v", d)
   193  	p.now = p.now.Add(d)
   194  	p.p.advance(p.now, p.cwnd, p.rtt)
   195  }
   196  
   197  func (p *pacerTest) sendPacket(size int) {
   198  	if canSend, next := p.p.canSend(p.now); !canSend {
   199  		p.t.Fatalf("ERROR: pacer unexpectedly blocked send, delay=%v", next.Sub(p.now))
   200  	}
   201  	p.t.Logf("send packet of size %v", size)
   202  	p.p.packetSent(p.now, size, p.cwnd, p.rtt)
   203  }
   204  
   205  func (p *pacerTest) wantSendDelay(want time.Duration) {
   206  	wantCanSend := want == 0
   207  	gotCanSend, next := p.p.canSend(p.now)
   208  	var got time.Duration
   209  	if !gotCanSend {
   210  		got = next.Sub(p.now)
   211  	}
   212  	p.t.Logf("# pacer send delay: %v", got)
   213  	if got != want || gotCanSend != wantCanSend {
   214  		p.t.Fatalf("ERROR: pacer send delay = %v (can send: %v); want %v, %v", got, gotCanSend, want, wantCanSend)
   215  	}
   216  }
   217  
   218  func (p *pacerTest) sendDelay() time.Duration {
   219  	canSend, next := p.p.canSend(p.now)
   220  	if canSend {
   221  		return 0
   222  	}
   223  	return next.Sub(p.now)
   224  }