diff --git a/quic/state/StreamData.h b/quic/state/StreamData.h index 245c2412a..04c5ffb78 100644 --- a/quic/state/StreamData.h +++ b/quic/state/StreamData.h @@ -345,6 +345,15 @@ struct QuicStreamLike { pendingWrites.splitAtMost(pendingWrites.chainLength()); } } + + [[nodiscard]] bool allBytesAckedTill(uint64_t offset) const { + if (ackedIntervals.empty()) { + return false; + } + + return ackedIntervals.front().start == 0 && + ackedIntervals.front().end >= offset; + } }; struct QuicConnectionStateBase; diff --git a/quic/state/test/StreamDataTest.cpp b/quic/state/test/StreamDataTest.cpp index df1f18f12..00bb993d3 100644 --- a/quic/state/test/StreamDataTest.cpp +++ b/quic/state/test/StreamDataTest.cpp @@ -585,4 +585,49 @@ TEST(StreamDataTest, WriteBufferMetaRemovalNoChange) { EXPECT_EQ(state.writeBufMeta.length, 12); } +TEST(StreamDataTest, AllBytesAckedTillEmptyAck) { + QuicConnectionStateBase qcsb(QuicNodeType::Client); + QuicStreamState state(0, qcsb); + + EXPECT_TRUE(state.ackedIntervals.empty()); + EXPECT_EQ(state.allBytesAckedTill(0), false); +} + +TEST(StreamDataTest, AllBytesAckedTillNotStartAtZero) { + QuicConnectionStateBase qcsb(QuicNodeType::Client); + QuicStreamState state(0, qcsb); + + EXPECT_TRUE(state.ackedIntervals.empty()); + state.updateAckedIntervals(1, 5, false); + EXPECT_EQ(state.allBytesAckedTill(5), false); +} + +TEST(StreamDataTest, AllBytesAckedTillNotEnoughLength) { + QuicConnectionStateBase qcsb(QuicNodeType::Client); + QuicStreamState state(0, qcsb); + + EXPECT_TRUE(state.ackedIntervals.empty()); + state.updateAckedIntervals(0, 5, false); + EXPECT_EQ(state.allBytesAckedTill(5), false); +} + +TEST(StreamDataTest, AllBytesAckedPass) { + QuicConnectionStateBase qcsb(QuicNodeType::Client); + QuicStreamState state(0, qcsb); + + EXPECT_TRUE(state.ackedIntervals.empty()); + state.updateAckedIntervals(0, 6, false); + EXPECT_EQ(state.allBytesAckedTill(5), true); +} + +TEST(StreamDataTest, AllBytesAckedDisjointIntervals) { + QuicConnectionStateBase qcsb(QuicNodeType::Client); + QuicStreamState state(0, qcsb); + + EXPECT_TRUE(state.ackedIntervals.empty()); + state.updateAckedIntervals(0, 2, false); + state.updateAckedIntervals(3, 5, false); + EXPECT_EQ(state.allBytesAckedTill(5), false); +} + } // namespace quic::test