1// Copyright 2009 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28#include "v8.h" 29#include "platform.h" 30#include "cctest.h" 31 32 33using namespace ::v8::internal; 34 35 36class SocketListenerThread : public Thread { 37 public: 38 SocketListenerThread(int port, int data_size) 39 : Thread("SocketListenerThread"), 40 port_(port), 41 data_size_(data_size), 42 server_(NULL), 43 client_(NULL), 44 listening_(OS::CreateSemaphore(0)) { 45 data_ = new char[data_size_]; 46 } 47 ~SocketListenerThread() { 48 // Close both sockets. 49 delete client_; 50 delete server_; 51 delete listening_; 52 delete[] data_; 53 } 54 55 void Run(); 56 void WaitForListening() { listening_->Wait(); } 57 char* data() { return data_; } 58 59 private: 60 int port_; 61 char* data_; 62 int data_size_; 63 Socket* server_; // Server socket used for bind/accept. 64 Socket* client_; // Single client connection used by the test. 65 Semaphore* listening_; // Signalled when the server socket is in listen mode. 66}; 67 68 69void SocketListenerThread::Run() { 70 bool ok; 71 72 // Create the server socket and bind it to the requested port. 73 server_ = OS::CreateSocket(); 74 server_->SetReuseAddress(true); 75 CHECK(server_ != NULL); 76 ok = server_->Bind(port_); 77 CHECK(ok); 78 79 // Listen for new connections. 80 ok = server_->Listen(1); 81 CHECK(ok); 82 listening_->Signal(); 83 84 // Accept a connection. 85 client_ = server_->Accept(); 86 CHECK(client_ != NULL); 87 88 // Read the expected niumber of bytes of data. 89 int bytes_read = 0; 90 while (bytes_read < data_size_) { 91 bytes_read += client_->Receive(data_ + bytes_read, data_size_ - bytes_read); 92 } 93} 94 95 96static bool SendAll(Socket* socket, const char* data, int len) { 97 int sent_len = 0; 98 while (sent_len < len) { 99 int status = socket->Send(data, len); 100 if (status <= 0) { 101 return false; 102 } 103 sent_len += status; 104 } 105 return true; 106} 107 108 109static void SendAndReceive(int port, char *data, int len) { 110 static const char* kLocalhost = "localhost"; 111 112 bool ok; 113 114 // Make a string with the port number. 115 const int kPortBuferLen = 6; 116 char port_str[kPortBuferLen]; 117 OS::SNPrintF(Vector<char>(port_str, kPortBuferLen), "%d", port); 118 119 // Create a socket listener. 120 SocketListenerThread* listener = new SocketListenerThread(port, len); 121 listener->Start(); 122 listener->WaitForListening(); 123 124 // Connect and write some data. 125 Socket* client = OS::CreateSocket(); 126 CHECK(client != NULL); 127 ok = client->Connect(kLocalhost, port_str); 128 CHECK(ok); 129 130 // Send all the data. 131 ok = SendAll(client, data, len); 132 CHECK(ok); 133 134 // Wait until data is received. 135 listener->Join(); 136 137 // Check that data received is the same as data send. 138 for (int i = 0; i < len; i++) { 139 CHECK(data[i] == listener->data()[i]); 140 } 141 142 // Close the client before the listener to avoid TIME_WAIT issues. 143 client->Shutdown(); 144 delete client; 145 delete listener; 146} 147 148 149TEST(Socket) { 150 // Make sure this port is not used by other tests to allow tests to run in 151 // parallel. 152 static const int kPort = 5859 + FlagDependentPortOffset(); 153 154 bool ok; 155 156 // Initialize socket support. 157 ok = Socket::SetUp(); 158 CHECK(ok); 159 160 // Send and receive some data. 161 static const int kBufferSizeSmall = 20; 162 char small_data[kBufferSizeSmall + 1] = "1234567890abcdefghij"; 163 SendAndReceive(kPort, small_data, kBufferSizeSmall); 164 165 // Send and receive some more data. 166 static const int kBufferSizeMedium = 10000; 167 char* medium_data = new char[kBufferSizeMedium]; 168 for (int i = 0; i < kBufferSizeMedium; i++) { 169 medium_data[i] = i % 256; 170 } 171 SendAndReceive(kPort, medium_data, kBufferSizeMedium); 172 delete[] medium_data; 173 174 // Send and receive even more data. 175 static const int kBufferSizeLarge = 1000000; 176 char* large_data = new char[kBufferSizeLarge]; 177 for (int i = 0; i < kBufferSizeLarge; i++) { 178 large_data[i] = i % 256; 179 } 180 SendAndReceive(kPort, large_data, kBufferSizeLarge); 181 delete[] large_data; 182} 183 184 185TEST(HToNNToH) { 186 uint16_t x = 1234; 187 CHECK_EQ(x, Socket::NToH(Socket::HToN(x))); 188 189 uint32_t y = 12345678; 190 CHECK(y == Socket::NToH(Socket::HToN(y))); 191} 192