...

Source file src/golang.org/x/net/internal/quic/acks_test.go

Documentation: golang.org/x/net/internal/quic

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

View as plain text