Home | History | Annotate | Download | only in tests
      1 // Copyright 2013 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.h"
      6 
      7 #include "ppapi/cpp/tcp_socket.h"
      8 #include "ppapi/tests/test_utils.h"
      9 #include "ppapi/tests/testing_instance.h"
     10 
     11 namespace {
     12 
     13 // Validates the first line of an HTTP response.
     14 bool ValidateHttpResponse(const std::string& s) {
     15   // Just check that it begins with "HTTP/" and ends with a "\r\n".
     16   return s.size() >= 5 &&
     17          s.substr(0, 5) == "HTTP/" &&
     18          s.substr(s.size() - 2) == "\r\n";
     19 }
     20 
     21 }  // namespace
     22 
     23 REGISTER_TEST_CASE(TCPSocket);
     24 
     25 TestTCPSocket::TestTCPSocket(TestingInstance* instance) : TestCase(instance) {
     26 }
     27 
     28 bool TestTCPSocket::Init() {
     29   if (!pp::TCPSocket::IsAvailable())
     30     return false;
     31 
     32   // We need something to connect to, so we connect to the HTTP server whence we
     33   // came. Grab the host and port.
     34   if (!EnsureRunningOverHTTP())
     35     return false;
     36 
     37   std::string host;
     38   uint16_t port = 0;
     39   if (!GetLocalHostPort(instance_->pp_instance(), &host, &port))
     40     return false;
     41 
     42   if (!ResolveHost(instance_->pp_instance(), host, port, &addr_))
     43     return false;
     44 
     45   return true;
     46 }
     47 
     48 void TestTCPSocket::RunTests(const std::string& filter) {
     49   RUN_CALLBACK_TEST(TestTCPSocket, Connect, filter);
     50   RUN_CALLBACK_TEST(TestTCPSocket, ReadWrite, filter);
     51   RUN_CALLBACK_TEST(TestTCPSocket, SetOption, filter);
     52 }
     53 
     54 std::string TestTCPSocket::TestConnect() {
     55   pp::TCPSocket socket(instance_);
     56   TestCompletionCallback cb(instance_->pp_instance(), callback_type());
     57 
     58   cb.WaitForResult(socket.Connect(addr_, cb.GetCallback()));
     59   CHECK_CALLBACK_BEHAVIOR(cb);
     60   ASSERT_EQ(PP_OK, cb.result());
     61 
     62   pp::NetAddress local_addr, remote_addr;
     63   local_addr = socket.GetLocalAddress();
     64   remote_addr = socket.GetRemoteAddress();
     65 
     66   ASSERT_NE(0, local_addr.pp_resource());
     67   ASSERT_NE(0, remote_addr.pp_resource());
     68   ASSERT_TRUE(EqualNetAddress(addr_, remote_addr));
     69 
     70   socket.Close();
     71 
     72   PASS();
     73 }
     74 
     75 std::string TestTCPSocket::TestReadWrite() {
     76   pp::TCPSocket socket(instance_);
     77   TestCompletionCallback cb(instance_->pp_instance(), callback_type());
     78 
     79   cb.WaitForResult(socket.Connect(addr_, cb.GetCallback()));
     80   CHECK_CALLBACK_BEHAVIOR(cb);
     81   ASSERT_EQ(PP_OK, cb.result());
     82 
     83   ASSERT_EQ(PP_OK, WriteStringToSocket(&socket, "GET / HTTP/1.0\r\n\r\n"));
     84 
     85   // Read up to the first \n and check that it looks like valid HTTP response.
     86   std::string s;
     87   ASSERT_EQ(PP_OK, ReadFirstLineFromSocket(&socket, &s));
     88   ASSERT_TRUE(ValidateHttpResponse(s));
     89 
     90   PASS();
     91 }
     92 
     93 std::string TestTCPSocket::TestSetOption() {
     94   pp::TCPSocket socket(instance_);
     95   TestCompletionCallback cb_1(instance_->pp_instance(), callback_type());
     96   TestCompletionCallback cb_2(instance_->pp_instance(), callback_type());
     97   TestCompletionCallback cb_3(instance_->pp_instance(), callback_type());
     98 
     99   // These options cannot be set before the socket is connected.
    100   int32_t result_1 = socket.SetOption(PP_TCPSOCKET_OPTION_NO_DELAY,
    101                                       true, cb_1.GetCallback());
    102   int32_t result_2 = socket.SetOption(PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE,
    103                                       256, cb_2.GetCallback());
    104   int32_t result_3 = socket.SetOption(PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE,
    105                                       512, cb_3.GetCallback());
    106 
    107   cb_1.WaitForResult(result_1);
    108   CHECK_CALLBACK_BEHAVIOR(cb_1);
    109   ASSERT_EQ(PP_ERROR_FAILED, cb_1.result());
    110 
    111   cb_2.WaitForResult(result_2);
    112   CHECK_CALLBACK_BEHAVIOR(cb_2);
    113   ASSERT_EQ(PP_ERROR_FAILED, cb_2.result());
    114 
    115   cb_3.WaitForResult(result_3);
    116   CHECK_CALLBACK_BEHAVIOR(cb_3);
    117   ASSERT_EQ(PP_ERROR_FAILED, cb_3.result());
    118 
    119   cb_1.WaitForResult(socket.Connect(addr_, cb_1.GetCallback()));
    120   CHECK_CALLBACK_BEHAVIOR(cb_1);
    121   ASSERT_EQ(PP_OK, cb_1.result());
    122 
    123   result_1 = socket.SetOption(PP_TCPSOCKET_OPTION_NO_DELAY,
    124                               false, cb_1.GetCallback());
    125   result_2 = socket.SetOption(PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE,
    126                               512, cb_2.GetCallback());
    127   result_3 = socket.SetOption(PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE,
    128                               1024, cb_3.GetCallback());
    129 
    130   cb_1.WaitForResult(result_1);
    131   CHECK_CALLBACK_BEHAVIOR(cb_1);
    132   ASSERT_EQ(PP_OK, cb_1.result());
    133 
    134   cb_2.WaitForResult(result_2);
    135   CHECK_CALLBACK_BEHAVIOR(cb_2);
    136   ASSERT_EQ(PP_OK, cb_2.result());
    137 
    138   cb_3.WaitForResult(result_3);
    139   CHECK_CALLBACK_BEHAVIOR(cb_3);
    140   ASSERT_EQ(PP_OK, cb_3.result());
    141 
    142   PASS();
    143 }
    144 
    145 int32_t TestTCPSocket::ReadFirstLineFromSocket(pp::TCPSocket* socket,
    146                                                std::string* s) {
    147   char buffer[1000];
    148 
    149   s->clear();
    150   // Make sure we don't just hang if |Read()| spews.
    151   while (s->size() < 10000) {
    152     TestCompletionCallback cb(instance_->pp_instance(), callback_type());
    153     int32_t rv = socket->Read(buffer, sizeof(buffer), cb.GetCallback());
    154     if (callback_type() == PP_REQUIRED && rv != PP_OK_COMPLETIONPENDING)
    155       return PP_ERROR_FAILED;
    156     cb.WaitForResult(rv);
    157     if (cb.result() < 0)
    158       return cb.result();
    159     if (cb.result() == 0)
    160       return PP_ERROR_FAILED;  // Didn't get a \n-terminated line.
    161     s->reserve(s->size() + cb.result());
    162     for (int32_t i = 0; i < cb.result(); i++) {
    163       s->push_back(buffer[i]);
    164       if (buffer[i] == '\n')
    165         return PP_OK;
    166     }
    167   }
    168   return PP_ERROR_FAILED;
    169 }
    170 
    171 int32_t TestTCPSocket::WriteStringToSocket(pp::TCPSocket* socket,
    172                                            const std::string& s) {
    173   const char* buffer = s.data();
    174   size_t written = 0;
    175   while (written < s.size()) {
    176     TestCompletionCallback cb(instance_->pp_instance(), callback_type());
    177     int32_t rv = socket->Write(buffer + written, s.size() - written,
    178                                cb.GetCallback());
    179     if (callback_type() == PP_REQUIRED && rv != PP_OK_COMPLETIONPENDING)
    180       return PP_ERROR_FAILED;
    181     cb.WaitForResult(rv);
    182     if (cb.result() < 0)
    183       return cb.result();
    184     if (cb.result() == 0)
    185       return PP_ERROR_FAILED;
    186     written += cb.result();
    187   }
    188   if (written != s.size())
    189     return PP_ERROR_FAILED;
    190   return PP_OK;
    191 }
    192