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/pp_errors.h" | 11 #include "ppapi/c/pp_errors.h" |
12 #include "ppapi/c/pp_var.h" | 12 #include "ppapi/c/pp_var.h" |
13 #include "ppapi/c/pp_completion_callback.h" | 13 #include "ppapi/c/pp_completion_callback.h" |
14 #include "ppapi/c/ppb_core.h" | 14 #include "ppapi/c/ppb_core.h" |
15 #include "ppapi/c/ppb_var.h" | 15 #include "ppapi/c/ppb_var.h" |
16 #include "ppapi/c/ppb_var_array_buffer.h" | 16 #include "ppapi/c/ppb_var_array_buffer.h" |
17 #include "ppapi/c/ppb_websocket.h" | 17 #include "ppapi/c/ppb_websocket.h" |
18 #include "ppapi/cpp/instance.h" | 18 #include "ppapi/cpp/instance.h" |
19 #include "ppapi/cpp/module.h" | 19 #include "ppapi/cpp/module.h" |
| 20 #include "ppapi/cpp/var_array_buffer.h" |
20 #include "ppapi/cpp/websocket.h" | 21 #include "ppapi/cpp/websocket.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 WebSocketDidOpen() { |
| 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 WebSocketDidClose( |
| 101 bool was_clean, uint16_t code, const pp::Var& reason) { |
| 102 events_.push_back( |
| 103 WebSocketEvent(WebSocketEvent::EVENT_CLOSE, was_clean, code, reason)); |
| 104 connected_ = true; |
| 105 closed_ = true; |
| 106 if (wait_for_connected_ || wait_for_closed_) { |
| 107 GetTestingInterface()->QuitMessageLoop(instance_); |
| 108 wait_for_connected_ = false; |
| 109 wait_for_closed_ = false; |
| 110 } |
| 111 } |
| 112 |
| 113 virtual void HandleWebSocketMessage(const pp::Var &message) { |
| 114 events_.push_back( |
| 115 WebSocketEvent(WebSocketEvent::EVENT_MESSAGE, true, 0U, message)); |
| 116 received_ = true; |
| 117 if (wait_for_received_) { |
| 118 GetTestingInterface()->QuitMessageLoop(instance_); |
| 119 wait_for_received_ = false; |
| 120 received_ = false; |
| 121 } |
| 122 } |
| 123 |
| 124 virtual void HandleWebSocketError() { |
| 125 events_.push_back( |
| 126 WebSocketEvent(WebSocketEvent::EVENT_ERROR, true, 0U, pp::Var())); |
| 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*>( | 170 websocket_interface_ = static_cast<const PPB_WebSocket*>( |
53 pp::Module::Get()->GetBrowserInterface(PPB_WEBSOCKET_INTERFACE)); | 171 pp::Module::Get()->GetBrowserInterface(PPB_WEBSOCKET_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*>( | 174 arraybuffer_interface_ = static_cast<const PPB_VarArrayBuffer*>( |
57 pp::Module::Get()->GetBrowserInterface( | 175 pp::Module::Get()->GetBrowserInterface( |
58 PPB_VAR_ARRAY_BUFFER_INTERFACE)); | 176 PPB_VAR_ARRAY_BUFFER_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 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
617 ASSERT_EQ(kCloseCodeNormalClosure, ws.GetCloseCode()); | 746 ASSERT_EQ(kCloseCodeNormalClosure, ws.GetCloseCode()); |
618 ASSERT_TRUE(AreEqualWithString(ws.GetCloseReason().pp_var(), reason.c_str())); | 747 ASSERT_TRUE(AreEqualWithString(ws.GetCloseReason().pp_var(), reason.c_str())); |
619 ASSERT_EQ(true, ws.GetCloseWasClean()); | 748 ASSERT_EQ(true, ws.GetCloseWasClean()); |
620 ASSERT_TRUE(AreEqualWithString(ws.GetExtensions().pp_var(), "")); | 749 ASSERT_TRUE(AreEqualWithString(ws.GetExtensions().pp_var(), "")); |
621 ASSERT_TRUE(AreEqualWithString(ws.GetProtocol().pp_var(), "")); | 750 ASSERT_TRUE(AreEqualWithString(ws.GetProtocol().pp_var(), "")); |
622 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED, ws.GetReadyState()); | 751 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED, ws.GetReadyState()); |
623 ASSERT_TRUE(AreEqualWithString(ws.GetURL().pp_var(), kCloseServerURL)); | 752 ASSERT_TRUE(AreEqualWithString(ws.GetURL().pp_var(), kCloseServerURL)); |
624 | 753 |
625 PASS(); | 754 PASS(); |
626 } | 755 } |
| 756 |
| 757 std::string TestWebSocket::TestUtilityInvalidConnect() { |
| 758 const pp::Var protocols[] = { pp::Var() }; |
| 759 |
| 760 TestWebSocketAPI websocket(instance_); |
| 761 int32_t result = websocket.Connect(pp::Var(), protocols, 1U); |
| 762 ASSERT_EQ(PP_ERROR_BADARGUMENT, result); |
| 763 ASSERT_EQ(0U, websocket.GetSeenEvents().size()); |
| 764 |
| 765 result = websocket.Connect(pp::Var(), protocols, 1U); |
| 766 ASSERT_EQ(PP_ERROR_INPROGRESS, result); |
| 767 ASSERT_EQ(0U, websocket.GetSeenEvents().size()); |
| 768 |
| 769 for (int i = 0; kInvalidURLs[i]; ++i) { |
| 770 TestWebSocketAPI ws(instance_); |
| 771 result = ws.Connect(pp::Var(std::string(kInvalidURLs[i])), protocols, 0U); |
| 772 ASSERT_EQ(PP_ERROR_BADARGUMENT, result); |
| 773 ASSERT_EQ(0U, ws.GetSeenEvents().size()); |
| 774 } |
| 775 |
| 776 PASS(); |
| 777 } |
| 778 |
| 779 std::string TestWebSocket::TestUtilityProtocols() { |
| 780 const pp::Var bad_protocols[] = { |
| 781 pp::Var(std::string("x-test")), pp::Var(std::string("x-test")) }; |
| 782 const pp::Var good_protocols[] = { |
| 783 pp::Var(std::string("x-test")), pp::Var(std::string("x-yatest")) }; |
| 784 |
| 785 { |
| 786 TestWebSocketAPI websocket(instance_); |
| 787 int32_t result = websocket.Connect( |
| 788 pp::Var(std::string(kEchoServerURL)), bad_protocols, 2U); |
| 789 ASSERT_EQ(PP_ERROR_BADARGUMENT, result); |
| 790 ASSERT_EQ(0U, websocket.GetSeenEvents().size()); |
| 791 } |
| 792 |
| 793 { |
| 794 TestWebSocketAPI websocket(instance_); |
| 795 int32_t result = websocket.Connect( |
| 796 pp::Var(std::string(kEchoServerURL)), good_protocols, 2U); |
| 797 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 798 websocket.WaitForConnected(); |
| 799 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents(); |
| 800 // Protocol arguments are valid, but this test run without a WebSocket |
| 801 // server. As a result, OnError() and OnClose() are invoked because of |
| 802 // a connection establishment failure. |
| 803 ASSERT_EQ(2U, events.size()); |
| 804 ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[0].event_type); |
| 805 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type); |
| 806 ASSERT_FALSE(events[1].was_clean); |
| 807 } |
| 808 |
| 809 PASS(); |
| 810 } |
| 811 |
| 812 std::string TestWebSocket::TestUtilityGetURL() { |
| 813 const pp::Var protocols[] = { pp::Var() }; |
| 814 |
| 815 for (int i = 0; kInvalidURLs[i]; ++i) { |
| 816 TestWebSocketAPI websocket(instance_); |
| 817 int32_t result = websocket.Connect( |
| 818 pp::Var(std::string(kInvalidURLs[i])), protocols, 0U); |
| 819 ASSERT_EQ(PP_ERROR_BADARGUMENT, result); |
| 820 pp::Var url = websocket.GetURL(); |
| 821 ASSERT_TRUE(AreEqualWithString(url.pp_var(), kInvalidURLs[i])); |
| 822 ASSERT_EQ(0U, websocket.GetSeenEvents().size()); |
| 823 } |
| 824 |
| 825 PASS(); |
| 826 } |
| 827 |
| 828 std::string TestWebSocket::TestUtilityValidConnect() { |
| 829 const pp::Var protocols[] = { pp::Var() }; |
| 830 TestWebSocketAPI websocket(instance_); |
| 831 int32_t result = websocket.Connect( |
| 832 pp::Var(std::string(kEchoServerURL)), protocols, 0U); |
| 833 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 834 websocket.WaitForConnected(); |
| 835 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents(); |
| 836 ASSERT_EQ(1U, events.size()); |
| 837 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type); |
| 838 |
| 839 PASS(); |
| 840 } |
| 841 |
| 842 std::string TestWebSocket::TestUtilityInvalidClose() { |
| 843 const pp::Var reason = pp::Var(std::string("close for test")); |
| 844 |
| 845 // Close before connect. |
| 846 { |
| 847 TestWebSocketAPI websocket(instance_); |
| 848 int32_t result = websocket.Close(kCloseCodeNormalClosure, reason); |
| 849 ASSERT_EQ(PP_ERROR_FAILED, result); |
| 850 ASSERT_EQ(0U, websocket.GetSeenEvents().size()); |
| 851 } |
| 852 |
| 853 // Close with bad arguments. |
| 854 { |
| 855 TestWebSocketAPI websocket(instance_); |
| 856 int32_t result = websocket.Connect(pp::Var(std::string(kEchoServerURL)), |
| 857 NULL, 0); |
| 858 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 859 websocket.WaitForConnected(); |
| 860 result = websocket.Close(1U, reason); |
| 861 ASSERT_EQ(PP_ERROR_NOACCESS, result); |
| 862 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents(); |
| 863 ASSERT_EQ(1U, events.size()); |
| 864 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type); |
| 865 } |
| 866 |
| 867 PASS(); |
| 868 } |
| 869 |
| 870 std::string TestWebSocket::TestUtilityValidClose() { |
| 871 std::string reason("close for test"); |
| 872 pp::Var url = pp::Var(std::string(kCloseServerURL)); |
| 873 |
| 874 // Close. |
| 875 { |
| 876 TestWebSocketAPI websocket(instance_); |
| 877 int32_t result = websocket.Connect(url, NULL, 0U); |
| 878 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 879 websocket.WaitForConnected(); |
| 880 result = websocket.Close(kCloseCodeNormalClosure, pp::Var(reason)); |
| 881 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 882 websocket.WaitForClosed(); |
| 883 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents(); |
| 884 ASSERT_EQ(2U, events.size()); |
| 885 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type); |
| 886 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type); |
| 887 ASSERT_TRUE(events[1].was_clean); |
| 888 ASSERT_EQ(kCloseCodeNormalClosure, events[1].close_code); |
| 889 ASSERT_TRUE(AreEqualWithString(events[1].var.pp_var(), reason.c_str())); |
| 890 } |
| 891 |
| 892 // Close in connecting. |
| 893 // The ongoing connect failed with PP_ERROR_ABORTED, then the close is done |
| 894 // successfully. |
| 895 { |
| 896 TestWebSocketAPI websocket(instance_); |
| 897 int32_t result = websocket.Connect(url, NULL, 0U); |
| 898 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 899 result = websocket.Close(kCloseCodeNormalClosure, pp::Var(reason)); |
| 900 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 901 websocket.WaitForClosed(); |
| 902 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents(); |
| 903 ASSERT_TRUE(events.size() == 2 || events.size() == 3); |
| 904 int index = 0; |
| 905 if (events.size() == 3) |
| 906 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[index++].event_type); |
| 907 ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[index++].event_type); |
| 908 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[index].event_type); |
| 909 ASSERT_FALSE(events[index].was_clean); |
| 910 } |
| 911 |
| 912 // Close in closing. |
| 913 // The first close will be done successfully, then the second one failed with |
| 914 // with PP_ERROR_INPROGRESS immediately. |
| 915 { |
| 916 TestWebSocketAPI websocket(instance_); |
| 917 int32_t result = websocket.Connect(url, NULL, 0U); |
| 918 result = websocket.Close(kCloseCodeNormalClosure, pp::Var(reason)); |
| 919 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 920 result = websocket.Close(kCloseCodeNormalClosure, pp::Var(reason)); |
| 921 ASSERT_EQ(PP_ERROR_INPROGRESS, result); |
| 922 websocket.WaitForClosed(); |
| 923 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents(); |
| 924 ASSERT_TRUE(events.size() == 2 || events.size() == 3) |
| 925 int index = 0; |
| 926 if (events.size() == 3) |
| 927 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[index++].event_type); |
| 928 ASSERT_EQ(WebSocketEvent::EVENT_ERROR, events[index++].event_type); |
| 929 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[index].event_type); |
| 930 ASSERT_FALSE(events[index].was_clean); |
| 931 } |
| 932 |
| 933 PASS(); |
| 934 } |
| 935 |
| 936 std::string TestWebSocket::TestUtilityGetProtocol() { |
| 937 const std::string protocol("x-chat"); |
| 938 const pp::Var protocols[] = { pp::Var(protocol) }; |
| 939 std::string url(kProtocolTestServerURL); |
| 940 url += protocol; |
| 941 TestWebSocketAPI websocket(instance_); |
| 942 int32_t result = websocket.Connect(pp::Var(url), protocols, 1U); |
| 943 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 944 websocket.WaitForReceived(); |
| 945 ASSERT_TRUE(AreEqualWithString( |
| 946 websocket.GetProtocol().pp_var(), protocol.c_str())); |
| 947 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents(); |
| 948 // The server to which this test connect returns the decided protocol as a |
| 949 // text frame message. So the WebSocketEvent records EVENT_MESSAGE event |
| 950 // after EVENT_OPEN event. |
| 951 ASSERT_EQ(2U, events.size()); |
| 952 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type); |
| 953 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type); |
| 954 ASSERT_TRUE(AreEqualWithString(events[1].var.pp_var(), protocol.c_str())); |
| 955 ASSERT_TRUE(events[1].was_clean); |
| 956 |
| 957 PASS(); |
| 958 } |
| 959 |
| 960 std::string TestWebSocket::TestUtilityTextSendReceive() { |
| 961 const pp::Var protocols[] = { pp::Var() }; |
| 962 TestWebSocketAPI websocket(instance_); |
| 963 int32_t result = |
| 964 websocket.Connect(pp::Var(std::string(kEchoServerURL)), protocols, 0U); |
| 965 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 966 websocket.WaitForConnected(); |
| 967 |
| 968 // Send 'hello pepper'. |
| 969 std::string message1("hello pepper"); |
| 970 result = websocket.Send(pp::Var(std::string(message1))); |
| 971 ASSERT_EQ(PP_OK, result); |
| 972 |
| 973 // Receive echoed 'hello pepper'. |
| 974 websocket.WaitForReceived(); |
| 975 |
| 976 // Send 'goodbye pepper'. |
| 977 std::string message2("goodbye pepper"); |
| 978 result = websocket.Send(pp::Var(std::string(message2))); |
| 979 |
| 980 // Receive echoed 'goodbye pepper'. |
| 981 websocket.WaitForReceived(); |
| 982 |
| 983 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents(); |
| 984 ASSERT_EQ(3U, events.size()); |
| 985 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type); |
| 986 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type); |
| 987 ASSERT_TRUE(AreEqualWithString(events[1].var.pp_var(), message1.c_str())); |
| 988 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[2].event_type); |
| 989 ASSERT_TRUE(AreEqualWithString(events[2].var.pp_var(), message2.c_str())); |
| 990 |
| 991 PASS(); |
| 992 } |
| 993 |
| 994 std::string TestWebSocket::TestUtilityBinarySendReceive() { |
| 995 const pp::Var protocols[] = { pp::Var() }; |
| 996 TestWebSocketAPI websocket(instance_); |
| 997 int32_t result = |
| 998 websocket.Connect(pp::Var(std::string(kEchoServerURL)), protocols, 0U); |
| 999 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 1000 websocket.WaitForConnected(); |
| 1001 |
| 1002 // Send binary message. |
| 1003 pp::VarArrayBuffer message(256); |
| 1004 uint32_t len = message.ByteLength(); |
| 1005 uint8_t* data = static_cast<uint8_t*>(message.Map()); |
| 1006 for (uint32_t i = 0; i < len; ++i) |
| 1007 data[i] = i; |
| 1008 result = websocket.Send(message); |
| 1009 ASSERT_EQ(PP_OK, result); |
| 1010 |
| 1011 // Receive echoed binary message. |
| 1012 websocket.WaitForReceived(); |
| 1013 |
| 1014 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents(); |
| 1015 ASSERT_EQ(2U, events.size()); |
| 1016 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type); |
| 1017 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type); |
| 1018 ASSERT_TRUE(AreEqualWithBinary(events[1].var.pp_var(), data, len)); |
| 1019 |
| 1020 PASS(); |
| 1021 } |
| 1022 |
| 1023 std::string TestWebSocket::TestUtilityBufferedAmount() { |
| 1024 // Connect to test echo server. |
| 1025 const pp::Var protocols[] = { pp::Var() }; |
| 1026 TestWebSocketAPI websocket(instance_); |
| 1027 int32_t result = |
| 1028 websocket.Connect(pp::Var(std::string(kEchoServerURL)), protocols, 0U); |
| 1029 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); |
| 1030 websocket.WaitForConnected(); |
| 1031 |
| 1032 // Prepare a large message that is not aligned with the internal buffer |
| 1033 // sizes. |
| 1034 char message_char[8194]; |
| 1035 memset(message_char, 'x', 8193); |
| 1036 message_char[8193] = 0; |
| 1037 std::string message_str(message_char); |
| 1038 |
| 1039 uint64_t buffered_amount = 0; |
| 1040 uint32_t sent; |
| 1041 for (sent = 0; sent < 100; sent++) { |
| 1042 result = websocket.Send(pp::Var(message_str)); |
| 1043 ASSERT_EQ(PP_OK, result); |
| 1044 buffered_amount = websocket.GetBufferedAmount(); |
| 1045 // Buffered amount size 262144 is too big for the internal buffer size. |
| 1046 if (buffered_amount > 262144) |
| 1047 break; |
| 1048 } |
| 1049 |
| 1050 // Close connection. |
| 1051 std::string reason_str = "close while busy"; |
| 1052 result = websocket.Close(kCloseCodeNormalClosure, pp::Var(reason_str)); |
| 1053 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSING, websocket.GetReadyState()); |
| 1054 websocket.WaitForClosed(); |
| 1055 ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSED, websocket.GetReadyState()); |
| 1056 |
| 1057 uint64_t base_buffered_amount = websocket.GetBufferedAmount(); |
| 1058 size_t events_on_closed = websocket.GetSeenEvents().size(); |
| 1059 |
| 1060 // After connection closure, all sending requests fail and just increase |
| 1061 // the bufferedAmount property. |
| 1062 result = websocket.Send(pp::Var(std::string(""))); |
| 1063 ASSERT_EQ(PP_ERROR_FAILED, result); |
| 1064 buffered_amount = websocket.GetBufferedAmount(); |
| 1065 ASSERT_EQ(base_buffered_amount + kMessageFrameOverhead, buffered_amount); |
| 1066 base_buffered_amount = buffered_amount; |
| 1067 |
| 1068 result = websocket.Send(pp::Var(reason_str)); |
| 1069 ASSERT_EQ(PP_ERROR_FAILED, result); |
| 1070 buffered_amount = websocket.GetBufferedAmount(); |
| 1071 uint64_t reason_frame_size = kMessageFrameOverhead + reason_str.length(); |
| 1072 ASSERT_EQ(base_buffered_amount + reason_frame_size, buffered_amount); |
| 1073 |
| 1074 const std::vector<WebSocketEvent>& events = websocket.GetSeenEvents(); |
| 1075 ASSERT_EQ(events_on_closed, events.size()); |
| 1076 ASSERT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type); |
| 1077 size_t last_event = events_on_closed - 1; |
| 1078 for (uint32_t i = 1; i < last_event; ++i) { |
| 1079 ASSERT_EQ(WebSocketEvent::EVENT_MESSAGE, events[i].event_type); |
| 1080 ASSERT_TRUE(AreEqualWithString(events[i].var.pp_var(), message_char)); |
| 1081 } |
| 1082 ASSERT_EQ(WebSocketEvent::EVENT_CLOSE, events[last_event].event_type); |
| 1083 ASSERT_TRUE(events[last_event].was_clean); |
| 1084 |
| 1085 PASS(); |
| 1086 } |
OLD | NEW |