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 REGISTER_TEST_CASE(TCPServerSocketPrivate);
     22 
     23 TestTCPServerSocketPrivate::TestTCPServerSocketPrivate(
     24     TestingInstance* instance) : TestCase(instance) {
     25 }
     26 
     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 
     56 void TestTCPServerSocketPrivate::RunTests(const std::string& filter) {
     57   RUN_CALLBACK_TEST(TestTCPServerSocketPrivate, Listen, filter);
     58   RUN_CALLBACK_TEST(TestTCPServerSocketPrivate, Backlog, filter);
     59 }
     60 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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