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