Add basic client state machine unit tests
Summary: This adds the Mocks for ClientHandshake and ClientHandshakeFactory. I added a simple test for `updateTransportParamsFromCachedEarlyParams`.
MODIFY
quic/client/CMakeLists.txt
quic/client/CMakeLists.txt
@@ -64,3 +64,5 @@ install(
EXPORT mvfst-exports
DESTINATION lib
)
+
+add_subdirectory(test)

ADD
quic/client/test/CMakeLists.txt
+# 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.
+
+if(NOT BUILD_TESTS)
+ return()
+endif()
+
+quic_add_test(TARGET ClientStateMachineTest
+ SOURCES
+ ClientStateMachineTest.cpp
+ DEPENDS
+ Folly::folly
+ mvfst_client
+ mvfst_test_utils
+)

ADD
quic/client/test/ClientStateMachineTest.cpp
+// Copyright 2004-present Facebook. All Rights Reserved.
+
+#include <quic/client/state/ClientStateMachine.h>
+#include <quic/client/handshake/CachedServerTransportParameters.h>
+#include <quic/client/handshake/ClientHandshake.h>
+#include <quic/handshake/CryptoFactory.h>
+#include <quic/handshake/TransportParameters.h>
+#include "quic/client/test/Mocks.h"
+
+using namespace ::testing;
+using namespace std::literals::chrono_literals;
+
+namespace quic::test {
+
+namespace {
+// Use non-default values to test for nops
+constexpr auto idleTimeout = kDefaultIdleTimeout + 1s;
+constexpr auto maxRecvPacketSize = 1420;
+constexpr auto initialMaxData = kDefaultConnectionWindowSize + 2;
+constexpr auto initialMaxStreamDataBidiLocal = kDefaultStreamWindowSize + 3;
+constexpr auto initialMaxStreamDataBidiRemote = kDefaultStreamWindowSize + 4;
+constexpr auto initialMaxStreamDataUni = kDefaultStreamWindowSize + 5;
+constexpr auto initialMaxStreamsBidi = kDefaultMaxStreamsBidirectional + 6;
+constexpr auto initialMaxStreamsUni = kDefaultMaxStreamsUnidirectional + 7;
+const CachedServerTransportParameters kParams{
+ std::chrono::milliseconds(idleTimeout).count(),
+ maxRecvPacketSize,
+ initialMaxData,
+ initialMaxStreamDataBidiLocal,
+ initialMaxStreamDataBidiRemote,
+ initialMaxStreamDataUni,
+ initialMaxStreamsBidi,
+ initialMaxStreamsUni};
+} // namespace
+
+class ClientStateMachineTest : public Test {
+ public:
+ void SetUp() override {
+ mockFactory_ = std::make_shared<MockClientHandshakeFactory>();
+ EXPECT_CALL(*mockFactory_, makeClientHandshake(_))
+ .WillOnce(Invoke(
+ [&](QuicClientConnectionState* conn)
+ -> std::unique_ptr<quic::ClientHandshake> {
+ auto handshake = std::make_unique<MockClientHandshake>(conn);
+ mockHandshake_ = handshake.get();
+ return handshake;
+ }));
+ client_ = std::make_unique<QuicClientConnectionState>(mockFactory_);
+ }
+
+ std::shared_ptr<MockClientHandshakeFactory> mockFactory_;
+ MockClientHandshake* mockHandshake_;
+ std::unique_ptr<QuicClientConnectionState> client_;
+};
+
+TEST_F(ClientStateMachineTest, TestUpdateTransportParamsNotIgnorePathMTU) {
+ updateTransportParamsFromCachedEarlyParams(*client_, kParams);
+ EXPECT_EQ(client_->udpSendPacketLen, kDefaultUDPSendPacketLen);
+}
+
+TEST_F(ClientStateMachineTest, TestUpdateTransportParamsFromCachedEarlyParams) {
+ client_->transportSettings.canIgnorePathMTU = true;
+
+ updateTransportParamsFromCachedEarlyParams(*client_, kParams);
+ EXPECT_EQ(client_->peerIdleTimeout, idleTimeout);
+ EXPECT_EQ(client_->udpSendPacketLen, maxRecvPacketSize);
+ EXPECT_EQ(client_->flowControlState.peerAdvertisedMaxOffset, initialMaxData);
+ EXPECT_EQ(
+ client_->flowControlState.peerAdvertisedInitialMaxStreamOffsetBidiLocal,
+ initialMaxStreamDataBidiLocal);
+ EXPECT_EQ(
+ client_->flowControlState.peerAdvertisedInitialMaxStreamOffsetBidiRemote,
+ initialMaxStreamDataBidiRemote);
+ EXPECT_EQ(
+ client_->flowControlState.peerAdvertisedInitialMaxStreamOffsetUni,
+ initialMaxStreamDataUni);
+
+ for (unsigned long i = 0; i < initialMaxStreamsBidi; i++) {
+ EXPECT_TRUE(
+ client_->streamManager->createNextBidirectionalStream().hasValue());
+ }
+ EXPECT_TRUE(
+ client_->streamManager->createNextBidirectionalStream().hasError());
+ for (unsigned long i = 0; i < initialMaxStreamsUni; i++) {
+ EXPECT_TRUE(
+ client_->streamManager->createNextUnidirectionalStream().hasValue());
+ }
+ EXPECT_TRUE(
+ client_->streamManager->createNextUnidirectionalStream().hasError());
+}
+
+} // namespace quic::test

ADD
quic/client/test/Mocks.h
+/*
+ * 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 <folly/portability/GMock.h>
+#include <quic/client/handshake/CachedServerTransportParameters.h>
+#include <quic/client/handshake/ClientHandshake.h>
+#include <quic/handshake/CryptoFactory.h>
+#include <quic/handshake/TransportParameters.h>
+
+namespace quic {
+namespace test {
+
+class MockClientHandshakeFactory : public ClientHandshakeFactory {
+ public:
+ MOCK_METHOD1(
+ makeClientHandshake,
+ std::unique_ptr<ClientHandshake>(QuicClientConnectionState*));
+};
+
+class MockClientHandshake : public ClientHandshake {
+ public:
+ MockClientHandshake(QuicClientConnectionState* conn)
+ : ClientHandshake(conn) {}
+ ~MockClientHandshake() override {
+ destroy();
+ }
+ // Legacy workaround for move-only types
+ void doHandshake(
+ std::unique_ptr<folly::IOBuf> data,
+ EncryptionLevel encryptionLevel) override {
+ doHandshakeImpl(data.get(), encryptionLevel);
+ }
+ MOCK_METHOD2(doHandshakeImpl, void(folly::IOBuf*, EncryptionLevel));
+ MOCK_METHOD0(getRetryPacketCipher, std::unique_ptr<Aead>());
+ MOCK_METHOD1(removePsk, void(const folly::Optional<std::string>&));
+ MOCK_CONST_METHOD0(getCryptoFactory, const CryptoFactory&());
+ MOCK_CONST_METHOD0(isTLSResumed, bool());
+ MOCK_METHOD0(getZeroRttRejected, folly::Optional<bool>());
+ MOCK_METHOD0(
+ getServerTransportParams,
+ folly::Optional<ServerTransportParameters>());
+ MOCK_METHOD0(destroy, void());
+
+ MOCK_METHOD1(
+ connectImpl,
+ folly::Optional<CachedServerTransportParameters>(
+ folly::Optional<std::string>));
+ MOCK_METHOD0(getReadRecordLayerEncryptionLevel, EncryptionLevel());
+ MOCK_METHOD1(processSocketData, void(folly::IOBufQueue& queue));
+ MOCK_METHOD0(matchEarlyParameters, bool());
+ MOCK_METHOD2(
+ buildCiphers,
+ std::pair<std::unique_ptr<Aead>, std::unique_ptr<PacketNumberCipher>>(
+ ClientHandshake::CipherKind kind,
+ folly::ByteRange secret));
+ MOCK_CONST_METHOD0(
+ getApplicationProtocol,
+ const folly::Optional<std::string>&());
+};
+
+} // namespace test
+} // namespace quic

Add basic client state machine unit tests

Summary: This adds the Mocks for ClientHandshake and ClientHandshakeFactory. I added a simple test for `updateTransportParamsFromCachedEarlyParams`.

Reviewed By: mjoras

Differential Revision: D23308946

fbshipit-source-id: 6c22412efc6708ad13cd64ade3e9bccc7c80305d