123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ppapi/tests/test_websocket.h"
- #include <stddef.h>
- #include <stdio.h>
- #include <string.h>
- #include <algorithm>
- #include <memory>
- #include <string>
- #include <vector>
- #include "ppapi/c/pp_bool.h"
- #include "ppapi/c/pp_completion_callback.h"
- #include "ppapi/c/pp_errors.h"
- #include "ppapi/c/pp_instance.h"
- #include "ppapi/c/pp_resource.h"
- #include "ppapi/c/pp_var.h"
- #include "ppapi/c/ppb_core.h"
- #include "ppapi/c/ppb_var.h"
- #include "ppapi/c/ppb_var_array_buffer.h"
- #include "ppapi/c/ppb_websocket.h"
- #include "ppapi/c/private/ppb_testing_private.h"
- #include "ppapi/cpp/instance.h"
- #include "ppapi/cpp/module.h"
- #include "ppapi/cpp/var_array_buffer.h"
- #include "ppapi/cpp/websocket.h"
- #include "ppapi/tests/test_utils.h"
- #include "ppapi/tests/testing_instance.h"
- #include "ppapi/utility/websocket/websocket_api.h"
- // net::SpawnedTestServer serves WebSocket service for testing.
- // Following URLs are handled by pywebsocket handlers in
- // net/data/websocket/*_wsh.py.
- const char kEchoServerURL[] = "echo-with-no-extension";
- const char kCloseServerURL[] = "close";
- const char kCloseWithCodeAndReasonServerURL[] = "close-code-and-reason";
- const char kProtocolTestServerURL[] = "protocol-test?protocol=";
- const char* const kInvalidURLs[] = {"http://www.google.com/invalid_scheme",
- "ws://www.google.com/invalid#fragment",
- "ws://www.google.com:7/invalid_port",
- NULL};
- // Internal packet sizes.
- const uint64_t kMessageFrameOverhead = 6;
- namespace {
- struct WebSocketEvent {
- enum EventType {
- EVENT_OPEN,
- EVENT_MESSAGE,
- EVENT_ERROR,
- EVENT_CLOSE
- };
- WebSocketEvent(EventType type,
- bool was_clean,
- uint16_t close_code,
- const pp::Var& var)
- : event_type(type),
- was_clean(was_clean),
- close_code(close_code),
- var(var) {
- }
- EventType event_type;
- bool was_clean;
- uint16_t close_code;
- pp::Var var;
- };
- class ReleaseResourceDelegate : public TestCompletionCallback::Delegate {
- public:
- explicit ReleaseResourceDelegate(const PPB_Core* core_interface,
- PP_Resource resource)
- : core_interface_(core_interface),
- resource_(resource) {
- }
- // TestCompletionCallback::Delegate implementation.
- virtual void OnCallback(void* user_data, int32_t result) {
- if (resource_)
- core_interface_->ReleaseResource(resource_);
- }
- private:
- const PPB_Core* core_interface_;
- PP_Resource resource_;
- };
- class TestWebSocketAPI : public pp::WebSocketAPI {
- public:
- explicit TestWebSocketAPI(pp::Instance* instance)
- : pp::WebSocketAPI(instance),
- connected_(false),
- received_(false),
- closed_(false),
- wait_for_connected_(false),
- wait_for_received_(false),
- wait_for_closed_(false),
- instance_(instance->pp_instance()) {
- }
- virtual void WebSocketDidOpen() {
- events_.push_back(
- WebSocketEvent(WebSocketEvent::EVENT_OPEN, true, 0U, pp::Var()));
- connected_ = true;
- if (wait_for_connected_) {
- GetTestingInterface()->QuitMessageLoop(instance_);
- wait_for_connected_ = false;
- }
- }
- virtual void WebSocketDidClose(
- bool was_clean, uint16_t code, const pp::Var& reason) {
- events_.push_back(
- WebSocketEvent(WebSocketEvent::EVENT_CLOSE, was_clean, code, reason));
- connected_ = true;
- closed_ = true;
- if (wait_for_connected_ || wait_for_closed_) {
- GetTestingInterface()->QuitMessageLoop(instance_);
- wait_for_connected_ = false;
- wait_for_closed_ = false;
- }
- }
- virtual void HandleWebSocketMessage(const pp::Var &message) {
- events_.push_back(
- WebSocketEvent(WebSocketEvent::EVENT_MESSAGE, true, 0U, message));
- received_ = true;
- if (wait_for_received_) {
- GetTestingInterface()->QuitMessageLoop(instance_);
- wait_for_received_ = false;
- received_ = false;
- }
- }
- virtual void HandleWebSocketError() {
- events_.push_back(
- WebSocketEvent(WebSocketEvent::EVENT_ERROR, true, 0U, pp::Var()));
- }
- void WaitForConnected() {
- if (!connected_) {
- wait_for_connected_ = true;
- GetTestingInterface()->RunMessageLoop(instance_);
- }
- }
- void WaitForReceived() {
- if (!received_) {
- wait_for_received_ = true;
- GetTestingInterface()->RunMessageLoop(instance_);
- }
- }
- void WaitForClosed() {
- if (!closed_) {
- wait_for_closed_ = true;
- GetTestingInterface()->RunMessageLoop(instance_);
- }
- }
- const std::vector<WebSocketEvent>& GetSeenEvents() const {
- return events_;
- }
- private:
- std::vector<WebSocketEvent> events_;
- bool connected_;
- bool received_;
- bool closed_;
- bool wait_for_connected_;
- bool wait_for_received_;
- bool wait_for_closed_;
- PP_Instance instance_;
- };
- } // namespace
- REGISTER_TEST_CASE(WebSocket);
- bool TestWebSocket::Init() {
- websocket_interface_ = static_cast<const PPB_WebSocket*>(
- pp::Module::Get()->GetBrowserInterface(PPB_WEBSOCKET_INTERFACE));
- var_interface_ = static_cast<const PPB_Var*>(
- pp::Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE));
- arraybuffer_interface_ = static_cast<const PPB_VarArrayBuffer*>(
- pp::Module::Get()->GetBrowserInterface(
- PPB_VAR_ARRAY_BUFFER_INTERFACE));
- core_interface_ = static_cast<const PPB_Core*>(
- pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE));
- if (!websocket_interface_ || !var_interface_ || !arraybuffer_interface_ ||
- !core_interface_)
- return false;
- return CheckTestingInterface();
- }
- void TestWebSocket::RunTests(const std::string& filter) {
- RUN_TEST_WITH_REFERENCE_CHECK(IsWebSocket, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(UninitializedPropertiesAccess, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(InvalidConnect, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(Protocols, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(GetURL, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(ValidConnect, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(InvalidClose, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(ValidClose, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(GetProtocol, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(TextSendReceive, filter);
- RUN_TEST_BACKGROUND(TestWebSocket, TextSendReceiveTwice, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(BinarySendReceive, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(StressedSendReceive, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(BufferedAmount, filter);
- // PP_Resource for WebSocket may be released later because of an internal
- // reference for asynchronous IPC handling. So, suppress reference check on
- // the following AbortCallsWithCallback test.
- RUN_TEST(AbortCallsWithCallback, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(AbortSendMessageCall, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(AbortCloseCall, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(AbortReceiveMessageCall, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(ClosedFromServerWhileSending, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(CcInterfaces, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(UtilityInvalidConnect, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(UtilityProtocols, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(UtilityGetURL, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(UtilityValidConnect, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(UtilityInvalidClose, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(UtilityValidClose, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(UtilityGetProtocol, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(UtilityTextSendReceive, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(UtilityBinarySendReceive, filter);
- RUN_TEST_WITH_REFERENCE_CHECK(UtilityBufferedAmount, filter);
- }
- std::string TestWebSocket::GetFullURL(const char* url) {
- std::string rv = "ws://";
- // Some WebSocket tests don't start the server so there'll be no host and
- // port.
- if (instance_->websocket_host().empty())
- rv += "127.0.0.1";
- else
- rv += instance_->websocket_host();
- if (instance_->websocket_port() != -1) {
- char buffer[10];
- snprintf(buffer, sizeof(buffer), ":%d", instance_->websocket_port());
- rv += std::string(buffer);
- }
- rv += "/";
- rv += url;
- return rv;
- }
- PP_Var TestWebSocket::CreateVarString(const std::string& string) {
- return var_interface_->VarFromUtf8(string.c_str(),
- static_cast<uint32_t>(string.size()));
- }
- PP_Var TestWebSocket::CreateVarBinary(const std::vector<uint8_t>& binary) {
- PP_Var var =
- arraybuffer_interface_->Create(static_cast<uint32_t>(binary.size()));
- uint8_t* var_data = static_cast<uint8_t*>(arraybuffer_interface_->Map(var));
- std::copy(binary.begin(), binary.end(), var_data);
- return var;
- }
- void TestWebSocket::ReleaseVar(const PP_Var& var) {
- var_interface_->Release(var);
- }
- bool TestWebSocket::AreEqualWithString(const PP_Var& var,
- const std::string& string) {
- if (var.type != PP_VARTYPE_STRING)
- return false;
- uint32_t utf8_length;
- const char* utf8 = var_interface_->VarToUtf8(var, &utf8_length);
- if (utf8_length != string.size())
- return false;
- if (string.compare(utf8))
- return false;
- return true;
- }
- bool TestWebSocket::AreEqualWithBinary(const PP_Var& var,
- const std::vector<uint8_t>& binary) {
- uint32_t buffer_size = 0;
- PP_Bool success = arraybuffer_interface_->ByteLength(var, &buffer_size);
- if (!success || buffer_size != binary.size())
- return false;
- if (!std::equal(binary.begin(), binary.end(),
- static_cast<uint8_t*>(arraybuffer_interface_->Map(var))))
- return false;
- return true;
- }
- PP_Resource TestWebSocket::Connect(const std::string& url,
- int32_t* result,
- const std::string& protocol) {
- PP_Var protocols[] = { PP_MakeUndefined() };
- PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
- if (!ws)
- return 0;
- PP_Var url_var = CreateVarString(url);
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- uint32_t protocol_count = 0U;
- if (protocol.size()) {
- protocols[0] = CreateVarString(protocol);
- protocol_count = 1U;
- }
- callback.WaitForResult(websocket_interface_->Connect(
- ws, url_var, protocols, protocol_count,
- callback.GetCallback().pp_completion_callback()));
- ReleaseVar(url_var);
- if (protocol.size())
- ReleaseVar(protocols[0]);
- *result = callback.result();
- return ws;
- }
- void TestWebSocket::Send(int32_t /* result */, PP_Resource ws,
- const std::string& message) {
- PP_Var message_var = CreateVarString(message);
- websocket_interface_->SendMessage(ws, message_var);
- ReleaseVar(message_var);
- }
- std::string TestWebSocket::TestIsWebSocket() {
- // Test that a NULL resource isn't a websocket.
- pp::Resource null_resource;
- PP_Bool result =
- websocket_interface_->IsWebSocket(null_resource.pp_resource());
- ASSERT_FALSE(result);
- PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
- ASSERT_TRUE(ws);
- result = websocket_interface_->IsWebSocket(ws);
- ASSERT_TRUE(result);
- core_interface_->ReleaseResource(ws);
- PASS();
- }
- std::string TestWebSocket::TestUninitializedPropertiesAccess() {
- PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
- ASSERT_TRUE(ws);
- uint64_t bufferedAmount = websocket_interface_->GetBufferedAmount(ws);
- ASSERT_EQ(0U, bufferedAmount);
- uint16_t close_code = websocket_interface_->GetCloseCode(ws);
- ASSERT_EQ(0U, close_code);
- PP_Var close_reason = websocket_interface_->GetCloseReason(ws);
- ASSERT_TRUE(AreEqualWithString(close_reason, std::string()));
- ReleaseVar(close_reason);
- PP_Bool close_was_clean = websocket_interface_->GetCloseWasClean(ws);
- ASSERT_EQ(PP_FALSE, close_was_clean);
- PP_Var extensions = websocket_interface_->GetExtensions(ws);
- ASSERT_TRUE(AreEqualWithString(extensions, std::string()));
- ReleaseVar(extensions);
- PP_Var protocol = websocket_interface_->GetProtocol(ws);
- ASSERT_TRUE(AreEqualWithString(protocol, std::string()));
- ReleaseVar(protocol);
- PP_WebSocketReadyState ready_state =
- websocket_interface_->GetReadyState(ws);
- ASSERT_EQ(PP_WEBSOCKETREADYSTATE_INVALID, ready_state);
- PP_Var url = websocket_interface_->GetURL(ws);
- ASSERT_TRUE(AreEqualWithString(url, std::string()));
- ReleaseVar(url);
- core_interface_->ReleaseResource(ws);
- PASS();
- }
- std::string TestWebSocket::TestInvalidConnect() {
- PP_Var protocols[] = { PP_MakeUndefined() };
- PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
- ASSERT_TRUE(ws);
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- callback.WaitForResult(websocket_interface_->Connect(
- ws, PP_MakeUndefined(), protocols, 1U,
- callback.GetCallback().pp_completion_callback()));
- ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
- callback.WaitForResult(websocket_interface_->Connect(
- ws, PP_MakeUndefined(), protocols, 1U,
- callback.GetCallback().pp_completion_callback()));
- ASSERT_EQ(PP_ERROR_INPROGRESS, callback.result());
- core_interface_->ReleaseResource(ws);
- for (int i = 0; kInvalidURLs[i]; ++i) {
- int32_t result;
- ws = Connect(kInvalidURLs[i], &result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
- core_interface_->ReleaseResource(ws);
- }
- PASS();
- }
- std::string TestWebSocket::TestProtocols() {
- PP_Var url = CreateVarString(GetFullURL(kEchoServerURL).c_str());
- PP_Var bad_protocols[] = {
- CreateVarString("x-test"),
- CreateVarString("x-test")
- };
- PP_Var good_protocols[] = {
- CreateVarString("x-test"),
- CreateVarString("x-yatest")
- };
- PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
- ASSERT_TRUE(ws);
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- callback.WaitForResult(websocket_interface_->Connect(
- ws, url, bad_protocols, 2U,
- callback.GetCallback().pp_completion_callback()));
- ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
- core_interface_->ReleaseResource(ws);
- ws = websocket_interface_->Create(instance_->pp_instance());
- ASSERT_TRUE(ws);
- int32_t result = websocket_interface_->Connect(
- ws, url, good_protocols, 2U, PP_BlockUntilComplete());
- ASSERT_EQ(PP_ERROR_BLOCKS_MAIN_THREAD, result);
- core_interface_->ReleaseResource(ws);
- ReleaseVar(url);
- for (int i = 0; i < 2; ++i) {
- ReleaseVar(bad_protocols[i]);
- ReleaseVar(good_protocols[i]);
- }
- core_interface_->ReleaseResource(ws);
- PASS();
- }
- std::string TestWebSocket::TestGetURL() {
- for (int i = 0; kInvalidURLs[i]; ++i) {
- int32_t result;
- PP_Resource ws = Connect(kInvalidURLs[i], &result, std::string());
- ASSERT_TRUE(ws);
- PP_Var url = websocket_interface_->GetURL(ws);
- ASSERT_TRUE(AreEqualWithString(url, kInvalidURLs[i]));
- ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
- ReleaseVar(url);
- core_interface_->ReleaseResource(ws);
- }
- PASS();
- }
- std::string TestWebSocket::TestValidConnect() {
- int32_t result;
- PP_Resource ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, result);
- PP_Var extensions = websocket_interface_->GetExtensions(ws);
- ASSERT_TRUE(AreEqualWithString(extensions, std::string()));
- core_interface_->ReleaseResource(ws);
- ReleaseVar(extensions);
- PASS();
- }
- std::string TestWebSocket::TestInvalidClose() {
- PP_Var reason = CreateVarString("close for test");
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- TestCompletionCallback async_callback(instance_->pp_instance(), PP_REQUIRED);
- // Close before connect.
- PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
- callback.WaitForResult(websocket_interface_->Close(
- ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
- callback.GetCallback().pp_completion_callback()));
- ASSERT_EQ(PP_ERROR_FAILED, callback.result());
- core_interface_->ReleaseResource(ws);
- // Close with bad arguments.
- int32_t result;
- ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, result);
- callback.WaitForResult(websocket_interface_->Close(
- ws, 1U, reason, callback.GetCallback().pp_completion_callback()));
- ASSERT_EQ(PP_ERROR_NOACCESS, callback.result());
- core_interface_->ReleaseResource(ws);
- // Close with PP_VARTYPE_NULL.
- ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, result);
- callback.WaitForResult(websocket_interface_->Close(
- ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeNull(),
- callback.GetCallback().pp_completion_callback()));
- ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
- core_interface_->ReleaseResource(ws);
- // Close with PP_VARTYPE_NULL and ongoing receive message.
- ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, result);
- PP_Var receive_message_var;
- result = websocket_interface_->ReceiveMessage(
- ws, &receive_message_var,
- async_callback.GetCallback().pp_completion_callback());
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- callback.WaitForResult(websocket_interface_->Close(
- ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeNull(),
- callback.GetCallback().pp_completion_callback()));
- ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
- const char* send_message = "hi";
- PP_Var send_message_var = CreateVarString(send_message);
- result = websocket_interface_->SendMessage(ws, send_message_var);
- ReleaseVar(send_message_var);
- ASSERT_EQ(PP_OK, result);
- async_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
- ASSERT_EQ(PP_OK, async_callback.result());
- ASSERT_TRUE(AreEqualWithString(receive_message_var, send_message));
- ReleaseVar(receive_message_var);
- core_interface_->ReleaseResource(ws);
- // Close twice.
- ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, result);
- result = websocket_interface_->Close(
- ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
- async_callback.GetCallback().pp_completion_callback());
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- // Call another Close() before previous one is in progress.
- result = websocket_interface_->Close(
- ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
- callback.GetCallback().pp_completion_callback());
- ASSERT_EQ(PP_ERROR_INPROGRESS, result);
- async_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
- ASSERT_EQ(PP_OK, async_callback.result());
- // Call another Close() after previous one is completed.
- // This Close() must do nothing and reports no error.
- callback.WaitForResult(websocket_interface_->Close(
- ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
- callback.GetCallback().pp_completion_callback()));
- ASSERT_EQ(PP_OK, callback.result());
- core_interface_->ReleaseResource(ws);
- ReleaseVar(reason);
- PASS();
- }
- // TODO(tyoshino): Consider splitting this test into smaller ones.
- // http://crbug.com/397035
- std::string TestWebSocket::TestValidClose() {
- PP_Var reason = CreateVarString("close for test");
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- TestCompletionCallback another_callback(
- instance_->pp_instance(), callback_type());
- // Close.
- int32_t result;
- PP_Resource ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, result);
- callback.WaitForResult(websocket_interface_->Close(
- ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
- callback.GetCallback().pp_completion_callback()));
- CHECK_CALLBACK_BEHAVIOR(callback);
- ASSERT_EQ(PP_OK, callback.result());
- core_interface_->ReleaseResource(ws);
- // Close without code and reason.
- ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, result);
- callback.WaitForResult(websocket_interface_->Close(
- ws, PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED, reason,
- callback.GetCallback().pp_completion_callback()));
- CHECK_CALLBACK_BEHAVIOR(callback);
- ASSERT_EQ(PP_OK, callback.result());
- core_interface_->ReleaseResource(ws);
- // Close with PP_VARTYPE_UNDEFINED.
- ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, result);
- callback.WaitForResult(websocket_interface_->Close(
- ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(),
- callback.GetCallback().pp_completion_callback()));
- CHECK_CALLBACK_BEHAVIOR(callback);
- ASSERT_EQ(PP_OK, callback.result());
- core_interface_->ReleaseResource(ws);
- // Close in CONNECTING state.
- // The ongoing Connect() fails with PP_ERROR_ABORTED, then the Close()
- // completes successfully.
- ws = websocket_interface_->Create(instance_->pp_instance());
- PP_Var url = CreateVarString(GetFullURL(kEchoServerURL).c_str());
- PP_Var protocols[] = { PP_MakeUndefined() };
- result = websocket_interface_->Connect(
- ws, url, protocols, 0U, callback.GetCallback().pp_completion_callback());
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- result = websocket_interface_->Close(
- ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
- another_callback.GetCallback().pp_completion_callback());
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- callback.WaitForResult(PP_OK_COMPLETIONPENDING);
- ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
- another_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
- ASSERT_EQ(PP_OK, another_callback.result());
- core_interface_->ReleaseResource(ws);
- ReleaseVar(url);
- // Close while already closing.
- // The first Close will succeed, and the second one will synchronously fail
- // with PP_ERROR_INPROGRESS.
- ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, result);
- result = websocket_interface_->Close(
- ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
- callback.GetCallback().pp_completion_callback());
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- result = websocket_interface_->Close(
- ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
- another_callback.GetCallback().pp_completion_callback());
- ASSERT_EQ(PP_ERROR_INPROGRESS, result);
- callback.WaitForResult(PP_OK_COMPLETIONPENDING);
- ASSERT_EQ(PP_OK, callback.result());
- core_interface_->ReleaseResource(ws);
- // Close with ongoing ReceiveMessage.
- ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, result);
- PP_Var receive_message_var;
- result = websocket_interface_->ReceiveMessage(
- ws, &receive_message_var,
- callback.GetCallback().pp_completion_callback());
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- result = websocket_interface_->Close(
- ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
- another_callback.GetCallback().pp_completion_callback());
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- callback.WaitForResult(PP_OK_COMPLETIONPENDING);
- ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
- another_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
- ASSERT_EQ(PP_OK, another_callback.result());
- core_interface_->ReleaseResource(ws);
- // Close with PP_VARTYPE_UNDEFINED for reason and ongoing ReceiveMessage.
- ws = Connect(GetFullURL(kEchoServerURL), &result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, result);
- result = websocket_interface_->ReceiveMessage(
- ws, &receive_message_var,
- callback.GetCallback().pp_completion_callback());
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- result = websocket_interface_->Close(
- ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(),
- another_callback.GetCallback().pp_completion_callback());
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- callback.WaitForResult(PP_OK_COMPLETIONPENDING);
- ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
- another_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
- ASSERT_EQ(PP_OK, another_callback.result());
- core_interface_->ReleaseResource(ws);
- // Server initiated closing handshake.
- ws = Connect(
- GetFullURL(kCloseWithCodeAndReasonServerURL), &result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, result);
- // Text messsage "1000 bye" requests the server to initiate closing handshake
- // with code being 1000 and reason being "bye".
- PP_Var close_request_var = CreateVarString("1000 bye");
- result = websocket_interface_->SendMessage(ws, close_request_var);
- ReleaseVar(close_request_var);
- callback.WaitForResult(websocket_interface_->ReceiveMessage(
- ws, &receive_message_var,
- callback.GetCallback().pp_completion_callback()));
- ASSERT_EQ(PP_ERROR_FAILED, callback.result());
- core_interface_->ReleaseResource(ws);
- ReleaseVar(reason);
- PASS();
- }
- std::string TestWebSocket::TestGetProtocol() {
- const char* expected_protocols[] = {
- "x-chat",
- "hoehoe",
- NULL
- };
- for (int i = 0; expected_protocols[i]; ++i) {
- std::string url(GetFullURL(kProtocolTestServerURL));
- url += expected_protocols[i];
- int32_t result;
- PP_Resource ws = Connect(url.c_str(), &result, expected_protocols[i]);
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, result);
- PP_Var protocol = websocket_interface_->GetProtocol(ws);
- ASSERT_TRUE(AreEqualWithString(protocol, expected_protocols[i]));
- ReleaseVar(protocol);
- core_interface_->ReleaseResource(ws);
- }
- PASS();
- }
- std::string TestWebSocket::TestTextSendReceive() {
- // Connect to test echo server.
- int32_t connect_result;
- PP_Resource ws =
- Connect(GetFullURL(kEchoServerURL), &connect_result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, connect_result);
- // Send 'hello pepper' text message.
- const char* message = "hello pepper";
- PP_Var message_var = CreateVarString(message);
- int32_t result = websocket_interface_->SendMessage(ws, message_var);
- ReleaseVar(message_var);
- ASSERT_EQ(PP_OK, result);
- // Receive echoed 'hello pepper'.
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- PP_Var received_message;
- callback.WaitForResult(websocket_interface_->ReceiveMessage(
- ws, &received_message, callback.GetCallback().pp_completion_callback()));
- ASSERT_EQ(PP_OK, callback.result());
- ASSERT_TRUE(AreEqualWithString(received_message, message));
- ReleaseVar(received_message);
- core_interface_->ReleaseResource(ws);
- PASS();
- }
- // Run as a BACKGROUND test.
- std::string TestWebSocket::TestTextSendReceiveTwice() {
- // Connect to test echo server.
- int32_t connect_result;
- PP_Resource ws =
- Connect(GetFullURL(kEchoServerURL), &connect_result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, connect_result);
- pp::MessageLoop message_loop = pp::MessageLoop::GetCurrent();
- pp::CompletionCallbackFactory<TestWebSocket> factory(this);
- message_loop.PostWork(factory.NewCallback(&TestWebSocket::Send,
- ws, std::string("hello")));
- // When the server receives 'Goodbye', it closes the session.
- message_loop.PostWork(factory.NewCallback(&TestWebSocket::Send,
- ws, std::string("Goodbye")));
- message_loop.PostQuit(false);
- message_loop.Run();
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- PP_Var received_message;
- int32_t result = websocket_interface_->ReceiveMessage(
- ws, &received_message, callback.GetCallback().pp_completion_callback());
- ASSERT_EQ(PP_OK, result);
- // Since we don't run the message loop, the callback will stay
- // "pending and scheduled to run" state.
- // Waiting for the connection close which will be done by the server.
- while (true) {
- PP_WebSocketReadyState ready_state =
- websocket_interface_->GetReadyState(ws);
- if (ready_state != PP_WEBSOCKETREADYSTATE_CONNECTING &&
- ready_state != PP_WEBSOCKETREADYSTATE_OPEN) {
- break;
- }
- PlatformSleep(100); // 100ms
- }
- // Cleanup the message loop
- message_loop.PostQuit(false);
- message_loop.Run();
- ASSERT_EQ(PP_OK, callback.result());
- ASSERT_TRUE(AreEqualWithString(received_message, "hello"));
- ReleaseVar(received_message);
- core_interface_->ReleaseResource(ws);
- PASS();
- }
- std::string TestWebSocket::TestBinarySendReceive() {
- // Connect to test echo server.
- int32_t connect_result;
- PP_Resource ws =
- Connect(GetFullURL(kEchoServerURL), &connect_result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, connect_result);
- // Send binary message.
- std::vector<uint8_t> binary(256);
- for (uint32_t i = 0; i < binary.size(); ++i)
- binary[i] = i;
- PP_Var message_var = CreateVarBinary(binary);
- int32_t result = websocket_interface_->SendMessage(ws, message_var);
- ReleaseVar(message_var);
- ASSERT_EQ(PP_OK, result);
- // Receive echoed binary.
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- PP_Var received_message;
- callback.WaitForResult(websocket_interface_->ReceiveMessage(
- ws, &received_message, callback.GetCallback().pp_completion_callback()));
- ASSERT_EQ(PP_OK, callback.result());
- ASSERT_TRUE(AreEqualWithBinary(received_message, binary));
- ReleaseVar(received_message);
- core_interface_->ReleaseResource(ws);
- PASS();
- }
- std::string TestWebSocket::TestStressedSendReceive() {
- // Connect to test echo server.
- int32_t connect_result;
- PP_Resource ws =
- Connect(GetFullURL(kEchoServerURL), &connect_result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, connect_result);
- // Prepare PP_Var objects to send.
- const char* text = "hello pepper";
- PP_Var text_var = CreateVarString(text);
- std::vector<uint8_t> binary(256);
- for (uint32_t i = 0; i < binary.size(); ++i)
- binary[i] = i;
- PP_Var binary_var = CreateVarBinary(binary);
- // Prepare very large binary data over 64KiB. Object serializer in
- // ppapi_proxy has a limitation of 64KiB as maximum return PP_Var data size
- // to SRPC. In case received data over 64KiB exists, a specific code handles
- // this large data via asynchronous callback from main thread. This data
- // intends to test the code.
- std::vector<uint8_t> large_binary(65 * 1024);
- for (uint32_t i = 0; i < large_binary.size(); ++i)
- large_binary[i] = i & 0xff;
- PP_Var large_binary_var = CreateVarBinary(large_binary);
- // Send many messages.
- int32_t result;
- for (int i = 0; i < 256; ++i) {
- result = websocket_interface_->SendMessage(ws, text_var);
- ASSERT_EQ(PP_OK, result);
- result = websocket_interface_->SendMessage(ws, binary_var);
- ASSERT_EQ(PP_OK, result);
- }
- result = websocket_interface_->SendMessage(ws, large_binary_var);
- ASSERT_EQ(PP_OK, result);
- ReleaseVar(text_var);
- ReleaseVar(binary_var);
- ReleaseVar(large_binary_var);
- // Receive echoed data.
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- for (int i = 0; i <= 512; ++i) {
- PP_Var received_message;
- callback.WaitForResult(websocket_interface_->ReceiveMessage(
- ws, &received_message,
- callback.GetCallback().pp_completion_callback()));
- ASSERT_EQ(PP_OK, callback.result());
- if (i == 512) {
- ASSERT_TRUE(AreEqualWithBinary(received_message, large_binary));
- } else if (i & 1) {
- ASSERT_TRUE(AreEqualWithBinary(received_message, binary));
- } else {
- ASSERT_TRUE(AreEqualWithString(received_message, text));
- }
- ReleaseVar(received_message);
- }
- core_interface_->ReleaseResource(ws);
- PASS();
- }
- std::string TestWebSocket::TestBufferedAmount() {
- // Connect to test echo server.
- int32_t connect_result;
- PP_Resource ws =
- Connect(GetFullURL(kEchoServerURL), &connect_result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, connect_result);
- // Prepare a large message that is not aligned with the internal buffer
- // sizes.
- std::string message(8193, 'x');
- PP_Var message_var = CreateVarString(message);
- uint64_t buffered_amount = 0;
- int32_t result;
- for (int i = 0; i < 100; i++) {
- result = websocket_interface_->SendMessage(ws, message_var);
- ASSERT_EQ(PP_OK, result);
- buffered_amount = websocket_interface_->GetBufferedAmount(ws);
- // Buffered amount size 262144 is too big for the internal buffer size.
- if (buffered_amount > 262144)
- break;
- }
- // Close connection.
- std::string reason_str = "close while busy";
- PP_Var reason = CreateVarString(reason_str.c_str());
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- result = websocket_interface_->Close(
- ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
- callback.GetCallback().pp_completion_callback());
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSING,
- websocket_interface_->GetReadyState(ws));
- callback.WaitForResult(result);
- ASSERT_EQ(PP_OK, callback.result());
- ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED,
- websocket_interface_->GetReadyState(ws));
- uint64_t base_buffered_amount = websocket_interface_->GetBufferedAmount(ws);
- // After connection closure, all sending requests fail and just increase
- // the bufferedAmount property.
- PP_Var empty_string = CreateVarString(std::string());
- result = websocket_interface_->SendMessage(ws, empty_string);
- ASSERT_EQ(PP_ERROR_FAILED, result);
- buffered_amount = websocket_interface_->GetBufferedAmount(ws);
- ASSERT_EQ(base_buffered_amount + kMessageFrameOverhead, buffered_amount);
- base_buffered_amount = buffered_amount;
- result = websocket_interface_->SendMessage(ws, reason);
- ASSERT_EQ(PP_ERROR_FAILED, result);
- buffered_amount = websocket_interface_->GetBufferedAmount(ws);
- uint64_t reason_frame_size = kMessageFrameOverhead + reason_str.length();
- ASSERT_EQ(base_buffered_amount + reason_frame_size, buffered_amount);
- ReleaseVar(message_var);
- ReleaseVar(reason);
- ReleaseVar(empty_string);
- core_interface_->ReleaseResource(ws);
- PASS();
- }
- // Test abort behaviors where a WebSocket PP_Resource is released while each
- // function is in-flight on the WebSocket PP_Resource.
- std::string TestWebSocket::TestAbortCallsWithCallback() {
- // Following tests make sure the behavior for functions which require a
- // callback. The callback must get a PP_ERROR_ABORTED.
- // Test the behavior for Connect().
- PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
- ASSERT_TRUE(ws);
- std::string url = GetFullURL(kEchoServerURL);
- PP_Var url_var = CreateVarString(url);
- TestCompletionCallback connect_callback(
- instance_->pp_instance(), callback_type());
- int32_t result = websocket_interface_->Connect(
- ws, url_var, NULL, 0,
- connect_callback.GetCallback().pp_completion_callback());
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- core_interface_->ReleaseResource(ws);
- connect_callback.WaitForResult(result);
- ASSERT_EQ(PP_ERROR_ABORTED, connect_callback.result());
- // Test the behavior for Close().
- ws = Connect(url, &result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, result);
- PP_Var reason_var = CreateVarString("abort");
- TestCompletionCallback close_callback(
- instance_->pp_instance(), callback_type());
- result = websocket_interface_->Close(
- ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason_var,
- close_callback.GetCallback().pp_completion_callback());
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- core_interface_->ReleaseResource(ws);
- close_callback.WaitForResult(result);
- ASSERT_EQ(PP_ERROR_ABORTED, close_callback.result());
- ReleaseVar(reason_var);
- // Test the behavior for ReceiveMessage().
- // Make sure the simplest case to wait for data which never arrives, here.
- ws = Connect(url, &result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, result);
- PP_Var receive_var;
- TestCompletionCallback receive_callback(
- instance_->pp_instance(), callback_type());
- result = websocket_interface_->ReceiveMessage(
- ws, &receive_var,
- receive_callback.GetCallback().pp_completion_callback());
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- core_interface_->ReleaseResource(ws);
- receive_callback.WaitForResult(result);
- ASSERT_EQ(PP_ERROR_ABORTED, receive_callback.result());
- // Release the resource in the aborting receive completion callback which is
- // introduced by calling Close().
- ws = Connect(url, &result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, result);
- result = websocket_interface_->ReceiveMessage(
- ws, &receive_var,
- receive_callback.GetCallback().pp_completion_callback());
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- ReleaseResourceDelegate receive_delegate(core_interface_, ws);
- receive_callback.SetDelegate(&receive_delegate);
- result = websocket_interface_->Close(
- ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(),
- close_callback.GetCallback().pp_completion_callback());
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- receive_callback.WaitForResult(result);
- CHECK_CALLBACK_BEHAVIOR(receive_callback);
- ASSERT_EQ(PP_ERROR_ABORTED, receive_callback.result());
- close_callback.WaitForResult(result);
- CHECK_CALLBACK_BEHAVIOR(close_callback);
- ASSERT_EQ(PP_ERROR_ABORTED, close_callback.result());
- ReleaseVar(url_var);
- PASS();
- }
- std::string TestWebSocket::TestAbortSendMessageCall() {
- // Test the behavior for SendMessage().
- // This function doesn't require a callback, but operation will be done
- // asynchronously in WebKit and browser process.
- std::vector<uint8_t> large_binary(65 * 1024);
- PP_Var large_var = CreateVarBinary(large_binary);
- int32_t result;
- std::string url = GetFullURL(kEchoServerURL);
- PP_Resource ws = Connect(url, &result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, result);
- result = websocket_interface_->SendMessage(ws, large_var);
- ASSERT_EQ(PP_OK, result);
- core_interface_->ReleaseResource(ws);
- ReleaseVar(large_var);
- PASS();
- }
- std::string TestWebSocket::TestAbortCloseCall() {
- // Release the resource in the close completion callback.
- int32_t result;
- std::string url = GetFullURL(kEchoServerURL);
- PP_Resource ws = Connect(url, &result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, result);
- TestCompletionCallback close_callback(
- instance_->pp_instance(), callback_type());
- result = websocket_interface_->Close(
- ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(),
- close_callback.GetCallback().pp_completion_callback());
- ReleaseResourceDelegate close_delegate(core_interface_, ws);
- close_callback.SetDelegate(&close_delegate);
- close_callback.WaitForResult(result);
- CHECK_CALLBACK_BEHAVIOR(close_callback);
- ASSERT_EQ(PP_OK, close_callback.result());
- PASS();
- }
- std::string TestWebSocket::TestAbortReceiveMessageCall() {
- // Test the behavior where receive process might be in-flight.
- std::vector<uint8_t> large_binary(65 * 1024);
- PP_Var large_var = CreateVarBinary(large_binary);
- const char* text = "yukarin";
- PP_Var text_var = CreateVarString(text);
- std::string url = GetFullURL(kEchoServerURL);
- int32_t result;
- PP_Resource ws;
- // Each trial sends |trial_count| + 1 messages and receives just |trial|
- // number of message(s) before releasing the WebSocket. The WebSocket is
- // released while the next message is going to be received.
- const int trial_count = 8;
- for (int trial = 1; trial <= trial_count; trial++) {
- ws = Connect(url, &result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, result);
- for (int i = 0; i <= trial_count; ++i) {
- result = websocket_interface_->SendMessage(ws, text_var);
- ASSERT_EQ(PP_OK, result);
- }
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- PP_Var var;
- for (int i = 0; i < trial; ++i) {
- callback.WaitForResult(websocket_interface_->ReceiveMessage(
- ws, &var, callback.GetCallback().pp_completion_callback()));
- ASSERT_EQ(PP_OK, callback.result());
- ASSERT_TRUE(AreEqualWithString(var, text));
- ReleaseVar(var);
- }
- result = websocket_interface_->ReceiveMessage(
- ws, &var, callback.GetCallback().pp_completion_callback());
- core_interface_->ReleaseResource(ws);
- if (result != PP_OK) {
- callback.WaitForResult(result);
- ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
- }
- }
- // Same test, but the last receiving message is large message over 64KiB.
- for (int trial = 1; trial <= trial_count; trial++) {
- ws = Connect(url, &result, std::string());
- ASSERT_TRUE(ws);
- ASSERT_EQ(PP_OK, result);
- for (int i = 0; i <= trial_count; ++i) {
- if (i == trial)
- result = websocket_interface_->SendMessage(ws, large_var);
- else
- result = websocket_interface_->SendMessage(ws, text_var);
- ASSERT_EQ(PP_OK, result);
- }
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- PP_Var var;
- for (int i = 0; i < trial; ++i) {
- callback.WaitForResult(websocket_interface_->ReceiveMessage(
- ws, &var, callback.GetCallback().pp_completion_callback()));
- ASSERT_EQ(PP_OK, callback.result());
- ASSERT_TRUE(AreEqualWithString(var, text));
- ReleaseVar(var);
- }
- result = websocket_interface_->ReceiveMessage(
- ws, &var, callback.GetCallback().pp_completion_callback());
- core_interface_->ReleaseResource(ws);
- if (result != PP_OK) {
- callback.WaitForResult(result);
- ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
- }
- }
- ReleaseVar(large_var);
- ReleaseVar(text_var);
- PASS();
- }
- std::string TestWebSocket::TestClosedFromServerWhileSending() {
- // Connect to test echo server.
- const pp::Var protocols[] = { pp::Var() };
- TestWebSocketAPI websocket(instance_);
- int32_t result =
- websocket.Connect(pp::Var(GetFullURL(kEchoServerURL)), protocols, 0U);
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- websocket.WaitForConnected();
- result = websocket.Send(pp::Var("hello"));
- ASSERT_EQ(PP_OK, result);
- result = websocket.Send(pp::Var("Goodbye"));
- // We send many messages so that PepperWebSocketHost::SendText is called
- // after PepperWebSocketHost::didClose is called.
- // Note: We must not wait for CLOSED event here because
- // WebSocketResource::SendMessage doesn't call PepperWebSocketHost::SendText
- // when its internal state is CLOSING or CLOSED. We want to test if the
- // pepper WebSocket works well when WebSocketResource is OPEN and
- // PepperWebSocketHost is CLOSED.
- for (size_t i = 0; i < 10000; ++i) {
- result = websocket.Send(pp::Var(""));
- ASSERT_EQ(PP_OK, result);
- }
- PASS();
- }
- std::string TestWebSocket::TestCcInterfaces() {
- // C++ bindings is simple straightforward, then just verifies interfaces work
- // as a interface bridge fine.
- pp::WebSocket ws(instance_);
- // Check uninitialized properties access.
- ASSERT_EQ(0, ws.GetBufferedAmount());
- ASSERT_EQ(0, ws.GetCloseCode());
- ASSERT_TRUE(AreEqualWithString(ws.GetCloseReason().pp_var(), std::string()));
- ASSERT_FALSE(ws.GetCloseWasClean());
- ASSERT_TRUE(AreEqualWithString(ws.GetExtensions().pp_var(), std::string()));
- ASSERT_TRUE(AreEqualWithString(ws.GetProtocol().pp_var(), std::string()));
- ASSERT_EQ(PP_WEBSOCKETREADYSTATE_INVALID, ws.GetReadyState());
- ASSERT_TRUE(AreEqualWithString(ws.GetURL().pp_var(), std::string()));
- // Check communication interfaces (connect, send, receive, and close).
- TestCompletionCallback connect_callback(
- instance_->pp_instance(), callback_type());
- connect_callback.WaitForResult(ws.Connect(
- pp::Var(GetFullURL(kCloseServerURL)), NULL, 0U,
- connect_callback.GetCallback()));
- CHECK_CALLBACK_BEHAVIOR(connect_callback);
- ASSERT_EQ(PP_OK, connect_callback.result());
- std::string text_message("hello C++");
- int32_t result = ws.SendMessage(pp::Var(text_message));
- ASSERT_EQ(PP_OK, result);
- std::vector<uint8_t> binary(256);
- for (uint32_t i = 0; i < binary.size(); ++i)
- binary[i] = i;
- result = ws.SendMessage(
- pp::Var(pp::PASS_REF, CreateVarBinary(binary)));
- ASSERT_EQ(PP_OK, result);
- pp::Var text_receive_var;
- TestCompletionCallback text_receive_callback(
- instance_->pp_instance(), callback_type());
- text_receive_callback.WaitForResult(
- ws.ReceiveMessage(&text_receive_var,
- text_receive_callback.GetCallback()));
- ASSERT_EQ(PP_OK, text_receive_callback.result());
- ASSERT_TRUE(
- AreEqualWithString(text_receive_var.pp_var(), text_message.c_str()));
- pp::Var binary_receive_var;
- TestCompletionCallback binary_receive_callback(
- instance_->pp_instance(), callback_type());
- binary_receive_callback.WaitForResult(
- ws.ReceiveMessage(&binary_receive_var,
- binary_receive_callback.GetCallback()));
- ASSERT_EQ(PP_OK, binary_receive_callback.result());
- ASSERT_TRUE(AreEqualWithBinary(binary_receive_var.pp_var(), binary));
- TestCompletionCallback close_callback(
- instance_->pp_instance(), callback_type());
- std::string reason("bye");
- close_callback.WaitForResult(ws.Close(
- PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason),
- close_callback.GetCallback()));
- CHECK_CALLBACK_BEHAVIOR(close_callback);
- ASSERT_EQ(PP_OK, close_callback.result());
- // Check initialized properties access.
- ASSERT_EQ(0, ws.GetBufferedAmount());
- ASSERT_EQ(PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, ws.GetCloseCode());
- ASSERT_TRUE(
- AreEqualWithString(ws.GetCloseReason().pp_var(), reason.c_str()));
- ASSERT_EQ(true, ws.GetCloseWasClean());
- ASSERT_TRUE(AreEqualWithString(ws.GetProtocol().pp_var(), std::string()));
- ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED, ws.GetReadyState());
- ASSERT_TRUE(AreEqualWithString(
- ws.GetURL().pp_var(), GetFullURL(kCloseServerURL).c_str()));
- PASS();
- }
- std::string TestWebSocket::TestUtilityInvalidConnect() {
- const pp::Var protocols[] = { pp::Var() };
- TestWebSocketAPI websocket(instance_);
- int32_t result = websocket.Connect(pp::Var(), protocols, 1U);
- ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
- ASSERT_EQ(0U, websocket.GetSeenEvents().size());
- result = websocket.Connect(pp::Var(), protocols, 1U);
- ASSERT_EQ(PP_ERROR_INPROGRESS, result);
- ASSERT_EQ(0U, websocket.GetSeenEvents().size());
- for (int i = 0; kInvalidURLs[i]; ++i) {
- TestWebSocketAPI ws(instance_);
- result = ws.Connect(pp::Var(std::string(kInvalidURLs[i])), protocols, 0U);
- if (result == PP_OK_COMPLETIONPENDING) {
- ws.WaitForClosed();
- const std::vector<WebSocketEvent>& events = ws.GetSeenEvents();
- ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[0].event_type);
- ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type);
- ASSERT_EQ(2U, ws.GetSeenEvents().size());
- } else {
- ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
- ASSERT_EQ(0U, ws.GetSeenEvents().size());
- }
- }
- PASS();
- }
- std::string TestWebSocket::TestUtilityProtocols() {
- const pp::Var bad_protocols[] = {
- pp::Var(std::string("x-test")), pp::Var(std::string("x-test")) };
- const pp::Var good_protocols[] = {
- pp::Var(std::string("x-test")), pp::Var(std::string("x-yatest")) };
- {
- TestWebSocketAPI websocket(instance_);
- int32_t result = websocket.Connect(
- pp::Var(GetFullURL(kEchoServerURL)), bad_protocols, 2U);
- ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
- ASSERT_EQ(0U, websocket.GetSeenEvents().size());
- }
- {
- TestWebSocketAPI websocket(instance_);
- int32_t result = websocket.Connect(
- pp::Var(GetFullURL(kEchoServerURL)), good_protocols, 2U);
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- websocket.WaitForConnected();
- const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
- // Protocol arguments are valid, but this test run without a WebSocket
- // server. As a result, OnError() and OnClose() are invoked because of
- // a connection establishment failure.
- ASSERT_EQ(2U, events.size());
- ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[0].event_type);
- ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type);
- ASSERT_FALSE(events[1].was_clean);
- }
- PASS();
- }
- std::string TestWebSocket::TestUtilityGetURL() {
- const pp::Var protocols[] = { pp::Var() };
- for (int i = 0; kInvalidURLs[i]; ++i) {
- TestWebSocketAPI websocket(instance_);
- int32_t result = websocket.Connect(
- pp::Var(std::string(kInvalidURLs[i])), protocols, 0U);
- if (result == PP_OK_COMPLETIONPENDING) {
- websocket.WaitForClosed();
- const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
- ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[0].event_type);
- ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type);
- ASSERT_EQ(2U, events.size());
- } else {
- ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
- ASSERT_EQ(0U, websocket.GetSeenEvents().size());
- }
- pp::Var url = websocket.GetURL();
- ASSERT_TRUE(AreEqualWithString(url.pp_var(), kInvalidURLs[i]));
- }
- PASS();
- }
- std::string TestWebSocket::TestUtilityValidConnect() {
- const pp::Var protocols[] = { pp::Var() };
- TestWebSocketAPI websocket(instance_);
- int32_t result = websocket.Connect(
- pp::Var(GetFullURL(kEchoServerURL)), protocols, 0U);
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- websocket.WaitForConnected();
- const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
- ASSERT_EQ(1U, events.size());
- ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
- ASSERT_TRUE(
- AreEqualWithString(websocket.GetExtensions().pp_var(), std::string()));
- PASS();
- }
- std::string TestWebSocket::TestUtilityInvalidClose() {
- const pp::Var reason = pp::Var(std::string("close for test"));
- // Close before connect.
- {
- TestWebSocketAPI websocket(instance_);
- int32_t result = websocket.Close(
- PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason);
- ASSERT_EQ(PP_ERROR_FAILED, result);
- ASSERT_EQ(0U, websocket.GetSeenEvents().size());
- }
- // Close with bad arguments.
- {
- TestWebSocketAPI websocket(instance_);
- int32_t result = websocket.Connect(pp::Var(GetFullURL(kEchoServerURL)),
- NULL, 0);
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- websocket.WaitForConnected();
- result = websocket.Close(1U, reason);
- ASSERT_EQ(PP_ERROR_NOACCESS, result);
- const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
- ASSERT_EQ(1U, events.size());
- ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
- }
- PASS();
- }
- std::string TestWebSocket::TestUtilityValidClose() {
- std::string reason("close for test");
- pp::Var url = pp::Var(GetFullURL(kCloseServerURL));
- // Close.
- {
- TestWebSocketAPI websocket(instance_);
- int32_t result = websocket.Connect(url, NULL, 0U);
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- websocket.WaitForConnected();
- result = websocket.Close(
- PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- websocket.WaitForClosed();
- const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
- ASSERT_EQ(2U, events.size());
- ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
- ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type);
- ASSERT_TRUE(events[1].was_clean);
- ASSERT_EQ(PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, events[1].close_code);
- ASSERT_TRUE(AreEqualWithString(events[1].var.pp_var(), reason.c_str()));
- }
- // Close in connecting.
- // The ongoing connect failed with PP_ERROR_ABORTED, then the close is done
- // successfully.
- {
- TestWebSocketAPI websocket(instance_);
- int32_t result = websocket.Connect(url, NULL, 0U);
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- result = websocket.Close(
- PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- websocket.WaitForClosed();
- const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
- ASSERT_TRUE(events.size() == 2 || events.size() == 3);
- int index = 0;
- if (events.size() == 3)
- ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[index++].event_type);
- ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[index++].event_type);
- ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[index].event_type);
- ASSERT_FALSE(events[index].was_clean);
- }
- // Close in closing.
- // The first close will be done successfully, then the second one failed with
- // with PP_ERROR_INPROGRESS immediately.
- {
- TestWebSocketAPI websocket(instance_);
- int32_t result = websocket.Connect(url, NULL, 0U);
- result = websocket.Close(
- PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- result = websocket.Close(
- PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
- ASSERT_EQ(PP_ERROR_INPROGRESS, result);
- websocket.WaitForClosed();
- const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
- ASSERT_TRUE(events.size() == 2 || events.size() == 3);
- int index = 0;
- if (events.size() == 3)
- ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[index++].event_type);
- ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[index++].event_type);
- ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[index].event_type);
- ASSERT_FALSE(events[index].was_clean);
- }
- PASS();
- }
- std::string TestWebSocket::TestUtilityGetProtocol() {
- const std::string protocol("x-chat");
- const pp::Var protocols[] = { pp::Var(protocol) };
- std::string url(GetFullURL(kProtocolTestServerURL));
- url += protocol;
- TestWebSocketAPI websocket(instance_);
- int32_t result = websocket.Connect(pp::Var(url), protocols, 1U);
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- websocket.WaitForReceived();
- ASSERT_TRUE(AreEqualWithString(
- websocket.GetProtocol().pp_var(), protocol.c_str()));
- const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
- // The server to which this test connect returns the decided protocol as a
- // text frame message. So the WebSocketEvent records EVENT_MESSAGE event
- // after EVENT_OPEN event.
- ASSERT_EQ(2U, events.size());
- ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
- ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type);
- ASSERT_TRUE(AreEqualWithString(events[1].var.pp_var(), protocol.c_str()));
- PASS();
- }
- std::string TestWebSocket::TestUtilityTextSendReceive() {
- const pp::Var protocols[] = { pp::Var() };
- TestWebSocketAPI websocket(instance_);
- int32_t result =
- websocket.Connect(pp::Var(GetFullURL(kEchoServerURL)), protocols, 0U);
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- websocket.WaitForConnected();
- // Send 'hello pepper'.
- std::string message1("hello pepper");
- result = websocket.Send(pp::Var(std::string(message1)));
- ASSERT_EQ(PP_OK, result);
- // Receive echoed 'hello pepper'.
- websocket.WaitForReceived();
- // Send 'goodbye pepper'.
- std::string message2("goodbye pepper");
- result = websocket.Send(pp::Var(std::string(message2)));
- // Receive echoed 'goodbye pepper'.
- websocket.WaitForReceived();
- const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
- ASSERT_EQ(3U, events.size());
- ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
- ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type);
- ASSERT_TRUE(AreEqualWithString(events[1].var.pp_var(), message1.c_str()));
- ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[2].event_type);
- ASSERT_TRUE(AreEqualWithString(events[2].var.pp_var(), message2.c_str()));
- PASS();
- }
- std::string TestWebSocket::TestUtilityBinarySendReceive() {
- const pp::Var protocols[] = { pp::Var() };
- TestWebSocketAPI websocket(instance_);
- int32_t result =
- websocket.Connect(pp::Var(GetFullURL(kEchoServerURL)), protocols, 0U);
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- websocket.WaitForConnected();
- // Send binary message.
- uint32_t len = 256;
- std::vector<uint8_t> binary(len);
- for (uint32_t i = 0; i < len; ++i)
- binary[i] = i;
- pp::VarArrayBuffer message(len);
- uint8_t* var_data = static_cast<uint8_t*>(message.Map());
- std::copy(binary.begin(), binary.end(), var_data);
- result = websocket.Send(message);
- ASSERT_EQ(PP_OK, result);
- // Receive echoed binary message.
- websocket.WaitForReceived();
- const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
- ASSERT_EQ(2U, events.size());
- ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
- ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type);
- ASSERT_TRUE(AreEqualWithBinary(events[1].var.pp_var(), binary));
- PASS();
- }
- std::string TestWebSocket::TestUtilityBufferedAmount() {
- // Connect to test echo server.
- const pp::Var protocols[] = { pp::Var() };
- TestWebSocketAPI websocket(instance_);
- int32_t result =
- websocket.Connect(pp::Var(GetFullURL(kEchoServerURL)), protocols, 0U);
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- websocket.WaitForConnected();
- // Prepare a large message that is not aligned with the internal buffer
- // sizes.
- std::string message(8193, 'x');
- uint64_t buffered_amount = 0;
- uint32_t sent;
- for (sent = 0; sent < 100; sent++) {
- result = websocket.Send(pp::Var(message));
- ASSERT_EQ(PP_OK, result);
- buffered_amount = websocket.GetBufferedAmount();
- // Buffered amount size 262144 is too big for the internal buffer size.
- if (buffered_amount > 262144)
- break;
- }
- // Close connection.
- std::string reason = "close while busy";
- result = websocket.Close(
- PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var(reason));
- ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSING, websocket.GetReadyState());
- websocket.WaitForClosed();
- ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED, websocket.GetReadyState());
- uint64_t base_buffered_amount = websocket.GetBufferedAmount();
- size_t events_on_closed = websocket.GetSeenEvents().size();
- // After connection closure, all sending requests fail and just increase
- // the bufferedAmount property.
- result = websocket.Send(pp::Var(std::string()));
- ASSERT_EQ(PP_ERROR_FAILED, result);
- buffered_amount = websocket.GetBufferedAmount();
- ASSERT_EQ(base_buffered_amount + kMessageFrameOverhead, buffered_amount);
- base_buffered_amount = buffered_amount;
- result = websocket.Send(pp::Var(reason));
- ASSERT_EQ(PP_ERROR_FAILED, result);
- buffered_amount = websocket.GetBufferedAmount();
- uint64_t reason_frame_size = kMessageFrameOverhead + reason.length();
- ASSERT_EQ(base_buffered_amount + reason_frame_size, buffered_amount);
- const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents();
- ASSERT_EQ(events_on_closed, events.size());
- ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
- size_t last_event = events_on_closed - 1;
- for (uint32_t i = 1; i < last_event; ++i) {
- ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[i].event_type);
- ASSERT_TRUE(AreEqualWithString(events[i].var.pp_var(), message));
- }
- ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[last_event].event_type);
- ASSERT_TRUE(events[last_event].was_clean);
- PASS();
- }
|