mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-04 04:37:36 +03:00
uTLS is not yet bumped to the new version, so this commit breaks the dependencies relationship by getting rid of the local replace.
480 lines
18 KiB
Go
480 lines
18 KiB
Go
package wire
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"math"
|
|
"time"
|
|
|
|
"github.com/refraction-networking/uquic/internal/protocol"
|
|
"github.com/refraction-networking/uquic/quicvarint"
|
|
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
)
|
|
|
|
var _ = Describe("ACK Frame (for IETF QUIC)", func() {
|
|
Context("parsing", func() {
|
|
It("parses an ACK frame without any ranges", func() {
|
|
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
|
|
b := bytes.NewReader(data)
|
|
var frame AckFrame
|
|
Expect(parseAckFrame(&frame, b, ackFrameType, protocol.AckDelayExponent, protocol.Version1)).To(Succeed())
|
|
Expect(frame.LargestAcked()).To(Equal(protocol.PacketNumber(100)))
|
|
Expect(frame.LowestAcked()).To(Equal(protocol.PacketNumber(90)))
|
|
Expect(frame.HasMissingRanges()).To(BeFalse())
|
|
Expect(b.Len()).To(BeZero())
|
|
})
|
|
|
|
It("parses an ACK frame that only acks a single packet", func() {
|
|
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
|
|
b := bytes.NewReader(data)
|
|
var frame AckFrame
|
|
Expect(parseAckFrame(&frame, b, ackFrameType, protocol.AckDelayExponent, protocol.Version1)).To(Succeed())
|
|
Expect(frame.LargestAcked()).To(Equal(protocol.PacketNumber(55)))
|
|
Expect(frame.LowestAcked()).To(Equal(protocol.PacketNumber(55)))
|
|
Expect(frame.HasMissingRanges()).To(BeFalse())
|
|
Expect(b.Len()).To(BeZero())
|
|
})
|
|
|
|
It("accepts an ACK frame that acks all packets from 0 to largest", func() {
|
|
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
|
|
b := bytes.NewReader(data)
|
|
var frame AckFrame
|
|
Expect(parseAckFrame(&frame, b, ackFrameType, protocol.AckDelayExponent, protocol.Version1)).To(Succeed())
|
|
Expect(frame.LargestAcked()).To(Equal(protocol.PacketNumber(20)))
|
|
Expect(frame.LowestAcked()).To(Equal(protocol.PacketNumber(0)))
|
|
Expect(frame.HasMissingRanges()).To(BeFalse())
|
|
Expect(b.Len()).To(BeZero())
|
|
})
|
|
|
|
It("rejects an ACK frame that has a first ACK block which is larger than LargestAcked", func() {
|
|
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
|
|
Expect(parseAckFrame(&frame, bytes.NewReader(data), ackFrameType, protocol.AckDelayExponent, protocol.Version1)).To(MatchError("invalid first ACK range"))
|
|
})
|
|
|
|
It("parses an ACK frame that has a single block", func() {
|
|
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
|
|
b := bytes.NewReader(data)
|
|
var frame AckFrame
|
|
err := parseAckFrame(&frame, b, ackFrameType, protocol.AckDelayExponent, protocol.Version1)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(frame.LargestAcked()).To(Equal(protocol.PacketNumber(1000)))
|
|
Expect(frame.LowestAcked()).To(Equal(protocol.PacketNumber(750)))
|
|
Expect(frame.HasMissingRanges()).To(BeTrue())
|
|
Expect(frame.AckRanges).To(Equal([]AckRange{
|
|
{Largest: 1000, Smallest: 900},
|
|
{Largest: 800, Smallest: 750},
|
|
}))
|
|
Expect(b.Len()).To(BeZero())
|
|
})
|
|
|
|
It("parses an ACK frame that has a multiple blocks", func() {
|
|
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
|
|
b := bytes.NewReader(data)
|
|
var frame AckFrame
|
|
err := parseAckFrame(&frame, b, ackFrameType, protocol.AckDelayExponent, protocol.Version1)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(frame.LargestAcked()).To(Equal(protocol.PacketNumber(100)))
|
|
Expect(frame.LowestAcked()).To(Equal(protocol.PacketNumber(94)))
|
|
Expect(frame.HasMissingRanges()).To(BeTrue())
|
|
Expect(frame.AckRanges).To(Equal([]AckRange{
|
|
{Largest: 100, Smallest: 100},
|
|
{Largest: 98, Smallest: 98},
|
|
{Largest: 95, Smallest: 94},
|
|
}))
|
|
Expect(b.Len()).To(BeZero())
|
|
})
|
|
|
|
It("uses the ack delay exponent", func() {
|
|
const delayTime = 1 << 10 * time.Millisecond
|
|
f := &AckFrame{
|
|
AckRanges: []AckRange{{Smallest: 1, Largest: 1}},
|
|
DelayTime: delayTime,
|
|
}
|
|
b, err := f.Append(nil, protocol.Version1)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
for i := uint8(0); i < 8; i++ {
|
|
r := bytes.NewReader(b)
|
|
typ, err := quicvarint.Read(r)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
var frame AckFrame
|
|
Expect(parseAckFrame(&frame, r, typ, protocol.AckDelayExponent+i, protocol.Version1)).To(Succeed())
|
|
Expect(frame.DelayTime).To(Equal(delayTime * (1 << i)))
|
|
}
|
|
})
|
|
|
|
It("gracefully handles overflows of the delay time", func() {
|
|
data := encodeVarInt(100) // largest acked
|
|
data = append(data, encodeVarInt(math.MaxUint64/5)...) // delay
|
|
data = append(data, encodeVarInt(0)...) // num blocks
|
|
data = append(data, encodeVarInt(0)...) // first ack block
|
|
b := bytes.NewReader(data)
|
|
var frame AckFrame
|
|
err := parseAckFrame(&frame, b, ackFrameType, protocol.AckDelayExponent, protocol.Version1)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(frame.DelayTime).To(BeNumerically(">", 0))
|
|
// The maximum encodable duration is ~292 years.
|
|
Expect(frame.DelayTime.Hours()).To(BeNumerically("~", 292*365*24, 365*24))
|
|
})
|
|
|
|
It("errors on EOF", func() {
|
|
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
|
|
Expect(parseAckFrame(&frame, bytes.NewReader(data), ackFrameType, protocol.AckDelayExponent, protocol.Version1)).To(Succeed())
|
|
for i := range data {
|
|
var frame AckFrame
|
|
Expect(parseAckFrame(&frame, bytes.NewReader(data[:i]), ackFrameType, protocol.AckDelayExponent, protocol.Version1)).To(MatchError(io.EOF))
|
|
}
|
|
})
|
|
|
|
Context("ACK_ECN", func() {
|
|
It("parses", func() {
|
|
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
|
|
data = append(data, encodeVarInt(0x42)...) // ECT(0)
|
|
data = append(data, encodeVarInt(0x12345)...) // ECT(1)
|
|
data = append(data, encodeVarInt(0x12345678)...) // ECN-CE
|
|
b := bytes.NewReader(data)
|
|
var frame AckFrame
|
|
err := parseAckFrame(&frame, b, ackECNFrameType, protocol.AckDelayExponent, protocol.Version1)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(frame.LargestAcked()).To(Equal(protocol.PacketNumber(100)))
|
|
Expect(frame.LowestAcked()).To(Equal(protocol.PacketNumber(90)))
|
|
Expect(frame.HasMissingRanges()).To(BeFalse())
|
|
Expect(frame.ECT0).To(BeEquivalentTo(0x42))
|
|
Expect(frame.ECT1).To(BeEquivalentTo(0x12345))
|
|
Expect(frame.ECNCE).To(BeEquivalentTo(0x12345678))
|
|
Expect(b.Len()).To(BeZero())
|
|
})
|
|
|
|
It("errors on EOF", func() {
|
|
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
|
|
data = append(data, encodeVarInt(0x42)...) // ECT(0)
|
|
data = append(data, encodeVarInt(0x12345)...) // ECT(1)
|
|
data = append(data, encodeVarInt(0x12345678)...) // ECN-CE
|
|
var frame AckFrame
|
|
Expect(parseAckFrame(&frame, bytes.NewReader(data), ackECNFrameType, protocol.AckDelayExponent, protocol.Version1)).To(Succeed())
|
|
for i := range data {
|
|
var frame AckFrame
|
|
Expect(parseAckFrame(&frame, bytes.NewReader(data[:i]), ackECNFrameType, protocol.AckDelayExponent, protocol.Version1)).To(MatchError(io.EOF))
|
|
}
|
|
})
|
|
})
|
|
})
|
|
|
|
Context("when writing", func() {
|
|
It("writes a simple frame", func() {
|
|
f := &AckFrame{
|
|
AckRanges: []AckRange{{Smallest: 100, Largest: 1337}},
|
|
}
|
|
b, err := f.Append(nil, protocol.Version1)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
expected := []byte{ackFrameType}
|
|
expected = append(expected, encodeVarInt(1337)...) // largest acked
|
|
expected = append(expected, 0) // delay
|
|
expected = append(expected, encodeVarInt(0)...) // num ranges
|
|
expected = append(expected, encodeVarInt(1337-100)...)
|
|
Expect(b).To(Equal(expected))
|
|
})
|
|
|
|
It("writes an ACK-ECN frame", func() {
|
|
f := &AckFrame{
|
|
AckRanges: []AckRange{{Smallest: 10, Largest: 2000}},
|
|
ECT0: 13,
|
|
ECT1: 37,
|
|
ECNCE: 12345,
|
|
}
|
|
b, err := f.Append(nil, protocol.Version1)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(b).To(HaveLen(int(f.Length(protocol.Version1))))
|
|
expected := []byte{ackECNFrameType}
|
|
expected = append(expected, encodeVarInt(2000)...) // largest acked
|
|
expected = append(expected, 0) // delay
|
|
expected = append(expected, encodeVarInt(0)...) // num ranges
|
|
expected = append(expected, encodeVarInt(2000-10)...)
|
|
expected = append(expected, encodeVarInt(13)...)
|
|
expected = append(expected, encodeVarInt(37)...)
|
|
expected = append(expected, encodeVarInt(12345)...)
|
|
Expect(b).To(Equal(expected))
|
|
})
|
|
|
|
It("writes a frame that acks a single packet", func() {
|
|
f := &AckFrame{
|
|
AckRanges: []AckRange{{Smallest: 0x2eadbeef, Largest: 0x2eadbeef}},
|
|
DelayTime: 18 * time.Millisecond,
|
|
}
|
|
b, err := f.Append(nil, protocol.Version1)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(b).To(HaveLen(int(f.Length(protocol.Version1))))
|
|
r := bytes.NewReader(b)
|
|
typ, err := quicvarint.Read(r)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
var frame AckFrame
|
|
Expect(parseAckFrame(&frame, r, typ, protocol.AckDelayExponent, protocol.Version1)).To(Succeed())
|
|
Expect(&frame).To(Equal(f))
|
|
Expect(frame.HasMissingRanges()).To(BeFalse())
|
|
Expect(frame.DelayTime).To(Equal(f.DelayTime))
|
|
Expect(r.Len()).To(BeZero())
|
|
})
|
|
|
|
It("writes a frame that acks many packets", func() {
|
|
f := &AckFrame{
|
|
AckRanges: []AckRange{{Smallest: 0x1337, Largest: 0x2eadbeef}},
|
|
}
|
|
b, err := f.Append(nil, protocol.Version1)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(b).To(HaveLen(int(f.Length(protocol.Version1))))
|
|
r := bytes.NewReader(b)
|
|
typ, err := quicvarint.Read(r)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
var frame AckFrame
|
|
Expect(parseAckFrame(&frame, r, typ, protocol.AckDelayExponent, protocol.Version1)).To(Succeed())
|
|
Expect(&frame).To(Equal(f))
|
|
Expect(frame.HasMissingRanges()).To(BeFalse())
|
|
Expect(r.Len()).To(BeZero())
|
|
})
|
|
|
|
It("writes a frame with a a single gap", func() {
|
|
f := &AckFrame{
|
|
AckRanges: []AckRange{
|
|
{Smallest: 400, Largest: 1000},
|
|
{Smallest: 100, Largest: 200},
|
|
},
|
|
}
|
|
Expect(f.validateAckRanges()).To(BeTrue())
|
|
b, err := f.Append(nil, protocol.Version1)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(b).To(HaveLen(int(f.Length(protocol.Version1))))
|
|
r := bytes.NewReader(b)
|
|
typ, err := quicvarint.Read(r)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
var frame AckFrame
|
|
Expect(parseAckFrame(&frame, r, typ, protocol.AckDelayExponent, protocol.Version1)).To(Succeed())
|
|
Expect(&frame).To(Equal(f))
|
|
Expect(frame.HasMissingRanges()).To(BeTrue())
|
|
Expect(r.Len()).To(BeZero())
|
|
})
|
|
|
|
It("writes a frame with multiple ranges", func() {
|
|
f := &AckFrame{
|
|
AckRanges: []AckRange{
|
|
{Smallest: 10, Largest: 10},
|
|
{Smallest: 8, Largest: 8},
|
|
{Smallest: 5, Largest: 6},
|
|
{Smallest: 1, Largest: 3},
|
|
},
|
|
}
|
|
Expect(f.validateAckRanges()).To(BeTrue())
|
|
b, err := f.Append(nil, protocol.Version1)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(b).To(HaveLen(int(f.Length(protocol.Version1))))
|
|
r := bytes.NewReader(b)
|
|
typ, err := quicvarint.Read(r)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
var frame AckFrame
|
|
Expect(parseAckFrame(&frame, r, typ, protocol.AckDelayExponent, protocol.Version1)).To(Succeed())
|
|
Expect(&frame).To(Equal(f))
|
|
Expect(frame.HasMissingRanges()).To(BeTrue())
|
|
Expect(r.Len()).To(BeZero())
|
|
})
|
|
|
|
It("limits the maximum size of the ACK frame", func() {
|
|
const numRanges = 1000
|
|
ackRanges := make([]AckRange, numRanges)
|
|
for i := protocol.PacketNumber(1); i <= numRanges; i++ {
|
|
ackRanges[numRanges-i] = AckRange{Smallest: 2 * i, Largest: 2 * i}
|
|
}
|
|
f := &AckFrame{AckRanges: ackRanges}
|
|
Expect(f.validateAckRanges()).To(BeTrue())
|
|
b, err := f.Append(nil, protocol.Version1)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(b).To(HaveLen(int(f.Length(protocol.Version1))))
|
|
// make sure the ACK frame is *a little bit* smaller than the MaxAckFrameSize
|
|
Expect(len(b)).To(BeNumerically(">", protocol.MaxAckFrameSize-5))
|
|
Expect(len(b)).To(BeNumerically("<=", protocol.MaxAckFrameSize))
|
|
r := bytes.NewReader(b)
|
|
typ, err := quicvarint.Read(r)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
var frame AckFrame
|
|
Expect(parseAckFrame(&frame, r, typ, protocol.AckDelayExponent, protocol.Version1)).To(Succeed())
|
|
Expect(frame.HasMissingRanges()).To(BeTrue())
|
|
Expect(r.Len()).To(BeZero())
|
|
Expect(len(frame.AckRanges)).To(BeNumerically("<", numRanges)) // make sure we dropped some ranges
|
|
})
|
|
})
|
|
|
|
Context("ACK range validator", func() {
|
|
It("rejects ACKs without ranges", func() {
|
|
Expect((&AckFrame{}).validateAckRanges()).To(BeFalse())
|
|
})
|
|
|
|
It("accepts an ACK without NACK Ranges", func() {
|
|
ack := AckFrame{
|
|
AckRanges: []AckRange{{Smallest: 1, Largest: 7}},
|
|
}
|
|
Expect(ack.validateAckRanges()).To(BeTrue())
|
|
})
|
|
|
|
It("rejects ACK ranges with Smallest greater than Largest", func() {
|
|
ack := AckFrame{
|
|
AckRanges: []AckRange{
|
|
{Smallest: 8, Largest: 10},
|
|
{Smallest: 4, Largest: 3},
|
|
},
|
|
}
|
|
Expect(ack.validateAckRanges()).To(BeFalse())
|
|
})
|
|
|
|
It("rejects ACK ranges in the wrong order", func() {
|
|
ack := AckFrame{
|
|
AckRanges: []AckRange{
|
|
{Smallest: 2, Largest: 2},
|
|
{Smallest: 6, Largest: 7},
|
|
},
|
|
}
|
|
Expect(ack.validateAckRanges()).To(BeFalse())
|
|
})
|
|
|
|
It("rejects with overlapping ACK ranges", func() {
|
|
ack := AckFrame{
|
|
AckRanges: []AckRange{
|
|
{Smallest: 5, Largest: 7},
|
|
{Smallest: 2, Largest: 5},
|
|
},
|
|
}
|
|
Expect(ack.validateAckRanges()).To(BeFalse())
|
|
})
|
|
|
|
It("rejects ACK ranges that are part of a larger ACK range", func() {
|
|
ack := AckFrame{
|
|
AckRanges: []AckRange{
|
|
{Smallest: 4, Largest: 7},
|
|
{Smallest: 5, Largest: 6},
|
|
},
|
|
}
|
|
Expect(ack.validateAckRanges()).To(BeFalse())
|
|
})
|
|
|
|
It("rejects with directly adjacent ACK ranges", func() {
|
|
ack := AckFrame{
|
|
AckRanges: []AckRange{
|
|
{Smallest: 5, Largest: 7},
|
|
{Smallest: 2, Largest: 4},
|
|
},
|
|
}
|
|
Expect(ack.validateAckRanges()).To(BeFalse())
|
|
})
|
|
|
|
It("accepts an ACK with one lost packet", func() {
|
|
ack := AckFrame{
|
|
AckRanges: []AckRange{
|
|
{Smallest: 5, Largest: 10},
|
|
{Smallest: 1, Largest: 3},
|
|
},
|
|
}
|
|
Expect(ack.validateAckRanges()).To(BeTrue())
|
|
})
|
|
|
|
It("accepts an ACK with multiple lost packets", func() {
|
|
ack := AckFrame{
|
|
AckRanges: []AckRange{
|
|
{Smallest: 15, Largest: 20},
|
|
{Smallest: 10, Largest: 12},
|
|
{Smallest: 1, Largest: 3},
|
|
},
|
|
}
|
|
Expect(ack.validateAckRanges()).To(BeTrue())
|
|
})
|
|
})
|
|
|
|
Context("check if ACK frame acks a certain packet", func() {
|
|
It("works with an ACK without any ranges", func() {
|
|
f := AckFrame{
|
|
AckRanges: []AckRange{{Smallest: 5, Largest: 10}},
|
|
}
|
|
Expect(f.AcksPacket(1)).To(BeFalse())
|
|
Expect(f.AcksPacket(4)).To(BeFalse())
|
|
Expect(f.AcksPacket(5)).To(BeTrue())
|
|
Expect(f.AcksPacket(8)).To(BeTrue())
|
|
Expect(f.AcksPacket(10)).To(BeTrue())
|
|
Expect(f.AcksPacket(11)).To(BeFalse())
|
|
Expect(f.AcksPacket(20)).To(BeFalse())
|
|
})
|
|
|
|
It("works with an ACK with multiple ACK ranges", func() {
|
|
f := AckFrame{
|
|
AckRanges: []AckRange{
|
|
{Smallest: 15, Largest: 20},
|
|
{Smallest: 5, Largest: 8},
|
|
},
|
|
}
|
|
Expect(f.AcksPacket(4)).To(BeFalse())
|
|
Expect(f.AcksPacket(5)).To(BeTrue())
|
|
Expect(f.AcksPacket(6)).To(BeTrue())
|
|
Expect(f.AcksPacket(7)).To(BeTrue())
|
|
Expect(f.AcksPacket(8)).To(BeTrue())
|
|
Expect(f.AcksPacket(9)).To(BeFalse())
|
|
Expect(f.AcksPacket(14)).To(BeFalse())
|
|
Expect(f.AcksPacket(15)).To(BeTrue())
|
|
Expect(f.AcksPacket(18)).To(BeTrue())
|
|
Expect(f.AcksPacket(19)).To(BeTrue())
|
|
Expect(f.AcksPacket(20)).To(BeTrue())
|
|
Expect(f.AcksPacket(21)).To(BeFalse())
|
|
})
|
|
})
|
|
|
|
It("resets", func() {
|
|
f := &AckFrame{
|
|
DelayTime: time.Second,
|
|
AckRanges: []AckRange{{Smallest: 1, Largest: 3}},
|
|
ECT0: 1,
|
|
ECT1: 2,
|
|
ECNCE: 3,
|
|
}
|
|
f.Reset()
|
|
Expect(f.AckRanges).To(BeEmpty())
|
|
Expect(f.AckRanges).To(HaveCap(1))
|
|
Expect(f.DelayTime).To(BeZero())
|
|
Expect(f.ECT0).To(BeZero())
|
|
Expect(f.ECT1).To(BeZero())
|
|
Expect(f.ECNCE).To(BeZero())
|
|
})
|
|
})
|