1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-08-09 20:42:44 +03:00
Files
mvfst/quic/dsr/backend/test/DSRPacketizerTest.cpp
Matt Joras 612a00c3f9 Move happy eyeballs state to client state.
Summary: This doesn't belong in the generic state. Untangling it is a little difficult, but I think this solution is cleaner than having it in the generic state.

Reviewed By: JunqiWang

Differential Revision: D29856391

fbshipit-source-id: 1042109ed29cd1d20d139e08548d187b469c8398
2021-07-23 14:21:16 -07:00

189 lines
5.9 KiB
C++

// Copyright 2004-present Facebook. All Rights Reserved.
#include <folly/portability/GTest.h>
#include <quic/common/test/TestUtils.h>
#include <quic/dsr/backend/DSRPacketizer.h>
#include <quic/dsr/backend/test/TestUtils.h>
#include <quic/dsr/frontend/WriteFunctions.h>
#include <quic/dsr/test/TestCommon.h>
using namespace testing;
namespace {
fizz::TrafficKey getFizzTestKey() {
fizz::TrafficKey testKey;
auto quicKey = quic::test::getQuicTestKey();
testKey.key = std::move(quicKey.key);
testKey.iv = std::move(quicKey.iv);
return testKey;
}
} // namespace
namespace quic {
namespace test {
class DSRPacketizerTest : public DSRCommonTestFixture {};
TEST_F(DSRPacketizerTest, BuildCipher) {
CipherBuilder cipherBuilder;
auto cipherPair = cipherBuilder.buildCiphers(
getFizzTestKey(),
fizz::CipherSuite::TLS_AES_128_GCM_SHA256,
packetProtectionKey_->clone());
EXPECT_NE(cipherPair.aead, nullptr);
EXPECT_NE(cipherPair.headerCipher, nullptr);
}
class DSRPacketizerSingleWriteTest : public Test {
protected:
void SetUp() override {
aead = test::createNoOpAead();
headerCipher = test::createNoOpHeaderCipher();
}
folly::EventBase evb;
folly::SocketAddress peerAddress{"127.0.0.1", 1234};
std::unique_ptr<Aead> aead;
std::unique_ptr<PacketNumberCipher> headerCipher;
};
TEST_F(DSRPacketizerSingleWriteTest, SingleWrite) {
auto testBatchWriter = new test::TestPacketBatchWriter(16);
auto batchWriter = BatchWriterPtr(testBatchWriter);
auto socket =
std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
IOBufQuicBatch ioBufBatch(
std::move(batchWriter),
false /* threadLocal */,
*socket,
peerAddress,
nullptr /* statsCallback */,
nullptr /* happyEyeballsState */);
PacketNum packetNum = 20;
PacketNum largestAckedByPeer = 0;
StreamId streamId = 0;
size_t offset = 0;
size_t length = 100;
bool eof = false;
auto dcid = test::getTestConnectionId();
auto ret = writeSingleQuicPacket(
ioBufBatch,
dcid,
packetNum,
largestAckedByPeer,
*aead,
*headerCipher,
streamId,
offset,
length,
eof,
test::buildRandomInputData(5000));
EXPECT_TRUE(ret);
// This sucks. But i can't think of a better way to verify we do not
// write a stream frame length into the packet.
EXPECT_EQ(
testBatchWriter->getBufSize(),
1 /* short header initial byte */ + 1 /* packet num */ +
dcid.size() /* dcid */ + 1 /* stream frame initial byte */ +
1 /* stream id */ + length /* actual data */ +
aead->getCipherOverhead());
ioBufBatch.flush();
EXPECT_EQ(1, ioBufBatch.getPktSent());
}
TEST_F(DSRPacketizerSingleWriteTest, NotEnoughData) {
auto batchWriter = BatchWriterPtr(new test::TestPacketBatchWriter(16));
auto socket =
std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
IOBufQuicBatch ioBufBatch(
std::move(batchWriter),
false /* threadLocal */,
*socket,
peerAddress,
nullptr /* statsCallback */,
nullptr /* happyEyeballsState */);
PacketNum packetNum = 20;
PacketNum largestAckedByPeer = 0;
StreamId streamId = 0;
size_t offset = 0;
size_t length = 100;
bool eof = false;
auto ret = writeSingleQuicPacket(
ioBufBatch,
test::getTestConnectionId(),
packetNum,
largestAckedByPeer,
*aead,
*headerCipher,
streamId,
offset,
length,
eof,
folly::IOBuf::copyBuffer("Clif"));
EXPECT_FALSE(ret);
ioBufBatch.flush();
EXPECT_EQ(0, ioBufBatch.getPktSent());
}
class DSRMultiWriteTest : public DSRCommonTestFixture {
protected:
FizzCryptoFactory factory_;
folly::EventBase evb;
};
TEST_F(DSRMultiWriteTest, TwoRequests) {
prepareFlowControlAndStreamLimit();
auto streamId = prepareOneStream(1000);
auto stream = conn_.streamManager->findStream(streamId);
auto bufMetaStartingOffset = stream->writeBufMeta.offset;
// Move part of the BufMetas to lossBufMetas
auto split = stream->writeBufMeta.split(500);
stream->lossBufMetas.push_back(split);
size_t packetLimit = 10;
EXPECT_EQ(
1,
writePacketizationRequest(
conn_, getTestConnectionId(), packetLimit, *aead_));
EXPECT_EQ(2, countInstructions(streamId));
EXPECT_EQ(1, conn_.outstandings.packets.size());
auto& packet = conn_.outstandings.packets.back().packet;
EXPECT_EQ(2, packet.frames.size());
WriteStreamFrame expectedFirstFrame(
streamId, bufMetaStartingOffset, 500, false, true);
WriteStreamFrame expectedSecondFrame(
streamId, 500 + bufMetaStartingOffset, 500, true, true);
EXPECT_EQ(expectedFirstFrame, *packet.frames[0].asWriteStreamFrame());
EXPECT_EQ(expectedSecondFrame, *packet.frames[1].asWriteStreamFrame());
std::vector<Buf> sentData;
auto sock = std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
EXPECT_CALL(*sock, writeGSO(conn_.peerAddress, _, _))
.WillRepeatedly(Invoke([&](const folly::SocketAddress&,
const std::unique_ptr<folly::IOBuf>& buf,
int) {
sentData.push_back(buf->clone());
return buf->computeChainDataLength();
}));
EXPECT_CALL(*sock, write(conn_.peerAddress, _))
.WillRepeatedly(Invoke([&](const folly::SocketAddress&,
const std::unique_ptr<folly::IOBuf>& buf) {
sentData.push_back(buf->clone());
return buf->computeChainDataLength();
}));
std::vector<PacketizationRequest> requests;
for (const auto& instruction : pendingInstructions_) {
requests.push_back(sendInstructionToPacketizationRequest(instruction));
}
EXPECT_EQ(
2,
writePacketsGroup(*sock, requests, [](const PacketizationRequest& req) {
return buildRandomInputData(req.len);
}));
EXPECT_EQ(2, sentData.size());
EXPECT_GT(sentData[0]->computeChainDataLength(), 500);
EXPECT_GT(sentData[1]->computeChainDataLength(), 500);
}
} // namespace test
} // namespace quic