- add sources.
[platform/framework/web/crosswalk.git] / src / net / socket / tcp_socket_unittest.cc
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/socket/tcp_socket.h"
6
7 #include <string.h>
8
9 #include <string>
10 #include <vector>
11
12 #include "base/memory/ref_counted.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "net/base/address_list.h"
15 #include "net/base/io_buffer.h"
16 #include "net/base/ip_endpoint.h"
17 #include "net/base/net_errors.h"
18 #include "net/base/test_completion_callback.h"
19 #include "net/socket/tcp_client_socket.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "testing/platform_test.h"
22
23 namespace net {
24
25 namespace {
26 const int kListenBacklog = 5;
27
28 class TCPSocketTest : public PlatformTest {
29  protected:
30   TCPSocketTest() : socket_(NULL, NetLog::Source()) {
31   }
32
33   void SetUpListenIPv4() {
34     IPEndPoint address;
35     ParseAddress("127.0.0.1", 0, &address);
36
37     ASSERT_EQ(OK, socket_.Open(ADDRESS_FAMILY_IPV4));
38     ASSERT_EQ(OK, socket_.Bind(address));
39     ASSERT_EQ(OK, socket_.Listen(kListenBacklog));
40     ASSERT_EQ(OK, socket_.GetLocalAddress(&local_address_));
41   }
42
43   void SetUpListenIPv6(bool* success) {
44     *success = false;
45     IPEndPoint address;
46     ParseAddress("::1", 0, &address);
47
48     if (socket_.Open(ADDRESS_FAMILY_IPV6) != OK ||
49         socket_.Bind(address) != OK ||
50         socket_.Listen(kListenBacklog) != OK) {
51       LOG(ERROR) << "Failed to listen on ::1 - probably because IPv6 is "
52           "disabled. Skipping the test";
53       return;
54     }
55     ASSERT_EQ(OK, socket_.GetLocalAddress(&local_address_));
56     *success = true;
57   }
58
59   void ParseAddress(const std::string& ip_str, int port, IPEndPoint* address) {
60     IPAddressNumber ip_number;
61     bool rv = ParseIPLiteralToNumber(ip_str, &ip_number);
62     if (!rv)
63       return;
64     *address = IPEndPoint(ip_number, port);
65   }
66
67   AddressList local_address_list() const {
68     return AddressList(local_address_);
69   }
70
71   TCPSocket socket_;
72   IPEndPoint local_address_;
73 };
74
75 // Test listening and accepting with a socket bound to an IPv4 address.
76 TEST_F(TCPSocketTest, Accept) {
77   ASSERT_NO_FATAL_FAILURE(SetUpListenIPv4());
78
79   TestCompletionCallback connect_callback;
80   // TODO(yzshen): Switch to use TCPSocket when it supports client socket
81   // operations.
82   TCPClientSocket connecting_socket(local_address_list(),
83                                     NULL, NetLog::Source());
84   connecting_socket.Connect(connect_callback.callback());
85
86   TestCompletionCallback accept_callback;
87   scoped_ptr<TCPSocket> accepted_socket;
88   IPEndPoint accepted_address;
89   int result = socket_.Accept(&accepted_socket, &accepted_address,
90                               accept_callback.callback());
91   if (result == ERR_IO_PENDING)
92     result = accept_callback.WaitForResult();
93   ASSERT_EQ(OK, result);
94
95   EXPECT_TRUE(accepted_socket.get());
96
97   // Both sockets should be on the loopback network interface.
98   EXPECT_EQ(accepted_address.address(), local_address_.address());
99
100   EXPECT_EQ(OK, connect_callback.WaitForResult());
101 }
102
103 // Test Accept() callback.
104 TEST_F(TCPSocketTest, AcceptAsync) {
105   ASSERT_NO_FATAL_FAILURE(SetUpListenIPv4());
106
107   TestCompletionCallback accept_callback;
108   scoped_ptr<TCPSocket> accepted_socket;
109   IPEndPoint accepted_address;
110   ASSERT_EQ(ERR_IO_PENDING,
111             socket_.Accept(&accepted_socket, &accepted_address,
112                            accept_callback.callback()));
113
114   TestCompletionCallback connect_callback;
115   TCPClientSocket connecting_socket(local_address_list(),
116                                     NULL, NetLog::Source());
117   connecting_socket.Connect(connect_callback.callback());
118
119   EXPECT_EQ(OK, connect_callback.WaitForResult());
120   EXPECT_EQ(OK, accept_callback.WaitForResult());
121
122   EXPECT_TRUE(accepted_socket.get());
123
124   // Both sockets should be on the loopback network interface.
125   EXPECT_EQ(accepted_address.address(), local_address_.address());
126 }
127
128 // Accept two connections simultaneously.
129 TEST_F(TCPSocketTest, Accept2Connections) {
130   ASSERT_NO_FATAL_FAILURE(SetUpListenIPv4());
131
132   TestCompletionCallback accept_callback;
133   scoped_ptr<TCPSocket> accepted_socket;
134   IPEndPoint accepted_address;
135
136   ASSERT_EQ(ERR_IO_PENDING,
137             socket_.Accept(&accepted_socket, &accepted_address,
138                            accept_callback.callback()));
139
140   TestCompletionCallback connect_callback;
141   TCPClientSocket connecting_socket(local_address_list(),
142                                     NULL, NetLog::Source());
143   connecting_socket.Connect(connect_callback.callback());
144
145   TestCompletionCallback connect_callback2;
146   TCPClientSocket connecting_socket2(local_address_list(),
147                                      NULL, NetLog::Source());
148   connecting_socket2.Connect(connect_callback2.callback());
149
150   EXPECT_EQ(OK, accept_callback.WaitForResult());
151
152   TestCompletionCallback accept_callback2;
153   scoped_ptr<TCPSocket> accepted_socket2;
154   IPEndPoint accepted_address2;
155
156   int result = socket_.Accept(&accepted_socket2, &accepted_address2,
157                               accept_callback2.callback());
158   if (result == ERR_IO_PENDING)
159     result = accept_callback2.WaitForResult();
160   ASSERT_EQ(OK, result);
161
162   EXPECT_EQ(OK, connect_callback.WaitForResult());
163   EXPECT_EQ(OK, connect_callback2.WaitForResult());
164
165   EXPECT_TRUE(accepted_socket.get());
166   EXPECT_TRUE(accepted_socket2.get());
167   EXPECT_NE(accepted_socket.get(), accepted_socket2.get());
168
169   EXPECT_EQ(accepted_address.address(), local_address_.address());
170   EXPECT_EQ(accepted_address2.address(), local_address_.address());
171 }
172
173 // Test listening and accepting with a socket bound to an IPv6 address.
174 TEST_F(TCPSocketTest, AcceptIPv6) {
175   bool initialized = false;
176   ASSERT_NO_FATAL_FAILURE(SetUpListenIPv6(&initialized));
177   if (!initialized)
178     return;
179
180   TestCompletionCallback connect_callback;
181   TCPClientSocket connecting_socket(local_address_list(),
182                                     NULL, NetLog::Source());
183   connecting_socket.Connect(connect_callback.callback());
184
185   TestCompletionCallback accept_callback;
186   scoped_ptr<TCPSocket> accepted_socket;
187   IPEndPoint accepted_address;
188   int result = socket_.Accept(&accepted_socket, &accepted_address,
189                               accept_callback.callback());
190   if (result == ERR_IO_PENDING)
191     result = accept_callback.WaitForResult();
192   ASSERT_EQ(OK, result);
193
194   EXPECT_TRUE(accepted_socket.get());
195
196   // Both sockets should be on the loopback network interface.
197   EXPECT_EQ(accepted_address.address(), local_address_.address());
198
199   EXPECT_EQ(OK, connect_callback.WaitForResult());
200 }
201
202 TEST_F(TCPSocketTest, ReadWrite) {
203   ASSERT_NO_FATAL_FAILURE(SetUpListenIPv4());
204
205   TestCompletionCallback connect_callback;
206   TCPSocket connecting_socket(NULL, NetLog::Source());
207   int result = connecting_socket.Open(ADDRESS_FAMILY_IPV4);
208   ASSERT_EQ(OK, result);
209   connecting_socket.Connect(local_address_, connect_callback.callback());
210
211   TestCompletionCallback accept_callback;
212   scoped_ptr<TCPSocket> accepted_socket;
213   IPEndPoint accepted_address;
214   result = socket_.Accept(&accepted_socket, &accepted_address,
215                           accept_callback.callback());
216   ASSERT_EQ(OK, accept_callback.GetResult(result));
217
218   ASSERT_TRUE(accepted_socket.get());
219
220   // Both sockets should be on the loopback network interface.
221   EXPECT_EQ(accepted_address.address(), local_address_.address());
222
223   EXPECT_EQ(OK, connect_callback.WaitForResult());
224
225   const std::string message("test message");
226   std::vector<char> buffer(message.size());
227
228   size_t bytes_written = 0;
229   while (bytes_written < message.size()) {
230     scoped_refptr<IOBufferWithSize> write_buffer(
231         new IOBufferWithSize(message.size() - bytes_written));
232     memmove(write_buffer->data(), message.data() + bytes_written,
233             message.size() - bytes_written);
234
235     TestCompletionCallback write_callback;
236     int write_result = accepted_socket->Write(
237         write_buffer.get(), write_buffer->size(), write_callback.callback());
238     write_result = write_callback.GetResult(write_result);
239     ASSERT_TRUE(write_result >= 0);
240     bytes_written += write_result;
241     ASSERT_TRUE(bytes_written <= message.size());
242   }
243
244   size_t bytes_read = 0;
245   while (bytes_read < message.size()) {
246     scoped_refptr<IOBufferWithSize> read_buffer(
247         new IOBufferWithSize(message.size() - bytes_read));
248     TestCompletionCallback read_callback;
249     int read_result = connecting_socket.Read(
250         read_buffer.get(), read_buffer->size(), read_callback.callback());
251     read_result = read_callback.GetResult(read_result);
252     ASSERT_TRUE(read_result >= 0);
253     ASSERT_TRUE(bytes_read + read_result <= message.size());
254     memmove(&buffer[bytes_read], read_buffer->data(), read_result);
255     bytes_read += read_result;
256   }
257
258   std::string received_message(buffer.begin(), buffer.end());
259   ASSERT_EQ(message, received_message);
260 }
261
262 }  // namespace
263 }  // namespace net