package wire import ( "io" "math" "testing" "time" "github.com/quic-go/quic-go/internal/protocol" "github.com/quic-go/quic-go/quicvarint" "github.com/stretchr/testify/require" ) func TestParseACKWithoutRanges(t *testing.T) { data := encodeVarInt(100) // largest acked data = append(data, encodeVarInt(0)...) // delay data = append(data, encodeVarInt(0)...) // num blocks data = append(data, encodeVarInt(10)...) // first ack block var frame AckFrame n, err := parseAckFrame(&frame, data, FrameTypeAck, protocol.AckDelayExponent, protocol.Version1) require.NoError(t, err) require.Equal(t, len(data), n) require.Equal(t, protocol.PacketNumber(100), frame.LargestAcked()) require.Equal(t, protocol.PacketNumber(90), frame.LowestAcked()) require.False(t, frame.HasMissingRanges()) } func TestParseACKSinglePacket(t *testing.T) { data := encodeVarInt(55) // largest acked data = append(data, encodeVarInt(0)...) // delay data = append(data, encodeVarInt(0)...) // num blocks data = append(data, encodeVarInt(0)...) // first ack block var frame AckFrame n, err := parseAckFrame(&frame, data, FrameTypeAck, protocol.AckDelayExponent, protocol.Version1) require.NoError(t, err) require.Equal(t, len(data), n) require.Equal(t, protocol.PacketNumber(55), frame.LargestAcked()) require.Equal(t, protocol.PacketNumber(55), frame.LowestAcked()) require.False(t, frame.HasMissingRanges()) } func TestParseACKAllPacketsFrom0ToLargest(t *testing.T) { data := encodeVarInt(20) // largest acked data = append(data, encodeVarInt(0)...) // delay data = append(data, encodeVarInt(0)...) // num blocks data = append(data, encodeVarInt(20)...) // first ack block var frame AckFrame n, err := parseAckFrame(&frame, data, FrameTypeAck, protocol.AckDelayExponent, protocol.Version1) require.NoError(t, err) require.Equal(t, len(data), n) require.Equal(t, protocol.PacketNumber(20), frame.LargestAcked()) require.Equal(t, protocol.PacketNumber(0), frame.LowestAcked()) require.False(t, frame.HasMissingRanges()) } func TestParseACKRejectFirstBlockLargerThanLargestAcked(t *testing.T) { data := encodeVarInt(20) // largest acked data = append(data, encodeVarInt(0)...) // delay data = append(data, encodeVarInt(0)...) // num blocks data = append(data, encodeVarInt(21)...) // first ack block var frame AckFrame _, err := parseAckFrame(&frame, data, FrameTypeAck, protocol.AckDelayExponent, protocol.Version1) require.EqualError(t, err, "invalid first ACK range") } func TestParseACKWithSingleBlock(t *testing.T) { data := encodeVarInt(1000) // largest acked data = append(data, encodeVarInt(0)...) // delay data = append(data, encodeVarInt(1)...) // num blocks data = append(data, encodeVarInt(100)...) // first ack block data = append(data, encodeVarInt(98)...) // gap data = append(data, encodeVarInt(50)...) // ack block var frame AckFrame n, err := parseAckFrame(&frame, data, FrameTypeAck, protocol.AckDelayExponent, protocol.Version1) require.NoError(t, err) require.Equal(t, len(data), n) require.Equal(t, protocol.PacketNumber(1000), frame.LargestAcked()) require.Equal(t, protocol.PacketNumber(750), frame.LowestAcked()) require.True(t, frame.HasMissingRanges()) require.Equal(t, []AckRange{ {Largest: 1000, Smallest: 900}, {Largest: 800, Smallest: 750}, }, frame.AckRanges) } func TestParseACKWithMultipleBlocks(t *testing.T) { data := encodeVarInt(100) // largest acked data = append(data, encodeVarInt(0)...) // delay data = append(data, encodeVarInt(2)...) // num blocks data = append(data, encodeVarInt(0)...) // first ack block data = append(data, encodeVarInt(0)...) // gap data = append(data, encodeVarInt(0)...) // ack block data = append(data, encodeVarInt(1)...) // gap data = append(data, encodeVarInt(1)...) // ack block var frame AckFrame n, err := parseAckFrame(&frame, data, FrameTypeAck, protocol.AckDelayExponent, protocol.Version1) require.NoError(t, err) require.Equal(t, len(data), n) require.Equal(t, protocol.PacketNumber(100), frame.LargestAcked()) require.Equal(t, protocol.PacketNumber(94), frame.LowestAcked()) require.True(t, frame.HasMissingRanges()) require.Equal(t, []AckRange{ {Largest: 100, Smallest: 100}, {Largest: 98, Smallest: 98}, {Largest: 95, Smallest: 94}, }, frame.AckRanges) } func TestParseACKUseAckDelayExponent(t *testing.T) { const delayTime = 1 << 10 * time.Millisecond f := &AckFrame{ AckRanges: []AckRange{{Smallest: 1, Largest: 1}}, DelayTime: delayTime, } b, err := f.Append(nil, protocol.Version1) require.NoError(t, err) for i := uint8(0); i < 8; i++ { typ, l, err := quicvarint.Parse(b) require.NoError(t, err) var frame AckFrame n, err := parseAckFrame(&frame, b[l:], FrameType(typ), protocol.AckDelayExponent+i, protocol.Version1) require.NoError(t, err) require.Equal(t, len(b[l:]), n) require.Equal(t, delayTime*(1<