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_tcp_server_socket_private.h" 6 7 #include <cstdio> 8 #include <vector> 9 10 #include "ppapi/cpp/pass_ref.h" 11 #include "ppapi/cpp/private/net_address_private.h" 12 #include "ppapi/cpp/private/tcp_server_socket_private.h" 13 #include "ppapi/cpp/private/tcp_socket_private.h" 14 #include "ppapi/tests/test_utils.h" 15 #include "ppapi/tests/testing_instance.h" 16 17 using pp::NetAddressPrivate; 18 using pp::TCPServerSocketPrivate; 19 using pp::TCPSocketPrivate; 20 21 namespace { 22 23 const uint16_t kPortScanFrom = 1024; 24 const uint16_t kPortScanTo = 4096; 25 26 } // namespace 27 28 REGISTER_TEST_CASE(TCPServerSocketPrivate); 29 30 TestTCPServerSocketPrivate::TestTCPServerSocketPrivate( 31 TestingInstance* instance) : TestCase(instance) { 32 } 33 34 bool TestTCPServerSocketPrivate::Init() { 35 bool tcp_server_socket_private_is_available = 36 TCPServerSocketPrivate::IsAvailable(); 37 if (!tcp_server_socket_private_is_available) { 38 instance_->AppendError( 39 "PPB_TCPServerSocket_Private interface not available"); 40 } 41 42 bool tcp_socket_private_is_available = TCPSocketPrivate::IsAvailable(); 43 if (!tcp_socket_private_is_available) 44 instance_->AppendError("PPB_TCPSocket_Private interface not available"); 45 46 bool net_address_private_is_available = NetAddressPrivate::IsAvailable(); 47 if (!net_address_private_is_available) 48 instance_->AppendError("PPB_NetAddress_Private interface not available"); 49 50 bool init_host_port = GetLocalHostPort(instance_->pp_instance(), 51 &host_, &port_); 52 if (!init_host_port) 53 instance_->AppendError("Can't init host and port"); 54 55 return tcp_server_socket_private_is_available && 56 tcp_socket_private_is_available && 57 net_address_private_is_available && 58 init_host_port && 59 CheckTestingInterface() && 60 EnsureRunningOverHTTP(); 61 } 62 63 void TestTCPServerSocketPrivate::RunTests(const std::string& filter) { 64 RUN_CALLBACK_TEST(TestTCPServerSocketPrivate, Listen, filter); 65 RUN_CALLBACK_TEST(TestTCPServerSocketPrivate, Backlog, filter); 66 } 67 68 std::string TestTCPServerSocketPrivate::GetLocalAddress( 69 PP_NetAddress_Private* address) { 70 TCPSocketPrivate socket(instance_); 71 TestCompletionCallback callback(instance_->pp_instance(), callback_type()); 72 callback.WaitForResult( 73 socket.Connect(host_.c_str(), port_, callback.GetCallback())); 74 CHECK_CALLBACK_BEHAVIOR(callback); 75 ASSERT_EQ(PP_OK, callback.result()); 76 ASSERT_TRUE(socket.GetLocalAddress(address)); 77 socket.Disconnect(); 78 PASS(); 79 } 80 81 std::string TestTCPServerSocketPrivate::SyncRead(TCPSocketPrivate* socket, 82 char* buffer, 83 size_t num_bytes) { 84 while (num_bytes > 0) { 85 TestCompletionCallback callback(instance_->pp_instance(), callback_type()); 86 callback.WaitForResult( 87 socket->Read(buffer, num_bytes, callback.GetCallback())); 88 CHECK_CALLBACK_BEHAVIOR(callback); 89 ASSERT_TRUE(callback.result() >= 0); 90 buffer += callback.result(); 91 num_bytes -= callback.result(); 92 } 93 PASS(); 94 } 95 96 std::string TestTCPServerSocketPrivate::SyncWrite(TCPSocketPrivate* socket, 97 const char* buffer, 98 size_t num_bytes) { 99 while (num_bytes > 0) { 100 TestCompletionCallback callback(instance_->pp_instance(), callback_type()); 101 callback.WaitForResult( 102 socket->Write(buffer, num_bytes, callback.GetCallback())); 103 CHECK_CALLBACK_BEHAVIOR(callback); 104 ASSERT_TRUE(callback.result() >= 0); 105 buffer += callback.result(); 106 num_bytes -= callback.result(); 107 } 108 PASS(); 109 } 110 111 std::string TestTCPServerSocketPrivate::SyncConnect( 112 TCPSocketPrivate* socket, 113 PP_NetAddress_Private* address) { 114 TestCompletionCallback callback(instance_->pp_instance(), callback_type()); 115 callback.WaitForResult( 116 socket->ConnectWithNetAddress(address, callback.GetCallback())); 117 CHECK_CALLBACK_BEHAVIOR(callback); 118 ASSERT_EQ(PP_OK, callback.result()); 119 PASS(); 120 } 121 122 void TestTCPServerSocketPrivate::ForceConnect(TCPSocketPrivate* socket, 123 PP_NetAddress_Private* address) { 124 std::string error_message; 125 do { 126 error_message = SyncConnect(socket, address); 127 } while (!error_message.empty()); 128 } 129 130 std::string TestTCPServerSocketPrivate::SyncListen( 131 TCPServerSocketPrivate* socket, 132 PP_NetAddress_Private* address, 133 int32_t backlog) { 134 PP_NetAddress_Private base_address; 135 ASSERT_SUBTEST_SUCCESS(GetLocalAddress(&base_address)); 136 if (!NetAddressPrivate::ReplacePort(base_address, 0, address)) 137 return ReportError("PPB_NetAddress_Private::ReplacePort", 0); 138 TestCompletionCallback callback(instance_->pp_instance(), callback_type()); 139 callback.WaitForResult( 140 socket->Listen(address, backlog, callback.GetCallback())); 141 CHECK_CALLBACK_BEHAVIOR(callback); 142 ASSERT_EQ(PP_OK, callback.result()); 143 int32_t rv = socket->GetLocalAddress(address); 144 ASSERT_EQ(PP_OK, rv); 145 ASSERT_TRUE(NetAddressPrivate::GetPort(*address) != 0); 146 PASS(); 147 } 148 149 std::string TestTCPServerSocketPrivate::TestListen() { 150 static const int kBacklog = 2; 151 152 TCPServerSocketPrivate server_socket(instance_); 153 PP_NetAddress_Private address; 154 ASSERT_SUBTEST_SUCCESS(SyncListen(&server_socket, &address, kBacklog)); 155 156 // We can't use a blocking callback for Accept, because it will wait forever 157 // for the client to connect, since the client connects after. 158 TestCompletionCallback accept_callback(instance_->pp_instance(), PP_REQUIRED); 159 // We need to make sure there's a message loop to run accept_callback on. 160 pp::MessageLoop current_thread_loop(pp::MessageLoop::GetCurrent()); 161 if (current_thread_loop.is_null() && testing_interface_->IsOutOfProcess()) { 162 current_thread_loop = pp::MessageLoop(instance_); 163 current_thread_loop.AttachToCurrentThread(); 164 } 165 166 PP_Resource resource; 167 int32_t accept_rv = server_socket.Accept(&resource, 168 accept_callback.GetCallback()); 169 170 TCPSocketPrivate client_socket(instance_); 171 ForceConnect(&client_socket, &address); 172 173 accept_callback.WaitForResult(accept_rv); 174 CHECK_CALLBACK_BEHAVIOR(accept_callback); 175 ASSERT_EQ(PP_OK, accept_callback.result()); 176 177 ASSERT_TRUE(resource != 0); 178 TCPSocketPrivate accepted_socket(pp::PassRef(), resource); 179 180 const char kSentByte = 'a'; 181 ASSERT_SUBTEST_SUCCESS(SyncWrite(&client_socket, 182 &kSentByte, 183 sizeof(kSentByte))); 184 185 char received_byte; 186 ASSERT_SUBTEST_SUCCESS(SyncRead(&accepted_socket, 187 &received_byte, 188 sizeof(received_byte))); 189 ASSERT_EQ(kSentByte, received_byte); 190 191 accepted_socket.Disconnect(); 192 client_socket.Disconnect(); 193 server_socket.StopListening(); 194 195 PASS(); 196 } 197 198 std::string TestTCPServerSocketPrivate::TestBacklog() { 199 static const size_t kBacklog = 5; 200 201 TCPServerSocketPrivate server_socket(instance_); 202 PP_NetAddress_Private address; 203 ASSERT_SUBTEST_SUCCESS(SyncListen(&server_socket, &address, 2 * kBacklog)); 204 205 std::vector<TCPSocketPrivate*> client_sockets(kBacklog); 206 std::vector<TestCompletionCallback*> connect_callbacks(kBacklog); 207 std::vector<int32_t> connect_rv(kBacklog); 208 for (size_t i = 0; i < kBacklog; ++i) { 209 client_sockets[i] = new TCPSocketPrivate(instance_); 210 connect_callbacks[i] = new TestCompletionCallback(instance_->pp_instance(), 211 callback_type()); 212 connect_rv[i] = client_sockets[i]->ConnectWithNetAddress( 213 &address, 214 connect_callbacks[i]->GetCallback()); 215 } 216 217 std::vector<PP_Resource> resources(kBacklog); 218 std::vector<TCPSocketPrivate*> accepted_sockets(kBacklog); 219 for (size_t i = 0; i < kBacklog; ++i) { 220 TestCompletionCallback callback(instance_->pp_instance(), callback_type()); 221 callback.WaitForResult( 222 server_socket.Accept(&resources[i], callback.GetCallback())); 223 CHECK_CALLBACK_BEHAVIOR(callback); 224 ASSERT_EQ(PP_OK, callback.result()); 225 226 ASSERT_TRUE(resources[i] != 0); 227 accepted_sockets[i] = new TCPSocketPrivate(pp::PassRef(), resources[i]); 228 } 229 230 for (size_t i = 0; i < kBacklog; ++i) { 231 connect_callbacks[i]->WaitForResult(connect_rv[i]); 232 CHECK_CALLBACK_BEHAVIOR(*connect_callbacks[i]); 233 ASSERT_EQ(PP_OK, connect_callbacks[i]->result()); 234 } 235 236 for (size_t i = 0; i < kBacklog; ++i) { 237 const char byte = 'a' + i; 238 ASSERT_SUBTEST_SUCCESS(SyncWrite(client_sockets[i], &byte, sizeof(byte))); 239 } 240 241 bool byte_received[kBacklog] = {}; 242 for (size_t i = 0; i < kBacklog; ++i) { 243 char byte; 244 ASSERT_SUBTEST_SUCCESS(SyncRead(accepted_sockets[i], &byte, sizeof(byte))); 245 const size_t index = byte - 'a'; 246 ASSERT_FALSE(byte_received[index]); 247 byte_received[index] = true; 248 } 249 250 for (size_t i = 0; i < kBacklog; ++i) { 251 client_sockets[i]->Disconnect(); 252 delete client_sockets[i]; 253 delete connect_callbacks[i]; 254 accepted_sockets[i]->Disconnect(); 255 delete accepted_sockets[i]; 256 } 257 258 server_socket.StopListening(); 259 PASS(); 260 } 261