Index: content/renderer/presentation/presentation_dispatcher_unittest.cc |
diff --git a/content/renderer/presentation/presentation_dispatcher_unittest.cc b/content/renderer/presentation/presentation_dispatcher_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e1381ee2684b2b2fb9d74a6df2669e3b846b2902 |
--- /dev/null |
+++ b/content/renderer/presentation/presentation_dispatcher_unittest.cc |
@@ -0,0 +1,315 @@ |
+// Copyright 2016 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 <memory> |
+#include <utility> |
+ |
+#include "base/run_loop.h" |
+#include "content/public/test/test_browser_thread_bundle.h" |
+#include "content/renderer/presentation/presentation_dispatcher.h" |
+#include "testing/gmock/include/gmock/gmock.h" |
+#include "third_party/WebKit/public/platform/modules/presentation/WebPresentationAvailabilityObserver.h" |
+#include "third_party/WebKit/public/web/WebArrayBuffer.h" |
+ |
+using ::testing::_; |
+using ::testing::Invoke; |
+using blink::WebArrayBuffer; |
+using blink::WebPresentationAvailabilityCallbacks; |
+using blink::WebPresentationAvailabilityObserver; |
+using blink::WebPresentationConnectionClientCallbacks; |
+using blink::WebString; |
+using blink::WebURL; |
+using blink::WebVector; |
+using blink::mojom::PresentationErrorPtr; |
+using blink::mojom::PresentationService; |
+using blink::mojom::PresentationServiceClientPtr; |
+using blink::mojom::PresentationSessionInfo; |
+using blink::mojom::PresentationSessionInfoPtr; |
+using blink::mojom::ConnectionMessage; |
+using blink::mojom::ConnectionMessagePtr; |
+ |
+namespace content { |
+ |
+class MockPresentationAvailabilityObserver |
+ : public WebPresentationAvailabilityObserver { |
+ public: |
+ explicit MockPresentationAvailabilityObserver(WebURL url) : url_(url) {} |
+ ~MockPresentationAvailabilityObserver() override {} |
+ |
+ MOCK_METHOD1(availabilityChanged, void(bool is_available)); |
+ const WebURL url() const override { return url_; } |
+ |
+ private: |
+ const WebURL url_; |
+}; |
+ |
+class MockPresentationService : public PresentationService { |
+ public: |
+ void SetClient(PresentationServiceClientPtr client) override {} |
+ MOCK_METHOD1(SetDefaultPresentationUrls, |
+ void(const std::vector<GURL>& presentation_urls)); |
+ MOCK_METHOD1(ListenForScreenAvailability, void(const GURL& availability_url)); |
+ MOCK_METHOD1(StopListeningForScreenAvailability, |
+ void(const GURL& availability_url)); |
+ MOCK_METHOD2(StartSession, |
+ void(const std::vector<GURL>& presentation_urls, |
+ const StartSessionCallback& callback)); |
+ MOCK_METHOD3(JoinSession, |
+ void(const std::vector<GURL>& presentation_urls, |
+ const base::Optional<std::string>& presentation_id, |
+ const JoinSessionCallback& callback)); |
+ |
+ // *Internal method is to work around lack of support for move-only types in |
+ // GMock. |
+ void SendConnectionMessage( |
+ PresentationSessionInfoPtr session_info, |
+ ConnectionMessagePtr message_request, |
+ const SendConnectionMessageCallback& callback) override { |
+ SendConnectionMessageInternal(session_info.get(), message_request.get(), |
+ callback); |
+ } |
+ MOCK_METHOD3(SendConnectionMessageInternal, |
+ void(PresentationSessionInfo* session_info, |
+ ConnectionMessage* message_request, |
+ const SendConnectionMessageCallback& callback)); |
+ |
+ MOCK_METHOD2(CloseConnection, |
+ void(const GURL& presentation_url, |
+ const std::string& presentation_id)); |
+ MOCK_METHOD2(Terminate, |
+ void(const GURL& presentation_url, |
+ const std::string& presentation_id)); |
+ |
+ // *Internal method is to work around lack of support for move-only types in |
+ // GMock. |
+ void ListenForConnectionMessages( |
+ PresentationSessionInfoPtr session_info) override { |
+ ListenForConnectionMessagesInternal(session_info.get()); |
+ } |
+ MOCK_METHOD1(ListenForConnectionMessagesInternal, |
+ void(PresentationSessionInfo* session_info)); |
+}; |
+ |
+class TestPresentationDispatcher : public PresentationDispatcher { |
+ public: |
+ explicit TestPresentationDispatcher( |
+ MockPresentationService* presentation_service) |
+ : PresentationDispatcher(nullptr), |
+ mock_presentation_service_(presentation_service) {} |
+ ~TestPresentationDispatcher() override {} |
+ |
+ private: |
+ void ConnectToPresentationServiceIfNeeded() override { |
+ if (!mock_binding_) { |
+ mock_binding_ = base::MakeUnique<mojo::Binding<PresentationService>>( |
+ mock_presentation_service_, |
+ mojo::MakeRequest(&presentation_service_)); |
+ } |
+ } |
+ |
+ MockPresentationService* mock_presentation_service_; |
+ std::unique_ptr<mojo::Binding<PresentationService>> mock_binding_; |
+}; |
+ |
+class PresentationDispatcherTest : public ::testing::Test { |
+ public: |
+ PresentationDispatcherTest() |
+ : gurl1_(GURL("https://www.example.com/1.html")), |
+ gurl2_(GURL("https://www.example.com/2.html")), |
+ gurls_({gurl1_, gurl2_}), |
+ url1_(WebURL(gurl1_)), |
+ url2_(WebURL(gurl2_)), |
+ urls_(WebVector<WebURL>(gurls_)), |
+ presentation_id_(WebString::fromUTF8("test-id")), |
+ array_buffer_(WebArrayBuffer::create(4, 1)), |
+ observer_(url1_) {} |
+ ~PresentationDispatcherTest() override {} |
+ |
+ void SetUp() override { |
+ presentation_service_ = base::MakeUnique<MockPresentationService>(); |
+ dispatcher_ = |
+ base::MakeUnique<TestPresentationDispatcher>(presentation_service()); |
+ |
+ // Set some test data. |
+ *(static_cast<uint8_t*>(array_buffer_.data())) = 42; |
+ } |
+ |
+ void TearDown() override { |
+ dispatcher_.reset(); |
+ presentation_service_.reset(); |
+ } |
+ |
+ PresentationDispatcher* dispatcher() { return dispatcher_.get(); } |
+ MockPresentationService* presentation_service() { |
+ return presentation_service_.get(); |
+ } |
+ |
+ protected: |
+ const GURL gurl1_; |
+ const GURL gurl2_; |
+ const std::vector<GURL> gurls_; |
+ const WebURL url1_; |
+ const WebURL url2_; |
+ const WebVector<WebURL> urls_; |
+ const WebString presentation_id_; |
+ const WebArrayBuffer array_buffer_; |
+ MockPresentationAvailabilityObserver observer_; |
+ |
+ private: |
+ content::TestBrowserThreadBundle thread_bundle_; |
+ std::unique_ptr<PresentationDispatcher> dispatcher_; |
+ std::unique_ptr<MockPresentationService> presentation_service_; |
+}; |
+ |
+TEST_F(PresentationDispatcherTest, TestStartSession) { |
+ base::RunLoop run_loop; |
+ EXPECT_CALL(*presentation_service(), StartSession(gurls_, _)) |
+ .WillOnce(Invoke([]( |
+ const std::vector<GURL>& presentation_urls, |
+ const PresentationService::StartSessionCallback& callback) { |
+ PresentationSessionInfoPtr session_info(PresentationSessionInfo::New()); |
+ callback.Run(std::move(session_info), PresentationErrorPtr()); |
+ })); |
+ dispatcher()->startSession( |
+ urls_, base::MakeUnique<WebPresentationConnectionClientCallbacks>()); |
mark a. foltz
2016/12/26 20:15:15
Can you add verification that the callback passed
takumif
2016/12/28 00:59:18
Done.
|
+ run_loop.RunUntilIdle(); |
+} |
+ |
mark a. foltz
2016/12/26 20:15:15
Can you add a test case for returning an error fro
takumif
2016/12/28 00:59:18
Done.
|
+TEST_F(PresentationDispatcherTest, TestJoinSession) { |
+ base::RunLoop run_loop; |
+ EXPECT_CALL(*presentation_service(), JoinSession(gurls_, _, _)) |
+ .WillOnce(Invoke([&]( |
+ const std::vector<GURL>& presentation_urls, |
+ const base::Optional<std::string>& presentation_id, |
+ const PresentationService::JoinSessionCallback& callback) { |
+ EXPECT_TRUE(presentation_id.has_value()); |
+ EXPECT_EQ(presentation_id_.utf8(), presentation_id.value()); |
+ PresentationSessionInfoPtr session_info(PresentationSessionInfo::New()); |
+ callback.Run(std::move(session_info), PresentationErrorPtr()); |
+ })); |
+ dispatcher()->joinSession( |
+ urls_, presentation_id_, |
+ base::MakeUnique<WebPresentationConnectionClientCallbacks>()); |
mark a. foltz
2016/12/26 20:15:15
Similar comment to above.
takumif
2016/12/28 00:59:18
Done.
|
+ run_loop.RunUntilIdle(); |
+} |
+ |
mark a. foltz
2016/12/26 20:15:15
Test error case.
takumif
2016/12/28 00:59:18
Done.
|
+TEST_F(PresentationDispatcherTest, TestSendString) { |
+ WebString message = WebString::fromUTF8("test message"); |
+ base::RunLoop run_loop; |
+ EXPECT_CALL(*presentation_service(), SendConnectionMessageInternal(_, _, _)) |
+ .WillOnce(Invoke([&]( |
+ PresentationSessionInfo* session_info, |
+ ConnectionMessage* message_request, |
+ const PresentationService::SendConnectionMessageCallback& callback) { |
+ EXPECT_EQ(gurl1_, session_info->url); |
+ EXPECT_EQ(presentation_id_.utf8(), session_info->id); |
+ EXPECT_TRUE(message_request->message.has_value()); |
+ EXPECT_EQ(message.utf8(), message_request->message.value()); |
+ callback.Run(true); |
+ })); |
+ dispatcher()->sendString(url1_, presentation_id_, message); |
+ run_loop.RunUntilIdle(); |
+} |
+ |
+TEST_F(PresentationDispatcherTest, TestSendArrayBuffer) { |
+ base::RunLoop run_loop; |
+ EXPECT_CALL(*presentation_service(), SendConnectionMessageInternal(_, _, _)) |
+ .WillOnce(Invoke([&]( |
+ PresentationSessionInfo* session_info, |
+ ConnectionMessage* message_request, |
+ const PresentationService::SendConnectionMessageCallback& callback) { |
+ EXPECT_EQ(gurl1_, session_info->url); |
+ EXPECT_EQ(presentation_id_.utf8(), session_info->id); |
+ std::vector<uint8_t> data( |
+ static_cast<const uint8_t*>(array_buffer_.data()), |
+ static_cast<const uint8_t*>(array_buffer_.data()) + |
+ array_buffer_.byteLength()); |
+ EXPECT_TRUE(message_request->data.has_value()); |
+ EXPECT_EQ(data, message_request->data.value()); |
+ callback.Run(true); |
+ })); |
+ dispatcher()->sendArrayBuffer( |
+ url1_, presentation_id_, |
+ static_cast<const uint8_t*>(array_buffer_.data()), |
+ array_buffer_.byteLength()); |
+ run_loop.RunUntilIdle(); |
+} |
+ |
+TEST_F(PresentationDispatcherTest, TestSendBlobData) { |
+ base::RunLoop run_loop; |
+ EXPECT_CALL(*presentation_service(), SendConnectionMessageInternal(_, _, _)) |
+ .WillOnce(Invoke([&]( |
+ PresentationSessionInfo* session_info, |
+ ConnectionMessage* message_request, |
+ const PresentationService::SendConnectionMessageCallback& callback) { |
+ EXPECT_EQ(gurl1_, session_info->url); |
+ EXPECT_EQ(presentation_id_.utf8(), session_info->id); |
+ std::vector<uint8_t> data( |
+ static_cast<const uint8_t*>(array_buffer_.data()), |
+ static_cast<const uint8_t*>(array_buffer_.data()) + |
+ array_buffer_.byteLength()); |
+ EXPECT_TRUE(message_request->data.has_value()); |
+ EXPECT_EQ(data, message_request->data.value()); |
+ callback.Run(true); |
+ })); |
+ dispatcher()->sendBlobData(url1_, presentation_id_, |
+ static_cast<const uint8_t*>(array_buffer_.data()), |
+ array_buffer_.byteLength()); |
+ run_loop.RunUntilIdle(); |
+} |
+ |
mark a. foltz
2016/12/26 20:15:15
It looks like we aren't handling the boolean retur
mark a. foltz
2016/12/26 20:17:12
Can you please add a TODO to handle (or remove) th
takumif
2016/12/28 00:59:18
Sorry, I don't understand why the boolean argument
mark a. foltz
2017/01/03 18:44:59
Ignore this comment, we can discuss offline; I thi
|
+TEST_F(PresentationDispatcherTest, TestCloseSession) { |
+ base::RunLoop run_loop; |
+ EXPECT_CALL(*presentation_service(), |
+ CloseConnection(gurl1_, presentation_id_.utf8())); |
+ dispatcher()->closeSession(url1_, presentation_id_); |
+ run_loop.RunUntilIdle(); |
+} |
+ |
+TEST_F(PresentationDispatcherTest, TestTerminateSession) { |
+ base::RunLoop run_loop; |
+ EXPECT_CALL(*presentation_service(), |
+ Terminate(gurl1_, presentation_id_.utf8())); |
+ dispatcher()->terminateSession(url1_, presentation_id_); |
+ run_loop.RunUntilIdle(); |
+} |
+ |
+TEST_F(PresentationDispatcherTest, TestListenForScreenAvailability) { |
+ base::RunLoop run_loop1; |
+ EXPECT_CALL(*presentation_service(), ListenForScreenAvailability(gurl1_)); |
+ dispatcher()->getAvailability( |
+ url1_, base::MakeUnique<WebPresentationAvailabilityCallbacks>()); |
+ dispatcher()->OnScreenAvailabilityUpdated(url1_, true); |
+ run_loop1.RunUntilIdle(); |
+ |
+ base::RunLoop run_loop2; |
+ EXPECT_CALL(*presentation_service(), ListenForScreenAvailability(gurl1_)); |
+ dispatcher()->startListening(&observer_); |
+ run_loop2.RunUntilIdle(); |
+ |
+ base::RunLoop run_loop3; |
+ EXPECT_CALL(observer_, availabilityChanged(false)); |
+ dispatcher()->OnScreenAvailabilityUpdated(url1_, false); |
+ EXPECT_CALL(observer_, availabilityChanged(true)); |
+ dispatcher()->OnScreenAvailabilityUpdated(url1_, true); |
+ EXPECT_CALL(*presentation_service(), |
+ StopListeningForScreenAvailability(gurl1_)); |
+ dispatcher()->stopListening(&observer_); |
+ run_loop3.RunUntilIdle(); |
+ |
+ // After stopListening(), |observer_| should no longer be notified. |
+ base::RunLoop run_loop4; |
+ EXPECT_CALL(observer_, availabilityChanged(false)).Times(0); |
+ dispatcher()->OnScreenAvailabilityUpdated(url1_, false); |
+ run_loop4.RunUntilIdle(); |
+} |
+ |
+TEST_F(PresentationDispatcherTest, TestSetDefaultPresentationUrls) { |
+ base::RunLoop run_loop; |
+ EXPECT_CALL(*presentation_service(), SetDefaultPresentationUrls(gurls_)); |
+ dispatcher()->setDefaultPresentationUrls(urls_); |
+ run_loop.RunUntilIdle(); |
+} |
+ |
+} // namespace content |