Refactor android test results logging.
[chromium-blink-merge.git] / ppapi / tests / test_websocket.cc
blobd5dc4863fe49e27e0b804649d8682755c7570097
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::TestServer serves WebSocket service for testing.
35 // Following URLs are handled by pywebsocket handlers in
36 // net/data/websocket/*_wsh.py.
37 const char kEchoServerURL[] = "echo-with-no-extension";
38 const char kCloseServerURL[] = "close";
39 const char kCloseWithCodeAndReasonServerURL[] = "close-code-and-reason";
40 const char kProtocolTestServerURL[] = "protocol-test?protocol=";
42 const char* const kInvalidURLs[] = {
43 "http://www.google.com/invalid_scheme",
44 "ws://www.google.com/invalid#fragment",
45 "ws://www.google.com:65535/invalid_port",
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_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://localhost";
244 // Some WebSocket tests don't start the server so there'll be no port.
245 if (instance_->websocket_port() != -1) {
246 char buffer[10];
247 sprintf(buffer, ":%d", instance_->websocket_port());
248 rv += std::string(buffer);
250 rv += "/";
251 rv += url;
252 return rv;
255 PP_Var TestWebSocket::CreateVarString(const std::string& string) {
256 return var_interface_->VarFromUtf8(string.c_str(), string.size());
259 PP_Var TestWebSocket::CreateVarBinary(const std::vector<uint8_t>& binary) {
260 PP_Var var = arraybuffer_interface_->Create(binary.size());
261 uint8_t* var_data = static_cast<uint8_t*>(arraybuffer_interface_->Map(var));
262 std::copy(binary.begin(), binary.end(), var_data);
263 return var;
266 void TestWebSocket::ReleaseVar(const PP_Var& var) {
267 var_interface_->Release(var);
270 bool TestWebSocket::AreEqualWithString(const PP_Var& var,
271 const std::string& string) {
272 if (var.type != PP_VARTYPE_STRING)
273 return false;
274 uint32_t utf8_length;
275 const char* utf8 = var_interface_->VarToUtf8(var, &utf8_length);
276 if (utf8_length != string.size())
277 return false;
278 if (string.compare(utf8))
279 return false;
280 return true;
283 bool TestWebSocket::AreEqualWithBinary(const PP_Var& var,
284 const std::vector<uint8_t>& binary) {
285 uint32_t buffer_size = 0;
286 PP_Bool success = arraybuffer_interface_->ByteLength(var, &buffer_size);
287 if (!success || buffer_size != binary.size())
288 return false;
289 if (!std::equal(binary.begin(), binary.end(),
290 static_cast<uint8_t*>(arraybuffer_interface_->Map(var))))
291 return false;
292 return true;
295 PP_Resource TestWebSocket::Connect(const std::string& url,
296 int32_t* result,
297 const std::string& protocol) {
298 PP_Var protocols[] = { PP_MakeUndefined() };
299 PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
300 if (!ws)
301 return 0;
302 PP_Var url_var = CreateVarString(url);
303 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
304 uint32_t protocol_count = 0U;
305 if (protocol.size()) {
306 protocols[0] = CreateVarString(protocol);
307 protocol_count = 1U;
309 callback.WaitForResult(websocket_interface_->Connect(
310 ws, url_var, protocols, protocol_count,
311 callback.GetCallback().pp_completion_callback()));
312 ReleaseVar(url_var);
313 if (protocol.size())
314 ReleaseVar(protocols[0]);
315 *result = callback.result();
316 return ws;
319 std::string TestWebSocket::TestIsWebSocket() {
320 // Test that a NULL resource isn't a websocket.
321 pp::Resource null_resource;
322 PP_Bool result =
323 websocket_interface_->IsWebSocket(null_resource.pp_resource());
324 ASSERT_FALSE(result);
326 PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
327 ASSERT_TRUE(ws);
329 result = websocket_interface_->IsWebSocket(ws);
330 ASSERT_TRUE(result);
332 core_interface_->ReleaseResource(ws);
334 PASS();
337 std::string TestWebSocket::TestUninitializedPropertiesAccess() {
338 PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
339 ASSERT_TRUE(ws);
341 uint64_t bufferedAmount = websocket_interface_->GetBufferedAmount(ws);
342 ASSERT_EQ(0U, bufferedAmount);
344 uint16_t close_code = websocket_interface_->GetCloseCode(ws);
345 ASSERT_EQ(0U, close_code);
347 PP_Var close_reason = websocket_interface_->GetCloseReason(ws);
348 ASSERT_TRUE(AreEqualWithString(close_reason, ""));
349 ReleaseVar(close_reason);
351 PP_Bool close_was_clean = websocket_interface_->GetCloseWasClean(ws);
352 ASSERT_EQ(PP_FALSE, close_was_clean);
354 PP_Var extensions = websocket_interface_->GetExtensions(ws);
355 ASSERT_TRUE(AreEqualWithString(extensions, ""));
356 ReleaseVar(extensions);
358 PP_Var protocol = websocket_interface_->GetProtocol(ws);
359 ASSERT_TRUE(AreEqualWithString(protocol, ""));
360 ReleaseVar(protocol);
362 PP_WebSocketReadyState ready_state =
363 websocket_interface_->GetReadyState(ws);
364 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_INVALID, ready_state);
366 PP_Var url = websocket_interface_->GetURL(ws);
367 ASSERT_TRUE(AreEqualWithString(url, ""));
368 ReleaseVar(url);
370 core_interface_->ReleaseResource(ws);
372 PASS();
375 std::string TestWebSocket::TestInvalidConnect() {
376 PP_Var protocols[] = { PP_MakeUndefined() };
378 PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
379 ASSERT_TRUE(ws);
381 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
382 callback.WaitForResult(websocket_interface_->Connect(
383 ws, PP_MakeUndefined(), protocols, 1U,
384 callback.GetCallback().pp_completion_callback()));
385 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
387 callback.WaitForResult(websocket_interface_->Connect(
388 ws, PP_MakeUndefined(), protocols, 1U,
389 callback.GetCallback().pp_completion_callback()));
390 ASSERT_EQ(PP_ERROR_INPROGRESS, callback.result());
392 core_interface_->ReleaseResource(ws);
394 for (int i = 0; kInvalidURLs[i]; ++i) {
395 int32_t result;
396 ws = Connect(kInvalidURLs[i], &result, "");
397 ASSERT_TRUE(ws);
398 ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
400 core_interface_->ReleaseResource(ws);
403 PASS();
406 std::string TestWebSocket::TestProtocols() {
407 PP_Var url = CreateVarString(GetFullURL(kEchoServerURL).c_str());
408 PP_Var bad_protocols[] = {
409 CreateVarString("x-test"),
410 CreateVarString("x-test")
412 PP_Var good_protocols[] = {
413 CreateVarString("x-test"),
414 CreateVarString("x-yatest")
417 PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
418 ASSERT_TRUE(ws);
419 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
420 callback.WaitForResult(websocket_interface_->Connect(
421 ws, url, bad_protocols, 2U,
422 callback.GetCallback().pp_completion_callback()));
423 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
424 core_interface_->ReleaseResource(ws);
426 ws = websocket_interface_->Create(instance_->pp_instance());
427 ASSERT_TRUE(ws);
428 int32_t result = websocket_interface_->Connect(
429 ws, url, good_protocols, 2U, PP_BlockUntilComplete());
430 ASSERT_EQ(PP_ERROR_BLOCKS_MAIN_THREAD, result);
431 core_interface_->ReleaseResource(ws);
433 ReleaseVar(url);
434 for (int i = 0; i < 2; ++i) {
435 ReleaseVar(bad_protocols[i]);
436 ReleaseVar(good_protocols[i]);
438 core_interface_->ReleaseResource(ws);
440 PASS();
443 std::string TestWebSocket::TestGetURL() {
444 for (int i = 0; kInvalidURLs[i]; ++i) {
445 int32_t result;
446 PP_Resource ws = Connect(kInvalidURLs[i], &result, "");
447 ASSERT_TRUE(ws);
448 PP_Var url = websocket_interface_->GetURL(ws);
449 ASSERT_TRUE(AreEqualWithString(url, kInvalidURLs[i]));
450 ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
452 ReleaseVar(url);
453 core_interface_->ReleaseResource(ws);
456 PASS();
459 std::string TestWebSocket::TestValidConnect() {
460 int32_t result;
461 PP_Resource ws = Connect(GetFullURL(kEchoServerURL), &result, "");
462 ASSERT_TRUE(ws);
463 ASSERT_EQ(PP_OK, result);
464 PP_Var extensions = websocket_interface_->GetExtensions(ws);
465 ASSERT_TRUE(AreEqualWithString(extensions, ""));
466 core_interface_->ReleaseResource(ws);
468 PASS();
471 std::string TestWebSocket::TestInvalidClose() {
472 PP_Var reason = CreateVarString("close for test");
473 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
474 TestCompletionCallback async_callback(instance_->pp_instance(), PP_REQUIRED);
476 // Close before connect.
477 PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
478 callback.WaitForResult(websocket_interface_->Close(
479 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
480 callback.GetCallback().pp_completion_callback()));
481 ASSERT_EQ(PP_ERROR_FAILED, callback.result());
482 core_interface_->ReleaseResource(ws);
484 // Close with bad arguments.
485 int32_t result;
486 ws = Connect(GetFullURL(kEchoServerURL), &result, "");
487 ASSERT_TRUE(ws);
488 ASSERT_EQ(PP_OK, result);
489 callback.WaitForResult(websocket_interface_->Close(
490 ws, 1U, reason, callback.GetCallback().pp_completion_callback()));
491 ASSERT_EQ(PP_ERROR_NOACCESS, callback.result());
492 core_interface_->ReleaseResource(ws);
494 // Close with PP_VARTYPE_NULL.
495 ws = Connect(GetFullURL(kEchoServerURL), &result, "");
496 ASSERT_TRUE(ws);
497 ASSERT_EQ(PP_OK, result);
498 callback.WaitForResult(websocket_interface_->Close(
499 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeNull(),
500 callback.GetCallback().pp_completion_callback()));
501 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
502 core_interface_->ReleaseResource(ws);
504 // Close with PP_VARTYPE_NULL and ongoing receive message.
505 ws = Connect(GetFullURL(kEchoServerURL), &result, "");
506 ASSERT_TRUE(ws);
507 ASSERT_EQ(PP_OK, result);
508 PP_Var receive_message_var;
509 result = websocket_interface_->ReceiveMessage(
510 ws, &receive_message_var,
511 async_callback.GetCallback().pp_completion_callback());
512 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
513 callback.WaitForResult(websocket_interface_->Close(
514 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeNull(),
515 callback.GetCallback().pp_completion_callback()));
516 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
517 const char* send_message = "hi";
518 PP_Var send_message_var = CreateVarString(send_message);
519 result = websocket_interface_->SendMessage(ws, send_message_var);
520 ReleaseVar(send_message_var);
521 ASSERT_EQ(PP_OK, result);
522 async_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
523 ASSERT_EQ(PP_OK, async_callback.result());
524 ASSERT_TRUE(AreEqualWithString(receive_message_var, send_message));
525 ReleaseVar(receive_message_var);
526 core_interface_->ReleaseResource(ws);
528 // Close twice.
529 ws = Connect(GetFullURL(kEchoServerURL), &result, "");
530 ASSERT_TRUE(ws);
531 ASSERT_EQ(PP_OK, result);
532 result = websocket_interface_->Close(
533 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
534 async_callback.GetCallback().pp_completion_callback());
535 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
536 // Call another Close() before previous one is in progress.
537 result = websocket_interface_->Close(
538 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
539 callback.GetCallback().pp_completion_callback());
540 ASSERT_EQ(PP_ERROR_INPROGRESS, result);
541 async_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
542 ASSERT_EQ(PP_OK, async_callback.result());
543 // Call another Close() after previous one is completed.
544 // This Close() must do nothing and reports no error.
545 callback.WaitForResult(websocket_interface_->Close(
546 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
547 callback.GetCallback().pp_completion_callback()));
548 ASSERT_EQ(PP_OK, callback.result());
549 core_interface_->ReleaseResource(ws);
551 ReleaseVar(reason);
553 PASS();
556 std::string TestWebSocket::TestValidClose() {
557 PP_Var reason = CreateVarString("close for test");
558 PP_Var url = CreateVarString(GetFullURL(kEchoServerURL).c_str());
559 PP_Var protocols[] = { PP_MakeUndefined() };
560 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
561 TestCompletionCallback another_callback(
562 instance_->pp_instance(), callback_type());
564 // Close.
565 int32_t result;
566 PP_Resource ws = Connect(GetFullURL(kEchoServerURL), &result, "");
567 ASSERT_TRUE(ws);
568 ASSERT_EQ(PP_OK, result);
569 callback.WaitForResult(websocket_interface_->Close(
570 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
571 callback.GetCallback().pp_completion_callback()));
572 CHECK_CALLBACK_BEHAVIOR(callback);
573 ASSERT_EQ(PP_OK, callback.result());
574 core_interface_->ReleaseResource(ws);
576 // Close without code and reason.
577 ws = Connect(GetFullURL(kEchoServerURL), &result, "");
578 ASSERT_TRUE(ws);
579 ASSERT_EQ(PP_OK, result);
580 callback.WaitForResult(websocket_interface_->Close(
581 ws, PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED, reason,
582 callback.GetCallback().pp_completion_callback()));
583 ASSERT_EQ(PP_OK, callback.result());
584 core_interface_->ReleaseResource(ws);
586 // Close with PP_VARTYPE_UNDEFINED.
587 ws = Connect(GetFullURL(kEchoServerURL), &result, "");
588 ASSERT_TRUE(ws);
589 ASSERT_EQ(PP_OK, result);
590 callback.WaitForResult(websocket_interface_->Close(
591 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(),
592 callback.GetCallback().pp_completion_callback()));
593 CHECK_CALLBACK_BEHAVIOR(callback);
594 ASSERT_EQ(PP_OK, callback.result());
595 core_interface_->ReleaseResource(ws);
597 // Close in connecting.
598 // The ongoing connect failed with PP_ERROR_ABORTED, then the close is done
599 // successfully.
600 ws = websocket_interface_->Create(instance_->pp_instance());
601 result = websocket_interface_->Connect(
602 ws, url, protocols, 0U, callback.GetCallback().pp_completion_callback());
603 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
604 result = websocket_interface_->Close(
605 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
606 another_callback.GetCallback().pp_completion_callback());
607 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
608 callback.WaitForResult(PP_OK_COMPLETIONPENDING);
609 ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
610 another_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
611 ASSERT_EQ(PP_OK, another_callback.result());
612 core_interface_->ReleaseResource(ws);
614 // Close in closing.
615 // The first close will be done successfully, then the second one failed with
616 // with PP_ERROR_INPROGRESS immediately.
617 ws = Connect(GetFullURL(kEchoServerURL), &result, "");
618 ASSERT_TRUE(ws);
619 ASSERT_EQ(PP_OK, result);
620 result = websocket_interface_->Close(
621 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
622 callback.GetCallback().pp_completion_callback());
623 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
624 result = websocket_interface_->Close(
625 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
626 another_callback.GetCallback().pp_completion_callback());
627 ASSERT_EQ(PP_ERROR_INPROGRESS, result);
628 callback.WaitForResult(PP_OK_COMPLETIONPENDING);
629 ASSERT_EQ(PP_OK, callback.result());
630 core_interface_->ReleaseResource(ws);
632 // Close with ongoing receive message.
633 ws = Connect(GetFullURL(kEchoServerURL), &result, "");
634 ASSERT_TRUE(ws);
635 ASSERT_EQ(PP_OK, result);
636 PP_Var receive_message_var;
637 result = websocket_interface_->ReceiveMessage(
638 ws, &receive_message_var,
639 callback.GetCallback().pp_completion_callback());
640 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
641 result = websocket_interface_->Close(
642 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
643 another_callback.GetCallback().pp_completion_callback());
644 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
645 callback.WaitForResult(PP_OK_COMPLETIONPENDING);
646 ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
647 another_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
648 ASSERT_EQ(PP_OK, another_callback.result());
649 core_interface_->ReleaseResource(ws);
651 // Close with PP_VARTYPE_UNDEFINED and ongoing receive message.
652 ws = Connect(GetFullURL(kEchoServerURL), &result, "");
653 ASSERT_TRUE(ws);
654 ASSERT_EQ(PP_OK, result);
655 result = websocket_interface_->ReceiveMessage(
656 ws, &receive_message_var,
657 callback.GetCallback().pp_completion_callback());
658 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
659 result = websocket_interface_->Close(
660 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(),
661 another_callback.GetCallback().pp_completion_callback());
662 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
663 callback.WaitForResult(PP_OK_COMPLETIONPENDING);
664 ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
665 another_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
666 ASSERT_EQ(PP_OK, another_callback.result());
667 core_interface_->ReleaseResource(ws);
669 // Server initiated closing handshake.
670 ws = Connect(GetFullURL(kCloseWithCodeAndReasonServerURL), &result, "");
671 ASSERT_TRUE(ws);
672 ASSERT_EQ(PP_OK, result);
673 // Text messsage "1000 bye" requests the server to initiate closing handshake
674 // with code being 1000 and reason being "bye".
675 PP_Var close_request_var = CreateVarString("1000 bye");
676 result = websocket_interface_->SendMessage(ws, close_request_var);
677 ReleaseVar(close_request_var);
678 callback.WaitForResult(websocket_interface_->ReceiveMessage(
679 ws, &receive_message_var,
680 callback.GetCallback().pp_completion_callback()));
681 ASSERT_EQ(PP_ERROR_FAILED, callback.result());
682 core_interface_->ReleaseResource(ws);
684 ReleaseVar(reason);
685 ReleaseVar(url);
687 PASS();
690 std::string TestWebSocket::TestGetProtocol() {
691 const char* expected_protocols[] = {
692 "x-chat",
693 "hoehoe",
694 NULL
696 for (int i = 0; expected_protocols[i]; ++i) {
697 std::string url(GetFullURL(kProtocolTestServerURL));
698 url += expected_protocols[i];
699 int32_t result;
700 PP_Resource ws = Connect(url.c_str(), &result, expected_protocols[i]);
701 ASSERT_TRUE(ws);
702 ASSERT_EQ(PP_OK, result);
704 PP_Var protocol = websocket_interface_->GetProtocol(ws);
705 ASSERT_TRUE(AreEqualWithString(protocol, expected_protocols[i]));
707 ReleaseVar(protocol);
708 core_interface_->ReleaseResource(ws);
711 PASS();
714 std::string TestWebSocket::TestTextSendReceive() {
715 // Connect to test echo server.
716 int32_t connect_result;
717 PP_Resource ws = Connect(GetFullURL(kEchoServerURL), &connect_result, "");
718 ASSERT_TRUE(ws);
719 ASSERT_EQ(PP_OK, connect_result);
721 // Send 'hello pepper' text message.
722 const char* message = "hello pepper";
723 PP_Var message_var = CreateVarString(message);
724 int32_t result = websocket_interface_->SendMessage(ws, message_var);
725 ReleaseVar(message_var);
726 ASSERT_EQ(PP_OK, result);
728 // Receive echoed 'hello pepper'.
729 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
730 PP_Var received_message;
731 callback.WaitForResult(websocket_interface_->ReceiveMessage(
732 ws, &received_message, callback.GetCallback().pp_completion_callback()));
733 ASSERT_EQ(PP_OK, callback.result());
734 ASSERT_TRUE(AreEqualWithString(received_message, message));
735 ReleaseVar(received_message);
736 core_interface_->ReleaseResource(ws);
738 PASS();
741 std::string TestWebSocket::TestBinarySendReceive() {
742 // Connect to test echo server.
743 int32_t connect_result;
744 PP_Resource ws = Connect(GetFullURL(kEchoServerURL), &connect_result, "");
745 ASSERT_TRUE(ws);
746 ASSERT_EQ(PP_OK, connect_result);
748 // Send binary message.
749 std::vector<uint8_t> binary(256);
750 for (uint32_t i = 0; i < binary.size(); ++i)
751 binary[i] = i;
752 PP_Var message_var = CreateVarBinary(binary);
753 int32_t result = websocket_interface_->SendMessage(ws, message_var);
754 ReleaseVar(message_var);
755 ASSERT_EQ(PP_OK, result);
757 // Receive echoed binary.
758 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
759 PP_Var received_message;
760 callback.WaitForResult(websocket_interface_->ReceiveMessage(
761 ws, &received_message, callback.GetCallback().pp_completion_callback()));
762 ASSERT_EQ(PP_OK, callback.result());
763 ASSERT_TRUE(AreEqualWithBinary(received_message, binary));
764 ReleaseVar(received_message);
765 core_interface_->ReleaseResource(ws);
767 PASS();
770 std::string TestWebSocket::TestStressedSendReceive() {
771 // Connect to test echo server.
772 int32_t connect_result;
773 PP_Resource ws = Connect(GetFullURL(kEchoServerURL), &connect_result, "");
774 ASSERT_TRUE(ws);
775 ASSERT_EQ(PP_OK, connect_result);
777 // Prepare PP_Var objects to send.
778 const char* text = "hello pepper";
779 PP_Var text_var = CreateVarString(text);
780 std::vector<uint8_t> binary(256);
781 for (uint32_t i = 0; i < binary.size(); ++i)
782 binary[i] = i;
783 PP_Var binary_var = CreateVarBinary(binary);
784 // Prepare very large binary data over 64KiB. Object serializer in
785 // ppapi_proxy has a limitation of 64KiB as maximum return PP_Var data size
786 // to SRPC. In case received data over 64KiB exists, a specific code handles
787 // this large data via asynchronous callback from main thread. This data
788 // intends to test the code.
789 std::vector<uint8_t> large_binary(65 * 1024);
790 for (uint32_t i = 0; i < large_binary.size(); ++i)
791 large_binary[i] = i & 0xff;
792 PP_Var large_binary_var = CreateVarBinary(large_binary);
794 // Send many messages.
795 int32_t result;
796 for (int i = 0; i < 256; ++i) {
797 result = websocket_interface_->SendMessage(ws, text_var);
798 ASSERT_EQ(PP_OK, result);
799 result = websocket_interface_->SendMessage(ws, binary_var);
800 ASSERT_EQ(PP_OK, result);
802 result = websocket_interface_->SendMessage(ws, large_binary_var);
803 ASSERT_EQ(PP_OK, result);
804 ReleaseVar(text_var);
805 ReleaseVar(binary_var);
806 ReleaseVar(large_binary_var);
808 // Receive echoed data.
809 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
810 for (int i = 0; i <= 512; ++i) {
811 PP_Var received_message;
812 callback.WaitForResult(websocket_interface_->ReceiveMessage(
813 ws, &received_message,
814 callback.GetCallback().pp_completion_callback()));
815 ASSERT_EQ(PP_OK, callback.result());
816 if (i == 512) {
817 ASSERT_TRUE(AreEqualWithBinary(received_message, large_binary));
818 } else if (i & 1) {
819 ASSERT_TRUE(AreEqualWithBinary(received_message, binary));
820 } else {
821 ASSERT_TRUE(AreEqualWithString(received_message, text));
823 ReleaseVar(received_message);
825 core_interface_->ReleaseResource(ws);
827 PASS();
830 std::string TestWebSocket::TestBufferedAmount() {
831 // Connect to test echo server.
832 int32_t connect_result;
833 PP_Resource ws = Connect(GetFullURL(kEchoServerURL), &connect_result, "");
834 ASSERT_TRUE(ws);
835 ASSERT_EQ(PP_OK, connect_result);
837 // Prepare a large message that is not aligned with the internal buffer
838 // sizes.
839 std::string message(8193, 'x');
840 PP_Var message_var = CreateVarString(message);
842 uint64_t buffered_amount = 0;
843 int32_t result;
844 for (int i = 0; i < 100; i++) {
845 result = websocket_interface_->SendMessage(ws, message_var);
846 ASSERT_EQ(PP_OK, result);
847 buffered_amount = websocket_interface_->GetBufferedAmount(ws);
848 // Buffered amount size 262144 is too big for the internal buffer size.
849 if (buffered_amount > 262144)
850 break;
853 // Close connection.
854 std::string reason_str = "close while busy";
855 PP_Var reason = CreateVarString(reason_str.c_str());
856 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
857 result = websocket_interface_->Close(
858 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
859 callback.GetCallback().pp_completion_callback());
860 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
861 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSING,
862 websocket_interface_->GetReadyState(ws));
864 callback.WaitForResult(result);
865 ASSERT_EQ(PP_OK, callback.result());
866 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED,
867 websocket_interface_->GetReadyState(ws));
869 uint64_t base_buffered_amount = websocket_interface_->GetBufferedAmount(ws);
871 // After connection closure, all sending requests fail and just increase
872 // the bufferedAmount property.
873 PP_Var empty_string = CreateVarString("");
874 result = websocket_interface_->SendMessage(ws, empty_string);
875 ASSERT_EQ(PP_ERROR_FAILED, result);
876 buffered_amount = websocket_interface_->GetBufferedAmount(ws);
877 ASSERT_EQ(base_buffered_amount + kMessageFrameOverhead, buffered_amount);
878 base_buffered_amount = buffered_amount;
880 result = websocket_interface_->SendMessage(ws, reason);
881 ASSERT_EQ(PP_ERROR_FAILED, result);
882 buffered_amount = websocket_interface_->GetBufferedAmount(ws);
883 uint64_t reason_frame_size = kMessageFrameOverhead + reason_str.length();
884 ASSERT_EQ(base_buffered_amount + reason_frame_size, buffered_amount);
886 ReleaseVar(message_var);
887 ReleaseVar(reason);
888 ReleaseVar(empty_string);
889 core_interface_->ReleaseResource(ws);
891 PASS();
894 // Test abort behaviors where a WebSocket PP_Resource is released while each
895 // function is in-flight on the WebSocket PP_Resource.
896 std::string TestWebSocket::TestAbortCallsWithCallback() {
897 // Following tests make sure the behavior for functions which require a
898 // callback. The callback must get a PP_ERROR_ABORTED.
900 // Test the behavior for Connect().
901 PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
902 ASSERT_TRUE(ws);
903 std::string url = GetFullURL(kEchoServerURL);
904 PP_Var url_var = CreateVarString(url);
905 TestCompletionCallback connect_callback(
906 instance_->pp_instance(), callback_type());
907 int32_t result = websocket_interface_->Connect(
908 ws, url_var, NULL, 0,
909 connect_callback.GetCallback().pp_completion_callback());
910 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
911 core_interface_->ReleaseResource(ws);
912 connect_callback.WaitForResult(result);
913 ASSERT_EQ(PP_ERROR_ABORTED, connect_callback.result());
915 // Test the behavior for Close().
916 ws = Connect(url, &result, "");
917 ASSERT_TRUE(ws);
918 ASSERT_EQ(PP_OK, result);
919 PP_Var reason_var = CreateVarString("abort");
920 TestCompletionCallback close_callback(
921 instance_->pp_instance(), callback_type());
922 result = websocket_interface_->Close(
923 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason_var,
924 close_callback.GetCallback().pp_completion_callback());
925 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
926 core_interface_->ReleaseResource(ws);
927 close_callback.WaitForResult(result);
928 ASSERT_EQ(PP_ERROR_ABORTED, close_callback.result());
929 ReleaseVar(reason_var);
931 // Test the behavior for ReceiveMessage().
932 // Make sure the simplest case to wait for data which never arrives, here.
933 ws = Connect(url, &result, "");
934 ASSERT_TRUE(ws);
935 ASSERT_EQ(PP_OK, result);
936 PP_Var receive_var;
937 TestCompletionCallback receive_callback(
938 instance_->pp_instance(), callback_type());
939 result = websocket_interface_->ReceiveMessage(
940 ws, &receive_var,
941 receive_callback.GetCallback().pp_completion_callback());
942 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
943 core_interface_->ReleaseResource(ws);
944 receive_callback.WaitForResult(result);
945 ASSERT_EQ(PP_ERROR_ABORTED, receive_callback.result());
947 // Release the resource in the aborting receive completion callback which is
948 // introduced by calling Close().
949 ws = Connect(url, &result, "");
950 ASSERT_TRUE(ws);
951 ASSERT_EQ(PP_OK, result);
952 result = websocket_interface_->ReceiveMessage(
953 ws, &receive_var,
954 receive_callback.GetCallback().pp_completion_callback());
955 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
956 ReleaseResourceDelegate receive_delegate(core_interface_, ws);
957 receive_callback.SetDelegate(&receive_delegate);
958 result = websocket_interface_->Close(
959 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(),
960 close_callback.GetCallback().pp_completion_callback());
961 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
962 receive_callback.WaitForResult(result);
963 CHECK_CALLBACK_BEHAVIOR(receive_callback);
964 ASSERT_EQ(PP_ERROR_ABORTED, receive_callback.result());
965 close_callback.WaitForResult(result);
966 CHECK_CALLBACK_BEHAVIOR(close_callback);
967 ASSERT_EQ(PP_ERROR_ABORTED, close_callback.result());
969 ReleaseVar(url_var);
971 PASS();
974 std::string TestWebSocket::TestAbortSendMessageCall() {
975 // Test the behavior for SendMessage().
976 // This function doesn't require a callback, but operation will be done
977 // asynchronously in WebKit and browser process.
978 std::vector<uint8_t> large_binary(65 * 1024);
979 PP_Var large_var = CreateVarBinary(large_binary);
981 int32_t result;
982 std::string url = GetFullURL(kEchoServerURL);
983 PP_Resource ws = Connect(url, &result, "");
984 ASSERT_TRUE(ws);
985 ASSERT_EQ(PP_OK, result);
986 result = websocket_interface_->SendMessage(ws, large_var);
987 ASSERT_EQ(PP_OK, result);
988 core_interface_->ReleaseResource(ws);
989 ReleaseVar(large_var);
991 PASS();
994 std::string TestWebSocket::TestAbortCloseCall() {
995 // Release the resource in the close completion callback.
996 int32_t result;
997 std::string url = GetFullURL(kEchoServerURL);
998 PP_Resource ws = Connect(url, &result, "");
999 ASSERT_TRUE(ws);
1000 ASSERT_EQ(PP_OK, result);
1001 TestCompletionCallback close_callback(
1002 instance_->pp_instance(), callback_type());
1003 result = websocket_interface_->Close(
1004 ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(),
1005 close_callback.GetCallback().pp_completion_callback());
1006 ReleaseResourceDelegate close_delegate(core_interface_, ws);
1007 close_callback.SetDelegate(&close_delegate);
1008 close_callback.WaitForResult(result);
1009 CHECK_CALLBACK_BEHAVIOR(close_callback);
1010 ASSERT_EQ(PP_OK, close_callback.result());
1012 PASS();
1015 std::string TestWebSocket::TestAbortReceiveMessageCall() {
1016 // Test the behavior where receive process might be in-flight.
1017 std::vector<uint8_t> large_binary(65 * 1024);
1018 PP_Var large_var = CreateVarBinary(large_binary);
1019 const char* text = "yukarin";
1020 PP_Var text_var = CreateVarString(text);
1022 std::string url = GetFullURL(kEchoServerURL);
1023 int32_t result;
1024 PP_Resource ws;
1026 // Each trial sends |trial_count| + 1 messages and receives just |trial|
1027 // number of message(s) before releasing the WebSocket. The WebSocket is
1028 // released while the next message is going to be received.
1029 const int trial_count = 8;
1030 for (int trial = 1; trial <= trial_count; trial++) {
1031 ws = Connect(url, &result, "");
1032 ASSERT_TRUE(ws);
1033 ASSERT_EQ(PP_OK, result);
1034 for (int i = 0; i <= trial_count; ++i) {
1035 result = websocket_interface_->SendMessage(ws, text_var);
1036 ASSERT_EQ(PP_OK, result);
1038 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
1039 PP_Var var;
1040 for (int i = 0; i < trial; ++i) {
1041 callback.WaitForResult(websocket_interface_->ReceiveMessage(
1042 ws, &var, callback.GetCallback().pp_completion_callback()));
1043 ASSERT_EQ(PP_OK, callback.result());
1044 ASSERT_TRUE(AreEqualWithString(var, text));
1045 ReleaseVar(var);
1047 result = websocket_interface_->ReceiveMessage(
1048 ws, &var, callback.GetCallback().pp_completion_callback());
1049 core_interface_->ReleaseResource(ws);
1050 if (result != PP_OK) {
1051 callback.WaitForResult(result);
1052 ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
1055 // Same test, but the last receiving message is large message over 64KiB.
1056 for (int trial = 1; trial <= trial_count; trial++) {
1057 ws = Connect(url, &result, "");
1058 ASSERT_TRUE(ws);
1059 ASSERT_EQ(PP_OK, result);
1060 for (int i = 0; i <= trial_count; ++i) {
1061 if (i == trial)
1062 result = websocket_interface_->SendMessage(ws, large_var);
1063 else
1064 result = websocket_interface_->SendMessage(ws, text_var);
1065 ASSERT_EQ(PP_OK, result);
1067 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
1068 PP_Var var;
1069 for (int i = 0; i < trial; ++i) {
1070 callback.WaitForResult(websocket_interface_->ReceiveMessage(
1071 ws, &var, callback.GetCallback().pp_completion_callback()));
1072 ASSERT_EQ(PP_OK, callback.result());
1073 ASSERT_TRUE(AreEqualWithString(var, text));
1074 ReleaseVar(var);
1076 result = websocket_interface_->ReceiveMessage(
1077 ws, &var, callback.GetCallback().pp_completion_callback());
1078 core_interface_->ReleaseResource(ws);
1079 if (result != PP_OK) {
1080 callback.WaitForResult(result);
1081 ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
1085 ReleaseVar(large_var);
1086 ReleaseVar(text_var);
1088 PASS();
1091 std::string TestWebSocket::TestCcInterfaces() {
1092 // C++ bindings is simple straightforward, then just verifies interfaces work
1093 // as a interface bridge fine.
1094 pp::WebSocket ws(instance_);
1096 // Check uninitialized properties access.
1097 ASSERT_EQ(0, ws.GetBufferedAmount());
1098 ASSERT_EQ(0, ws.GetCloseCode());
1099 ASSERT_TRUE(AreEqualWithString(ws.GetCloseReason().pp_var(), ""));
1100 ASSERT_EQ(false, ws.GetCloseWasClean());
1101 ASSERT_TRUE(AreEqualWithString(ws.GetExtensions().pp_var(), ""));
1102 ASSERT_TRUE(AreEqualWithString(ws.GetProtocol().pp_var(), ""));
1103 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_INVALID, ws.GetReadyState());
1104 ASSERT_TRUE(AreEqualWithString(ws.GetURL().pp_var(), ""));
1106 // Check communication interfaces (connect, send, receive, and close).
1107 TestCompletionCallback connect_callback(
1108 instance_->pp_instance(), callback_type());
1109 connect_callback.WaitForResult(ws.Connect(
1110 pp::Var(GetFullURL(kCloseServerURL)), NULL, 0U, connect_callback));
1111 CHECK_CALLBACK_BEHAVIOR(connect_callback);
1112 ASSERT_EQ(PP_OK, connect_callback.result());
1114 std::string text_message("hello C++");
1115 int32_t result = ws.SendMessage(pp::Var(text_message));
1116 ASSERT_EQ(PP_OK, result);
1118 std::vector<uint8_t> binary(256);
1119 for (uint32_t i = 0; i < binary.size(); ++i)
1120 binary[i] = i;
1121 result = ws.SendMessage(
1122 pp::Var(pp::PASS_REF, CreateVarBinary(binary)));
1123 ASSERT_EQ(PP_OK, result);
1125 pp::Var text_receive_var;
1126 TestCompletionCallback text_receive_callback(
1127 instance_->pp_instance(), callback_type());
1128 text_receive_callback.WaitForResult(
1129 ws.ReceiveMessage(&text_receive_var, text_receive_callback));
1130 ASSERT_EQ(PP_OK, text_receive_callback.result());
1131 ASSERT_TRUE(
1132 AreEqualWithString(text_receive_var.pp_var(), text_message.c_str()));
1134 pp::Var binary_receive_var;
1135 TestCompletionCallback binary_receive_callback(
1136 instance_->pp_instance(), callback_type());
1137 binary_receive_callback.WaitForResult(
1138 ws.ReceiveMessage(&binary_receive_var, binary_receive_callback));
1139 ASSERT_EQ(PP_OK, binary_receive_callback.result());
1140 ASSERT_TRUE(AreEqualWithBinary(binary_receive_var.pp_var(), binary));
1142 TestCompletionCallback close_callback(
1143 instance_->pp_instance(), callback_type());
1144 std::string reason("bye");
1145 close_callback.WaitForResult(ws.Close(
1146 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason), close_callback));
1147 CHECK_CALLBACK_BEHAVIOR(close_callback);
1148 ASSERT_EQ(PP_OK, close_callback.result());
1150 // Check initialized properties access.
1151 ASSERT_EQ(0, ws.GetBufferedAmount());
1152 ASSERT_EQ(PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, ws.GetCloseCode());
1153 ASSERT_TRUE(
1154 AreEqualWithString(ws.GetCloseReason().pp_var(), reason.c_str()));
1155 ASSERT_EQ(true, ws.GetCloseWasClean());
1156 ASSERT_TRUE(AreEqualWithString(ws.GetProtocol().pp_var(), ""));
1157 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED, ws.GetReadyState());
1158 ASSERT_TRUE(AreEqualWithString(
1159 ws.GetURL().pp_var(), GetFullURL(kCloseServerURL).c_str()));
1161 PASS();
1164 std::string TestWebSocket::TestUtilityInvalidConnect() {
1165 const pp::Var protocols[] = { pp::Var() };
1167 TestWebSocketAPI websocket(instance_);
1168 int32_t result = websocket.Connect(pp::Var(), protocols, 1U);
1169 ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
1170 ASSERT_EQ(0U, websocket.GetSeenEvents().size());
1172 result = websocket.Connect(pp::Var(), protocols, 1U);
1173 ASSERT_EQ(PP_ERROR_INPROGRESS, result);
1174 ASSERT_EQ(0U, websocket.GetSeenEvents().size());
1176 for (int i = 0; kInvalidURLs[i]; ++i) {
1177 TestWebSocketAPI ws(instance_);
1178 result = ws.Connect(pp::Var(std::string(kInvalidURLs[i])), protocols, 0U);
1179 if (result == PP_OK_COMPLETIONPENDING) {
1180 ws.WaitForClosed();
1181 const std::vector<WebSocketEvent>& events = ws.GetSeenEvents();
1182 ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[0].event_type);
1183 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type);
1184 ASSERT_EQ(2U, ws.GetSeenEvents().size());
1185 } else {
1186 ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
1187 ASSERT_EQ(0U, ws.GetSeenEvents().size());
1191 PASS();
1194 std::string TestWebSocket::TestUtilityProtocols() {
1195 const pp::Var bad_protocols[] = {
1196 pp::Var(std::string("x-test")), pp::Var(std::string("x-test")) };
1197 const pp::Var good_protocols[] = {
1198 pp::Var(std::string("x-test")), pp::Var(std::string("x-yatest")) };
1201 TestWebSocketAPI websocket(instance_);
1202 int32_t result = websocket.Connect(
1203 pp::Var(GetFullURL(kEchoServerURL)), bad_protocols, 2U);
1204 ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
1205 ASSERT_EQ(0U, websocket.GetSeenEvents().size());
1209 TestWebSocketAPI websocket(instance_);
1210 int32_t result = websocket.Connect(
1211 pp::Var(GetFullURL(kEchoServerURL)), good_protocols, 2U);
1212 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1213 websocket.WaitForConnected();
1214 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1215 // Protocol arguments are valid, but this test run without a WebSocket
1216 // server. As a result, OnError() and OnClose() are invoked because of
1217 // a connection establishment failure.
1218 ASSERT_EQ(2U, events.size());
1219 ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[0].event_type);
1220 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type);
1221 ASSERT_FALSE(events[1].was_clean);
1224 PASS();
1227 std::string TestWebSocket::TestUtilityGetURL() {
1228 const pp::Var protocols[] = { pp::Var() };
1230 for (int i = 0; kInvalidURLs[i]; ++i) {
1231 TestWebSocketAPI websocket(instance_);
1232 int32_t result = websocket.Connect(
1233 pp::Var(std::string(kInvalidURLs[i])), protocols, 0U);
1234 if (result == PP_OK_COMPLETIONPENDING) {
1235 websocket.WaitForClosed();
1236 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1237 ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[0].event_type);
1238 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type);
1239 ASSERT_EQ(2U, events.size());
1240 } else {
1241 ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
1242 ASSERT_EQ(0U, websocket.GetSeenEvents().size());
1244 pp::Var url = websocket.GetURL();
1245 ASSERT_TRUE(AreEqualWithString(url.pp_var(), kInvalidURLs[i]));
1248 PASS();
1251 std::string TestWebSocket::TestUtilityValidConnect() {
1252 const pp::Var protocols[] = { pp::Var() };
1253 TestWebSocketAPI websocket(instance_);
1254 int32_t result = websocket.Connect(
1255 pp::Var(GetFullURL(kEchoServerURL)), protocols, 0U);
1256 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1257 websocket.WaitForConnected();
1258 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1259 ASSERT_EQ(1U, events.size());
1260 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1261 ASSERT_TRUE(AreEqualWithString(websocket.GetExtensions().pp_var(), ""));
1263 PASS();
1266 std::string TestWebSocket::TestUtilityInvalidClose() {
1267 const pp::Var reason = pp::Var(std::string("close for test"));
1269 // Close before connect.
1271 TestWebSocketAPI websocket(instance_);
1272 int32_t result = websocket.Close(
1273 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason);
1274 ASSERT_EQ(PP_ERROR_FAILED, result);
1275 ASSERT_EQ(0U, websocket.GetSeenEvents().size());
1278 // Close with bad arguments.
1280 TestWebSocketAPI websocket(instance_);
1281 int32_t result = websocket.Connect(pp::Var(GetFullURL(kEchoServerURL)),
1282 NULL, 0);
1283 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1284 websocket.WaitForConnected();
1285 result = websocket.Close(1U, reason);
1286 ASSERT_EQ(PP_ERROR_NOACCESS, result);
1287 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1288 ASSERT_EQ(1U, events.size());
1289 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1292 PASS();
1295 std::string TestWebSocket::TestUtilityValidClose() {
1296 std::string reason("close for test");
1297 pp::Var url = pp::Var(GetFullURL(kCloseServerURL));
1299 // Close.
1301 TestWebSocketAPI websocket(instance_);
1302 int32_t result = websocket.Connect(url, NULL, 0U);
1303 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1304 websocket.WaitForConnected();
1305 result = websocket.Close(
1306 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
1307 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1308 websocket.WaitForClosed();
1309 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1310 ASSERT_EQ(2U, events.size());
1311 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1312 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type);
1313 ASSERT_TRUE(events[1].was_clean);
1314 ASSERT_EQ(PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, events[1].close_code);
1315 ASSERT_TRUE(AreEqualWithString(events[1].var.pp_var(), reason.c_str()));
1318 // Close in connecting.
1319 // The ongoing connect failed with PP_ERROR_ABORTED, then the close is done
1320 // successfully.
1322 TestWebSocketAPI websocket(instance_);
1323 int32_t result = websocket.Connect(url, NULL, 0U);
1324 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1325 result = websocket.Close(
1326 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
1327 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1328 websocket.WaitForClosed();
1329 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1330 ASSERT_TRUE(events.size() == 2 || events.size() == 3);
1331 int index = 0;
1332 if (events.size() == 3)
1333 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[index++].event_type);
1334 ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[index++].event_type);
1335 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[index].event_type);
1336 ASSERT_FALSE(events[index].was_clean);
1339 // Close in closing.
1340 // The first close will be done successfully, then the second one failed with
1341 // with PP_ERROR_INPROGRESS immediately.
1343 TestWebSocketAPI websocket(instance_);
1344 int32_t result = websocket.Connect(url, NULL, 0U);
1345 result = websocket.Close(
1346 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
1347 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1348 result = websocket.Close(
1349 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
1350 ASSERT_EQ(PP_ERROR_INPROGRESS, result);
1351 websocket.WaitForClosed();
1352 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1353 ASSERT_TRUE(events.size() == 2 || events.size() == 3)
1354 int index = 0;
1355 if (events.size() == 3)
1356 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[index++].event_type);
1357 ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[index++].event_type);
1358 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[index].event_type);
1359 ASSERT_FALSE(events[index].was_clean);
1362 PASS();
1365 std::string TestWebSocket::TestUtilityGetProtocol() {
1366 const std::string protocol("x-chat");
1367 const pp::Var protocols[] = { pp::Var(protocol) };
1368 std::string url(GetFullURL(kProtocolTestServerURL));
1369 url += protocol;
1370 TestWebSocketAPI websocket(instance_);
1371 int32_t result = websocket.Connect(pp::Var(url), protocols, 1U);
1372 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1373 websocket.WaitForReceived();
1374 ASSERT_TRUE(AreEqualWithString(
1375 websocket.GetProtocol().pp_var(), protocol.c_str()));
1376 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1377 // The server to which this test connect returns the decided protocol as a
1378 // text frame message. So the WebSocketEvent records EVENT_MESSAGE event
1379 // after EVENT_OPEN event.
1380 ASSERT_EQ(2U, events.size());
1381 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1382 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type);
1383 ASSERT_TRUE(AreEqualWithString(events[1].var.pp_var(), protocol.c_str()));
1385 PASS();
1388 std::string TestWebSocket::TestUtilityTextSendReceive() {
1389 const pp::Var protocols[] = { pp::Var() };
1390 TestWebSocketAPI websocket(instance_);
1391 int32_t result =
1392 websocket.Connect(pp::Var(GetFullURL(kEchoServerURL)), protocols, 0U);
1393 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1394 websocket.WaitForConnected();
1396 // Send 'hello pepper'.
1397 std::string message1("hello pepper");
1398 result = websocket.Send(pp::Var(std::string(message1)));
1399 ASSERT_EQ(PP_OK, result);
1401 // Receive echoed 'hello pepper'.
1402 websocket.WaitForReceived();
1404 // Send 'goodbye pepper'.
1405 std::string message2("goodbye pepper");
1406 result = websocket.Send(pp::Var(std::string(message2)));
1408 // Receive echoed 'goodbye pepper'.
1409 websocket.WaitForReceived();
1411 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1412 ASSERT_EQ(3U, events.size());
1413 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1414 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type);
1415 ASSERT_TRUE(AreEqualWithString(events[1].var.pp_var(), message1.c_str()));
1416 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[2].event_type);
1417 ASSERT_TRUE(AreEqualWithString(events[2].var.pp_var(), message2.c_str()));
1419 PASS();
1422 std::string TestWebSocket::TestUtilityBinarySendReceive() {
1423 const pp::Var protocols[] = { pp::Var() };
1424 TestWebSocketAPI websocket(instance_);
1425 int32_t result =
1426 websocket.Connect(pp::Var(GetFullURL(kEchoServerURL)), protocols, 0U);
1427 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1428 websocket.WaitForConnected();
1430 // Send binary message.
1431 uint32_t len = 256;
1432 std::vector<uint8_t> binary(len);
1433 for (uint32_t i = 0; i < len; ++i)
1434 binary[i] = i;
1435 pp::VarArrayBuffer message(len);
1436 uint8_t* var_data = static_cast<uint8_t*>(message.Map());
1437 std::copy(binary.begin(), binary.end(), var_data);
1438 result = websocket.Send(message);
1439 ASSERT_EQ(PP_OK, result);
1441 // Receive echoed binary message.
1442 websocket.WaitForReceived();
1444 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1445 ASSERT_EQ(2U, events.size());
1446 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1447 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type);
1448 ASSERT_TRUE(AreEqualWithBinary(events[1].var.pp_var(), binary));
1450 PASS();
1453 std::string TestWebSocket::TestUtilityBufferedAmount() {
1454 // Connect to test echo server.
1455 const pp::Var protocols[] = { pp::Var() };
1456 TestWebSocketAPI websocket(instance_);
1457 int32_t result =
1458 websocket.Connect(pp::Var(GetFullURL(kEchoServerURL)), protocols, 0U);
1459 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
1460 websocket.WaitForConnected();
1462 // Prepare a large message that is not aligned with the internal buffer
1463 // sizes.
1464 std::string message(8193, 'x');
1465 uint64_t buffered_amount = 0;
1466 uint32_t sent;
1467 for (sent = 0; sent < 100; sent++) {
1468 result = websocket.Send(pp::Var(message));
1469 ASSERT_EQ(PP_OK, result);
1470 buffered_amount = websocket.GetBufferedAmount();
1471 // Buffered amount size 262144 is too big for the internal buffer size.
1472 if (buffered_amount > 262144)
1473 break;
1476 // Close connection.
1477 std::string reason = "close while busy";
1478 result = websocket.Close(
1479 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
1480 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSING, websocket.GetReadyState());
1481 websocket.WaitForClosed();
1482 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED, websocket.GetReadyState());
1484 uint64_t base_buffered_amount = websocket.GetBufferedAmount();
1485 size_t events_on_closed = websocket.GetSeenEvents().size();
1487 // After connection closure, all sending requests fail and just increase
1488 // the bufferedAmount property.
1489 result = websocket.Send(pp::Var(std::string("")));
1490 ASSERT_EQ(PP_ERROR_FAILED, result);
1491 buffered_amount = websocket.GetBufferedAmount();
1492 ASSERT_EQ(base_buffered_amount + kMessageFrameOverhead, buffered_amount);
1493 base_buffered_amount = buffered_amount;
1495 result = websocket.Send(pp::Var(reason));
1496 ASSERT_EQ(PP_ERROR_FAILED, result);
1497 buffered_amount = websocket.GetBufferedAmount();
1498 uint64_t reason_frame_size = kMessageFrameOverhead + reason.length();
1499 ASSERT_EQ(base_buffered_amount + reason_frame_size, buffered_amount);
1501 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1502 ASSERT_EQ(events_on_closed, events.size());
1503 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1504 size_t last_event = events_on_closed - 1;
1505 for (uint32_t i = 1; i < last_event; ++i) {
1506 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[i].event_type);
1507 ASSERT_TRUE(AreEqualWithString(events[i].var.pp_var(), message));
1509 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[last_event].event_type);
1510 ASSERT_TRUE(events[last_event].was_clean);
1512 PASS();