Skip to content

Commit c68c32d

Browse files
committed
Fix bad assert and add missing test case
1 parent 105d0b7 commit c68c32d

File tree

2 files changed

+62
-1
lines changed

2 files changed

+62
-1
lines changed

src/core/recv_buffer.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,6 @@ QuicRecvBufferResize(
454454
TargetBufferLength != 0 &&
455455
(TargetBufferLength & (TargetBufferLength - 1)) == 0); // Power of 2
456456
CXPLAT_DBG_ASSERT(!CxPlatListIsEmpty(&RecvBuffer->Chunks)); // Should always have at least one chunk
457-
CXPLAT_DBG_ASSERT(RecvBuffer->RetiredChunk == NULL);
458457

459458
QUIC_RECV_CHUNK* LastChunk =
460459
CXPLAT_CONTAINING_RECORD(RecvBuffer->Chunks.Blink, QUIC_RECV_CHUNK, Link);
@@ -527,10 +526,12 @@ QuicRecvBufferResize(
527526
if (LastChunk->ExternalReference) {
528527
//
529528
// The chunk is referenced, so we need to retire it until we can free it.
529+
// (only one read can be pending at a time, so there is no retired chunk)
530530
//
531531
CXPLAT_DBG_ASSERT(
532532
RecvBuffer->RecvMode == QUIC_RECV_BUF_MODE_SINGLE ||
533533
RecvBuffer->RecvMode == QUIC_RECV_BUF_MODE_CIRCULAR);
534+
CXPLAT_DBG_ASSERT(RecvBuffer->RetiredChunk == NULL);
534535

535536
RecvBuffer->RetiredChunk = LastChunk;
536537
} else {

src/core/unittest/RecvBufferTest.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,66 @@ TEST_P(WithMode, MultiWriteLarge)
704704
ASSERT_FALSE(RecvBuf.HasUnreadData());
705705
}
706706

707+
TEST_P(WithMode, MultiWriteLargeWhileReadPending)
708+
{
709+
auto Mode = GetParam();
710+
RecvBuffer RecvBuf{};
711+
ASSERT_EQ(QUIC_STATUS_SUCCESS, RecvBuf.Initialize(Mode, false, DEF_TEST_BUFFER_LENGTH, LARGE_TEST_BUFFER_LENGTH));
712+
713+
//
714+
// Write some data and read it so a read operation is pending
715+
//
716+
{
717+
uint64_t InOutWriteLength = LARGE_TEST_BUFFER_LENGTH; // FC limit same as recv buffer size
718+
BOOLEAN DataReady = FALSE;
719+
ASSERT_EQ(QUIC_STATUS_SUCCESS, RecvBuf.Write(0, 64, &InOutWriteLength, &DataReady));
720+
721+
uint64_t ReadOffset{};
722+
QUIC_BUFFER ReadBuffers[3]{};
723+
uint32_t BufferCount = ARRAYSIZE(ReadBuffers);
724+
RecvBuf.Read(&ReadOffset, &BufferCount, ReadBuffers);
725+
ASSERT_FALSE(RecvBuf.HasUnreadData());
726+
ASSERT_EQ(1u, BufferCount);
727+
ASSERT_EQ(64u, ReadBuffers[0].Length);
728+
}
729+
730+
//
731+
// Write more data while the read is pending, forcing buffer re-allocations
732+
//
733+
for (uint32_t i = 1; i < 4; ++i) {
734+
uint64_t InOutWriteLength = LARGE_TEST_BUFFER_LENGTH; // FC limit same as recv buffer size
735+
BOOLEAN DataReady = FALSE;
736+
ASSERT_EQ(QUIC_STATUS_SUCCESS, RecvBuf.Write(i * 64, 64, &InOutWriteLength, &DataReady));
737+
ASSERT_TRUE(DataReady);
738+
ASSERT_TRUE(RecvBuf.HasUnreadData());
739+
ASSERT_EQ(64ull, InOutWriteLength);
740+
ASSERT_EQ((i + 1) * 64ull, RecvBuf.GetTotalLength());
741+
}
742+
743+
//
744+
// Drain the data from the first read
745+
//
746+
ASSERT_FALSE(RecvBuf.Drain(64));
747+
748+
//
749+
// Read all the remaining data
750+
//
751+
uint64_t ReadOffset{};
752+
QUIC_BUFFER ReadBuffers[3]{};
753+
uint32_t BufferCount = ARRAYSIZE(ReadBuffers);
754+
RecvBuf.Read(&ReadOffset, &BufferCount, ReadBuffers);
755+
ASSERT_FALSE(RecvBuf.HasUnreadData());
756+
ASSERT_EQ(64ull, ReadOffset);
757+
ASSERT_EQ(1u, BufferCount);
758+
ASSERT_EQ(192u, ReadBuffers[0].Length);
759+
760+
//
761+
// Drain all the data.
762+
//
763+
ASSERT_TRUE(RecvBuf.Drain(192));
764+
ASSERT_FALSE(RecvBuf.HasUnreadData());
765+
}
766+
707767
TEST_P(WithMode, ReadPartial)
708768
{
709769
RecvBuffer RecvBuf;

0 commit comments

Comments
 (0)