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