OLD | NEW |
(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 "testing/gmock/include/gmock/gmock.h" |
| 19 #include "testing/gtest/include/gtest/gtest.h" |
| 20 |
| 21 using testing::_; |
| 22 using testing::Eq; |
| 23 using testing::Invoke; |
| 24 using testing::Pointee; |
| 25 using testing::Return; |
| 26 using testing::ReturnRef; |
| 27 using testing::SaveArg; |
| 28 |
| 29 const char kDescription[] = "description"; |
| 30 const char kError[] = "error"; |
| 31 const char kMessage[] = "message"; |
| 32 const char kSource[] = "source1"; |
| 33 const char kSource2[] = "source2"; |
| 34 const char kRouteId[] = "routeId"; |
| 35 const char kRouteId2[] = "routeId2"; |
| 36 const char kSink[] = "sink"; |
| 37 const char kSink2[] = "sink2"; |
| 38 const char kSinkName[] = "sinkName"; |
| 39 |
| 40 namespace media_router { |
| 41 |
| 42 // Adapts a callback handler with move-only parameters to a method that only |
| 43 // takes by-value parameters. |
| 44 // Used because GMock does not support move-only parameters as expectations. |
| 45 class RouteResponseCallbackHandler { |
| 46 public: |
| 47 void Invoke(scoped_ptr<MediaRoute> route, const std::string& error_text) { |
| 48 InvokeObserver(route.get(), error_text); |
| 49 } |
| 50 |
| 51 MOCK_METHOD2(InvokeObserver, |
| 52 void(MediaRoute* route, const std::string& error_text)); |
| 53 }; |
| 54 |
| 55 template <typename T> |
| 56 void StoreAndRun(T* result, const base::Closure& closure, const T& result_val) { |
| 57 *result = result_val; |
| 58 closure.Run(); |
| 59 } |
| 60 |
| 61 class MediaRouterMojoImplTest : public MediaRouterMojoTest { |
| 62 public: |
| 63 MediaRouterMojoImplTest() {} |
| 64 ~MediaRouterMojoImplTest() override {} |
| 65 }; |
| 66 |
| 67 TEST_F(MediaRouterMojoImplTest, CreateRoute) { |
| 68 MediaRoute expected_route(kRouteId, MediaSource(std::string(kSource)), |
| 69 MediaSink(kSink, kSinkName), "", false); |
| 70 interfaces::MediaRoutePtr route = interfaces::MediaRoute::New(); |
| 71 route->media_source = kSource; |
| 72 route->media_sink = interfaces::MediaSink::New(); |
| 73 route->media_sink->sink_id = kSink; |
| 74 route->media_sink->name = kSinkName; |
| 75 route->media_route_id = kRouteId; |
| 76 route->description = kDescription; |
| 77 |
| 78 // Use a lambda function as an invocation target here to work around |
| 79 // a limitation with GMock::Invoke that prevents it from using move-only types |
| 80 // in runnable parameter lists. |
| 81 EXPECT_CALL(mock_mrpm_host_, |
| 82 CreateRoute(mojo::String(kSource), mojo::String(kSink), _)) |
| 83 .WillOnce(Invoke( |
| 84 [&route](const mojo::String& source, const mojo::String& sink, |
| 85 const interfaces::MediaRouter::CreateRouteCallback& cb) { |
| 86 cb.Run(route.Pass(), mojo::String()); |
| 87 })); |
| 88 |
| 89 RouteResponseCallbackHandler handler; |
| 90 EXPECT_CALL(handler, InvokeObserver(Pointee(Equals(expected_route)), "")); |
| 91 observer_impl_->CreateRoute(kSource, kSink, |
| 92 base::Bind(&RouteResponseCallbackHandler::Invoke, |
| 93 base::Unretained(&handler))); |
| 94 ProcessEventLoop(); |
| 95 } |
| 96 |
| 97 TEST_F(MediaRouterMojoImplTest, CreateRouteFails) { |
| 98 EXPECT_CALL(mock_mrpm_host_, |
| 99 CreateRoute(mojo::String(kSource), mojo::String(kSink), _)) |
| 100 .WillOnce( |
| 101 Invoke([](const mojo::String& source, const mojo::String& sink, |
| 102 const interfaces::MediaRouter::CreateRouteCallback& cb) { |
| 103 cb.Run(interfaces::MediaRoutePtr(), mojo::String(kError)); |
| 104 })); |
| 105 |
| 106 RouteResponseCallbackHandler handler; |
| 107 EXPECT_CALL(handler, InvokeObserver(nullptr, kError)); |
| 108 observer_impl_->CreateRoute(kSource, kSink, |
| 109 base::Bind(&RouteResponseCallbackHandler::Invoke, |
| 110 base::Unretained(&handler))); |
| 111 ProcessEventLoop(); |
| 112 } |
| 113 |
| 114 TEST_F(MediaRouterMojoImplTest, CloseRoute) { |
| 115 EXPECT_CALL(mock_mrpm_host_, CloseRoute(mojo::String(kRouteId))); |
| 116 observer_impl_->CloseRoute(kRouteId); |
| 117 ProcessEventLoop(); |
| 118 } |
| 119 |
| 120 TEST_F(MediaRouterMojoImplTest, RegisterAndUnregisterMediaSinksObserver) { |
| 121 MediaSource media_source(kSource); |
| 122 |
| 123 MockMediaRouter mock_router; |
| 124 EXPECT_CALL(mock_mrpm_host_, StartObservingMediaSinks(mojo::String(kSource))); |
| 125 EXPECT_CALL(mock_mrpm_host_, |
| 126 StartObservingMediaSinks(mojo::String(kSource2))); |
| 127 |
| 128 MediaSinksObserver* captured_observer; |
| 129 EXPECT_CALL(mock_router, RegisterMediaSinksObserver(_)) |
| 130 .Times(3) |
| 131 .WillRepeatedly(DoAll(SaveArg<0>(&captured_observer), Return(true))); |
| 132 |
| 133 MockMediaSinksObserver sinks_observer(&mock_router, media_source); |
| 134 EXPECT_EQ(&sinks_observer, captured_observer); |
| 135 observer_impl_->RegisterMediaSinksObserver(&sinks_observer); |
| 136 MockMediaSinksObserver extra_sinks_observer(&mock_router, media_source); |
| 137 EXPECT_EQ(&extra_sinks_observer, captured_observer); |
| 138 observer_impl_->RegisterMediaSinksObserver(&extra_sinks_observer); |
| 139 MockMediaSinksObserver unrelated_sinks_observer(&mock_router, |
| 140 MediaSource(kSource2)); |
| 141 EXPECT_EQ(&unrelated_sinks_observer, captured_observer); |
| 142 observer_impl_->RegisterMediaSinksObserver(&unrelated_sinks_observer); |
| 143 |
| 144 std::vector<MediaSink> expected_sinks; |
| 145 expected_sinks.push_back(MediaSink(kSink, kSinkName)); |
| 146 expected_sinks.push_back(MediaSink(kSink2, kSinkName)); |
| 147 |
| 148 mojo::Array<interfaces::MediaSinkPtr> mojo_sinks(2); |
| 149 mojo_sinks[0] = interfaces::MediaSink::New(); |
| 150 mojo_sinks[0]->sink_id = kSink; |
| 151 mojo_sinks[0]->name = kSink; |
| 152 mojo_sinks[1] = interfaces::MediaSink::New(); |
| 153 mojo_sinks[1]->sink_id = kSink2; |
| 154 mojo_sinks[1]->name = kSink2; |
| 155 |
| 156 EXPECT_CALL(sinks_observer, OnSinksReceived(SequenceEquals(expected_sinks))); |
| 157 EXPECT_CALL(extra_sinks_observer, |
| 158 OnSinksReceived(SequenceEquals(expected_sinks))); |
| 159 observer_proxy_->OnSinksReceived(media_source.id(), mojo_sinks.Pass()); |
| 160 ProcessEventLoop(); |
| 161 |
| 162 EXPECT_CALL(mock_router, UnregisterMediaSinksObserver(&sinks_observer)); |
| 163 EXPECT_CALL(mock_router, UnregisterMediaSinksObserver(&extra_sinks_observer)); |
| 164 EXPECT_CALL(mock_router, |
| 165 UnregisterMediaSinksObserver(&unrelated_sinks_observer)); |
| 166 EXPECT_CALL(mock_mrpm_host_, StopObservingMediaSinks(mojo::String(kSource))); |
| 167 EXPECT_CALL(mock_mrpm_host_, StopObservingMediaSinks(mojo::String(kSource2))); |
| 168 observer_impl_->UnregisterMediaSinksObserver(&sinks_observer); |
| 169 observer_impl_->UnregisterMediaSinksObserver(&extra_sinks_observer); |
| 170 observer_impl_->UnregisterMediaSinksObserver(&unrelated_sinks_observer); |
| 171 ProcessEventLoop(); |
| 172 } |
| 173 |
| 174 TEST_F(MediaRouterMojoImplTest, RegisterAndUnregisterMediaRoutesObserver) { |
| 175 MockMediaRouter mock_router; |
| 176 EXPECT_CALL(mock_mrpm_host_, StartObservingMediaRoutes()); |
| 177 |
| 178 MediaRoutesObserver* observer_captured; |
| 179 EXPECT_CALL(mock_router, RegisterMediaRoutesObserver(_)) |
| 180 .Times(2) |
| 181 .WillRepeatedly(DoAll(SaveArg<0>(&observer_captured), Return(true))); |
| 182 MockMediaRoutesObserver routes_observer(&mock_router); |
| 183 EXPECT_EQ(observer_captured, &routes_observer); |
| 184 MockMediaRoutesObserver extra_routes_observer(&mock_router); |
| 185 EXPECT_EQ(observer_captured, &extra_routes_observer); |
| 186 observer_impl_->RegisterMediaRoutesObserver(&routes_observer); |
| 187 observer_impl_->RegisterMediaRoutesObserver(&extra_routes_observer); |
| 188 |
| 189 std::vector<MediaRoute> expected_routes; |
| 190 expected_routes.push_back(MediaRoute(kRouteId, MediaSource(kSource), |
| 191 MediaSink(kSink, kSink), kDescription, |
| 192 false)); |
| 193 expected_routes.push_back(MediaRoute(kRouteId2, MediaSource(kSource), |
| 194 MediaSink(kSink, kSink), kDescription, |
| 195 false)); |
| 196 |
| 197 mojo::Array<interfaces::MediaRoutePtr> mojo_routes(2); |
| 198 mojo_routes[0] = interfaces::MediaRoute::New(); |
| 199 mojo_routes[0]->media_route_id = kRouteId; |
| 200 mojo_routes[0]->media_source = kSource; |
| 201 mojo_routes[0]->media_sink = interfaces::MediaSink::New(); |
| 202 mojo_routes[0]->media_sink->sink_id = kSink; |
| 203 mojo_routes[0]->media_sink->name = kSink; |
| 204 mojo_routes[0]->description = kDescription; |
| 205 mojo_routes[0]->is_local = false; |
| 206 mojo_routes[1] = interfaces::MediaRoute::New(); |
| 207 mojo_routes[1]->media_route_id = kRouteId2; |
| 208 mojo_routes[1]->media_source = kSource; |
| 209 mojo_routes[1]->media_sink = interfaces::MediaSink::New(); |
| 210 mojo_routes[1]->media_sink->sink_id = kSink; |
| 211 mojo_routes[1]->media_sink->name = kSink; |
| 212 mojo_routes[1]->description = kDescription; |
| 213 mojo_routes[1]->is_local = false; |
| 214 |
| 215 EXPECT_CALL(routes_observer, |
| 216 OnRoutesUpdated(SequenceEquals(expected_routes))); |
| 217 EXPECT_CALL(extra_routes_observer, |
| 218 OnRoutesUpdated(SequenceEquals(expected_routes))); |
| 219 observer_proxy_->OnRoutesUpdated(mojo_routes.Pass()); |
| 220 ProcessEventLoop(); |
| 221 |
| 222 EXPECT_CALL(mock_router, UnregisterMediaRoutesObserver(&routes_observer)); |
| 223 EXPECT_CALL(mock_router, |
| 224 UnregisterMediaRoutesObserver(&extra_routes_observer)); |
| 225 observer_impl_->UnregisterMediaRoutesObserver(&routes_observer); |
| 226 observer_impl_->UnregisterMediaRoutesObserver(&extra_routes_observer); |
| 227 EXPECT_CALL(mock_mrpm_host_, StopObservingMediaRoutes()); |
| 228 ProcessEventLoop(); |
| 229 } |
| 230 |
| 231 TEST_F(MediaRouterMojoImplTest, PostMessage) { |
| 232 EXPECT_CALL(mock_mrpm_host_, |
| 233 PostMessage(mojo::String(kRouteId), mojo::String(kMessage))); |
| 234 observer_impl_->PostMessage(kRouteId, kMessage); |
| 235 ProcessEventLoop(); |
| 236 } |
| 237 |
| 238 TEST_F(MediaRouterMojoImplTest, QueuedWhileAsleep) { |
| 239 EXPECT_CALL(mock_event_page_tracker_, IsEventPageSuspended(extension_id_)) |
| 240 .Times(2) |
| 241 .WillRepeatedly(Return(true)); |
| 242 EXPECT_CALL(mock_event_page_tracker_, WakeEventPage(extension_id_, _)) |
| 243 .Times(2) |
| 244 .WillRepeatedly(Return(true)); |
| 245 observer_impl_->CloseRoute(kRouteId); |
| 246 observer_impl_->CloseRoute(kRouteId2); |
| 247 ProcessEventLoop(); |
| 248 EXPECT_CALL(mock_event_page_tracker_, IsEventPageSuspended(extension_id_)) |
| 249 .Times(1) |
| 250 .WillRepeatedly(Return(false)); |
| 251 EXPECT_CALL(mock_mrpm_host_, CloseRoute(mojo::String(kRouteId))); |
| 252 EXPECT_CALL(mock_mrpm_host_, CloseRoute(mojo::String(kRouteId2))); |
| 253 ConnectProviderManagerService(); |
| 254 ProcessEventLoop(); |
| 255 } |
| 256 |
| 257 } // namespace media_router |
OLD | NEW |