golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/quic/acks_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  	"slices"
    11  	"testing"
    12  	"time"
    13  )
    14  
    15  func TestAcksDisallowDuplicate(t *testing.T) {
    16  	// Don't process a packet that we've seen before.
    17  	acks := ackState{}
    18  	now := time.Now()
    19  	receive := []packetNumber{0, 1, 2, 4, 7, 6, 9}
    20  	seen := map[packetNumber]bool{}
    21  	for i, pnum := range receive {
    22  		acks.receive(now, appDataSpace, pnum, true)
    23  		seen[pnum] = true
    24  		for ppnum := packetNumber(0); ppnum < 11; ppnum++ {
    25  			if got, want := acks.shouldProcess(ppnum), !seen[ppnum]; got != want {
    26  				t.Fatalf("after receiving %v: acks.shouldProcess(%v) = %v, want %v", receive[:i+1], ppnum, got, want)
    27  			}
    28  		}
    29  	}
    30  }
    31  
    32  func TestAcksDisallowDiscardedAckRanges(t *testing.T) {
    33  	// Don't process a packet with a number in a discarded range.
    34  	acks := ackState{}
    35  	now := time.Now()
    36  	for pnum := packetNumber(0); ; pnum += 2 {
    37  		acks.receive(now, appDataSpace, pnum, true)
    38  		send, _ := acks.acksToSend(now)
    39  		for ppnum := packetNumber(0); ppnum < packetNumber(send.min()); ppnum++ {
    40  			if acks.shouldProcess(ppnum) {
    41  				t.Fatalf("after limiting ack ranges to %v: acks.shouldProcess(%v) (in discarded range) = true, want false", send, ppnum)
    42  			}
    43  		}
    44  		if send.min() > 10 {
    45  			break
    46  		}
    47  	}
    48  }
    49  
    50  func TestAcksSent(t *testing.T) {
    51  	type packet struct {
    52  		pnum         packetNumber
    53  		ackEliciting bool
    54  	}
    55  	for _, test := range []struct {
    56  		name  string
    57  		space numberSpace
    58  
    59  		// ackedPackets and packets are packets that we receive.
    60  		// After receiving all packets in ackedPackets, we send an ack.
    61  		// Then we receive the subsequent packets in packets.
    62  		ackedPackets []packet
    63  		packets      []packet
    64  
    65  		wantDelay time.Duration
    66  		wantAcks  rangeset[packetNumber]
    67  	}{{
    68  		name:  "no packets to ack",
    69  		space: initialSpace,
    70  	}, {
    71  		name:  "non-ack-eliciting packets are not acked",
    72  		space: initialSpace,
    73  		packets: []packet{{
    74  			pnum:         0,
    75  			ackEliciting: false,
    76  		}},
    77  	}, {
    78  		name:  "ack-eliciting Initial packets are acked immediately",
    79  		space: initialSpace,
    80  		packets: []packet{{
    81  			pnum:         0,
    82  			ackEliciting: true,
    83  		}},
    84  		wantAcks:  rangeset[packetNumber]{{0, 1}},
    85  		wantDelay: 0,
    86  	}, {
    87  		name:  "ack-eliciting Handshake packets are acked immediately",
    88  		space: handshakeSpace,
    89  		packets: []packet{{
    90  			pnum:         0,
    91  			ackEliciting: true,
    92  		}},
    93  		wantAcks:  rangeset[packetNumber]{{0, 1}},
    94  		wantDelay: 0,
    95  	}, {
    96  		name:  "ack-eliciting AppData packets are acked after max_ack_delay",
    97  		space: appDataSpace,
    98  		packets: []packet{{
    99  			pnum:         0,
   100  			ackEliciting: true,
   101  		}},
   102  		wantAcks:  rangeset[packetNumber]{{0, 1}},
   103  		wantDelay: maxAckDelay - timerGranularity,
   104  	}, {
   105  		name:  "reordered ack-eliciting packets are acked immediately",
   106  		space: appDataSpace,
   107  		ackedPackets: []packet{{
   108  			pnum:         1,
   109  			ackEliciting: true,
   110  		}},
   111  		packets: []packet{{
   112  			pnum:         0,
   113  			ackEliciting: true,
   114  		}},
   115  		wantAcks:  rangeset[packetNumber]{{0, 2}},
   116  		wantDelay: 0,
   117  	}, {
   118  		name:  "gaps in ack-eliciting packets are acked immediately",
   119  		space: appDataSpace,
   120  		packets: []packet{{
   121  			pnum:         1,
   122  			ackEliciting: true,
   123  		}},
   124  		wantAcks:  rangeset[packetNumber]{{1, 2}},
   125  		wantDelay: 0,
   126  	}, {
   127  		name:  "reordered non-ack-eliciting packets are not acked immediately",
   128  		space: appDataSpace,
   129  		ackedPackets: []packet{{
   130  			pnum:         1,
   131  			ackEliciting: true,
   132  		}},
   133  		packets: []packet{{
   134  			pnum:         2,
   135  			ackEliciting: true,
   136  		}, {
   137  			pnum:         0,
   138  			ackEliciting: false,
   139  		}, {
   140  			pnum:         4,
   141  			ackEliciting: false,
   142  		}},
   143  		wantAcks:  rangeset[packetNumber]{{0, 3}, {4, 5}},
   144  		wantDelay: maxAckDelay - timerGranularity,
   145  	}, {
   146  		name:  "immediate ack after two ack-eliciting packets are received",
   147  		space: appDataSpace,
   148  		packets: []packet{{
   149  			pnum:         0,
   150  			ackEliciting: true,
   151  		}, {
   152  			pnum:         1,
   153  			ackEliciting: true,
   154  		}},
   155  		wantAcks:  rangeset[packetNumber]{{0, 2}},
   156  		wantDelay: 0,
   157  	}} {
   158  		t.Run(test.name, func(t *testing.T) {
   159  			acks := ackState{}
   160  			start := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
   161  			for _, p := range test.ackedPackets {
   162  				t.Logf("receive %v.%v, ack-eliciting=%v", test.space, p.pnum, p.ackEliciting)
   163  				acks.receive(start, test.space, p.pnum, p.ackEliciting)
   164  			}
   165  			t.Logf("send an ACK frame")
   166  			acks.sentAck()
   167  			for _, p := range test.packets {
   168  				t.Logf("receive %v.%v, ack-eliciting=%v", test.space, p.pnum, p.ackEliciting)
   169  				acks.receive(start, test.space, p.pnum, p.ackEliciting)
   170  			}
   171  			switch {
   172  			case len(test.wantAcks) == 0:
   173  				// No ACK should be sent, even well after max_ack_delay.
   174  				if acks.shouldSendAck(start.Add(10 * maxAckDelay)) {
   175  					t.Errorf("acks.shouldSendAck(T+10*max_ack_delay) = true, want false")
   176  				}
   177  			case test.wantDelay > 0:
   178  				// No ACK should be sent before a delay.
   179  				if acks.shouldSendAck(start.Add(test.wantDelay - 1)) {
   180  					t.Errorf("acks.shouldSendAck(T+%v-1ns) = true, want false", test.wantDelay)
   181  				}
   182  				fallthrough
   183  			default:
   184  				// ACK should be sent after a delay.
   185  				if !acks.shouldSendAck(start.Add(test.wantDelay)) {
   186  					t.Errorf("acks.shouldSendAck(T+%v) = false, want true", test.wantDelay)
   187  				}
   188  			}
   189  			// acksToSend always reports the available packets that can be acked,
   190  			// and the amount of time that has passed since the most recent acked
   191  			// packet was received.
   192  			for _, delay := range []time.Duration{
   193  				0,
   194  				test.wantDelay,
   195  				test.wantDelay + 1,
   196  			} {
   197  				gotNums, gotDelay := acks.acksToSend(start.Add(delay))
   198  				wantDelay := delay
   199  				if len(gotNums) == 0 {
   200  					wantDelay = 0
   201  				}
   202  				if !slices.Equal(gotNums, test.wantAcks) || gotDelay != wantDelay {
   203  					t.Errorf("acks.acksToSend(T+%v) = %v, %v; want %v, %v", delay, gotNums, gotDelay, test.wantAcks, wantDelay)
   204  				}
   205  			}
   206  		})
   207  	}
   208  }
   209  
   210  func TestAcksDiscardAfterAck(t *testing.T) {
   211  	acks := ackState{}
   212  	now := time.Now()
   213  	acks.receive(now, appDataSpace, 0, true)
   214  	acks.receive(now, appDataSpace, 2, true)
   215  	acks.receive(now, appDataSpace, 4, true)
   216  	acks.receive(now, appDataSpace, 5, true)
   217  	acks.receive(now, appDataSpace, 6, true)
   218  	acks.handleAck(6) // discards all ranges prior to the one containing packet 6
   219  	acks.receive(now, appDataSpace, 7, true)
   220  	got, _ := acks.acksToSend(now)
   221  	if len(got) != 1 {
   222  		t.Errorf("acks.acksToSend contains ranges prior to last acknowledged ack; got %v, want 1 range", got)
   223  	}
   224  }
   225  
   226  func TestAcksLargestSeen(t *testing.T) {
   227  	acks := ackState{}
   228  	now := time.Now()
   229  	acks.receive(now, appDataSpace, 0, true)
   230  	acks.receive(now, appDataSpace, 4, true)
   231  	acks.receive(now, appDataSpace, 1, true)
   232  	if got, want := acks.largestSeen(), packetNumber(4); got != want {
   233  		t.Errorf("acks.largestSeen() = %v, want %v", got, want)
   234  	}
   235  }