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