mirror of
https://github.com/facebookincubator/mvfst.git
synced 2025-11-28 15:43:57 +03:00
QuicClientIntegrationTest
Summary: - initially created the integration test within QuicServerTest for convenience, but its better suited in its own file Reviewed By: mjoras Differential Revision: D50738655 fbshipit-source-id: 8e73ab2ab11510779d279b9e6273297a4482a58c
This commit is contained in:
committed by
Facebook GitHub Bot
parent
d66b8f23aa
commit
3f847ef079
@@ -20,6 +20,18 @@ quic_add_test(TARGET QuicServerTest
|
|||||||
mvfst_transport
|
mvfst_transport
|
||||||
)
|
)
|
||||||
|
|
||||||
|
quic_add_test(TARGET QuicClientServerIntegrationTest
|
||||||
|
SOURCES
|
||||||
|
QuicClientServerIntegrationTest.cpp
|
||||||
|
DEPENDS
|
||||||
|
Folly::folly
|
||||||
|
mvfst_codec
|
||||||
|
mvfst_codec_types
|
||||||
|
mvfst_server
|
||||||
|
mvfst_test_utils
|
||||||
|
mvfst_transport
|
||||||
|
)
|
||||||
|
|
||||||
quic_add_test(TARGET QuicServerTransportTest
|
quic_add_test(TARGET QuicServerTransportTest
|
||||||
SOURCES
|
SOURCES
|
||||||
QuicServerTransportTest.cpp
|
QuicServerTransportTest.cpp
|
||||||
|
|||||||
213
quic/server/test/QuicClientServerIntegrationTest.cpp
Normal file
213
quic/server/test/QuicClientServerIntegrationTest.cpp
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <quic/api/test/Mocks.h>
|
||||||
|
#include <quic/client/QuicClientTransport.h>
|
||||||
|
#include <quic/common/test/TestClientUtils.h>
|
||||||
|
#include <quic/common/test/TestUtils.h>
|
||||||
|
#include <quic/fizz/client/handshake/FizzClientQuicHandshakeContext.h>
|
||||||
|
#include <quic/server/QuicServer.h>
|
||||||
|
|
||||||
|
#include <folly/portability/GMock.h>
|
||||||
|
#include <folly/portability/GTest.h>
|
||||||
|
|
||||||
|
using namespace testing;
|
||||||
|
|
||||||
|
namespace quic::test {
|
||||||
|
|
||||||
|
// dummy/no-op callback to install on QuicServerTransport
|
||||||
|
class MockMergedConnectionCallbacks : public MockConnectionSetupCallback,
|
||||||
|
public MockConnectionCallback {};
|
||||||
|
|
||||||
|
class QuicTransportFactory : public quic::QuicServerTransportFactory {
|
||||||
|
// no-op quic server transport factory
|
||||||
|
quic::QuicServerTransport::Ptr make(
|
||||||
|
folly::EventBase* evb,
|
||||||
|
std::unique_ptr<QuicAsyncUDPSocketWrapper> socket,
|
||||||
|
const folly::SocketAddress& /* peerAddr */,
|
||||||
|
quic::QuicVersion /*quicVersion*/,
|
||||||
|
std::shared_ptr<const fizz::server::FizzServerContext> ctx) noexcept
|
||||||
|
override {
|
||||||
|
// delete mocked object as soon as terminal callback is rx'd
|
||||||
|
auto noopCb = new MockMergedConnectionCallbacks();
|
||||||
|
EXPECT_CALL(*noopCb, onConnectionEnd())
|
||||||
|
.Times(AtMost(1))
|
||||||
|
.WillRepeatedly([noopCb] { delete noopCb; });
|
||||||
|
EXPECT_CALL(*noopCb, onConnectionError(_))
|
||||||
|
.Times(AtMost(1))
|
||||||
|
.WillRepeatedly([noopCb] { delete noopCb; });
|
||||||
|
return quic::QuicServerTransport::make(
|
||||||
|
evb, std::move(socket), noopCb, noopCb, ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ServerTransportParameters : public testing::Test {
|
||||||
|
public:
|
||||||
|
void TearDown() override {
|
||||||
|
if (client_) {
|
||||||
|
client_->close(folly::none);
|
||||||
|
}
|
||||||
|
evb_.loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clientConnect() {
|
||||||
|
CHECK(client_) << "client not initialized";
|
||||||
|
MockConnectionSetupCallback setupCb;
|
||||||
|
MockConnectionCallback connCb;
|
||||||
|
EXPECT_CALL(setupCb, onReplaySafe()).WillOnce(Invoke([&] {
|
||||||
|
evb_.terminateLoopSoon();
|
||||||
|
}));
|
||||||
|
client_->start(&setupCb, &connCb);
|
||||||
|
|
||||||
|
evb_.loopForever();
|
||||||
|
}
|
||||||
|
|
||||||
|
// start server with the transport settings that unit test can set accordingly
|
||||||
|
void startServer() {
|
||||||
|
server_ = QuicServer::createQuicServer();
|
||||||
|
// set server configs
|
||||||
|
server_->setFizzContext(quic::test::createServerCtx());
|
||||||
|
serverTs_.statelessResetTokenSecret = getRandSecret();
|
||||||
|
server_->setTransportSettings(serverTs_);
|
||||||
|
server_->setQuicServerTransportFactory(
|
||||||
|
std::make_unique<QuicTransportFactory>());
|
||||||
|
// start server
|
||||||
|
server_->start(folly::SocketAddress("::1", 0), 1);
|
||||||
|
server_->waitUntilInitialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
// create new quic client
|
||||||
|
std::shared_ptr<QuicClientTransport> createQuicClient() {
|
||||||
|
// server must be already started
|
||||||
|
CHECK(server_)
|
||||||
|
<< "::startServer() must be invoked prior to ::createQuicClient()";
|
||||||
|
auto fizzClientContext =
|
||||||
|
FizzClientQuicHandshakeContext::Builder()
|
||||||
|
.setCertificateVerifier(createTestCertificateVerifier())
|
||||||
|
.build();
|
||||||
|
auto client = std::make_shared<QuicClientTransport>(
|
||||||
|
&evb_,
|
||||||
|
std::make_unique<QuicAsyncUDPSocketWrapperImpl>(&evb_),
|
||||||
|
std::move(fizzClientContext));
|
||||||
|
client->addNewPeerAddress(server_->getAddress());
|
||||||
|
client->setHostname("::1");
|
||||||
|
client->setSupportedVersions({QuicVersion::MVFST});
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<QuicClientTransport> client_;
|
||||||
|
std::shared_ptr<QuicServer> server_;
|
||||||
|
TransportSettings serverTs_{};
|
||||||
|
folly::EventBase evb_;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(ServerTransportParameters, InvariantlyAdvertisedParameters) {
|
||||||
|
startServer();
|
||||||
|
|
||||||
|
// create & connect client
|
||||||
|
client_ = createQuicClient();
|
||||||
|
clientConnect();
|
||||||
|
|
||||||
|
// validate all the parameters we unconditionally advertise
|
||||||
|
auto clientConn =
|
||||||
|
dynamic_cast<const QuicClientConnectionState*>(client_->getState());
|
||||||
|
const auto& serverTransportParams =
|
||||||
|
clientConn->clientHandshakeLayer->getServerTransportParams();
|
||||||
|
CHECK(serverTransportParams.has_value());
|
||||||
|
|
||||||
|
using _id = TransportParameterId;
|
||||||
|
for (auto paramId :
|
||||||
|
{_id::initial_max_stream_data_bidi_local,
|
||||||
|
_id::initial_max_stream_data_bidi_remote,
|
||||||
|
_id::initial_max_stream_data_uni,
|
||||||
|
_id::initial_max_data,
|
||||||
|
_id::initial_max_streams_bidi,
|
||||||
|
_id::initial_max_streams_uni,
|
||||||
|
_id::idle_timeout,
|
||||||
|
_id::ack_delay_exponent,
|
||||||
|
_id::max_packet_size,
|
||||||
|
_id::stateless_reset_token}) {
|
||||||
|
auto param =
|
||||||
|
getIntegerParameter(paramId, serverTransportParams->parameters);
|
||||||
|
EXPECT_TRUE(param.has_value());
|
||||||
|
}
|
||||||
|
|
||||||
|
client_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ServerTransportParameters, DatagramTest) {
|
||||||
|
// turn off datagram support to begin with
|
||||||
|
serverTs_.datagramConfig.enabled = false;
|
||||||
|
startServer();
|
||||||
|
|
||||||
|
{
|
||||||
|
// create & connect client
|
||||||
|
client_ = createQuicClient();
|
||||||
|
clientConnect();
|
||||||
|
|
||||||
|
// validate no datagram support was advertised by server
|
||||||
|
auto clientConn =
|
||||||
|
dynamic_cast<const QuicClientConnectionState*>(client_->getState());
|
||||||
|
const auto& serverTransportParams =
|
||||||
|
clientConn->clientHandshakeLayer->getServerTransportParams();
|
||||||
|
CHECK(serverTransportParams.has_value());
|
||||||
|
|
||||||
|
auto param = getIntegerParameter(
|
||||||
|
TransportParameterId::max_datagram_frame_size,
|
||||||
|
serverTransportParams->parameters);
|
||||||
|
EXPECT_FALSE(param.has_value());
|
||||||
|
client_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// now enable datagram support
|
||||||
|
serverTs_.datagramConfig.enabled = true;
|
||||||
|
server_->setTransportSettings(serverTs_);
|
||||||
|
|
||||||
|
// create & connect client
|
||||||
|
client_ = createQuicClient();
|
||||||
|
clientConnect();
|
||||||
|
|
||||||
|
// validate datagram support was advertised by server
|
||||||
|
auto clientConn =
|
||||||
|
dynamic_cast<const QuicClientConnectionState*>(client_->getState());
|
||||||
|
const auto& serverTransportParams =
|
||||||
|
clientConn->clientHandshakeLayer->getServerTransportParams();
|
||||||
|
CHECK(serverTransportParams.has_value());
|
||||||
|
|
||||||
|
auto param = getIntegerParameter(
|
||||||
|
TransportParameterId::max_datagram_frame_size,
|
||||||
|
serverTransportParams->parameters);
|
||||||
|
CHECK(param.has_value());
|
||||||
|
// also validate value because why not
|
||||||
|
EXPECT_EQ(param.value(), kMaxDatagramFrameSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ServerTransportParameters, disableMigrationParam) {
|
||||||
|
// turn off migration
|
||||||
|
serverTs_.disableMigration = true;
|
||||||
|
startServer();
|
||||||
|
|
||||||
|
// create & connect client
|
||||||
|
client_ = createQuicClient();
|
||||||
|
clientConnect();
|
||||||
|
auto clientConn =
|
||||||
|
dynamic_cast<const QuicClientConnectionState*>(client_->getState());
|
||||||
|
|
||||||
|
const auto& serverTransportParams =
|
||||||
|
clientConn->clientHandshakeLayer->getServerTransportParams();
|
||||||
|
CHECK(serverTransportParams.has_value());
|
||||||
|
|
||||||
|
// validate disable_migration parameter was rx'd
|
||||||
|
auto it = findParameter(
|
||||||
|
serverTransportParams->parameters,
|
||||||
|
TransportParameterId::disable_migration);
|
||||||
|
EXPECT_NE(it, serverTransportParams->parameters.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace quic::test
|
||||||
@@ -3157,197 +3157,5 @@ TEST_F(QuicServerTest, OneEVB) {
|
|||||||
evb.loop();
|
evb.loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* used for testing / observer transport parameters advertised by the server
|
|
||||||
*/
|
|
||||||
class MockMergedConnectionCallbacks : public MockConnectionSetupCallback,
|
|
||||||
public MockConnectionCallback {};
|
|
||||||
|
|
||||||
class QuicTransportFactory : public quic::QuicServerTransportFactory {
|
|
||||||
// no-op quic server transport factory
|
|
||||||
quic::QuicServerTransport::Ptr make(
|
|
||||||
folly::EventBase* evb,
|
|
||||||
std::unique_ptr<QuicAsyncUDPSocketWrapper> socket,
|
|
||||||
const folly::SocketAddress& /* peerAddr */,
|
|
||||||
quic::QuicVersion /*quicVersion*/,
|
|
||||||
std::shared_ptr<const fizz::server::FizzServerContext> ctx) noexcept
|
|
||||||
override {
|
|
||||||
// delete mocked object as soon as terminal callback is rx'd
|
|
||||||
auto noopCb = new MockMergedConnectionCallbacks();
|
|
||||||
EXPECT_CALL(*noopCb, onConnectionEnd())
|
|
||||||
.Times(AtMost(1))
|
|
||||||
.WillRepeatedly([noopCb] { delete noopCb; });
|
|
||||||
EXPECT_CALL(*noopCb, onConnectionError(_))
|
|
||||||
.Times(AtMost(1))
|
|
||||||
.WillRepeatedly([noopCb] { delete noopCb; });
|
|
||||||
return quic::QuicServerTransport::make(
|
|
||||||
evb, std::move(socket), noopCb, noopCb, ctx);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class ServerTransportParameters : public testing::Test {
|
|
||||||
public:
|
|
||||||
void TearDown() override {
|
|
||||||
if (client_) {
|
|
||||||
client_->close(folly::none);
|
|
||||||
}
|
|
||||||
evb_.loop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void clientConnect() {
|
|
||||||
CHECK(client_) << "client not initialized";
|
|
||||||
MockConnectionSetupCallback setupCb;
|
|
||||||
MockConnectionCallback connCb;
|
|
||||||
EXPECT_CALL(setupCb, onReplaySafe()).WillOnce(Invoke([&] {
|
|
||||||
evb_.terminateLoopSoon();
|
|
||||||
}));
|
|
||||||
client_->start(&setupCb, &connCb);
|
|
||||||
|
|
||||||
evb_.loopForever();
|
|
||||||
}
|
|
||||||
|
|
||||||
// start server with the transport settings that unit test can set accordingly
|
|
||||||
void startServer() {
|
|
||||||
server_ = QuicServer::createQuicServer();
|
|
||||||
// set server configs
|
|
||||||
server_->setFizzContext(quic::test::createServerCtx());
|
|
||||||
serverTs_.statelessResetTokenSecret = getRandSecret();
|
|
||||||
server_->setTransportSettings(serverTs_);
|
|
||||||
server_->setQuicServerTransportFactory(
|
|
||||||
std::make_unique<QuicTransportFactory>());
|
|
||||||
// start server
|
|
||||||
server_->start(folly::SocketAddress("::1", 0), 1);
|
|
||||||
server_->waitUntilInitialized();
|
|
||||||
}
|
|
||||||
|
|
||||||
// create new quic client
|
|
||||||
std::shared_ptr<QuicClientTransport> createQuicClient() {
|
|
||||||
// server must be already started
|
|
||||||
CHECK(server_)
|
|
||||||
<< "::startServer() must be invoked prior to ::createQuicClient()";
|
|
||||||
auto fizzClientContext =
|
|
||||||
FizzClientQuicHandshakeContext::Builder()
|
|
||||||
.setCertificateVerifier(createTestCertificateVerifier())
|
|
||||||
.build();
|
|
||||||
auto client = std::make_shared<QuicClientTransport>(
|
|
||||||
&evb_,
|
|
||||||
std::make_unique<QuicAsyncUDPSocketWrapperImpl>(&evb_),
|
|
||||||
std::move(fizzClientContext));
|
|
||||||
client->addNewPeerAddress(server_->getAddress());
|
|
||||||
client->setHostname("::1");
|
|
||||||
client->setSupportedVersions({QuicVersion::MVFST});
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<QuicClientTransport> client_;
|
|
||||||
std::shared_ptr<QuicServer> server_;
|
|
||||||
TransportSettings serverTs_{};
|
|
||||||
folly::EventBase evb_;
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_F(ServerTransportParameters, InvariantlyAdvertisedParameters) {
|
|
||||||
startServer();
|
|
||||||
|
|
||||||
// create & connect client
|
|
||||||
client_ = createQuicClient();
|
|
||||||
clientConnect();
|
|
||||||
|
|
||||||
// validate all the parameters we unconditionally advertise
|
|
||||||
auto clientConn =
|
|
||||||
dynamic_cast<const QuicClientConnectionState*>(client_->getState());
|
|
||||||
const auto& serverTransportParams =
|
|
||||||
clientConn->clientHandshakeLayer->getServerTransportParams();
|
|
||||||
CHECK(serverTransportParams.has_value());
|
|
||||||
|
|
||||||
using _id = TransportParameterId;
|
|
||||||
for (auto paramId :
|
|
||||||
{_id::initial_max_stream_data_bidi_local,
|
|
||||||
_id::initial_max_stream_data_bidi_remote,
|
|
||||||
_id::initial_max_stream_data_uni,
|
|
||||||
_id::initial_max_data,
|
|
||||||
_id::initial_max_streams_bidi,
|
|
||||||
_id::initial_max_streams_uni,
|
|
||||||
_id::idle_timeout,
|
|
||||||
_id::ack_delay_exponent,
|
|
||||||
_id::max_packet_size,
|
|
||||||
_id::stateless_reset_token}) {
|
|
||||||
auto param =
|
|
||||||
getIntegerParameter(paramId, serverTransportParams->parameters);
|
|
||||||
EXPECT_TRUE(param.has_value());
|
|
||||||
}
|
|
||||||
|
|
||||||
client_.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(ServerTransportParameters, DatagramTest) {
|
|
||||||
// turn off datagram support to begin with
|
|
||||||
serverTs_.datagramConfig.enabled = false;
|
|
||||||
startServer();
|
|
||||||
|
|
||||||
{
|
|
||||||
// create & connect client
|
|
||||||
client_ = createQuicClient();
|
|
||||||
clientConnect();
|
|
||||||
|
|
||||||
// validate no datagram support was advertised by server
|
|
||||||
auto clientConn =
|
|
||||||
dynamic_cast<const QuicClientConnectionState*>(client_->getState());
|
|
||||||
const auto& serverTransportParams =
|
|
||||||
clientConn->clientHandshakeLayer->getServerTransportParams();
|
|
||||||
CHECK(serverTransportParams.has_value());
|
|
||||||
|
|
||||||
auto param = getIntegerParameter(
|
|
||||||
TransportParameterId::max_datagram_frame_size,
|
|
||||||
serverTransportParams->parameters);
|
|
||||||
EXPECT_FALSE(param.has_value());
|
|
||||||
client_.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// now enable datagram support
|
|
||||||
serverTs_.datagramConfig.enabled = true;
|
|
||||||
server_->setTransportSettings(serverTs_);
|
|
||||||
|
|
||||||
// create & connect client
|
|
||||||
client_ = createQuicClient();
|
|
||||||
clientConnect();
|
|
||||||
|
|
||||||
// validate datagram support was advertised by server
|
|
||||||
auto clientConn =
|
|
||||||
dynamic_cast<const QuicClientConnectionState*>(client_->getState());
|
|
||||||
const auto& serverTransportParams =
|
|
||||||
clientConn->clientHandshakeLayer->getServerTransportParams();
|
|
||||||
CHECK(serverTransportParams.has_value());
|
|
||||||
|
|
||||||
auto param = getIntegerParameter(
|
|
||||||
TransportParameterId::max_datagram_frame_size,
|
|
||||||
serverTransportParams->parameters);
|
|
||||||
CHECK(param.has_value());
|
|
||||||
// also validate value because why not
|
|
||||||
EXPECT_EQ(param.value(), kMaxDatagramFrameSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(ServerTransportParameters, disableMigrationParam) {
|
|
||||||
// turn off migration
|
|
||||||
serverTs_.disableMigration = true;
|
|
||||||
startServer();
|
|
||||||
|
|
||||||
// create & connect client
|
|
||||||
client_ = createQuicClient();
|
|
||||||
clientConnect();
|
|
||||||
auto clientConn =
|
|
||||||
dynamic_cast<const QuicClientConnectionState*>(client_->getState());
|
|
||||||
|
|
||||||
const auto& serverTransportParams =
|
|
||||||
clientConn->clientHandshakeLayer->getServerTransportParams();
|
|
||||||
CHECK(serverTransportParams.has_value());
|
|
||||||
|
|
||||||
// validate disable_migration parameter was rx'd
|
|
||||||
auto it = findParameter(
|
|
||||||
serverTransportParams->parameters,
|
|
||||||
TransportParameterId::disable_migration);
|
|
||||||
EXPECT_NE(it, serverTransportParams->parameters.end());
|
|
||||||
}
|
|
||||||
} // namespace test
|
} // namespace test
|
||||||
} // namespace quic
|
} // namespace quic
|
||||||
|
|||||||
Reference in New Issue
Block a user