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