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