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