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.
5 #include "ppapi/tests/test_tcp_server_socket_private.h"
9 #include "ppapi/cpp/pass_ref.h"
10 #include "ppapi/cpp/private/net_address_private.h"
11 #include "ppapi/cpp/private/tcp_server_socket_private.h"
12 #include "ppapi/cpp/private/tcp_socket_private.h"
13 #include "ppapi/tests/test_utils.h"
14 #include "ppapi/tests/testing_instance.h"
16 using pp::NetAddressPrivate
;
17 using pp::TCPServerSocketPrivate
;
18 using pp::TCPSocketPrivate
;
22 const uint16_t kPortScanFrom
= 1024;
23 const uint16_t kPortScanTo
= 4096;
27 REGISTER_TEST_CASE(TCPServerSocketPrivate
);
29 TestTCPServerSocketPrivate::TestTCPServerSocketPrivate(
30 TestingInstance
* instance
) : TestCase(instance
) {
33 bool TestTCPServerSocketPrivate::Init() {
34 bool tcp_server_socket_private_is_available
=
35 TCPServerSocketPrivate::IsAvailable();
36 if (!tcp_server_socket_private_is_available
) {
37 instance_
->AppendError(
38 "PPB_TCPServerSocket_Private interface not available");
41 bool tcp_socket_private_is_available
= TCPSocketPrivate::IsAvailable();
42 if (!tcp_socket_private_is_available
)
43 instance_
->AppendError("PPB_TCPSocket_Private interface not available");
45 bool net_address_private_is_available
= NetAddressPrivate::IsAvailable();
46 if (!net_address_private_is_available
)
47 instance_
->AppendError("PPB_NetAddress_Private interface not available");
49 bool init_host_port
= GetLocalHostPort(instance_
->pp_instance(),
52 instance_
->AppendError("Can't init host and port");
54 return tcp_server_socket_private_is_available
&&
55 tcp_socket_private_is_available
&&
56 net_address_private_is_available
&&
58 CheckTestingInterface() &&
59 EnsureRunningOverHTTP();
62 void TestTCPServerSocketPrivate::RunTests(const std::string
& filter
) {
63 RUN_CALLBACK_TEST(TestTCPServerSocketPrivate
, Listen
, filter
);
64 RUN_CALLBACK_TEST(TestTCPServerSocketPrivate
, Backlog
, filter
);
67 std::string
TestTCPServerSocketPrivate::GetLocalAddress(
68 PP_NetAddress_Private
* address
) {
69 TCPSocketPrivate
socket(instance_
);
70 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
71 callback
.WaitForResult(
72 socket
.Connect(host_
.c_str(), port_
, callback
.GetCallback()));
73 CHECK_CALLBACK_BEHAVIOR(callback
);
74 ASSERT_EQ(PP_OK
, callback
.result());
75 ASSERT_TRUE(socket
.GetLocalAddress(address
));
80 std::string
TestTCPServerSocketPrivate::SyncRead(TCPSocketPrivate
* socket
,
83 while (num_bytes
> 0) {
84 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
85 callback
.WaitForResult(
86 socket
->Read(buffer
, num_bytes
, callback
.GetCallback()));
87 CHECK_CALLBACK_BEHAVIOR(callback
);
88 ASSERT_TRUE(callback
.result() >= 0);
89 buffer
+= callback
.result();
90 num_bytes
-= callback
.result();
95 std::string
TestTCPServerSocketPrivate::SyncWrite(TCPSocketPrivate
* socket
,
98 while (num_bytes
> 0) {
99 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
100 callback
.WaitForResult(
101 socket
->Write(buffer
, num_bytes
, callback
.GetCallback()));
102 CHECK_CALLBACK_BEHAVIOR(callback
);
103 ASSERT_TRUE(callback
.result() >= 0);
104 buffer
+= callback
.result();
105 num_bytes
-= callback
.result();
110 std::string
TestTCPServerSocketPrivate::SyncConnect(
111 TCPSocketPrivate
* socket
,
112 PP_NetAddress_Private
* address
) {
113 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
114 callback
.WaitForResult(
115 socket
->ConnectWithNetAddress(address
, callback
.GetCallback()));
116 CHECK_CALLBACK_BEHAVIOR(callback
);
117 ASSERT_EQ(PP_OK
, callback
.result());
121 void TestTCPServerSocketPrivate::ForceConnect(TCPSocketPrivate
* socket
,
122 PP_NetAddress_Private
* address
) {
123 std::string error_message
;
125 error_message
= SyncConnect(socket
, address
);
126 } while (!error_message
.empty());
129 std::string
TestTCPServerSocketPrivate::SyncListen(
130 TCPServerSocketPrivate
* socket
,
131 PP_NetAddress_Private
* address
,
133 PP_NetAddress_Private base_address
;
134 ASSERT_SUBTEST_SUCCESS(GetLocalAddress(&base_address
));
136 // TODO (ygorshenin): find more efficient way to select available
138 bool is_free_port_found
= false;
139 for (uint16_t port
= kPortScanFrom
; port
< kPortScanTo
; ++port
) {
140 if (!NetAddressPrivate::ReplacePort(base_address
, port
, address
))
141 return ReportError("PPB_NetAddress_Private::ReplacePort", 0);
143 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
144 callback
.WaitForResult(
145 socket
->Listen(address
, backlog
, callback
.GetCallback()));
146 CHECK_CALLBACK_BEHAVIOR(callback
);
147 if (callback
.result() == PP_OK
) {
148 is_free_port_found
= true;
153 ASSERT_TRUE(is_free_port_found
);
157 std::string
TestTCPServerSocketPrivate::TestListen() {
158 static const int kBacklog
= 2;
160 TCPServerSocketPrivate
server_socket(instance_
);
162 PP_NetAddress_Private address
;
163 ASSERT_SUBTEST_SUCCESS(SyncListen(&server_socket
, &address
, kBacklog
));
165 // We can't use a blocking callback for Accept, because it will wait forever
166 // for the client to connect, since the client connects after.
167 TestCompletionCallback
accept_callback(instance_
->pp_instance(),
169 // We need to make sure there's a message loop to run accept_callback on.
170 pp::MessageLoop
current_thread_loop(pp::MessageLoop::GetCurrent());
171 if (current_thread_loop
.is_null() && testing_interface_
->IsOutOfProcess()) {
172 current_thread_loop
= pp::MessageLoop(instance_
);
173 current_thread_loop
.AttachToCurrentThread();
176 PP_Resource resource
;
177 int32_t accept_rv
= server_socket
.Accept(&resource
,
178 accept_callback
.GetCallback());
180 TCPSocketPrivate
client_socket(instance_
);
181 ForceConnect(&client_socket
, &address
);
183 accept_callback
.WaitForResult(accept_rv
);
184 CHECK_CALLBACK_BEHAVIOR(accept_callback
);
185 ASSERT_EQ(PP_OK
, accept_callback
.result());
187 ASSERT_TRUE(resource
!= 0);
188 TCPSocketPrivate
accepted_socket(pp::PassRef(), resource
);
190 const char kSentByte
= 'a';
191 ASSERT_SUBTEST_SUCCESS(SyncWrite(&client_socket
,
196 ASSERT_SUBTEST_SUCCESS(SyncRead(&accepted_socket
,
198 sizeof(received_byte
)));
199 ASSERT_EQ(kSentByte
, received_byte
);
201 accepted_socket
.Disconnect();
202 client_socket
.Disconnect();
203 server_socket
.StopListening();
208 std::string
TestTCPServerSocketPrivate::TestBacklog() {
209 static const size_t kBacklog
= 5;
211 TCPServerSocketPrivate
server_socket(instance_
);
213 PP_NetAddress_Private address
;
214 ASSERT_SUBTEST_SUCCESS(SyncListen(&server_socket
, &address
, 2 * kBacklog
));
216 std::vector
<TCPSocketPrivate
*> client_sockets(kBacklog
);
217 std::vector
<TestCompletionCallback
*> connect_callbacks(kBacklog
);
218 std::vector
<int32_t> connect_rv(kBacklog
);
219 for (size_t i
= 0; i
< kBacklog
; ++i
) {
220 client_sockets
[i
] = new TCPSocketPrivate(instance_
);
221 connect_callbacks
[i
] = new TestCompletionCallback(instance_
->pp_instance(),
223 connect_rv
[i
] = client_sockets
[i
]->ConnectWithNetAddress(
225 connect_callbacks
[i
]->GetCallback());
228 std::vector
<PP_Resource
> resources(kBacklog
);
229 std::vector
<TCPSocketPrivate
*> accepted_sockets(kBacklog
);
230 for (size_t i
= 0; i
< kBacklog
; ++i
) {
231 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
232 callback
.WaitForResult(
233 server_socket
.Accept(&resources
[i
], callback
.GetCallback()));
234 CHECK_CALLBACK_BEHAVIOR(callback
);
235 ASSERT_EQ(PP_OK
, callback
.result());
237 ASSERT_TRUE(resources
[i
] != 0);
238 accepted_sockets
[i
] = new TCPSocketPrivate(pp::PassRef(), resources
[i
]);
241 for (size_t i
= 0; i
< kBacklog
; ++i
) {
242 connect_callbacks
[i
]->WaitForResult(connect_rv
[i
]);
243 CHECK_CALLBACK_BEHAVIOR(*connect_callbacks
[i
]);
244 ASSERT_EQ(PP_OK
, connect_callbacks
[i
]->result());
247 for (size_t i
= 0; i
< kBacklog
; ++i
) {
248 const char byte
= 'a' + i
;
249 ASSERT_SUBTEST_SUCCESS(SyncWrite(client_sockets
[i
], &byte
, sizeof(byte
)));
252 bool byte_received
[kBacklog
] = {};
253 for (size_t i
= 0; i
< kBacklog
; ++i
) {
255 ASSERT_SUBTEST_SUCCESS(SyncRead(accepted_sockets
[i
], &byte
, sizeof(byte
)));
256 const size_t index
= byte
- 'a';
257 ASSERT_FALSE(byte_received
[index
]);
258 byte_received
[index
] = true;
261 for (size_t i
= 0; i
< kBacklog
; ++i
) {
262 client_sockets
[i
]->Disconnect();
263 delete client_sockets
[i
];
264 delete connect_callbacks
[i
];
265 accepted_sockets
[i
]->Disconnect();
266 delete accepted_sockets
[i
];
269 server_socket
.StopListening();