• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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