OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ppapi/tests/test_websocket.h" | 5 #include "ppapi/tests/test_websocket.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "ppapi/c/dev/ppb_testing_dev.h" | 10 #include "ppapi/c/dev/ppb_testing_dev.h" |
11 #include "ppapi/c/dev/ppb_var_array_buffer_dev.h" | 11 #include "ppapi/c/dev/ppb_var_array_buffer_dev.h" |
12 #include "ppapi/c/dev/ppb_websocket_dev.h" | 12 #include "ppapi/c/dev/ppb_websocket_dev.h" |
13 #include "ppapi/c/pp_errors.h" | 13 #include "ppapi/c/pp_errors.h" |
14 #include "ppapi/c/pp_var.h" | 14 #include "ppapi/c/pp_var.h" |
15 #include "ppapi/c/pp_completion_callback.h" | 15 #include "ppapi/c/pp_completion_callback.h" |
16 #include "ppapi/c/ppb_core.h" | 16 #include "ppapi/c/ppb_core.h" |
17 #include "ppapi/c/ppb_var.h" | 17 #include "ppapi/c/ppb_var.h" |
| 18 #include "ppapi/cpp/dev/var_array_buffer_dev.h" |
18 #include "ppapi/cpp/dev/websocket_dev.h" | 19 #include "ppapi/cpp/dev/websocket_dev.h" |
19 #include "ppapi/cpp/instance.h" | 20 #include "ppapi/cpp/instance.h" |
20 #include "ppapi/cpp/module.h" | 21 #include "ppapi/cpp/module.h" |
21 #include "ppapi/tests/test_utils.h" | 22 #include "ppapi/tests/test_utils.h" |
22 #include "ppapi/tests/testing_instance.h" | 23 #include "ppapi/tests/testing_instance.h" |
| 24 #include "ppapi/utility/websocket/websocket_api.h" |
23 | 25 |
| 26 // These servers are provided by pywebsocket server side handlers in |
| 27 // LayoutTests/http/tests/websocket/tests/hybi/*_wsh. |
| 28 // pywebsocket server itself is launched in ppapi_ui_test.cc. |
24 const char kEchoServerURL[] = | 29 const char kEchoServerURL[] = |
25 "ws://localhost:8880/websocket/tests/hybi/echo"; | 30 "ws://localhost:8880/websocket/tests/hybi/echo"; |
26 | 31 |
27 const char kCloseServerURL[] = | 32 const char kCloseServerURL[] = |
28 "ws://localhost:8880/websocket/tests/hybi/close"; | 33 "ws://localhost:8880/websocket/tests/hybi/close"; |
29 | 34 |
30 const char kProtocolTestServerURL[] = | 35 const char kProtocolTestServerURL[] = |
31 "ws://localhost:8880/websocket/tests/hybi/protocol-test?protocol="; | 36 "ws://localhost:8880/websocket/tests/hybi/protocol-test?protocol="; |
32 | 37 |
33 const char* const kInvalidURLs[] = { | 38 const char* const kInvalidURLs[] = { |
34 "http://www.google.com/invalid_scheme", | 39 "http://www.google.com/invalid_scheme", |
35 "ws://www.google.com/invalid#fragment", | 40 "ws://www.google.com/invalid#fragment", |
36 "ws://www.google.com:65535/invalid_port", | 41 "ws://www.google.com:65535/invalid_port", |
37 NULL | 42 NULL |
38 }; | 43 }; |
39 | 44 |
40 // Connection close code is defined in WebSocket protocol specification. | 45 // Connection close code is defined in WebSocket protocol specification. |
41 // The magic number 1000 means gracefull closure without any error. | 46 // The magic number 1000 means gracefull closure without any error. |
42 // See section 7.4.1. of RFC 6455. | 47 // See section 7.4.1. of RFC 6455. |
43 const uint16_t kCloseCodeNormalClosure = 1000U; | 48 const uint16_t kCloseCodeNormalClosure = 1000U; |
44 | 49 |
45 // Internal packet sizes. | 50 // Internal packet sizes. |
46 const uint64_t kCloseFrameSize = 6; | 51 const uint64_t kCloseFrameSize = 6; |
47 const uint64_t kMessageFrameOverhead = 6; | 52 const uint64_t kMessageFrameOverhead = 6; |
48 | 53 |
| 54 namespace { |
| 55 |
| 56 struct WebSocketEvent { |
| 57 enum EventType { |
| 58 EVENT_OPEN, |
| 59 EVENT_MESSAGE, |
| 60 EVENT_ERROR, |
| 61 EVENT_CLOSE |
| 62 }; |
| 63 |
| 64 WebSocketEvent(EventType type, |
| 65 bool was_clean, |
| 66 uint16_t close_code, |
| 67 const pp::Var& var) |
| 68 : event_type(type), |
| 69 was_clean(was_clean), |
| 70 close_code(close_code), |
| 71 var(var) {} |
| 72 EventType event_type; |
| 73 bool was_clean; |
| 74 uint16_t close_code; |
| 75 pp::Var var; |
| 76 }; |
| 77 |
| 78 class TestWebSocketAPI : public pp::WebSocketAPI { |
| 79 public: |
| 80 explicit TestWebSocketAPI(pp::Instance* instance) |
| 81 : pp::WebSocketAPI(instance), |
| 82 connected_(false), |
| 83 received_(false), |
| 84 closed_(false), |
| 85 wait_for_connected_(false), |
| 86 wait_for_received_(false), |
| 87 wait_for_closed_(false), |
| 88 instance_(instance->pp_instance()) {} |
| 89 |
| 90 virtual void OnOpen() { |
| 91 events_.push_back( |
| 92 WebSocketEvent(WebSocketEvent::EVENT_OPEN, true, 0U, pp::Var())); |
| 93 connected_ = true; |
| 94 if (wait_for_connected_) { |
| 95 GetTestingInterface()->QuitMessageLoop(instance_); |
| 96 wait_for_connected_ = false; |
| 97 } |
| 98 } |
| 99 |
| 100 virtual void OnMessage(const pp::Var &message) { |
| 101 events_.push_back( |
| 102 WebSocketEvent(WebSocketEvent::EVENT_MESSAGE, true, 0U, message)); |
| 103 received_ = true; |
| 104 if (wait_for_received_) { |
| 105 GetTestingInterface()->QuitMessageLoop(instance_); |
| 106 wait_for_received_ = false; |
| 107 received_ = false; |
| 108 } |
| 109 } |
| 110 |
| 111 virtual void OnError() { |
| 112 events_.push_back( |
| 113 WebSocketEvent(WebSocketEvent::EVENT_ERROR, true, 0U, pp::Var())); |
| 114 } |
| 115 |
| 116 virtual void OnClose( |
| 117 bool was_clean, uint16_t code, const pp::Var& reason) { |
| 118 events_.push_back( |
| 119 WebSocketEvent(WebSocketEvent::EVENT_CLOSE, was_clean, code, reason)); |
| 120 connected_ = true; |
| 121 closed_ = true; |
| 122 if (wait_for_connected_ || wait_for_closed_) { |
| 123 GetTestingInterface()->QuitMessageLoop(instance_); |
| 124 wait_for_connected_ = false; |
| 125 wait_for_closed_ = false; |
| 126 } |
| 127 } |
| 128 |
| 129 void WaitForConnected() { |
| 130 if (!connected_) { |
| 131 wait_for_connected_ = true; |
| 132 GetTestingInterface()->RunMessageLoop(instance_); |
| 133 } |
| 134 } |
| 135 |
| 136 void WaitForReceived() { |
| 137 if (!received_) { |
| 138 wait_for_received_ = true; |
| 139 GetTestingInterface()->RunMessageLoop(instance_); |
| 140 } |
| 141 } |
| 142 |
| 143 void WaitForClosed() { |
| 144 if (!closed_) { |
| 145 wait_for_closed_ = true; |
| 146 GetTestingInterface()->RunMessageLoop(instance_); |
| 147 } |
| 148 } |
| 149 |
| 150 const std::vector<WebSocketEvent>& GetSeenEvents() const { |
| 151 return events_; |
| 152 } |
| 153 |
| 154 private: |
| 155 std::vector<WebSocketEvent> events_; |
| 156 bool connected_; |
| 157 bool received_; |
| 158 bool closed_; |
| 159 bool wait_for_connected_; |
| 160 bool wait_for_received_; |
| 161 bool wait_for_closed_; |
| 162 PP_Instance instance_; |
| 163 }; |
| 164 |
| 165 } // namespace |
| 166 |
49 REGISTER_TEST_CASE(WebSocket); | 167 REGISTER_TEST_CASE(WebSocket); |
50 | 168 |
51 bool TestWebSocket::Init() { | 169 bool TestWebSocket::Init() { |
52 websocket_interface_ = static_cast<const PPB_WebSocket_Dev*>( | 170 websocket_interface_ = static_cast<const PPB_WebSocket_Dev*>( |
53 pp::Module::Get()->GetBrowserInterface(PPB_WEBSOCKET_DEV_INTERFACE)); | 171 pp::Module::Get()->GetBrowserInterface(PPB_WEBSOCKET_DEV_INTERFACE)); |
54 var_interface_ = static_cast<const PPB_Var*>( | 172 var_interface_ = static_cast<const PPB_Var*>( |
55 pp::Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE)); | 173 pp::Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE)); |
56 arraybuffer_interface_ = static_cast<const PPB_VarArrayBuffer_Dev*>( | 174 arraybuffer_interface_ = static_cast<const PPB_VarArrayBuffer_Dev*>( |
57 pp::Module::Get()->GetBrowserInterface( | 175 pp::Module::Get()->GetBrowserInterface( |
58 PPB_VAR_ARRAY_BUFFER_DEV_INTERFACE)); | 176 PPB_VAR_ARRAY_BUFFER_DEV_INTERFACE)); |
(...skipping 14 matching lines...) Expand all Loading... |
73 RUN_TEST_WITH_REFERENCE_CHECK(GetURL, filter); | 191 RUN_TEST_WITH_REFERENCE_CHECK(GetURL, filter); |
74 RUN_TEST_WITH_REFERENCE_CHECK(ValidConnect, filter); | 192 RUN_TEST_WITH_REFERENCE_CHECK(ValidConnect, filter); |
75 RUN_TEST_WITH_REFERENCE_CHECK(InvalidClose, filter); | 193 RUN_TEST_WITH_REFERENCE_CHECK(InvalidClose, filter); |
76 RUN_TEST_WITH_REFERENCE_CHECK(ValidClose, filter); | 194 RUN_TEST_WITH_REFERENCE_CHECK(ValidClose, filter); |
77 RUN_TEST_WITH_REFERENCE_CHECK(GetProtocol, filter); | 195 RUN_TEST_WITH_REFERENCE_CHECK(GetProtocol, filter); |
78 RUN_TEST_WITH_REFERENCE_CHECK(TextSendReceive, filter); | 196 RUN_TEST_WITH_REFERENCE_CHECK(TextSendReceive, filter); |
79 RUN_TEST_WITH_REFERENCE_CHECK(BinarySendReceive, filter); | 197 RUN_TEST_WITH_REFERENCE_CHECK(BinarySendReceive, filter); |
80 RUN_TEST_WITH_REFERENCE_CHECK(BufferedAmount, filter); | 198 RUN_TEST_WITH_REFERENCE_CHECK(BufferedAmount, filter); |
81 | 199 |
82 RUN_TEST_WITH_REFERENCE_CHECK(CcInterfaces, filter); | 200 RUN_TEST_WITH_REFERENCE_CHECK(CcInterfaces, filter); |
| 201 |
| 202 RUN_TEST_WITH_REFERENCE_CHECK(UtilityInvalidConnect, filter); |
| 203 RUN_TEST_WITH_REFERENCE_CHECK(UtilityProtocols, filter); |
| 204 RUN_TEST_WITH_REFERENCE_CHECK(UtilityGetURL, filter); |
| 205 RUN_TEST_WITH_REFERENCE_CHECK(UtilityValidConnect, filter); |
| 206 RUN_TEST_WITH_REFERENCE_CHECK(UtilityInvalidClose, filter); |
| 207 RUN_TEST_WITH_REFERENCE_CHECK(UtilityValidClose, filter); |
| 208 RUN_TEST_WITH_REFERENCE_CHECK(UtilityGetProtocol, filter); |
| 209 RUN_TEST_WITH_REFERENCE_CHECK(UtilityTextSendReceive, filter); |
| 210 RUN_TEST_WITH_REFERENCE_CHECK(UtilityBinarySendReceive, filter); |
| 211 RUN_TEST_WITH_REFERENCE_CHECK(UtilityBufferedAmount, filter); |
83 } | 212 } |
84 | 213 |
85 PP_Var TestWebSocket::CreateVarString(const char* string) { | 214 PP_Var TestWebSocket::CreateVarString(const char* string) { |
86 return var_interface_->VarFromUtf8(string, strlen(string)); | 215 return var_interface_->VarFromUtf8(string, strlen(string)); |
87 } | 216 } |
88 | 217 |
89 PP_Var TestWebSocket::CreateVarBinary(const uint8_t* data, uint32_t size) { | 218 PP_Var TestWebSocket::CreateVarBinary(const uint8_t* data, uint32_t size) { |
90 PP_Var var = arraybuffer_interface_->Create(size); | 219 PP_Var var = arraybuffer_interface_->Create(size); |
91 void* var_data = arraybuffer_interface_->Map(var); | 220 void* var_data = arraybuffer_interface_->Map(var); |
92 memcpy(var_data, data, size); | 221 memcpy(var_data, data, size); |
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
565 ASSERT_EQ(0, ws.GetBufferedAmount()); | 694 ASSERT_EQ(0, ws.GetBufferedAmount()); |
566 ASSERT_EQ(0, ws.GetCloseCode()); | 695 ASSERT_EQ(0, ws.GetCloseCode()); |
567 ASSERT_TRUE(AreEqualWithString(ws.GetCloseReason().pp_var(), "")); | 696 ASSERT_TRUE(AreEqualWithString(ws.GetCloseReason().pp_var(), "")); |
568 ASSERT_EQ(false, ws.GetCloseWasClean()); | 697 ASSERT_EQ(false, ws.GetCloseWasClean()); |
569 ASSERT_TRUE(AreEqualWithString(ws.GetExtensions().pp_var(), "")); | 698 ASSERT_TRUE(AreEqualWithString(ws.GetExtensions().pp_var(), "")); |
570 ASSERT_TRUE(AreEqualWithString(ws.GetProtocol().pp_var(), "")); | 699 ASSERT_TRUE(AreEqualWithString(ws.GetProtocol().pp_var(), "")); |
571 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_INVALID_DEV, ws.GetReadyState()); | 700 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_INVALID_DEV, ws.GetReadyState()); |
572 ASSERT_TRUE(AreEqualWithString(ws.GetURL().pp_var(), "")); | 701 ASSERT_TRUE(AreEqualWithString(ws.GetURL().pp_var(), "")); |
573 | 702 |
574 // Check communication interfaces (connect, send, receive, and close). | 703 // Check communication interfaces (connect, send, receive, and close). |
575 ws.SetBinaryType(PP_WEBSOCKETBINARYTYPE_ARRAYBUFFER_DEV); | 704 ASSERT_TRUE(ws.SetBinaryType(PP_WEBSOCKETBINARYTYPE_ARRAYBUFFER_DEV)); |
576 TestCompletionCallback connect_callback(instance_->pp_instance()); | 705 TestCompletionCallback connect_callback(instance_->pp_instance()); |
577 int32_t result = ws.Connect(pp::Var(std::string(kCloseServerURL)), NULL, 0U, | 706 int32_t result = ws.Connect(pp::Var(std::string(kCloseServerURL)), NULL, 0U, |
578 connect_callback); | 707 connect_callback); |
579 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); | 708 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
580 result = connect_callback.WaitForResult(); | 709 result = connect_callback.WaitForResult(); |
581 ASSERT_EQ(PP_OK, result); | 710 ASSERT_EQ(PP_OK, result); |
582 | 711 |
583 std::string text_message("hello C++"); | 712 std::string text_message("hello C++"); |
584 result = ws.SendMessage(pp::Var(text_message)); | 713 result = ws.SendMessage(pp::Var(text_message)); |
585 ASSERT_EQ(PP_OK, result); | 714 ASSERT_EQ(PP_OK, result); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
623 ASSERT_TRUE(AreEqualWithString(ws.GetCloseReason().pp_var(), reason.c_str())); | 752 ASSERT_TRUE(AreEqualWithString(ws.GetCloseReason().pp_var(), reason.c_str())); |
624 ASSERT_EQ(true, ws.GetCloseWasClean()); | 753 ASSERT_EQ(true, ws.GetCloseWasClean()); |
625 ASSERT_TRUE(AreEqualWithString(ws.GetExtensions().pp_var(), "")); | 754 ASSERT_TRUE(AreEqualWithString(ws.GetExtensions().pp_var(), "")); |
626 ASSERT_TRUE(AreEqualWithString(ws.GetProtocol().pp_var(), "")); | 755 ASSERT_TRUE(AreEqualWithString(ws.GetProtocol().pp_var(), "")); |
627 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED_DEV, ws.GetReadyState()); | 756 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED_DEV, ws.GetReadyState()); |
628 ASSERT_TRUE(AreEqualWithString(ws.GetURL().pp_var(), kCloseServerURL)); | 757 ASSERT_TRUE(AreEqualWithString(ws.GetURL().pp_var(), kCloseServerURL)); |
629 ASSERT_EQ(PP_WEBSOCKETBINARYTYPE_ARRAYBUFFER_DEV, ws.GetBinaryType()); | 758 ASSERT_EQ(PP_WEBSOCKETBINARYTYPE_ARRAYBUFFER_DEV, ws.GetBinaryType()); |
630 | 759 |
631 PASS(); | 760 PASS(); |
632 } | 761 } |
| 762 |
| 763 std::string TestWebSocket::TestUtilityInvalidConnect() { |
| 764 const pp::Var protocols[] = { pp::Var() }; |
| 765 |
| 766 TestWebSocketAPI websocket(instance_); |
| 767 int32_t result = websocket.Connect(pp::Var(), protocols, 1U); |
| 768 ASSERT_EQ(PP_ERROR_BADARGUMENT, result); |
| 769 ASSERT_EQ(0U, websocket.GetSeenEvents().size()); |
| 770 |
| 771 result = websocket.Connect(pp::Var(), protocols, 1U); |
| 772 ASSERT_EQ(PP_ERROR_INPROGRESS, result); |
| 773 ASSERT_EQ(0U, websocket.GetSeenEvents().size()); |
| 774 |
| 775 for (int i = 0; kInvalidURLs[i]; ++i) { |
| 776 TestWebSocketAPI ws(instance_); |
| 777 result = ws.Connect(pp::Var(std::string(kInvalidURLs[i])), protocols, 0U); |
| 778 ASSERT_EQ(PP_ERROR_BADARGUMENT, result); |
| 779 ASSERT_EQ(0U, ws.GetSeenEvents().size()); |
| 780 } |
| 781 |
| 782 PASS(); |
| 783 } |
| 784 |
| 785 std::string TestWebSocket::TestUtilityProtocols() { |
| 786 const pp::Var bad_protocols[] = { |
| 787 pp::Var(std::string("x-test")), pp::Var(std::string("x-test")) }; |
| 788 const pp::Var good_protocols[] = { |
| 789 pp::Var(std::string("x-test")), pp::Var(std::string("x-yatest")) }; |
| 790 |
| 791 { |
| 792 TestWebSocketAPI websocket(instance_); |
| 793 int32_t result = websocket.Connect( |
| 794 pp::Var(std::string(kEchoServerURL)), bad_protocols, 2U); |
| 795 ASSERT_EQ(PP_ERROR_BADARGUMENT, result); |
| 796 ASSERT_EQ(0U, websocket.GetSeenEvents().size()); |
| 797 } |
| 798 |
| 799 { |
| 800 TestWebSocketAPI websocket(instance_); |
| 801 int32_t result = websocket.Connect( |
| 802 pp::Var(std::string(kEchoServerURL)), good_protocols, 2U); |
| 803 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 804 websocket.WaitForConnected(); |
| 805 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents(); |
| 806 // Protocol arguments are valid, but this test run without a WebSocket |
| 807 // server. As a result, OnError() and OnClose() are invoked because of |
| 808 // a connection establishment failure. |
| 809 ASSERT_EQ(2U, events.size()); |
| 810 ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[0].event_type); |
| 811 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type); |
| 812 ASSERT_FALSE(events[1].was_clean); |
| 813 } |
| 814 |
| 815 PASS(); |
| 816 } |
| 817 |
| 818 std::string TestWebSocket::TestUtilityGetURL() { |
| 819 const pp::Var protocols[] = { pp::Var() }; |
| 820 |
| 821 for (int i = 0; kInvalidURLs[i]; ++i) { |
| 822 TestWebSocketAPI websocket(instance_); |
| 823 int32_t result = websocket.Connect( |
| 824 pp::Var(std::string(kInvalidURLs[i])), protocols, 0U); |
| 825 ASSERT_EQ(PP_ERROR_BADARGUMENT, result); |
| 826 pp::Var url = websocket.GetURL(); |
| 827 ASSERT_TRUE(AreEqualWithString(url.pp_var(), kInvalidURLs[i])); |
| 828 ASSERT_EQ(0U, websocket.GetSeenEvents().size()); |
| 829 } |
| 830 |
| 831 PASS(); |
| 832 } |
| 833 |
| 834 std::string TestWebSocket::TestUtilityValidConnect() { |
| 835 const pp::Var protocols[] = { pp::Var() }; |
| 836 TestWebSocketAPI websocket(instance_); |
| 837 int32_t result = websocket.Connect( |
| 838 pp::Var(std::string(kEchoServerURL)), protocols, 0U); |
| 839 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 840 websocket.WaitForConnected(); |
| 841 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents(); |
| 842 ASSERT_EQ(1U, events.size()); |
| 843 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type); |
| 844 |
| 845 PASS(); |
| 846 } |
| 847 |
| 848 std::string TestWebSocket::TestUtilityInvalidClose() { |
| 849 const pp::Var reason = pp::Var(std::string("close for test")); |
| 850 |
| 851 // Close before connect. |
| 852 { |
| 853 TestWebSocketAPI websocket(instance_); |
| 854 int32_t result = websocket.Close(kCloseCodeNormalClosure, reason); |
| 855 ASSERT_EQ(PP_ERROR_FAILED, result); |
| 856 ASSERT_EQ(0U, websocket.GetSeenEvents().size()); |
| 857 } |
| 858 |
| 859 // Close with bad arguments. |
| 860 { |
| 861 TestWebSocketAPI websocket(instance_); |
| 862 int32_t result = websocket.Connect(pp::Var(std::string(kEchoServerURL)), |
| 863 NULL, 0); |
| 864 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 865 websocket.WaitForConnected(); |
| 866 result = websocket.Close(1U, reason); |
| 867 ASSERT_EQ(PP_ERROR_NOACCESS, result); |
| 868 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents(); |
| 869 ASSERT_EQ(1U, events.size()); |
| 870 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type); |
| 871 } |
| 872 |
| 873 PASS(); |
| 874 } |
| 875 |
| 876 std::string TestWebSocket::TestUtilityValidClose() { |
| 877 std::string reason("close for test"); |
| 878 pp::Var url = pp::Var(std::string(kCloseServerURL)); |
| 879 |
| 880 // Close. |
| 881 { |
| 882 TestWebSocketAPI websocket(instance_); |
| 883 int32_t result = websocket.Connect(url, NULL, 0U); |
| 884 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 885 websocket.WaitForConnected(); |
| 886 result = websocket.Close(kCloseCodeNormalClosure, pp::Var(reason)); |
| 887 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 888 websocket.WaitForClosed(); |
| 889 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents(); |
| 890 ASSERT_EQ(2U, events.size()); |
| 891 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type); |
| 892 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type); |
| 893 ASSERT_TRUE(events[1].was_clean); |
| 894 ASSERT_EQ(kCloseCodeNormalClosure, events[1].close_code); |
| 895 ASSERT_TRUE(AreEqualWithString(events[1].var.pp_var(), reason.c_str())); |
| 896 } |
| 897 |
| 898 // Close in connecting. |
| 899 // The ongoing connect failed with PP_ERROR_ABORTED, then the close is done |
| 900 // successfully. |
| 901 { |
| 902 TestWebSocketAPI websocket(instance_); |
| 903 int32_t result = websocket.Connect(url, NULL, 0U); |
| 904 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 905 result = websocket.Close(kCloseCodeNormalClosure, pp::Var(reason)); |
| 906 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 907 websocket.WaitForClosed(); |
| 908 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents(); |
| 909 ASSERT_TRUE(events.size() == 2 || events.size() == 3); |
| 910 int index = 0; |
| 911 if (events.size() == 3) |
| 912 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[index++].event_type); |
| 913 ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[index++].event_type); |
| 914 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[index].event_type); |
| 915 ASSERT_FALSE(events[index].was_clean); |
| 916 } |
| 917 |
| 918 // Close in closing. |
| 919 // The first close will be done successfully, then the second one failed with |
| 920 // with PP_ERROR_INPROGRESS immediately. |
| 921 { |
| 922 TestWebSocketAPI websocket(instance_); |
| 923 int32_t result = websocket.Connect(url, NULL, 0U); |
| 924 result = websocket.Close(kCloseCodeNormalClosure, pp::Var(reason)); |
| 925 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 926 result = websocket.Close(kCloseCodeNormalClosure, pp::Var(reason)); |
| 927 ASSERT_EQ(PP_ERROR_INPROGRESS, result); |
| 928 websocket.WaitForClosed(); |
| 929 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents(); |
| 930 ASSERT_TRUE(events.size() == 2 || events.size() == 3) |
| 931 int index = 0; |
| 932 if (events.size() == 3) |
| 933 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[index++].event_type); |
| 934 ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[index++].event_type); |
| 935 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[index].event_type); |
| 936 ASSERT_FALSE(events[index].was_clean); |
| 937 } |
| 938 |
| 939 PASS(); |
| 940 } |
| 941 |
| 942 std::string TestWebSocket::TestUtilityGetProtocol() { |
| 943 const std::string protocol("x-chat"); |
| 944 const pp::Var protocols[] = { pp::Var(protocol) }; |
| 945 std::string url(kProtocolTestServerURL); |
| 946 url += protocol; |
| 947 TestWebSocketAPI websocket(instance_); |
| 948 int32_t result = websocket.Connect(pp::Var(url), protocols, 1U); |
| 949 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 950 websocket.WaitForReceived(); |
| 951 ASSERT_TRUE(AreEqualWithString( |
| 952 websocket.GetProtocol().pp_var(), protocol.c_str())); |
| 953 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents(); |
| 954 // The server to which this test connect returns the decided protocol as a |
| 955 // text frame message. So the WebSocketEvent records EVENT_MESSAGE event |
| 956 // after EVENT_OPEN event. |
| 957 ASSERT_EQ(2U, events.size()); |
| 958 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type); |
| 959 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type); |
| 960 ASSERT_TRUE(AreEqualWithString(events[1].var.pp_var(), protocol.c_str())); |
| 961 ASSERT_TRUE(events[1].was_clean); |
| 962 |
| 963 PASS(); |
| 964 } |
| 965 |
| 966 std::string TestWebSocket::TestUtilityTextSendReceive() { |
| 967 const pp::Var protocols[] = { pp::Var() }; |
| 968 TestWebSocketAPI websocket(instance_); |
| 969 int32_t result = |
| 970 websocket.Connect(pp::Var(std::string(kEchoServerURL)), protocols, 0U); |
| 971 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 972 websocket.WaitForConnected(); |
| 973 |
| 974 // Send 'hello pepper'. |
| 975 std::string message1("hello pepper"); |
| 976 result = websocket.Send(pp::Var(std::string(message1))); |
| 977 ASSERT_EQ(PP_OK, result); |
| 978 |
| 979 // Receive echoed 'hello pepper'. |
| 980 websocket.WaitForReceived(); |
| 981 |
| 982 // Send 'goodbye pepper'. |
| 983 std::string message2("goodbye pepper"); |
| 984 result = websocket.Send(pp::Var(std::string(message2))); |
| 985 |
| 986 // Receive echoed 'goodbye pepper'. |
| 987 websocket.WaitForReceived(); |
| 988 |
| 989 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents(); |
| 990 ASSERT_EQ(3U, events.size()); |
| 991 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type); |
| 992 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type); |
| 993 ASSERT_TRUE(AreEqualWithString(events[1].var.pp_var(), message1.c_str())); |
| 994 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[2].event_type); |
| 995 ASSERT_TRUE(AreEqualWithString(events[2].var.pp_var(), message2.c_str())); |
| 996 |
| 997 PASS(); |
| 998 } |
| 999 |
| 1000 std::string TestWebSocket::TestUtilityBinarySendReceive() { |
| 1001 const pp::Var protocols[] = { pp::Var() }; |
| 1002 TestWebSocketAPI websocket(instance_); |
| 1003 ASSERT_TRUE( |
| 1004 websocket.SetBinaryType(PP_WEBSOCKETBINARYTYPE_ARRAYBUFFER_DEV)); |
| 1005 int32_t result = |
| 1006 websocket.Connect(pp::Var(std::string(kEchoServerURL)), protocols, 0U); |
| 1007 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 1008 websocket.WaitForConnected(); |
| 1009 |
| 1010 // Send binary message. |
| 1011 pp::VarArrayBuffer_Dev message(256); |
| 1012 uint32_t len = message.ByteLength(); |
| 1013 uint8_t* data = static_cast<uint8_t*>(message.Map()); |
| 1014 for (uint32_t i = 0; i < len; ++i) |
| 1015 data[i] = i; |
| 1016 result = websocket.Send(message); |
| 1017 ASSERT_EQ(PP_OK, result); |
| 1018 |
| 1019 // Receive echoed binary message. |
| 1020 websocket.WaitForReceived(); |
| 1021 |
| 1022 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents(); |
| 1023 ASSERT_EQ(2U, events.size()); |
| 1024 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type); |
| 1025 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type); |
| 1026 ASSERT_TRUE(AreEqualWithBinary(events[1].var.pp_var(), data, len)); |
| 1027 |
| 1028 PASS(); |
| 1029 } |
| 1030 |
| 1031 std::string TestWebSocket::TestUtilityBufferedAmount() { |
| 1032 // Connect to test echo server. |
| 1033 const pp::Var protocols[] = { pp::Var() }; |
| 1034 TestWebSocketAPI websocket(instance_); |
| 1035 int32_t result = |
| 1036 websocket.Connect(pp::Var(std::string(kEchoServerURL)), protocols, 0U); |
| 1037 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 1038 websocket.WaitForConnected(); |
| 1039 |
| 1040 // Prepare a large message that is not aligned with the internal buffer |
| 1041 // sizes. |
| 1042 char message_char[8194]; |
| 1043 memset(message_char, 'x', 8193); |
| 1044 message_char[8193] = 0; |
| 1045 std::string message_str(message_char); |
| 1046 |
| 1047 uint64_t buffered_amount = 0; |
| 1048 uint32_t sent; |
| 1049 for (sent = 0; sent < 100; sent++) { |
| 1050 result = websocket.Send(pp::Var(message_str)); |
| 1051 ASSERT_EQ(PP_OK, result); |
| 1052 buffered_amount = websocket.GetBufferedAmount(); |
| 1053 // Buffered amount size 262144 is too big for the internal buffer size. |
| 1054 if (buffered_amount > 262144) |
| 1055 break; |
| 1056 } |
| 1057 |
| 1058 // Close connection. |
| 1059 std::string reason_str = "close while busy"; |
| 1060 result = websocket.Close(kCloseCodeNormalClosure, pp::Var(reason_str)); |
| 1061 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSING_DEV, websocket.GetReadyState()); |
| 1062 websocket.WaitForClosed(); |
| 1063 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED_DEV, websocket.GetReadyState()); |
| 1064 |
| 1065 uint64_t base_buffered_amount = websocket.GetBufferedAmount(); |
| 1066 size_t events_on_closed = websocket.GetSeenEvents().size(); |
| 1067 |
| 1068 // After connection closure, all sending requests fail and just increase |
| 1069 // the bufferedAmount property. |
| 1070 result = websocket.Send(pp::Var(std::string(""))); |
| 1071 ASSERT_EQ(PP_ERROR_FAILED, result); |
| 1072 buffered_amount = websocket.GetBufferedAmount(); |
| 1073 ASSERT_EQ(base_buffered_amount + kMessageFrameOverhead, buffered_amount); |
| 1074 base_buffered_amount = buffered_amount; |
| 1075 |
| 1076 result = websocket.Send(pp::Var(reason_str)); |
| 1077 ASSERT_EQ(PP_ERROR_FAILED, result); |
| 1078 buffered_amount = websocket.GetBufferedAmount(); |
| 1079 uint64_t reason_frame_size = kMessageFrameOverhead + reason_str.length(); |
| 1080 ASSERT_EQ(base_buffered_amount + reason_frame_size, buffered_amount); |
| 1081 |
| 1082 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents(); |
| 1083 ASSERT_EQ(events_on_closed, events.size()); |
| 1084 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type); |
| 1085 size_t last_event = events_on_closed - 1; |
| 1086 for (uint32_t i = 1; i < last_event; ++i) { |
| 1087 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[i].event_type); |
| 1088 ASSERT_TRUE(AreEqualWithString(events[i].var.pp_var(), message_char)); |
| 1089 } |
| 1090 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[last_event].event_type); |
| 1091 ASSERT_TRUE(events[last_event].was_clean); |
| 1092 |
| 1093 PASS(); |
| 1094 } |
OLD | NEW |