cc: Added inline to Tile::IsReadyToDraw
[chromium-blink-merge.git] / ppapi / tests / test_websocket.cc
blob6cc774d73662569d2ffb2ad5c6e4de4265132608
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 kCloseFrameSize = 6;
51 const uint64_t kMessageFrameOverhead = 6;
53 namespace {
55 struct WebSocketEvent {
56 enum EventType {
57 EVENT_OPEN,
58 EVENT_MESSAGE,
59 EVENT_ERROR,
60 EVENT_CLOSE
63 WebSocketEvent(EventType type,
64 bool was_clean,
65 uint16_t close_code,
66 const pp::Var& var)
67 : event_type(type),
68 was_clean(was_clean),
69 close_code(close_code),
70 var(var) {
72 EventType event_type;
73 bool was_clean;
74 uint16_t close_code;
75 pp::Var var;
78 class ReleaseResourceDelegate : public TestCompletionCallback::Delegate {
79 public:
80 explicit ReleaseResourceDelegate(const PPB_Core* core_interface,
81 PP_Resource resource)
82 : core_interface_(core_interface),
83 resource_(resource) {
86 // TestCompletionCallback::Delegate implementation.
87 virtual void OnCallback(void* user_data, int32_t result) {
88 if (resource_)
89 core_interface_->ReleaseResource(resource_);
92 private:
93 const PPB_Core* core_interface_;
94 PP_Resource resource_;
97 class TestWebSocketAPI : public pp::WebSocketAPI {
98 public:
99 explicit TestWebSocketAPI(pp::Instance* instance)
100 : pp::WebSocketAPI(instance),
101 connected_(false),
102 received_(false),
103 closed_(false),
104 wait_for_connected_(false),
105 wait_for_received_(false),
106 wait_for_closed_(false),
107 instance_(instance->pp_instance()) {
110 virtual void WebSocketDidOpen() {
111 events_.push_back(
112 WebSocketEvent(WebSocketEvent::EVENT_OPEN, true, 0U, pp::Var()));
113 connected_ = true;
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) {
122 events_.push_back(
123 WebSocketEvent(WebSocketEvent::EVENT_CLOSE, was_clean, code, reason));
124 connected_ = true;
125 closed_ = true;
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) {
134 events_.push_back(
135 WebSocketEvent(WebSocketEvent::EVENT_MESSAGE, true, 0U, message));
136 received_ = true;
137 if (wait_for_received_) {
138 GetTestingInterface()->QuitMessageLoop(instance_);
139 wait_for_received_ = false;
140 received_ = false;
144 virtual void HandleWebSocketError() {
145 events_.push_back(
146 WebSocketEvent(WebSocketEvent::EVENT_ERROR, true, 0U, pp::Var()));
149 void WaitForConnected() {
150 if (!connected_) {
151 wait_for_connected_ = true;
152 GetTestingInterface()->RunMessageLoop(instance_);
156 void WaitForReceived() {
157 if (!received_) {
158 wait_for_received_ = true;
159 GetTestingInterface()->RunMessageLoop(instance_);
163 void WaitForClosed() {
164 if (!closed_) {
165 wait_for_closed_ = true;
166 GetTestingInterface()->RunMessageLoop(instance_);
170 const std::vector<WebSocketEvent>& GetSeenEvents() const {
171 return events_;
174 private:
175 std::vector<WebSocketEvent> events_;
176 bool connected_;
177 bool received_;
178 bool closed_;
179 bool wait_for_connected_;
180 bool wait_for_received_;
181 bool wait_for_closed_;
182 PP_Instance instance_;
185 } // namespace
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_ ||
200 !core_interface_)
201 return false;
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_BACKGROUND(TestWebSocket, TextSendReceiveTwice, filter);
218 RUN_TEST_WITH_REFERENCE_CHECK(BinarySendReceive, filter);
219 RUN_TEST_WITH_REFERENCE_CHECK(StressedSendReceive, filter);
220 RUN_TEST_WITH_REFERENCE_CHECK(BufferedAmount, filter);
221 // PP_Resource for WebSocket may be released later because of an internal
222 // reference for asynchronous IPC handling. So, suppress reference check on
223 // the following AbortCallsWithCallback test.
224 RUN_TEST(AbortCallsWithCallback, filter);
225 RUN_TEST_WITH_REFERENCE_CHECK(AbortSendMessageCall, filter);
226 RUN_TEST_WITH_REFERENCE_CHECK(AbortCloseCall, filter);
227 RUN_TEST_WITH_REFERENCE_CHECK(AbortReceiveMessageCall, filter);
229 RUN_TEST_WITH_REFERENCE_CHECK(CcInterfaces, filter);
231 RUN_TEST_WITH_REFERENCE_CHECK(UtilityInvalidConnect, filter);
232 RUN_TEST_WITH_REFERENCE_CHECK(UtilityProtocols, filter);
233 RUN_TEST_WITH_REFERENCE_CHECK(UtilityGetURL, filter);
234 RUN_TEST_WITH_REFERENCE_CHECK(UtilityValidConnect, filter);
235 RUN_TEST_WITH_REFERENCE_CHECK(UtilityInvalidClose, filter);
236 RUN_TEST_WITH_REFERENCE_CHECK(UtilityValidClose, filter);
237 RUN_TEST_WITH_REFERENCE_CHECK(UtilityGetProtocol, filter);
238 RUN_TEST_WITH_REFERENCE_CHECK(UtilityTextSendReceive, filter);
239 RUN_TEST_WITH_REFERENCE_CHECK(UtilityBinarySendReceive, filter);
240 RUN_TEST_WITH_REFERENCE_CHECK(UtilityBufferedAmount, filter);
243 std::string TestWebSocket::GetFullURL(const char* url) {
244 std::string rv = "ws://";
245 // Some WebSocket tests don't start the server so there'll be no host and
246 // port.
247 if (instance_->websocket_host().empty())
248 rv += "127.0.0.1";
249 else
250 rv += instance_->websocket_host();
251 if (instance_->websocket_port() != -1) {
252 char buffer[10];
253 sprintf(buffer, ":%d", instance_->websocket_port());
254 rv += std::string(buffer);
256 rv += "/";
257 rv += url;
258 return rv;
261 PP_Var TestWebSocket::CreateVarString(const std::string& string) {
262 return var_interface_->VarFromUtf8(string.c_str(), string.size());
265 PP_Var TestWebSocket::CreateVarBinary(const std::vector<uint8_t>& binary) {
266 PP_Var var = arraybuffer_interface_->Create(binary.size());
267 uint8_t* var_data = static_cast<uint8_t*>(arraybuffer_interface_->Map(var));
268 std::copy(binary.begin(), binary.end(), var_data);
269 return var;
272 void TestWebSocket::ReleaseVar(const PP_Var& var) {
273 var_interface_->Release(var);
276 bool TestWebSocket::AreEqualWithString(const PP_Var& var,
277 const std::string& string) {
278 if (var.type != PP_VARTYPE_STRING)
279 return false;
280 uint32_t utf8_length;
281 const char* utf8 = var_interface_->VarToUtf8(var, &utf8_length);
282 if (utf8_length != string.size())
283 return false;
284 if (string.compare(utf8))
285 return false;
286 return true;
289 bool TestWebSocket::AreEqualWithBinary(const PP_Var& var,
290 const std::vector<uint8_t>& binary) {
291 uint32_t buffer_size = 0;
292 PP_Bool success = arraybuffer_interface_->ByteLength(var, &buffer_size);
293 if (!success || buffer_size != binary.size())
294 return false;
295 if (!std::equal(binary.begin(), binary.end(),
296 static_cast<uint8_t*>(arraybuffer_interface_->Map(var))))
297 return false;
298 return true;
301 PP_Resource TestWebSocket::Connect(const std::string& url,
302 int32_t* result,
303 const std::string& protocol) {
304 PP_Var protocols[] = { PP_MakeUndefined() };
305 PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
306 if (!ws)
307 return 0;
308 PP_Var url_var = CreateVarString(url);
309 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
310 uint32_t protocol_count = 0U;
311 if (protocol.size()) {
312 protocols[0] = CreateVarString(protocol);
313 protocol_count = 1U;
315 callback.WaitForResult(websocket_interface_->Connect(
316 ws, url_var, protocols, protocol_count,
317 callback.GetCallback().pp_completion_callback()));
318 ReleaseVar(url_var);
319 if (protocol.size())
320 ReleaseVar(protocols[0]);
321 *result = callback.result();
322 return ws;
325 void TestWebSocket::Send(int32_t /* result */, PP_Resource ws,
326 const std::string& message) {
327 PP_Var message_var = CreateVarString(message);
328 websocket_interface_->SendMessage(ws, message_var);
329 ReleaseVar(message_var);
332 std::string TestWebSocket::TestIsWebSocket() {
333 // Test that a NULL resource isn't a websocket.
334 pp::Resource null_resource;
335 PP_Bool result =
336 websocket_interface_->IsWebSocket(null_resource.pp_resource());
337 ASSERT_FALSE(result);
339 PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
340 ASSERT_TRUE(ws);
342 result = websocket_interface_->IsWebSocket(ws);
343 ASSERT_TRUE(result);
345 core_interface_->ReleaseResource(ws);
347 PASS();
350 std::string TestWebSocket::TestUninitializedPropertiesAccess() {
351 PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
352 ASSERT_TRUE(ws);
354 uint64_t bufferedAmount = websocket_interface_->GetBufferedAmount(ws);
355 ASSERT_EQ(0U, bufferedAmount);
357 uint16_t close_code = websocket_interface_->GetCloseCode(ws);
358 ASSERT_EQ(0U, close_code);
360 PP_Var close_reason = websocket_interface_->GetCloseReason(ws);
361 ASSERT_TRUE(AreEqualWithString(close_reason, std::string()));
362 ReleaseVar(close_reason);
364 PP_Bool close_was_clean = websocket_interface_->GetCloseWasClean(ws);
365 ASSERT_EQ(PP_FALSE, close_was_clean);
367 PP_Var extensions = websocket_interface_->GetExtensions(ws);
368 ASSERT_TRUE(AreEqualWithString(extensions, std::string()));
369 ReleaseVar(extensions);
371 PP_Var protocol = websocket_interface_->GetProtocol(ws);
372 ASSERT_TRUE(AreEqualWithString(protocol, std::string()));
373 ReleaseVar(protocol);
375 PP_WebSocketReadyState ready_state =
376 websocket_interface_->GetReadyState(ws);
377 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_INVALID, ready_state);
379 PP_Var url = websocket_interface_->GetURL(ws);
380 ASSERT_TRUE(AreEqualWithString(url, std::string()));
381 ReleaseVar(url);
383 core_interface_->ReleaseResource(ws);
385 PASS();
388 std::string TestWebSocket::TestInvalidConnect() {
389 PP_Var protocols[] = { PP_MakeUndefined() };
391 PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
392 ASSERT_TRUE(ws);
394 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
395 callback.WaitForResult(websocket_interface_->Connect(
396 ws, PP_MakeUndefined(), protocols, 1U,
397 callback.GetCallback().pp_completion_callback()));
398 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
400 callback.WaitForResult(websocket_interface_->Connect(
401 ws, PP_MakeUndefined(), protocols, 1U,
402 callback.GetCallback().pp_completion_callback()));
403 ASSERT_EQ(PP_ERROR_INPROGRESS, callback.result());
405 core_interface_->ReleaseResource(ws);
407 for (int i = 0; kInvalidURLs[i]; ++i) {
408 int32_t result;
409 ws = Connect(kInvalidURLs[i], &result, std::string());
410 ASSERT_TRUE(ws);
411 ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
413 core_interface_->ReleaseResource(ws);
416 PASS();
419 std::string TestWebSocket::TestProtocols() {
420 PP_Var url = CreateVarString(GetFullURL(kEchoServerURL).c_str());
421 PP_Var bad_protocols[] = {
422 CreateVarString("x-test"),
423 CreateVarString("x-test")
425 PP_Var good_protocols[] = {
426 CreateVarString("x-test"),
427 CreateVarString("x-yatest")
430 PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
431 ASSERT_TRUE(ws);
432 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
433 callback.WaitForResult(websocket_interface_->Connect(
434 ws, url, bad_protocols, 2U,
435 callback.GetCallback().pp_completion_callback()));
436 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
437 core_interface_->ReleaseResource(ws);
439 ws = websocket_interface_->Create(instance_->pp_instance());
440 ASSERT_TRUE(ws);
441 int32_t result = websocket_interface_->Connect(
442 ws, url, good_protocols, 2U, PP_BlockUntilComplete());
443 ASSERT_EQ(PP_ERROR_BLOCKS_MAIN_THREAD, result);
444 core_interface_->ReleaseResource(ws);
446 ReleaseVar(url);
447 for (int i = 0; i < 2; ++i) {
448 ReleaseVar(bad_protocols[i]);
449 ReleaseVar(good_protocols[i]);
451 core_interface_->ReleaseResource(ws);
453 PASS();
456 std::string TestWebSocket::TestGetURL() {
457 for (int i = 0; kInvalidURLs[i]; ++i) {
458 int32_t result;
459 PP_Resource ws = Connect(kInvalidURLs[i], &result, std::string());
460 ASSERT_TRUE(ws);
461 PP_Var url = websocket_interface_->GetURL(ws);
462 ASSERT_TRUE(AreEqualWithString(url, kInvalidURLs[i]));
463 ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
465 ReleaseVar(url);
466 core_interface_->ReleaseResource(ws);
469 PASS();
472 std::string TestWebSocket::TestValidConnect() {
473 int32_t result;
474 PP_Resource ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
475 ASSERT_TRUE(ws);
476 ASSERT_EQ(PP_OK, result);
477 PP_Var extensions = websocket_interface_->GetExtensions(ws);
478 ASSERT_TRUE(AreEqualWithString(extensions, std::string()));
479 core_interface_->ReleaseResource(ws);
480 ReleaseVar(extensions);
482 PASS();
485 std::string TestWebSocket::TestInvalidClose() {
486 PP_Var reason = CreateVarString("close for test");
487 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
488 TestCompletionCallback async_callback(instance_->pp_instance(), PP_REQUIRED);
490 // Close before connect.
491 PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
492 callback.WaitForResult(websocket_interface_->Close(
493 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
494 callback.GetCallback().pp_completion_callback()));
495 ASSERT_EQ(PP_ERROR_FAILED, callback.result());
496 core_interface_->ReleaseResource(ws);
498 // Close with bad arguments.
499 int32_t result;
500 ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
501 ASSERT_TRUE(ws);
502 ASSERT_EQ(PP_OK, result);
503 callback.WaitForResult(websocket_interface_->Close(
504 ws, 1U, reason, callback.GetCallback().pp_completion_callback()));
505 ASSERT_EQ(PP_ERROR_NOACCESS, callback.result());
506 core_interface_->ReleaseResource(ws);
508 // Close with PP_VARTYPE_NULL.
509 ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
510 ASSERT_TRUE(ws);
511 ASSERT_EQ(PP_OK, result);
512 callback.WaitForResult(websocket_interface_->Close(
513 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeNull(),
514 callback.GetCallback().pp_completion_callback()));
515 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
516 core_interface_->ReleaseResource(ws);
518 // Close with PP_VARTYPE_NULL and ongoing receive message.
519 ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
520 ASSERT_TRUE(ws);
521 ASSERT_EQ(PP_OK, result);
522 PP_Var receive_message_var;
523 result = websocket_interface_->ReceiveMessage(
524 ws, &receive_message_var,
525 async_callback.GetCallback().pp_completion_callback());
526 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
527 callback.WaitForResult(websocket_interface_->Close(
528 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeNull(),
529 callback.GetCallback().pp_completion_callback()));
530 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
531 const char* send_message = "hi";
532 PP_Var send_message_var = CreateVarString(send_message);
533 result = websocket_interface_->SendMessage(ws, send_message_var);
534 ReleaseVar(send_message_var);
535 ASSERT_EQ(PP_OK, result);
536 async_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
537 ASSERT_EQ(PP_OK, async_callback.result());
538 ASSERT_TRUE(AreEqualWithString(receive_message_var, send_message));
539 ReleaseVar(receive_message_var);
540 core_interface_->ReleaseResource(ws);
542 // Close twice.
543 ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
544 ASSERT_TRUE(ws);
545 ASSERT_EQ(PP_OK, result);
546 result = websocket_interface_->Close(
547 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
548 async_callback.GetCallback().pp_completion_callback());
549 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
550 // Call another Close() before previous one is in progress.
551 result = websocket_interface_->Close(
552 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
553 callback.GetCallback().pp_completion_callback());
554 ASSERT_EQ(PP_ERROR_INPROGRESS, result);
555 async_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
556 ASSERT_EQ(PP_OK, async_callback.result());
557 // Call another Close() after previous one is completed.
558 // This Close() must do nothing and reports no error.
559 callback.WaitForResult(websocket_interface_->Close(
560 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
561 callback.GetCallback().pp_completion_callback()));
562 ASSERT_EQ(PP_OK, callback.result());
563 core_interface_->ReleaseResource(ws);
565 ReleaseVar(reason);
567 PASS();
570 std::string TestWebSocket::TestValidClose() {
571 PP_Var reason = CreateVarString("close for test");
572 PP_Var url = CreateVarString(GetFullURL(kEchoServerURL).c_str());
573 PP_Var protocols[] = { PP_MakeUndefined() };
574 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
575 TestCompletionCallback another_callback(
576 instance_->pp_instance(), callback_type());
578 // Close.
579 int32_t result;
580 PP_Resource ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
581 ASSERT_TRUE(ws);
582 ASSERT_EQ(PP_OK, result);
583 callback.WaitForResult(websocket_interface_->Close(
584 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
585 callback.GetCallback().pp_completion_callback()));
586 CHECK_CALLBACK_BEHAVIOR(callback);
587 ASSERT_EQ(PP_OK, callback.result());
588 core_interface_->ReleaseResource(ws);
590 // Close without code and reason.
591 ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
592 ASSERT_TRUE(ws);
593 ASSERT_EQ(PP_OK, result);
594 callback.WaitForResult(websocket_interface_->Close(
595 ws, PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED, reason,
596 callback.GetCallback().pp_completion_callback()));
597 ASSERT_EQ(PP_OK, callback.result());
598 core_interface_->ReleaseResource(ws);
600 // Close with PP_VARTYPE_UNDEFINED.
601 ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
602 ASSERT_TRUE(ws);
603 ASSERT_EQ(PP_OK, result);
604 callback.WaitForResult(websocket_interface_->Close(
605 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(),
606 callback.GetCallback().pp_completion_callback()));
607 CHECK_CALLBACK_BEHAVIOR(callback);
608 ASSERT_EQ(PP_OK, callback.result());
609 core_interface_->ReleaseResource(ws);
611 // Close in connecting.
612 // The ongoing connect failed with PP_ERROR_ABORTED, then the close is done
613 // successfully.
614 ws = websocket_interface_->Create(instance_->pp_instance());
615 result = websocket_interface_->Connect(
616 ws, url, protocols, 0U, callback.GetCallback().pp_completion_callback());
617 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
618 result = websocket_interface_->Close(
619 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
620 another_callback.GetCallback().pp_completion_callback());
621 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
622 callback.WaitForResult(PP_OK_COMPLETIONPENDING);
623 ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
624 another_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
625 ASSERT_EQ(PP_OK, another_callback.result());
626 core_interface_->ReleaseResource(ws);
628 // Close in closing.
629 // The first close will be done successfully, then the second one failed with
630 // with PP_ERROR_INPROGRESS immediately.
631 ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
632 ASSERT_TRUE(ws);
633 ASSERT_EQ(PP_OK, result);
634 result = websocket_interface_->Close(
635 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
636 callback.GetCallback().pp_completion_callback());
637 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
638 result = websocket_interface_->Close(
639 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
640 another_callback.GetCallback().pp_completion_callback());
641 ASSERT_EQ(PP_ERROR_INPROGRESS, result);
642 callback.WaitForResult(PP_OK_COMPLETIONPENDING);
643 ASSERT_EQ(PP_OK, callback.result());
644 core_interface_->ReleaseResource(ws);
646 // Close with ongoing receive message.
647 ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
648 ASSERT_TRUE(ws);
649 ASSERT_EQ(PP_OK, result);
650 PP_Var receive_message_var;
651 result = websocket_interface_->ReceiveMessage(
652 ws, &receive_message_var,
653 callback.GetCallback().pp_completion_callback());
654 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
655 result = websocket_interface_->Close(
656 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
657 another_callback.GetCallback().pp_completion_callback());
658 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
659 callback.WaitForResult(PP_OK_COMPLETIONPENDING);
660 ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
661 another_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
662 ASSERT_EQ(PP_OK, another_callback.result());
663 core_interface_->ReleaseResource(ws);
665 // Close with PP_VARTYPE_UNDEFINED and ongoing receive message.
666 ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
667 ASSERT_TRUE(ws);
668 ASSERT_EQ(PP_OK, result);
669 result = websocket_interface_->ReceiveMessage(
670 ws, &receive_message_var,
671 callback.GetCallback().pp_completion_callback());
672 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
673 result = websocket_interface_->Close(
674 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(),
675 another_callback.GetCallback().pp_completion_callback());
676 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
677 callback.WaitForResult(PP_OK_COMPLETIONPENDING);
678 ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
679 another_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
680 ASSERT_EQ(PP_OK, another_callback.result());
681 core_interface_->ReleaseResource(ws);
683 // Server initiated closing handshake.
684 ws = Connect(
685 GetFullURL(kCloseWithCodeAndReasonServerURL), &result, std::string());
686 ASSERT_TRUE(ws);
687 ASSERT_EQ(PP_OK, result);
688 // Text messsage "1000 bye" requests the server to initiate closing handshake
689 // with code being 1000 and reason being "bye".
690 PP_Var close_request_var = CreateVarString("1000 bye");
691 result = websocket_interface_->SendMessage(ws, close_request_var);
692 ReleaseVar(close_request_var);
693 callback.WaitForResult(websocket_interface_->ReceiveMessage(
694 ws, &receive_message_var,
695 callback.GetCallback().pp_completion_callback()));
696 ASSERT_EQ(PP_ERROR_FAILED, callback.result());
697 core_interface_->ReleaseResource(ws);
699 ReleaseVar(reason);
700 ReleaseVar(url);
702 PASS();
705 std::string TestWebSocket::TestGetProtocol() {
706 const char* expected_protocols[] = {
707 "x-chat",
708 "hoehoe",
709 NULL
711 for (int i = 0; expected_protocols[i]; ++i) {
712 std::string url(GetFullURL(kProtocolTestServerURL));
713 url += expected_protocols[i];
714 int32_t result;
715 PP_Resource ws = Connect(url.c_str(), &result, expected_protocols[i]);
716 ASSERT_TRUE(ws);
717 ASSERT_EQ(PP_OK, result);
719 PP_Var protocol = websocket_interface_->GetProtocol(ws);
720 ASSERT_TRUE(AreEqualWithString(protocol, expected_protocols[i]));
722 ReleaseVar(protocol);
723 core_interface_->ReleaseResource(ws);
726 PASS();
729 std::string TestWebSocket::TestTextSendReceive() {
730 // Connect to test echo server.
731 int32_t connect_result;
732 PP_Resource ws =
733 Connect(GetFullURL(kEchoServerURL), &connect_result, std::string());
734 ASSERT_TRUE(ws);
735 ASSERT_EQ(PP_OK, connect_result);
737 // Send 'hello pepper' text message.
738 const char* message = "hello pepper";
739 PP_Var message_var = CreateVarString(message);
740 int32_t result = websocket_interface_->SendMessage(ws, message_var);
741 ReleaseVar(message_var);
742 ASSERT_EQ(PP_OK, result);
744 // Receive echoed 'hello pepper'.
745 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
746 PP_Var received_message;
747 callback.WaitForResult(websocket_interface_->ReceiveMessage(
748 ws, &received_message, callback.GetCallback().pp_completion_callback()));
749 ASSERT_EQ(PP_OK, callback.result());
750 ASSERT_TRUE(AreEqualWithString(received_message, message));
751 ReleaseVar(received_message);
752 core_interface_->ReleaseResource(ws);
754 PASS();
757 // Run as a BACKGROUND test.
758 std::string TestWebSocket::TestTextSendReceiveTwice() {
759 // Connect to test echo server.
760 int32_t connect_result;
761 PP_Resource ws =
762 Connect(GetFullURL(kEchoServerURL), &connect_result, std::string());
763 ASSERT_TRUE(ws);
764 ASSERT_EQ(PP_OK, connect_result);
765 pp::MessageLoop message_loop = pp::MessageLoop::GetCurrent();
766 pp::CompletionCallbackFactory<TestWebSocket> factory(this);
768 message_loop.PostWork(factory.NewCallback(&TestWebSocket::Send,
769 ws, std::string("hello")));
770 // When the server receives 'Goodbye', it closes the session.
771 message_loop.PostWork(factory.NewCallback(&TestWebSocket::Send,
772 ws, std::string("Goodbye")));
773 message_loop.PostQuit(false);
774 message_loop.Run();
776 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
777 PP_Var received_message;
778 int32_t result = websocket_interface_->ReceiveMessage(
779 ws, &received_message, callback.GetCallback().pp_completion_callback());
780 ASSERT_EQ(PP_OK, result);
781 // Since we don't run the message loop, the callback will stay
782 // "pending and scheduled to run" state.
784 // Waiting for the connection close which will be done by the server.
785 while (true) {
786 PP_WebSocketReadyState ready_state =
787 websocket_interface_->GetReadyState(ws);
788 if (ready_state != PP_WEBSOCKETREADYSTATE_CONNECTING &&
789 ready_state != PP_WEBSOCKETREADYSTATE_OPEN) {
790 break;
792 PlatformSleep(100); // 100ms
795 // Cleanup the message loop
796 message_loop.PostQuit(false);
797 message_loop.Run();
799 ASSERT_EQ(PP_OK, callback.result());
800 ASSERT_TRUE(AreEqualWithString(received_message, "hello"));
801 ReleaseVar(received_message);
802 core_interface_->ReleaseResource(ws);
803 PASS();
806 std::string TestWebSocket::TestBinarySendReceive() {
807 // Connect to test echo server.
808 int32_t connect_result;
809 PP_Resource ws =
810 Connect(GetFullURL(kEchoServerURL), &connect_result, std::string());
811 ASSERT_TRUE(ws);
812 ASSERT_EQ(PP_OK, connect_result);
814 // Send binary message.
815 std::vector<uint8_t> binary(256);
816 for (uint32_t i = 0; i < binary.size(); ++i)
817 binary[i] = i;
818 PP_Var message_var = CreateVarBinary(binary);
819 int32_t result = websocket_interface_->SendMessage(ws, message_var);
820 ReleaseVar(message_var);
821 ASSERT_EQ(PP_OK, result);
823 // Receive echoed binary.
824 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
825 PP_Var received_message;
826 callback.WaitForResult(websocket_interface_->ReceiveMessage(
827 ws, &received_message, callback.GetCallback().pp_completion_callback()));
828 ASSERT_EQ(PP_OK, callback.result());
829 ASSERT_TRUE(AreEqualWithBinary(received_message, binary));
830 ReleaseVar(received_message);
831 core_interface_->ReleaseResource(ws);
833 PASS();
836 std::string TestWebSocket::TestStressedSendReceive() {
837 // Connect to test echo server.
838 int32_t connect_result;
839 PP_Resource ws =
840 Connect(GetFullURL(kEchoServerURL), &connect_result, std::string());
841 ASSERT_TRUE(ws);
842 ASSERT_EQ(PP_OK, connect_result);
844 // Prepare PP_Var objects to send.
845 const char* text = "hello pepper";
846 PP_Var text_var = CreateVarString(text);
847 std::vector<uint8_t> binary(256);
848 for (uint32_t i = 0; i < binary.size(); ++i)
849 binary[i] = i;
850 PP_Var binary_var = CreateVarBinary(binary);
851 // Prepare very large binary data over 64KiB. Object serializer in
852 // ppapi_proxy has a limitation of 64KiB as maximum return PP_Var data size
853 // to SRPC. In case received data over 64KiB exists, a specific code handles
854 // this large data via asynchronous callback from main thread. This data
855 // intends to test the code.
856 std::vector<uint8_t> large_binary(65 * 1024);
857 for (uint32_t i = 0; i < large_binary.size(); ++i)
858 large_binary[i] = i & 0xff;
859 PP_Var large_binary_var = CreateVarBinary(large_binary);
861 // Send many messages.
862 int32_t result;
863 for (int i = 0; i < 256; ++i) {
864 result = websocket_interface_->SendMessage(ws, text_var);
865 ASSERT_EQ(PP_OK, result);
866 result = websocket_interface_->SendMessage(ws, binary_var);
867 ASSERT_EQ(PP_OK, result);
869 result = websocket_interface_->SendMessage(ws, large_binary_var);
870 ASSERT_EQ(PP_OK, result);
871 ReleaseVar(text_var);
872 ReleaseVar(binary_var);
873 ReleaseVar(large_binary_var);
875 // Receive echoed data.
876 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
877 for (int i = 0; i <= 512; ++i) {
878 PP_Var received_message;
879 callback.WaitForResult(websocket_interface_->ReceiveMessage(
880 ws, &received_message,
881 callback.GetCallback().pp_completion_callback()));
882 ASSERT_EQ(PP_OK, callback.result());
883 if (i == 512) {
884 ASSERT_TRUE(AreEqualWithBinary(received_message, large_binary));
885 } else if (i & 1) {
886 ASSERT_TRUE(AreEqualWithBinary(received_message, binary));
887 } else {
888 ASSERT_TRUE(AreEqualWithString(received_message, text));
890 ReleaseVar(received_message);
892 core_interface_->ReleaseResource(ws);
894 PASS();
897 std::string TestWebSocket::TestBufferedAmount() {
898 // Connect to test echo server.
899 int32_t connect_result;
900 PP_Resource ws =
901 Connect(GetFullURL(kEchoServerURL), &connect_result, std::string());
902 ASSERT_TRUE(ws);
903 ASSERT_EQ(PP_OK, connect_result);
905 // Prepare a large message that is not aligned with the internal buffer
906 // sizes.
907 std::string message(8193, 'x');
908 PP_Var message_var = CreateVarString(message);
910 uint64_t buffered_amount = 0;
911 int32_t result;
912 for (int i = 0; i < 100; i++) {
913 result = websocket_interface_->SendMessage(ws, message_var);
914 ASSERT_EQ(PP_OK, result);
915 buffered_amount = websocket_interface_->GetBufferedAmount(ws);
916 // Buffered amount size 262144 is too big for the internal buffer size.
917 if (buffered_amount > 262144)
918 break;
921 // Close connection.
922 std::string reason_str = "close while busy";
923 PP_Var reason = CreateVarString(reason_str.c_str());
924 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
925 result = websocket_interface_->Close(
926 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
927 callback.GetCallback().pp_completion_callback());
928 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
929 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSING,
930 websocket_interface_->GetReadyState(ws));
932 callback.WaitForResult(result);
933 ASSERT_EQ(PP_OK, callback.result());
934 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED,
935 websocket_interface_->GetReadyState(ws));
937 uint64_t base_buffered_amount = websocket_interface_->GetBufferedAmount(ws);
939 // After connection closure, all sending requests fail and just increase
940 // the bufferedAmount property.
941 PP_Var empty_string = CreateVarString(std::string());
942 result = websocket_interface_->SendMessage(ws, empty_string);
943 ASSERT_EQ(PP_ERROR_FAILED, result);
944 buffered_amount = websocket_interface_->GetBufferedAmount(ws);
945 ASSERT_EQ(base_buffered_amount + kMessageFrameOverhead, buffered_amount);
946 base_buffered_amount = buffered_amount;
948 result = websocket_interface_->SendMessage(ws, reason);
949 ASSERT_EQ(PP_ERROR_FAILED, result);
950 buffered_amount = websocket_interface_->GetBufferedAmount(ws);
951 uint64_t reason_frame_size = kMessageFrameOverhead + reason_str.length();
952 ASSERT_EQ(base_buffered_amount + reason_frame_size, buffered_amount);
954 ReleaseVar(message_var);
955 ReleaseVar(reason);
956 ReleaseVar(empty_string);
957 core_interface_->ReleaseResource(ws);
959 PASS();
962 // Test abort behaviors where a WebSocket PP_Resource is released while each
963 // function is in-flight on the WebSocket PP_Resource.
964 std::string TestWebSocket::TestAbortCallsWithCallback() {
965 // Following tests make sure the behavior for functions which require a
966 // callback. The callback must get a PP_ERROR_ABORTED.
968 // Test the behavior for Connect().
969 PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
970 ASSERT_TRUE(ws);
971 std::string url = GetFullURL(kEchoServerURL);
972 PP_Var url_var = CreateVarString(url);
973 TestCompletionCallback connect_callback(
974 instance_->pp_instance(), callback_type());
975 int32_t result = websocket_interface_->Connect(
976 ws, url_var, NULL, 0,
977 connect_callback.GetCallback().pp_completion_callback());
978 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
979 core_interface_->ReleaseResource(ws);
980 connect_callback.WaitForResult(result);
981 ASSERT_EQ(PP_ERROR_ABORTED, connect_callback.result());
983 // Test the behavior for Close().
984 ws = Connect(url, &result, std::string());
985 ASSERT_TRUE(ws);
986 ASSERT_EQ(PP_OK, result);
987 PP_Var reason_var = CreateVarString("abort");
988 TestCompletionCallback close_callback(
989 instance_->pp_instance(), callback_type());
990 result = websocket_interface_->Close(
991 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason_var,
992 close_callback.GetCallback().pp_completion_callback());
993 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
994 core_interface_->ReleaseResource(ws);
995 close_callback.WaitForResult(result);
996 ASSERT_EQ(PP_ERROR_ABORTED, close_callback.result());
997 ReleaseVar(reason_var);
999 // Test the behavior for ReceiveMessage().
1000 // Make sure the simplest case to wait for data which never arrives, here.
1001 ws = Connect(url, &result, std::string());
1002 ASSERT_TRUE(ws);
1003 ASSERT_EQ(PP_OK, result);
1004 PP_Var receive_var;
1005 TestCompletionCallback receive_callback(
1006 instance_->pp_instance(), callback_type());
1007 result = websocket_interface_->ReceiveMessage(
1008 ws, &receive_var,
1009 receive_callback.GetCallback().pp_completion_callback());
1010 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1011 core_interface_->ReleaseResource(ws);
1012 receive_callback.WaitForResult(result);
1013 ASSERT_EQ(PP_ERROR_ABORTED, receive_callback.result());
1015 // Release the resource in the aborting receive completion callback which is
1016 // introduced by calling Close().
1017 ws = Connect(url, &result, std::string());
1018 ASSERT_TRUE(ws);
1019 ASSERT_EQ(PP_OK, result);
1020 result = websocket_interface_->ReceiveMessage(
1021 ws, &receive_var,
1022 receive_callback.GetCallback().pp_completion_callback());
1023 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1024 ReleaseResourceDelegate receive_delegate(core_interface_, ws);
1025 receive_callback.SetDelegate(&receive_delegate);
1026 result = websocket_interface_->Close(
1027 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(),
1028 close_callback.GetCallback().pp_completion_callback());
1029 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1030 receive_callback.WaitForResult(result);
1031 CHECK_CALLBACK_BEHAVIOR(receive_callback);
1032 ASSERT_EQ(PP_ERROR_ABORTED, receive_callback.result());
1033 close_callback.WaitForResult(result);
1034 CHECK_CALLBACK_BEHAVIOR(close_callback);
1035 ASSERT_EQ(PP_ERROR_ABORTED, close_callback.result());
1037 ReleaseVar(url_var);
1039 PASS();
1042 std::string TestWebSocket::TestAbortSendMessageCall() {
1043 // Test the behavior for SendMessage().
1044 // This function doesn't require a callback, but operation will be done
1045 // asynchronously in WebKit and browser process.
1046 std::vector<uint8_t> large_binary(65 * 1024);
1047 PP_Var large_var = CreateVarBinary(large_binary);
1049 int32_t result;
1050 std::string url = GetFullURL(kEchoServerURL);
1051 PP_Resource ws = Connect(url, &result, std::string());
1052 ASSERT_TRUE(ws);
1053 ASSERT_EQ(PP_OK, result);
1054 result = websocket_interface_->SendMessage(ws, large_var);
1055 ASSERT_EQ(PP_OK, result);
1056 core_interface_->ReleaseResource(ws);
1057 ReleaseVar(large_var);
1059 PASS();
1062 std::string TestWebSocket::TestAbortCloseCall() {
1063 // Release the resource in the close completion callback.
1064 int32_t result;
1065 std::string url = GetFullURL(kEchoServerURL);
1066 PP_Resource ws = Connect(url, &result, std::string());
1067 ASSERT_TRUE(ws);
1068 ASSERT_EQ(PP_OK, result);
1069 TestCompletionCallback close_callback(
1070 instance_->pp_instance(), callback_type());
1071 result = websocket_interface_->Close(
1072 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(),
1073 close_callback.GetCallback().pp_completion_callback());
1074 ReleaseResourceDelegate close_delegate(core_interface_, ws);
1075 close_callback.SetDelegate(&close_delegate);
1076 close_callback.WaitForResult(result);
1077 CHECK_CALLBACK_BEHAVIOR(close_callback);
1078 ASSERT_EQ(PP_OK, close_callback.result());
1080 PASS();
1083 std::string TestWebSocket::TestAbortReceiveMessageCall() {
1084 // Test the behavior where receive process might be in-flight.
1085 std::vector<uint8_t> large_binary(65 * 1024);
1086 PP_Var large_var = CreateVarBinary(large_binary);
1087 const char* text = "yukarin";
1088 PP_Var text_var = CreateVarString(text);
1090 std::string url = GetFullURL(kEchoServerURL);
1091 int32_t result;
1092 PP_Resource ws;
1094 // Each trial sends |trial_count| + 1 messages and receives just |trial|
1095 // number of message(s) before releasing the WebSocket. The WebSocket is
1096 // released while the next message is going to be received.
1097 const int trial_count = 8;
1098 for (int trial = 1; trial <= trial_count; trial++) {
1099 ws = Connect(url, &result, std::string());
1100 ASSERT_TRUE(ws);
1101 ASSERT_EQ(PP_OK, result);
1102 for (int i = 0; i <= trial_count; ++i) {
1103 result = websocket_interface_->SendMessage(ws, text_var);
1104 ASSERT_EQ(PP_OK, result);
1106 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
1107 PP_Var var;
1108 for (int i = 0; i < trial; ++i) {
1109 callback.WaitForResult(websocket_interface_->ReceiveMessage(
1110 ws, &var, callback.GetCallback().pp_completion_callback()));
1111 ASSERT_EQ(PP_OK, callback.result());
1112 ASSERT_TRUE(AreEqualWithString(var, text));
1113 ReleaseVar(var);
1115 result = websocket_interface_->ReceiveMessage(
1116 ws, &var, callback.GetCallback().pp_completion_callback());
1117 core_interface_->ReleaseResource(ws);
1118 if (result != PP_OK) {
1119 callback.WaitForResult(result);
1120 ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
1123 // Same test, but the last receiving message is large message over 64KiB.
1124 for (int trial = 1; trial <= trial_count; trial++) {
1125 ws = Connect(url, &result, std::string());
1126 ASSERT_TRUE(ws);
1127 ASSERT_EQ(PP_OK, result);
1128 for (int i = 0; i <= trial_count; ++i) {
1129 if (i == trial)
1130 result = websocket_interface_->SendMessage(ws, large_var);
1131 else
1132 result = websocket_interface_->SendMessage(ws, text_var);
1133 ASSERT_EQ(PP_OK, result);
1135 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
1136 PP_Var var;
1137 for (int i = 0; i < trial; ++i) {
1138 callback.WaitForResult(websocket_interface_->ReceiveMessage(
1139 ws, &var, callback.GetCallback().pp_completion_callback()));
1140 ASSERT_EQ(PP_OK, callback.result());
1141 ASSERT_TRUE(AreEqualWithString(var, text));
1142 ReleaseVar(var);
1144 result = websocket_interface_->ReceiveMessage(
1145 ws, &var, callback.GetCallback().pp_completion_callback());
1146 core_interface_->ReleaseResource(ws);
1147 if (result != PP_OK) {
1148 callback.WaitForResult(result);
1149 ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
1153 ReleaseVar(large_var);
1154 ReleaseVar(text_var);
1156 PASS();
1159 std::string TestWebSocket::TestCcInterfaces() {
1160 // C++ bindings is simple straightforward, then just verifies interfaces work
1161 // as a interface bridge fine.
1162 pp::WebSocket ws(instance_);
1164 // Check uninitialized properties access.
1165 ASSERT_EQ(0, ws.GetBufferedAmount());
1166 ASSERT_EQ(0, ws.GetCloseCode());
1167 ASSERT_TRUE(AreEqualWithString(ws.GetCloseReason().pp_var(), std::string()));
1168 ASSERT_EQ(false, ws.GetCloseWasClean());
1169 ASSERT_TRUE(AreEqualWithString(ws.GetExtensions().pp_var(), std::string()));
1170 ASSERT_TRUE(AreEqualWithString(ws.GetProtocol().pp_var(), std::string()));
1171 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_INVALID, ws.GetReadyState());
1172 ASSERT_TRUE(AreEqualWithString(ws.GetURL().pp_var(), std::string()));
1174 // Check communication interfaces (connect, send, receive, and close).
1175 TestCompletionCallback connect_callback(
1176 instance_->pp_instance(), callback_type());
1177 connect_callback.WaitForResult(ws.Connect(
1178 pp::Var(GetFullURL(kCloseServerURL)), NULL, 0U,
1179 connect_callback.GetCallback()));
1180 CHECK_CALLBACK_BEHAVIOR(connect_callback);
1181 ASSERT_EQ(PP_OK, connect_callback.result());
1183 std::string text_message("hello C++");
1184 int32_t result = ws.SendMessage(pp::Var(text_message));
1185 ASSERT_EQ(PP_OK, result);
1187 std::vector<uint8_t> binary(256);
1188 for (uint32_t i = 0; i < binary.size(); ++i)
1189 binary[i] = i;
1190 result = ws.SendMessage(
1191 pp::Var(pp::PASS_REF, CreateVarBinary(binary)));
1192 ASSERT_EQ(PP_OK, result);
1194 pp::Var text_receive_var;
1195 TestCompletionCallback text_receive_callback(
1196 instance_->pp_instance(), callback_type());
1197 text_receive_callback.WaitForResult(
1198 ws.ReceiveMessage(&text_receive_var,
1199 text_receive_callback.GetCallback()));
1200 ASSERT_EQ(PP_OK, text_receive_callback.result());
1201 ASSERT_TRUE(
1202 AreEqualWithString(text_receive_var.pp_var(), text_message.c_str()));
1204 pp::Var binary_receive_var;
1205 TestCompletionCallback binary_receive_callback(
1206 instance_->pp_instance(), callback_type());
1207 binary_receive_callback.WaitForResult(
1208 ws.ReceiveMessage(&binary_receive_var,
1209 binary_receive_callback.GetCallback()));
1210 ASSERT_EQ(PP_OK, binary_receive_callback.result());
1211 ASSERT_TRUE(AreEqualWithBinary(binary_receive_var.pp_var(), binary));
1213 TestCompletionCallback close_callback(
1214 instance_->pp_instance(), callback_type());
1215 std::string reason("bye");
1216 close_callback.WaitForResult(ws.Close(
1217 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason),
1218 close_callback.GetCallback()));
1219 CHECK_CALLBACK_BEHAVIOR(close_callback);
1220 ASSERT_EQ(PP_OK, close_callback.result());
1222 // Check initialized properties access.
1223 ASSERT_EQ(0, ws.GetBufferedAmount());
1224 ASSERT_EQ(PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, ws.GetCloseCode());
1225 ASSERT_TRUE(
1226 AreEqualWithString(ws.GetCloseReason().pp_var(), reason.c_str()));
1227 ASSERT_EQ(true, ws.GetCloseWasClean());
1228 ASSERT_TRUE(AreEqualWithString(ws.GetProtocol().pp_var(), std::string()));
1229 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED, ws.GetReadyState());
1230 ASSERT_TRUE(AreEqualWithString(
1231 ws.GetURL().pp_var(), GetFullURL(kCloseServerURL).c_str()));
1233 PASS();
1236 std::string TestWebSocket::TestUtilityInvalidConnect() {
1237 const pp::Var protocols[] = { pp::Var() };
1239 TestWebSocketAPI websocket(instance_);
1240 int32_t result = websocket.Connect(pp::Var(), protocols, 1U);
1241 ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
1242 ASSERT_EQ(0U, websocket.GetSeenEvents().size());
1244 result = websocket.Connect(pp::Var(), protocols, 1U);
1245 ASSERT_EQ(PP_ERROR_INPROGRESS, result);
1246 ASSERT_EQ(0U, websocket.GetSeenEvents().size());
1248 for (int i = 0; kInvalidURLs[i]; ++i) {
1249 TestWebSocketAPI ws(instance_);
1250 result = ws.Connect(pp::Var(std::string(kInvalidURLs[i])), protocols, 0U);
1251 if (result == PP_OK_COMPLETIONPENDING) {
1252 ws.WaitForClosed();
1253 const std::vector<WebSocketEvent>& events = ws.GetSeenEvents();
1254 ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[0].event_type);
1255 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type);
1256 ASSERT_EQ(2U, ws.GetSeenEvents().size());
1257 } else {
1258 ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
1259 ASSERT_EQ(0U, ws.GetSeenEvents().size());
1263 PASS();
1266 std::string TestWebSocket::TestUtilityProtocols() {
1267 const pp::Var bad_protocols[] = {
1268 pp::Var(std::string("x-test")), pp::Var(std::string("x-test")) };
1269 const pp::Var good_protocols[] = {
1270 pp::Var(std::string("x-test")), pp::Var(std::string("x-yatest")) };
1273 TestWebSocketAPI websocket(instance_);
1274 int32_t result = websocket.Connect(
1275 pp::Var(GetFullURL(kEchoServerURL)), bad_protocols, 2U);
1276 ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
1277 ASSERT_EQ(0U, websocket.GetSeenEvents().size());
1281 TestWebSocketAPI websocket(instance_);
1282 int32_t result = websocket.Connect(
1283 pp::Var(GetFullURL(kEchoServerURL)), good_protocols, 2U);
1284 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1285 websocket.WaitForConnected();
1286 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1287 // Protocol arguments are valid, but this test run without a WebSocket
1288 // server. As a result, OnError() and OnClose() are invoked because of
1289 // a connection establishment failure.
1290 ASSERT_EQ(2U, events.size());
1291 ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[0].event_type);
1292 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type);
1293 ASSERT_FALSE(events[1].was_clean);
1296 PASS();
1299 std::string TestWebSocket::TestUtilityGetURL() {
1300 const pp::Var protocols[] = { pp::Var() };
1302 for (int i = 0; kInvalidURLs[i]; ++i) {
1303 TestWebSocketAPI websocket(instance_);
1304 int32_t result = websocket.Connect(
1305 pp::Var(std::string(kInvalidURLs[i])), protocols, 0U);
1306 if (result == PP_OK_COMPLETIONPENDING) {
1307 websocket.WaitForClosed();
1308 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1309 ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[0].event_type);
1310 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type);
1311 ASSERT_EQ(2U, events.size());
1312 } else {
1313 ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
1314 ASSERT_EQ(0U, websocket.GetSeenEvents().size());
1316 pp::Var url = websocket.GetURL();
1317 ASSERT_TRUE(AreEqualWithString(url.pp_var(), kInvalidURLs[i]));
1320 PASS();
1323 std::string TestWebSocket::TestUtilityValidConnect() {
1324 const pp::Var protocols[] = { pp::Var() };
1325 TestWebSocketAPI websocket(instance_);
1326 int32_t result = websocket.Connect(
1327 pp::Var(GetFullURL(kEchoServerURL)), protocols, 0U);
1328 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1329 websocket.WaitForConnected();
1330 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1331 ASSERT_EQ(1U, events.size());
1332 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1333 ASSERT_TRUE(
1334 AreEqualWithString(websocket.GetExtensions().pp_var(), std::string()));
1336 PASS();
1339 std::string TestWebSocket::TestUtilityInvalidClose() {
1340 const pp::Var reason = pp::Var(std::string("close for test"));
1342 // Close before connect.
1344 TestWebSocketAPI websocket(instance_);
1345 int32_t result = websocket.Close(
1346 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason);
1347 ASSERT_EQ(PP_ERROR_FAILED, result);
1348 ASSERT_EQ(0U, websocket.GetSeenEvents().size());
1351 // Close with bad arguments.
1353 TestWebSocketAPI websocket(instance_);
1354 int32_t result = websocket.Connect(pp::Var(GetFullURL(kEchoServerURL)),
1355 NULL, 0);
1356 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1357 websocket.WaitForConnected();
1358 result = websocket.Close(1U, reason);
1359 ASSERT_EQ(PP_ERROR_NOACCESS, result);
1360 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1361 ASSERT_EQ(1U, events.size());
1362 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1365 PASS();
1368 std::string TestWebSocket::TestUtilityValidClose() {
1369 std::string reason("close for test");
1370 pp::Var url = pp::Var(GetFullURL(kCloseServerURL));
1372 // Close.
1374 TestWebSocketAPI websocket(instance_);
1375 int32_t result = websocket.Connect(url, NULL, 0U);
1376 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1377 websocket.WaitForConnected();
1378 result = websocket.Close(
1379 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
1380 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1381 websocket.WaitForClosed();
1382 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1383 ASSERT_EQ(2U, events.size());
1384 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1385 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type);
1386 ASSERT_TRUE(events[1].was_clean);
1387 ASSERT_EQ(PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, events[1].close_code);
1388 ASSERT_TRUE(AreEqualWithString(events[1].var.pp_var(), reason.c_str()));
1391 // Close in connecting.
1392 // The ongoing connect failed with PP_ERROR_ABORTED, then the close is done
1393 // successfully.
1395 TestWebSocketAPI websocket(instance_);
1396 int32_t result = websocket.Connect(url, NULL, 0U);
1397 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1398 result = websocket.Close(
1399 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
1400 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1401 websocket.WaitForClosed();
1402 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1403 ASSERT_TRUE(events.size() == 2 || events.size() == 3);
1404 int index = 0;
1405 if (events.size() == 3)
1406 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[index++].event_type);
1407 ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[index++].event_type);
1408 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[index].event_type);
1409 ASSERT_FALSE(events[index].was_clean);
1412 // Close in closing.
1413 // The first close will be done successfully, then the second one failed with
1414 // with PP_ERROR_INPROGRESS immediately.
1416 TestWebSocketAPI websocket(instance_);
1417 int32_t result = websocket.Connect(url, NULL, 0U);
1418 result = websocket.Close(
1419 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
1420 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1421 result = websocket.Close(
1422 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
1423 ASSERT_EQ(PP_ERROR_INPROGRESS, result);
1424 websocket.WaitForClosed();
1425 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1426 ASSERT_TRUE(events.size() == 2 || events.size() == 3);
1427 int index = 0;
1428 if (events.size() == 3)
1429 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[index++].event_type);
1430 ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[index++].event_type);
1431 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[index].event_type);
1432 ASSERT_FALSE(events[index].was_clean);
1435 PASS();
1438 std::string TestWebSocket::TestUtilityGetProtocol() {
1439 const std::string protocol("x-chat");
1440 const pp::Var protocols[] = { pp::Var(protocol) };
1441 std::string url(GetFullURL(kProtocolTestServerURL));
1442 url += protocol;
1443 TestWebSocketAPI websocket(instance_);
1444 int32_t result = websocket.Connect(pp::Var(url), protocols, 1U);
1445 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1446 websocket.WaitForReceived();
1447 ASSERT_TRUE(AreEqualWithString(
1448 websocket.GetProtocol().pp_var(), protocol.c_str()));
1449 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1450 // The server to which this test connect returns the decided protocol as a
1451 // text frame message. So the WebSocketEvent records EVENT_MESSAGE event
1452 // after EVENT_OPEN event.
1453 ASSERT_EQ(2U, events.size());
1454 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1455 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type);
1456 ASSERT_TRUE(AreEqualWithString(events[1].var.pp_var(), protocol.c_str()));
1458 PASS();
1461 std::string TestWebSocket::TestUtilityTextSendReceive() {
1462 const pp::Var protocols[] = { pp::Var() };
1463 TestWebSocketAPI websocket(instance_);
1464 int32_t result =
1465 websocket.Connect(pp::Var(GetFullURL(kEchoServerURL)), protocols, 0U);
1466 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1467 websocket.WaitForConnected();
1469 // Send 'hello pepper'.
1470 std::string message1("hello pepper");
1471 result = websocket.Send(pp::Var(std::string(message1)));
1472 ASSERT_EQ(PP_OK, result);
1474 // Receive echoed 'hello pepper'.
1475 websocket.WaitForReceived();
1477 // Send 'goodbye pepper'.
1478 std::string message2("goodbye pepper");
1479 result = websocket.Send(pp::Var(std::string(message2)));
1481 // Receive echoed 'goodbye pepper'.
1482 websocket.WaitForReceived();
1484 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1485 ASSERT_EQ(3U, events.size());
1486 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1487 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type);
1488 ASSERT_TRUE(AreEqualWithString(events[1].var.pp_var(), message1.c_str()));
1489 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[2].event_type);
1490 ASSERT_TRUE(AreEqualWithString(events[2].var.pp_var(), message2.c_str()));
1492 PASS();
1495 std::string TestWebSocket::TestUtilityBinarySendReceive() {
1496 const pp::Var protocols[] = { pp::Var() };
1497 TestWebSocketAPI websocket(instance_);
1498 int32_t result =
1499 websocket.Connect(pp::Var(GetFullURL(kEchoServerURL)), protocols, 0U);
1500 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1501 websocket.WaitForConnected();
1503 // Send binary message.
1504 uint32_t len = 256;
1505 std::vector<uint8_t> binary(len);
1506 for (uint32_t i = 0; i < len; ++i)
1507 binary[i] = i;
1508 pp::VarArrayBuffer message(len);
1509 uint8_t* var_data = static_cast<uint8_t*>(message.Map());
1510 std::copy(binary.begin(), binary.end(), var_data);
1511 result = websocket.Send(message);
1512 ASSERT_EQ(PP_OK, result);
1514 // Receive echoed binary message.
1515 websocket.WaitForReceived();
1517 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1518 ASSERT_EQ(2U, events.size());
1519 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1520 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type);
1521 ASSERT_TRUE(AreEqualWithBinary(events[1].var.pp_var(), binary));
1523 PASS();
1526 std::string TestWebSocket::TestUtilityBufferedAmount() {
1527 // Connect to test echo server.
1528 const pp::Var protocols[] = { pp::Var() };
1529 TestWebSocketAPI websocket(instance_);
1530 int32_t result =
1531 websocket.Connect(pp::Var(GetFullURL(kEchoServerURL)), protocols, 0U);
1532 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1533 websocket.WaitForConnected();
1535 // Prepare a large message that is not aligned with the internal buffer
1536 // sizes.
1537 std::string message(8193, 'x');
1538 uint64_t buffered_amount = 0;
1539 uint32_t sent;
1540 for (sent = 0; sent < 100; sent++) {
1541 result = websocket.Send(pp::Var(message));
1542 ASSERT_EQ(PP_OK, result);
1543 buffered_amount = websocket.GetBufferedAmount();
1544 // Buffered amount size 262144 is too big for the internal buffer size.
1545 if (buffered_amount > 262144)
1546 break;
1549 // Close connection.
1550 std::string reason = "close while busy";
1551 result = websocket.Close(
1552 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
1553 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSING, websocket.GetReadyState());
1554 websocket.WaitForClosed();
1555 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED, websocket.GetReadyState());
1557 uint64_t base_buffered_amount = websocket.GetBufferedAmount();
1558 size_t events_on_closed = websocket.GetSeenEvents().size();
1560 // After connection closure, all sending requests fail and just increase
1561 // the bufferedAmount property.
1562 result = websocket.Send(pp::Var(std::string()));
1563 ASSERT_EQ(PP_ERROR_FAILED, result);
1564 buffered_amount = websocket.GetBufferedAmount();
1565 ASSERT_EQ(base_buffered_amount + kMessageFrameOverhead, buffered_amount);
1566 base_buffered_amount = buffered_amount;
1568 result = websocket.Send(pp::Var(reason));
1569 ASSERT_EQ(PP_ERROR_FAILED, result);
1570 buffered_amount = websocket.GetBufferedAmount();
1571 uint64_t reason_frame_size = kMessageFrameOverhead + reason.length();
1572 ASSERT_EQ(base_buffered_amount + reason_frame_size, buffered_amount);
1574 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1575 ASSERT_EQ(events_on_closed, events.size());
1576 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1577 size_t last_event = events_on_closed - 1;
1578 for (uint32_t i = 1; i < last_event; ++i) {
1579 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[i].event_type);
1580 ASSERT_TRUE(AreEqualWithString(events[i].var.pp_var(), message));
1582 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[last_event].event_type);
1583 ASSERT_TRUE(events[last_event].was_clean);
1585 PASS();