Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(324)

Side by Side Diff: chrome/browser/media/router/discovery/mdns/cast_media_sink_service_unittest.cc

Issue 2927833002: [Media Router] Add CastMediaSinkService (Closed)
Patch Set: rebase Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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 "chrome/browser/media/router/discovery/mdns/cast_media_sink_service.h"
6 #include "base/strings/stringprintf.h"
7 #include "base/test/mock_callback.h"
8 #include "base/timer/mock_timer.h"
9 #include "chrome/browser/media/router/discovery/mdns/mock_dns_sd_registry.h"
10 #include "chrome/browser/media/router/test_helper.h"
11 #include "chrome/test/base/testing_profile.h"
12 #include "components/cast_channel/cast_socket.h"
13 #include "components/cast_channel/cast_socket_service.h"
14 #include "components/cast_channel/cast_test_util.h"
15 #include "content/public/test/test_browser_thread_bundle.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 using ::testing::_;
20 using ::testing::Return;
21 using ::testing::SaveArg;
22
23 namespace {
24
25 const char SERVICE_TYPE[] = "_googlecast._tcp.local";
mark a. foltz 2017/06/28 22:43:13 This duplicates the definition in cast_media_sink_
zhaobin 2017/07/05 18:01:37 Done.
26
27 net::IPEndPoint CreateIPEndPoint(int num) {
28 net::IPAddress ip_address;
29 DCHECK(ip_address.AssignFromIPLiteral(
30 base::StringPrintf("192.168.0.10%d", num)));
31 return net::IPEndPoint(ip_address, 8009 + num);
32 }
33
34 media_router::DnsSdService CreateDnsService(int num) {
35 net::IPEndPoint ip_endpoint = CreateIPEndPoint(num);
36 media_router::DnsSdService service;
37 service.service_name = "_myDevice." + std::string(SERVICE_TYPE);
mark a. foltz 2017/06/28 22:43:13 I thing std::string is optional here.
zhaobin 2017/07/05 18:01:37 Compile error if removed...cannot add 'const char*
38 service.ip_address = ip_endpoint.address().ToString();
39 service.service_host_port = ip_endpoint.ToString();
40 service.service_data.push_back(base::StringPrintf("id=service %d", num));
41 service.service_data.push_back(
42 base::StringPrintf("fn=friendly name %d", num));
43 service.service_data.push_back(base::StringPrintf("md=model name %d", num));
44
45 return service;
46 }
47
48 void VerifyMediaSinkInternal(const media_router::MediaSinkInternal& cast_sink,
49 const media_router::DnsSdService& service,
50 int channel_id,
51 bool audio_only) {
52 std::string id = base::StringPrintf("service %d", channel_id);
53 std::string name = base::StringPrintf("friendly name %d", channel_id);
54 std::string model_name = base::StringPrintf("model name %d", channel_id);
55 EXPECT_EQ(id, cast_sink.sink().id());
56 EXPECT_EQ(name, cast_sink.sink().name());
57 EXPECT_EQ(model_name, cast_sink.cast_data().model_name);
58 EXPECT_EQ(service.ip_address, cast_sink.cast_data().ip_address.ToString());
59 EXPECT_TRUE(cast_channel::CastDeviceCapability::AUDIO_OUT &
60 cast_sink.cast_data().capabilities);
61 EXPECT_EQ(!audio_only, cast_channel::CastDeviceCapability::VIDEO_OUT &
62 cast_sink.cast_data().capabilities);
63 EXPECT_EQ(channel_id, cast_sink.cast_data().cast_channel_id);
64 }
65
66 } // namespace
67
68 namespace media_router {
69
70 class MockCastSocketService : public cast_channel::CastSocketService {
71 public:
72 MOCK_METHOD4(OpenSocket,
73 int(const net::IPEndPoint& ip_endpoint,
74 net::NetLog* net_log,
75 const cast_channel::CastSocket::OnOpenCallback& open_cb,
76 cast_channel::CastSocket::Observer* observer));
77 MOCK_CONST_METHOD1(GetSocket, cast_channel::CastSocket*(int channel_id));
78
79 private:
80 ~MockCastSocketService() {}
81 };
82
83 class CastMediaSinkServiceTest : public ::testing::Test {
84 public:
85 CastMediaSinkServiceTest()
86 : mock_cast_socket_service_(new MockCastSocketService()),
87 media_sink_service_(
88 new CastMediaSinkService(mock_sink_discovered_cb_.Get(),
89 mock_cast_socket_service_.get())),
90 test_dns_sd_registry_(media_sink_service_.get()) {}
91
92 void SetUp() override {
93 media_sink_service_->SetDnsSdRegistryForTest(&test_dns_sd_registry_);
94 mock_timer_ =
95 new base::MockTimer(true /*retain_user_task*/, false /*is_repeating*/);
96 media_sink_service_->SetTimerForTest(base::WrapUnique(mock_timer_));
97 }
98
99 protected:
100 const content::TestBrowserThreadBundle thread_bundle_;
101 TestingProfile profile_;
102
103 base::MockCallback<MediaSinkService::OnSinksDiscoveredCallback>
104 mock_sink_discovered_cb_;
105 scoped_refptr<MockCastSocketService> mock_cast_socket_service_;
106 scoped_refptr<CastMediaSinkService> media_sink_service_;
107 MockDnsSdRegistry test_dns_sd_registry_;
108 base::MockTimer* mock_timer_;
mark a. foltz 2017/06/28 22:43:13 Consider declaring this as std::unique_ptr and usi
zhaobin 2017/07/05 18:01:37 Ownership of |mock_timer_| is passed into MediaSin
109
110 DISALLOW_COPY_AND_ASSIGN(CastMediaSinkServiceTest);
111 };
112
113 TEST_F(CastMediaSinkServiceTest, TestReStartAfterStop) {
114 EXPECT_CALL(test_dns_sd_registry_, AddObserver(media_sink_service_.get()))
115 .Times(2);
116 EXPECT_CALL(test_dns_sd_registry_, RegisterDnsSdListener(_)).Times(2);
117 EXPECT_FALSE(mock_timer_->IsRunning());
118 media_sink_service_->Start();
119 EXPECT_TRUE(mock_timer_->IsRunning());
120
121 EXPECT_CALL(test_dns_sd_registry_, RemoveObserver(media_sink_service_.get()));
122 EXPECT_CALL(test_dns_sd_registry_, UnregisterDnsSdListener(_));
123 media_sink_service_->Stop();
124
125 mock_timer_ =
126 new base::MockTimer(true /*retain_user_task*/, false /*is_repeating*/);
127 media_sink_service_->SetTimerForTest(base::WrapUnique(mock_timer_));
128 media_sink_service_->Start();
129 EXPECT_TRUE(mock_timer_->IsRunning());
130 }
131
132 TEST_F(CastMediaSinkServiceTest, TestMultipleStartAndStop) {
133 EXPECT_CALL(test_dns_sd_registry_, AddObserver(media_sink_service_.get()));
134 EXPECT_CALL(test_dns_sd_registry_, RegisterDnsSdListener(_));
135 media_sink_service_->Start();
136 media_sink_service_->Start();
137 EXPECT_TRUE(mock_timer_->IsRunning());
138
139 EXPECT_CALL(test_dns_sd_registry_, RemoveObserver(media_sink_service_.get()));
140 EXPECT_CALL(test_dns_sd_registry_, UnregisterDnsSdListener(_));
141 media_sink_service_->Stop();
142 media_sink_service_->Stop();
143 }
144
145 TEST_F(CastMediaSinkServiceTest, TestOnChannelOpenedOnIOThread) {
146 DnsSdService service = CreateDnsService(1);
147 cast_channel::MockCastSocket socket;
148 EXPECT_CALL(*mock_cast_socket_service_, GetSocket(1))
149 .WillOnce(Return(&socket));
150
151 media_sink_service_->current_services_.push_back(service);
152 media_sink_service_->OnChannelOpenedOnIOThread(
153 service, 1, cast_channel::ChannelError::NONE);
154 // Invoke CastMediaSinkService::OnChannelOpenedOnUIThread on the UI thread.
155 base::RunLoop().RunUntilIdle();
156
157 // Verify sink content
158 EXPECT_EQ(size_t(1), media_sink_service_->current_sinks_.size());
159 for (const auto& sink_it : media_sink_service_->current_sinks_)
160 VerifyMediaSinkInternal(sink_it, service, 1, false);
161 }
162
163 TEST_F(CastMediaSinkServiceTest, TestMultipleOnChannelOpenedOnIOThread) {
164 DnsSdService service1 = CreateDnsService(1);
165 DnsSdService service2 = CreateDnsService(2);
166 DnsSdService service3 = CreateDnsService(3);
167
168 cast_channel::MockCastSocket socket2;
169 cast_channel::MockCastSocket socket3;
170 // Fail to open channel 1.
171 EXPECT_CALL(*mock_cast_socket_service_, GetSocket(1))
172 .WillOnce(Return(nullptr));
173 EXPECT_CALL(*mock_cast_socket_service_, GetSocket(2))
174 .WillOnce(Return(&socket2));
175 EXPECT_CALL(*mock_cast_socket_service_, GetSocket(3))
176 .WillOnce(Return(&socket2));
177
178 // Current round of Dns discovery finds service1 and service 2.
179 media_sink_service_->current_services_.push_back(service1);
180 media_sink_service_->current_services_.push_back(service2);
181 media_sink_service_->OnChannelOpenedOnIOThread(
182 service1, 1, cast_channel::ChannelError::NONE);
183 media_sink_service_->OnChannelOpenedOnIOThread(
184 service2, 2, cast_channel::ChannelError::NONE);
185 media_sink_service_->OnChannelOpenedOnIOThread(
186 service3, 3, cast_channel::ChannelError::NONE);
187 // Invoke CastMediaSinkService::OnChannelOpenedOnUIThread on the UI thread.
188 base::RunLoop().RunUntilIdle();
189
190 // Verify sink content
191 EXPECT_EQ(size_t(1), media_sink_service_->current_sinks_.size());
192 for (const auto& sink_it : media_sink_service_->current_sinks_)
193 VerifyMediaSinkInternal(sink_it, service2, 2, false);
194 }
195
196 TEST_F(CastMediaSinkServiceTest, TestOnDnsSdEvent) {
197 DnsSdService service1 = CreateDnsService(1);
198 DnsSdService service2 = CreateDnsService(2);
199 net::IPEndPoint ip_endpoint1 = CreateIPEndPoint(1);
200 net::IPEndPoint ip_endpoint2 = CreateIPEndPoint(2);
201
202 // Add dns services.
203 DnsSdRegistry::DnsSdServiceList service_list{service1, service2};
204
205 cast_channel::CastSocket::OnOpenCallback callback1;
206 cast_channel::CastSocket::OnOpenCallback callback2;
207 EXPECT_CALL(*mock_cast_socket_service_, OpenSocket(ip_endpoint1, _, _, _))
208 .WillOnce(DoAll(SaveArg<2>(&callback1), Return(1)));
209 EXPECT_CALL(*mock_cast_socket_service_, OpenSocket(ip_endpoint2, _, _, _))
210 .WillOnce(DoAll(SaveArg<2>(&callback2), Return(2)));
211
212 // Invoke CastSocketService::OpenSocket on the IO thread.
213 media_sink_service_->OnDnsSdEvent(SERVICE_TYPE, service_list);
214 base::RunLoop().RunUntilIdle();
215
216 cast_channel::MockCastSocket socket1;
217 cast_channel::MockCastSocket socket2;
218
219 EXPECT_CALL(*mock_cast_socket_service_, GetSocket(1))
220 .WillOnce(Return(&socket1));
221 EXPECT_CALL(*mock_cast_socket_service_, GetSocket(2))
222 .WillOnce(Return(&socket2));
223
224 callback1.Run(1, cast_channel::ChannelError::NONE);
225 callback2.Run(2, cast_channel::ChannelError::NONE);
226
227 // Invoke CastMediaSinkService::OnChannelOpenedOnUIThread on the UI thread.
228 base::RunLoop().RunUntilIdle();
229 // Verify sink content
230 EXPECT_EQ(size_t(2), media_sink_service_->current_sinks_.size());
231 }
232
233 TEST_F(CastMediaSinkServiceTest, TestMultipleOnDnsSdEvent) {
234 DnsSdService service1 = CreateDnsService(1);
235 DnsSdService service2 = CreateDnsService(2);
236 DnsSdService service3 = CreateDnsService(3);
237 net::IPEndPoint ip_endpoint1 = CreateIPEndPoint(1);
238 net::IPEndPoint ip_endpoint2 = CreateIPEndPoint(2);
239 net::IPEndPoint ip_endpoint3 = CreateIPEndPoint(3);
240
241 // 1st round finds service 1 & 2.
242 DnsSdRegistry::DnsSdServiceList service_list1{service1, service2};
243 media_sink_service_->OnDnsSdEvent(SERVICE_TYPE, service_list1);
244
245 EXPECT_CALL(*mock_cast_socket_service_, OpenSocket(ip_endpoint1, _, _, _));
246 EXPECT_CALL(*mock_cast_socket_service_, OpenSocket(ip_endpoint2, _, _, _));
247 base::RunLoop().RunUntilIdle();
248
249 // Channel 2 opened.
250 media_sink_service_->OnChannelOpenedOnUIThread(service2, 2, false);
251
252 // 2nd round finds service 2 & 3.
253 DnsSdRegistry::DnsSdServiceList service_list2{service2, service3};
254 media_sink_service_->OnDnsSdEvent(SERVICE_TYPE, service_list2);
255
256 EXPECT_CALL(*mock_cast_socket_service_, OpenSocket(ip_endpoint2, _, _, _));
257 EXPECT_CALL(*mock_cast_socket_service_, OpenSocket(ip_endpoint3, _, _, _));
258 base::RunLoop().RunUntilIdle();
259
260 // Channel 1 and 3 opened.
261 media_sink_service_->OnChannelOpenedOnUIThread(service1, 1, false);
262 media_sink_service_->OnChannelOpenedOnUIThread(service3, 3, false);
263
264 EXPECT_EQ(size_t(1), media_sink_service_->current_sinks_.size());
265 for (const auto& sink_it : media_sink_service_->current_sinks_)
266 VerifyMediaSinkInternal(sink_it, service3, 3, false);
267 }
268
269 TEST_F(CastMediaSinkServiceTest, TestTimer) {
270 DnsSdService service1 = CreateDnsService(1);
271 DnsSdService service2 = CreateDnsService(2);
272 net::IPEndPoint ip_endpoint1 = CreateIPEndPoint(1);
273 net::IPEndPoint ip_endpoint2 = CreateIPEndPoint(2);
274
275 EXPECT_FALSE(mock_timer_->IsRunning());
276 // finds service 1 & 2.
277 DnsSdRegistry::DnsSdServiceList service_list1{service1, service2};
278 media_sink_service_->OnDnsSdEvent(SERVICE_TYPE, service_list1);
279
280 EXPECT_CALL(*mock_cast_socket_service_, OpenSocket(ip_endpoint1, _, _, _));
281 EXPECT_CALL(*mock_cast_socket_service_, OpenSocket(ip_endpoint2, _, _, _));
282 base::RunLoop().RunUntilIdle();
283
284 // Channel 2 is opened.
285 media_sink_service_->OnChannelOpenedOnUIThread(service2, 2, false);
286
287 std::vector<MediaSinkInternal> sinks;
288 EXPECT_CALL(mock_sink_discovered_cb_, Run(_)).WillOnce(SaveArg<0>(&sinks));
289
290 // Fire timer.
291 mock_timer_->Fire();
292 EXPECT_EQ(size_t(1), sinks.size());
293 VerifyMediaSinkInternal(sinks[0], service2, 2, false);
294
295 EXPECT_FALSE(mock_timer_->IsRunning());
296 // Channel 1 is opened and timer is restarted.
297 media_sink_service_->OnChannelOpenedOnUIThread(service1, 1, false);
298 EXPECT_TRUE(mock_timer_->IsRunning());
299 }
300
301 } // namespace media_router
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698