Home | History | Annotate | Download | only in tests
      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 namespace {
     22 
     23 const uint16_t kPortScanFrom = 1024;
     24 const uint16_t kPortScanTo = 4096;
     25 
     26 }  // namespace
     27 
     28 REGISTER_TEST_CASE(TCPServerSocketPrivate);
     29 
     30 TestTCPServerSocketPrivate::TestTCPServerSocketPrivate(
     31     TestingInstance* instance) : TestCase(instance) {
     32 }
     33 
     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");
     40   }
     41 
     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");
     45 
     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");
     49 
     50   bool init_host_port = GetLocalHostPort(instance_->pp_instance(),
     51                                          &host_, &port_);
     52   if (!init_host_port)
     53     instance_->AppendError("Can't init host and port");
     54 
     55   return tcp_server_socket_private_is_available &&
     56       tcp_socket_private_is_available &&
     57       net_address_private_is_available &&
     58       init_host_port &&
     59       CheckTestingInterface() &&
     60       EnsureRunningOverHTTP();
     61 }
     62 
     63 void TestTCPServerSocketPrivate::RunTests(const std::string& filter) {
     64   RUN_CALLBACK_TEST(TestTCPServerSocketPrivate, Listen, filter);
     65   RUN_CALLBACK_TEST(TestTCPServerSocketPrivate, Backlog, filter);
     66 }
     67 
     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));
     77   socket.Disconnect();
     78   PASS();
     79 }
     80 
     81 std::string TestTCPServerSocketPrivate::SyncRead(TCPSocketPrivate* socket,
     82                                                  char* buffer,
     83                                                  size_t num_bytes) {
     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();
     92   }
     93   PASS();
     94 }
     95 
     96 std::string TestTCPServerSocketPrivate::SyncWrite(TCPSocketPrivate* socket,
     97                                                   const char* buffer,
     98                                                   size_t num_bytes) {
     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();
    107   }
    108   PASS();
    109 }
    110 
    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());
    119   PASS();
    120 }
    121 
    122 void TestTCPServerSocketPrivate::ForceConnect(TCPSocketPrivate* socket,
    123                                               PP_NetAddress_Private* address) {
    124   std::string error_message;
    125   do {
    126     error_message = SyncConnect(socket, address);
    127   } while (!error_message.empty());
    128 }
    129 
    130 std::string TestTCPServerSocketPrivate::SyncListen(
    131     TCPServerSocketPrivate* socket,
    132     PP_NetAddress_Private* address,
    133     int32_t backlog) {
    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);
    146   PASS();
    147 }
    148 
    149 std::string TestTCPServerSocketPrivate::TestListen() {
    150   static const int kBacklog = 2;
    151 
    152   TCPServerSocketPrivate server_socket(instance_);
    153   PP_NetAddress_Private address;
    154   ASSERT_SUBTEST_SUCCESS(SyncListen(&server_socket, &address, kBacklog));
    155 
    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();
    164   }
    165 
    166   PP_Resource resource;
    167   int32_t accept_rv = server_socket.Accept(&resource,
    168                                            accept_callback.GetCallback());
    169 
    170   TCPSocketPrivate client_socket(instance_);
    171   ForceConnect(&client_socket, &address);
    172 
    173   accept_callback.WaitForResult(accept_rv);
    174   CHECK_CALLBACK_BEHAVIOR(accept_callback);
    175   ASSERT_EQ(PP_OK, accept_callback.result());
    176 
    177   ASSERT_TRUE(resource != 0);
    178   TCPSocketPrivate accepted_socket(pp::PassRef(), resource);
    179 
    180   const char kSentByte = 'a';
    181   ASSERT_SUBTEST_SUCCESS(SyncWrite(&client_socket,
    182                                    &kSentByte,
    183                                    sizeof(kSentByte)));
    184 
    185   char received_byte;
    186   ASSERT_SUBTEST_SUCCESS(SyncRead(&accepted_socket,
    187                                   &received_byte,
    188                                   sizeof(received_byte)));
    189   ASSERT_EQ(kSentByte, received_byte);
    190 
    191   accepted_socket.Disconnect();
    192   client_socket.Disconnect();
    193   server_socket.StopListening();
    194 
    195   PASS();
    196 }
    197 
    198 std::string TestTCPServerSocketPrivate::TestBacklog() {
    199   static const size_t kBacklog = 5;
    200 
    201   TCPServerSocketPrivate server_socket(instance_);
    202   PP_NetAddress_Private address;
    203   ASSERT_SUBTEST_SUCCESS(SyncListen(&server_socket, &address, 2 * kBacklog));
    204 
    205   std::vector<TCPSocketPrivate*> client_sockets(kBacklog);
    206   std::vector<TestCompletionCallback*> connect_callbacks(kBacklog);
    207   std::vector<int32_t> connect_rv(kBacklog);
    208   for (size_t i = 0; i < kBacklog; ++i) {
    209     client_sockets[i] = new TCPSocketPrivate(instance_);
    210     connect_callbacks[i] = new TestCompletionCallback(instance_->pp_instance(),
    211                                                       callback_type());
    212     connect_rv[i] = client_sockets[i]->ConnectWithNetAddress(
    213         &address,
    214         connect_callbacks[i]->GetCallback());
    215   }
    216 
    217   std::vector<PP_Resource> resources(kBacklog);
    218   std::vector<TCPSocketPrivate*> accepted_sockets(kBacklog);
    219   for (size_t i = 0; i < kBacklog; ++i) {
    220     TestCompletionCallback callback(instance_->pp_instance(), callback_type());
    221     callback.WaitForResult(
    222         server_socket.Accept(&resources[i], callback.GetCallback()));
    223     CHECK_CALLBACK_BEHAVIOR(callback);
    224     ASSERT_EQ(PP_OK, callback.result());
    225 
    226     ASSERT_TRUE(resources[i] != 0);
    227     accepted_sockets[i] = new TCPSocketPrivate(pp::PassRef(), resources[i]);
    228   }
    229 
    230   for (size_t i = 0; i < kBacklog; ++i) {
    231     connect_callbacks[i]->WaitForResult(connect_rv[i]);
    232     CHECK_CALLBACK_BEHAVIOR(*connect_callbacks[i]);
    233     ASSERT_EQ(PP_OK, connect_callbacks[i]->result());
    234   }
    235 
    236   for (size_t i = 0; i < kBacklog; ++i) {
    237     const char byte = 'a' + i;
    238     ASSERT_SUBTEST_SUCCESS(SyncWrite(client_sockets[i], &byte, sizeof(byte)));
    239   }
    240 
    241   bool byte_received[kBacklog] = {};
    242   for (size_t i = 0; i < kBacklog; ++i) {
    243     char byte;
    244     ASSERT_SUBTEST_SUCCESS(SyncRead(accepted_sockets[i], &byte, sizeof(byte)));
    245     const size_t index = byte - 'a';
    246     ASSERT_FALSE(byte_received[index]);
    247     byte_received[index] = true;
    248   }
    249 
    250   for (size_t i = 0; i < kBacklog; ++i) {
    251     client_sockets[i]->Disconnect();
    252     delete client_sockets[i];
    253     delete connect_callbacks[i];
    254     accepted_sockets[i]->Disconnect();
    255     delete accepted_sockets[i];
    256   }
    257 
    258   server_socket.StopListening();
    259   PASS();
    260 }
    261