Index: chrome/browser/media/router/media_router_mojo_impl_unittest.cc |
diff --git a/chrome/browser/media/router/media_router_mojo_impl_unittest.cc b/chrome/browser/media/router/media_router_mojo_impl_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b9ea676d8f7cd851bcaeb150741cafded8505113 |
--- /dev/null |
+++ b/chrome/browser/media/router/media_router_mojo_impl_unittest.cc |
@@ -0,0 +1,257 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include <string> |
+ |
+#include "base/bind.h" |
+#include "base/bind_helpers.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/run_loop.h" |
+#include "base/synchronization/waitable_event.h" |
+#include "chrome/browser/media/router/media_route.h" |
+#include "chrome/browser/media/router/media_router_mojo_test.h" |
+#include "chrome/browser/media/router/mock_media_router.h" |
+#include "chrome/browser/media/router/test_helper.h" |
+#include "chrome/test/base/chrome_render_view_host_test_harness.h" |
+#include "chrome/test/base/testing_profile.h" |
+#include "testing/gmock/include/gmock/gmock.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+using testing::_; |
+using testing::Eq; |
+using testing::Invoke; |
+using testing::Pointee; |
+using testing::Return; |
+using testing::ReturnRef; |
+using testing::SaveArg; |
+ |
+const char kDescription[] = "description"; |
+const char kError[] = "error"; |
+const char kMessage[] = "message"; |
+const char kSource[] = "source1"; |
+const char kSource2[] = "source2"; |
+const char kRouteId[] = "routeId"; |
+const char kRouteId2[] = "routeId2"; |
+const char kSink[] = "sink"; |
+const char kSink2[] = "sink2"; |
+const char kSinkName[] = "sinkName"; |
+ |
+namespace media_router { |
+ |
+// Adapts a callback handler with move-only parameters to a method that only |
+// takes by-value parameters. |
+// Used because GMock does not support move-only parameters as expectations. |
+class RouteResponseCallbackHandler { |
+ public: |
+ void Invoke(scoped_ptr<MediaRoute> route, const std::string& error_text) { |
+ InvokeObserver(route.get(), error_text); |
+ } |
+ |
+ MOCK_METHOD2(InvokeObserver, |
+ void(MediaRoute* route, const std::string& error_text)); |
+}; |
+ |
+template <typename T> |
+void StoreAndRun(T* result, const base::Closure& closure, const T& result_val) { |
+ *result = result_val; |
+ closure.Run(); |
+} |
+ |
+class MediaRouterMojoImplTest : public MediaRouterMojoTest { |
+ public: |
+ MediaRouterMojoImplTest() {} |
+ ~MediaRouterMojoImplTest() override {} |
+}; |
+ |
+TEST_F(MediaRouterMojoImplTest, CreateRoute) { |
+ MediaRoute expected_route(kRouteId, MediaSource(std::string(kSource)), |
+ MediaSink(kSink, kSinkName), "", false); |
+ interfaces::MediaRoutePtr route = interfaces::MediaRoute::New(); |
+ route->media_source = kSource; |
+ route->media_sink = interfaces::MediaSink::New(); |
+ route->media_sink->sink_id = kSink; |
+ route->media_sink->name = kSinkName; |
+ route->media_route_id = kRouteId; |
+ route->description = kDescription; |
+ |
+ // Use a lambda function as an invocation target here to work around |
+ // a limitation with GMock::Invoke that prevents it from using move-only types |
+ // in runnable parameter lists. |
+ EXPECT_CALL(mock_mrpm_host_, |
+ CreateRoute(mojo::String(kSource), mojo::String(kSink), _)) |
+ .WillOnce(Invoke( |
+ [&route](const mojo::String& source, const mojo::String& sink, |
+ const interfaces::MediaRouter::CreateRouteCallback& cb) { |
+ cb.Run(route.Pass(), mojo::String()); |
+ })); |
+ |
+ RouteResponseCallbackHandler handler; |
+ EXPECT_CALL(handler, InvokeObserver(Pointee(Equals(expected_route)), "")); |
+ observer_impl_->CreateRoute(kSource, kSink, |
+ base::Bind(&RouteResponseCallbackHandler::Invoke, |
+ base::Unretained(&handler))); |
+ ProcessEventLoop(); |
+} |
+ |
+TEST_F(MediaRouterMojoImplTest, CreateRouteFails) { |
+ EXPECT_CALL(mock_mrpm_host_, |
+ CreateRoute(mojo::String(kSource), mojo::String(kSink), _)) |
+ .WillOnce( |
+ Invoke([](const mojo::String& source, const mojo::String& sink, |
+ const interfaces::MediaRouter::CreateRouteCallback& cb) { |
+ cb.Run(interfaces::MediaRoutePtr(), mojo::String(kError)); |
+ })); |
+ |
+ RouteResponseCallbackHandler handler; |
+ EXPECT_CALL(handler, InvokeObserver(nullptr, kError)); |
+ observer_impl_->CreateRoute(kSource, kSink, |
+ base::Bind(&RouteResponseCallbackHandler::Invoke, |
+ base::Unretained(&handler))); |
+ ProcessEventLoop(); |
+} |
+ |
+TEST_F(MediaRouterMojoImplTest, CloseRoute) { |
+ EXPECT_CALL(mock_mrpm_host_, CloseRoute(mojo::String(kRouteId))); |
+ observer_impl_->CloseRoute(kRouteId); |
+ ProcessEventLoop(); |
+} |
+ |
+TEST_F(MediaRouterMojoImplTest, RegisterAndUnregisterMediaSinksObserver) { |
+ MediaSource media_source(kSource); |
+ |
+ MockMediaRouter mock_router; |
+ EXPECT_CALL(mock_mrpm_host_, StartObservingMediaSinks(mojo::String(kSource))); |
+ EXPECT_CALL(mock_mrpm_host_, |
+ StartObservingMediaSinks(mojo::String(kSource2))); |
+ |
+ MediaSinksObserver* captured_observer; |
+ EXPECT_CALL(mock_router, RegisterMediaSinksObserver(_)) |
+ .Times(3) |
+ .WillRepeatedly(DoAll(SaveArg<0>(&captured_observer), Return(true))); |
+ |
+ MockMediaSinksObserver sinks_observer(&mock_router, media_source); |
+ EXPECT_EQ(&sinks_observer, captured_observer); |
+ observer_impl_->RegisterMediaSinksObserver(&sinks_observer); |
+ MockMediaSinksObserver extra_sinks_observer(&mock_router, media_source); |
+ EXPECT_EQ(&extra_sinks_observer, captured_observer); |
+ observer_impl_->RegisterMediaSinksObserver(&extra_sinks_observer); |
+ MockMediaSinksObserver unrelated_sinks_observer(&mock_router, |
+ MediaSource(kSource2)); |
+ EXPECT_EQ(&unrelated_sinks_observer, captured_observer); |
+ observer_impl_->RegisterMediaSinksObserver(&unrelated_sinks_observer); |
+ |
+ std::vector<MediaSink> expected_sinks; |
+ expected_sinks.push_back(MediaSink(kSink, kSinkName)); |
+ expected_sinks.push_back(MediaSink(kSink2, kSinkName)); |
+ |
+ mojo::Array<interfaces::MediaSinkPtr> mojo_sinks(2); |
+ mojo_sinks[0] = interfaces::MediaSink::New(); |
+ mojo_sinks[0]->sink_id = kSink; |
+ mojo_sinks[0]->name = kSink; |
+ mojo_sinks[1] = interfaces::MediaSink::New(); |
+ mojo_sinks[1]->sink_id = kSink2; |
+ mojo_sinks[1]->name = kSink2; |
+ |
+ EXPECT_CALL(sinks_observer, OnSinksReceived(SequenceEquals(expected_sinks))); |
+ EXPECT_CALL(extra_sinks_observer, |
+ OnSinksReceived(SequenceEquals(expected_sinks))); |
+ observer_proxy_->OnSinksReceived(media_source.id(), mojo_sinks.Pass()); |
+ ProcessEventLoop(); |
+ |
+ EXPECT_CALL(mock_router, UnregisterMediaSinksObserver(&sinks_observer)); |
+ EXPECT_CALL(mock_router, UnregisterMediaSinksObserver(&extra_sinks_observer)); |
+ EXPECT_CALL(mock_router, |
+ UnregisterMediaSinksObserver(&unrelated_sinks_observer)); |
+ EXPECT_CALL(mock_mrpm_host_, StopObservingMediaSinks(mojo::String(kSource))); |
+ EXPECT_CALL(mock_mrpm_host_, StopObservingMediaSinks(mojo::String(kSource2))); |
+ observer_impl_->UnregisterMediaSinksObserver(&sinks_observer); |
+ observer_impl_->UnregisterMediaSinksObserver(&extra_sinks_observer); |
+ observer_impl_->UnregisterMediaSinksObserver(&unrelated_sinks_observer); |
+ ProcessEventLoop(); |
+} |
+ |
+TEST_F(MediaRouterMojoImplTest, RegisterAndUnregisterMediaRoutesObserver) { |
+ MockMediaRouter mock_router; |
+ EXPECT_CALL(mock_mrpm_host_, StartObservingMediaRoutes()); |
+ |
+ MediaRoutesObserver* observer_captured; |
+ EXPECT_CALL(mock_router, RegisterMediaRoutesObserver(_)) |
+ .Times(2) |
+ .WillRepeatedly(DoAll(SaveArg<0>(&observer_captured), Return(true))); |
+ MockMediaRoutesObserver routes_observer(&mock_router); |
+ EXPECT_EQ(observer_captured, &routes_observer); |
+ MockMediaRoutesObserver extra_routes_observer(&mock_router); |
+ EXPECT_EQ(observer_captured, &extra_routes_observer); |
+ observer_impl_->RegisterMediaRoutesObserver(&routes_observer); |
+ observer_impl_->RegisterMediaRoutesObserver(&extra_routes_observer); |
+ |
+ std::vector<MediaRoute> expected_routes; |
+ expected_routes.push_back(MediaRoute(kRouteId, MediaSource(kSource), |
+ MediaSink(kSink, kSink), kDescription, |
+ false)); |
+ expected_routes.push_back(MediaRoute(kRouteId2, MediaSource(kSource), |
+ MediaSink(kSink, kSink), kDescription, |
+ false)); |
+ |
+ mojo::Array<interfaces::MediaRoutePtr> mojo_routes(2); |
+ mojo_routes[0] = interfaces::MediaRoute::New(); |
+ mojo_routes[0]->media_route_id = kRouteId; |
+ mojo_routes[0]->media_source = kSource; |
+ mojo_routes[0]->media_sink = interfaces::MediaSink::New(); |
+ mojo_routes[0]->media_sink->sink_id = kSink; |
+ mojo_routes[0]->media_sink->name = kSink; |
+ mojo_routes[0]->description = kDescription; |
+ mojo_routes[0]->is_local = false; |
+ mojo_routes[1] = interfaces::MediaRoute::New(); |
+ mojo_routes[1]->media_route_id = kRouteId2; |
+ mojo_routes[1]->media_source = kSource; |
+ mojo_routes[1]->media_sink = interfaces::MediaSink::New(); |
+ mojo_routes[1]->media_sink->sink_id = kSink; |
+ mojo_routes[1]->media_sink->name = kSink; |
+ mojo_routes[1]->description = kDescription; |
+ mojo_routes[1]->is_local = false; |
+ |
+ EXPECT_CALL(routes_observer, |
+ OnRoutesUpdated(SequenceEquals(expected_routes))); |
+ EXPECT_CALL(extra_routes_observer, |
+ OnRoutesUpdated(SequenceEquals(expected_routes))); |
+ observer_proxy_->OnRoutesUpdated(mojo_routes.Pass()); |
+ ProcessEventLoop(); |
+ |
+ EXPECT_CALL(mock_router, UnregisterMediaRoutesObserver(&routes_observer)); |
+ EXPECT_CALL(mock_router, |
+ UnregisterMediaRoutesObserver(&extra_routes_observer)); |
+ observer_impl_->UnregisterMediaRoutesObserver(&routes_observer); |
+ observer_impl_->UnregisterMediaRoutesObserver(&extra_routes_observer); |
+ EXPECT_CALL(mock_mrpm_host_, StopObservingMediaRoutes()); |
+ ProcessEventLoop(); |
+} |
+ |
+TEST_F(MediaRouterMojoImplTest, PostMessage) { |
+ EXPECT_CALL(mock_mrpm_host_, |
+ PostMessage(mojo::String(kRouteId), mojo::String(kMessage))); |
+ observer_impl_->PostMessage(kRouteId, kMessage); |
+ ProcessEventLoop(); |
+} |
+ |
+TEST_F(MediaRouterMojoImplTest, QueuedWhileAsleep) { |
+ EXPECT_CALL(mock_event_page_tracker_, IsEventPageSuspended(extension_id_)) |
+ .Times(2) |
+ .WillRepeatedly(Return(true)); |
+ EXPECT_CALL(mock_event_page_tracker_, WakeEventPage(extension_id_, _)) |
+ .Times(2) |
+ .WillRepeatedly(Return(true)); |
+ observer_impl_->CloseRoute(kRouteId); |
+ observer_impl_->CloseRoute(kRouteId2); |
+ ProcessEventLoop(); |
+ EXPECT_CALL(mock_event_page_tracker_, IsEventPageSuspended(extension_id_)) |
+ .Times(1) |
+ .WillRepeatedly(Return(false)); |
+ EXPECT_CALL(mock_mrpm_host_, CloseRoute(mojo::String(kRouteId))); |
+ EXPECT_CALL(mock_mrpm_host_, CloseRoute(mojo::String(kRouteId2))); |
+ ConnectProviderManagerService(); |
+ ProcessEventLoop(); |
+} |
+ |
+} // namespace media_router |