Home | History | Annotate | Download | only in cctest
      1 // Copyright 2009 the V8 project authors. All rights reserved.
      2 
      3 #include "v8.h"
      4 #include "platform.h"
      5 #include "cctest.h"
      6 
      7 
      8 using namespace ::v8::internal;
      9 
     10 
     11 class SocketListenerThread : public Thread {
     12  public:
     13   explicit SocketListenerThread(Isolate* isolate, int port, int data_size)
     14       : Thread(isolate, "SocketListenerThread"),
     15         port_(port),
     16         data_size_(data_size),
     17         server_(NULL),
     18         client_(NULL),
     19         listening_(OS::CreateSemaphore(0)) {
     20     data_ = new char[data_size_];
     21   }
     22   ~SocketListenerThread() {
     23     // Close both sockets.
     24     delete client_;
     25     delete server_;
     26     delete listening_;
     27     delete[] data_;
     28   }
     29 
     30   void Run();
     31   void WaitForListening() { listening_->Wait(); }
     32   char* data() { return data_; }
     33 
     34  private:
     35   int port_;
     36   char* data_;
     37   int data_size_;
     38   Socket* server_;  // Server socket used for bind/accept.
     39   Socket* client_;  // Single client connection used by the test.
     40   Semaphore* listening_;  // Signalled when the server socket is in listen mode.
     41 };
     42 
     43 
     44 void SocketListenerThread::Run() {
     45   bool ok;
     46 
     47   // Create the server socket and bind it to the requested port.
     48   server_ = OS::CreateSocket();
     49   server_->SetReuseAddress(true);
     50   CHECK(server_ != NULL);
     51   ok = server_->Bind(port_);
     52   CHECK(ok);
     53 
     54   // Listen for new connections.
     55   ok = server_->Listen(1);
     56   CHECK(ok);
     57   listening_->Signal();
     58 
     59   // Accept a connection.
     60   client_ = server_->Accept();
     61   CHECK(client_ != NULL);
     62 
     63   // Read the expected niumber of bytes of data.
     64   int bytes_read = 0;
     65   while (bytes_read < data_size_) {
     66     bytes_read += client_->Receive(data_ + bytes_read, data_size_ - bytes_read);
     67   }
     68 }
     69 
     70 
     71 static bool SendAll(Socket* socket, const char* data, int len) {
     72   int sent_len = 0;
     73   while (sent_len < len) {
     74     int status = socket->Send(data, len);
     75     if (status <= 0) {
     76       return false;
     77     }
     78     sent_len += status;
     79   }
     80   return true;
     81 }
     82 
     83 
     84 static void SendAndReceive(int port, char *data, int len) {
     85   static const char* kLocalhost = "localhost";
     86 
     87   bool ok;
     88 
     89   // Make a string with the port number.
     90   const int kPortBuferLen = 6;
     91   char port_str[kPortBuferLen];
     92   OS::SNPrintF(Vector<char>(port_str, kPortBuferLen), "%d", port);
     93 
     94   // Create a socket listener.
     95   SocketListenerThread* listener = new SocketListenerThread(Isolate::Current(),
     96       port, len);
     97   listener->Start();
     98   listener->WaitForListening();
     99 
    100   // Connect and write some data.
    101   Socket* client = OS::CreateSocket();
    102   CHECK(client != NULL);
    103   ok = client->Connect(kLocalhost, port_str);
    104   CHECK(ok);
    105 
    106   // Send all the data.
    107   ok = SendAll(client, data, len);
    108   CHECK(ok);
    109 
    110   // Wait until data is received.
    111   listener->Join();
    112 
    113   // Check that data received is the same as data send.
    114   for (int i = 0; i < len; i++) {
    115     CHECK(data[i] == listener->data()[i]);
    116   }
    117 
    118   // Close the client before the listener to avoid TIME_WAIT issues.
    119   client->Shutdown();
    120   delete client;
    121   delete listener;
    122 }
    123 
    124 
    125 TEST(Socket) {
    126   // Make sure this port is not used by other tests to allow tests to run in
    127   // parallel.
    128   static const int kPort = 5859;
    129 
    130   bool ok;
    131 
    132   // Initialize socket support.
    133   ok = Socket::Setup();
    134   CHECK(ok);
    135 
    136   // Send and receive some data.
    137   static const int kBufferSizeSmall = 20;
    138   char small_data[kBufferSizeSmall + 1] = "1234567890abcdefghij";
    139   SendAndReceive(kPort, small_data, kBufferSizeSmall);
    140 
    141   // Send and receive some more data.
    142   static const int kBufferSizeMedium = 10000;
    143   char* medium_data = new char[kBufferSizeMedium];
    144   for (int i = 0; i < kBufferSizeMedium; i++) {
    145     medium_data[i] = i % 256;
    146   }
    147   SendAndReceive(kPort, medium_data, kBufferSizeMedium);
    148   delete[] medium_data;
    149 
    150   // Send and receive even more data.
    151   static const int kBufferSizeLarge = 1000000;
    152   char* large_data = new char[kBufferSizeLarge];
    153   for (int i = 0; i < kBufferSizeLarge; i++) {
    154     large_data[i] = i % 256;
    155   }
    156   SendAndReceive(kPort, large_data, kBufferSizeLarge);
    157   delete[] large_data;
    158 }
    159 
    160 
    161 TEST(HToNNToH) {
    162   uint16_t x = 1234;
    163   CHECK_EQ(x, Socket::NToH(Socket::HToN(x)));
    164 
    165   uint32_t y = 12345678;
    166   CHECK(y == Socket::NToH(Socket::HToN(y)));
    167 }
    168