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

Side by Side Diff: chrome/browser/media/router/media_router_mojo_impl_unittest.cc

Issue 1143603004: [Media Router] Add Media Router Mojo impl code. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed nits Created 5 years, 7 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 2015 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 <string>
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/run_loop.h"
11 #include "base/synchronization/waitable_event.h"
12 #include "chrome/browser/media/router/media_route.h"
13 #include "chrome/browser/media/router/media_router_mojo_test.h"
14 #include "chrome/browser/media/router/mock_media_router.h"
15 #include "chrome/browser/media/router/test_helper.h"
16 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
17 #include "chrome/test/base/testing_profile.h"
18 #include "extensions/browser/extension_registry.h"
19 #include "extensions/browser/process_manager.h"
20 #include "extensions/browser/process_manager_factory.h"
21 #include "media/base/gmock_callback_support.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24
25 using testing::_;
26 using testing::Eq;
27 using testing::Invoke;
28 using testing::Pointee;
29 using testing::Return;
30 using testing::ReturnRef;
31 using testing::SaveArg;
32
33 const char kDescription[] = "description";
34 const char kError[] = "error";
35 const char kExtensionId[] = "extension1234";
36 const char kMessage[] = "message";
37 const char kSource[] = "source1";
38 const char kSource2[] = "source2";
39 const char kRouteId[] = "routeId";
40 const char kRouteId2[] = "routeId2";
41 const char kSink[] = "sink";
42 const char kSink2[] = "sink2";
43 const char kSinkName[] = "sinkName";
xhwang 2015/05/28 06:53:21 nit: move these into the media_router namespace?
imcheng (use chromium acct) 2015/05/28 20:46:35 Done.
44
45 namespace media_router {
46
47 // Adapts Invoke(), which takes a move-only scoped_ptr parameter (not mockable)
48 // to a variant that accepts raw pointers instead (mock friendly).
49 class RouteResponseCallbackHandler {
50 public:
51 void Invoke(scoped_ptr<MediaRoute> route, const std::string& error_text) {
52 InvokeObserver(route.get(), error_text);
53 }
54
55 MOCK_METHOD2(InvokeObserver,
56 void(MediaRoute* route, const std::string& error_text));
57 };
58
59 template <typename T>
60 void StoreAndRun(T* result, const base::Closure& closure, const T& result_val) {
61 *result = result_val;
62 closure.Run();
63 }
64
65 class MediaRouterMojoImplTest : public MediaRouterMojoTest {
66 public:
67 MediaRouterMojoImplTest() {}
68 ~MediaRouterMojoImplTest() override {}
69 };
70
71 // ProcessManager with a mocked method subset, for testing extension suspend
72 // handling.
73 class TestProcessManager : public extensions::ProcessManager {
74 public:
75 explicit TestProcessManager(content::BrowserContext* context)
76 : extensions::ProcessManager(
77 context,
78 context,
79 extensions::ExtensionRegistry::Get(context)) {}
80 ~TestProcessManager() override {}
81
82 static KeyedService* Create(content::BrowserContext* context) {
83 return new TestProcessManager(context);
84 }
85
86 MOCK_METHOD1(IsEventPageSuspended, bool(const std::string& ext_id));
87
88 MOCK_METHOD2(WakeEventPage,
89 bool(const std::string& extension_id,
90 const base::Callback<void(bool)>& callback));
91
92 private:
93 DISALLOW_COPY_AND_ASSIGN(TestProcessManager);
94 };
95
96 // Mockable class for awaiting ProvideMediaRouter callbacks.
97 class ProvideMediaRouterHandler {
98 public:
99 MOCK_METHOD1(Invoke, void(const std::string& instance_id));
100 };
101
102 TEST_F(MediaRouterMojoImplTest, CreateRoute) {
103 MediaRoute expected_route(kRouteId, MediaSource(std::string(kSource)),
104 MediaSink(kSink, kSinkName), "", false);
105 interfaces::MediaRoutePtr route = interfaces::MediaRoute::New();
106 route->media_source = kSource;
107 route->media_sink = interfaces::MediaSink::New();
108 route->media_sink->sink_id = kSink;
109 route->media_sink->name = kSinkName;
110 route->media_route_id = kRouteId;
111 route->description = kDescription;
112
113 // Use a lambda function as an invocation target here to work around
114 // a limitation with GMock::Invoke that prevents it from using move-only types
115 // in runnable parameter lists.
116 EXPECT_CALL(mock_mrpm_host_,
117 CreateRoute(mojo::String(kSource), mojo::String(kSink), _))
118 .WillOnce(Invoke(
119 [&route](const mojo::String& source, const mojo::String& sink,
120 const interfaces::MediaRouter::CreateRouteCallback& cb) {
121 cb.Run(route.Pass(), mojo::String());
122 }));
123
124 RouteResponseCallbackHandler handler;
125 EXPECT_CALL(handler, InvokeObserver(Pointee(Equals(expected_route)), ""));
126 observer_impl_->CreateRoute(kSource, kSink,
127 base::Bind(&RouteResponseCallbackHandler::Invoke,
128 base::Unretained(&handler)));
129 ProcessEventLoop();
130 }
131
132 TEST_F(MediaRouterMojoImplTest, CreateRouteFails) {
133 EXPECT_CALL(mock_mrpm_host_,
134 CreateRoute(mojo::String(kSource), mojo::String(kSink), _))
135 .WillOnce(
136 Invoke([](const mojo::String& source, const mojo::String& sink,
137 const interfaces::MediaRouter::CreateRouteCallback& cb) {
138 cb.Run(interfaces::MediaRoutePtr(), mojo::String(kError));
139 }));
140
141 RouteResponseCallbackHandler handler;
142 EXPECT_CALL(handler, InvokeObserver(nullptr, kError));
143 observer_impl_->CreateRoute(kSource, kSink,
144 base::Bind(&RouteResponseCallbackHandler::Invoke,
145 base::Unretained(&handler)));
146 ProcessEventLoop();
147 }
148
149 TEST_F(MediaRouterMojoImplTest, CloseRoute) {
150 EXPECT_CALL(mock_mrpm_host_, CloseRoute(mojo::String(kRouteId)));
151 observer_impl_->CloseRoute(kRouteId);
152 ProcessEventLoop();
153 }
154
155 TEST_F(MediaRouterMojoImplTest, RegisterAndUnregisterMediaSinksObserver) {
156 MediaSource media_source(kSource);
157
158 MockMediaRouter mock_router;
159 EXPECT_CALL(mock_mrpm_host_, StartObservingMediaSinks(mojo::String(kSource)))
160 .Times(2);
161 EXPECT_CALL(mock_mrpm_host_,
162 StartObservingMediaSinks(mojo::String(kSource2)));
163
164 MediaSinksObserver* captured_observer;
165 EXPECT_CALL(mock_router, RegisterMediaSinksObserver(_))
166 .Times(3)
167 .WillRepeatedly(SaveArg<0>(&captured_observer));
168
169 MockMediaSinksObserver sinks_observer(&mock_router, media_source);
170 EXPECT_EQ(&sinks_observer, captured_observer);
171 observer_impl_->RegisterMediaSinksObserver(&sinks_observer);
172 MockMediaSinksObserver extra_sinks_observer(&mock_router, media_source);
173 EXPECT_EQ(&extra_sinks_observer, captured_observer);
174 observer_impl_->RegisterMediaSinksObserver(&extra_sinks_observer);
175 MockMediaSinksObserver unrelated_sinks_observer(&mock_router,
176 MediaSource(kSource2));
177 EXPECT_EQ(&unrelated_sinks_observer, captured_observer);
178 observer_impl_->RegisterMediaSinksObserver(&unrelated_sinks_observer);
179
180 std::vector<MediaSink> expected_sinks;
181 expected_sinks.push_back(MediaSink(kSink, kSinkName));
182 expected_sinks.push_back(MediaSink(kSink2, kSinkName));
183
184 mojo::Array<interfaces::MediaSinkPtr> mojo_sinks(2);
185 mojo_sinks[0] = interfaces::MediaSink::New();
186 mojo_sinks[0]->sink_id = kSink;
187 mojo_sinks[0]->name = kSink;
188 mojo_sinks[1] = interfaces::MediaSink::New();
189 mojo_sinks[1]->sink_id = kSink2;
190 mojo_sinks[1]->name = kSink2;
191
192 EXPECT_CALL(sinks_observer, OnSinksReceived(SequenceEquals(expected_sinks)));
193 EXPECT_CALL(extra_sinks_observer,
194 OnSinksReceived(SequenceEquals(expected_sinks)));
195 observer_proxy_->OnSinksReceived(media_source.id(), mojo_sinks.Pass());
196 ProcessEventLoop();
197
198 EXPECT_CALL(mock_router, UnregisterMediaSinksObserver(&sinks_observer));
199 EXPECT_CALL(mock_router, UnregisterMediaSinksObserver(&extra_sinks_observer));
200 EXPECT_CALL(mock_router,
201 UnregisterMediaSinksObserver(&unrelated_sinks_observer));
202 EXPECT_CALL(mock_mrpm_host_, StopObservingMediaSinks(mojo::String(kSource)));
203 EXPECT_CALL(mock_mrpm_host_, StopObservingMediaSinks(mojo::String(kSource2)));
204 observer_impl_->UnregisterMediaSinksObserver(&sinks_observer);
205 observer_impl_->UnregisterMediaSinksObserver(&extra_sinks_observer);
206 observer_impl_->UnregisterMediaSinksObserver(&unrelated_sinks_observer);
207 ProcessEventLoop();
208 }
209
210 TEST_F(MediaRouterMojoImplTest, RegisterAndUnregisterMediaRoutesObserver) {
211 MockMediaRouter mock_router;
212 EXPECT_CALL(mock_mrpm_host_, StartObservingMediaRoutes()).Times(2);
213
214 MediaRoutesObserver* observer_captured;
215 EXPECT_CALL(mock_router, RegisterMediaRoutesObserver(_))
216 .Times(2)
217 .WillRepeatedly(SaveArg<0>(&observer_captured));
218 MockMediaRoutesObserver routes_observer(&mock_router);
219 EXPECT_EQ(observer_captured, &routes_observer);
220 MockMediaRoutesObserver extra_routes_observer(&mock_router);
221 EXPECT_EQ(observer_captured, &extra_routes_observer);
222 observer_impl_->RegisterMediaRoutesObserver(&routes_observer);
223 observer_impl_->RegisterMediaRoutesObserver(&extra_routes_observer);
224
225 std::vector<MediaRoute> expected_routes;
226 expected_routes.push_back(MediaRoute(kRouteId, MediaSource(kSource),
227 MediaSink(kSink, kSink), kDescription,
228 false));
229 expected_routes.push_back(MediaRoute(kRouteId2, MediaSource(kSource),
230 MediaSink(kSink, kSink), kDescription,
231 false));
232
233 mojo::Array<interfaces::MediaRoutePtr> mojo_routes(2);
234 mojo_routes[0] = interfaces::MediaRoute::New();
235 mojo_routes[0]->media_route_id = kRouteId;
236 mojo_routes[0]->media_source = kSource;
237 mojo_routes[0]->media_sink = interfaces::MediaSink::New();
238 mojo_routes[0]->media_sink->sink_id = kSink;
239 mojo_routes[0]->media_sink->name = kSink;
240 mojo_routes[0]->description = kDescription;
241 mojo_routes[0]->is_local = false;
242 mojo_routes[1] = interfaces::MediaRoute::New();
243 mojo_routes[1]->media_route_id = kRouteId2;
244 mojo_routes[1]->media_source = kSource;
245 mojo_routes[1]->media_sink = interfaces::MediaSink::New();
246 mojo_routes[1]->media_sink->sink_id = kSink;
247 mojo_routes[1]->media_sink->name = kSink;
248 mojo_routes[1]->description = kDescription;
249 mojo_routes[1]->is_local = false;
250
251 EXPECT_CALL(routes_observer,
252 OnRoutesUpdated(SequenceEquals(expected_routes)));
253 EXPECT_CALL(extra_routes_observer,
254 OnRoutesUpdated(SequenceEquals(expected_routes)));
255 observer_proxy_->OnRoutesUpdated(mojo_routes.Pass());
256 ProcessEventLoop();
257
258 EXPECT_CALL(mock_router, UnregisterMediaRoutesObserver(&routes_observer));
259 EXPECT_CALL(mock_router,
260 UnregisterMediaRoutesObserver(&extra_routes_observer));
261 observer_impl_->UnregisterMediaRoutesObserver(&routes_observer);
262 observer_impl_->UnregisterMediaRoutesObserver(&extra_routes_observer);
263 EXPECT_CALL(mock_mrpm_host_, StopObservingMediaRoutes());
264 ProcessEventLoop();
265 }
266
267 TEST_F(MediaRouterMojoImplTest, PostMessage) {
268 EXPECT_CALL(mock_mrpm_host_,
269 PostMessage(mojo::String(kRouteId), mojo::String(kMessage)));
270 observer_impl_->PostMessage(kRouteId, kMessage);
271 ProcessEventLoop();
272 }
273
274 TEST_F(MediaRouterMojoImplTest, QueuedWhileAsleep) {
275 EXPECT_CALL(mock_event_page_tracker_, IsEventPageSuspended(extension_id_))
276 .Times(2)
277 .WillRepeatedly(Return(true));
278 EXPECT_CALL(mock_event_page_tracker_, WakeEventPage(extension_id_, _))
279 .Times(2)
280 .WillRepeatedly(Return(true));
281 observer_impl_->CloseRoute(kRouteId);
282 observer_impl_->CloseRoute(kRouteId2);
283 ProcessEventLoop();
284 EXPECT_CALL(mock_event_page_tracker_, IsEventPageSuspended(extension_id_))
285 .Times(1)
286 .WillRepeatedly(Return(false));
287 EXPECT_CALL(mock_mrpm_host_, CloseRoute(mojo::String(kRouteId)));
288 EXPECT_CALL(mock_mrpm_host_, CloseRoute(mojo::String(kRouteId2)));
289 ConnectProviderManagerService();
290 ProcessEventLoop();
291 }
292
293 // Temporarily disabled until the issues with extension system teardown
294 // are addressed.
295 // TODO(kmarshall): Re-enable this test. (http://crbug.com/490468)
296 TEST(MediaRouterMojoExtensionTest, DISABLED_DeferredBindingAndSuspension) {
297 base::MessageLoop message_loop_(mojo::common::MessagePumpMojo::Create());
298
299 // Set up a mock ProcessManager instance.
300 TestingProfile profile;
301 extensions::ProcessManagerFactory::GetInstance()->SetTestingFactory(
302 &profile, &TestProcessManager::Create);
303 TestProcessManager* process_manager = static_cast<TestProcessManager*>(
304 extensions::ProcessManager::Get(&profile));
305
306 // Create MR and its proxy, so that it can be accessed through Mojo.
307 MediaRouterMojoImpl media_router;
308 interfaces::MediaRouterObserverPtr media_router_proxy;
xhwang 2015/05/28 06:53:21 Can we be consistent about naming mojo::InterfaceP
imcheng (use chromium acct) 2015/05/28 20:46:35 Done.
309
310 // Create a client object and its Mojo proxy.
311 testing::StrictMock<MockMojoMediaRouterService> mrpm;
xhwang 2015/05/28 06:53:21 throughout this CL, we have mrpm in many places. I
imcheng (use chromium acct) 2015/05/28 20:46:35 Done.
312 interfaces::MediaRouterPtr mrpm_proxy;
xhwang 2015/05/28 06:53:21 ditto about mrpm and proxy.
imcheng (use chromium acct) 2015/05/28 20:46:35 Done.
313
314 // CloseRoute is called before *any* extension has connected.
315 // It should be queued.
316 media_router.CloseRoute(kRouteId);
317
318 // MRPM connects.
319 scoped_ptr<mojo::Binding<interfaces::MediaRouter>> mrpm_binding(
320 new mojo::Binding<interfaces::MediaRouter>(&mrpm,
321 mojo::GetProxy(&mrpm_proxy)));
322 media_router.BindToMojoRequest(mojo::GetProxy(&media_router_proxy));
323 media_router.InitExtensionInfo(kExtensionId, &profile);
324
325 // The MRPM signals its readiness to the MR by registering itself via
326 // ProvideMediaRouter().
327 // Now that the MR and MRPM are fully initialized, the queued
328 // CloseRoute() call should be executed.
329 ProvideMediaRouterHandler provide_handler;
330 EXPECT_CALL(provide_handler, Invoke(testing::Not("")));
331 EXPECT_CALL(*process_manager, IsEventPageSuspended(kExtensionId))
332 .WillOnce(Return(false));
333 EXPECT_CALL(mrpm, CloseRoute(mojo::String(kRouteId)));
334 media_router_proxy->ProvideMediaRouter(
335 mrpm_proxy.Pass(), base::Bind(&ProvideMediaRouterHandler::Invoke,
336 base::Unretained(&provide_handler)));
337 message_loop_.RunUntilIdle();
338
339 // MRPM's extension is suspended and re-awoken.
340 mrpm_binding.reset();
341 media_router.BindToMojoRequest(mojo::GetProxy(&media_router_proxy));
342 media_router.InitExtensionInfo(kExtensionId, &profile);
343 EXPECT_CALL(*process_manager, IsEventPageSuspended(kExtensionId))
344 .WillOnce(Return(true));
345 EXPECT_CALL(*process_manager, WakeEventPage(kExtensionId, _))
346 .WillOnce(testing::DoAll(media::RunCallback<1>(true), Return(true)));
347 media_router.CloseRoute(kRouteId2);
348 message_loop_.RunUntilIdle();
349
350 // ProvideMediaRouter() is called.
351 // The queued CloseRoute(kRouteId2) call should be executed.
352 EXPECT_CALL(provide_handler, Invoke(testing::Not("")));
353 EXPECT_CALL(*process_manager, IsEventPageSuspended(kExtensionId))
354 .WillOnce(Return(false));
355 EXPECT_CALL(mrpm, CloseRoute(mojo::String(kRouteId2)));
356 mrpm_binding.reset(new mojo::Binding<interfaces::MediaRouter>(
357 &mrpm, mojo::GetProxy(&mrpm_proxy)));
358 media_router_proxy->ProvideMediaRouter(
359 mrpm_proxy.Pass(), base::Bind(&ProvideMediaRouterHandler::Invoke,
360 base::Unretained(&provide_handler)));
361 message_loop_.RunUntilIdle();
362 }
363
364 } // namespace media_router
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698