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