1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-11-09 10:00:57 +03:00
Files
mvfst/quic/common/test/TestUtils.h
Matt Joras d1a3652a4c Iterate QuicVersion::MVFST
Summary:
This iterates the mvfst version to be semantically equivalent to draft-27, and leaves support for the old mvfst version.

The client will not yet be moved to draft-27 by default.

Reviewed By: lnicco

Differential Revision: D20182452

fbshipit-source-id: 1e11ad7296a6cd8d15ca5ed359d9ed82af79bb17
2020-03-04 22:08:34 -08:00

276 lines
7.6 KiB
C++

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
#pragma once
#include <quic/client/handshake/QuicPskCache.h>
#include <quic/codec/QuicPacketBuilder.h>
#include <quic/codec/Types.h>
#include <quic/common/BufUtil.h>
#include <quic/handshake/test/Mocks.h>
#include <quic/logging/FileQLogger.h>
#include <quic/server/state/ServerStateMachine.h>
#include <quic/state/AckStates.h>
#include <quic/state/StateData.h>
#include <fizz/client/FizzClientContext.h>
#include <fizz/server/FizzServerContext.h>
#include <folly/io/async/test/MockAsyncUDPSocket.h>
#include <folly/ssl/Init.h>
namespace quic {
namespace test {
class MockClock {
public:
using time_point = quic::Clock::time_point;
using duration = quic::Clock::duration;
static std::function<time_point()> mockNow;
static time_point now() {
return mockNow();
}
};
constexpr QuicVersion MVFST1 = static_cast<QuicVersion>(0xfaceb00d);
constexpr QuicVersion MVFST2 = static_cast<QuicVersion>(0xfaceb00e);
constexpr folly::StringPiece kTestHost = "host";
const RegularQuicWritePacket& writeQuicPacket(
QuicServerConnectionState& conn,
ConnectionId srcConnId,
ConnectionId dstConnId,
folly::test::MockAsyncUDPSocket& sock,
QuicStreamState& stream,
const folly::IOBuf& data,
bool eof = false);
RegularQuicPacketBuilder::Packet createAckPacket(
QuicConnectionStateBase& dstConn,
PacketNum pn,
AckBlocks& acks,
PacketNumberSpace pnSpace,
const Aead* aead = nullptr);
PacketNum rstStreamAndSendPacket(
QuicServerConnectionState& conn,
folly::AsyncUDPSocket& sock,
QuicStreamState& stream,
ApplicationErrorCode errorCode);
// TODO: this is a really horrible API. User can easily pass srcConnId and
// destConnId wrong and won't realize it. All the other createXXXPacket are also
// horrible.
RegularQuicPacketBuilder::Packet createStreamPacket(
ConnectionId srcConnId,
ConnectionId dstConnId,
PacketNum packetNum,
StreamId streamId,
folly::IOBuf& data,
uint8_t cipherOverhead,
PacketNum largestAcked,
folly::Optional<std::pair<LongHeader::Types, QuicVersion>>
longHeaderOverride = folly::none,
bool eof = true,
folly::Optional<ProtectionType> shortHeaderOverride = folly::none,
uint64_t offset = 0,
uint64_t packetSizeLimit = kDefaultUDPSendPacketLen);
RegularQuicPacketBuilder::Packet createInitialCryptoPacket(
ConnectionId srcConnId,
ConnectionId dstConnId,
PacketNum packetNum,
QuicVersion version,
folly::IOBuf& data,
const Aead& aead,
PacketNum largestAcked,
uint64_t offset = 0);
RegularQuicPacketBuilder::Packet createCryptoPacket(
ConnectionId srcConnId,
ConnectionId dstConnId,
PacketNum packetNum,
QuicVersion version,
ProtectionType protectionType,
folly::IOBuf& data,
const Aead& aead,
PacketNum largestAcked,
uint64_t offset = 0,
uint64_t packetSizeLimit = kDefaultUDPSendPacketLen);
Buf packetToBuf(const RegularQuicPacketBuilder::Packet& packet);
Buf packetToBufCleartext(
const RegularQuicPacketBuilder::Packet& packet,
const Aead& cleartextCipher,
const PacketNumberCipher& headerCipher,
PacketNum packetNum);
template <typename T, typename S>
bool isState(const S& s) {
return folly::variant_match(
s.state,
[](const T&) { return true; },
[](const auto&) { return false; });
}
std::shared_ptr<fizz::server::FizzServerContext> createServerCtx();
void setupCtxWithTestCert(fizz::server::FizzServerContext& ctx);
void setupZeroRttOnServerCtx(
fizz::server::FizzServerContext& serverCtx,
const QuicCachedPsk& cachedPsk);
QuicCachedPsk setupZeroRttOnClientCtx(
fizz::client::FizzClientContext& clientCtx,
std::string hostname);
std::unique_ptr<MockAead> createNoOpAead();
std::unique_ptr<PacketNumberCipher> createNoOpHeaderCipher();
uint64_t computeExpectedDelay(
std::chrono::microseconds ackDelay,
uint8_t ackDelayExponent);
std::unique_ptr<fizz::CertificateVerifier> createTestCertificateVerifier();
// match error functions
bool matchError(
std::pair<QuicErrorCode, folly::Optional<folly::StringPiece>> errorCode,
LocalErrorCode error);
bool matchError(
std::pair<QuicErrorCode, folly::Optional<folly::StringPiece>> errorCode,
TransportErrorCode error);
bool matchError(
std::pair<QuicErrorCode, folly::Optional<folly::StringPiece>> errorCode,
ApplicationErrorCode error);
bool matchError(
std::pair<QuicErrorCode, std::string> errorCode,
ApplicationErrorCode error);
bool matchError(
std::pair<QuicErrorCode, std::string> errorCode,
TransportErrorCode error);
ConnectionId getTestConnectionId(uint16_t hostId = 0);
ProtectionType encryptionLevelToProtectionType(
fizz::EncryptionLevel encryptionLevel);
MATCHER_P(IsError, error, "") {
return matchError(arg, error);
}
MATCHER_P(IsAppError, error, "") {
return matchError(arg, error);
}
void updateAckState(
QuicConnectionStateBase& conn,
PacketNumberSpace pnSpace,
PacketNum packetNum,
bool pkHasRetransmittableData,
bool pkHasCryptoData,
TimePoint receivedTime);
template <typename Match>
OutstandingPacket* findOutstandingPacket(
QuicConnectionStateBase& conn,
Match match) {
auto helper =
[&](std::deque<OutstandingPacket>& packets) -> OutstandingPacket* {
for (auto& packet : packets) {
if (match(packet)) {
return &packet;
}
}
return nullptr;
};
return helper(conn.outstandingPackets);
}
// Helper function to generate a buffer containing random data of given length
std::unique_ptr<folly::IOBuf> buildRandomInputData(size_t length);
void addAckStatesWithCurrentTimestamps(
AckState& ackState,
PacketNum start,
PacketNum end);
OutstandingPacket makeTestingWritePacket(
PacketNum desiredPacketSeqNum,
size_t desiredSize,
uint64_t totalBytesSent,
TimePoint sentTime = Clock::now());
// TODO: The way we setup packet sent, ack, loss in test cases can use some
// major refactor.
CongestionController::AckEvent makeAck(
PacketNum seq,
uint64_t ackedSize,
TimePoint ackedTime,
TimePoint sendTime);
BufQueue bufToQueue(Buf buf);
StatelessResetToken generateStatelessResetToken();
std::array<uint8_t, kStatelessResetTokenSecretLength> getRandSecret();
RegularQuicWritePacket createNewPacket(
PacketNum packetNum,
PacketNumberSpace pnSpace);
std::vector<QuicVersion> versionList(
std::initializer_list<QuicVersionType> types);
RegularQuicWritePacket createRegularQuicWritePacket(
StreamId streamId,
uint64_t offset,
uint64_t len,
bool fin);
VersionNegotiationPacket createVersionNegotiationPacket();
RegularQuicWritePacket createPacketWithAckFrames();
RegularQuicWritePacket createPacketWithPaddingFrames();
// Helper function which takes in a specific event type and fetches all the
// instances of that type in QLogger
std::vector<int> getQLogEventIndices(
QLogEventType type,
const std::shared_ptr<FileQLogger>& q);
template <QuicSimpleFrame::Type Type>
auto findFrameInPacketFunc() {
return [&](auto& p) {
return std::find_if(
p.packet.frames.begin(), p.packet.frames.end(), [&](auto& f) {
QuicSimpleFrame* simpleFrame = f.asQuicSimpleFrame();
if (!simpleFrame) {
return false;
}
return simpleFrame->type() == Type;
}) != p.packet.frames.end();
};
}
CongestionController::AckEvent::AckPacket makeAckPacketFromOutstandingPacket(
OutstandingPacket outstandingPacket);
} // namespace test
} // namespace quic