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

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

Issue 1126923002: Add Media Router Mojo impl code. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Redundant forward decl removed. 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";
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(DoAll(SaveArg<0>(&captured_observer), Return(true)));
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())
213 .Times(2);
214
215 MediaRoutesObserver* observer_captured;
216 EXPECT_CALL(mock_router, RegisterMediaRoutesObserver(_))
217 .Times(2)
218 .WillRepeatedly(DoAll(SaveArg<0>(&observer_captured), Return(true)));
219 MockMediaRoutesObserver routes_observer(&mock_router);
220 EXPECT_EQ(observer_captured, &routes_observer);
221 MockMediaRoutesObserver extra_routes_observer(&mock_router);
222 EXPECT_EQ(observer_captured, &extra_routes_observer);
223 observer_impl_->RegisterMediaRoutesObserver(&routes_observer);
224 observer_impl_->RegisterMediaRoutesObserver(&extra_routes_observer);
225
226 std::vector<MediaRoute> expected_routes;
227 expected_routes.push_back(MediaRoute(kRouteId, MediaSource(kSource),
228 MediaSink(kSink, kSink), kDescription,
229 false));
230 expected_routes.push_back(MediaRoute(kRouteId2, MediaSource(kSource),
231 MediaSink(kSink, kSink), kDescription,
232 false));
233
234 mojo::Array<interfaces::MediaRoutePtr> mojo_routes(2);
235 mojo_routes[0] = interfaces::MediaRoute::New();
236 mojo_routes[0]->media_route_id = kRouteId;
237 mojo_routes[0]->media_source = kSource;
238 mojo_routes[0]->media_sink = interfaces::MediaSink::New();
239 mojo_routes[0]->media_sink->sink_id = kSink;
240 mojo_routes[0]->media_sink->name = kSink;
241 mojo_routes[0]->description = kDescription;
242 mojo_routes[0]->is_local = false;
243 mojo_routes[1] = interfaces::MediaRoute::New();
244 mojo_routes[1]->media_route_id = kRouteId2;
245 mojo_routes[1]->media_source = kSource;
246 mojo_routes[1]->media_sink = interfaces::MediaSink::New();
247 mojo_routes[1]->media_sink->sink_id = kSink;
248 mojo_routes[1]->media_sink->name = kSink;
249 mojo_routes[1]->description = kDescription;
250 mojo_routes[1]->is_local = false;
251
252 EXPECT_CALL(routes_observer,
253 OnRoutesUpdated(SequenceEquals(expected_routes)));
254 EXPECT_CALL(extra_routes_observer,
255 OnRoutesUpdated(SequenceEquals(expected_routes)));
256 observer_proxy_->OnRoutesUpdated(mojo_routes.Pass());
257 ProcessEventLoop();
258
259 EXPECT_CALL(mock_router, UnregisterMediaRoutesObserver(&routes_observer));
260 EXPECT_CALL(mock_router,
261 UnregisterMediaRoutesObserver(&extra_routes_observer));
262 observer_impl_->UnregisterMediaRoutesObserver(&routes_observer);
263 observer_impl_->UnregisterMediaRoutesObserver(&extra_routes_observer);
264 EXPECT_CALL(mock_mrpm_host_, StopObservingMediaRoutes());
265 ProcessEventLoop();
266 }
267
268 TEST_F(MediaRouterMojoImplTest, PostMessage) {
269 EXPECT_CALL(mock_mrpm_host_,
270 PostMessage(mojo::String(kRouteId), mojo::String(kMessage)));
271 observer_impl_->PostMessage(kRouteId, kMessage);
272 ProcessEventLoop();
273 }
274
275 TEST_F(MediaRouterMojoImplTest, QueuedWhileAsleep) {
276 EXPECT_CALL(mock_event_page_tracker_, IsEventPageSuspended(extension_id_))
277 .Times(2)
278 .WillRepeatedly(Return(true));
279 EXPECT_CALL(mock_event_page_tracker_, WakeEventPage(extension_id_, _))
280 .Times(2)
281 .WillRepeatedly(Return(true));
282 observer_impl_->CloseRoute(kRouteId);
283 observer_impl_->CloseRoute(kRouteId2);
284 ProcessEventLoop();
285 EXPECT_CALL(mock_event_page_tracker_, IsEventPageSuspended(extension_id_))
286 .Times(1)
287 .WillRepeatedly(Return(false));
288 EXPECT_CALL(mock_mrpm_host_, CloseRoute(mojo::String(kRouteId)));
289 EXPECT_CALL(mock_mrpm_host_, CloseRoute(mojo::String(kRouteId2)));
290 ConnectProviderManagerService();
291 ProcessEventLoop();
292 }
293
294 // Temporarily disabled until the issues with extension system teardown
295 // are addressed.
296 // TODO(kmarshall): Re-enable this test.
297 TEST(MediaRouterMojoExtensionTest, DISABLED_DeferredBindingAndSuspension) {
298 base::MessageLoop message_loop_(mojo::common::MessagePumpMojo::Create());
299
300 // Set up a mock ProcessManager instance.
301 TestingProfile profile;
302 extensions::ProcessManagerFactory::GetInstance()->SetTestingFactory(
303 &profile, &TestProcessManager::Create);
304 TestProcessManager* process_manager = static_cast<TestProcessManager*>(
305 extensions::ProcessManager::Get(&profile));
306
307 // Create MR and its proxy, so that it can be accessed through Mojo.
308 MediaRouterMojoImpl media_router;
309 interfaces::MediaRouterObserverPtr media_router_proxy;
310
311 // Create a client object and its Mojo proxy.
312 testing::StrictMock<MockMojoMediaRouterService> mrpm;
313 interfaces::MediaRouterPtr mrpm_proxy;
314
315 // CloseRoute is called before *any* extension has connected.
316 // It should be queued.
317 media_router.CloseRoute(kRouteId);
318
319 // MRPM connects.
320 scoped_ptr<mojo::Binding<interfaces::MediaRouter>> mrpm_binding(
321 new mojo::Binding<interfaces::MediaRouter>(&mrpm,
322 mojo::GetProxy(&mrpm_proxy)));
323 media_router.Bind(mojo::GetProxy(&media_router_proxy));
324 media_router.MonitorExtension(kExtensionId, &profile);
325
326 // The MRPM signals its readiness to the MR by registering itself via
327 // ProvideMediaRouter().
328 // Now that the MR and MRPM are fully initialized, the queued
329 // CloseRoute() call should be executed.
330 ProvideMediaRouterHandler provide_handler;
331 EXPECT_CALL(provide_handler, Invoke(testing::Not("")));
332 EXPECT_CALL(*process_manager, IsEventPageSuspended(kExtensionId))
333 .WillOnce(Return(false));
334 EXPECT_CALL(mrpm, CloseRoute(mojo::String(kRouteId)));
335 media_router_proxy->ProvideMediaRouter(
336 mrpm_proxy.Pass(), base::Bind(&ProvideMediaRouterHandler::Invoke,
337 base::Unretained(&provide_handler)));
338 message_loop_.RunUntilIdle();
339
340 // MRPM's extension is suspended and re-awoken.
341 mrpm_binding.reset();
342 media_router.Bind(mojo::GetProxy(&media_router_proxy));
343 media_router.MonitorExtension(kExtensionId, &profile);
344 EXPECT_CALL(*process_manager, IsEventPageSuspended(kExtensionId))
345 .WillOnce(Return(true));
346 EXPECT_CALL(*process_manager, WakeEventPage(kExtensionId, _))
347 .WillOnce(testing::DoAll(media::RunCallback<1>(true), Return(true)));
348 media_router.CloseRoute(kRouteId2);
349 message_loop_.RunUntilIdle();
350
351 // ProvideMediaRouter() is called.
352 // The queued CloseRoute(kRouteId2) call should be executed.
353 EXPECT_CALL(provide_handler, Invoke(testing::Not("")));
354 EXPECT_CALL(*process_manager, IsEventPageSuspended(kExtensionId))
355 .WillOnce(Return(false));
356 EXPECT_CALL(mrpm, CloseRoute(mojo::String(kRouteId2)));
357 mrpm_binding.reset(new mojo::Binding<interfaces::MediaRouter>(
358 &mrpm, mojo::GetProxy(&mrpm_proxy)));
359 media_router_proxy->ProvideMediaRouter(
360 mrpm_proxy.Pass(), base::Bind(&ProvideMediaRouterHandler::Invoke,
361 base::Unretained(&provide_handler)));
362 message_loop_.RunUntilIdle();
363 }
364
365 } // namespace media_router
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698