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"
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"
17 using pp::NetAddressPrivate
;
18 using pp::TCPServerSocketPrivate
;
19 using pp::TCPSocketPrivate
;
23 const uint16_t kPortScanFrom
= 1024;
24 const uint16_t kPortScanTo
= 4096;
28 REGISTER_TEST_CASE(TCPServerSocketPrivate
);
30 TestTCPServerSocketPrivate::TestTCPServerSocketPrivate(
31 TestingInstance
* instance
) : TestCase(instance
) {
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");
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");
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");
50 bool init_host_port
= GetLocalHostPort(instance_
->pp_instance(),
53 instance_
->AppendError("Can't init host and port");
55 return tcp_server_socket_private_is_available
&&
56 tcp_socket_private_is_available
&&
57 net_address_private_is_available
&&
59 CheckTestingInterface() &&
60 EnsureRunningOverHTTP();
63 void TestTCPServerSocketPrivate::RunTests(const std::string
& filter
) {
64 RUN_CALLBACK_TEST(TestTCPServerSocketPrivate
, Listen
, filter
);
65 RUN_CALLBACK_TEST(TestTCPServerSocketPrivate
, Backlog
, filter
);
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
));
81 std::string
TestTCPServerSocketPrivate::SyncRead(TCPSocketPrivate
* socket
,
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();
96 std::string
TestTCPServerSocketPrivate::SyncWrite(TCPSocketPrivate
* socket
,
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();
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());
122 void TestTCPServerSocketPrivate::ForceConnect(TCPSocketPrivate
* socket
,
123 PP_NetAddress_Private
* address
) {
124 std::string error_message
;
126 error_message
= SyncConnect(socket
, address
);
127 } while (!error_message
.empty());
130 std::string
TestTCPServerSocketPrivate::SyncListen(
131 TCPServerSocketPrivate
* socket
,
132 PP_NetAddress_Private
* address
,
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);
149 std::string
TestTCPServerSocketPrivate::TestListen() {
150 static const int kBacklog
= 2;
152 TCPServerSocketPrivate
server_socket(instance_
);
153 PP_NetAddress_Private address
;
154 ASSERT_SUBTEST_SUCCESS(SyncListen(&server_socket
, &address
, kBacklog
));
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();
166 PP_Resource resource
;
167 int32_t accept_rv
= server_socket
.Accept(&resource
,
168 accept_callback
.GetCallback());
170 TCPSocketPrivate
client_socket(instance_
);
171 ForceConnect(&client_socket
, &address
);
173 PP_NetAddress_Private client_local_addr
, client_remote_addr
;
174 ASSERT_TRUE(client_socket
.GetLocalAddress(&client_local_addr
));
175 ASSERT_TRUE(client_socket
.GetRemoteAddress(&client_remote_addr
));
177 accept_callback
.WaitForResult(accept_rv
);
178 CHECK_CALLBACK_BEHAVIOR(accept_callback
);
179 ASSERT_EQ(PP_OK
, accept_callback
.result());
181 ASSERT_TRUE(resource
!= 0);
182 TCPSocketPrivate
accepted_socket(pp::PassRef(), resource
);
183 PP_NetAddress_Private accepted_local_addr
, accepted_remote_addr
;
184 ASSERT_TRUE(accepted_socket
.GetLocalAddress(&accepted_local_addr
));
185 ASSERT_TRUE(accepted_socket
.GetRemoteAddress(&accepted_remote_addr
));
186 ASSERT_TRUE(NetAddressPrivate::AreEqual(client_local_addr
,
187 accepted_remote_addr
));
189 const char kSentByte
= 'a';
190 ASSERT_SUBTEST_SUCCESS(SyncWrite(&client_socket
,
195 ASSERT_SUBTEST_SUCCESS(SyncRead(&accepted_socket
,
197 sizeof(received_byte
)));
198 ASSERT_EQ(kSentByte
, received_byte
);
200 accepted_socket
.Disconnect();
201 client_socket
.Disconnect();
202 server_socket
.StopListening();
207 std::string
TestTCPServerSocketPrivate::TestBacklog() {
208 static const size_t kBacklog
= 5;
210 TCPServerSocketPrivate
server_socket(instance_
);
211 PP_NetAddress_Private address
;
212 ASSERT_SUBTEST_SUCCESS(SyncListen(&server_socket
, &address
, 2 * kBacklog
));
214 std::vector
<TCPSocketPrivate
*> client_sockets(kBacklog
);
215 std::vector
<TestCompletionCallback
*> connect_callbacks(kBacklog
);
216 std::vector
<int32_t> connect_rv(kBacklog
);
217 for (size_t i
= 0; i
< kBacklog
; ++i
) {
218 client_sockets
[i
] = new TCPSocketPrivate(instance_
);
219 connect_callbacks
[i
] = new TestCompletionCallback(instance_
->pp_instance(),
221 connect_rv
[i
] = client_sockets
[i
]->ConnectWithNetAddress(
223 connect_callbacks
[i
]->GetCallback());
226 std::vector
<PP_Resource
> resources(kBacklog
);
227 std::vector
<TCPSocketPrivate
*> accepted_sockets(kBacklog
);
228 for (size_t i
= 0; i
< kBacklog
; ++i
) {
229 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
230 callback
.WaitForResult(
231 server_socket
.Accept(&resources
[i
], callback
.GetCallback()));
232 CHECK_CALLBACK_BEHAVIOR(callback
);
233 ASSERT_EQ(PP_OK
, callback
.result());
235 ASSERT_TRUE(resources
[i
] != 0);
236 accepted_sockets
[i
] = new TCPSocketPrivate(pp::PassRef(), resources
[i
]);
239 for (size_t i
= 0; i
< kBacklog
; ++i
) {
240 connect_callbacks
[i
]->WaitForResult(connect_rv
[i
]);
241 CHECK_CALLBACK_BEHAVIOR(*connect_callbacks
[i
]);
242 ASSERT_EQ(PP_OK
, connect_callbacks
[i
]->result());
245 for (size_t i
= 0; i
< kBacklog
; ++i
) {
246 const char byte
= 'a' + i
;
247 ASSERT_SUBTEST_SUCCESS(SyncWrite(client_sockets
[i
], &byte
, sizeof(byte
)));
250 bool byte_received
[kBacklog
] = {};
251 for (size_t i
= 0; i
< kBacklog
; ++i
) {
253 ASSERT_SUBTEST_SUCCESS(SyncRead(accepted_sockets
[i
], &byte
, sizeof(byte
)));
254 const size_t index
= byte
- 'a';
255 ASSERT_FALSE(byte_received
[index
]);
256 byte_received
[index
] = true;
259 for (size_t i
= 0; i
< kBacklog
; ++i
) {
260 client_sockets
[i
]->Disconnect();
261 delete client_sockets
[i
];
262 delete connect_callbacks
[i
];
263 accepted_sockets
[i
]->Disconnect();
264 delete accepted_sockets
[i
];
267 server_socket
.StopListening();