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