Android: Remove unneeded Compositor::SetNeedsRedraw()
[chromium-blink-merge.git] / ppapi / tests / test_websocket.cc
blob3b654e24386182455ef8d18571fef43a7f7ada3f
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"
7 #include <stdio.h>
8 #include <string.h>
10 #include <algorithm>
11 #include <memory>
12 #include <string>
13 #include <vector>
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::SpawnedTestServer 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",
46 NULL
49 // Internal packet sizes.
50 const uint64_t kMessageFrameOverhead = 6;
52 namespace {
54 struct WebSocketEvent {
55 enum EventType {
56 EVENT_OPEN,
57 EVENT_MESSAGE,
58 EVENT_ERROR,
59 EVENT_CLOSE
62 WebSocketEvent(EventType type,
63 bool was_clean,
64 uint16_t close_code,
65 const pp::Var& var)
66 : event_type(type),
67 was_clean(was_clean),
68 close_code(close_code),
69 var(var) {
71 EventType event_type;
72 bool was_clean;
73 uint16_t close_code;
74 pp::Var var;
77 class ReleaseResourceDelegate : public TestCompletionCallback::Delegate {
78 public:
79 explicit ReleaseResourceDelegate(const PPB_Core* core_interface,
80 PP_Resource resource)
81 : core_interface_(core_interface),
82 resource_(resource) {
85 // TestCompletionCallback::Delegate implementation.
86 virtual void OnCallback(void* user_data, int32_t result) {
87 if (resource_)
88 core_interface_->ReleaseResource(resource_);
91 private:
92 const PPB_Core* core_interface_;
93 PP_Resource resource_;
96 class TestWebSocketAPI : public pp::WebSocketAPI {
97 public:
98 explicit TestWebSocketAPI(pp::Instance* instance)
99 : pp::WebSocketAPI(instance),
100 connected_(false),
101 received_(false),
102 closed_(false),
103 wait_for_connected_(false),
104 wait_for_received_(false),
105 wait_for_closed_(false),
106 instance_(instance->pp_instance()) {
109 virtual void WebSocketDidOpen() {
110 events_.push_back(
111 WebSocketEvent(WebSocketEvent::EVENT_OPEN, true, 0U, pp::Var()));
112 connected_ = true;
113 if (wait_for_connected_) {
114 GetTestingInterface()->QuitMessageLoop(instance_);
115 wait_for_connected_ = false;
119 virtual void WebSocketDidClose(
120 bool was_clean, uint16_t code, const pp::Var& reason) {
121 events_.push_back(
122 WebSocketEvent(WebSocketEvent::EVENT_CLOSE, was_clean, code, reason));
123 connected_ = true;
124 closed_ = true;
125 if (wait_for_connected_ || wait_for_closed_) {
126 GetTestingInterface()->QuitMessageLoop(instance_);
127 wait_for_connected_ = false;
128 wait_for_closed_ = false;
132 virtual void HandleWebSocketMessage(const pp::Var &message) {
133 events_.push_back(
134 WebSocketEvent(WebSocketEvent::EVENT_MESSAGE, true, 0U, message));
135 received_ = true;
136 if (wait_for_received_) {
137 GetTestingInterface()->QuitMessageLoop(instance_);
138 wait_for_received_ = false;
139 received_ = false;
143 virtual void HandleWebSocketError() {
144 events_.push_back(
145 WebSocketEvent(WebSocketEvent::EVENT_ERROR, true, 0U, pp::Var()));
148 void WaitForConnected() {
149 if (!connected_) {
150 wait_for_connected_ = true;
151 GetTestingInterface()->RunMessageLoop(instance_);
155 void WaitForReceived() {
156 if (!received_) {
157 wait_for_received_ = true;
158 GetTestingInterface()->RunMessageLoop(instance_);
162 void WaitForClosed() {
163 if (!closed_) {
164 wait_for_closed_ = true;
165 GetTestingInterface()->RunMessageLoop(instance_);
169 const std::vector<WebSocketEvent>& GetSeenEvents() const {
170 return events_;
173 private:
174 std::vector<WebSocketEvent> events_;
175 bool connected_;
176 bool received_;
177 bool closed_;
178 bool wait_for_connected_;
179 bool wait_for_received_;
180 bool wait_for_closed_;
181 PP_Instance instance_;
184 } // namespace
186 REGISTER_TEST_CASE(WebSocket);
188 bool TestWebSocket::Init() {
189 websocket_interface_ = static_cast<const PPB_WebSocket*>(
190 pp::Module::Get()->GetBrowserInterface(PPB_WEBSOCKET_INTERFACE));
191 var_interface_ = static_cast<const PPB_Var*>(
192 pp::Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE));
193 arraybuffer_interface_ = static_cast<const PPB_VarArrayBuffer*>(
194 pp::Module::Get()->GetBrowserInterface(
195 PPB_VAR_ARRAY_BUFFER_INTERFACE));
196 core_interface_ = static_cast<const PPB_Core*>(
197 pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE));
198 if (!websocket_interface_ || !var_interface_ || !arraybuffer_interface_ ||
199 !core_interface_)
200 return false;
202 return CheckTestingInterface();
205 void TestWebSocket::RunTests(const std::string& filter) {
206 RUN_TEST_WITH_REFERENCE_CHECK(IsWebSocket, filter);
207 RUN_TEST_WITH_REFERENCE_CHECK(UninitializedPropertiesAccess, filter);
208 RUN_TEST_WITH_REFERENCE_CHECK(InvalidConnect, filter);
209 RUN_TEST_WITH_REFERENCE_CHECK(Protocols, filter);
210 RUN_TEST_WITH_REFERENCE_CHECK(GetURL, filter);
211 RUN_TEST_WITH_REFERENCE_CHECK(ValidConnect, filter);
212 RUN_TEST_WITH_REFERENCE_CHECK(InvalidClose, filter);
213 RUN_TEST_WITH_REFERENCE_CHECK(ValidClose, filter);
214 RUN_TEST_WITH_REFERENCE_CHECK(GetProtocol, filter);
215 RUN_TEST_WITH_REFERENCE_CHECK(TextSendReceive, filter);
216 RUN_TEST_BACKGROUND(TestWebSocket, TextSendReceiveTwice, 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
245 // port.
246 if (instance_->websocket_host().empty())
247 rv += "127.0.0.1";
248 else
249 rv += instance_->websocket_host();
250 if (instance_->websocket_port() != -1) {
251 char buffer[10];
252 sprintf(buffer, ":%d", instance_->websocket_port());
253 rv += std::string(buffer);
255 rv += "/";
256 rv += url;
257 return rv;
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);
268 return var;
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)
278 return false;
279 uint32_t utf8_length;
280 const char* utf8 = var_interface_->VarToUtf8(var, &utf8_length);
281 if (utf8_length != string.size())
282 return false;
283 if (string.compare(utf8))
284 return false;
285 return true;
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())
293 return false;
294 if (!std::equal(binary.begin(), binary.end(),
295 static_cast<uint8_t*>(arraybuffer_interface_->Map(var))))
296 return false;
297 return true;
300 PP_Resource TestWebSocket::Connect(const std::string& url,
301 int32_t* result,
302 const std::string& protocol) {
303 PP_Var protocols[] = { PP_MakeUndefined() };
304 PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
305 if (!ws)
306 return 0;
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);
312 protocol_count = 1U;
314 callback.WaitForResult(websocket_interface_->Connect(
315 ws, url_var, protocols, protocol_count,
316 callback.GetCallback().pp_completion_callback()));
317 ReleaseVar(url_var);
318 if (protocol.size())
319 ReleaseVar(protocols[0]);
320 *result = callback.result();
321 return ws;
324 void TestWebSocket::Send(int32_t /* result */, PP_Resource ws,
325 const std::string& message) {
326 PP_Var message_var = CreateVarString(message);
327 websocket_interface_->SendMessage(ws, message_var);
328 ReleaseVar(message_var);
331 std::string TestWebSocket::TestIsWebSocket() {
332 // Test that a NULL resource isn't a websocket.
333 pp::Resource null_resource;
334 PP_Bool result =
335 websocket_interface_->IsWebSocket(null_resource.pp_resource());
336 ASSERT_FALSE(result);
338 PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
339 ASSERT_TRUE(ws);
341 result = websocket_interface_->IsWebSocket(ws);
342 ASSERT_TRUE(result);
344 core_interface_->ReleaseResource(ws);
346 PASS();
349 std::string TestWebSocket::TestUninitializedPropertiesAccess() {
350 PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
351 ASSERT_TRUE(ws);
353 uint64_t bufferedAmount = websocket_interface_->GetBufferedAmount(ws);
354 ASSERT_EQ(0U, bufferedAmount);
356 uint16_t close_code = websocket_interface_->GetCloseCode(ws);
357 ASSERT_EQ(0U, close_code);
359 PP_Var close_reason = websocket_interface_->GetCloseReason(ws);
360 ASSERT_TRUE(AreEqualWithString(close_reason, std::string()));
361 ReleaseVar(close_reason);
363 PP_Bool close_was_clean = websocket_interface_->GetCloseWasClean(ws);
364 ASSERT_EQ(PP_FALSE, close_was_clean);
366 PP_Var extensions = websocket_interface_->GetExtensions(ws);
367 ASSERT_TRUE(AreEqualWithString(extensions, std::string()));
368 ReleaseVar(extensions);
370 PP_Var protocol = websocket_interface_->GetProtocol(ws);
371 ASSERT_TRUE(AreEqualWithString(protocol, std::string()));
372 ReleaseVar(protocol);
374 PP_WebSocketReadyState ready_state =
375 websocket_interface_->GetReadyState(ws);
376 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_INVALID, ready_state);
378 PP_Var url = websocket_interface_->GetURL(ws);
379 ASSERT_TRUE(AreEqualWithString(url, std::string()));
380 ReleaseVar(url);
382 core_interface_->ReleaseResource(ws);
384 PASS();
387 std::string TestWebSocket::TestInvalidConnect() {
388 PP_Var protocols[] = { PP_MakeUndefined() };
390 PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
391 ASSERT_TRUE(ws);
393 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
394 callback.WaitForResult(websocket_interface_->Connect(
395 ws, PP_MakeUndefined(), protocols, 1U,
396 callback.GetCallback().pp_completion_callback()));
397 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
399 callback.WaitForResult(websocket_interface_->Connect(
400 ws, PP_MakeUndefined(), protocols, 1U,
401 callback.GetCallback().pp_completion_callback()));
402 ASSERT_EQ(PP_ERROR_INPROGRESS, callback.result());
404 core_interface_->ReleaseResource(ws);
406 for (int i = 0; kInvalidURLs[i]; ++i) {
407 int32_t result;
408 ws = Connect(kInvalidURLs[i], &result, std::string());
409 ASSERT_TRUE(ws);
410 ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
412 core_interface_->ReleaseResource(ws);
415 PASS();
418 std::string TestWebSocket::TestProtocols() {
419 PP_Var url = CreateVarString(GetFullURL(kEchoServerURL).c_str());
420 PP_Var bad_protocols[] = {
421 CreateVarString("x-test"),
422 CreateVarString("x-test")
424 PP_Var good_protocols[] = {
425 CreateVarString("x-test"),
426 CreateVarString("x-yatest")
429 PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
430 ASSERT_TRUE(ws);
431 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
432 callback.WaitForResult(websocket_interface_->Connect(
433 ws, url, bad_protocols, 2U,
434 callback.GetCallback().pp_completion_callback()));
435 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
436 core_interface_->ReleaseResource(ws);
438 ws = websocket_interface_->Create(instance_->pp_instance());
439 ASSERT_TRUE(ws);
440 int32_t result = websocket_interface_->Connect(
441 ws, url, good_protocols, 2U, PP_BlockUntilComplete());
442 ASSERT_EQ(PP_ERROR_BLOCKS_MAIN_THREAD, result);
443 core_interface_->ReleaseResource(ws);
445 ReleaseVar(url);
446 for (int i = 0; i < 2; ++i) {
447 ReleaseVar(bad_protocols[i]);
448 ReleaseVar(good_protocols[i]);
450 core_interface_->ReleaseResource(ws);
452 PASS();
455 std::string TestWebSocket::TestGetURL() {
456 for (int i = 0; kInvalidURLs[i]; ++i) {
457 int32_t result;
458 PP_Resource ws = Connect(kInvalidURLs[i], &result, std::string());
459 ASSERT_TRUE(ws);
460 PP_Var url = websocket_interface_->GetURL(ws);
461 ASSERT_TRUE(AreEqualWithString(url, kInvalidURLs[i]));
462 ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
464 ReleaseVar(url);
465 core_interface_->ReleaseResource(ws);
468 PASS();
471 std::string TestWebSocket::TestValidConnect() {
472 int32_t result;
473 PP_Resource ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
474 ASSERT_TRUE(ws);
475 ASSERT_EQ(PP_OK, result);
476 PP_Var extensions = websocket_interface_->GetExtensions(ws);
477 ASSERT_TRUE(AreEqualWithString(extensions, std::string()));
478 core_interface_->ReleaseResource(ws);
479 ReleaseVar(extensions);
481 PASS();
484 std::string TestWebSocket::TestInvalidClose() {
485 PP_Var reason = CreateVarString("close for test");
486 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
487 TestCompletionCallback async_callback(instance_->pp_instance(), PP_REQUIRED);
489 // Close before connect.
490 PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
491 callback.WaitForResult(websocket_interface_->Close(
492 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
493 callback.GetCallback().pp_completion_callback()));
494 ASSERT_EQ(PP_ERROR_FAILED, callback.result());
495 core_interface_->ReleaseResource(ws);
497 // Close with bad arguments.
498 int32_t result;
499 ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
500 ASSERT_TRUE(ws);
501 ASSERT_EQ(PP_OK, result);
502 callback.WaitForResult(websocket_interface_->Close(
503 ws, 1U, reason, callback.GetCallback().pp_completion_callback()));
504 ASSERT_EQ(PP_ERROR_NOACCESS, callback.result());
505 core_interface_->ReleaseResource(ws);
507 // Close with PP_VARTYPE_NULL.
508 ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
509 ASSERT_TRUE(ws);
510 ASSERT_EQ(PP_OK, result);
511 callback.WaitForResult(websocket_interface_->Close(
512 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeNull(),
513 callback.GetCallback().pp_completion_callback()));
514 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
515 core_interface_->ReleaseResource(ws);
517 // Close with PP_VARTYPE_NULL and ongoing receive message.
518 ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
519 ASSERT_TRUE(ws);
520 ASSERT_EQ(PP_OK, result);
521 PP_Var receive_message_var;
522 result = websocket_interface_->ReceiveMessage(
523 ws, &receive_message_var,
524 async_callback.GetCallback().pp_completion_callback());
525 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
526 callback.WaitForResult(websocket_interface_->Close(
527 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeNull(),
528 callback.GetCallback().pp_completion_callback()));
529 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
530 const char* send_message = "hi";
531 PP_Var send_message_var = CreateVarString(send_message);
532 result = websocket_interface_->SendMessage(ws, send_message_var);
533 ReleaseVar(send_message_var);
534 ASSERT_EQ(PP_OK, result);
535 async_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
536 ASSERT_EQ(PP_OK, async_callback.result());
537 ASSERT_TRUE(AreEqualWithString(receive_message_var, send_message));
538 ReleaseVar(receive_message_var);
539 core_interface_->ReleaseResource(ws);
541 // Close twice.
542 ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
543 ASSERT_TRUE(ws);
544 ASSERT_EQ(PP_OK, result);
545 result = websocket_interface_->Close(
546 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
547 async_callback.GetCallback().pp_completion_callback());
548 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
549 // Call another Close() before previous one is in progress.
550 result = websocket_interface_->Close(
551 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
552 callback.GetCallback().pp_completion_callback());
553 ASSERT_EQ(PP_ERROR_INPROGRESS, result);
554 async_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
555 ASSERT_EQ(PP_OK, async_callback.result());
556 // Call another Close() after previous one is completed.
557 // This Close() must do nothing and reports no error.
558 callback.WaitForResult(websocket_interface_->Close(
559 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
560 callback.GetCallback().pp_completion_callback()));
561 ASSERT_EQ(PP_OK, callback.result());
562 core_interface_->ReleaseResource(ws);
564 ReleaseVar(reason);
566 PASS();
569 std::string TestWebSocket::TestValidClose() {
570 PP_Var reason = CreateVarString("close for test");
571 PP_Var url = CreateVarString(GetFullURL(kEchoServerURL).c_str());
572 PP_Var protocols[] = { PP_MakeUndefined() };
573 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
574 TestCompletionCallback another_callback(
575 instance_->pp_instance(), callback_type());
577 // Close.
578 int32_t result;
579 PP_Resource ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
580 ASSERT_TRUE(ws);
581 ASSERT_EQ(PP_OK, result);
582 callback.WaitForResult(websocket_interface_->Close(
583 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
584 callback.GetCallback().pp_completion_callback()));
585 CHECK_CALLBACK_BEHAVIOR(callback);
586 ASSERT_EQ(PP_OK, callback.result());
587 core_interface_->ReleaseResource(ws);
589 // Close without code and reason.
590 ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
591 ASSERT_TRUE(ws);
592 ASSERT_EQ(PP_OK, result);
593 callback.WaitForResult(websocket_interface_->Close(
594 ws, PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED, reason,
595 callback.GetCallback().pp_completion_callback()));
596 ASSERT_EQ(PP_OK, callback.result());
597 core_interface_->ReleaseResource(ws);
599 // Close with PP_VARTYPE_UNDEFINED.
600 ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
601 ASSERT_TRUE(ws);
602 ASSERT_EQ(PP_OK, result);
603 callback.WaitForResult(websocket_interface_->Close(
604 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(),
605 callback.GetCallback().pp_completion_callback()));
606 CHECK_CALLBACK_BEHAVIOR(callback);
607 ASSERT_EQ(PP_OK, callback.result());
608 core_interface_->ReleaseResource(ws);
610 // Close in connecting.
611 // The ongoing connect failed with PP_ERROR_ABORTED, then the close is done
612 // successfully.
613 ws = websocket_interface_->Create(instance_->pp_instance());
614 result = websocket_interface_->Connect(
615 ws, url, protocols, 0U, callback.GetCallback().pp_completion_callback());
616 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
617 result = websocket_interface_->Close(
618 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
619 another_callback.GetCallback().pp_completion_callback());
620 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
621 callback.WaitForResult(PP_OK_COMPLETIONPENDING);
622 ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
623 another_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
624 ASSERT_EQ(PP_OK, another_callback.result());
625 core_interface_->ReleaseResource(ws);
627 // Close in closing.
628 // The first close will be done successfully, then the second one failed with
629 // with PP_ERROR_INPROGRESS immediately.
630 ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
631 ASSERT_TRUE(ws);
632 ASSERT_EQ(PP_OK, result);
633 result = websocket_interface_->Close(
634 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
635 callback.GetCallback().pp_completion_callback());
636 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
637 result = websocket_interface_->Close(
638 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
639 another_callback.GetCallback().pp_completion_callback());
640 ASSERT_EQ(PP_ERROR_INPROGRESS, result);
641 callback.WaitForResult(PP_OK_COMPLETIONPENDING);
642 ASSERT_EQ(PP_OK, callback.result());
643 core_interface_->ReleaseResource(ws);
645 // Close with ongoing receive message.
646 ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
647 ASSERT_TRUE(ws);
648 ASSERT_EQ(PP_OK, result);
649 PP_Var receive_message_var;
650 result = websocket_interface_->ReceiveMessage(
651 ws, &receive_message_var,
652 callback.GetCallback().pp_completion_callback());
653 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
654 result = websocket_interface_->Close(
655 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
656 another_callback.GetCallback().pp_completion_callback());
657 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
658 callback.WaitForResult(PP_OK_COMPLETIONPENDING);
659 ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
660 another_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
661 ASSERT_EQ(PP_OK, another_callback.result());
662 core_interface_->ReleaseResource(ws);
664 // Close with PP_VARTYPE_UNDEFINED and ongoing receive message.
665 ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
666 ASSERT_TRUE(ws);
667 ASSERT_EQ(PP_OK, result);
668 result = websocket_interface_->ReceiveMessage(
669 ws, &receive_message_var,
670 callback.GetCallback().pp_completion_callback());
671 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
672 result = websocket_interface_->Close(
673 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(),
674 another_callback.GetCallback().pp_completion_callback());
675 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
676 callback.WaitForResult(PP_OK_COMPLETIONPENDING);
677 ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
678 another_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
679 ASSERT_EQ(PP_OK, another_callback.result());
680 core_interface_->ReleaseResource(ws);
682 // Server initiated closing handshake.
683 ws = Connect(
684 GetFullURL(kCloseWithCodeAndReasonServerURL), &result, std::string());
685 ASSERT_TRUE(ws);
686 ASSERT_EQ(PP_OK, result);
687 // Text messsage "1000 bye" requests the server to initiate closing handshake
688 // with code being 1000 and reason being "bye".
689 PP_Var close_request_var = CreateVarString("1000 bye");
690 result = websocket_interface_->SendMessage(ws, close_request_var);
691 ReleaseVar(close_request_var);
692 callback.WaitForResult(websocket_interface_->ReceiveMessage(
693 ws, &receive_message_var,
694 callback.GetCallback().pp_completion_callback()));
695 ASSERT_EQ(PP_ERROR_FAILED, callback.result());
696 core_interface_->ReleaseResource(ws);
698 ReleaseVar(reason);
699 ReleaseVar(url);
701 PASS();
704 std::string TestWebSocket::TestGetProtocol() {
705 const char* expected_protocols[] = {
706 "x-chat",
707 "hoehoe",
708 NULL
710 for (int i = 0; expected_protocols[i]; ++i) {
711 std::string url(GetFullURL(kProtocolTestServerURL));
712 url += expected_protocols[i];
713 int32_t result;
714 PP_Resource ws = Connect(url.c_str(), &result, expected_protocols[i]);
715 ASSERT_TRUE(ws);
716 ASSERT_EQ(PP_OK, result);
718 PP_Var protocol = websocket_interface_->GetProtocol(ws);
719 ASSERT_TRUE(AreEqualWithString(protocol, expected_protocols[i]));
721 ReleaseVar(protocol);
722 core_interface_->ReleaseResource(ws);
725 PASS();
728 std::string TestWebSocket::TestTextSendReceive() {
729 // Connect to test echo server.
730 int32_t connect_result;
731 PP_Resource ws =
732 Connect(GetFullURL(kEchoServerURL), &connect_result, std::string());
733 ASSERT_TRUE(ws);
734 ASSERT_EQ(PP_OK, connect_result);
736 // Send 'hello pepper' text message.
737 const char* message = "hello pepper";
738 PP_Var message_var = CreateVarString(message);
739 int32_t result = websocket_interface_->SendMessage(ws, message_var);
740 ReleaseVar(message_var);
741 ASSERT_EQ(PP_OK, result);
743 // Receive echoed 'hello pepper'.
744 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
745 PP_Var received_message;
746 callback.WaitForResult(websocket_interface_->ReceiveMessage(
747 ws, &received_message, callback.GetCallback().pp_completion_callback()));
748 ASSERT_EQ(PP_OK, callback.result());
749 ASSERT_TRUE(AreEqualWithString(received_message, message));
750 ReleaseVar(received_message);
751 core_interface_->ReleaseResource(ws);
753 PASS();
756 // Run as a BACKGROUND test.
757 std::string TestWebSocket::TestTextSendReceiveTwice() {
758 // Connect to test echo server.
759 int32_t connect_result;
760 PP_Resource ws =
761 Connect(GetFullURL(kEchoServerURL), &connect_result, std::string());
762 ASSERT_TRUE(ws);
763 ASSERT_EQ(PP_OK, connect_result);
764 pp::MessageLoop message_loop = pp::MessageLoop::GetCurrent();
765 pp::CompletionCallbackFactory<TestWebSocket> factory(this);
767 message_loop.PostWork(factory.NewCallback(&TestWebSocket::Send,
768 ws, std::string("hello")));
769 // When the server receives 'Goodbye', it closes the session.
770 message_loop.PostWork(factory.NewCallback(&TestWebSocket::Send,
771 ws, std::string("Goodbye")));
772 message_loop.PostQuit(false);
773 message_loop.Run();
775 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
776 PP_Var received_message;
777 int32_t result = websocket_interface_->ReceiveMessage(
778 ws, &received_message, callback.GetCallback().pp_completion_callback());
779 ASSERT_EQ(PP_OK, result);
780 // Since we don't run the message loop, the callback will stay
781 // "pending and scheduled to run" state.
783 // Waiting for the connection close which will be done by the server.
784 while (true) {
785 PP_WebSocketReadyState ready_state =
786 websocket_interface_->GetReadyState(ws);
787 if (ready_state != PP_WEBSOCKETREADYSTATE_CONNECTING &&
788 ready_state != PP_WEBSOCKETREADYSTATE_OPEN) {
789 break;
791 PlatformSleep(100); // 100ms
794 // Cleanup the message loop
795 message_loop.PostQuit(false);
796 message_loop.Run();
798 ASSERT_EQ(PP_OK, callback.result());
799 ASSERT_TRUE(AreEqualWithString(received_message, "hello"));
800 ReleaseVar(received_message);
801 core_interface_->ReleaseResource(ws);
802 PASS();
805 std::string TestWebSocket::TestBinarySendReceive() {
806 // Connect to test echo server.
807 int32_t connect_result;
808 PP_Resource ws =
809 Connect(GetFullURL(kEchoServerURL), &connect_result, std::string());
810 ASSERT_TRUE(ws);
811 ASSERT_EQ(PP_OK, connect_result);
813 // Send binary message.
814 std::vector<uint8_t> binary(256);
815 for (uint32_t i = 0; i < binary.size(); ++i)
816 binary[i] = i;
817 PP_Var message_var = CreateVarBinary(binary);
818 int32_t result = websocket_interface_->SendMessage(ws, message_var);
819 ReleaseVar(message_var);
820 ASSERT_EQ(PP_OK, result);
822 // Receive echoed binary.
823 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
824 PP_Var received_message;
825 callback.WaitForResult(websocket_interface_->ReceiveMessage(
826 ws, &received_message, callback.GetCallback().pp_completion_callback()));
827 ASSERT_EQ(PP_OK, callback.result());
828 ASSERT_TRUE(AreEqualWithBinary(received_message, binary));
829 ReleaseVar(received_message);
830 core_interface_->ReleaseResource(ws);
832 PASS();
835 std::string TestWebSocket::TestStressedSendReceive() {
836 // Connect to test echo server.
837 int32_t connect_result;
838 PP_Resource ws =
839 Connect(GetFullURL(kEchoServerURL), &connect_result, std::string());
840 ASSERT_TRUE(ws);
841 ASSERT_EQ(PP_OK, connect_result);
843 // Prepare PP_Var objects to send.
844 const char* text = "hello pepper";
845 PP_Var text_var = CreateVarString(text);
846 std::vector<uint8_t> binary(256);
847 for (uint32_t i = 0; i < binary.size(); ++i)
848 binary[i] = i;
849 PP_Var binary_var = CreateVarBinary(binary);
850 // Prepare very large binary data over 64KiB. Object serializer in
851 // ppapi_proxy has a limitation of 64KiB as maximum return PP_Var data size
852 // to SRPC. In case received data over 64KiB exists, a specific code handles
853 // this large data via asynchronous callback from main thread. This data
854 // intends to test the code.
855 std::vector<uint8_t> large_binary(65 * 1024);
856 for (uint32_t i = 0; i < large_binary.size(); ++i)
857 large_binary[i] = i & 0xff;
858 PP_Var large_binary_var = CreateVarBinary(large_binary);
860 // Send many messages.
861 int32_t result;
862 for (int i = 0; i < 256; ++i) {
863 result = websocket_interface_->SendMessage(ws, text_var);
864 ASSERT_EQ(PP_OK, result);
865 result = websocket_interface_->SendMessage(ws, binary_var);
866 ASSERT_EQ(PP_OK, result);
868 result = websocket_interface_->SendMessage(ws, large_binary_var);
869 ASSERT_EQ(PP_OK, result);
870 ReleaseVar(text_var);
871 ReleaseVar(binary_var);
872 ReleaseVar(large_binary_var);
874 // Receive echoed data.
875 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
876 for (int i = 0; i <= 512; ++i) {
877 PP_Var received_message;
878 callback.WaitForResult(websocket_interface_->ReceiveMessage(
879 ws, &received_message,
880 callback.GetCallback().pp_completion_callback()));
881 ASSERT_EQ(PP_OK, callback.result());
882 if (i == 512) {
883 ASSERT_TRUE(AreEqualWithBinary(received_message, large_binary));
884 } else if (i & 1) {
885 ASSERT_TRUE(AreEqualWithBinary(received_message, binary));
886 } else {
887 ASSERT_TRUE(AreEqualWithString(received_message, text));
889 ReleaseVar(received_message);
891 core_interface_->ReleaseResource(ws);
893 PASS();
896 std::string TestWebSocket::TestBufferedAmount() {
897 // Connect to test echo server.
898 int32_t connect_result;
899 PP_Resource ws =
900 Connect(GetFullURL(kEchoServerURL), &connect_result, std::string());
901 ASSERT_TRUE(ws);
902 ASSERT_EQ(PP_OK, connect_result);
904 // Prepare a large message that is not aligned with the internal buffer
905 // sizes.
906 std::string message(8193, 'x');
907 PP_Var message_var = CreateVarString(message);
909 uint64_t buffered_amount = 0;
910 int32_t result;
911 for (int i = 0; i < 100; i++) {
912 result = websocket_interface_->SendMessage(ws, message_var);
913 ASSERT_EQ(PP_OK, result);
914 buffered_amount = websocket_interface_->GetBufferedAmount(ws);
915 // Buffered amount size 262144 is too big for the internal buffer size.
916 if (buffered_amount > 262144)
917 break;
920 // Close connection.
921 std::string reason_str = "close while busy";
922 PP_Var reason = CreateVarString(reason_str.c_str());
923 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
924 result = websocket_interface_->Close(
925 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
926 callback.GetCallback().pp_completion_callback());
927 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
928 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSING,
929 websocket_interface_->GetReadyState(ws));
931 callback.WaitForResult(result);
932 ASSERT_EQ(PP_OK, callback.result());
933 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED,
934 websocket_interface_->GetReadyState(ws));
936 uint64_t base_buffered_amount = websocket_interface_->GetBufferedAmount(ws);
938 // After connection closure, all sending requests fail and just increase
939 // the bufferedAmount property.
940 PP_Var empty_string = CreateVarString(std::string());
941 result = websocket_interface_->SendMessage(ws, empty_string);
942 ASSERT_EQ(PP_ERROR_FAILED, result);
943 buffered_amount = websocket_interface_->GetBufferedAmount(ws);
944 ASSERT_EQ(base_buffered_amount + kMessageFrameOverhead, buffered_amount);
945 base_buffered_amount = buffered_amount;
947 result = websocket_interface_->SendMessage(ws, reason);
948 ASSERT_EQ(PP_ERROR_FAILED, result);
949 buffered_amount = websocket_interface_->GetBufferedAmount(ws);
950 uint64_t reason_frame_size = kMessageFrameOverhead + reason_str.length();
951 ASSERT_EQ(base_buffered_amount + reason_frame_size, buffered_amount);
953 ReleaseVar(message_var);
954 ReleaseVar(reason);
955 ReleaseVar(empty_string);
956 core_interface_->ReleaseResource(ws);
958 PASS();
961 // Test abort behaviors where a WebSocket PP_Resource is released while each
962 // function is in-flight on the WebSocket PP_Resource.
963 std::string TestWebSocket::TestAbortCallsWithCallback() {
964 // Following tests make sure the behavior for functions which require a
965 // callback. The callback must get a PP_ERROR_ABORTED.
967 // Test the behavior for Connect().
968 PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
969 ASSERT_TRUE(ws);
970 std::string url = GetFullURL(kEchoServerURL);
971 PP_Var url_var = CreateVarString(url);
972 TestCompletionCallback connect_callback(
973 instance_->pp_instance(), callback_type());
974 int32_t result = websocket_interface_->Connect(
975 ws, url_var, NULL, 0,
976 connect_callback.GetCallback().pp_completion_callback());
977 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
978 core_interface_->ReleaseResource(ws);
979 connect_callback.WaitForResult(result);
980 ASSERT_EQ(PP_ERROR_ABORTED, connect_callback.result());
982 // Test the behavior for Close().
983 ws = Connect(url, &result, std::string());
984 ASSERT_TRUE(ws);
985 ASSERT_EQ(PP_OK, result);
986 PP_Var reason_var = CreateVarString("abort");
987 TestCompletionCallback close_callback(
988 instance_->pp_instance(), callback_type());
989 result = websocket_interface_->Close(
990 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason_var,
991 close_callback.GetCallback().pp_completion_callback());
992 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
993 core_interface_->ReleaseResource(ws);
994 close_callback.WaitForResult(result);
995 ASSERT_EQ(PP_ERROR_ABORTED, close_callback.result());
996 ReleaseVar(reason_var);
998 // Test the behavior for ReceiveMessage().
999 // Make sure the simplest case to wait for data which never arrives, here.
1000 ws = Connect(url, &result, std::string());
1001 ASSERT_TRUE(ws);
1002 ASSERT_EQ(PP_OK, result);
1003 PP_Var receive_var;
1004 TestCompletionCallback receive_callback(
1005 instance_->pp_instance(), callback_type());
1006 result = websocket_interface_->ReceiveMessage(
1007 ws, &receive_var,
1008 receive_callback.GetCallback().pp_completion_callback());
1009 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1010 core_interface_->ReleaseResource(ws);
1011 receive_callback.WaitForResult(result);
1012 ASSERT_EQ(PP_ERROR_ABORTED, receive_callback.result());
1014 // Release the resource in the aborting receive completion callback which is
1015 // introduced by calling Close().
1016 ws = Connect(url, &result, std::string());
1017 ASSERT_TRUE(ws);
1018 ASSERT_EQ(PP_OK, result);
1019 result = websocket_interface_->ReceiveMessage(
1020 ws, &receive_var,
1021 receive_callback.GetCallback().pp_completion_callback());
1022 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1023 ReleaseResourceDelegate receive_delegate(core_interface_, ws);
1024 receive_callback.SetDelegate(&receive_delegate);
1025 result = websocket_interface_->Close(
1026 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(),
1027 close_callback.GetCallback().pp_completion_callback());
1028 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1029 receive_callback.WaitForResult(result);
1030 CHECK_CALLBACK_BEHAVIOR(receive_callback);
1031 ASSERT_EQ(PP_ERROR_ABORTED, receive_callback.result());
1032 close_callback.WaitForResult(result);
1033 CHECK_CALLBACK_BEHAVIOR(close_callback);
1034 ASSERT_EQ(PP_ERROR_ABORTED, close_callback.result());
1036 ReleaseVar(url_var);
1038 PASS();
1041 std::string TestWebSocket::TestAbortSendMessageCall() {
1042 // Test the behavior for SendMessage().
1043 // This function doesn't require a callback, but operation will be done
1044 // asynchronously in WebKit and browser process.
1045 std::vector<uint8_t> large_binary(65 * 1024);
1046 PP_Var large_var = CreateVarBinary(large_binary);
1048 int32_t result;
1049 std::string url = GetFullURL(kEchoServerURL);
1050 PP_Resource ws = Connect(url, &result, std::string());
1051 ASSERT_TRUE(ws);
1052 ASSERT_EQ(PP_OK, result);
1053 result = websocket_interface_->SendMessage(ws, large_var);
1054 ASSERT_EQ(PP_OK, result);
1055 core_interface_->ReleaseResource(ws);
1056 ReleaseVar(large_var);
1058 PASS();
1061 std::string TestWebSocket::TestAbortCloseCall() {
1062 // Release the resource in the close completion callback.
1063 int32_t result;
1064 std::string url = GetFullURL(kEchoServerURL);
1065 PP_Resource ws = Connect(url, &result, std::string());
1066 ASSERT_TRUE(ws);
1067 ASSERT_EQ(PP_OK, result);
1068 TestCompletionCallback close_callback(
1069 instance_->pp_instance(), callback_type());
1070 result = websocket_interface_->Close(
1071 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(),
1072 close_callback.GetCallback().pp_completion_callback());
1073 ReleaseResourceDelegate close_delegate(core_interface_, ws);
1074 close_callback.SetDelegate(&close_delegate);
1075 close_callback.WaitForResult(result);
1076 CHECK_CALLBACK_BEHAVIOR(close_callback);
1077 ASSERT_EQ(PP_OK, close_callback.result());
1079 PASS();
1082 std::string TestWebSocket::TestAbortReceiveMessageCall() {
1083 // Test the behavior where receive process might be in-flight.
1084 std::vector<uint8_t> large_binary(65 * 1024);
1085 PP_Var large_var = CreateVarBinary(large_binary);
1086 const char* text = "yukarin";
1087 PP_Var text_var = CreateVarString(text);
1089 std::string url = GetFullURL(kEchoServerURL);
1090 int32_t result;
1091 PP_Resource ws;
1093 // Each trial sends |trial_count| + 1 messages and receives just |trial|
1094 // number of message(s) before releasing the WebSocket. The WebSocket is
1095 // released while the next message is going to be received.
1096 const int trial_count = 8;
1097 for (int trial = 1; trial <= trial_count; trial++) {
1098 ws = Connect(url, &result, std::string());
1099 ASSERT_TRUE(ws);
1100 ASSERT_EQ(PP_OK, result);
1101 for (int i = 0; i <= trial_count; ++i) {
1102 result = websocket_interface_->SendMessage(ws, text_var);
1103 ASSERT_EQ(PP_OK, result);
1105 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
1106 PP_Var var;
1107 for (int i = 0; i < trial; ++i) {
1108 callback.WaitForResult(websocket_interface_->ReceiveMessage(
1109 ws, &var, callback.GetCallback().pp_completion_callback()));
1110 ASSERT_EQ(PP_OK, callback.result());
1111 ASSERT_TRUE(AreEqualWithString(var, text));
1112 ReleaseVar(var);
1114 result = websocket_interface_->ReceiveMessage(
1115 ws, &var, callback.GetCallback().pp_completion_callback());
1116 core_interface_->ReleaseResource(ws);
1117 if (result != PP_OK) {
1118 callback.WaitForResult(result);
1119 ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
1122 // Same test, but the last receiving message is large message over 64KiB.
1123 for (int trial = 1; trial <= trial_count; trial++) {
1124 ws = Connect(url, &result, std::string());
1125 ASSERT_TRUE(ws);
1126 ASSERT_EQ(PP_OK, result);
1127 for (int i = 0; i <= trial_count; ++i) {
1128 if (i == trial)
1129 result = websocket_interface_->SendMessage(ws, large_var);
1130 else
1131 result = websocket_interface_->SendMessage(ws, text_var);
1132 ASSERT_EQ(PP_OK, result);
1134 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
1135 PP_Var var;
1136 for (int i = 0; i < trial; ++i) {
1137 callback.WaitForResult(websocket_interface_->ReceiveMessage(
1138 ws, &var, callback.GetCallback().pp_completion_callback()));
1139 ASSERT_EQ(PP_OK, callback.result());
1140 ASSERT_TRUE(AreEqualWithString(var, text));
1141 ReleaseVar(var);
1143 result = websocket_interface_->ReceiveMessage(
1144 ws, &var, callback.GetCallback().pp_completion_callback());
1145 core_interface_->ReleaseResource(ws);
1146 if (result != PP_OK) {
1147 callback.WaitForResult(result);
1148 ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
1152 ReleaseVar(large_var);
1153 ReleaseVar(text_var);
1155 PASS();
1158 std::string TestWebSocket::TestCcInterfaces() {
1159 // C++ bindings is simple straightforward, then just verifies interfaces work
1160 // as a interface bridge fine.
1161 pp::WebSocket ws(instance_);
1163 // Check uninitialized properties access.
1164 ASSERT_EQ(0, ws.GetBufferedAmount());
1165 ASSERT_EQ(0, ws.GetCloseCode());
1166 ASSERT_TRUE(AreEqualWithString(ws.GetCloseReason().pp_var(), std::string()));
1167 ASSERT_EQ(false, ws.GetCloseWasClean());
1168 ASSERT_TRUE(AreEqualWithString(ws.GetExtensions().pp_var(), std::string()));
1169 ASSERT_TRUE(AreEqualWithString(ws.GetProtocol().pp_var(), std::string()));
1170 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_INVALID, ws.GetReadyState());
1171 ASSERT_TRUE(AreEqualWithString(ws.GetURL().pp_var(), std::string()));
1173 // Check communication interfaces (connect, send, receive, and close).
1174 TestCompletionCallback connect_callback(
1175 instance_->pp_instance(), callback_type());
1176 connect_callback.WaitForResult(ws.Connect(
1177 pp::Var(GetFullURL(kCloseServerURL)), NULL, 0U,
1178 connect_callback.GetCallback()));
1179 CHECK_CALLBACK_BEHAVIOR(connect_callback);
1180 ASSERT_EQ(PP_OK, connect_callback.result());
1182 std::string text_message("hello C++");
1183 int32_t result = ws.SendMessage(pp::Var(text_message));
1184 ASSERT_EQ(PP_OK, result);
1186 std::vector<uint8_t> binary(256);
1187 for (uint32_t i = 0; i < binary.size(); ++i)
1188 binary[i] = i;
1189 result = ws.SendMessage(
1190 pp::Var(pp::PASS_REF, CreateVarBinary(binary)));
1191 ASSERT_EQ(PP_OK, result);
1193 pp::Var text_receive_var;
1194 TestCompletionCallback text_receive_callback(
1195 instance_->pp_instance(), callback_type());
1196 text_receive_callback.WaitForResult(
1197 ws.ReceiveMessage(&text_receive_var,
1198 text_receive_callback.GetCallback()));
1199 ASSERT_EQ(PP_OK, text_receive_callback.result());
1200 ASSERT_TRUE(
1201 AreEqualWithString(text_receive_var.pp_var(), text_message.c_str()));
1203 pp::Var binary_receive_var;
1204 TestCompletionCallback binary_receive_callback(
1205 instance_->pp_instance(), callback_type());
1206 binary_receive_callback.WaitForResult(
1207 ws.ReceiveMessage(&binary_receive_var,
1208 binary_receive_callback.GetCallback()));
1209 ASSERT_EQ(PP_OK, binary_receive_callback.result());
1210 ASSERT_TRUE(AreEqualWithBinary(binary_receive_var.pp_var(), binary));
1212 TestCompletionCallback close_callback(
1213 instance_->pp_instance(), callback_type());
1214 std::string reason("bye");
1215 close_callback.WaitForResult(ws.Close(
1216 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason),
1217 close_callback.GetCallback()));
1218 CHECK_CALLBACK_BEHAVIOR(close_callback);
1219 ASSERT_EQ(PP_OK, close_callback.result());
1221 // Check initialized properties access.
1222 ASSERT_EQ(0, ws.GetBufferedAmount());
1223 ASSERT_EQ(PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, ws.GetCloseCode());
1224 ASSERT_TRUE(
1225 AreEqualWithString(ws.GetCloseReason().pp_var(), reason.c_str()));
1226 ASSERT_EQ(true, ws.GetCloseWasClean());
1227 ASSERT_TRUE(AreEqualWithString(ws.GetProtocol().pp_var(), std::string()));
1228 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED, ws.GetReadyState());
1229 ASSERT_TRUE(AreEqualWithString(
1230 ws.GetURL().pp_var(), GetFullURL(kCloseServerURL).c_str()));
1232 PASS();
1235 std::string TestWebSocket::TestUtilityInvalidConnect() {
1236 const pp::Var protocols[] = { pp::Var() };
1238 TestWebSocketAPI websocket(instance_);
1239 int32_t result = websocket.Connect(pp::Var(), protocols, 1U);
1240 ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
1241 ASSERT_EQ(0U, websocket.GetSeenEvents().size());
1243 result = websocket.Connect(pp::Var(), protocols, 1U);
1244 ASSERT_EQ(PP_ERROR_INPROGRESS, result);
1245 ASSERT_EQ(0U, websocket.GetSeenEvents().size());
1247 for (int i = 0; kInvalidURLs[i]; ++i) {
1248 TestWebSocketAPI ws(instance_);
1249 result = ws.Connect(pp::Var(std::string(kInvalidURLs[i])), protocols, 0U);
1250 if (result == PP_OK_COMPLETIONPENDING) {
1251 ws.WaitForClosed();
1252 const std::vector<WebSocketEvent>& events = ws.GetSeenEvents();
1253 ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[0].event_type);
1254 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type);
1255 ASSERT_EQ(2U, ws.GetSeenEvents().size());
1256 } else {
1257 ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
1258 ASSERT_EQ(0U, ws.GetSeenEvents().size());
1262 PASS();
1265 std::string TestWebSocket::TestUtilityProtocols() {
1266 const pp::Var bad_protocols[] = {
1267 pp::Var(std::string("x-test")), pp::Var(std::string("x-test")) };
1268 const pp::Var good_protocols[] = {
1269 pp::Var(std::string("x-test")), pp::Var(std::string("x-yatest")) };
1272 TestWebSocketAPI websocket(instance_);
1273 int32_t result = websocket.Connect(
1274 pp::Var(GetFullURL(kEchoServerURL)), bad_protocols, 2U);
1275 ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
1276 ASSERT_EQ(0U, websocket.GetSeenEvents().size());
1280 TestWebSocketAPI websocket(instance_);
1281 int32_t result = websocket.Connect(
1282 pp::Var(GetFullURL(kEchoServerURL)), good_protocols, 2U);
1283 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1284 websocket.WaitForConnected();
1285 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1286 // Protocol arguments are valid, but this test run without a WebSocket
1287 // server. As a result, OnError() and OnClose() are invoked because of
1288 // a connection establishment failure.
1289 ASSERT_EQ(2U, events.size());
1290 ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[0].event_type);
1291 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type);
1292 ASSERT_FALSE(events[1].was_clean);
1295 PASS();
1298 std::string TestWebSocket::TestUtilityGetURL() {
1299 const pp::Var protocols[] = { pp::Var() };
1301 for (int i = 0; kInvalidURLs[i]; ++i) {
1302 TestWebSocketAPI websocket(instance_);
1303 int32_t result = websocket.Connect(
1304 pp::Var(std::string(kInvalidURLs[i])), protocols, 0U);
1305 if (result == PP_OK_COMPLETIONPENDING) {
1306 websocket.WaitForClosed();
1307 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1308 ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[0].event_type);
1309 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type);
1310 ASSERT_EQ(2U, events.size());
1311 } else {
1312 ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
1313 ASSERT_EQ(0U, websocket.GetSeenEvents().size());
1315 pp::Var url = websocket.GetURL();
1316 ASSERT_TRUE(AreEqualWithString(url.pp_var(), kInvalidURLs[i]));
1319 PASS();
1322 std::string TestWebSocket::TestUtilityValidConnect() {
1323 const pp::Var protocols[] = { pp::Var() };
1324 TestWebSocketAPI websocket(instance_);
1325 int32_t result = websocket.Connect(
1326 pp::Var(GetFullURL(kEchoServerURL)), protocols, 0U);
1327 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1328 websocket.WaitForConnected();
1329 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1330 ASSERT_EQ(1U, events.size());
1331 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1332 ASSERT_TRUE(
1333 AreEqualWithString(websocket.GetExtensions().pp_var(), std::string()));
1335 PASS();
1338 std::string TestWebSocket::TestUtilityInvalidClose() {
1339 const pp::Var reason = pp::Var(std::string("close for test"));
1341 // Close before connect.
1343 TestWebSocketAPI websocket(instance_);
1344 int32_t result = websocket.Close(
1345 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason);
1346 ASSERT_EQ(PP_ERROR_FAILED, result);
1347 ASSERT_EQ(0U, websocket.GetSeenEvents().size());
1350 // Close with bad arguments.
1352 TestWebSocketAPI websocket(instance_);
1353 int32_t result = websocket.Connect(pp::Var(GetFullURL(kEchoServerURL)),
1354 NULL, 0);
1355 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1356 websocket.WaitForConnected();
1357 result = websocket.Close(1U, reason);
1358 ASSERT_EQ(PP_ERROR_NOACCESS, result);
1359 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1360 ASSERT_EQ(1U, events.size());
1361 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1364 PASS();
1367 std::string TestWebSocket::TestUtilityValidClose() {
1368 std::string reason("close for test");
1369 pp::Var url = pp::Var(GetFullURL(kCloseServerURL));
1371 // Close.
1373 TestWebSocketAPI websocket(instance_);
1374 int32_t result = websocket.Connect(url, NULL, 0U);
1375 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1376 websocket.WaitForConnected();
1377 result = websocket.Close(
1378 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
1379 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1380 websocket.WaitForClosed();
1381 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1382 ASSERT_EQ(2U, events.size());
1383 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1384 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type);
1385 ASSERT_TRUE(events[1].was_clean);
1386 ASSERT_EQ(PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, events[1].close_code);
1387 ASSERT_TRUE(AreEqualWithString(events[1].var.pp_var(), reason.c_str()));
1390 // Close in connecting.
1391 // The ongoing connect failed with PP_ERROR_ABORTED, then the close is done
1392 // successfully.
1394 TestWebSocketAPI websocket(instance_);
1395 int32_t result = websocket.Connect(url, NULL, 0U);
1396 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1397 result = websocket.Close(
1398 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
1399 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1400 websocket.WaitForClosed();
1401 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1402 ASSERT_TRUE(events.size() == 2 || events.size() == 3);
1403 int index = 0;
1404 if (events.size() == 3)
1405 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[index++].event_type);
1406 ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[index++].event_type);
1407 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[index].event_type);
1408 ASSERT_FALSE(events[index].was_clean);
1411 // Close in closing.
1412 // The first close will be done successfully, then the second one failed with
1413 // with PP_ERROR_INPROGRESS immediately.
1415 TestWebSocketAPI websocket(instance_);
1416 int32_t result = websocket.Connect(url, NULL, 0U);
1417 result = websocket.Close(
1418 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
1419 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1420 result = websocket.Close(
1421 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
1422 ASSERT_EQ(PP_ERROR_INPROGRESS, result);
1423 websocket.WaitForClosed();
1424 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1425 ASSERT_TRUE(events.size() == 2 || events.size() == 3);
1426 int index = 0;
1427 if (events.size() == 3)
1428 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[index++].event_type);
1429 ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[index++].event_type);
1430 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[index].event_type);
1431 ASSERT_FALSE(events[index].was_clean);
1434 PASS();
1437 std::string TestWebSocket::TestUtilityGetProtocol() {
1438 const std::string protocol("x-chat");
1439 const pp::Var protocols[] = { pp::Var(protocol) };
1440 std::string url(GetFullURL(kProtocolTestServerURL));
1441 url += protocol;
1442 TestWebSocketAPI websocket(instance_);
1443 int32_t result = websocket.Connect(pp::Var(url), protocols, 1U);
1444 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1445 websocket.WaitForReceived();
1446 ASSERT_TRUE(AreEqualWithString(
1447 websocket.GetProtocol().pp_var(), protocol.c_str()));
1448 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1449 // The server to which this test connect returns the decided protocol as a
1450 // text frame message. So the WebSocketEvent records EVENT_MESSAGE event
1451 // after EVENT_OPEN event.
1452 ASSERT_EQ(2U, events.size());
1453 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1454 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type);
1455 ASSERT_TRUE(AreEqualWithString(events[1].var.pp_var(), protocol.c_str()));
1457 PASS();
1460 std::string TestWebSocket::TestUtilityTextSendReceive() {
1461 const pp::Var protocols[] = { pp::Var() };
1462 TestWebSocketAPI websocket(instance_);
1463 int32_t result =
1464 websocket.Connect(pp::Var(GetFullURL(kEchoServerURL)), protocols, 0U);
1465 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1466 websocket.WaitForConnected();
1468 // Send 'hello pepper'.
1469 std::string message1("hello pepper");
1470 result = websocket.Send(pp::Var(std::string(message1)));
1471 ASSERT_EQ(PP_OK, result);
1473 // Receive echoed 'hello pepper'.
1474 websocket.WaitForReceived();
1476 // Send 'goodbye pepper'.
1477 std::string message2("goodbye pepper");
1478 result = websocket.Send(pp::Var(std::string(message2)));
1480 // Receive echoed 'goodbye pepper'.
1481 websocket.WaitForReceived();
1483 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1484 ASSERT_EQ(3U, events.size());
1485 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1486 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type);
1487 ASSERT_TRUE(AreEqualWithString(events[1].var.pp_var(), message1.c_str()));
1488 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[2].event_type);
1489 ASSERT_TRUE(AreEqualWithString(events[2].var.pp_var(), message2.c_str()));
1491 PASS();
1494 std::string TestWebSocket::TestUtilityBinarySendReceive() {
1495 const pp::Var protocols[] = { pp::Var() };
1496 TestWebSocketAPI websocket(instance_);
1497 int32_t result =
1498 websocket.Connect(pp::Var(GetFullURL(kEchoServerURL)), protocols, 0U);
1499 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1500 websocket.WaitForConnected();
1502 // Send binary message.
1503 uint32_t len = 256;
1504 std::vector<uint8_t> binary(len);
1505 for (uint32_t i = 0; i < len; ++i)
1506 binary[i] = i;
1507 pp::VarArrayBuffer message(len);
1508 uint8_t* var_data = static_cast<uint8_t*>(message.Map());
1509 std::copy(binary.begin(), binary.end(), var_data);
1510 result = websocket.Send(message);
1511 ASSERT_EQ(PP_OK, result);
1513 // Receive echoed binary message.
1514 websocket.WaitForReceived();
1516 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1517 ASSERT_EQ(2U, events.size());
1518 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1519 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type);
1520 ASSERT_TRUE(AreEqualWithBinary(events[1].var.pp_var(), binary));
1522 PASS();
1525 std::string TestWebSocket::TestUtilityBufferedAmount() {
1526 // Connect to test echo server.
1527 const pp::Var protocols[] = { pp::Var() };
1528 TestWebSocketAPI websocket(instance_);
1529 int32_t result =
1530 websocket.Connect(pp::Var(GetFullURL(kEchoServerURL)), protocols, 0U);
1531 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1532 websocket.WaitForConnected();
1534 // Prepare a large message that is not aligned with the internal buffer
1535 // sizes.
1536 std::string message(8193, 'x');
1537 uint64_t buffered_amount = 0;
1538 uint32_t sent;
1539 for (sent = 0; sent < 100; sent++) {
1540 result = websocket.Send(pp::Var(message));
1541 ASSERT_EQ(PP_OK, result);
1542 buffered_amount = websocket.GetBufferedAmount();
1543 // Buffered amount size 262144 is too big for the internal buffer size.
1544 if (buffered_amount > 262144)
1545 break;
1548 // Close connection.
1549 std::string reason = "close while busy";
1550 result = websocket.Close(
1551 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
1552 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSING, websocket.GetReadyState());
1553 websocket.WaitForClosed();
1554 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED, websocket.GetReadyState());
1556 uint64_t base_buffered_amount = websocket.GetBufferedAmount();
1557 size_t events_on_closed = websocket.GetSeenEvents().size();
1559 // After connection closure, all sending requests fail and just increase
1560 // the bufferedAmount property.
1561 result = websocket.Send(pp::Var(std::string()));
1562 ASSERT_EQ(PP_ERROR_FAILED, result);
1563 buffered_amount = websocket.GetBufferedAmount();
1564 ASSERT_EQ(base_buffered_amount + kMessageFrameOverhead, buffered_amount);
1565 base_buffered_amount = buffered_amount;
1567 result = websocket.Send(pp::Var(reason));
1568 ASSERT_EQ(PP_ERROR_FAILED, result);
1569 buffered_amount = websocket.GetBufferedAmount();
1570 uint64_t reason_frame_size = kMessageFrameOverhead + reason.length();
1571 ASSERT_EQ(base_buffered_amount + reason_frame_size, buffered_amount);
1573 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1574 ASSERT_EQ(events_on_closed, events.size());
1575 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1576 size_t last_event = events_on_closed - 1;
1577 for (uint32_t i = 1; i < last_event; ++i) {
1578 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[i].event_type);
1579 ASSERT_TRUE(AreEqualWithString(events[i].var.pp_var(), message));
1581 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[last_event].event_type);
1582 ASSERT_TRUE(events[last_event].was_clean);
1584 PASS();