summaryrefslogtreecommitdiff
path: root/deps/v8/test/cctest/test-sockets.cc
blob: ad7354002ff2bd43863291030e1a3b90e0d37899 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// Copyright 2009 the V8 project authors. All rights reserved.

#include "v8.h"
#include "platform.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_(OS::CreateSemaphore(0)) {
    data_ = new char[data_size_];
  }
  ~SocketListenerThread() {
    // Close both sockets.
    delete client_;
    delete server_;
    delete listening_;
    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_ = OS::CreateSocket();
  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 = OS::CreateSocket();
  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;

  bool ok;

  // Initialize socket support.
  ok = Socket::SetUp();
  CHECK(ok);

  // 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;
}


TEST(HToNNToH) {
  uint16_t x = 1234;
  CHECK_EQ(x, Socket::NToH(Socket::HToN(x)));

  uint32_t y = 12345678;
  CHECK(y == Socket::NToH(Socket::HToN(y)));
}