mirror of
https://github.com/facebookincubator/mvfst.git
synced 2025-08-08 09:42:06 +03:00
Implement group streams receiver api in transport
Summary: Implement group streams receiver api in transport Reviewed By: mjoras Differential Revision: D36419901 fbshipit-source-id: 98bfefa1a4205fde8764f2e4300f51156667e024
This commit is contained in:
committed by
Facebook GitHub Bot
parent
451b519280
commit
e208ceffdd
@@ -39,15 +39,26 @@ enum class TestFrameType : uint8_t {
|
||||
EXPIRED_DATA,
|
||||
REJECTED_DATA,
|
||||
MAX_STREAMS,
|
||||
DATAGRAM
|
||||
DATAGRAM,
|
||||
STREAM_GROUP
|
||||
};
|
||||
|
||||
// A made up encoding decoding of a stream.
|
||||
Buf encodeStreamBuffer(StreamId id, StreamBuffer data) {
|
||||
Buf encodeStreamBuffer(
|
||||
StreamId id,
|
||||
StreamBuffer data,
|
||||
folly::Optional<StreamGroupId> groupId = folly::none) {
|
||||
auto buf = IOBuf::create(10);
|
||||
folly::io::Appender appender(buf.get(), 10);
|
||||
appender.writeBE(static_cast<uint8_t>(TestFrameType::STREAM));
|
||||
if (!groupId) {
|
||||
appender.writeBE(static_cast<uint8_t>(TestFrameType::STREAM));
|
||||
} else {
|
||||
appender.writeBE(static_cast<uint8_t>(TestFrameType::STREAM_GROUP));
|
||||
}
|
||||
appender.writeBE(id);
|
||||
if (groupId) {
|
||||
appender.writeBE(*groupId);
|
||||
}
|
||||
auto dataBuf = data.data.move();
|
||||
dataBuf->coalesce();
|
||||
appender.writeBE<uint32_t>(dataBuf->length());
|
||||
@@ -116,6 +127,23 @@ std::pair<StreamId, StreamBuffer> decodeStreamBuffer(
|
||||
StreamBuffer(std::move(dataBuffer.first), dataBuffer.second, eof));
|
||||
}
|
||||
|
||||
struct StreamGroupIdBuf {
|
||||
StreamId id;
|
||||
StreamGroupId groupId;
|
||||
StreamBuffer buf;
|
||||
};
|
||||
|
||||
StreamGroupIdBuf decodeStreamGroupBuffer(folly::io::Cursor& cursor) {
|
||||
auto streamId = cursor.readBE<StreamId>();
|
||||
auto groupId = cursor.readBE<StreamGroupId>();
|
||||
auto dataBuffer = decodeDataBuffer(cursor);
|
||||
bool eof = (bool)cursor.readBE<uint8_t>();
|
||||
return StreamGroupIdBuf{
|
||||
streamId,
|
||||
groupId,
|
||||
StreamBuffer(std::move(dataBuffer.first), dataBuffer.second, eof)};
|
||||
}
|
||||
|
||||
StreamBuffer decodeCryptoBuffer(folly::io::Cursor& cursor) {
|
||||
auto dataBuffer = decodeDataBuffer(cursor);
|
||||
return StreamBuffer(std::move(dataBuffer.first), dataBuffer.second, false);
|
||||
@@ -258,6 +286,16 @@ class TestQuicTransport
|
||||
auto buffer = decodeDatagramFrame(cursor);
|
||||
auto frame = DatagramFrame(buffer.second, std::move(buffer.first));
|
||||
handleDatagram(*conn_, frame, data.receiveTimePoint);
|
||||
} else if (type == TestFrameType::STREAM_GROUP) {
|
||||
auto res = decodeStreamGroupBuffer(cursor);
|
||||
QuicStreamState* stream =
|
||||
conn_->streamManager->getStream(res.id, res.groupId);
|
||||
if (!stream) {
|
||||
continue;
|
||||
}
|
||||
appendDataToReadBuffer(*stream, std::move(res.buf));
|
||||
conn_->streamManager->updateReadableStreams(*stream);
|
||||
conn_->streamManager->updatePeekableStreams(*stream);
|
||||
} else {
|
||||
auto buffer = decodeStreamBuffer(cursor);
|
||||
QuicStreamState* stream = conn_->streamManager->getStream(buffer.first);
|
||||
@@ -346,8 +384,11 @@ class TestQuicTransport
|
||||
|
||||
void onReadError(const folly::AsyncSocketException&) noexcept {}
|
||||
|
||||
void addDataToStream(StreamId id, StreamBuffer data) {
|
||||
auto buf = encodeStreamBuffer(id, std::move(data));
|
||||
void addDataToStream(
|
||||
StreamId id,
|
||||
StreamBuffer data,
|
||||
folly::Optional<StreamGroupId> groupId = folly::none) {
|
||||
auto buf = encodeStreamBuffer(id, std::move(data), std::move(groupId));
|
||||
SocketAddress addr("127.0.0.1", 1000);
|
||||
onNetworkData(addr, NetworkData(std::move(buf), Clock::now()));
|
||||
}
|
||||
@@ -4038,5 +4079,160 @@ TEST_P(QuicTransportImplTestBase, BackgroundModeChangeWithStreamChanges) {
|
||||
manager.removeClosedStream(stream2Id);
|
||||
}
|
||||
|
||||
class QuicTransportImplTestWithGroups : public QuicTransportImplTestBase {};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
QuicTransportImplTestWithGroups,
|
||||
QuicTransportImplTestWithGroups,
|
||||
::testing::Values(DelayedStreamNotifsTestParam{
|
||||
.notifyOnNewStreamsExplicitly = true}));
|
||||
|
||||
TEST_P(QuicTransportImplTestWithGroups, ReadCallbackWithGroupsDataAvailable) {
|
||||
auto transportSettings = transport->getTransportSettings();
|
||||
transportSettings.maxStreamGroupsAdvertized = 16;
|
||||
transport->setTransportSettings(transportSettings);
|
||||
transport->getConnectionState().streamManager->refreshTransportSettings(
|
||||
transportSettings);
|
||||
|
||||
auto groupId = transport->createBidirectionalStreamGroup();
|
||||
EXPECT_TRUE(groupId.hasValue());
|
||||
auto stream1 = transport->createBidirectionalStreamInGroup(*groupId).value();
|
||||
auto stream2 = transport->createBidirectionalStreamInGroup(*groupId).value();
|
||||
|
||||
NiceMock<MockReadCallback> readCb1;
|
||||
NiceMock<MockReadCallback> readCb2;
|
||||
|
||||
transport->setReadCallback(stream1, &readCb1);
|
||||
transport->setReadCallback(stream2, &readCb2);
|
||||
|
||||
transport->addDataToStream(
|
||||
stream1,
|
||||
StreamBuffer(folly::IOBuf::copyBuffer("actual stream data"), 0),
|
||||
*groupId);
|
||||
|
||||
transport->addDataToStream(
|
||||
stream2,
|
||||
StreamBuffer(folly::IOBuf::copyBuffer("actual stream data"), 10),
|
||||
*groupId);
|
||||
|
||||
EXPECT_CALL(readCb1, readAvailableWithGroup(stream1, *groupId));
|
||||
transport->driveReadCallbacks();
|
||||
|
||||
transport->addDataToStream(
|
||||
stream2,
|
||||
StreamBuffer(folly::IOBuf::copyBuffer("actual stream data"), 0),
|
||||
*groupId);
|
||||
|
||||
EXPECT_CALL(readCb1, readAvailableWithGroup(stream1, *groupId));
|
||||
EXPECT_CALL(readCb2, readAvailableWithGroup(stream2, *groupId));
|
||||
transport->driveReadCallbacks();
|
||||
|
||||
EXPECT_CALL(readCb1, readAvailableWithGroup(stream1, *groupId));
|
||||
EXPECT_CALL(readCb2, readAvailableWithGroup(stream2, *groupId));
|
||||
transport->driveReadCallbacks();
|
||||
|
||||
EXPECT_CALL(readCb2, readAvailableWithGroup(stream2, *groupId));
|
||||
transport->setReadCallback(stream1, nullptr);
|
||||
transport->driveReadCallbacks();
|
||||
transport.reset();
|
||||
}
|
||||
|
||||
TEST_P(QuicTransportImplTestWithGroups, ReadErrorCallbackWithGroups) {
|
||||
auto transportSettings = transport->getTransportSettings();
|
||||
transportSettings.maxStreamGroupsAdvertized = 16;
|
||||
transport->setTransportSettings(transportSettings);
|
||||
transport->getConnectionState().streamManager->refreshTransportSettings(
|
||||
transportSettings);
|
||||
|
||||
auto groupId = transport->createBidirectionalStreamGroup();
|
||||
EXPECT_TRUE(groupId.hasValue());
|
||||
auto stream1 = transport->createBidirectionalStreamInGroup(*groupId).value();
|
||||
|
||||
NiceMock<MockReadCallback> readCb1;
|
||||
|
||||
transport->setReadCallback(stream1, &readCb1);
|
||||
|
||||
transport->addStreamReadError(stream1, LocalErrorCode::NO_ERROR);
|
||||
transport->addDataToStream(
|
||||
stream1,
|
||||
StreamBuffer(folly::IOBuf::copyBuffer("actual stream data"), 0),
|
||||
*groupId);
|
||||
|
||||
EXPECT_CALL(readCb1, readErrorWithGroup(stream1, *groupId, _));
|
||||
transport->driveReadCallbacks();
|
||||
|
||||
transport.reset();
|
||||
}
|
||||
|
||||
TEST_P(
|
||||
QuicTransportImplTestWithGroups,
|
||||
ReadCallbackWithGroupsCancellCallbacks) {
|
||||
auto transportSettings = transport->getTransportSettings();
|
||||
transportSettings.maxStreamGroupsAdvertized = 16;
|
||||
transport->setTransportSettings(transportSettings);
|
||||
transport->getConnectionState().streamManager->refreshTransportSettings(
|
||||
transportSettings);
|
||||
|
||||
auto groupId = transport->createBidirectionalStreamGroup();
|
||||
EXPECT_TRUE(groupId.hasValue());
|
||||
auto stream1 = transport->createBidirectionalStreamInGroup(*groupId).value();
|
||||
auto stream2 = transport->createBidirectionalStreamInGroup(*groupId).value();
|
||||
|
||||
NiceMock<MockReadCallback> readCb1;
|
||||
NiceMock<MockReadCallback> readCb2;
|
||||
|
||||
transport->setReadCallback(stream1, &readCb1);
|
||||
transport->setReadCallback(stream2, &readCb2);
|
||||
|
||||
transport->addDataToStream(
|
||||
stream1,
|
||||
StreamBuffer(folly::IOBuf::copyBuffer("actual stream data"), 0),
|
||||
*groupId);
|
||||
|
||||
transport->addDataToStream(
|
||||
stream2,
|
||||
StreamBuffer(folly::IOBuf::copyBuffer("actual stream data"), 10),
|
||||
*groupId);
|
||||
|
||||
EXPECT_CALL(readCb1, readErrorWithGroup(stream1, *groupId, _));
|
||||
EXPECT_CALL(readCb2, readErrorWithGroup(stream2, *groupId, _));
|
||||
QuicError error =
|
||||
QuicError(TransportErrorCode::PROTOCOL_VIOLATION, "test error");
|
||||
transport->cancelAllAppCallbacks(error);
|
||||
transport.reset();
|
||||
}
|
||||
|
||||
TEST_P(QuicTransportImplTestWithGroups, onNewStreamsAndGroupsCallbacks) {
|
||||
auto transportSettings = transport->getTransportSettings();
|
||||
transportSettings.maxStreamGroupsAdvertized = 16;
|
||||
transport->setTransportSettings(transportSettings);
|
||||
transport->getConnectionState().streamManager->refreshTransportSettings(
|
||||
transportSettings);
|
||||
|
||||
auto readData = folly::IOBuf::copyBuffer("actual stream data");
|
||||
|
||||
StreamGroupId groupId = 0x00;
|
||||
StreamId stream1 = 0x00;
|
||||
EXPECT_CALL(connCallback, onNewBidirectionalStreamGroup(groupId));
|
||||
EXPECT_CALL(connCallback, onNewBidirectionalStreamInGroup(stream1, groupId));
|
||||
transport->addDataToStream(
|
||||
stream1, StreamBuffer(readData->clone(), 0, true), groupId);
|
||||
|
||||
StreamId stream2 = 0x04;
|
||||
EXPECT_CALL(connCallback, onNewBidirectionalStreamInGroup(stream2, groupId));
|
||||
transport->addDataToStream(
|
||||
stream2, StreamBuffer(readData->clone(), 0, true), groupId);
|
||||
|
||||
StreamGroupId groupIdUni = 0x02;
|
||||
StreamId uniStream3 = 0xa;
|
||||
EXPECT_CALL(connCallback, onNewUnidirectionalStreamGroup(groupIdUni));
|
||||
EXPECT_CALL(
|
||||
connCallback, onNewUnidirectionalStreamInGroup(uniStream3, groupIdUni));
|
||||
transport->addDataToStream(
|
||||
uniStream3, StreamBuffer(readData->clone(), 0, true), groupIdUni);
|
||||
|
||||
transport.reset();
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace quic
|
||||
|
Reference in New Issue
Block a user