1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
package ackhandler
import (
"testing"
"time"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/utils"
"github.com/quic-go/quic-go/internal/wire"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
)
func TestGenerateACKsForPacketNumberSpaces(t *testing.T) {
ctrl := gomock.NewController(t)
sentPackets := NewMockSentPacketTracker(ctrl)
handler := newReceivedPacketHandler(sentPackets, utils.DefaultLogger)
now := time.Now()
sendTime := now.Add(-time.Second)
sentPackets.EXPECT().GetLowestPacketNotConfirmedAcked().AnyTimes()
sentPackets.EXPECT().ReceivedPacket(protocol.EncryptionInitial, sendTime).Times(2)
sentPackets.EXPECT().ReceivedPacket(protocol.EncryptionHandshake, sendTime).Times(2)
sentPackets.EXPECT().ReceivedPacket(protocol.Encryption1RTT, sendTime).Times(2)
require.NoError(t, handler.ReceivedPacket(2, protocol.ECT0, protocol.EncryptionInitial, sendTime, true))
require.NoError(t, handler.ReceivedPacket(1, protocol.ECT1, protocol.EncryptionHandshake, sendTime, true))
require.NoError(t, handler.ReceivedPacket(5, protocol.ECNCE, protocol.Encryption1RTT, sendTime, true))
require.NoError(t, handler.ReceivedPacket(3, protocol.ECT0, protocol.EncryptionInitial, sendTime, true))
require.NoError(t, handler.ReceivedPacket(2, protocol.ECT1, protocol.EncryptionHandshake, sendTime, true))
require.NoError(t, handler.ReceivedPacket(4, protocol.ECNCE, protocol.Encryption1RTT, sendTime, true))
// Initial
initialAck := handler.GetAckFrame(protocol.EncryptionInitial, now, true)
require.NotNil(t, initialAck)
require.Equal(t, []wire.AckRange{{Smallest: 2, Largest: 3}}, initialAck.AckRanges)
require.Zero(t, initialAck.DelayTime)
require.EqualValues(t, 2, initialAck.ECT0)
require.Zero(t, initialAck.ECT1)
require.Zero(t, initialAck.ECNCE)
// Handshake
handshakeAck := handler.GetAckFrame(protocol.EncryptionHandshake, now, true)
require.NotNil(t, handshakeAck)
require.Equal(t, []wire.AckRange{{Smallest: 1, Largest: 2}}, handshakeAck.AckRanges)
require.Zero(t, handshakeAck.DelayTime)
require.Zero(t, handshakeAck.ECT0)
require.EqualValues(t, 2, handshakeAck.ECT1)
require.Zero(t, handshakeAck.ECNCE)
// 1-RTT
oneRTTAck := handler.GetAckFrame(protocol.Encryption1RTT, now, true)
require.NotNil(t, oneRTTAck)
require.Equal(t, []wire.AckRange{{Smallest: 4, Largest: 5}}, oneRTTAck.AckRanges)
require.Equal(t, time.Second, oneRTTAck.DelayTime)
require.Zero(t, oneRTTAck.ECT0)
require.Zero(t, oneRTTAck.ECT1)
require.EqualValues(t, 2, oneRTTAck.ECNCE)
}
func TestReceive0RTTAnd1RTT(t *testing.T) {
mockCtrl := gomock.NewController(t)
sentPackets := NewMockSentPacketTracker(mockCtrl)
handler := newReceivedPacketHandler(sentPackets, utils.DefaultLogger)
sendTime := time.Now().Add(-time.Second)
sentPackets.EXPECT().GetLowestPacketNotConfirmedAcked().AnyTimes()
sentPackets.EXPECT().ReceivedPacket(protocol.Encryption0RTT, sendTime).AnyTimes()
sentPackets.EXPECT().ReceivedPacket(protocol.Encryption1RTT, sendTime)
require.NoError(t, handler.ReceivedPacket(2, protocol.ECNNon, protocol.Encryption0RTT, sendTime, true))
require.NoError(t, handler.ReceivedPacket(3, protocol.ECNNon, protocol.Encryption1RTT, sendTime, true))
ack := handler.GetAckFrame(protocol.Encryption1RTT, time.Now(), true)
require.NotNil(t, ack)
require.Equal(t, []wire.AckRange{{Smallest: 2, Largest: 3}}, ack.AckRanges)
// 0-RTT packets with higher packet numbers than 1-RTT packets are rejected...
require.Error(t, handler.ReceivedPacket(4, protocol.ECNNon, protocol.Encryption0RTT, sendTime, true))
// ... but reordered 0-RTT packets are allowed
require.NoError(t, handler.ReceivedPacket(1, protocol.ECNNon, protocol.Encryption0RTT, sendTime, true))
}
func TestDropPackets(t *testing.T) {
mockCtrl := gomock.NewController(t)
sentPackets := NewMockSentPacketTracker(mockCtrl)
sentPackets.EXPECT().ReceivedPacket(gomock.Any(), gomock.Any()).AnyTimes()
sentPackets.EXPECT().GetLowestPacketNotConfirmedAcked().AnyTimes()
handler := newReceivedPacketHandler(sentPackets, utils.DefaultLogger)
sendTime := time.Now().Add(-time.Second)
require.NoError(t, handler.ReceivedPacket(2, protocol.ECNNon, protocol.EncryptionInitial, sendTime, true))
require.NoError(t, handler.ReceivedPacket(1, protocol.ECNNon, protocol.EncryptionHandshake, sendTime, true))
require.NoError(t, handler.ReceivedPacket(2, protocol.ECNNon, protocol.Encryption1RTT, sendTime, true))
// Initial
require.NotNil(t, handler.GetAckFrame(protocol.EncryptionInitial, time.Now(), true))
handler.DropPackets(protocol.EncryptionInitial)
require.Nil(t, handler.GetAckFrame(protocol.EncryptionInitial, time.Now(), true))
// Handshake
require.NotNil(t, handler.GetAckFrame(protocol.EncryptionHandshake, time.Now(), true))
handler.DropPackets(protocol.EncryptionHandshake)
require.Nil(t, handler.GetAckFrame(protocol.EncryptionHandshake, time.Now(), true))
// 1-RTT
require.NotNil(t, handler.GetAckFrame(protocol.Encryption1RTT, time.Now(), true))
// 0-RTT is a no-op
handler.DropPackets(protocol.Encryption0RTT)
}
func TestAckRangePruning(t *testing.T) {
mockCtrl := gomock.NewController(t)
sentPackets := NewMockSentPacketTracker(mockCtrl)
sentPackets.EXPECT().ReceivedPacket(gomock.Any(), gomock.Any()).AnyTimes()
sentPackets.EXPECT().GetLowestPacketNotConfirmedAcked().Times(3)
handler := newReceivedPacketHandler(sentPackets, utils.DefaultLogger)
sendTime := time.Now()
require.NoError(t, handler.ReceivedPacket(1, protocol.ECNNon, protocol.Encryption1RTT, sendTime, true))
require.NoError(t, handler.ReceivedPacket(2, protocol.ECNNon, protocol.Encryption1RTT, sendTime, true))
ack := handler.GetAckFrame(protocol.Encryption1RTT, time.Now(), true)
require.NotNil(t, ack)
require.Equal(t, []wire.AckRange{{Smallest: 1, Largest: 2}}, ack.AckRanges)
require.NoError(t, handler.ReceivedPacket(3, protocol.ECNNon, protocol.Encryption1RTT, sendTime, true))
sentPackets.EXPECT().GetLowestPacketNotConfirmedAcked().Return(protocol.PacketNumber(2))
require.NoError(t, handler.ReceivedPacket(4, protocol.ECNNon, protocol.Encryption1RTT, sendTime, true))
ack = handler.GetAckFrame(protocol.Encryption1RTT, time.Now(), true)
require.NotNil(t, ack)
require.Equal(t, []wire.AckRange{{Smallest: 2, Largest: 4}}, ack.AckRanges)
}
func TestPacketDuplicateDetection(t *testing.T) {
mockCtrl := gomock.NewController(t)
sentPackets := NewMockSentPacketTracker(mockCtrl)
sentPackets.EXPECT().ReceivedPacket(gomock.Any(), gomock.Any()).AnyTimes()
sentPackets.EXPECT().GetLowestPacketNotConfirmedAcked().AnyTimes()
handler := newReceivedPacketHandler(sentPackets, utils.DefaultLogger)
sendTime := time.Now()
// 1-RTT is tested separately at the end
encLevels := []protocol.EncryptionLevel{
protocol.EncryptionInitial,
protocol.EncryptionHandshake,
protocol.Encryption0RTT,
}
for _, encLevel := range encLevels {
// first, packet 3 is not a duplicate
require.False(t, handler.IsPotentiallyDuplicate(3, encLevel))
require.NoError(t, handler.ReceivedPacket(3, protocol.ECNNon, encLevel, sendTime, true))
// now packet 3 is considered a duplicate
require.True(t, handler.IsPotentiallyDuplicate(3, encLevel))
}
// 1-RTT
require.True(t, handler.IsPotentiallyDuplicate(3, protocol.Encryption1RTT))
require.False(t, handler.IsPotentiallyDuplicate(4, protocol.Encryption1RTT))
require.NoError(t, handler.ReceivedPacket(4, protocol.ECNNon, protocol.Encryption1RTT, sendTime, true))
require.True(t, handler.IsPotentiallyDuplicate(4, protocol.Encryption1RTT))
}
|