• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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