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
TestTCPServerSocketPrivate(TestingInstance * instance)23 TestTCPServerSocketPrivate::TestTCPServerSocketPrivate(
24 TestingInstance* instance) : TestCase(instance) {
25 }
26
Init()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
RunTests(const std::string & filter)56 void TestTCPServerSocketPrivate::RunTests(const std::string& filter) {
57 RUN_CALLBACK_TEST(TestTCPServerSocketPrivate, Listen, filter);
58 RUN_CALLBACK_TEST(TestTCPServerSocketPrivate, Backlog, filter);
59 }
60
GetLocalAddress(PP_NetAddress_Private * address)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
SyncRead(TCPSocketPrivate * socket,char * buffer,size_t num_bytes)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
SyncWrite(TCPSocketPrivate * socket,const char * buffer,size_t num_bytes)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
SyncConnect(TCPSocketPrivate * socket,PP_NetAddress_Private * address)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
ForceConnect(TCPSocketPrivate * socket,PP_NetAddress_Private * address)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
SyncListen(TCPServerSocketPrivate * socket,PP_NetAddress_Private * address,int32_t backlog)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
TestListen()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
TestBacklog()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