1 // Copyright (c) 2012 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.
5 #include "ppapi/tests/test_websocket.h"
15 #include "ppapi/c/dev/ppb_testing_dev.h"
16 #include "ppapi/c/pp_bool.h"
17 #include "ppapi/c/pp_completion_callback.h"
18 #include "ppapi/c/pp_errors.h"
19 #include "ppapi/c/pp_instance.h"
20 #include "ppapi/c/pp_resource.h"
21 #include "ppapi/c/pp_var.h"
22 #include "ppapi/c/ppb_core.h"
23 #include "ppapi/c/ppb_var.h"
24 #include "ppapi/c/ppb_var_array_buffer.h"
25 #include "ppapi/c/ppb_websocket.h"
26 #include "ppapi/cpp/instance.h"
27 #include "ppapi/cpp/module.h"
28 #include "ppapi/cpp/var_array_buffer.h"
29 #include "ppapi/cpp/websocket.h"
30 #include "ppapi/tests/test_utils.h"
31 #include "ppapi/tests/testing_instance.h"
32 #include "ppapi/utility/websocket/websocket_api.h"
34 // net::TestServer serves WebSocket service for testing.
35 // Following URLs are handled by pywebsocket handlers in
36 // net/data/websocket/*_wsh.py.
37 const char kEchoServerURL
[] = "echo-with-no-extension";
38 const char kCloseServerURL
[] = "close";
39 const char kCloseWithCodeAndReasonServerURL
[] = "close-code-and-reason";
40 const char kProtocolTestServerURL
[] = "protocol-test?protocol=";
42 const char* const kInvalidURLs
[] = {
43 "http://www.google.com/invalid_scheme",
44 "ws://www.google.com/invalid#fragment",
45 "ws://www.google.com:65535/invalid_port",
49 // Internal packet sizes.
50 const uint64_t kCloseFrameSize
= 6;
51 const uint64_t kMessageFrameOverhead
= 6;
55 struct WebSocketEvent
{
63 WebSocketEvent(EventType type
,
69 close_code(close_code
),
78 class ReleaseResourceDelegate
: public TestCompletionCallback::Delegate
{
80 explicit ReleaseResourceDelegate(const PPB_Core
* core_interface
,
82 : core_interface_(core_interface
),
86 // TestCompletionCallback::Delegate implementation.
87 virtual void OnCallback(void* user_data
, int32_t result
) {
89 core_interface_
->ReleaseResource(resource_
);
93 const PPB_Core
* core_interface_
;
94 PP_Resource resource_
;
97 class TestWebSocketAPI
: public pp::WebSocketAPI
{
99 explicit TestWebSocketAPI(pp::Instance
* instance
)
100 : pp::WebSocketAPI(instance
),
104 wait_for_connected_(false),
105 wait_for_received_(false),
106 wait_for_closed_(false),
107 instance_(instance
->pp_instance()) {
110 virtual void WebSocketDidOpen() {
112 WebSocketEvent(WebSocketEvent::EVENT_OPEN
, true, 0U, pp::Var()));
114 if (wait_for_connected_
) {
115 GetTestingInterface()->QuitMessageLoop(instance_
);
116 wait_for_connected_
= false;
120 virtual void WebSocketDidClose(
121 bool was_clean
, uint16_t code
, const pp::Var
& reason
) {
123 WebSocketEvent(WebSocketEvent::EVENT_CLOSE
, was_clean
, code
, reason
));
126 if (wait_for_connected_
|| wait_for_closed_
) {
127 GetTestingInterface()->QuitMessageLoop(instance_
);
128 wait_for_connected_
= false;
129 wait_for_closed_
= false;
133 virtual void HandleWebSocketMessage(const pp::Var
&message
) {
135 WebSocketEvent(WebSocketEvent::EVENT_MESSAGE
, true, 0U, message
));
137 if (wait_for_received_
) {
138 GetTestingInterface()->QuitMessageLoop(instance_
);
139 wait_for_received_
= false;
144 virtual void HandleWebSocketError() {
146 WebSocketEvent(WebSocketEvent::EVENT_ERROR
, true, 0U, pp::Var()));
149 void WaitForConnected() {
151 wait_for_connected_
= true;
152 GetTestingInterface()->RunMessageLoop(instance_
);
156 void WaitForReceived() {
158 wait_for_received_
= true;
159 GetTestingInterface()->RunMessageLoop(instance_
);
163 void WaitForClosed() {
165 wait_for_closed_
= true;
166 GetTestingInterface()->RunMessageLoop(instance_
);
170 const std::vector
<WebSocketEvent
>& GetSeenEvents() const {
175 std::vector
<WebSocketEvent
> events_
;
179 bool wait_for_connected_
;
180 bool wait_for_received_
;
181 bool wait_for_closed_
;
182 PP_Instance instance_
;
187 REGISTER_TEST_CASE(WebSocket
);
189 bool TestWebSocket::Init() {
190 websocket_interface_
= static_cast<const PPB_WebSocket
*>(
191 pp::Module::Get()->GetBrowserInterface(PPB_WEBSOCKET_INTERFACE
));
192 var_interface_
= static_cast<const PPB_Var
*>(
193 pp::Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE
));
194 arraybuffer_interface_
= static_cast<const PPB_VarArrayBuffer
*>(
195 pp::Module::Get()->GetBrowserInterface(
196 PPB_VAR_ARRAY_BUFFER_INTERFACE
));
197 core_interface_
= static_cast<const PPB_Core
*>(
198 pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE
));
199 if (!websocket_interface_
|| !var_interface_
|| !arraybuffer_interface_
||
203 return CheckTestingInterface();
206 void TestWebSocket::RunTests(const std::string
& filter
) {
207 RUN_TEST_WITH_REFERENCE_CHECK(IsWebSocket
, filter
);
208 RUN_TEST_WITH_REFERENCE_CHECK(UninitializedPropertiesAccess
, filter
);
209 RUN_TEST_WITH_REFERENCE_CHECK(InvalidConnect
, filter
);
210 RUN_TEST_WITH_REFERENCE_CHECK(Protocols
, filter
);
211 RUN_TEST_WITH_REFERENCE_CHECK(GetURL
, filter
);
212 RUN_TEST_WITH_REFERENCE_CHECK(ValidConnect
, filter
);
213 RUN_TEST_WITH_REFERENCE_CHECK(InvalidClose
, filter
);
214 RUN_TEST_WITH_REFERENCE_CHECK(ValidClose
, filter
);
215 RUN_TEST_WITH_REFERENCE_CHECK(GetProtocol
, filter
);
216 RUN_TEST_WITH_REFERENCE_CHECK(TextSendReceive
, filter
);
217 RUN_TEST_WITH_REFERENCE_CHECK(BinarySendReceive
, filter
);
218 RUN_TEST_WITH_REFERENCE_CHECK(StressedSendReceive
, filter
);
219 RUN_TEST_WITH_REFERENCE_CHECK(BufferedAmount
, filter
);
220 // PP_Resource for WebSocket may be released later because of an internal
221 // reference for asynchronous IPC handling. So, suppress reference check on
222 // the following AbortCallsWithCallback test.
223 RUN_TEST(AbortCallsWithCallback
, filter
);
224 RUN_TEST_WITH_REFERENCE_CHECK(AbortSendMessageCall
, filter
);
225 RUN_TEST_WITH_REFERENCE_CHECK(AbortCloseCall
, filter
);
226 RUN_TEST_WITH_REFERENCE_CHECK(AbortReceiveMessageCall
, filter
);
228 RUN_TEST_WITH_REFERENCE_CHECK(CcInterfaces
, filter
);
230 RUN_TEST_WITH_REFERENCE_CHECK(UtilityInvalidConnect
, filter
);
231 RUN_TEST_WITH_REFERENCE_CHECK(UtilityProtocols
, filter
);
232 RUN_TEST_WITH_REFERENCE_CHECK(UtilityGetURL
, filter
);
233 RUN_TEST_WITH_REFERENCE_CHECK(UtilityValidConnect
, filter
);
234 RUN_TEST_WITH_REFERENCE_CHECK(UtilityInvalidClose
, filter
);
235 RUN_TEST_WITH_REFERENCE_CHECK(UtilityValidClose
, filter
);
236 RUN_TEST_WITH_REFERENCE_CHECK(UtilityGetProtocol
, filter
);
237 RUN_TEST_WITH_REFERENCE_CHECK(UtilityTextSendReceive
, filter
);
238 RUN_TEST_WITH_REFERENCE_CHECK(UtilityBinarySendReceive
, filter
);
239 RUN_TEST_WITH_REFERENCE_CHECK(UtilityBufferedAmount
, filter
);
242 std::string
TestWebSocket::GetFullURL(const char* url
) {
243 std::string rv
= "ws://";
244 // Some WebSocket tests don't start the server so there'll be no host and
246 if (instance_
->websocket_host().empty())
249 rv
+= instance_
->websocket_host();
250 if (instance_
->websocket_port() != -1) {
252 sprintf(buffer
, ":%d", instance_
->websocket_port());
253 rv
+= std::string(buffer
);
260 PP_Var
TestWebSocket::CreateVarString(const std::string
& string
) {
261 return var_interface_
->VarFromUtf8(string
.c_str(), string
.size());
264 PP_Var
TestWebSocket::CreateVarBinary(const std::vector
<uint8_t>& binary
) {
265 PP_Var var
= arraybuffer_interface_
->Create(binary
.size());
266 uint8_t* var_data
= static_cast<uint8_t*>(arraybuffer_interface_
->Map(var
));
267 std::copy(binary
.begin(), binary
.end(), var_data
);
271 void TestWebSocket::ReleaseVar(const PP_Var
& var
) {
272 var_interface_
->Release(var
);
275 bool TestWebSocket::AreEqualWithString(const PP_Var
& var
,
276 const std::string
& string
) {
277 if (var
.type
!= PP_VARTYPE_STRING
)
279 uint32_t utf8_length
;
280 const char* utf8
= var_interface_
->VarToUtf8(var
, &utf8_length
);
281 if (utf8_length
!= string
.size())
283 if (string
.compare(utf8
))
288 bool TestWebSocket::AreEqualWithBinary(const PP_Var
& var
,
289 const std::vector
<uint8_t>& binary
) {
290 uint32_t buffer_size
= 0;
291 PP_Bool success
= arraybuffer_interface_
->ByteLength(var
, &buffer_size
);
292 if (!success
|| buffer_size
!= binary
.size())
294 if (!std::equal(binary
.begin(), binary
.end(),
295 static_cast<uint8_t*>(arraybuffer_interface_
->Map(var
))))
300 PP_Resource
TestWebSocket::Connect(const std::string
& url
,
302 const std::string
& protocol
) {
303 PP_Var protocols
[] = { PP_MakeUndefined() };
304 PP_Resource ws
= websocket_interface_
->Create(instance_
->pp_instance());
307 PP_Var url_var
= CreateVarString(url
);
308 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
309 uint32_t protocol_count
= 0U;
310 if (protocol
.size()) {
311 protocols
[0] = CreateVarString(protocol
);
314 callback
.WaitForResult(websocket_interface_
->Connect(
315 ws
, url_var
, protocols
, protocol_count
,
316 callback
.GetCallback().pp_completion_callback()));
319 ReleaseVar(protocols
[0]);
320 *result
= callback
.result();
324 std::string
TestWebSocket::TestIsWebSocket() {
325 // Test that a NULL resource isn't a websocket.
326 pp::Resource null_resource
;
328 websocket_interface_
->IsWebSocket(null_resource
.pp_resource());
329 ASSERT_FALSE(result
);
331 PP_Resource ws
= websocket_interface_
->Create(instance_
->pp_instance());
334 result
= websocket_interface_
->IsWebSocket(ws
);
337 core_interface_
->ReleaseResource(ws
);
342 std::string
TestWebSocket::TestUninitializedPropertiesAccess() {
343 PP_Resource ws
= websocket_interface_
->Create(instance_
->pp_instance());
346 uint64_t bufferedAmount
= websocket_interface_
->GetBufferedAmount(ws
);
347 ASSERT_EQ(0U, bufferedAmount
);
349 uint16_t close_code
= websocket_interface_
->GetCloseCode(ws
);
350 ASSERT_EQ(0U, close_code
);
352 PP_Var close_reason
= websocket_interface_
->GetCloseReason(ws
);
353 ASSERT_TRUE(AreEqualWithString(close_reason
, std::string()));
354 ReleaseVar(close_reason
);
356 PP_Bool close_was_clean
= websocket_interface_
->GetCloseWasClean(ws
);
357 ASSERT_EQ(PP_FALSE
, close_was_clean
);
359 PP_Var extensions
= websocket_interface_
->GetExtensions(ws
);
360 ASSERT_TRUE(AreEqualWithString(extensions
, std::string()));
361 ReleaseVar(extensions
);
363 PP_Var protocol
= websocket_interface_
->GetProtocol(ws
);
364 ASSERT_TRUE(AreEqualWithString(protocol
, std::string()));
365 ReleaseVar(protocol
);
367 PP_WebSocketReadyState ready_state
=
368 websocket_interface_
->GetReadyState(ws
);
369 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_INVALID
, ready_state
);
371 PP_Var url
= websocket_interface_
->GetURL(ws
);
372 ASSERT_TRUE(AreEqualWithString(url
, std::string()));
375 core_interface_
->ReleaseResource(ws
);
380 std::string
TestWebSocket::TestInvalidConnect() {
381 PP_Var protocols
[] = { PP_MakeUndefined() };
383 PP_Resource ws
= websocket_interface_
->Create(instance_
->pp_instance());
386 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
387 callback
.WaitForResult(websocket_interface_
->Connect(
388 ws
, PP_MakeUndefined(), protocols
, 1U,
389 callback
.GetCallback().pp_completion_callback()));
390 ASSERT_EQ(PP_ERROR_BADARGUMENT
, callback
.result());
392 callback
.WaitForResult(websocket_interface_
->Connect(
393 ws
, PP_MakeUndefined(), protocols
, 1U,
394 callback
.GetCallback().pp_completion_callback()));
395 ASSERT_EQ(PP_ERROR_INPROGRESS
, callback
.result());
397 core_interface_
->ReleaseResource(ws
);
399 for (int i
= 0; kInvalidURLs
[i
]; ++i
) {
401 ws
= Connect(kInvalidURLs
[i
], &result
, std::string());
403 ASSERT_EQ(PP_ERROR_BADARGUMENT
, result
);
405 core_interface_
->ReleaseResource(ws
);
411 std::string
TestWebSocket::TestProtocols() {
412 PP_Var url
= CreateVarString(GetFullURL(kEchoServerURL
).c_str());
413 PP_Var bad_protocols
[] = {
414 CreateVarString("x-test"),
415 CreateVarString("x-test")
417 PP_Var good_protocols
[] = {
418 CreateVarString("x-test"),
419 CreateVarString("x-yatest")
422 PP_Resource ws
= websocket_interface_
->Create(instance_
->pp_instance());
424 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
425 callback
.WaitForResult(websocket_interface_
->Connect(
426 ws
, url
, bad_protocols
, 2U,
427 callback
.GetCallback().pp_completion_callback()));
428 ASSERT_EQ(PP_ERROR_BADARGUMENT
, callback
.result());
429 core_interface_
->ReleaseResource(ws
);
431 ws
= websocket_interface_
->Create(instance_
->pp_instance());
433 int32_t result
= websocket_interface_
->Connect(
434 ws
, url
, good_protocols
, 2U, PP_BlockUntilComplete());
435 ASSERT_EQ(PP_ERROR_BLOCKS_MAIN_THREAD
, result
);
436 core_interface_
->ReleaseResource(ws
);
439 for (int i
= 0; i
< 2; ++i
) {
440 ReleaseVar(bad_protocols
[i
]);
441 ReleaseVar(good_protocols
[i
]);
443 core_interface_
->ReleaseResource(ws
);
448 std::string
TestWebSocket::TestGetURL() {
449 for (int i
= 0; kInvalidURLs
[i
]; ++i
) {
451 PP_Resource ws
= Connect(kInvalidURLs
[i
], &result
, std::string());
453 PP_Var url
= websocket_interface_
->GetURL(ws
);
454 ASSERT_TRUE(AreEqualWithString(url
, kInvalidURLs
[i
]));
455 ASSERT_EQ(PP_ERROR_BADARGUMENT
, result
);
458 core_interface_
->ReleaseResource(ws
);
464 std::string
TestWebSocket::TestValidConnect() {
466 PP_Resource ws
= Connect(GetFullURL(kEchoServerURL
), &result
, std::string());
468 ASSERT_EQ(PP_OK
, result
);
469 PP_Var extensions
= websocket_interface_
->GetExtensions(ws
);
470 ASSERT_TRUE(AreEqualWithString(extensions
, std::string()));
471 core_interface_
->ReleaseResource(ws
);
472 ReleaseVar(extensions
);
477 std::string
TestWebSocket::TestInvalidClose() {
478 PP_Var reason
= CreateVarString("close for test");
479 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
480 TestCompletionCallback
async_callback(instance_
->pp_instance(), PP_REQUIRED
);
482 // Close before connect.
483 PP_Resource ws
= websocket_interface_
->Create(instance_
->pp_instance());
484 callback
.WaitForResult(websocket_interface_
->Close(
485 ws
, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, reason
,
486 callback
.GetCallback().pp_completion_callback()));
487 ASSERT_EQ(PP_ERROR_FAILED
, callback
.result());
488 core_interface_
->ReleaseResource(ws
);
490 // Close with bad arguments.
492 ws
= Connect(GetFullURL(kEchoServerURL
), &result
, std::string());
494 ASSERT_EQ(PP_OK
, result
);
495 callback
.WaitForResult(websocket_interface_
->Close(
496 ws
, 1U, reason
, callback
.GetCallback().pp_completion_callback()));
497 ASSERT_EQ(PP_ERROR_NOACCESS
, callback
.result());
498 core_interface_
->ReleaseResource(ws
);
500 // Close with PP_VARTYPE_NULL.
501 ws
= Connect(GetFullURL(kEchoServerURL
), &result
, std::string());
503 ASSERT_EQ(PP_OK
, result
);
504 callback
.WaitForResult(websocket_interface_
->Close(
505 ws
, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, PP_MakeNull(),
506 callback
.GetCallback().pp_completion_callback()));
507 ASSERT_EQ(PP_ERROR_BADARGUMENT
, callback
.result());
508 core_interface_
->ReleaseResource(ws
);
510 // Close with PP_VARTYPE_NULL and ongoing receive message.
511 ws
= Connect(GetFullURL(kEchoServerURL
), &result
, std::string());
513 ASSERT_EQ(PP_OK
, result
);
514 PP_Var receive_message_var
;
515 result
= websocket_interface_
->ReceiveMessage(
516 ws
, &receive_message_var
,
517 async_callback
.GetCallback().pp_completion_callback());
518 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
519 callback
.WaitForResult(websocket_interface_
->Close(
520 ws
, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, PP_MakeNull(),
521 callback
.GetCallback().pp_completion_callback()));
522 ASSERT_EQ(PP_ERROR_BADARGUMENT
, callback
.result());
523 const char* send_message
= "hi";
524 PP_Var send_message_var
= CreateVarString(send_message
);
525 result
= websocket_interface_
->SendMessage(ws
, send_message_var
);
526 ReleaseVar(send_message_var
);
527 ASSERT_EQ(PP_OK
, result
);
528 async_callback
.WaitForResult(PP_OK_COMPLETIONPENDING
);
529 ASSERT_EQ(PP_OK
, async_callback
.result());
530 ASSERT_TRUE(AreEqualWithString(receive_message_var
, send_message
));
531 ReleaseVar(receive_message_var
);
532 core_interface_
->ReleaseResource(ws
);
535 ws
= Connect(GetFullURL(kEchoServerURL
), &result
, std::string());
537 ASSERT_EQ(PP_OK
, result
);
538 result
= websocket_interface_
->Close(
539 ws
, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, reason
,
540 async_callback
.GetCallback().pp_completion_callback());
541 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
542 // Call another Close() before previous one is in progress.
543 result
= websocket_interface_
->Close(
544 ws
, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, reason
,
545 callback
.GetCallback().pp_completion_callback());
546 ASSERT_EQ(PP_ERROR_INPROGRESS
, result
);
547 async_callback
.WaitForResult(PP_OK_COMPLETIONPENDING
);
548 ASSERT_EQ(PP_OK
, async_callback
.result());
549 // Call another Close() after previous one is completed.
550 // This Close() must do nothing and reports no error.
551 callback
.WaitForResult(websocket_interface_
->Close(
552 ws
, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, reason
,
553 callback
.GetCallback().pp_completion_callback()));
554 ASSERT_EQ(PP_OK
, callback
.result());
555 core_interface_
->ReleaseResource(ws
);
562 std::string
TestWebSocket::TestValidClose() {
563 PP_Var reason
= CreateVarString("close for test");
564 PP_Var url
= CreateVarString(GetFullURL(kEchoServerURL
).c_str());
565 PP_Var protocols
[] = { PP_MakeUndefined() };
566 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
567 TestCompletionCallback
another_callback(
568 instance_
->pp_instance(), callback_type());
572 PP_Resource ws
= Connect(GetFullURL(kEchoServerURL
), &result
, std::string());
574 ASSERT_EQ(PP_OK
, result
);
575 callback
.WaitForResult(websocket_interface_
->Close(
576 ws
, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, reason
,
577 callback
.GetCallback().pp_completion_callback()));
578 CHECK_CALLBACK_BEHAVIOR(callback
);
579 ASSERT_EQ(PP_OK
, callback
.result());
580 core_interface_
->ReleaseResource(ws
);
582 // Close without code and reason.
583 ws
= Connect(GetFullURL(kEchoServerURL
), &result
, std::string());
585 ASSERT_EQ(PP_OK
, result
);
586 callback
.WaitForResult(websocket_interface_
->Close(
587 ws
, PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED
, reason
,
588 callback
.GetCallback().pp_completion_callback()));
589 ASSERT_EQ(PP_OK
, callback
.result());
590 core_interface_
->ReleaseResource(ws
);
592 // Close with PP_VARTYPE_UNDEFINED.
593 ws
= Connect(GetFullURL(kEchoServerURL
), &result
, std::string());
595 ASSERT_EQ(PP_OK
, result
);
596 callback
.WaitForResult(websocket_interface_
->Close(
597 ws
, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, PP_MakeUndefined(),
598 callback
.GetCallback().pp_completion_callback()));
599 CHECK_CALLBACK_BEHAVIOR(callback
);
600 ASSERT_EQ(PP_OK
, callback
.result());
601 core_interface_
->ReleaseResource(ws
);
603 // Close in connecting.
604 // The ongoing connect failed with PP_ERROR_ABORTED, then the close is done
606 ws
= websocket_interface_
->Create(instance_
->pp_instance());
607 result
= websocket_interface_
->Connect(
608 ws
, url
, protocols
, 0U, callback
.GetCallback().pp_completion_callback());
609 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
610 result
= websocket_interface_
->Close(
611 ws
, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, reason
,
612 another_callback
.GetCallback().pp_completion_callback());
613 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
614 callback
.WaitForResult(PP_OK_COMPLETIONPENDING
);
615 ASSERT_EQ(PP_ERROR_ABORTED
, callback
.result());
616 another_callback
.WaitForResult(PP_OK_COMPLETIONPENDING
);
617 ASSERT_EQ(PP_OK
, another_callback
.result());
618 core_interface_
->ReleaseResource(ws
);
621 // The first close will be done successfully, then the second one failed with
622 // with PP_ERROR_INPROGRESS immediately.
623 ws
= Connect(GetFullURL(kEchoServerURL
), &result
, std::string());
625 ASSERT_EQ(PP_OK
, result
);
626 result
= websocket_interface_
->Close(
627 ws
, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, reason
,
628 callback
.GetCallback().pp_completion_callback());
629 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
630 result
= websocket_interface_
->Close(
631 ws
, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, reason
,
632 another_callback
.GetCallback().pp_completion_callback());
633 ASSERT_EQ(PP_ERROR_INPROGRESS
, result
);
634 callback
.WaitForResult(PP_OK_COMPLETIONPENDING
);
635 ASSERT_EQ(PP_OK
, callback
.result());
636 core_interface_
->ReleaseResource(ws
);
638 // Close with ongoing receive message.
639 ws
= Connect(GetFullURL(kEchoServerURL
), &result
, std::string());
641 ASSERT_EQ(PP_OK
, result
);
642 PP_Var receive_message_var
;
643 result
= websocket_interface_
->ReceiveMessage(
644 ws
, &receive_message_var
,
645 callback
.GetCallback().pp_completion_callback());
646 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
647 result
= websocket_interface_
->Close(
648 ws
, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, reason
,
649 another_callback
.GetCallback().pp_completion_callback());
650 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
651 callback
.WaitForResult(PP_OK_COMPLETIONPENDING
);
652 ASSERT_EQ(PP_ERROR_ABORTED
, callback
.result());
653 another_callback
.WaitForResult(PP_OK_COMPLETIONPENDING
);
654 ASSERT_EQ(PP_OK
, another_callback
.result());
655 core_interface_
->ReleaseResource(ws
);
657 // Close with PP_VARTYPE_UNDEFINED and ongoing receive message.
658 ws
= Connect(GetFullURL(kEchoServerURL
), &result
, std::string());
660 ASSERT_EQ(PP_OK
, result
);
661 result
= websocket_interface_
->ReceiveMessage(
662 ws
, &receive_message_var
,
663 callback
.GetCallback().pp_completion_callback());
664 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
665 result
= websocket_interface_
->Close(
666 ws
, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, PP_MakeUndefined(),
667 another_callback
.GetCallback().pp_completion_callback());
668 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
669 callback
.WaitForResult(PP_OK_COMPLETIONPENDING
);
670 ASSERT_EQ(PP_ERROR_ABORTED
, callback
.result());
671 another_callback
.WaitForResult(PP_OK_COMPLETIONPENDING
);
672 ASSERT_EQ(PP_OK
, another_callback
.result());
673 core_interface_
->ReleaseResource(ws
);
675 // Server initiated closing handshake.
677 GetFullURL(kCloseWithCodeAndReasonServerURL
), &result
, std::string());
679 ASSERT_EQ(PP_OK
, result
);
680 // Text messsage "1000 bye" requests the server to initiate closing handshake
681 // with code being 1000 and reason being "bye".
682 PP_Var close_request_var
= CreateVarString("1000 bye");
683 result
= websocket_interface_
->SendMessage(ws
, close_request_var
);
684 ReleaseVar(close_request_var
);
685 callback
.WaitForResult(websocket_interface_
->ReceiveMessage(
686 ws
, &receive_message_var
,
687 callback
.GetCallback().pp_completion_callback()));
688 ASSERT_EQ(PP_ERROR_FAILED
, callback
.result());
689 core_interface_
->ReleaseResource(ws
);
697 std::string
TestWebSocket::TestGetProtocol() {
698 const char* expected_protocols
[] = {
703 for (int i
= 0; expected_protocols
[i
]; ++i
) {
704 std::string
url(GetFullURL(kProtocolTestServerURL
));
705 url
+= expected_protocols
[i
];
707 PP_Resource ws
= Connect(url
.c_str(), &result
, expected_protocols
[i
]);
709 ASSERT_EQ(PP_OK
, result
);
711 PP_Var protocol
= websocket_interface_
->GetProtocol(ws
);
712 ASSERT_TRUE(AreEqualWithString(protocol
, expected_protocols
[i
]));
714 ReleaseVar(protocol
);
715 core_interface_
->ReleaseResource(ws
);
721 std::string
TestWebSocket::TestTextSendReceive() {
722 // Connect to test echo server.
723 int32_t connect_result
;
725 Connect(GetFullURL(kEchoServerURL
), &connect_result
, std::string());
727 ASSERT_EQ(PP_OK
, connect_result
);
729 // Send 'hello pepper' text message.
730 const char* message
= "hello pepper";
731 PP_Var message_var
= CreateVarString(message
);
732 int32_t result
= websocket_interface_
->SendMessage(ws
, message_var
);
733 ReleaseVar(message_var
);
734 ASSERT_EQ(PP_OK
, result
);
736 // Receive echoed 'hello pepper'.
737 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
738 PP_Var received_message
;
739 callback
.WaitForResult(websocket_interface_
->ReceiveMessage(
740 ws
, &received_message
, callback
.GetCallback().pp_completion_callback()));
741 ASSERT_EQ(PP_OK
, callback
.result());
742 ASSERT_TRUE(AreEqualWithString(received_message
, message
));
743 ReleaseVar(received_message
);
744 core_interface_
->ReleaseResource(ws
);
749 std::string
TestWebSocket::TestBinarySendReceive() {
750 // Connect to test echo server.
751 int32_t connect_result
;
753 Connect(GetFullURL(kEchoServerURL
), &connect_result
, std::string());
755 ASSERT_EQ(PP_OK
, connect_result
);
757 // Send binary message.
758 std::vector
<uint8_t> binary(256);
759 for (uint32_t i
= 0; i
< binary
.size(); ++i
)
761 PP_Var message_var
= CreateVarBinary(binary
);
762 int32_t result
= websocket_interface_
->SendMessage(ws
, message_var
);
763 ReleaseVar(message_var
);
764 ASSERT_EQ(PP_OK
, result
);
766 // Receive echoed binary.
767 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
768 PP_Var received_message
;
769 callback
.WaitForResult(websocket_interface_
->ReceiveMessage(
770 ws
, &received_message
, callback
.GetCallback().pp_completion_callback()));
771 ASSERT_EQ(PP_OK
, callback
.result());
772 ASSERT_TRUE(AreEqualWithBinary(received_message
, binary
));
773 ReleaseVar(received_message
);
774 core_interface_
->ReleaseResource(ws
);
779 std::string
TestWebSocket::TestStressedSendReceive() {
780 // Connect to test echo server.
781 int32_t connect_result
;
783 Connect(GetFullURL(kEchoServerURL
), &connect_result
, std::string());
785 ASSERT_EQ(PP_OK
, connect_result
);
787 // Prepare PP_Var objects to send.
788 const char* text
= "hello pepper";
789 PP_Var text_var
= CreateVarString(text
);
790 std::vector
<uint8_t> binary(256);
791 for (uint32_t i
= 0; i
< binary
.size(); ++i
)
793 PP_Var binary_var
= CreateVarBinary(binary
);
794 // Prepare very large binary data over 64KiB. Object serializer in
795 // ppapi_proxy has a limitation of 64KiB as maximum return PP_Var data size
796 // to SRPC. In case received data over 64KiB exists, a specific code handles
797 // this large data via asynchronous callback from main thread. This data
798 // intends to test the code.
799 std::vector
<uint8_t> large_binary(65 * 1024);
800 for (uint32_t i
= 0; i
< large_binary
.size(); ++i
)
801 large_binary
[i
] = i
& 0xff;
802 PP_Var large_binary_var
= CreateVarBinary(large_binary
);
804 // Send many messages.
806 for (int i
= 0; i
< 256; ++i
) {
807 result
= websocket_interface_
->SendMessage(ws
, text_var
);
808 ASSERT_EQ(PP_OK
, result
);
809 result
= websocket_interface_
->SendMessage(ws
, binary_var
);
810 ASSERT_EQ(PP_OK
, result
);
812 result
= websocket_interface_
->SendMessage(ws
, large_binary_var
);
813 ASSERT_EQ(PP_OK
, result
);
814 ReleaseVar(text_var
);
815 ReleaseVar(binary_var
);
816 ReleaseVar(large_binary_var
);
818 // Receive echoed data.
819 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
820 for (int i
= 0; i
<= 512; ++i
) {
821 PP_Var received_message
;
822 callback
.WaitForResult(websocket_interface_
->ReceiveMessage(
823 ws
, &received_message
,
824 callback
.GetCallback().pp_completion_callback()));
825 ASSERT_EQ(PP_OK
, callback
.result());
827 ASSERT_TRUE(AreEqualWithBinary(received_message
, large_binary
));
829 ASSERT_TRUE(AreEqualWithBinary(received_message
, binary
));
831 ASSERT_TRUE(AreEqualWithString(received_message
, text
));
833 ReleaseVar(received_message
);
835 core_interface_
->ReleaseResource(ws
);
840 std::string
TestWebSocket::TestBufferedAmount() {
841 // Connect to test echo server.
842 int32_t connect_result
;
844 Connect(GetFullURL(kEchoServerURL
), &connect_result
, std::string());
846 ASSERT_EQ(PP_OK
, connect_result
);
848 // Prepare a large message that is not aligned with the internal buffer
850 std::string
message(8193, 'x');
851 PP_Var message_var
= CreateVarString(message
);
853 uint64_t buffered_amount
= 0;
855 for (int i
= 0; i
< 100; i
++) {
856 result
= websocket_interface_
->SendMessage(ws
, message_var
);
857 ASSERT_EQ(PP_OK
, result
);
858 buffered_amount
= websocket_interface_
->GetBufferedAmount(ws
);
859 // Buffered amount size 262144 is too big for the internal buffer size.
860 if (buffered_amount
> 262144)
865 std::string reason_str
= "close while busy";
866 PP_Var reason
= CreateVarString(reason_str
.c_str());
867 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
868 result
= websocket_interface_
->Close(
869 ws
, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, reason
,
870 callback
.GetCallback().pp_completion_callback());
871 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
872 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSING
,
873 websocket_interface_
->GetReadyState(ws
));
875 callback
.WaitForResult(result
);
876 ASSERT_EQ(PP_OK
, callback
.result());
877 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED
,
878 websocket_interface_
->GetReadyState(ws
));
880 uint64_t base_buffered_amount
= websocket_interface_
->GetBufferedAmount(ws
);
882 // After connection closure, all sending requests fail and just increase
883 // the bufferedAmount property.
884 PP_Var empty_string
= CreateVarString(std::string());
885 result
= websocket_interface_
->SendMessage(ws
, empty_string
);
886 ASSERT_EQ(PP_ERROR_FAILED
, result
);
887 buffered_amount
= websocket_interface_
->GetBufferedAmount(ws
);
888 ASSERT_EQ(base_buffered_amount
+ kMessageFrameOverhead
, buffered_amount
);
889 base_buffered_amount
= buffered_amount
;
891 result
= websocket_interface_
->SendMessage(ws
, reason
);
892 ASSERT_EQ(PP_ERROR_FAILED
, result
);
893 buffered_amount
= websocket_interface_
->GetBufferedAmount(ws
);
894 uint64_t reason_frame_size
= kMessageFrameOverhead
+ reason_str
.length();
895 ASSERT_EQ(base_buffered_amount
+ reason_frame_size
, buffered_amount
);
897 ReleaseVar(message_var
);
899 ReleaseVar(empty_string
);
900 core_interface_
->ReleaseResource(ws
);
905 // Test abort behaviors where a WebSocket PP_Resource is released while each
906 // function is in-flight on the WebSocket PP_Resource.
907 std::string
TestWebSocket::TestAbortCallsWithCallback() {
908 // Following tests make sure the behavior for functions which require a
909 // callback. The callback must get a PP_ERROR_ABORTED.
911 // Test the behavior for Connect().
912 PP_Resource ws
= websocket_interface_
->Create(instance_
->pp_instance());
914 std::string url
= GetFullURL(kEchoServerURL
);
915 PP_Var url_var
= CreateVarString(url
);
916 TestCompletionCallback
connect_callback(
917 instance_
->pp_instance(), callback_type());
918 int32_t result
= websocket_interface_
->Connect(
919 ws
, url_var
, NULL
, 0,
920 connect_callback
.GetCallback().pp_completion_callback());
921 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
922 core_interface_
->ReleaseResource(ws
);
923 connect_callback
.WaitForResult(result
);
924 ASSERT_EQ(PP_ERROR_ABORTED
, connect_callback
.result());
926 // Test the behavior for Close().
927 ws
= Connect(url
, &result
, std::string());
929 ASSERT_EQ(PP_OK
, result
);
930 PP_Var reason_var
= CreateVarString("abort");
931 TestCompletionCallback
close_callback(
932 instance_
->pp_instance(), callback_type());
933 result
= websocket_interface_
->Close(
934 ws
, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, reason_var
,
935 close_callback
.GetCallback().pp_completion_callback());
936 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
937 core_interface_
->ReleaseResource(ws
);
938 close_callback
.WaitForResult(result
);
939 ASSERT_EQ(PP_ERROR_ABORTED
, close_callback
.result());
940 ReleaseVar(reason_var
);
942 // Test the behavior for ReceiveMessage().
943 // Make sure the simplest case to wait for data which never arrives, here.
944 ws
= Connect(url
, &result
, std::string());
946 ASSERT_EQ(PP_OK
, result
);
948 TestCompletionCallback
receive_callback(
949 instance_
->pp_instance(), callback_type());
950 result
= websocket_interface_
->ReceiveMessage(
952 receive_callback
.GetCallback().pp_completion_callback());
953 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
954 core_interface_
->ReleaseResource(ws
);
955 receive_callback
.WaitForResult(result
);
956 ASSERT_EQ(PP_ERROR_ABORTED
, receive_callback
.result());
958 // Release the resource in the aborting receive completion callback which is
959 // introduced by calling Close().
960 ws
= Connect(url
, &result
, std::string());
962 ASSERT_EQ(PP_OK
, result
);
963 result
= websocket_interface_
->ReceiveMessage(
965 receive_callback
.GetCallback().pp_completion_callback());
966 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
967 ReleaseResourceDelegate
receive_delegate(core_interface_
, ws
);
968 receive_callback
.SetDelegate(&receive_delegate
);
969 result
= websocket_interface_
->Close(
970 ws
, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, PP_MakeUndefined(),
971 close_callback
.GetCallback().pp_completion_callback());
972 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
973 receive_callback
.WaitForResult(result
);
974 CHECK_CALLBACK_BEHAVIOR(receive_callback
);
975 ASSERT_EQ(PP_ERROR_ABORTED
, receive_callback
.result());
976 close_callback
.WaitForResult(result
);
977 CHECK_CALLBACK_BEHAVIOR(close_callback
);
978 ASSERT_EQ(PP_ERROR_ABORTED
, close_callback
.result());
985 std::string
TestWebSocket::TestAbortSendMessageCall() {
986 // Test the behavior for SendMessage().
987 // This function doesn't require a callback, but operation will be done
988 // asynchronously in WebKit and browser process.
989 std::vector
<uint8_t> large_binary(65 * 1024);
990 PP_Var large_var
= CreateVarBinary(large_binary
);
993 std::string url
= GetFullURL(kEchoServerURL
);
994 PP_Resource ws
= Connect(url
, &result
, std::string());
996 ASSERT_EQ(PP_OK
, result
);
997 result
= websocket_interface_
->SendMessage(ws
, large_var
);
998 ASSERT_EQ(PP_OK
, result
);
999 core_interface_
->ReleaseResource(ws
);
1000 ReleaseVar(large_var
);
1005 std::string
TestWebSocket::TestAbortCloseCall() {
1006 // Release the resource in the close completion callback.
1008 std::string url
= GetFullURL(kEchoServerURL
);
1009 PP_Resource ws
= Connect(url
, &result
, std::string());
1011 ASSERT_EQ(PP_OK
, result
);
1012 TestCompletionCallback
close_callback(
1013 instance_
->pp_instance(), callback_type());
1014 result
= websocket_interface_
->Close(
1015 ws
, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, PP_MakeUndefined(),
1016 close_callback
.GetCallback().pp_completion_callback());
1017 ReleaseResourceDelegate
close_delegate(core_interface_
, ws
);
1018 close_callback
.SetDelegate(&close_delegate
);
1019 close_callback
.WaitForResult(result
);
1020 CHECK_CALLBACK_BEHAVIOR(close_callback
);
1021 ASSERT_EQ(PP_OK
, close_callback
.result());
1026 std::string
TestWebSocket::TestAbortReceiveMessageCall() {
1027 // Test the behavior where receive process might be in-flight.
1028 std::vector
<uint8_t> large_binary(65 * 1024);
1029 PP_Var large_var
= CreateVarBinary(large_binary
);
1030 const char* text
= "yukarin";
1031 PP_Var text_var
= CreateVarString(text
);
1033 std::string url
= GetFullURL(kEchoServerURL
);
1037 // Each trial sends |trial_count| + 1 messages and receives just |trial|
1038 // number of message(s) before releasing the WebSocket. The WebSocket is
1039 // released while the next message is going to be received.
1040 const int trial_count
= 8;
1041 for (int trial
= 1; trial
<= trial_count
; trial
++) {
1042 ws
= Connect(url
, &result
, std::string());
1044 ASSERT_EQ(PP_OK
, result
);
1045 for (int i
= 0; i
<= trial_count
; ++i
) {
1046 result
= websocket_interface_
->SendMessage(ws
, text_var
);
1047 ASSERT_EQ(PP_OK
, result
);
1049 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
1051 for (int i
= 0; i
< trial
; ++i
) {
1052 callback
.WaitForResult(websocket_interface_
->ReceiveMessage(
1053 ws
, &var
, callback
.GetCallback().pp_completion_callback()));
1054 ASSERT_EQ(PP_OK
, callback
.result());
1055 ASSERT_TRUE(AreEqualWithString(var
, text
));
1058 result
= websocket_interface_
->ReceiveMessage(
1059 ws
, &var
, callback
.GetCallback().pp_completion_callback());
1060 core_interface_
->ReleaseResource(ws
);
1061 if (result
!= PP_OK
) {
1062 callback
.WaitForResult(result
);
1063 ASSERT_EQ(PP_ERROR_ABORTED
, callback
.result());
1066 // Same test, but the last receiving message is large message over 64KiB.
1067 for (int trial
= 1; trial
<= trial_count
; trial
++) {
1068 ws
= Connect(url
, &result
, std::string());
1070 ASSERT_EQ(PP_OK
, result
);
1071 for (int i
= 0; i
<= trial_count
; ++i
) {
1073 result
= websocket_interface_
->SendMessage(ws
, large_var
);
1075 result
= websocket_interface_
->SendMessage(ws
, text_var
);
1076 ASSERT_EQ(PP_OK
, result
);
1078 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
1080 for (int i
= 0; i
< trial
; ++i
) {
1081 callback
.WaitForResult(websocket_interface_
->ReceiveMessage(
1082 ws
, &var
, callback
.GetCallback().pp_completion_callback()));
1083 ASSERT_EQ(PP_OK
, callback
.result());
1084 ASSERT_TRUE(AreEqualWithString(var
, text
));
1087 result
= websocket_interface_
->ReceiveMessage(
1088 ws
, &var
, callback
.GetCallback().pp_completion_callback());
1089 core_interface_
->ReleaseResource(ws
);
1090 if (result
!= PP_OK
) {
1091 callback
.WaitForResult(result
);
1092 ASSERT_EQ(PP_ERROR_ABORTED
, callback
.result());
1096 ReleaseVar(large_var
);
1097 ReleaseVar(text_var
);
1102 std::string
TestWebSocket::TestCcInterfaces() {
1103 // C++ bindings is simple straightforward, then just verifies interfaces work
1104 // as a interface bridge fine.
1105 pp::WebSocket
ws(instance_
);
1107 // Check uninitialized properties access.
1108 ASSERT_EQ(0, ws
.GetBufferedAmount());
1109 ASSERT_EQ(0, ws
.GetCloseCode());
1110 ASSERT_TRUE(AreEqualWithString(ws
.GetCloseReason().pp_var(), std::string()));
1111 ASSERT_EQ(false, ws
.GetCloseWasClean());
1112 ASSERT_TRUE(AreEqualWithString(ws
.GetExtensions().pp_var(), std::string()));
1113 ASSERT_TRUE(AreEqualWithString(ws
.GetProtocol().pp_var(), std::string()));
1114 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_INVALID
, ws
.GetReadyState());
1115 ASSERT_TRUE(AreEqualWithString(ws
.GetURL().pp_var(), std::string()));
1117 // Check communication interfaces (connect, send, receive, and close).
1118 TestCompletionCallback
connect_callback(
1119 instance_
->pp_instance(), callback_type());
1120 connect_callback
.WaitForResult(ws
.Connect(
1121 pp::Var(GetFullURL(kCloseServerURL
)), NULL
, 0U,
1122 connect_callback
.GetCallback()));
1123 CHECK_CALLBACK_BEHAVIOR(connect_callback
);
1124 ASSERT_EQ(PP_OK
, connect_callback
.result());
1126 std::string
text_message("hello C++");
1127 int32_t result
= ws
.SendMessage(pp::Var(text_message
));
1128 ASSERT_EQ(PP_OK
, result
);
1130 std::vector
<uint8_t> binary(256);
1131 for (uint32_t i
= 0; i
< binary
.size(); ++i
)
1133 result
= ws
.SendMessage(
1134 pp::Var(pp::PASS_REF
, CreateVarBinary(binary
)));
1135 ASSERT_EQ(PP_OK
, result
);
1137 pp::Var text_receive_var
;
1138 TestCompletionCallback
text_receive_callback(
1139 instance_
->pp_instance(), callback_type());
1140 text_receive_callback
.WaitForResult(
1141 ws
.ReceiveMessage(&text_receive_var
,
1142 text_receive_callback
.GetCallback()));
1143 ASSERT_EQ(PP_OK
, text_receive_callback
.result());
1145 AreEqualWithString(text_receive_var
.pp_var(), text_message
.c_str()));
1147 pp::Var binary_receive_var
;
1148 TestCompletionCallback
binary_receive_callback(
1149 instance_
->pp_instance(), callback_type());
1150 binary_receive_callback
.WaitForResult(
1151 ws
.ReceiveMessage(&binary_receive_var
,
1152 binary_receive_callback
.GetCallback()));
1153 ASSERT_EQ(PP_OK
, binary_receive_callback
.result());
1154 ASSERT_TRUE(AreEqualWithBinary(binary_receive_var
.pp_var(), binary
));
1156 TestCompletionCallback
close_callback(
1157 instance_
->pp_instance(), callback_type());
1158 std::string
reason("bye");
1159 close_callback
.WaitForResult(ws
.Close(
1160 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, pp::Var(reason
),
1161 close_callback
.GetCallback()));
1162 CHECK_CALLBACK_BEHAVIOR(close_callback
);
1163 ASSERT_EQ(PP_OK
, close_callback
.result());
1165 // Check initialized properties access.
1166 ASSERT_EQ(0, ws
.GetBufferedAmount());
1167 ASSERT_EQ(PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, ws
.GetCloseCode());
1169 AreEqualWithString(ws
.GetCloseReason().pp_var(), reason
.c_str()));
1170 ASSERT_EQ(true, ws
.GetCloseWasClean());
1171 ASSERT_TRUE(AreEqualWithString(ws
.GetProtocol().pp_var(), std::string()));
1172 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED
, ws
.GetReadyState());
1173 ASSERT_TRUE(AreEqualWithString(
1174 ws
.GetURL().pp_var(), GetFullURL(kCloseServerURL
).c_str()));
1179 std::string
TestWebSocket::TestUtilityInvalidConnect() {
1180 const pp::Var protocols
[] = { pp::Var() };
1182 TestWebSocketAPI
websocket(instance_
);
1183 int32_t result
= websocket
.Connect(pp::Var(), protocols
, 1U);
1184 ASSERT_EQ(PP_ERROR_BADARGUMENT
, result
);
1185 ASSERT_EQ(0U, websocket
.GetSeenEvents().size());
1187 result
= websocket
.Connect(pp::Var(), protocols
, 1U);
1188 ASSERT_EQ(PP_ERROR_INPROGRESS
, result
);
1189 ASSERT_EQ(0U, websocket
.GetSeenEvents().size());
1191 for (int i
= 0; kInvalidURLs
[i
]; ++i
) {
1192 TestWebSocketAPI
ws(instance_
);
1193 result
= ws
.Connect(pp::Var(std::string(kInvalidURLs
[i
])), protocols
, 0U);
1194 if (result
== PP_OK_COMPLETIONPENDING
) {
1196 const std::vector
<WebSocketEvent
>& events
= ws
.GetSeenEvents();
1197 ASSERT_EQ(WebSocketEvent::EVENT_ERROR
, events
[0].event_type
);
1198 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE
, events
[1].event_type
);
1199 ASSERT_EQ(2U, ws
.GetSeenEvents().size());
1201 ASSERT_EQ(PP_ERROR_BADARGUMENT
, result
);
1202 ASSERT_EQ(0U, ws
.GetSeenEvents().size());
1209 std::string
TestWebSocket::TestUtilityProtocols() {
1210 const pp::Var bad_protocols
[] = {
1211 pp::Var(std::string("x-test")), pp::Var(std::string("x-test")) };
1212 const pp::Var good_protocols
[] = {
1213 pp::Var(std::string("x-test")), pp::Var(std::string("x-yatest")) };
1216 TestWebSocketAPI
websocket(instance_
);
1217 int32_t result
= websocket
.Connect(
1218 pp::Var(GetFullURL(kEchoServerURL
)), bad_protocols
, 2U);
1219 ASSERT_EQ(PP_ERROR_BADARGUMENT
, result
);
1220 ASSERT_EQ(0U, websocket
.GetSeenEvents().size());
1224 TestWebSocketAPI
websocket(instance_
);
1225 int32_t result
= websocket
.Connect(
1226 pp::Var(GetFullURL(kEchoServerURL
)), good_protocols
, 2U);
1227 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
1228 websocket
.WaitForConnected();
1229 const std::vector
<WebSocketEvent
>& events
= websocket
.GetSeenEvents();
1230 // Protocol arguments are valid, but this test run without a WebSocket
1231 // server. As a result, OnError() and OnClose() are invoked because of
1232 // a connection establishment failure.
1233 ASSERT_EQ(2U, events
.size());
1234 ASSERT_EQ(WebSocketEvent::EVENT_ERROR
, events
[0].event_type
);
1235 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE
, events
[1].event_type
);
1236 ASSERT_FALSE(events
[1].was_clean
);
1242 std::string
TestWebSocket::TestUtilityGetURL() {
1243 const pp::Var protocols
[] = { pp::Var() };
1245 for (int i
= 0; kInvalidURLs
[i
]; ++i
) {
1246 TestWebSocketAPI
websocket(instance_
);
1247 int32_t result
= websocket
.Connect(
1248 pp::Var(std::string(kInvalidURLs
[i
])), protocols
, 0U);
1249 if (result
== PP_OK_COMPLETIONPENDING
) {
1250 websocket
.WaitForClosed();
1251 const std::vector
<WebSocketEvent
>& events
= websocket
.GetSeenEvents();
1252 ASSERT_EQ(WebSocketEvent::EVENT_ERROR
, events
[0].event_type
);
1253 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE
, events
[1].event_type
);
1254 ASSERT_EQ(2U, events
.size());
1256 ASSERT_EQ(PP_ERROR_BADARGUMENT
, result
);
1257 ASSERT_EQ(0U, websocket
.GetSeenEvents().size());
1259 pp::Var url
= websocket
.GetURL();
1260 ASSERT_TRUE(AreEqualWithString(url
.pp_var(), kInvalidURLs
[i
]));
1266 std::string
TestWebSocket::TestUtilityValidConnect() {
1267 const pp::Var protocols
[] = { pp::Var() };
1268 TestWebSocketAPI
websocket(instance_
);
1269 int32_t result
= websocket
.Connect(
1270 pp::Var(GetFullURL(kEchoServerURL
)), protocols
, 0U);
1271 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
1272 websocket
.WaitForConnected();
1273 const std::vector
<WebSocketEvent
>& events
= websocket
.GetSeenEvents();
1274 ASSERT_EQ(1U, events
.size());
1275 ASSERT_EQ(WebSocketEvent::EVENT_OPEN
, events
[0].event_type
);
1277 AreEqualWithString(websocket
.GetExtensions().pp_var(), std::string()));
1282 std::string
TestWebSocket::TestUtilityInvalidClose() {
1283 const pp::Var reason
= pp::Var(std::string("close for test"));
1285 // Close before connect.
1287 TestWebSocketAPI
websocket(instance_
);
1288 int32_t result
= websocket
.Close(
1289 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, reason
);
1290 ASSERT_EQ(PP_ERROR_FAILED
, result
);
1291 ASSERT_EQ(0U, websocket
.GetSeenEvents().size());
1294 // Close with bad arguments.
1296 TestWebSocketAPI
websocket(instance_
);
1297 int32_t result
= websocket
.Connect(pp::Var(GetFullURL(kEchoServerURL
)),
1299 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
1300 websocket
.WaitForConnected();
1301 result
= websocket
.Close(1U, reason
);
1302 ASSERT_EQ(PP_ERROR_NOACCESS
, result
);
1303 const std::vector
<WebSocketEvent
>& events
= websocket
.GetSeenEvents();
1304 ASSERT_EQ(1U, events
.size());
1305 ASSERT_EQ(WebSocketEvent::EVENT_OPEN
, events
[0].event_type
);
1311 std::string
TestWebSocket::TestUtilityValidClose() {
1312 std::string
reason("close for test");
1313 pp::Var url
= pp::Var(GetFullURL(kCloseServerURL
));
1317 TestWebSocketAPI
websocket(instance_
);
1318 int32_t result
= websocket
.Connect(url
, NULL
, 0U);
1319 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
1320 websocket
.WaitForConnected();
1321 result
= websocket
.Close(
1322 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, pp::Var(reason
));
1323 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
1324 websocket
.WaitForClosed();
1325 const std::vector
<WebSocketEvent
>& events
= websocket
.GetSeenEvents();
1326 ASSERT_EQ(2U, events
.size());
1327 ASSERT_EQ(WebSocketEvent::EVENT_OPEN
, events
[0].event_type
);
1328 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE
, events
[1].event_type
);
1329 ASSERT_TRUE(events
[1].was_clean
);
1330 ASSERT_EQ(PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, events
[1].close_code
);
1331 ASSERT_TRUE(AreEqualWithString(events
[1].var
.pp_var(), reason
.c_str()));
1334 // Close in connecting.
1335 // The ongoing connect failed with PP_ERROR_ABORTED, then the close is done
1338 TestWebSocketAPI
websocket(instance_
);
1339 int32_t result
= websocket
.Connect(url
, NULL
, 0U);
1340 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
1341 result
= websocket
.Close(
1342 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, pp::Var(reason
));
1343 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
1344 websocket
.WaitForClosed();
1345 const std::vector
<WebSocketEvent
>& events
= websocket
.GetSeenEvents();
1346 ASSERT_TRUE(events
.size() == 2 || events
.size() == 3);
1348 if (events
.size() == 3)
1349 ASSERT_EQ(WebSocketEvent::EVENT_OPEN
, events
[index
++].event_type
);
1350 ASSERT_EQ(WebSocketEvent::EVENT_ERROR
, events
[index
++].event_type
);
1351 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE
, events
[index
].event_type
);
1352 ASSERT_FALSE(events
[index
].was_clean
);
1355 // Close in closing.
1356 // The first close will be done successfully, then the second one failed with
1357 // with PP_ERROR_INPROGRESS immediately.
1359 TestWebSocketAPI
websocket(instance_
);
1360 int32_t result
= websocket
.Connect(url
, NULL
, 0U);
1361 result
= websocket
.Close(
1362 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, pp::Var(reason
));
1363 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
1364 result
= websocket
.Close(
1365 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, pp::Var(reason
));
1366 ASSERT_EQ(PP_ERROR_INPROGRESS
, result
);
1367 websocket
.WaitForClosed();
1368 const std::vector
<WebSocketEvent
>& events
= websocket
.GetSeenEvents();
1369 ASSERT_TRUE(events
.size() == 2 || events
.size() == 3);
1371 if (events
.size() == 3)
1372 ASSERT_EQ(WebSocketEvent::EVENT_OPEN
, events
[index
++].event_type
);
1373 ASSERT_EQ(WebSocketEvent::EVENT_ERROR
, events
[index
++].event_type
);
1374 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE
, events
[index
].event_type
);
1375 ASSERT_FALSE(events
[index
].was_clean
);
1381 std::string
TestWebSocket::TestUtilityGetProtocol() {
1382 const std::string
protocol("x-chat");
1383 const pp::Var protocols
[] = { pp::Var(protocol
) };
1384 std::string
url(GetFullURL(kProtocolTestServerURL
));
1386 TestWebSocketAPI
websocket(instance_
);
1387 int32_t result
= websocket
.Connect(pp::Var(url
), protocols
, 1U);
1388 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
1389 websocket
.WaitForReceived();
1390 ASSERT_TRUE(AreEqualWithString(
1391 websocket
.GetProtocol().pp_var(), protocol
.c_str()));
1392 const std::vector
<WebSocketEvent
>& events
= websocket
.GetSeenEvents();
1393 // The server to which this test connect returns the decided protocol as a
1394 // text frame message. So the WebSocketEvent records EVENT_MESSAGE event
1395 // after EVENT_OPEN event.
1396 ASSERT_EQ(2U, events
.size());
1397 ASSERT_EQ(WebSocketEvent::EVENT_OPEN
, events
[0].event_type
);
1398 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE
, events
[1].event_type
);
1399 ASSERT_TRUE(AreEqualWithString(events
[1].var
.pp_var(), protocol
.c_str()));
1404 std::string
TestWebSocket::TestUtilityTextSendReceive() {
1405 const pp::Var protocols
[] = { pp::Var() };
1406 TestWebSocketAPI
websocket(instance_
);
1408 websocket
.Connect(pp::Var(GetFullURL(kEchoServerURL
)), protocols
, 0U);
1409 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
1410 websocket
.WaitForConnected();
1412 // Send 'hello pepper'.
1413 std::string
message1("hello pepper");
1414 result
= websocket
.Send(pp::Var(std::string(message1
)));
1415 ASSERT_EQ(PP_OK
, result
);
1417 // Receive echoed 'hello pepper'.
1418 websocket
.WaitForReceived();
1420 // Send 'goodbye pepper'.
1421 std::string
message2("goodbye pepper");
1422 result
= websocket
.Send(pp::Var(std::string(message2
)));
1424 // Receive echoed 'goodbye pepper'.
1425 websocket
.WaitForReceived();
1427 const std::vector
<WebSocketEvent
>& events
= websocket
.GetSeenEvents();
1428 ASSERT_EQ(3U, events
.size());
1429 ASSERT_EQ(WebSocketEvent::EVENT_OPEN
, events
[0].event_type
);
1430 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE
, events
[1].event_type
);
1431 ASSERT_TRUE(AreEqualWithString(events
[1].var
.pp_var(), message1
.c_str()));
1432 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE
, events
[2].event_type
);
1433 ASSERT_TRUE(AreEqualWithString(events
[2].var
.pp_var(), message2
.c_str()));
1438 std::string
TestWebSocket::TestUtilityBinarySendReceive() {
1439 const pp::Var protocols
[] = { pp::Var() };
1440 TestWebSocketAPI
websocket(instance_
);
1442 websocket
.Connect(pp::Var(GetFullURL(kEchoServerURL
)), protocols
, 0U);
1443 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
1444 websocket
.WaitForConnected();
1446 // Send binary message.
1448 std::vector
<uint8_t> binary(len
);
1449 for (uint32_t i
= 0; i
< len
; ++i
)
1451 pp::VarArrayBuffer
message(len
);
1452 uint8_t* var_data
= static_cast<uint8_t*>(message
.Map());
1453 std::copy(binary
.begin(), binary
.end(), var_data
);
1454 result
= websocket
.Send(message
);
1455 ASSERT_EQ(PP_OK
, result
);
1457 // Receive echoed binary message.
1458 websocket
.WaitForReceived();
1460 const std::vector
<WebSocketEvent
>& events
= websocket
.GetSeenEvents();
1461 ASSERT_EQ(2U, events
.size());
1462 ASSERT_EQ(WebSocketEvent::EVENT_OPEN
, events
[0].event_type
);
1463 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE
, events
[1].event_type
);
1464 ASSERT_TRUE(AreEqualWithBinary(events
[1].var
.pp_var(), binary
));
1469 std::string
TestWebSocket::TestUtilityBufferedAmount() {
1470 // Connect to test echo server.
1471 const pp::Var protocols
[] = { pp::Var() };
1472 TestWebSocketAPI
websocket(instance_
);
1474 websocket
.Connect(pp::Var(GetFullURL(kEchoServerURL
)), protocols
, 0U);
1475 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
1476 websocket
.WaitForConnected();
1478 // Prepare a large message that is not aligned with the internal buffer
1480 std::string
message(8193, 'x');
1481 uint64_t buffered_amount
= 0;
1483 for (sent
= 0; sent
< 100; sent
++) {
1484 result
= websocket
.Send(pp::Var(message
));
1485 ASSERT_EQ(PP_OK
, result
);
1486 buffered_amount
= websocket
.GetBufferedAmount();
1487 // Buffered amount size 262144 is too big for the internal buffer size.
1488 if (buffered_amount
> 262144)
1492 // Close connection.
1493 std::string reason
= "close while busy";
1494 result
= websocket
.Close(
1495 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE
, pp::Var(reason
));
1496 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSING
, websocket
.GetReadyState());
1497 websocket
.WaitForClosed();
1498 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED
, websocket
.GetReadyState());
1500 uint64_t base_buffered_amount
= websocket
.GetBufferedAmount();
1501 size_t events_on_closed
= websocket
.GetSeenEvents().size();
1503 // After connection closure, all sending requests fail and just increase
1504 // the bufferedAmount property.
1505 result
= websocket
.Send(pp::Var(std::string()));
1506 ASSERT_EQ(PP_ERROR_FAILED
, result
);
1507 buffered_amount
= websocket
.GetBufferedAmount();
1508 ASSERT_EQ(base_buffered_amount
+ kMessageFrameOverhead
, buffered_amount
);
1509 base_buffered_amount
= buffered_amount
;
1511 result
= websocket
.Send(pp::Var(reason
));
1512 ASSERT_EQ(PP_ERROR_FAILED
, result
);
1513 buffered_amount
= websocket
.GetBufferedAmount();
1514 uint64_t reason_frame_size
= kMessageFrameOverhead
+ reason
.length();
1515 ASSERT_EQ(base_buffered_amount
+ reason_frame_size
, buffered_amount
);
1517 const std::vector
<WebSocketEvent
>& events
= websocket
.GetSeenEvents();
1518 ASSERT_EQ(events_on_closed
, events
.size());
1519 ASSERT_EQ(WebSocketEvent::EVENT_OPEN
, events
[0].event_type
);
1520 size_t last_event
= events_on_closed
- 1;
1521 for (uint32_t i
= 1; i
< last_event
; ++i
) {
1522 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE
, events
[i
].event_type
);
1523 ASSERT_TRUE(AreEqualWithString(events
[i
].var
.pp_var(), message
));
1525 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE
, events
[last_event
].event_type
);
1526 ASSERT_TRUE(events
[last_event
].was_clean
);