summaryrefslogtreecommitdiff
path: root/deps/v8/test/cctest/test-socket.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test/cctest/test-socket.cc')
-rw-r--r--deps/v8/test/cctest/test-socket.cc176
1 files changed, 176 insertions, 0 deletions
diff --git a/deps/v8/test/cctest/test-socket.cc b/deps/v8/test/cctest/test-socket.cc
new file mode 100644
index 000000000..47d8b1783
--- /dev/null
+++ b/deps/v8/test/cctest/test-socket.cc
@@ -0,0 +1,176 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+#include "platform.h"
+#include "platform/socket.h"
+#include "cctest.h"
+
+
+using namespace ::v8::internal;
+
+
+class SocketListenerThread : public Thread {
+ public:
+ SocketListenerThread(int port, int data_size)
+ : Thread("SocketListenerThread"),
+ port_(port),
+ data_size_(data_size),
+ server_(NULL),
+ client_(NULL),
+ listening_(0) {
+ data_ = new char[data_size_];
+ }
+ ~SocketListenerThread() {
+ // Close both sockets.
+ delete client_;
+ delete server_;
+ delete[] data_;
+ }
+
+ void Run();
+ void WaitForListening() { listening_.Wait(); }
+ char* data() { return data_; }
+
+ private:
+ int port_;
+ char* data_;
+ int data_size_;
+ Socket* server_; // Server socket used for bind/accept.
+ Socket* client_; // Single client connection used by the test.
+ Semaphore listening_; // Signalled when the server socket is in listen mode.
+};
+
+
+void SocketListenerThread::Run() {
+ bool ok;
+
+ // Create the server socket and bind it to the requested port.
+ server_ = new Socket;
+ server_->SetReuseAddress(true);
+ CHECK(server_ != NULL);
+ ok = server_->Bind(port_);
+ CHECK(ok);
+
+ // Listen for new connections.
+ ok = server_->Listen(1);
+ CHECK(ok);
+ listening_.Signal();
+
+ // Accept a connection.
+ client_ = server_->Accept();
+ CHECK(client_ != NULL);
+
+ // Read the expected niumber of bytes of data.
+ int bytes_read = 0;
+ while (bytes_read < data_size_) {
+ bytes_read += client_->Receive(data_ + bytes_read, data_size_ - bytes_read);
+ }
+}
+
+
+static bool SendAll(Socket* socket, const char* data, int len) {
+ int sent_len = 0;
+ while (sent_len < len) {
+ int status = socket->Send(data, len);
+ if (status <= 0) {
+ return false;
+ }
+ sent_len += status;
+ }
+ return true;
+}
+
+
+static void SendAndReceive(int port, char *data, int len) {
+ static const char* kLocalhost = "localhost";
+
+ bool ok;
+
+ // Make a string with the port number.
+ const int kPortBuferLen = 6;
+ char port_str[kPortBuferLen];
+ OS::SNPrintF(Vector<char>(port_str, kPortBuferLen), "%d", port);
+
+ // Create a socket listener.
+ SocketListenerThread* listener = new SocketListenerThread(port, len);
+ listener->Start();
+ listener->WaitForListening();
+
+ // Connect and write some data.
+ Socket* client = new Socket;
+ CHECK(client != NULL);
+ ok = client->Connect(kLocalhost, port_str);
+ CHECK(ok);
+
+ // Send all the data.
+ ok = SendAll(client, data, len);
+ CHECK(ok);
+
+ // Wait until data is received.
+ listener->Join();
+
+ // Check that data received is the same as data send.
+ for (int i = 0; i < len; i++) {
+ CHECK(data[i] == listener->data()[i]);
+ }
+
+ // Close the client before the listener to avoid TIME_WAIT issues.
+ client->Shutdown();
+ delete client;
+ delete listener;
+}
+
+
+TEST(Socket) {
+ // Make sure this port is not used by other tests to allow tests to run in
+ // parallel.
+ static const int kPort = 5859 + FlagDependentPortOffset();
+
+ // Send and receive some data.
+ static const int kBufferSizeSmall = 20;
+ char small_data[kBufferSizeSmall + 1] = "1234567890abcdefghij";
+ SendAndReceive(kPort, small_data, kBufferSizeSmall);
+
+ // Send and receive some more data.
+ static const int kBufferSizeMedium = 10000;
+ char* medium_data = new char[kBufferSizeMedium];
+ for (int i = 0; i < kBufferSizeMedium; i++) {
+ medium_data[i] = i % 256;
+ }
+ SendAndReceive(kPort, medium_data, kBufferSizeMedium);
+ delete[] medium_data;
+
+ // Send and receive even more data.
+ static const int kBufferSizeLarge = 1000000;
+ char* large_data = new char[kBufferSizeLarge];
+ for (int i = 0; i < kBufferSizeLarge; i++) {
+ large_data[i] = i % 256;
+ }
+ SendAndReceive(kPort, large_data, kBufferSizeLarge);
+ delete[] large_data;
+}