OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 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 <memory> | |
6 #include <utility> | |
7 | |
8 #include "base/run_loop.h" | |
9 #include "content/public/test/test_browser_thread_bundle.h" | |
10 #include "content/renderer/presentation/presentation_dispatcher.h" | |
11 #include "testing/gmock/include/gmock/gmock.h" | |
12 #include "third_party/WebKit/public/platform/modules/presentation/WebPresentatio nAvailabilityObserver.h" | |
13 #include "third_party/WebKit/public/web/WebArrayBuffer.h" | |
14 | |
15 using ::testing::_; | |
16 using ::testing::Invoke; | |
17 using blink::WebArrayBuffer; | |
18 using blink::WebPresentationAvailabilityCallbacks; | |
19 using blink::WebPresentationAvailabilityObserver; | |
20 using blink::WebPresentationConnectionClientCallbacks; | |
21 using blink::WebString; | |
22 using blink::WebURL; | |
23 using blink::WebVector; | |
24 using blink::mojom::PresentationErrorPtr; | |
25 using blink::mojom::PresentationService; | |
26 using blink::mojom::PresentationServiceClientPtr; | |
27 using blink::mojom::PresentationSessionInfo; | |
28 using blink::mojom::PresentationSessionInfoPtr; | |
29 using blink::mojom::ConnectionMessage; | |
30 using blink::mojom::ConnectionMessagePtr; | |
31 | |
32 namespace content { | |
33 | |
34 class MockPresentationAvailabilityObserver | |
35 : public WebPresentationAvailabilityObserver { | |
36 public: | |
37 explicit MockPresentationAvailabilityObserver(WebURL url) : url_(url) {} | |
38 ~MockPresentationAvailabilityObserver() override {} | |
39 | |
40 MOCK_METHOD1(availabilityChanged, void(bool is_available)); | |
41 const WebURL url() const override { return url_; } | |
42 | |
43 private: | |
44 const WebURL url_; | |
45 }; | |
46 | |
47 class MockPresentationService : public PresentationService { | |
48 public: | |
49 void SetClient(PresentationServiceClientPtr client) override {} | |
50 MOCK_METHOD1(SetDefaultPresentationUrls, | |
51 void(const std::vector<GURL>& presentation_urls)); | |
52 MOCK_METHOD1(ListenForScreenAvailability, void(const GURL& availability_url)); | |
53 MOCK_METHOD1(StopListeningForScreenAvailability, | |
54 void(const GURL& availability_url)); | |
55 MOCK_METHOD2(StartSession, | |
56 void(const std::vector<GURL>& presentation_urls, | |
57 const StartSessionCallback& callback)); | |
58 MOCK_METHOD3(JoinSession, | |
59 void(const std::vector<GURL>& presentation_urls, | |
60 const base::Optional<std::string>& presentation_id, | |
61 const JoinSessionCallback& callback)); | |
62 | |
63 // *Internal method is to work around lack of support for move-only types in | |
64 // GMock. | |
65 void SendConnectionMessage( | |
66 PresentationSessionInfoPtr session_info, | |
67 ConnectionMessagePtr message_request, | |
68 const SendConnectionMessageCallback& callback) override { | |
69 SendConnectionMessageInternal(session_info.get(), message_request.get(), | |
70 callback); | |
71 } | |
72 MOCK_METHOD3(SendConnectionMessageInternal, | |
73 void(PresentationSessionInfo* session_info, | |
74 ConnectionMessage* message_request, | |
75 const SendConnectionMessageCallback& callback)); | |
76 | |
77 MOCK_METHOD2(CloseConnection, | |
78 void(const GURL& presentation_url, | |
79 const std::string& presentation_id)); | |
80 MOCK_METHOD2(Terminate, | |
81 void(const GURL& presentation_url, | |
82 const std::string& presentation_id)); | |
83 | |
84 // *Internal method is to work around lack of support for move-only types in | |
85 // GMock. | |
86 void ListenForConnectionMessages( | |
87 PresentationSessionInfoPtr session_info) override { | |
88 ListenForConnectionMessagesInternal(session_info.get()); | |
89 } | |
90 MOCK_METHOD1(ListenForConnectionMessagesInternal, | |
91 void(PresentationSessionInfo* session_info)); | |
92 }; | |
93 | |
94 class TestPresentationDispatcher : public PresentationDispatcher { | |
95 public: | |
96 explicit TestPresentationDispatcher( | |
97 MockPresentationService* presentation_service) | |
98 : PresentationDispatcher(nullptr), | |
99 mock_presentation_service_(presentation_service) {} | |
100 ~TestPresentationDispatcher() override {} | |
101 | |
102 private: | |
103 void ConnectToPresentationServiceIfNeeded() override { | |
104 if (!mock_binding_) { | |
105 mock_binding_ = base::MakeUnique<mojo::Binding<PresentationService>>( | |
106 mock_presentation_service_, | |
107 mojo::MakeRequest(&presentation_service_)); | |
108 } | |
109 } | |
110 | |
111 MockPresentationService* mock_presentation_service_; | |
112 std::unique_ptr<mojo::Binding<PresentationService>> mock_binding_; | |
113 }; | |
114 | |
115 class PresentationDispatcherTest : public ::testing::Test { | |
116 public: | |
117 PresentationDispatcherTest() | |
118 : gurl1_(GURL("https://www.example.com/1.html")), | |
119 gurl2_(GURL("https://www.example.com/2.html")), | |
120 gurls_({gurl1_, gurl2_}), | |
121 url1_(WebURL(gurl1_)), | |
122 url2_(WebURL(gurl2_)), | |
123 urls_(WebVector<WebURL>(gurls_)), | |
124 presentation_id_(WebString::fromUTF8("test-id")), | |
125 array_buffer_(WebArrayBuffer::create(4, 1)), | |
126 observer_(url1_) {} | |
127 ~PresentationDispatcherTest() override {} | |
128 | |
129 void SetUp() override { | |
130 presentation_service_ = base::MakeUnique<MockPresentationService>(); | |
131 dispatcher_ = | |
132 base::MakeUnique<TestPresentationDispatcher>(presentation_service()); | |
133 | |
134 // Set some test data. | |
135 *(static_cast<uint8_t*>(array_buffer_.data())) = 42; | |
136 } | |
137 | |
138 void TearDown() override { | |
139 dispatcher_.reset(); | |
140 presentation_service_.reset(); | |
141 } | |
142 | |
143 PresentationDispatcher* dispatcher() { return dispatcher_.get(); } | |
144 MockPresentationService* presentation_service() { | |
145 return presentation_service_.get(); | |
146 } | |
147 | |
148 protected: | |
149 const GURL gurl1_; | |
150 const GURL gurl2_; | |
151 const std::vector<GURL> gurls_; | |
152 const WebURL url1_; | |
153 const WebURL url2_; | |
154 const WebVector<WebURL> urls_; | |
155 const WebString presentation_id_; | |
156 const WebArrayBuffer array_buffer_; | |
157 MockPresentationAvailabilityObserver observer_; | |
158 | |
159 private: | |
160 content::TestBrowserThreadBundle thread_bundle_; | |
161 std::unique_ptr<PresentationDispatcher> dispatcher_; | |
162 std::unique_ptr<MockPresentationService> presentation_service_; | |
163 }; | |
164 | |
165 TEST_F(PresentationDispatcherTest, TestStartSession) { | |
166 base::RunLoop run_loop; | |
167 EXPECT_CALL(*presentation_service(), StartSession(gurls_, _)) | |
168 .WillOnce(Invoke([]( | |
169 const std::vector<GURL>& presentation_urls, | |
170 const PresentationService::StartSessionCallback& callback) { | |
171 PresentationSessionInfoPtr session_info(PresentationSessionInfo::New()); | |
172 callback.Run(std::move(session_info), PresentationErrorPtr()); | |
173 })); | |
174 dispatcher()->startSession( | |
175 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.
| |
176 run_loop.RunUntilIdle(); | |
177 } | |
178 | |
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.
| |
179 TEST_F(PresentationDispatcherTest, TestJoinSession) { | |
180 base::RunLoop run_loop; | |
181 EXPECT_CALL(*presentation_service(), JoinSession(gurls_, _, _)) | |
182 .WillOnce(Invoke([&]( | |
183 const std::vector<GURL>& presentation_urls, | |
184 const base::Optional<std::string>& presentation_id, | |
185 const PresentationService::JoinSessionCallback& callback) { | |
186 EXPECT_TRUE(presentation_id.has_value()); | |
187 EXPECT_EQ(presentation_id_.utf8(), presentation_id.value()); | |
188 PresentationSessionInfoPtr session_info(PresentationSessionInfo::New()); | |
189 callback.Run(std::move(session_info), PresentationErrorPtr()); | |
190 })); | |
191 dispatcher()->joinSession( | |
192 urls_, presentation_id_, | |
193 base::MakeUnique<WebPresentationConnectionClientCallbacks>()); | |
mark a. foltz
2016/12/26 20:15:15
Similar comment to above.
takumif
2016/12/28 00:59:18
Done.
| |
194 run_loop.RunUntilIdle(); | |
195 } | |
196 | |
mark a. foltz
2016/12/26 20:15:15
Test error case.
takumif
2016/12/28 00:59:18
Done.
| |
197 TEST_F(PresentationDispatcherTest, TestSendString) { | |
198 WebString message = WebString::fromUTF8("test message"); | |
199 base::RunLoop run_loop; | |
200 EXPECT_CALL(*presentation_service(), SendConnectionMessageInternal(_, _, _)) | |
201 .WillOnce(Invoke([&]( | |
202 PresentationSessionInfo* session_info, | |
203 ConnectionMessage* message_request, | |
204 const PresentationService::SendConnectionMessageCallback& callback) { | |
205 EXPECT_EQ(gurl1_, session_info->url); | |
206 EXPECT_EQ(presentation_id_.utf8(), session_info->id); | |
207 EXPECT_TRUE(message_request->message.has_value()); | |
208 EXPECT_EQ(message.utf8(), message_request->message.value()); | |
209 callback.Run(true); | |
210 })); | |
211 dispatcher()->sendString(url1_, presentation_id_, message); | |
212 run_loop.RunUntilIdle(); | |
213 } | |
214 | |
215 TEST_F(PresentationDispatcherTest, TestSendArrayBuffer) { | |
216 base::RunLoop run_loop; | |
217 EXPECT_CALL(*presentation_service(), SendConnectionMessageInternal(_, _, _)) | |
218 .WillOnce(Invoke([&]( | |
219 PresentationSessionInfo* session_info, | |
220 ConnectionMessage* message_request, | |
221 const PresentationService::SendConnectionMessageCallback& callback) { | |
222 EXPECT_EQ(gurl1_, session_info->url); | |
223 EXPECT_EQ(presentation_id_.utf8(), session_info->id); | |
224 std::vector<uint8_t> data( | |
225 static_cast<const uint8_t*>(array_buffer_.data()), | |
226 static_cast<const uint8_t*>(array_buffer_.data()) + | |
227 array_buffer_.byteLength()); | |
228 EXPECT_TRUE(message_request->data.has_value()); | |
229 EXPECT_EQ(data, message_request->data.value()); | |
230 callback.Run(true); | |
231 })); | |
232 dispatcher()->sendArrayBuffer( | |
233 url1_, presentation_id_, | |
234 static_cast<const uint8_t*>(array_buffer_.data()), | |
235 array_buffer_.byteLength()); | |
236 run_loop.RunUntilIdle(); | |
237 } | |
238 | |
239 TEST_F(PresentationDispatcherTest, TestSendBlobData) { | |
240 base::RunLoop run_loop; | |
241 EXPECT_CALL(*presentation_service(), SendConnectionMessageInternal(_, _, _)) | |
242 .WillOnce(Invoke([&]( | |
243 PresentationSessionInfo* session_info, | |
244 ConnectionMessage* message_request, | |
245 const PresentationService::SendConnectionMessageCallback& callback) { | |
246 EXPECT_EQ(gurl1_, session_info->url); | |
247 EXPECT_EQ(presentation_id_.utf8(), session_info->id); | |
248 std::vector<uint8_t> data( | |
249 static_cast<const uint8_t*>(array_buffer_.data()), | |
250 static_cast<const uint8_t*>(array_buffer_.data()) + | |
251 array_buffer_.byteLength()); | |
252 EXPECT_TRUE(message_request->data.has_value()); | |
253 EXPECT_EQ(data, message_request->data.value()); | |
254 callback.Run(true); | |
255 })); | |
256 dispatcher()->sendBlobData(url1_, presentation_id_, | |
257 static_cast<const uint8_t*>(array_buffer_.data()), | |
258 array_buffer_.byteLength()); | |
259 run_loop.RunUntilIdle(); | |
260 } | |
261 | |
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
| |
262 TEST_F(PresentationDispatcherTest, TestCloseSession) { | |
263 base::RunLoop run_loop; | |
264 EXPECT_CALL(*presentation_service(), | |
265 CloseConnection(gurl1_, presentation_id_.utf8())); | |
266 dispatcher()->closeSession(url1_, presentation_id_); | |
267 run_loop.RunUntilIdle(); | |
268 } | |
269 | |
270 TEST_F(PresentationDispatcherTest, TestTerminateSession) { | |
271 base::RunLoop run_loop; | |
272 EXPECT_CALL(*presentation_service(), | |
273 Terminate(gurl1_, presentation_id_.utf8())); | |
274 dispatcher()->terminateSession(url1_, presentation_id_); | |
275 run_loop.RunUntilIdle(); | |
276 } | |
277 | |
278 TEST_F(PresentationDispatcherTest, TestListenForScreenAvailability) { | |
279 base::RunLoop run_loop1; | |
280 EXPECT_CALL(*presentation_service(), ListenForScreenAvailability(gurl1_)); | |
281 dispatcher()->getAvailability( | |
282 url1_, base::MakeUnique<WebPresentationAvailabilityCallbacks>()); | |
283 dispatcher()->OnScreenAvailabilityUpdated(url1_, true); | |
284 run_loop1.RunUntilIdle(); | |
285 | |
286 base::RunLoop run_loop2; | |
287 EXPECT_CALL(*presentation_service(), ListenForScreenAvailability(gurl1_)); | |
288 dispatcher()->startListening(&observer_); | |
289 run_loop2.RunUntilIdle(); | |
290 | |
291 base::RunLoop run_loop3; | |
292 EXPECT_CALL(observer_, availabilityChanged(false)); | |
293 dispatcher()->OnScreenAvailabilityUpdated(url1_, false); | |
294 EXPECT_CALL(observer_, availabilityChanged(true)); | |
295 dispatcher()->OnScreenAvailabilityUpdated(url1_, true); | |
296 EXPECT_CALL(*presentation_service(), | |
297 StopListeningForScreenAvailability(gurl1_)); | |
298 dispatcher()->stopListening(&observer_); | |
299 run_loop3.RunUntilIdle(); | |
300 | |
301 // After stopListening(), |observer_| should no longer be notified. | |
302 base::RunLoop run_loop4; | |
303 EXPECT_CALL(observer_, availabilityChanged(false)).Times(0); | |
304 dispatcher()->OnScreenAvailabilityUpdated(url1_, false); | |
305 run_loop4.RunUntilIdle(); | |
306 } | |
307 | |
308 TEST_F(PresentationDispatcherTest, TestSetDefaultPresentationUrls) { | |
309 base::RunLoop run_loop; | |
310 EXPECT_CALL(*presentation_service(), SetDefaultPresentationUrls(gurls_)); | |
311 dispatcher()->setDefaultPresentationUrls(urls_); | |
312 run_loop.RunUntilIdle(); | |
313 } | |
314 | |
315 } // namespace content | |
OLD | NEW |