15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/tests/test_websocket.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <memory>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_bool.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_completion_callback.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_errors.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_instance.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_resource.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_var.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_core.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_var.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_var_array_buffer.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_websocket.h"
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ppapi/c/private/ppb_testing_private.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/instance.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/module.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/var_array_buffer.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/websocket.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/tests/test_utils.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/tests/testing_instance.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/utility/websocket/websocket_api.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// net::SpawnedTestServer serves WebSocket service for testing.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Following URLs are handled by pywebsocket handlers in
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// net/data/websocket/*_wsh.py.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kEchoServerURL[] = "echo-with-no-extension";
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kCloseServerURL[] = "close";
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kCloseWithCodeAndReasonServerURL[] = "close-code-and-reason";
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kProtocolTestServerURL[] = "protocol-test?protocol=";
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kInvalidURLs[] = {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "http://www.google.com/invalid_scheme",
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "ws://www.google.com/invalid#fragment",
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "ws://www.google.com:65535/invalid_port",
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NULL
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Internal packet sizes.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint64_t kMessageFrameOverhead = 6;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WebSocketEvent {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum EventType {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EVENT_OPEN,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EVENT_MESSAGE,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EVENT_ERROR,
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EVENT_CLOSE
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebSocketEvent(EventType type,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 bool was_clean,
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 uint16_t close_code,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const pp::Var& var)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : event_type(type),
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        was_clean(was_clean),
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        close_code(close_code),
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var(var) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventType event_type;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool was_clean;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint16_t close_code;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Var var;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ReleaseResourceDelegate : public TestCompletionCallback::Delegate {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit ReleaseResourceDelegate(const PPB_Core* core_interface,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   PP_Resource resource)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : core_interface_(core_interface),
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        resource_(resource) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TestCompletionCallback::Delegate implementation.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnCallback(void* user_data, int32_t result) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (resource_)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      core_interface_->ReleaseResource(resource_);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PPB_Core* core_interface_;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Resource resource_;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestWebSocketAPI : public pp::WebSocketAPI {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit TestWebSocketAPI(pp::Instance* instance)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : pp::WebSocketAPI(instance),
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        connected_(false),
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        received_(false),
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        closed_(false),
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        wait_for_connected_(false),
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        wait_for_received_(false),
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        wait_for_closed_(false),
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        instance_(instance->pp_instance()) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void WebSocketDidOpen() {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push_back(
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        WebSocketEvent(WebSocketEvent::EVENT_OPEN, true, 0U, pp::Var()));
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connected_ = true;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (wait_for_connected_) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetTestingInterface()->QuitMessageLoop(instance_);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wait_for_connected_ = false;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void WebSocketDidClose(
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool was_clean, uint16_t code, const pp::Var& reason) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push_back(
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        WebSocketEvent(WebSocketEvent::EVENT_CLOSE, was_clean, code, reason));
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connected_ = true;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    closed_ = true;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (wait_for_connected_ || wait_for_closed_) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetTestingInterface()->QuitMessageLoop(instance_);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wait_for_connected_ = false;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wait_for_closed_ = false;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void HandleWebSocketMessage(const pp::Var &message) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push_back(
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        WebSocketEvent(WebSocketEvent::EVENT_MESSAGE, true, 0U, message));
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    received_ = true;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (wait_for_received_) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetTestingInterface()->QuitMessageLoop(instance_);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wait_for_received_ = false;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      received_ = false;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void HandleWebSocketError() {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push_back(
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        WebSocketEvent(WebSocketEvent::EVENT_ERROR, true, 0U, pp::Var()));
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitForConnected() {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!connected_) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wait_for_connected_ = true;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetTestingInterface()->RunMessageLoop(instance_);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitForReceived() {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!received_) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wait_for_received_ = true;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetTestingInterface()->RunMessageLoop(instance_);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitForClosed() {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!closed_) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wait_for_closed_ = true;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetTestingInterface()->RunMessageLoop(instance_);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<WebSocketEvent>& GetSeenEvents() const {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return events_;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<WebSocketEvent> events_;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool connected_;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool received_;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool closed_;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool wait_for_connected_;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool wait_for_received_;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool wait_for_closed_;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Instance instance_;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_TEST_CASE(WebSocket);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TestWebSocket::Init() {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  websocket_interface_ = static_cast<const PPB_WebSocket*>(
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::Module::Get()->GetBrowserInterface(PPB_WEBSOCKET_INTERFACE));
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_interface_ = static_cast<const PPB_Var*>(
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE));
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  arraybuffer_interface_ = static_cast<const PPB_VarArrayBuffer*>(
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::Module::Get()->GetBrowserInterface(
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          PPB_VAR_ARRAY_BUFFER_INTERFACE));
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_ = static_cast<const PPB_Core*>(
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE));
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!websocket_interface_ || !var_interface_ || !arraybuffer_interface_ ||
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !core_interface_)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CheckTestingInterface();
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestWebSocket::RunTests(const std::string& filter) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(IsWebSocket, filter);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(UninitializedPropertiesAccess, filter);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(InvalidConnect, filter);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(Protocols, filter);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(GetURL, filter);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(ValidConnect, filter);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(InvalidClose, filter);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(ValidClose, filter);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(GetProtocol, filter);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(TextSendReceive, filter);
216558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  RUN_TEST_BACKGROUND(TestWebSocket, TextSendReceiveTwice, filter);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(BinarySendReceive, filter);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(StressedSendReceive, filter);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(BufferedAmount, filter);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PP_Resource for WebSocket may be released later because of an internal
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reference for asynchronous IPC handling. So, suppress reference check on
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the following AbortCallsWithCallback test.
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST(AbortCallsWithCallback, filter);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(AbortSendMessageCall, filter);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(AbortCloseCall, filter);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(AbortReceiveMessageCall, filter);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(CcInterfaces, filter);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(UtilityInvalidConnect, filter);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(UtilityProtocols, filter);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(UtilityGetURL, filter);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(UtilityValidConnect, filter);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(UtilityInvalidClose, filter);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(UtilityValidClose, filter);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(UtilityGetProtocol, filter);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(UtilityTextSendReceive, filter);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(UtilityBinarySendReceive, filter);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUN_TEST_WITH_REFERENCE_CHECK(UtilityBufferedAmount, filter);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::GetFullURL(const char* url) {
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string rv = "ws://";
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Some WebSocket tests don't start the server so there'll be no host and
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // port.
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (instance_->websocket_host().empty())
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rv += "127.0.0.1";
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rv += instance_->websocket_host();
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (instance_->websocket_port() != -1) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char buffer[10];
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sprintf(buffer, ":%d", instance_->websocket_port());
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv += std::string(buffer);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv += "/";
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv += url;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Var TestWebSocket::CreateVarString(const std::string& string) {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return var_interface_->VarFromUtf8(string.c_str(), string.size());
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Var TestWebSocket::CreateVarBinary(const std::vector<uint8_t>& binary) {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var var = arraybuffer_interface_->Create(binary.size());
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8_t* var_data = static_cast<uint8_t*>(arraybuffer_interface_->Map(var));
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::copy(binary.begin(), binary.end(), var_data);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return var;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestWebSocket::ReleaseVar(const PP_Var& var) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_interface_->Release(var);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TestWebSocket::AreEqualWithString(const PP_Var& var,
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const std::string& string) {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (var.type != PP_VARTYPE_STRING)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t utf8_length;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* utf8 = var_interface_->VarToUtf8(var, &utf8_length);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (utf8_length != string.size())
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (string.compare(utf8))
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TestWebSocket::AreEqualWithBinary(const PP_Var& var,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const std::vector<uint8_t>& binary) {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t buffer_size = 0;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Bool success = arraybuffer_interface_->ByteLength(var, &buffer_size);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!success || buffer_size != binary.size())
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!std::equal(binary.begin(), binary.end(),
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<uint8_t*>(arraybuffer_interface_->Map(var))))
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Resource TestWebSocket::Connect(const std::string& url,
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   int32_t* result,
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const std::string& protocol) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var protocols[] = { PP_MakeUndefined() };
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ws)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var url_var = CreateVarString(url);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t protocol_count = 0U;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (protocol.size()) {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    protocols[0] = CreateVarString(protocol);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    protocol_count = 1U;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.WaitForResult(websocket_interface_->Connect(
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, url_var, protocols, protocol_count,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.GetCallback().pp_completion_callback()));
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(url_var);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (protocol.size())
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReleaseVar(protocols[0]);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *result = callback.result();
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ws;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
324558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid TestWebSocket::Send(int32_t /* result */, PP_Resource ws,
325558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                         const std::string& message) {
326558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  PP_Var message_var = CreateVarString(message);
327558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  websocket_interface_->SendMessage(ws, message_var);
328558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  ReleaseVar(message_var);
329558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
330558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestIsWebSocket() {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test that a NULL resource isn't a websocket.
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Resource null_resource;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Bool result =
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      websocket_interface_->IsWebSocket(null_resource.pp_resource());
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(result);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->IsWebSocket(ws);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(result);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestUninitializedPropertiesAccess() {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64_t bufferedAmount = websocket_interface_->GetBufferedAmount(ws);
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0U, bufferedAmount);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint16_t close_code = websocket_interface_->GetCloseCode(ws);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0U, close_code);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var close_reason = websocket_interface_->GetCloseReason(ws);
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(AreEqualWithString(close_reason, std::string()));
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(close_reason);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Bool close_was_clean = websocket_interface_->GetCloseWasClean(ws);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_FALSE, close_was_clean);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var extensions = websocket_interface_->GetExtensions(ws);
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(AreEqualWithString(extensions, std::string()));
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(extensions);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var protocol = websocket_interface_->GetProtocol(ws);
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(AreEqualWithString(protocol, std::string()));
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(protocol);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_WebSocketReadyState ready_state =
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      websocket_interface_->GetReadyState(ws);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_WEBSOCKETREADYSTATE_INVALID, ready_state);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var url = websocket_interface_->GetURL(ws);
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(AreEqualWithString(url, std::string()));
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(url);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestInvalidConnect() {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var protocols[] = { PP_MakeUndefined() };
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.WaitForResult(websocket_interface_->Connect(
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, PP_MakeUndefined(), protocols, 1U,
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.GetCallback().pp_completion_callback()));
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.WaitForResult(websocket_interface_->Connect(
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, PP_MakeUndefined(), protocols, 1U,
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.GetCallback().pp_completion_callback()));
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_INPROGRESS, callback.result());
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; kInvalidURLs[i]; ++i) {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t result;
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ws = Connect(kInvalidURLs[i], &result, std::string());
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(ws);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core_interface_->ReleaseResource(ws);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestProtocols() {
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var url = CreateVarString(GetFullURL(kEchoServerURL).c_str());
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var bad_protocols[] = {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateVarString("x-test"),
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateVarString("x-test")
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var good_protocols[] = {
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateVarString("x-test"),
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateVarString("x-yatest")
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.WaitForResult(websocket_interface_->Connect(
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, url, bad_protocols, 2U,
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.GetCallback().pp_completion_callback()));
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ws = websocket_interface_->Create(instance_->pp_instance());
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result = websocket_interface_->Connect(
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, url, good_protocols, 2U, PP_BlockUntilComplete());
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_BLOCKS_MAIN_THREAD, result);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(url);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 2; ++i) {
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReleaseVar(bad_protocols[i]);
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReleaseVar(good_protocols[i]);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestGetURL() {
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; kInvalidURLs[i]; ++i) {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t result;
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PP_Resource ws = Connect(kInvalidURLs[i], &result, std::string());
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(ws);
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_Var url = websocket_interface_->GetURL(ws);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(AreEqualWithString(url, kInvalidURLs[i]));
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReleaseVar(url);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core_interface_->ReleaseResource(ws);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestValidConnect() {
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result;
473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PP_Resource ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var extensions = websocket_interface_->GetExtensions(ws);
477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(AreEqualWithString(extensions, std::string()));
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseVar(extensions);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestInvalidClose() {
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var reason = CreateVarString("close for test");
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback async_callback(instance_->pp_instance(), PP_REQUIRED);
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close before connect.
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.WaitForResult(websocket_interface_->Close(
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.GetCallback().pp_completion_callback()));
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_FAILED, callback.result());
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close with bad arguments.
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result;
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.WaitForResult(websocket_interface_->Close(
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, 1U, reason, callback.GetCallback().pp_completion_callback()));
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_NOACCESS, callback.result());
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close with PP_VARTYPE_NULL.
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.WaitForResult(websocket_interface_->Close(
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeNull(),
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.GetCallback().pp_completion_callback()));
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close with PP_VARTYPE_NULL and ongoing receive message.
518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var receive_message_var;
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->ReceiveMessage(
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, &receive_message_var,
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      async_callback.GetCallback().pp_completion_callback());
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.WaitForResult(websocket_interface_->Close(
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeNull(),
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.GetCallback().pp_completion_callback()));
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* send_message = "hi";
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var send_message_var = CreateVarString(send_message);
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->SendMessage(ws, send_message_var);
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(send_message_var);
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  async_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, async_callback.result());
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(AreEqualWithString(receive_message_var, send_message));
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(receive_message_var);
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close twice.
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->Close(
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      async_callback.GetCallback().pp_completion_callback());
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Call another Close() before previous one is in progress.
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->Close(
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.GetCallback().pp_completion_callback());
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_INPROGRESS, result);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  async_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, async_callback.result());
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Call another Close() after previous one is completed.
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This Close() must do nothing and reports no error.
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.WaitForResult(websocket_interface_->Close(
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.GetCallback().pp_completion_callback()));
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(reason);
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestValidClose() {
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var reason = CreateVarString("close for test");
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var url = CreateVarString(GetFullURL(kEchoServerURL).c_str());
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var protocols[] = { PP_MakeUndefined() };
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback another_callback(
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      instance_->pp_instance(), callback_type());
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close.
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result;
579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PP_Resource ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.WaitForResult(websocket_interface_->Close(
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.GetCallback().pp_completion_callback()));
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close without code and reason.
590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.WaitForResult(websocket_interface_->Close(
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED, reason,
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.GetCallback().pp_completion_callback()));
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close with PP_VARTYPE_UNDEFINED.
600c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.WaitForResult(websocket_interface_->Close(
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(),
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.GetCallback().pp_completion_callback()));
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close in connecting.
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The ongoing connect failed with PP_ERROR_ABORTED, then the close is done
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // successfully.
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ws = websocket_interface_->Create(instance_->pp_instance());
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->Connect(
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, url, protocols, 0U, callback.GetCallback().pp_completion_callback());
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->Close(
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      another_callback.GetCallback().pp_completion_callback());
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.WaitForResult(PP_OK_COMPLETIONPENDING);
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  another_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, another_callback.result());
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close in closing.
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The first close will be done successfully, then the second one failed with
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with PP_ERROR_INPROGRESS immediately.
630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->Close(
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.GetCallback().pp_completion_callback());
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->Close(
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      another_callback.GetCallback().pp_completion_callback());
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_INPROGRESS, result);
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.WaitForResult(PP_OK_COMPLETIONPENDING);
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close with ongoing receive message.
646c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var receive_message_var;
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->ReceiveMessage(
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, &receive_message_var,
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.GetCallback().pp_completion_callback());
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->Close(
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      another_callback.GetCallback().pp_completion_callback());
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.WaitForResult(PP_OK_COMPLETIONPENDING);
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  another_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, another_callback.result());
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close with PP_VARTYPE_UNDEFINED and ongoing receive message.
665c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->ReceiveMessage(
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, &receive_message_var,
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.GetCallback().pp_completion_callback());
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->Close(
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(),
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      another_callback.GetCallback().pp_completion_callback());
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.WaitForResult(PP_OK_COMPLETIONPENDING);
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  another_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, another_callback.result());
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Server initiated closing handshake.
683c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ws = Connect(
684c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetFullURL(kCloseWithCodeAndReasonServerURL), &result, std::string());
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Text messsage "1000 bye" requests the server to initiate closing handshake
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with code being 1000 and reason being "bye".
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var close_request_var = CreateVarString("1000 bye");
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->SendMessage(ws, close_request_var);
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(close_request_var);
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.WaitForResult(websocket_interface_->ReceiveMessage(
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, &receive_message_var,
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.GetCallback().pp_completion_callback()));
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_FAILED, callback.result());
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(reason);
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(url);
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestGetProtocol() {
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* expected_protocols[] = {
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "x-chat",
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "hoehoe",
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NULL
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; expected_protocols[i]; ++i) {
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string url(GetFullURL(kProtocolTestServerURL));
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    url += expected_protocols[i];
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t result;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_Resource ws = Connect(url.c_str(), &result, expected_protocols[i]);
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(ws);
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_OK, result);
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_Var protocol = websocket_interface_->GetProtocol(ws);
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(AreEqualWithString(protocol, expected_protocols[i]));
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReleaseVar(protocol);
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core_interface_->ReleaseResource(ws);
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestTextSendReceive() {
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Connect to test echo server.
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t connect_result;
731c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PP_Resource ws =
732c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Connect(GetFullURL(kEchoServerURL), &connect_result, std::string());
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, connect_result);
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send 'hello pepper' text message.
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* message = "hello pepper";
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var message_var = CreateVarString(message);
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result = websocket_interface_->SendMessage(ws, message_var);
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(message_var);
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Receive echoed 'hello pepper'.
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var received_message;
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.WaitForResult(websocket_interface_->ReceiveMessage(
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, &received_message, callback.GetCallback().pp_completion_callback()));
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(AreEqualWithString(received_message, message));
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(received_message);
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
756558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Run as a BACKGROUND test.
757558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochstd::string TestWebSocket::TestTextSendReceiveTwice() {
758558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Connect to test echo server.
759558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  int32_t connect_result;
760558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  PP_Resource ws =
761558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      Connect(GetFullURL(kEchoServerURL), &connect_result, std::string());
762558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  ASSERT_TRUE(ws);
763558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  ASSERT_EQ(PP_OK, connect_result);
764558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  pp::MessageLoop message_loop = pp::MessageLoop::GetCurrent();
765558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  pp::CompletionCallbackFactory<TestWebSocket> factory(this);
766558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
767558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  message_loop.PostWork(factory.NewCallback(&TestWebSocket::Send,
768558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                                            ws, std::string("hello")));
769558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // When the server receives 'Goodbye', it closes the session.
770558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  message_loop.PostWork(factory.NewCallback(&TestWebSocket::Send,
771558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                                            ws, std::string("Goodbye")));
772558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  message_loop.PostQuit(false);
773558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  message_loop.Run();
774558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
775558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
776558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  PP_Var received_message;
777558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  int32_t result = websocket_interface_->ReceiveMessage(
778558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      ws, &received_message, callback.GetCallback().pp_completion_callback());
779558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  ASSERT_EQ(PP_OK, result);
780558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Since we don't run the message loop, the callback will stay
781558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // "pending and scheduled to run" state.
782558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
783558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Waiting for the connection close which will be done by the server.
784558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  while (true) {
785558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    PP_WebSocketReadyState ready_state =
786558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        websocket_interface_->GetReadyState(ws);
787558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    if (ready_state != PP_WEBSOCKETREADYSTATE_CONNECTING &&
788558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        ready_state != PP_WEBSOCKETREADYSTATE_OPEN) {
789558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      break;
790558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    }
791558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    PlatformSleep(100);  // 100ms
792558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
793558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
794558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Cleanup the message loop
795558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  message_loop.PostQuit(false);
796558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  message_loop.Run();
797558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
798558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  ASSERT_EQ(PP_OK, callback.result());
799558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  ASSERT_TRUE(AreEqualWithString(received_message, "hello"));
800558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  ReleaseVar(received_message);
801558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  core_interface_->ReleaseResource(ws);
802558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  PASS();
803558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
804558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestBinarySendReceive() {
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Connect to test echo server.
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t connect_result;
808c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PP_Resource ws =
809c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Connect(GetFullURL(kEchoServerURL), &connect_result, std::string());
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, connect_result);
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send binary message.
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<uint8_t> binary(256);
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (uint32_t i = 0; i < binary.size(); ++i)
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    binary[i] = i;
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var message_var = CreateVarBinary(binary);
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result = websocket_interface_->SendMessage(ws, message_var);
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(message_var);
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Receive echoed binary.
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var received_message;
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.WaitForResult(websocket_interface_->ReceiveMessage(
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, &received_message, callback.GetCallback().pp_completion_callback()));
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(AreEqualWithBinary(received_message, binary));
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(received_message);
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestStressedSendReceive() {
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Connect to test echo server.
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t connect_result;
838c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PP_Resource ws =
839c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Connect(GetFullURL(kEchoServerURL), &connect_result, std::string());
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, connect_result);
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prepare PP_Var objects to send.
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* text = "hello pepper";
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var text_var = CreateVarString(text);
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<uint8_t> binary(256);
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (uint32_t i = 0; i < binary.size(); ++i)
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    binary[i] = i;
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var binary_var = CreateVarBinary(binary);
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prepare very large binary data over 64KiB. Object serializer in
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ppapi_proxy has a limitation of 64KiB as maximum return PP_Var data size
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to SRPC. In case received data over 64KiB exists, a specific code handles
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this large data via asynchronous callback from main thread. This data
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // intends to test the code.
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<uint8_t> large_binary(65 * 1024);
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (uint32_t i = 0; i < large_binary.size(); ++i)
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    large_binary[i] = i & 0xff;
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var large_binary_var = CreateVarBinary(large_binary);
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send many messages.
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result;
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 256; ++i) {
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = websocket_interface_->SendMessage(ws, text_var);
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_OK, result);
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = websocket_interface_->SendMessage(ws, binary_var);
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_OK, result);
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->SendMessage(ws, large_binary_var);
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(text_var);
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(binary_var);
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(large_binary_var);
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Receive echoed data.
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i <= 512; ++i) {
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_Var received_message;
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback.WaitForResult(websocket_interface_->ReceiveMessage(
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ws, &received_message,
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        callback.GetCallback().pp_completion_callback()));
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_OK, callback.result());
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i == 512) {
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(AreEqualWithBinary(received_message, large_binary));
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (i & 1) {
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(AreEqualWithBinary(received_message, binary));
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(AreEqualWithString(received_message, text));
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReleaseVar(received_message);
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestBufferedAmount() {
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Connect to test echo server.
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t connect_result;
899c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PP_Resource ws =
900c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Connect(GetFullURL(kEchoServerURL), &connect_result, std::string());
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, connect_result);
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prepare a large message that is not aligned with the internal buffer
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sizes.
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string message(8193, 'x');
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var message_var = CreateVarString(message);
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64_t buffered_amount = 0;
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result;
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 100; i++) {
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = websocket_interface_->SendMessage(ws, message_var);
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_OK, result);
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffered_amount = websocket_interface_->GetBufferedAmount(ws);
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Buffered amount size 262144 is too big for the internal buffer size.
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (buffered_amount > 262144)
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close connection.
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string reason_str = "close while busy";
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var reason = CreateVarString(reason_str.c_str());
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->Close(
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.GetCallback().pp_completion_callback());
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSING,
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      websocket_interface_->GetReadyState(ws));
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.WaitForResult(result);
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED,
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      websocket_interface_->GetReadyState(ws));
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64_t base_buffered_amount = websocket_interface_->GetBufferedAmount(ws);
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // After connection closure, all sending requests fail and just increase
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the bufferedAmount property.
940c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PP_Var empty_string = CreateVarString(std::string());
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->SendMessage(ws, empty_string);
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_FAILED, result);
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffered_amount = websocket_interface_->GetBufferedAmount(ws);
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(base_buffered_amount + kMessageFrameOverhead, buffered_amount);
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base_buffered_amount = buffered_amount;
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->SendMessage(ws, reason);
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_FAILED, result);
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffered_amount = websocket_interface_->GetBufferedAmount(ws);
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64_t reason_frame_size = kMessageFrameOverhead + reason_str.length();
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(base_buffered_amount + reason_frame_size, buffered_amount);
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(message_var);
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(reason);
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(empty_string);
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test abort behaviors where a WebSocket PP_Resource is released while each
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// function is in-flight on the WebSocket PP_Resource.
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestAbortCallsWithCallback() {
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Following tests make sure the behavior for functions which require a
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // callback. The callback must get a PP_ERROR_ABORTED.
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test the behavior for Connect().
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url = GetFullURL(kEchoServerURL);
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var url_var = CreateVarString(url);
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback connect_callback(
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      instance_->pp_instance(), callback_type());
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result = websocket_interface_->Connect(
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, url_var, NULL, 0,
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connect_callback.GetCallback().pp_completion_callback());
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connect_callback.WaitForResult(result);
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_ABORTED, connect_callback.result());
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test the behavior for Close().
983c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ws = Connect(url, &result, std::string());
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var reason_var = CreateVarString("abort");
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback close_callback(
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      instance_->pp_instance(), callback_type());
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->Close(
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason_var,
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      close_callback.GetCallback().pp_completion_callback());
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  close_callback.WaitForResult(result);
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_ABORTED, close_callback.result());
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(reason_var);
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test the behavior for ReceiveMessage().
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure the simplest case to wait for data which never arrives, here.
1000c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ws = Connect(url, &result, std::string());
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var receive_var;
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback receive_callback(
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      instance_->pp_instance(), callback_type());
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->ReceiveMessage(
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, &receive_var,
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      receive_callback.GetCallback().pp_completion_callback());
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  receive_callback.WaitForResult(result);
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_ABORTED, receive_callback.result());
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Release the resource in the aborting receive completion callback which is
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // introduced by calling Close().
1016c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ws = Connect(url, &result, std::string());
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->ReceiveMessage(
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, &receive_var,
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      receive_callback.GetCallback().pp_completion_callback());
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseResourceDelegate receive_delegate(core_interface_, ws);
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  receive_callback.SetDelegate(&receive_delegate);
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->Close(
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(),
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      close_callback.GetCallback().pp_completion_callback());
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  receive_callback.WaitForResult(result);
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(receive_callback);
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_ABORTED, receive_callback.result());
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  close_callback.WaitForResult(result);
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(close_callback);
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_ABORTED, close_callback.result());
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(url_var);
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestAbortSendMessageCall() {
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test the behavior for SendMessage().
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This function doesn't require a callback, but operation will be done
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // asynchronously in WebKit and browser process.
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<uint8_t> large_binary(65 * 1024);
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var large_var = CreateVarBinary(large_binary);
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result;
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url = GetFullURL(kEchoServerURL);
1050c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PP_Resource ws = Connect(url, &result, std::string());
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->SendMessage(ws, large_var);
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_interface_->ReleaseResource(ws);
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(large_var);
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestAbortCloseCall() {
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Release the resource in the close completion callback.
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result;
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url = GetFullURL(kEchoServerURL);
1065c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PP_Resource ws = Connect(url, &result, std::string());
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ws);
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback close_callback(
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      instance_->pp_instance(), callback_type());
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket_interface_->Close(
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(),
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      close_callback.GetCallback().pp_completion_callback());
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseResourceDelegate close_delegate(core_interface_, ws);
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  close_callback.SetDelegate(&close_delegate);
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  close_callback.WaitForResult(result);
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(close_callback);
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, close_callback.result());
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestAbortReceiveMessageCall() {
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test the behavior where receive process might be in-flight.
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<uint8_t> large_binary(65 * 1024);
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var large_var = CreateVarBinary(large_binary);
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* text = "yukarin";
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var text_var = CreateVarString(text);
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url = GetFullURL(kEchoServerURL);
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result;
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Resource ws;
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Each trial sends |trial_count| + 1 messages and receives just |trial|
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // number of message(s) before releasing the WebSocket. The WebSocket is
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // released while the next message is going to be received.
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int trial_count = 8;
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int trial = 1; trial <= trial_count; trial++) {
1098c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ws = Connect(url, &result, std::string());
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(ws);
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_OK, result);
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i <= trial_count; ++i) {
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = websocket_interface_->SendMessage(ws, text_var);
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(PP_OK, result);
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestCompletionCallback callback(instance_->pp_instance(), callback_type());
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_Var var;
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < trial; ++i) {
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.WaitForResult(websocket_interface_->ReceiveMessage(
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ws, &var, callback.GetCallback().pp_completion_callback()));
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(PP_OK, callback.result());
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(AreEqualWithString(var, text));
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReleaseVar(var);
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = websocket_interface_->ReceiveMessage(
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ws, &var, callback.GetCallback().pp_completion_callback());
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core_interface_->ReleaseResource(ws);
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result != PP_OK) {
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.WaitForResult(result);
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Same test, but the last receiving message is large message over 64KiB.
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int trial = 1; trial <= trial_count; trial++) {
1124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ws = Connect(url, &result, std::string());
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(ws);
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_OK, result);
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i <= trial_count; ++i) {
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i == trial)
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = websocket_interface_->SendMessage(ws, large_var);
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = websocket_interface_->SendMessage(ws, text_var);
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(PP_OK, result);
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestCompletionCallback callback(instance_->pp_instance(), callback_type());
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_Var var;
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < trial; ++i) {
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.WaitForResult(websocket_interface_->ReceiveMessage(
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ws, &var, callback.GetCallback().pp_completion_callback()));
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(PP_OK, callback.result());
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(AreEqualWithString(var, text));
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReleaseVar(var);
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = websocket_interface_->ReceiveMessage(
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ws, &var, callback.GetCallback().pp_completion_callback());
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core_interface_->ReleaseResource(ws);
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result != PP_OK) {
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.WaitForResult(result);
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(large_var);
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseVar(text_var);
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestCcInterfaces() {
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // C++ bindings is simple straightforward, then just verifies interfaces work
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // as a interface bridge fine.
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::WebSocket ws(instance_);
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check uninitialized properties access.
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, ws.GetBufferedAmount());
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, ws.GetCloseCode());
1166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(AreEqualWithString(ws.GetCloseReason().pp_var(), std::string()));
11675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_FALSE(ws.GetCloseWasClean());
1168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(AreEqualWithString(ws.GetExtensions().pp_var(), std::string()));
1169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(AreEqualWithString(ws.GetProtocol().pp_var(), std::string()));
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_WEBSOCKETREADYSTATE_INVALID, ws.GetReadyState());
1171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(AreEqualWithString(ws.GetURL().pp_var(), std::string()));
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check communication interfaces (connect, send, receive, and close).
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback connect_callback(
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      instance_->pp_instance(), callback_type());
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connect_callback.WaitForResult(ws.Connect(
11772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pp::Var(GetFullURL(kCloseServerURL)), NULL, 0U,
11782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              connect_callback.GetCallback()));
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(connect_callback);
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, connect_callback.result());
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string text_message("hello C++");
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result = ws.SendMessage(pp::Var(text_message));
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<uint8_t> binary(256);
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (uint32_t i = 0; i < binary.size(); ++i)
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    binary[i] = i;
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = ws.SendMessage(
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::Var(pp::PASS_REF, CreateVarBinary(binary)));
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Var text_receive_var;
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback text_receive_callback(
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      instance_->pp_instance(), callback_type());
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  text_receive_callback.WaitForResult(
11972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ws.ReceiveMessage(&text_receive_var,
11982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        text_receive_callback.GetCallback()));
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, text_receive_callback.result());
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AreEqualWithString(text_receive_var.pp_var(), text_message.c_str()));
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Var binary_receive_var;
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback binary_receive_callback(
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      instance_->pp_instance(), callback_type());
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  binary_receive_callback.WaitForResult(
12072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ws.ReceiveMessage(&binary_receive_var,
12082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        binary_receive_callback.GetCallback()));
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, binary_receive_callback.result());
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(AreEqualWithBinary(binary_receive_var.pp_var(), binary));
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback close_callback(
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      instance_->pp_instance(), callback_type());
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string reason("bye");
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  close_callback.WaitForResult(ws.Close(
12162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason),
12172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      close_callback.GetCallback()));
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(close_callback);
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, close_callback.result());
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check initialized properties access.
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, ws.GetBufferedAmount());
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, ws.GetCloseCode());
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AreEqualWithString(ws.GetCloseReason().pp_var(), reason.c_str()));
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(true, ws.GetCloseWasClean());
1227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(AreEqualWithString(ws.GetProtocol().pp_var(), std::string()));
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED, ws.GetReadyState());
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(AreEqualWithString(
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws.GetURL().pp_var(), GetFullURL(kCloseServerURL).c_str()));
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestUtilityInvalidConnect() {
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const pp::Var protocols[] = { pp::Var() };
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestWebSocketAPI websocket(instance_);
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result = websocket.Connect(pp::Var(), protocols, 1U);
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0U, websocket.GetSeenEvents().size());
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket.Connect(pp::Var(), protocols, 1U);
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_INPROGRESS, result);
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0U, websocket.GetSeenEvents().size());
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; kInvalidURLs[i]; ++i) {
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestWebSocketAPI ws(instance_);
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = ws.Connect(pp::Var(std::string(kInvalidURLs[i])), protocols, 0U);
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result == PP_OK_COMPLETIONPENDING) {
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ws.WaitForClosed();
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::vector<WebSocketEvent>& events = ws.GetSeenEvents();
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[0].event_type);
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type);
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(2U, ws.GetSeenEvents().size());
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(0U, ws.GetSeenEvents().size());
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestUtilityProtocols() {
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const pp::Var bad_protocols[] = {
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::Var(std::string("x-test")), pp::Var(std::string("x-test")) };
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const pp::Var good_protocols[] = {
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::Var(std::string("x-test")), pp::Var(std::string("x-yatest")) };
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestWebSocketAPI websocket(instance_);
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t result = websocket.Connect(
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pp::Var(GetFullURL(kEchoServerURL)), bad_protocols, 2U);
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(0U, websocket.GetSeenEvents().size());
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestWebSocketAPI websocket(instance_);
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t result = websocket.Connect(
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pp::Var(GetFullURL(kEchoServerURL)), good_protocols, 2U);
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    websocket.WaitForConnected();
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Protocol arguments are valid, but this test run without a WebSocket
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // server. As a result, OnError() and OnClose() are invoked because of
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // a connection establishment failure.
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(2U, events.size());
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[0].event_type);
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type);
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_FALSE(events[1].was_clean);
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestUtilityGetURL() {
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const pp::Var protocols[] = { pp::Var() };
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; kInvalidURLs[i]; ++i) {
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestWebSocketAPI websocket(instance_);
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t result = websocket.Connect(
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pp::Var(std::string(kInvalidURLs[i])), protocols, 0U);
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result == PP_OK_COMPLETIONPENDING) {
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      websocket.WaitForClosed();
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[0].event_type);
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type);
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(2U, events.size());
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(0U, websocket.GetSeenEvents().size());
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::Var url = websocket.GetURL();
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(AreEqualWithString(url.pp_var(), kInvalidURLs[i]));
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestUtilityValidConnect() {
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const pp::Var protocols[] = { pp::Var() };
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestWebSocketAPI websocket(instance_);
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result = websocket.Connect(
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::Var(GetFullURL(kEchoServerURL)), protocols, 0U);
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  websocket.WaitForConnected();
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1U, events.size());
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
1332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(
1333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      AreEqualWithString(websocket.GetExtensions().pp_var(), std::string()));
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestUtilityInvalidClose() {
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const pp::Var reason = pp::Var(std::string("close for test"));
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close before connect.
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestWebSocketAPI websocket(instance_);
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t result = websocket.Close(
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason);
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_ERROR_FAILED, result);
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(0U, websocket.GetSeenEvents().size());
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close with bad arguments.
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestWebSocketAPI websocket(instance_);
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t result = websocket.Connect(pp::Var(GetFullURL(kEchoServerURL)),
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NULL, 0);
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    websocket.WaitForConnected();
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = websocket.Close(1U, reason);
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_ERROR_NOACCESS, result);
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(1U, events.size());
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestUtilityValidClose() {
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string reason("close for test");
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Var url = pp::Var(GetFullURL(kCloseServerURL));
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close.
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestWebSocketAPI websocket(instance_);
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t result = websocket.Connect(url, NULL, 0U);
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    websocket.WaitForConnected();
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = websocket.Close(
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    websocket.WaitForClosed();
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(2U, events.size());
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type);
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(events[1].was_clean);
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, events[1].close_code);
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(AreEqualWithString(events[1].var.pp_var(), reason.c_str()));
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close in connecting.
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The ongoing connect failed with PP_ERROR_ABORTED, then the close is done
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // successfully.
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestWebSocketAPI websocket(instance_);
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t result = websocket.Connect(url, NULL, 0U);
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = websocket.Close(
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    websocket.WaitForClosed();
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(events.size() == 2 || events.size() == 3);
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int index = 0;
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (events.size() == 3)
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[index++].event_type);
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[index++].event_type);
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[index].event_type);
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_FALSE(events[index].was_clean);
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close in closing.
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The first close will be done successfully, then the second one failed with
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with PP_ERROR_INPROGRESS immediately.
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestWebSocketAPI websocket(instance_);
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t result = websocket.Connect(url, NULL, 0U);
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = websocket.Close(
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = websocket.Close(
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_ERROR_INPROGRESS, result);
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    websocket.WaitForClosed();
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
1425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_TRUE(events.size() == 2 || events.size() == 3);
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int index = 0;
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (events.size() == 3)
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[index++].event_type);
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[index++].event_type);
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[index].event_type);
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_FALSE(events[index].was_clean);
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestUtilityGetProtocol() {
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string protocol("x-chat");
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const pp::Var protocols[] = { pp::Var(protocol) };
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url(GetFullURL(kProtocolTestServerURL));
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url += protocol;
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestWebSocketAPI websocket(instance_);
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result = websocket.Connect(pp::Var(url), protocols, 1U);
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  websocket.WaitForReceived();
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(AreEqualWithString(
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      websocket.GetProtocol().pp_var(), protocol.c_str()));
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The server to which this test connect returns the decided protocol as a
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // text frame message. So the WebSocketEvent records EVENT_MESSAGE event
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // after EVENT_OPEN event.
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2U, events.size());
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type);
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(AreEqualWithString(events[1].var.pp_var(), protocol.c_str()));
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestUtilityTextSendReceive() {
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const pp::Var protocols[] = { pp::Var() };
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestWebSocketAPI websocket(instance_);
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result =
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      websocket.Connect(pp::Var(GetFullURL(kEchoServerURL)), protocols, 0U);
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  websocket.WaitForConnected();
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send 'hello pepper'.
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string message1("hello pepper");
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket.Send(pp::Var(std::string(message1)));
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Receive echoed 'hello pepper'.
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  websocket.WaitForReceived();
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send 'goodbye pepper'.
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string message2("goodbye pepper");
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket.Send(pp::Var(std::string(message2)));
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Receive echoed 'goodbye pepper'.
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  websocket.WaitForReceived();
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(3U, events.size());
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type);
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(AreEqualWithString(events[1].var.pp_var(), message1.c_str()));
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[2].event_type);
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(AreEqualWithString(events[2].var.pp_var(), message2.c_str()));
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestUtilityBinarySendReceive() {
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const pp::Var protocols[] = { pp::Var() };
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestWebSocketAPI websocket(instance_);
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result =
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      websocket.Connect(pp::Var(GetFullURL(kEchoServerURL)), protocols, 0U);
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  websocket.WaitForConnected();
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send binary message.
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t len = 256;
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<uint8_t> binary(len);
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (uint32_t i = 0; i < len; ++i)
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    binary[i] = i;
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::VarArrayBuffer message(len);
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8_t* var_data = static_cast<uint8_t*>(message.Map());
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::copy(binary.begin(), binary.end(), var_data);
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket.Send(message);
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK, result);
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Receive echoed binary message.
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  websocket.WaitForReceived();
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2U, events.size());
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type);
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(AreEqualWithBinary(events[1].var.pp_var(), binary));
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestWebSocket::TestUtilityBufferedAmount() {
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Connect to test echo server.
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const pp::Var protocols[] = { pp::Var() };
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestWebSocketAPI websocket(instance_);
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result =
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      websocket.Connect(pp::Var(GetFullURL(kEchoServerURL)), protocols, 0U);
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  websocket.WaitForConnected();
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prepare a large message that is not aligned with the internal buffer
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sizes.
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string message(8193, 'x');
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64_t buffered_amount = 0;
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t sent;
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (sent = 0; sent < 100; sent++) {
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = websocket.Send(pp::Var(message));
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(PP_OK, result);
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffered_amount = websocket.GetBufferedAmount();
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Buffered amount size 262144 is too big for the internal buffer size.
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (buffered_amount > 262144)
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close connection.
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string reason = "close while busy";
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket.Close(
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSING, websocket.GetReadyState());
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  websocket.WaitForClosed();
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED, websocket.GetReadyState());
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64_t base_buffered_amount = websocket.GetBufferedAmount();
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t events_on_closed = websocket.GetSeenEvents().size();
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // After connection closure, all sending requests fail and just increase
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the bufferedAmount property.
1561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  result = websocket.Send(pp::Var(std::string()));
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_FAILED, result);
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffered_amount = websocket.GetBufferedAmount();
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(base_buffered_amount + kMessageFrameOverhead, buffered_amount);
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base_buffered_amount = buffered_amount;
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = websocket.Send(pp::Var(reason));
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_FAILED, result);
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffered_amount = websocket.GetBufferedAmount();
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64_t reason_frame_size = kMessageFrameOverhead + reason.length();
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(base_buffered_amount + reason_frame_size, buffered_amount);
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(events_on_closed, events.size());
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t last_event = events_on_closed - 1;
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (uint32_t i = 1; i < last_event; ++i) {
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[i].event_type);
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(AreEqualWithString(events[i].var.pp_var(), message));
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[last_event].event_type);
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(events[last_event].was_clean);
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1586