• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <memory>
6 #include <string>
7 
8 #include "absl/strings/string_view.h"
9 #include "quiche/quic/core/crypto/quic_compressed_certs_cache.h"
10 #include "quiche/quic/core/crypto/quic_crypto_client_config.h"
11 #include "quiche/quic/core/crypto/quic_crypto_server_config.h"
12 #include "quiche/quic/core/crypto/quic_random.h"
13 #include "quiche/quic/core/quic_config.h"
14 #include "quiche/quic/core/quic_generic_session.h"
15 #include "quiche/quic/core/quic_types.h"
16 #include "quiche/quic/moqt/moqt_messages.h"
17 #include "quiche/quic/moqt/moqt_session.h"
18 #include "quiche/quic/test_tools/crypto_test_utils.h"
19 #include "quiche/quic/test_tools/simulator/simulator.h"
20 #include "quiche/quic/test_tools/simulator/test_harness.h"
21 #include "quiche/common/platform/api/quiche_test.h"
22 
23 namespace moqt::test {
24 namespace {
25 
26 using ::quic::simulator::Simulator;
27 using ::testing::_;
28 using ::testing::Assign;
29 
30 struct MockSessionCallbacks {
31   testing::MockFunction<void()> session_established_callback;
32   testing::MockFunction<void(absl::string_view)> session_terminated_callback;
33   testing::MockFunction<void()> session_deleted_callback;
34 
AsSessionCallbacksmoqt::test::__anon8df813690111::MockSessionCallbacks35   MoqtSessionCallbacks AsSessionCallbacks() {
36     return MoqtSessionCallbacks{session_established_callback.AsStdFunction(),
37                                 session_terminated_callback.AsStdFunction(),
38                                 session_deleted_callback.AsStdFunction()};
39   }
40 };
41 
42 class ClientEndpoint : public quic::simulator::QuicEndpointWithConnection {
43  public:
ClientEndpoint(Simulator * simulator,const std::string & name,const std::string & peer_name,MoqtVersion version)44   ClientEndpoint(Simulator* simulator, const std::string& name,
45                  const std::string& peer_name, MoqtVersion version)
46       : QuicEndpointWithConnection(simulator, name, peer_name,
47                                    quic::Perspective::IS_CLIENT,
48                                    quic::GetQuicVersionsForGenericSession()),
49         crypto_config_(
50             quic::test::crypto_test_utils::ProofVerifierForTesting()),
51         quic_session_(connection_.get(), false, nullptr, quic::QuicConfig(),
52                       "test.example.com", 443, "moqt", &session_,
53                       /*visitor_owned=*/false, nullptr, &crypto_config_),
54         session_(
55             &quic_session_,
56             MoqtSessionParameters{.version = version,
57                                   .perspective = quic::Perspective::IS_CLIENT,
58                                   .using_webtrans = false},
59             callbacks_.AsSessionCallbacks()) {
60     quic_session_.Initialize();
61   }
62 
session()63   MoqtSession* session() { return &session_; }
quic_session()64   quic::QuicGenericClientSession* quic_session() { return &quic_session_; }
established_callback()65   testing::MockFunction<void()>& established_callback() {
66     return callbacks_.session_established_callback;
67   }
terminated_callback()68   testing::MockFunction<void(absl::string_view)>& terminated_callback() {
69     return callbacks_.session_terminated_callback;
70   }
71 
72  private:
73   MockSessionCallbacks callbacks_;
74   quic::QuicCryptoClientConfig crypto_config_;
75   quic::QuicGenericClientSession quic_session_;
76   MoqtSession session_;
77 };
78 
79 class ServerEndpoint : public quic::simulator::QuicEndpointWithConnection {
80  public:
ServerEndpoint(Simulator * simulator,const std::string & name,const std::string & peer_name,MoqtVersion version)81   ServerEndpoint(Simulator* simulator, const std::string& name,
82                  const std::string& peer_name, MoqtVersion version)
83       : QuicEndpointWithConnection(simulator, name, peer_name,
84                                    quic::Perspective::IS_SERVER,
85                                    quic::GetQuicVersionsForGenericSession()),
86         compressed_certs_cache_(
87             quic::QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
88         crypto_config_(quic::QuicCryptoServerConfig::TESTING,
89                        quic::QuicRandom::GetInstance(),
90                        quic::test::crypto_test_utils::ProofSourceForTesting(),
91                        quic::KeyExchangeSource::Default()),
92         quic_session_(connection_.get(), false, nullptr, quic::QuicConfig(),
93                       "moqt", &session_,
94                       /*visitor_owned=*/false, nullptr, &crypto_config_,
95                       &compressed_certs_cache_),
96         session_(
97             &quic_session_,
98             MoqtSessionParameters{.version = version,
99                                   .perspective = quic::Perspective::IS_SERVER,
100                                   .using_webtrans = false},
101             callbacks_.AsSessionCallbacks()) {
102     quic_session_.Initialize();
103   }
104 
session()105   MoqtSession* session() { return &session_; }
established_callback()106   testing::MockFunction<void()>& established_callback() {
107     return callbacks_.session_established_callback;
108   }
terminated_callback()109   testing::MockFunction<void(absl::string_view)>& terminated_callback() {
110     return callbacks_.session_terminated_callback;
111   }
112 
113  private:
114   MockSessionCallbacks callbacks_;
115   quic::QuicCompressedCertsCache compressed_certs_cache_;
116   quic::QuicCryptoServerConfig crypto_config_;
117   quic::QuicGenericServerSession quic_session_;
118   MoqtSession session_;
119 };
120 
121 class MoqtIntegrationTest : public quiche::test::QuicheTest {
122  public:
CreateDefaultEndpoints()123   void CreateDefaultEndpoints() {
124     client_ = std::make_unique<ClientEndpoint>(
125         &test_harness_.simulator(), "Client", "Server", MoqtVersion::kDraft01);
126     server_ = std::make_unique<ServerEndpoint>(
127         &test_harness_.simulator(), "Server", "Client", MoqtVersion::kDraft01);
128     test_harness_.set_client(client_.get());
129     test_harness_.set_server(server_.get());
130   }
131 
WireUpEndpoints()132   void WireUpEndpoints() { test_harness_.WireUpEndpoints(); }
133 
134  protected:
135   quic::simulator::TestHarness test_harness_;
136 
137   std::unique_ptr<ClientEndpoint> client_;
138   std::unique_ptr<ServerEndpoint> server_;
139 };
140 
TEST_F(MoqtIntegrationTest,Handshake)141 TEST_F(MoqtIntegrationTest, Handshake) {
142   CreateDefaultEndpoints();
143   WireUpEndpoints();
144 
145   client_->quic_session()->CryptoConnect();
146   bool client_established = false;
147   bool server_established = false;
148   EXPECT_CALL(client_->established_callback(), Call())
149       .WillOnce(Assign(&client_established, true));
150   EXPECT_CALL(server_->established_callback(), Call())
151       .WillOnce(Assign(&server_established, true));
152   bool success = test_harness_.RunUntilWithDefaultTimeout(
153       [&]() { return client_established && server_established; });
154   EXPECT_TRUE(success);
155 }
156 
TEST_F(MoqtIntegrationTest,VersionMismatch)157 TEST_F(MoqtIntegrationTest, VersionMismatch) {
158   client_ = std::make_unique<ClientEndpoint>(
159       &test_harness_.simulator(), "Client", "Server",
160       MoqtVersion::kUnrecognizedVersionForTests);
161   server_ = std::make_unique<ServerEndpoint>(
162       &test_harness_.simulator(), "Server", "Client", MoqtVersion::kDraft01);
163   test_harness_.set_client(client_.get());
164   test_harness_.set_server(server_.get());
165   WireUpEndpoints();
166 
167   client_->quic_session()->CryptoConnect();
168   bool client_terminated = false;
169   bool server_terminated = false;
170   EXPECT_CALL(client_->established_callback(), Call()).Times(0);
171   EXPECT_CALL(server_->established_callback(), Call()).Times(0);
172   EXPECT_CALL(client_->terminated_callback(), Call(_))
173       .WillOnce(Assign(&client_terminated, true));
174   EXPECT_CALL(server_->terminated_callback(), Call(_))
175       .WillOnce(Assign(&server_terminated, true));
176   bool success = test_harness_.RunUntilWithDefaultTimeout(
177       [&]() { return client_terminated && server_terminated; });
178   EXPECT_TRUE(success);
179 }
180 
181 }  // namespace
182 }  // namespace moqt::test
183