blob: 1fcb735ff1635d60a8cb81e7b1942604d75425fc [file] [log] [blame]
// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package quic
import "testing"
func TestSkipPackets(t *testing.T) {
tc, s := newTestConnAndLocalStream(t, serverSide, uniStream, permissiveTransportParameters)
connWritesPacket := func() {
s.WriteByte(0)
s.Flush()
tc.wantFrameType("conn sends STREAM data",
packetType1RTT, debugFrameStream{})
tc.writeAckForLatest()
tc.wantIdle("conn is idle")
}
connWritesPacket()
expectSkip:
for maxUntilSkip := 256; maxUntilSkip <= 1024; maxUntilSkip *= 2 {
for range maxUntilSkip + 1 {
nextNum := tc.lastPacket.num + 1
connWritesPacket()
if tc.lastPacket.num == nextNum+1 {
// A packet number was skipped, as expected.
continue expectSkip
}
if tc.lastPacket.num != nextNum {
t.Fatalf("got packet number %v, want %v or %v+1", tc.lastPacket.num, nextNum, nextNum)
}
}
t.Fatalf("no numbers skipped after %v packets", maxUntilSkip)
}
}
func TestSkipAckForSkippedPacket(t *testing.T) {
tc, s := newTestConnAndLocalStream(t, serverSide, uniStream, permissiveTransportParameters)
// Cause the connection to send packets until it skips a packet number.
for {
// Cause the connection to send a packet.
last := tc.lastPacket
s.WriteByte(0)
s.Flush()
tc.wantFrameType("conn sends STREAM data",
packetType1RTT, debugFrameStream{})
if tc.lastPacket.num > 256 {
t.Fatalf("no numbers skipped after 256 packets")
}
// Acknowledge everything up to the packet before the one we just received.
// We don't acknowledge the most-recently-received packet, because doing
// so will cause the connection to drop state for the skipped packet number.
// (We only retain state up to the oldest in-flight packet.)
//
// If the conn has skipped a packet number, then this ack will improperly
// acknowledge the unsent packet.
t.Log(tc.lastPacket.num)
tc.writeFrames(tc.lastPacket.ptype, debugFrameAck{
ranges: []i64range[packetNumber]{{0, tc.lastPacket.num}},
})
if last != nil && tc.lastPacket.num == last.num+2 {
// The connection has skipped a packet number.
break
}
}
// We wrote an ACK for a skipped packet number.
// The connection should close.
tc.wantFrame("ACK for skipped packet causes CONNECTION_CLOSE",
packetType1RTT, debugFrameConnectionCloseTransport{
code: errProtocolViolation,
})
}