xref: /aosp_15_r20/external/openscreen/osp/impl/quic/quic_client_unittest.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1 // Copyright 2018 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 "osp/impl/quic/quic_client.h"
6 
7 #include <memory>
8 
9 #include "gmock/gmock.h"
10 #include "gtest/gtest.h"
11 #include "osp/impl/quic/quic_service_common.h"
12 #include "osp/impl/quic/testing/fake_quic_connection_factory.h"
13 #include "osp/impl/quic/testing/quic_test_support.h"
14 #include "osp/public/network_metrics.h"
15 #include "osp/public/network_service_manager.h"
16 #include "osp/public/testing/message_demuxer_test_support.h"
17 #include "platform/base/error.h"
18 #include "platform/test/fake_clock.h"
19 #include "platform/test/fake_task_runner.h"
20 #include "util/osp_logging.h"
21 
22 namespace openscreen {
23 namespace osp {
24 namespace {
25 
26 using ::testing::_;
27 using ::testing::Invoke;
28 
29 class MockConnectionObserver final : public ProtocolConnection::Observer {
30  public:
31   ~MockConnectionObserver() override = default;
32 
33   MOCK_METHOD1(OnConnectionClosed, void(const ProtocolConnection& connection));
34 };
35 
36 class ConnectionCallback final
37     : public ProtocolConnectionClient::ConnectionRequestCallback {
38  public:
ConnectionCallback(std::unique_ptr<ProtocolConnection> * connection)39   explicit ConnectionCallback(std::unique_ptr<ProtocolConnection>* connection)
40       : connection_(connection) {}
41   ~ConnectionCallback() override = default;
42 
OnConnectionOpened(uint64_t request_id,std::unique_ptr<ProtocolConnection> connection)43   void OnConnectionOpened(
44       uint64_t request_id,
45       std::unique_ptr<ProtocolConnection> connection) override {
46     OSP_DCHECK(!failed_ && !*connection_);
47     *connection_ = std::move(connection);
48   }
49 
OnConnectionFailed(uint64_t request_id)50   void OnConnectionFailed(uint64_t request_id) override {
51     OSP_DCHECK(!failed_ && !*connection_);
52     failed_ = true;
53   }
54 
55  private:
56   bool failed_ = false;
57   std::unique_ptr<ProtocolConnection>* const connection_;
58 };
59 
60 class QuicClientTest : public ::testing::Test {
61  public:
QuicClientTest()62   QuicClientTest() {
63     fake_clock_ = std::make_unique<FakeClock>(
64         Clock::time_point(std::chrono::milliseconds(1298424)));
65     task_runner_ = std::make_unique<FakeTaskRunner>(fake_clock_.get());
66     quic_bridge_ =
67         std::make_unique<FakeQuicBridge>(task_runner_.get(), FakeClock::now);
68   }
69 
70  protected:
SetUp()71   void SetUp() override {
72     client_ = quic_bridge_->quic_client.get();
73     NetworkServiceManager::Create(nullptr, nullptr,
74                                   std::move(quic_bridge_->quic_client),
75                                   std::move(quic_bridge_->quic_server));
76   }
77 
TearDown()78   void TearDown() override { NetworkServiceManager::Dispose(); }
79 
SendTestMessage(ProtocolConnection * connection)80   void SendTestMessage(ProtocolConnection* connection) {
81     MockMessageCallback mock_message_callback;
82     MessageDemuxer::MessageWatch message_watch =
83         quic_bridge_->receiver_demuxer->WatchMessageType(
84             0, msgs::Type::kPresentationConnectionMessage,
85             &mock_message_callback);
86 
87     msgs::CborEncodeBuffer buffer;
88     msgs::PresentationConnectionMessage message;
89     message.connection_id = 7;
90     message.message.which = decltype(message.message.which)::kString;
91     new (&message.message.str) std::string("message from client");
92     ASSERT_TRUE(msgs::EncodePresentationConnectionMessage(message, &buffer));
93     connection->Write(buffer.data(), buffer.size());
94     connection->CloseWriteEnd();
95 
96     ssize_t decode_result = 0;
97     msgs::PresentationConnectionMessage received_message;
98     EXPECT_CALL(
99         mock_message_callback,
100         OnStreamMessage(0, connection->id(),
101                         msgs::Type::kPresentationConnectionMessage, _, _, _))
102         .WillOnce(Invoke([&decode_result, &received_message](
103                              uint64_t endpoint_id, uint64_t connection_id,
104                              msgs::Type message_type, const uint8_t* buffer,
105                              size_t buffer_size, Clock::time_point now) {
106           decode_result = msgs::DecodePresentationConnectionMessage(
107               buffer, buffer_size, &received_message);
108           if (decode_result < 0)
109             return ErrorOr<size_t>(Error::Code::kCborParsing);
110           return ErrorOr<size_t>(decode_result);
111         }));
112     quic_bridge_->RunTasksUntilIdle();
113 
114     ASSERT_GT(decode_result, 0);
115     EXPECT_EQ(decode_result, static_cast<ssize_t>(buffer.size() - 1));
116     EXPECT_EQ(received_message.connection_id, message.connection_id);
117     ASSERT_EQ(received_message.message.which,
118               decltype(received_message.message.which)::kString);
119     EXPECT_EQ(received_message.message.str, message.message.str);
120   }
121 
122   std::unique_ptr<FakeClock> fake_clock_;
123   std::unique_ptr<FakeTaskRunner> task_runner_;
124   std::unique_ptr<FakeQuicBridge> quic_bridge_;
125   QuicClient* client_;
126 };
127 
128 }  // namespace
129 
TEST_F(QuicClientTest,Connect)130 TEST_F(QuicClientTest, Connect) {
131   client_->Start();
132 
133   std::unique_ptr<ProtocolConnection> connection;
134   ConnectionCallback connection_callback(&connection);
135   ProtocolConnectionClient::ConnectRequest request =
136       client_->Connect(quic_bridge_->kReceiverEndpoint, &connection_callback);
137   ASSERT_TRUE(request);
138 
139   quic_bridge_->RunTasksUntilIdle();
140   ASSERT_TRUE(connection);
141 
142   SendTestMessage(connection.get());
143 
144   client_->Stop();
145 }
146 
TEST_F(QuicClientTest,DoubleConnect)147 TEST_F(QuicClientTest, DoubleConnect) {
148   client_->Start();
149 
150   std::unique_ptr<ProtocolConnection> connection1;
151   ConnectionCallback connection_callback1(&connection1);
152   ProtocolConnectionClient::ConnectRequest request1 =
153       client_->Connect(quic_bridge_->kReceiverEndpoint, &connection_callback1);
154   ASSERT_TRUE(request1);
155   ASSERT_FALSE(connection1);
156 
157   std::unique_ptr<ProtocolConnection> connection2;
158   ConnectionCallback connection_callback2(&connection2);
159   ProtocolConnectionClient::ConnectRequest request2 =
160       client_->Connect(quic_bridge_->kReceiverEndpoint, &connection_callback2);
161   ASSERT_TRUE(request2);
162 
163   quic_bridge_->RunTasksUntilIdle();
164   ASSERT_TRUE(connection1);
165   ASSERT_TRUE(connection2);
166 
167   SendTestMessage(connection1.get());
168 
169   client_->Stop();
170 }
171 
TEST_F(QuicClientTest,OpenImmediate)172 TEST_F(QuicClientTest, OpenImmediate) {
173   client_->Start();
174 
175   std::unique_ptr<ProtocolConnection> connection1;
176   std::unique_ptr<ProtocolConnection> connection2;
177 
178   connection2 = client_->CreateProtocolConnection(1);
179   EXPECT_FALSE(connection2);
180 
181   ConnectionCallback connection_callback(&connection1);
182   ProtocolConnectionClient::ConnectRequest request =
183       client_->Connect(quic_bridge_->kReceiverEndpoint, &connection_callback);
184   ASSERT_TRUE(request);
185 
186   connection2 = client_->CreateProtocolConnection(1);
187   EXPECT_FALSE(connection2);
188 
189   quic_bridge_->RunTasksUntilIdle();
190   ASSERT_TRUE(connection1);
191 
192   connection2 = client_->CreateProtocolConnection(connection1->endpoint_id());
193   ASSERT_TRUE(connection2);
194 
195   SendTestMessage(connection2.get());
196 
197   client_->Stop();
198 }
199 
TEST_F(QuicClientTest,States)200 TEST_F(QuicClientTest, States) {
201   client_->Stop();
202   std::unique_ptr<ProtocolConnection> connection1;
203   ConnectionCallback connection_callback(&connection1);
204   ProtocolConnectionClient::ConnectRequest request =
205       client_->Connect(quic_bridge_->kReceiverEndpoint, &connection_callback);
206   EXPECT_FALSE(request);
207   std::unique_ptr<ProtocolConnection> connection2 =
208       client_->CreateProtocolConnection(1);
209   EXPECT_FALSE(connection2);
210 
211   EXPECT_CALL(quic_bridge_->mock_client_observer, OnRunning());
212   EXPECT_TRUE(client_->Start());
213   EXPECT_FALSE(client_->Start());
214 
215   request =
216       client_->Connect(quic_bridge_->kReceiverEndpoint, &connection_callback);
217   ASSERT_TRUE(request);
218   quic_bridge_->RunTasksUntilIdle();
219   ASSERT_TRUE(connection1);
220   MockConnectionObserver mock_connection_observer1;
221   connection1->SetObserver(&mock_connection_observer1);
222 
223   connection2 = client_->CreateProtocolConnection(connection1->endpoint_id());
224   ASSERT_TRUE(connection2);
225   MockConnectionObserver mock_connection_observer2;
226   connection2->SetObserver(&mock_connection_observer2);
227 
228   EXPECT_CALL(mock_connection_observer1, OnConnectionClosed(_));
229   EXPECT_CALL(mock_connection_observer2, OnConnectionClosed(_));
230   EXPECT_CALL(quic_bridge_->mock_client_observer, OnStopped());
231   EXPECT_TRUE(client_->Stop());
232   EXPECT_FALSE(client_->Stop());
233 
234   request =
235       client_->Connect(quic_bridge_->kReceiverEndpoint, &connection_callback);
236   EXPECT_FALSE(request);
237   connection2 = client_->CreateProtocolConnection(1);
238   EXPECT_FALSE(connection2);
239 }
240 
TEST_F(QuicClientTest,RequestIds)241 TEST_F(QuicClientTest, RequestIds) {
242   client_->Start();
243 
244   EXPECT_CALL(quic_bridge_->mock_server_observer, OnIncomingConnectionMock(_))
245       .WillOnce(Invoke([](std::unique_ptr<ProtocolConnection>& connection) {
246         connection->CloseWriteEnd();
247       }));
248   std::unique_ptr<ProtocolConnection> connection;
249   ConnectionCallback connection_callback(&connection);
250   ProtocolConnectionClient::ConnectRequest request =
251       client_->Connect(quic_bridge_->kReceiverEndpoint, &connection_callback);
252   ASSERT_TRUE(request);
253 
254   quic_bridge_->RunTasksUntilIdle();
255   ASSERT_TRUE(connection);
256 
257   const uint64_t endpoint_id = connection->endpoint_id();
258   EXPECT_EQ(0u, client_->endpoint_request_ids()->GetNextRequestId(endpoint_id));
259   EXPECT_EQ(2u, client_->endpoint_request_ids()->GetNextRequestId(endpoint_id));
260 
261   connection->CloseWriteEnd();
262   connection.reset();
263   quic_bridge_->RunTasksUntilIdle();
264   EXPECT_EQ(4u, client_->endpoint_request_ids()->GetNextRequestId(endpoint_id));
265 
266   client_->Stop();
267   EXPECT_EQ(0u, client_->endpoint_request_ids()->GetNextRequestId(endpoint_id));
268 }
269 
270 }  // namespace osp
271 }  // namespace openscreen
272