test_websocket.cc 58 KB

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