OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2010 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 // This test suite uses SSLClientSocket to test the implementation of | |
6 // SSLServerSocket. In order to establish connections between the sockets | |
7 // we need two additional classes: | |
8 // 1. FakeClientSocket | |
9 // Connects SSL socket to FakeDataChannel. This class is just a stub. | |
10 // | |
11 // 2. FakeDataChannel | |
12 // Implements the actual exchange of data between two FakeClientSockets. | |
13 // | |
14 // Implementations of these two classes are included in this file. | |
15 | |
16 #include <queue> | |
17 | |
18 #include "base/crypto/rsa_private_key.h" | |
19 #include "net/base/address_list.h" | |
20 #include "net/base/host_port_pair.h" | |
21 #include "net/base/io_buffer.h" | |
22 #include "net/base/net_errors.h" | |
23 #include "net/base/net_log.h" | |
24 #include "net/base/ssl_config_service.h" | |
25 #include "net/base/x509_certificate.h" | |
26 #include "net/socket/client_socket.h" | |
27 #include "net/socket/client_socket_factory.h" | |
28 #include "net/socket/socket_test_util.h" | |
29 #include "net/socket/ssl_client_socket.h" | |
30 #include "net/socket/ssl_server_socket.h" | |
wtc
2010/12/17 00:16:26
Nit: list "net/socket/ssl_server_socket.h" first.
Alpha Left Google
2010/12/17 08:30:43
Done.
| |
31 #include "testing/gtest/include/gtest/gtest.h" | |
32 #include "testing/platform_test.h" | |
33 | |
34 namespace net { | |
35 | |
36 namespace { | |
37 | |
38 class FakeDataChannel { | |
39 public: | |
40 FakeDataChannel() : read_callback_(NULL), read_buf_len_(0) { | |
41 } | |
42 | |
43 virtual int Read(IOBuffer* buf, int buf_len, | |
44 CompletionCallback* callback) { | |
45 if (data_.empty()) { | |
46 read_callback_ = callback; | |
47 read_buf_ = buf; | |
48 read_buf_len_ = buf_len; | |
49 return net::ERR_IO_PENDING; | |
50 } | |
51 return PropogateData(buf, buf_len); | |
52 } | |
53 | |
54 virtual int Write(IOBuffer* buf, int buf_len, | |
55 CompletionCallback* callback) { | |
56 data_.push(new net::DrainableIOBuffer(buf, buf_len)); | |
57 DoReadCallback(); | |
58 return buf_len; | |
59 } | |
60 | |
61 private: | |
62 void DoReadCallback() { | |
63 if (!read_callback_) | |
64 return; | |
65 | |
66 int copied = PropogateData(read_buf_, read_buf_len_); | |
67 net::CompletionCallback* callback = read_callback_; | |
68 read_callback_ = NULL; | |
69 read_buf_ = NULL; | |
70 read_buf_len_ = 0; | |
71 callback->Run(copied); | |
72 } | |
73 | |
74 int PropogateData(scoped_refptr<net::IOBuffer> read_buf, int read_buf_len) { | |
75 scoped_refptr<net::DrainableIOBuffer> buf = data_.front(); | |
76 int copied = std::min(buf->BytesRemaining(), read_buf_len); | |
77 memcpy(read_buf->data(), buf->data(), copied); | |
78 buf->DidConsume(copied); | |
79 | |
80 if (!buf->BytesRemaining()) | |
81 data_.pop(); | |
82 return copied; | |
83 } | |
84 | |
85 net::CompletionCallback* read_callback_; | |
86 scoped_refptr<net::IOBuffer> read_buf_; | |
87 int read_buf_len_; | |
88 | |
89 std::queue<scoped_refptr<net::DrainableIOBuffer> > data_; | |
90 | |
91 DISALLOW_COPY_AND_ASSIGN(FakeDataChannel); | |
92 }; | |
93 | |
94 class FakeClientSocket : public ClientSocket { | |
95 public: | |
96 FakeClientSocket(FakeDataChannel* incoming_channel, | |
97 FakeDataChannel* outgoing_channel) | |
98 : incoming_(incoming_channel), | |
99 outgoing_(outgoing_channel) { | |
100 } | |
101 | |
102 virtual ~FakeClientSocket() { | |
103 | |
104 } | |
105 | |
106 virtual int Read(IOBuffer* buf, int buf_len, | |
107 CompletionCallback* callback) { | |
108 return incoming_->Read(buf, buf_len, callback); | |
109 } | |
110 | |
111 virtual int Write(IOBuffer* buf, int buf_len, | |
112 CompletionCallback* callback) { | |
113 return outgoing_->Write(buf, buf_len, callback); | |
114 } | |
115 | |
116 virtual bool SetReceiveBufferSize(int32 size) { | |
117 return true; | |
118 } | |
119 | |
120 virtual bool SetSendBufferSize(int32 size) { | |
121 return true; | |
122 } | |
123 | |
124 virtual int Connect(CompletionCallback* callback) { | |
125 return net::OK; | |
126 } | |
127 | |
128 virtual void Disconnect() {} | |
129 | |
130 virtual bool IsConnected() const { | |
131 return true; | |
132 } | |
133 | |
134 virtual bool IsConnectedAndIdle() const { | |
135 return false; | |
wtc
2010/12/17 00:16:26
This probably should return true.
Alpha Left Google
2010/12/17 08:30:43
Done.
| |
136 } | |
137 | |
138 virtual int GetPeerAddress(AddressList* address) const { | |
139 net::IPAddressNumber ip_address(4); | |
140 *address = net::AddressList(ip_address, 0, false); | |
141 return net::OK; | |
142 } | |
143 | |
144 virtual const BoundNetLog& NetLog() const { | |
145 return net_log_; | |
146 } | |
147 | |
148 virtual void SetSubresourceSpeculation() {} | |
149 virtual void SetOmniboxSpeculation() {} | |
150 | |
151 virtual bool WasEverUsed() const { | |
152 return true; | |
153 } | |
154 | |
155 virtual bool UsingTCPFastOpen() const { | |
156 return false; | |
157 } | |
158 | |
159 private: | |
160 net::BoundNetLog net_log_; | |
161 FakeDataChannel* incoming_; | |
162 FakeDataChannel* outgoing_; | |
163 | |
164 DISALLOW_COPY_AND_ASSIGN(FakeClientSocket); | |
165 }; | |
166 | |
167 } // namespace | |
168 | |
169 // Verify the correctness of the test helper classes first. | |
170 TEST(FakeClientSocketTest, DataTransfer) { | |
171 // Establish connections between two sockets. | |
wtc
2010/12/17 00:16:26
Nit: connections => channels
Alpha Left Google
2010/12/17 08:30:43
Done.
| |
172 FakeDataChannel channel_1; | |
173 FakeDataChannel channel_2; | |
174 FakeClientSocket client(&channel_1, &channel_2); | |
175 FakeClientSocket server(&channel_2, &channel_1); | |
176 | |
177 const char kTestData[] = "testing123"; | |
178 const int kTestDataSize = strlen(kTestData); | |
179 const int kReadBufSize = 1024; | |
180 scoped_refptr<net::IOBuffer> write_buf = new net::StringIOBuffer(kTestData); | |
181 scoped_refptr<net::IOBuffer> read_buf = new net::IOBuffer(kReadBufSize); | |
182 | |
183 // Write then read. | |
184 EXPECT_EQ(kTestDataSize, server.Write(write_buf, kTestDataSize, NULL)); | |
185 EXPECT_EQ(kTestDataSize, client.Read(read_buf, kReadBufSize, NULL)); | |
186 EXPECT_EQ(0, memcmp(kTestData, read_buf->data(), kTestDataSize)); | |
187 | |
188 // Read then write. | |
189 TestCompletionCallback callback; | |
190 EXPECT_EQ(net::ERR_IO_PENDING, | |
191 server.Read(read_buf, kReadBufSize, &callback)); | |
192 EXPECT_EQ(kTestDataSize, client.Write(write_buf, kTestDataSize, NULL)); | |
193 EXPECT_EQ(0, memcmp(kTestData, read_buf->data(), kTestDataSize)); | |
194 EXPECT_EQ(kTestDataSize, callback.WaitForResult()); | |
wtc
2010/12/17 00:16:26
BUG: these two statements should be reversed. You
Alpha Left Google
2010/12/17 08:30:43
nice catch, done.
| |
195 } | |
196 | |
197 class SSLServerSocketTest : public PlatformTest { | |
198 public: | |
199 SSLServerSocketTest() | |
200 : socket_factory_(net::ClientSocketFactory::GetDefaultFactory()) { | |
201 } | |
202 | |
203 protected: | |
204 void Initialize() { | |
205 net::ClientSocket* fake_client_socket = new FakeClientSocket(&channel_1_, | |
206 &channel_2_); | |
207 net::ClientSocket* fake_server_socket = new FakeClientSocket(&channel_2_, | |
wtc
2010/12/17 00:16:26
It is confusing to see fake_server_socket is a Cli
Alpha Left Google
2010/12/17 08:30:43
Renamed FakeClientSocket to FakeSocket. And instea
| |
208 &channel_1_); | |
209 | |
210 // Generate private key and certificate. | |
211 scoped_ptr<base::RSAPrivateKey> private_key( | |
212 base::RSAPrivateKey::Create(1024)); | |
213 | |
214 std::string subject = "CN=net-unittest"; | |
215 scoped_refptr<net::X509Certificate> cert = | |
216 net::X509Certificate::CreateSelfSigned( | |
217 private_key.get(), subject, 0, base::TimeDelta::FromDays(1)); | |
218 | |
219 net::SSLConfig ssl_config; | |
220 ssl_config.false_start_enabled = false; | |
221 ssl_config.snap_start_enabled = false; | |
222 ssl_config.ssl3_enabled = true; | |
223 ssl_config.tls1_enabled = true; | |
224 ssl_config.no_cache_enabled = true; | |
225 | |
226 // Certificate provided by the host doesn't need authority. | |
227 net::SSLConfig::CertAndStatus cert_and_status; | |
228 cert_and_status.cert_status = net::ERR_CERT_AUTHORITY_INVALID; | |
229 cert_and_status.cert = cert; | |
230 ssl_config.allowed_bad_certs.push_back(cert_and_status); | |
231 | |
232 net::HostPortPair host_and_pair("net-unittest", 0); | |
233 client_socket_.reset( | |
234 net::ClientSocketFactory::GetDefaultFactory()->CreateSSLClientSocket( | |
wtc
2010/12/17 00:16:26
You should replace net::ClientSocketFactory::GetDe
Alpha Left Google
2010/12/17 08:30:43
Done.
| |
235 fake_client_socket, host_and_pair, ssl_config, NULL)); | |
236 server_socket_.reset(net::CreateSSLServerSocket(fake_server_socket, | |
237 cert, private_key.get())); | |
238 } | |
239 | |
240 FakeDataChannel channel_1_; | |
241 FakeDataChannel channel_2_; | |
242 scoped_ptr<net::SSLClientSocket> client_socket_; | |
243 scoped_ptr<net::SSLServerSocket> server_socket_; | |
244 net::ClientSocketFactory* socket_factory_; | |
245 }; | |
246 | |
247 // SSLServerSocket is only implemented using NSS. | |
248 #if defined(USE_NSS) | |
249 TEST_F(SSLServerSocketTest, Initialize) { | |
wtc
2010/12/17 00:16:26
What's the purpose of this test? To check that In
Alpha Left Google
2010/12/17 08:30:43
To make sure setting up the sockets is successful.
| |
250 Initialize(); | |
251 } | |
252 | |
253 TEST_F(SSLServerSocketTest, Connect) { | |
wtc
2010/12/17 00:16:26
Nit: it may be better to name this test Handshake
Alpha Left Google
2010/12/17 08:30:43
Done.
| |
254 Initialize(); | |
255 | |
256 TestCompletionCallback connect_callback; | |
257 TestCompletionCallback accept_callback; | |
258 | |
259 int client_ret = client_socket_->Connect(&connect_callback); | |
260 EXPECT_TRUE(client_ret == net::OK || client_ret == net::ERR_IO_PENDING); | |
261 | |
262 int server_ret = server_socket_->Accept(&accept_callback); | |
263 EXPECT_TRUE(server_ret == net::OK || server_ret == net::ERR_IO_PENDING); | |
264 | |
265 if (client_ret == net::ERR_IO_PENDING) { | |
wtc
2010/12/17 00:16:26
Nit: in the 'net' module we usually omit curly bra
Alpha Left Google
2010/12/17 08:30:43
Yup, I tend to omit {} for a single line, but this
wtc
2010/12/17 16:38:32
Someone else also told me about this exception. D
Alpha Left Google
2010/12/17 20:09:57
Don't remember if this is in the Style Guide. But
| |
266 EXPECT_EQ(net::OK, connect_callback.WaitForResult()); | |
267 } | |
268 if (server_ret == net::ERR_IO_PENDING) { | |
269 EXPECT_EQ(net::OK, accept_callback.WaitForResult()); | |
270 } | |
271 } | |
272 | |
273 TEST_F(SSLServerSocketTest, DataTransfer) { | |
274 Initialize(); | |
275 | |
276 TestCompletionCallback connect_callback; | |
277 TestCompletionCallback accept_callback; | |
278 | |
279 // Establish connection. | |
280 int client_ret = client_socket_->Connect(&connect_callback); | |
281 EXPECT_TRUE(client_ret == net::OK || client_ret == net::ERR_IO_PENDING); | |
282 | |
283 int server_ret = server_socket_->Accept(&accept_callback); | |
284 EXPECT_TRUE(server_ret == net::OK || server_ret == net::ERR_IO_PENDING); | |
285 | |
286 if (client_ret == net::ERR_IO_PENDING) { | |
287 EXPECT_EQ(net::OK, connect_callback.WaitForResult()); | |
288 } | |
289 if (server_ret == net::ERR_IO_PENDING) { | |
290 EXPECT_EQ(net::OK, accept_callback.WaitForResult()); | |
291 } | |
292 | |
293 const char kTestData[] = "testing123"; | |
294 const int kTestDataSize = strlen(kTestData); | |
295 const int kReadBufSize = 1024; | |
296 scoped_refptr<net::IOBuffer> write_buf = new net::StringIOBuffer(kTestData); | |
297 scoped_refptr<net::IOBuffer> read_buf = new net::IOBuffer(kReadBufSize); | |
298 | |
299 // Write then read. | |
300 TestCompletionCallback write_callback; | |
301 TestCompletionCallback read_callback; | |
302 server_ret = server_socket_->Write(write_buf, kTestDataSize, &write_callback); | |
303 EXPECT_TRUE(server_ret > 0 || server_ret == net::ERR_IO_PENDING); | |
304 client_ret = client_socket_->Read(read_buf, kReadBufSize, &read_callback); | |
305 EXPECT_TRUE(client_ret > 0 || client_ret == net::ERR_IO_PENDING); | |
306 | |
307 if (server_ret == net::ERR_IO_PENDING) { | |
308 EXPECT_GT(write_callback.WaitForResult(), 0); | |
309 } | |
310 if (client_ret == net::ERR_IO_PENDING) { | |
311 EXPECT_GT(read_callback.WaitForResult(), 0); | |
312 } | |
313 EXPECT_EQ(0, memcmp(kTestData, read_buf->data(), kTestDataSize)); | |
314 | |
315 // Read then write. | |
wtc
2010/12/17 00:16:26
Since you reuse the read buffer for the "Read then
Alpha Left Google
2010/12/17 08:30:43
Done.
| |
316 server_ret = server_socket_->Read(read_buf, kReadBufSize, &read_callback); | |
317 EXPECT_TRUE(server_ret > 0 || server_ret == net::ERR_IO_PENDING); | |
318 client_ret = client_socket_->Write(write_buf, kTestDataSize, &write_callback); | |
319 EXPECT_TRUE(client_ret > 0 || client_ret == net::ERR_IO_PENDING); | |
320 | |
321 if (server_ret == net::ERR_IO_PENDING) { | |
322 EXPECT_GT(read_callback.WaitForResult(), 0); | |
323 } | |
324 if (client_ret == net::ERR_IO_PENDING) { | |
325 EXPECT_GT(write_callback.WaitForResult(), 0); | |
326 } | |
327 EXPECT_EQ(0, memcmp(kTestData, read_buf->data(), kTestDataSize)); | |
328 } | |
329 #endif | |
330 | |
331 } // namespace net | |
OLD | NEW |