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_socket_private.h"
      6 
      7 #include <stdlib.h>
      8 
      9 #include <new>
     10 
     11 #include "ppapi/cpp/private/tcp_socket_private.h"
     12 #include "ppapi/tests/test_utils.h"
     13 #include "ppapi/tests/testing_instance.h"
     14 
     15 namespace {
     16 
     17 // Validates the first line of an HTTP response.
     18 bool ValidateHttpResponse(const std::string& s) {
     19   // Just check that it begins with "HTTP/" and ends with a "\r\n".
     20   return s.size() >= 5 &&
     21          s.substr(0, 5) == "HTTP/" &&
     22          s.substr(s.size() - 2) == "\r\n";
     23 }
     24 
     25 }  // namespace
     26 
     27 REGISTER_TEST_CASE(TCPSocketPrivate);
     28 
     29 TestTCPSocketPrivate::TestTCPSocketPrivate(TestingInstance* instance)
     30     : TestCase(instance) {
     31 }
     32 
     33 bool TestTCPSocketPrivate::Init() {
     34   if (!pp::TCPSocketPrivate::IsAvailable())
     35     return false;
     36 
     37   // We need something to connect to, so we connect to the HTTP server whence we
     38   // came. Grab the host and port.
     39   if (!EnsureRunningOverHTTP())
     40     return false;
     41 
     42   if (!GetLocalHostPort(instance_->pp_instance(), &host_, &port_))
     43     return false;
     44 
     45   // Get the port for the SSL server.
     46   ssl_port_ = instance_->ssl_server_port();
     47 
     48   return true;
     49 }
     50 
     51 void TestTCPSocketPrivate::RunTests(const std::string& filter) {
     52   RUN_CALLBACK_TEST(TestTCPSocketPrivate, Basic, filter);
     53   RUN_CALLBACK_TEST(TestTCPSocketPrivate, ReadWrite, filter);
     54   RUN_CALLBACK_TEST(TestTCPSocketPrivate, ReadWriteSSL, filter);
     55   RUN_CALLBACK_TEST(TestTCPSocketPrivate, ConnectAddress, filter);
     56   RUN_CALLBACK_TEST(TestTCPSocketPrivate, SetOption, filter);
     57   RUN_CALLBACK_TEST(TestTCPSocketPrivate, LargeRead, filter);
     58 }
     59 
     60 std::string TestTCPSocketPrivate::TestBasic() {
     61   pp::TCPSocketPrivate socket(instance_);
     62   TestCompletionCallback cb(instance_->pp_instance(), callback_type());
     63 
     64   cb.WaitForResult(socket.Connect(host_.c_str(), port_, cb.GetCallback()));
     65   CHECK_CALLBACK_BEHAVIOR(cb);
     66   ASSERT_EQ(PP_OK, cb.result());
     67 
     68   PP_NetAddress_Private unused;
     69   // TODO(viettrungluu): check the values somehow.
     70   ASSERT_TRUE(socket.GetLocalAddress(&unused));
     71   ASSERT_TRUE(socket.GetRemoteAddress(&unused));
     72 
     73   socket.Disconnect();
     74 
     75   PASS();
     76 }
     77 
     78 std::string TestTCPSocketPrivate::TestReadWrite() {
     79   pp::TCPSocketPrivate socket(instance_);
     80   TestCompletionCallback cb(instance_->pp_instance(), callback_type());
     81 
     82   cb.WaitForResult(socket.Connect(host_.c_str(), port_, cb.GetCallback()));
     83   CHECK_CALLBACK_BEHAVIOR(cb);
     84   ASSERT_EQ(PP_OK, cb.result());
     85 
     86   ASSERT_EQ(PP_OK, WriteStringToSocket(&socket, "GET / HTTP/1.0\r\n\r\n"));
     87 
     88   // Read up to the first \n and check that it looks like valid HTTP response.
     89   std::string s;
     90   ASSERT_EQ(PP_OK, ReadFirstLineFromSocket(&socket, &s));
     91   ASSERT_TRUE(ValidateHttpResponse(s));
     92 
     93   socket.Disconnect();
     94 
     95   PASS();
     96 }
     97 
     98 std::string TestTCPSocketPrivate::TestReadWriteSSL() {
     99   pp::TCPSocketPrivate socket(instance_);
    100   TestCompletionCallback cb(instance_->pp_instance(), callback_type());
    101 
    102   cb.WaitForResult(socket.Connect(host_.c_str(), ssl_port_, cb.GetCallback()));
    103   CHECK_CALLBACK_BEHAVIOR(cb);
    104   ASSERT_EQ(PP_OK, cb.result());
    105 
    106   cb.WaitForResult(
    107       socket.SSLHandshake(host_.c_str(), ssl_port_, cb.GetCallback()));
    108   CHECK_CALLBACK_BEHAVIOR(cb);
    109   ASSERT_EQ(PP_OK, cb.result());
    110 
    111   ASSERT_EQ(PP_OK, WriteStringToSocket(&socket, "GET / HTTP/1.0\r\n\r\n"));
    112 
    113   // Read up to the first \n and check that it looks like valid HTTP response.
    114   std::string s;
    115   ASSERT_EQ(PP_OK, ReadFirstLineFromSocket(&socket, &s));
    116   ASSERT_TRUE(ValidateHttpResponse(s));
    117 
    118   socket.Disconnect();
    119 
    120   PASS();
    121 }
    122 
    123 std::string TestTCPSocketPrivate::TestConnectAddress() {
    124   PP_NetAddress_Private address;
    125 
    126   // First, bring up a connection and grab the address.
    127   {
    128     pp::TCPSocketPrivate socket(instance_);
    129     TestCompletionCallback cb(instance_->pp_instance(), callback_type());
    130     cb.WaitForResult(socket.Connect(host_.c_str(), port_, cb.GetCallback()));
    131     CHECK_CALLBACK_BEHAVIOR(cb);
    132     ASSERT_EQ(PP_OK, cb.result());
    133     ASSERT_TRUE(socket.GetRemoteAddress(&address));
    134     // Omit the |Disconnect()| here to make sure we don't crash if we just let
    135     // the resource be destroyed.
    136   }
    137 
    138   // Connect to that address.
    139   pp::TCPSocketPrivate socket(instance_);
    140   TestCompletionCallback cb(instance_->pp_instance(), callback_type());
    141   cb.WaitForResult(socket.ConnectWithNetAddress(&address, cb.GetCallback()));
    142   CHECK_CALLBACK_BEHAVIOR(cb);
    143   ASSERT_EQ(PP_OK, cb.result());
    144 
    145   // Make sure we can read/write to it properly (see |TestReadWrite()|).
    146   ASSERT_EQ(PP_OK, WriteStringToSocket(&socket, "GET / HTTP/1.0\r\n\r\n"));
    147   std::string s;
    148   ASSERT_EQ(PP_OK, ReadFirstLineFromSocket(&socket, &s));
    149   ASSERT_TRUE(ValidateHttpResponse(s));
    150 
    151   socket.Disconnect();
    152 
    153   PASS();
    154 }
    155 
    156 std::string TestTCPSocketPrivate::TestSetOption() {
    157   pp::TCPSocketPrivate socket(instance_);
    158   TestCompletionCallback cb(instance_->pp_instance(), callback_type());
    159 
    160   cb.WaitForResult(
    161       socket.SetOption(PP_TCPSOCKETOPTION_PRIVATE_NO_DELAY, true,
    162                        cb.GetCallback()));
    163   CHECK_CALLBACK_BEHAVIOR(cb);
    164   ASSERT_EQ(PP_ERROR_FAILED, cb.result());
    165 
    166   cb.WaitForResult(socket.Connect(host_.c_str(), port_, cb.GetCallback()));
    167   CHECK_CALLBACK_BEHAVIOR(cb);
    168   ASSERT_EQ(PP_OK, cb.result());
    169 
    170   cb.WaitForResult(
    171       socket.SetOption(PP_TCPSOCKETOPTION_PRIVATE_NO_DELAY, true,
    172                        cb.GetCallback()));
    173   CHECK_CALLBACK_BEHAVIOR(cb);
    174   ASSERT_EQ(PP_OK, cb.result());
    175 
    176   cb.WaitForResult(
    177       socket.SetOption(PP_TCPSOCKETOPTION_PRIVATE_INVALID, true,
    178                        cb.GetCallback()));
    179   CHECK_CALLBACK_BEHAVIOR(cb);
    180   ASSERT_EQ(PP_ERROR_BADARGUMENT, cb.result());
    181 
    182   socket.Disconnect();
    183 
    184   PASS();
    185 }
    186 
    187 std::string TestTCPSocketPrivate::TestLargeRead() {
    188   pp::TCPSocketPrivate socket(instance_);
    189   {
    190     TestCompletionCallback cb(instance_->pp_instance(), callback_type());
    191 
    192     cb.WaitForResult(socket.Connect(host_.c_str(), port_, cb.GetCallback()));
    193     CHECK_CALLBACK_BEHAVIOR(cb);
    194     ASSERT_EQ(PP_OK, cb.result());
    195   }
    196 
    197   ASSERT_EQ(PP_OK, WriteStringToSocket(&socket, "GET / HTTP/1.0\r\n\r\n"));
    198 
    199   const size_t kReadSize = 1024 * 1024 + 32;
    200   // Create large buffer in heap to prevent run-time errors related to
    201   // limits on stack size.
    202   char* buffer = new (std::nothrow) char[kReadSize];
    203   ASSERT_TRUE(buffer != NULL);
    204 
    205   TestCompletionCallback cb(instance_->pp_instance(), callback_type());
    206   cb.WaitForResult(socket.Read(buffer, kReadSize * sizeof(*buffer),
    207                                cb.GetCallback()));
    208   CHECK_CALLBACK_BEHAVIOR(cb);
    209   ASSERT_LE(0, cb.result());
    210 
    211   delete [] buffer;
    212 
    213   PASS();
    214 }
    215 
    216 int32_t TestTCPSocketPrivate::ReadFirstLineFromSocket(
    217     pp::TCPSocketPrivate* socket,
    218     std::string* s) {
    219   char buffer[10000];
    220 
    221   s->clear();
    222   // Make sure we don't just hang if |Read()| spews.
    223   while (s->size() < 1000000) {
    224     TestCompletionCallback cb(instance_->pp_instance(), callback_type());
    225     int32_t rv = socket->Read(buffer, sizeof(buffer), cb.GetCallback());
    226     if (callback_type() == PP_REQUIRED && rv != PP_OK_COMPLETIONPENDING)
    227       return PP_ERROR_FAILED;
    228     cb.WaitForResult(rv);
    229     if (cb.result() < 0)
    230       return cb.result();
    231     if (cb.result() == 0)
    232       return PP_ERROR_FAILED;  // Didn't get a \n-terminated line.
    233     s->reserve(s->size() + cb.result());
    234     for (int32_t i = 0; i < cb.result(); i++) {
    235       s->push_back(buffer[i]);
    236       if (buffer[i] == '\n')
    237         return PP_OK;
    238     }
    239   }
    240   return PP_ERROR_FAILED;
    241 }
    242 
    243 int32_t TestTCPSocketPrivate::WriteStringToSocket(pp::TCPSocketPrivate* socket,
    244                                                   const std::string& s) {
    245   const char* buffer = s.data();
    246   size_t written = 0;
    247   while (written < s.size()) {
    248     TestCompletionCallback cb(instance_->pp_instance(), callback_type());
    249     int32_t rv = socket->Write(buffer + written, s.size() - written,
    250                                cb.GetCallback());
    251     if (callback_type() == PP_REQUIRED && rv != PP_OK_COMPLETIONPENDING)
    252       return PP_ERROR_FAILED;
    253     cb.WaitForResult(rv);
    254     if (cb.result() < 0)
    255       return cb.result();
    256     if (cb.result() == 0)
    257       return PP_ERROR_FAILED;
    258     written += cb.result();
    259   }
    260   if (written != s.size())
    261     return PP_ERROR_FAILED;
    262   return PP_OK;
    263 }
    264