1 // Copyright 2020 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 "cast/sender/cast_app_discovery_service_impl.h"
6
7 #include <utility>
8
9 #include "cast/common/channel/testing/fake_cast_socket.h"
10 #include "cast/common/channel/testing/mock_socket_error_handler.h"
11 #include "cast/common/channel/virtual_connection_router.h"
12 #include "cast/common/public/receiver_info.h"
13 #include "cast/sender/testing/test_helpers.h"
14 #include "gtest/gtest.h"
15 #include "platform/test/fake_clock.h"
16 #include "platform/test/fake_task_runner.h"
17 #include "util/osp_logging.h"
18
19 namespace openscreen {
20 namespace cast {
21
22 using ::cast::channel::CastMessage;
23
24 using ::testing::_;
25
26 class CastAppDiscoveryServiceImplTest : public ::testing::Test {
27 public:
SetUp()28 void SetUp() override {
29 socket_id_ = fake_cast_socket_pair_.socket->socket_id();
30 router_.TakeSocket(&mock_error_handler_,
31 std::move(fake_cast_socket_pair_.socket));
32
33 receiver_.v4_address = fake_cast_socket_pair_.remote_endpoint.address;
34 receiver_.port = fake_cast_socket_pair_.remote_endpoint.port;
35 receiver_.unique_id = "receiverId1";
36 receiver_.friendly_name = "Some Name";
37 }
38
39 protected:
peer_socket()40 CastSocket& peer_socket() { return *fake_cast_socket_pair_.peer_socket; }
peer_client()41 MockCastSocketClient& peer_client() {
42 return fake_cast_socket_pair_.mock_peer_client;
43 }
44
AddOrUpdateReceiver(const ReceiverInfo & receiver,int32_t socket_id)45 void AddOrUpdateReceiver(const ReceiverInfo& receiver, int32_t socket_id) {
46 platform_client_.AddOrUpdateReceiver(receiver, socket_id);
47 app_discovery_service_.AddOrUpdateReceiver(receiver);
48 }
49
StartObservingAvailability(const CastMediaSource & source,std::vector<ReceiverInfo> * save_receivers)50 CastAppDiscoveryService::Subscription StartObservingAvailability(
51 const CastMediaSource& source,
52 std::vector<ReceiverInfo>* save_receivers) {
53 return app_discovery_service_.StartObservingAvailability(
54 source, [save_receivers](const CastMediaSource& source,
55 const std::vector<ReceiverInfo>& receivers) {
56 *save_receivers = receivers;
57 });
58 }
59
StartSourceA1Query(std::vector<ReceiverInfo> * receivers,int * request_id,std::string * sender_id)60 CastAppDiscoveryService::Subscription StartSourceA1Query(
61 std::vector<ReceiverInfo>* receivers,
62 int* request_id,
63 std::string* sender_id) {
64 auto subscription = StartObservingAvailability(source_a_1_, receivers);
65
66 // Adding a receiver after app registered causes app availability request to
67 // be sent.
68 *request_id = -1;
69 *sender_id = "";
70 EXPECT_CALL(peer_client(), OnMessage(_, _))
71 .WillOnce([request_id, sender_id](CastSocket*, CastMessage message) {
72 VerifyAppAvailabilityRequest(message, "AAA", request_id, sender_id);
73 });
74
75 AddOrUpdateReceiver(receiver_, socket_id_);
76
77 return subscription;
78 }
79
80 FakeCastSocketPair fake_cast_socket_pair_;
81 int32_t socket_id_;
82 MockSocketErrorHandler mock_error_handler_;
83 VirtualConnectionRouter router_;
84 FakeClock clock_{Clock::now()};
85 FakeTaskRunner task_runner_{&clock_};
86 CastPlatformClient platform_client_{&router_, &FakeClock::now, &task_runner_};
87 CastAppDiscoveryServiceImpl app_discovery_service_{&platform_client_,
88 &FakeClock::now};
89
90 CastMediaSource source_a_1_{"cast:AAA?clientId=1", {"AAA"}};
91 CastMediaSource source_a_2_{"cast:AAA?clientId=2", {"AAA"}};
92 CastMediaSource source_b_1_{"cast:BBB?clientId=1", {"BBB"}};
93
94 ReceiverInfo receiver_;
95 };
96
TEST_F(CastAppDiscoveryServiceImplTest,StartObservingAvailability)97 TEST_F(CastAppDiscoveryServiceImplTest, StartObservingAvailability) {
98 std::vector<ReceiverInfo> receivers1;
99 int request_id;
100 std::string sender_id;
101 auto subscription1 = StartSourceA1Query(&receivers1, &request_id, &sender_id);
102
103 // Same app ID should not trigger another request.
104 EXPECT_CALL(peer_client(), OnMessage(_, _)).Times(0);
105 std::vector<ReceiverInfo> receivers2;
106 auto subscription2 = StartObservingAvailability(source_a_2_, &receivers2);
107
108 CastMessage availability_response =
109 CreateAppAvailableResponseChecked(request_id, sender_id, "AAA");
110 EXPECT_TRUE(peer_socket().Send(availability_response).ok());
111 ASSERT_EQ(receivers1.size(), 1u);
112 ASSERT_EQ(receivers2.size(), 1u);
113 EXPECT_EQ(receivers1[0].unique_id, "receiverId1");
114 EXPECT_EQ(receivers2[0].unique_id, "receiverId1");
115
116 // No more updates for |source_a_1_| (i.e. |receivers1|).
117 subscription1.Reset();
118 platform_client_.RemoveReceiver(receiver_);
119 app_discovery_service_.RemoveReceiver(receiver_);
120 ASSERT_EQ(receivers1.size(), 1u);
121 EXPECT_EQ(receivers2.size(), 0u);
122 EXPECT_EQ(receivers1[0].unique_id, "receiverId1");
123 }
124
TEST_F(CastAppDiscoveryServiceImplTest,ReAddAvailQueryUsesCachedValue)125 TEST_F(CastAppDiscoveryServiceImplTest, ReAddAvailQueryUsesCachedValue) {
126 std::vector<ReceiverInfo> receivers1;
127 int request_id;
128 std::string sender_id;
129 auto subscription1 = StartSourceA1Query(&receivers1, &request_id, &sender_id);
130
131 CastMessage availability_response =
132 CreateAppAvailableResponseChecked(request_id, sender_id, "AAA");
133 EXPECT_TRUE(peer_socket().Send(availability_response).ok());
134 ASSERT_EQ(receivers1.size(), 1u);
135 EXPECT_EQ(receivers1[0].unique_id, "receiverId1");
136
137 subscription1.Reset();
138 receivers1.clear();
139
140 // Request not re-sent; cached kAvailable value is used.
141 EXPECT_CALL(peer_client(), OnMessage(_, _)).Times(0);
142 subscription1 = StartObservingAvailability(source_a_1_, &receivers1);
143 ASSERT_EQ(receivers1.size(), 1u);
144 EXPECT_EQ(receivers1[0].unique_id, "receiverId1");
145 }
146
TEST_F(CastAppDiscoveryServiceImplTest,AvailQueryUpdatedOnReceiverUpdate)147 TEST_F(CastAppDiscoveryServiceImplTest, AvailQueryUpdatedOnReceiverUpdate) {
148 std::vector<ReceiverInfo> receivers1;
149 int request_id;
150 std::string sender_id;
151 auto subscription1 = StartSourceA1Query(&receivers1, &request_id, &sender_id);
152
153 // Result set now includes |receiver_|.
154 CastMessage availability_response =
155 CreateAppAvailableResponseChecked(request_id, sender_id, "AAA");
156 EXPECT_TRUE(peer_socket().Send(availability_response).ok());
157 ASSERT_EQ(receivers1.size(), 1u);
158 EXPECT_EQ(receivers1[0].unique_id, "receiverId1");
159
160 // Updating |receiver_| causes |source_a_1_| query to be updated, but it's too
161 // soon for a new message to be sent.
162 EXPECT_CALL(peer_client(), OnMessage(_, _)).Times(0);
163 receiver_.friendly_name = "New Name";
164
165 AddOrUpdateReceiver(receiver_, socket_id_);
166
167 ASSERT_EQ(receivers1.size(), 1u);
168 EXPECT_EQ(receivers1[0].friendly_name, "New Name");
169 }
170
TEST_F(CastAppDiscoveryServiceImplTest,Refresh)171 TEST_F(CastAppDiscoveryServiceImplTest, Refresh) {
172 std::vector<ReceiverInfo> receivers1;
173 auto subscription1 = StartObservingAvailability(source_a_1_, &receivers1);
174 std::vector<ReceiverInfo> receivers2;
175 auto subscription2 = StartObservingAvailability(source_b_1_, &receivers2);
176
177 // Adding a receiver after app registered causes two separate app availability
178 // requests to be sent.
179 int request_idA = -1;
180 int request_idB = -1;
181 std::string sender_id = "";
182 EXPECT_CALL(peer_client(), OnMessage(_, _))
183 .Times(2)
184 .WillRepeatedly([&request_idA, &request_idB, &sender_id](
185 CastSocket*, CastMessage message) {
186 std::string app_id;
187 int request_id = -1;
188 VerifyAppAvailabilityRequest(message, &app_id, &request_id, &sender_id);
189 if (app_id == "AAA") {
190 EXPECT_EQ(request_idA, -1);
191 request_idA = request_id;
192 } else if (app_id == "BBB") {
193 EXPECT_EQ(request_idB, -1);
194 request_idB = request_id;
195 } else {
196 EXPECT_TRUE(false);
197 }
198 });
199
200 AddOrUpdateReceiver(receiver_, socket_id_);
201
202 CastMessage availability_response =
203 CreateAppAvailableResponseChecked(request_idA, sender_id, "AAA");
204 EXPECT_TRUE(peer_socket().Send(availability_response).ok());
205 availability_response =
206 CreateAppUnavailableResponseChecked(request_idB, sender_id, "BBB");
207 EXPECT_TRUE(peer_socket().Send(availability_response).ok());
208 ASSERT_EQ(receivers1.size(), 1u);
209 ASSERT_EQ(receivers2.size(), 0u);
210 EXPECT_EQ(receivers1[0].unique_id, "receiverId1");
211
212 // Not enough time has passed for a refresh.
213 clock_.Advance(std::chrono::seconds(30));
214 EXPECT_CALL(peer_client(), OnMessage(_, _)).Times(0);
215 app_discovery_service_.Refresh();
216
217 // Refresh will now query again for unavailable app IDs.
218 clock_.Advance(std::chrono::minutes(2));
219 EXPECT_CALL(peer_client(), OnMessage(_, _))
220 .WillOnce([&request_idB, &sender_id](CastSocket*, CastMessage message) {
221 VerifyAppAvailabilityRequest(message, "BBB", &request_idB, &sender_id);
222 });
223 app_discovery_service_.Refresh();
224 }
225
TEST_F(CastAppDiscoveryServiceImplTest,StartObservingAvailabilityAfterReceiverAdded)226 TEST_F(CastAppDiscoveryServiceImplTest,
227 StartObservingAvailabilityAfterReceiverAdded) {
228 // No registered apps.
229 EXPECT_CALL(peer_client(), OnMessage(_, _)).Times(0);
230 AddOrUpdateReceiver(receiver_, socket_id_);
231
232 // Registering apps immediately sends requests to |receiver_|.
233 int request_idA = -1;
234 std::string sender_id = "";
235 EXPECT_CALL(peer_client(), OnMessage(_, _))
236 .WillOnce([&request_idA, &sender_id](CastSocket*, CastMessage message) {
237 VerifyAppAvailabilityRequest(message, "AAA", &request_idA, &sender_id);
238 });
239 std::vector<ReceiverInfo> receivers1;
240 auto subscription1 = StartObservingAvailability(source_a_1_, &receivers1);
241
242 int request_idB = -1;
243 EXPECT_CALL(peer_client(), OnMessage(_, _))
244 .WillOnce([&request_idB, &sender_id](CastSocket*, CastMessage message) {
245 VerifyAppAvailabilityRequest(message, "BBB", &request_idB, &sender_id);
246 });
247 std::vector<ReceiverInfo> receivers2;
248 auto subscription2 = StartObservingAvailability(source_b_1_, &receivers2);
249
250 // Add a new receiver with a corresponding socket.
251 FakeCastSocketPair fake_sockets2({{192, 168, 1, 17}, 2345},
252 {{192, 168, 1, 19}, 2345});
253 CastSocket* socket2 = fake_sockets2.socket.get();
254 router_.TakeSocket(&mock_error_handler_, std::move(fake_sockets2.socket));
255 ReceiverInfo receiver2;
256 receiver2.unique_id = "receiverId2";
257 receiver2.v4_address = fake_sockets2.remote_endpoint.address;
258 receiver2.port = fake_sockets2.remote_endpoint.port;
259
260 // Adding new receiver causes availability requests for both apps to be sent
261 // to the new receiver.
262 request_idA = -1;
263 request_idB = -1;
264 EXPECT_CALL(fake_sockets2.mock_peer_client, OnMessage(_, _))
265 .Times(2)
266 .WillRepeatedly([&request_idA, &request_idB, &sender_id](
267 CastSocket*, CastMessage message) {
268 std::string app_id;
269 int request_id = -1;
270 VerifyAppAvailabilityRequest(message, &app_id, &request_id, &sender_id);
271 if (app_id == "AAA") {
272 EXPECT_EQ(request_idA, -1);
273 request_idA = request_id;
274 } else if (app_id == "BBB") {
275 EXPECT_EQ(request_idB, -1);
276 request_idB = request_id;
277 } else {
278 EXPECT_TRUE(false);
279 }
280 });
281
282 AddOrUpdateReceiver(receiver2, socket2->socket_id());
283 }
284
TEST_F(CastAppDiscoveryServiceImplTest,StartObservingAvailabilityCachedValue)285 TEST_F(CastAppDiscoveryServiceImplTest, StartObservingAvailabilityCachedValue) {
286 std::vector<ReceiverInfo> receivers1;
287 int request_id;
288 std::string sender_id;
289 auto subscription1 = StartSourceA1Query(&receivers1, &request_id, &sender_id);
290
291 CastMessage availability_response =
292 CreateAppAvailableResponseChecked(request_id, sender_id, "AAA");
293 EXPECT_TRUE(peer_socket().Send(availability_response).ok());
294 ASSERT_EQ(receivers1.size(), 1u);
295 EXPECT_EQ(receivers1[0].unique_id, "receiverId1");
296
297 // Same app ID should not trigger another request, but it should return
298 // cached value.
299 EXPECT_CALL(peer_client(), OnMessage(_, _)).Times(0);
300 std::vector<ReceiverInfo> receivers2;
301 auto subscription2 = StartObservingAvailability(source_a_2_, &receivers2);
302 ASSERT_EQ(receivers2.size(), 1u);
303 EXPECT_EQ(receivers2[0].unique_id, "receiverId1");
304 }
305
TEST_F(CastAppDiscoveryServiceImplTest,AvailabilityUnknownOrUnavailable)306 TEST_F(CastAppDiscoveryServiceImplTest, AvailabilityUnknownOrUnavailable) {
307 std::vector<ReceiverInfo> receivers1;
308 int request_id;
309 std::string sender_id;
310 auto subscription1 = StartSourceA1Query(&receivers1, &request_id, &sender_id);
311
312 // The request will timeout resulting in unknown app availability.
313 clock_.Advance(std::chrono::seconds(10));
314 task_runner_.RunTasksUntilIdle();
315 EXPECT_EQ(receivers1.size(), 0u);
316
317 // Receiver updated together with unknown app availability will cause a
318 // request to be sent again.
319 request_id = -1;
320 EXPECT_CALL(peer_client(), OnMessage(_, _))
321 .WillOnce([&request_id, &sender_id](CastSocket*, CastMessage message) {
322 VerifyAppAvailabilityRequest(message, "AAA", &request_id, &sender_id);
323 });
324 AddOrUpdateReceiver(receiver_, socket_id_);
325
326 CastMessage availability_response =
327 CreateAppUnavailableResponseChecked(request_id, sender_id, "AAA");
328 EXPECT_TRUE(peer_socket().Send(availability_response).ok());
329
330 // Known availability so no request sent.
331 EXPECT_CALL(peer_client(), OnMessage(_, _)).Times(0);
332 AddOrUpdateReceiver(receiver_, socket_id_);
333
334 // Removing the receiver will also remove previous availability information.
335 // Next time the receiver is added, a new request will be sent.
336 platform_client_.RemoveReceiver(receiver_);
337 app_discovery_service_.RemoveReceiver(receiver_);
338
339 request_id = -1;
340 EXPECT_CALL(peer_client(), OnMessage(_, _))
341 .WillOnce([&request_id, &sender_id](CastSocket*, CastMessage message) {
342 VerifyAppAvailabilityRequest(message, "AAA", &request_id, &sender_id);
343 });
344
345 AddOrUpdateReceiver(receiver_, socket_id_);
346 }
347
348 } // namespace cast
349 } // namespace openscreen
350