Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / jingle / glue / fake_ssl_client_socket_unittest.cc
blob0f8112700fa73627dfcbdbff96c2e3bb3204e745
1 // Copyright (c) 2012 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.
5 #include "jingle/glue/fake_ssl_client_socket.h"
7 #include <algorithm>
8 #include <vector>
10 #include "base/basictypes.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop.h"
14 #include "net/base/io_buffer.h"
15 #include "net/base/test_completion_callback.h"
16 #include "net/log/net_log.h"
17 #include "net/socket/socket_test_util.h"
18 #include "net/socket/stream_socket.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 namespace jingle_glue {
24 namespace {
26 using ::testing::Return;
27 using ::testing::ReturnRef;
29 // Used by RunUnsuccessfulHandshakeTestHelper. Represents where in
30 // the handshake step an error should be inserted.
31 enum HandshakeErrorLocation {
32 CONNECT_ERROR,
33 SEND_CLIENT_HELLO_ERROR,
34 VERIFY_SERVER_HELLO_ERROR,
37 // Private error codes appended to the net::Error set.
38 enum {
39 // An error representing a server hello that has been corrupted in
40 // transit.
41 ERR_MALFORMED_SERVER_HELLO = -15000,
44 // Used by PassThroughMethods test.
45 class MockClientSocket : public net::StreamSocket {
46 public:
47 virtual ~MockClientSocket() {}
49 MOCK_METHOD3(Read, int(net::IOBuffer*, int,
50 const net::CompletionCallback&));
51 MOCK_METHOD3(Write, int(net::IOBuffer*, int,
52 const net::CompletionCallback&));
53 MOCK_METHOD1(SetReceiveBufferSize, int(int32));
54 MOCK_METHOD1(SetSendBufferSize, int(int32));
55 MOCK_METHOD1(Connect, int(const net::CompletionCallback&));
56 MOCK_METHOD0(Disconnect, void());
57 MOCK_CONST_METHOD0(IsConnected, bool());
58 MOCK_CONST_METHOD0(IsConnectedAndIdle, bool());
59 MOCK_CONST_METHOD1(GetPeerAddress, int(net::IPEndPoint*));
60 MOCK_CONST_METHOD1(GetLocalAddress, int(net::IPEndPoint*));
61 MOCK_CONST_METHOD0(NetLog, const net::BoundNetLog&());
62 MOCK_METHOD0(SetSubresourceSpeculation, void());
63 MOCK_METHOD0(SetOmniboxSpeculation, void());
64 MOCK_CONST_METHOD0(WasEverUsed, bool());
65 MOCK_CONST_METHOD0(UsingTCPFastOpen, bool());
66 MOCK_CONST_METHOD0(NumBytesRead, int64());
67 MOCK_CONST_METHOD0(GetConnectTimeMicros, base::TimeDelta());
68 MOCK_CONST_METHOD0(WasNpnNegotiated, bool());
69 MOCK_CONST_METHOD0(GetNegotiatedProtocol, net::NextProto());
70 MOCK_METHOD1(GetSSLInfo, bool(net::SSLInfo*));
71 MOCK_CONST_METHOD1(GetConnectionAttempts, void(net::ConnectionAttempts*));
72 MOCK_METHOD0(ClearConnectionAttempts, void());
73 MOCK_METHOD1(AddConnectionAttempts, void(const net::ConnectionAttempts&));
76 // Break up |data| into a bunch of chunked MockReads/Writes and push
77 // them onto |ops|.
78 template <net::MockReadWriteType type>
79 void AddChunkedOps(base::StringPiece data, size_t chunk_size, net::IoMode mode,
80 std::vector<net::MockReadWrite<type> >* ops) {
81 DCHECK_GT(chunk_size, 0U);
82 size_t offset = 0;
83 while (offset < data.size()) {
84 size_t bounded_chunk_size = std::min(data.size() - offset, chunk_size);
85 ops->push_back(net::MockReadWrite<type>(mode, data.data() + offset,
86 bounded_chunk_size));
87 offset += bounded_chunk_size;
91 class FakeSSLClientSocketTest : public testing::Test {
92 protected:
93 FakeSSLClientSocketTest() {}
95 ~FakeSSLClientSocketTest() override {}
97 scoped_ptr<net::StreamSocket> MakeClientSocket() {
98 return mock_client_socket_factory_.CreateTransportClientSocket(
99 net::AddressList(), NULL, net::NetLog::Source());
102 void SetData(const net::MockConnect& mock_connect,
103 std::vector<net::MockRead>* reads,
104 std::vector<net::MockWrite>* writes) {
105 static_socket_data_provider_.reset(
106 new net::StaticSocketDataProvider(
107 reads->empty() ? NULL : &*reads->begin(), reads->size(),
108 writes->empty() ? NULL : &*writes->begin(), writes->size()));
109 static_socket_data_provider_->set_connect_data(mock_connect);
110 mock_client_socket_factory_.AddSocketDataProvider(
111 static_socket_data_provider_.get());
114 void ExpectStatus(
115 net::IoMode mode, int expected_status, int immediate_status,
116 net::TestCompletionCallback* test_completion_callback) {
117 if (mode == net::ASYNC) {
118 EXPECT_EQ(net::ERR_IO_PENDING, immediate_status);
119 int status = test_completion_callback->WaitForResult();
120 EXPECT_EQ(expected_status, status);
121 } else {
122 EXPECT_EQ(expected_status, immediate_status);
126 // Sets up the mock socket to generate a successful handshake
127 // (sliced up according to the parameters) and makes sure the
128 // FakeSSLClientSocket behaves as expected.
129 void RunSuccessfulHandshakeTest(
130 net::IoMode mode, size_t read_chunk_size, size_t write_chunk_size,
131 int num_resets) {
132 base::StringPiece ssl_client_hello =
133 FakeSSLClientSocket::GetSslClientHello();
134 base::StringPiece ssl_server_hello =
135 FakeSSLClientSocket::GetSslServerHello();
137 net::MockConnect mock_connect(mode, net::OK);
138 std::vector<net::MockRead> reads;
139 std::vector<net::MockWrite> writes;
140 static const char kReadTestData[] = "read test data";
141 static const char kWriteTestData[] = "write test data";
142 for (int i = 0; i < num_resets + 1; ++i) {
143 SCOPED_TRACE(i);
144 AddChunkedOps(ssl_server_hello, read_chunk_size, mode, &reads);
145 AddChunkedOps(ssl_client_hello, write_chunk_size, mode, &writes);
146 reads.push_back(
147 net::MockRead(mode, kReadTestData, arraysize(kReadTestData)));
148 writes.push_back(
149 net::MockWrite(mode, kWriteTestData, arraysize(kWriteTestData)));
151 SetData(mock_connect, &reads, &writes);
153 FakeSSLClientSocket fake_ssl_client_socket(MakeClientSocket());
155 for (int i = 0; i < num_resets + 1; ++i) {
156 SCOPED_TRACE(i);
157 net::TestCompletionCallback test_completion_callback;
158 int status = fake_ssl_client_socket.Connect(
159 test_completion_callback.callback());
160 if (mode == net::ASYNC) {
161 EXPECT_FALSE(fake_ssl_client_socket.IsConnected());
163 ExpectStatus(mode, net::OK, status, &test_completion_callback);
164 if (fake_ssl_client_socket.IsConnected()) {
165 int read_len = arraysize(kReadTestData);
166 int read_buf_len = 2 * read_len;
167 scoped_refptr<net::IOBuffer> read_buf(
168 new net::IOBuffer(read_buf_len));
169 int read_status = fake_ssl_client_socket.Read(
170 read_buf.get(), read_buf_len, test_completion_callback.callback());
171 ExpectStatus(mode, read_len, read_status, &test_completion_callback);
173 scoped_refptr<net::IOBuffer> write_buf(
174 new net::StringIOBuffer(kWriteTestData));
175 int write_status =
176 fake_ssl_client_socket.Write(write_buf.get(),
177 arraysize(kWriteTestData),
178 test_completion_callback.callback());
179 ExpectStatus(mode, arraysize(kWriteTestData), write_status,
180 &test_completion_callback);
181 } else {
182 ADD_FAILURE();
184 fake_ssl_client_socket.Disconnect();
185 EXPECT_FALSE(fake_ssl_client_socket.IsConnected());
189 // Sets up the mock socket to generate an unsuccessful handshake
190 // FakeSSLClientSocket fails as expected.
191 void RunUnsuccessfulHandshakeTestHelper(
192 net::IoMode mode, int error, HandshakeErrorLocation location) {
193 DCHECK_NE(error, net::OK);
194 base::StringPiece ssl_client_hello =
195 FakeSSLClientSocket::GetSslClientHello();
196 base::StringPiece ssl_server_hello =
197 FakeSSLClientSocket::GetSslServerHello();
199 net::MockConnect mock_connect(mode, net::OK);
200 std::vector<net::MockRead> reads;
201 std::vector<net::MockWrite> writes;
202 const size_t kChunkSize = 1;
203 AddChunkedOps(ssl_server_hello, kChunkSize, mode, &reads);
204 AddChunkedOps(ssl_client_hello, kChunkSize, mode, &writes);
205 switch (location) {
206 case CONNECT_ERROR:
207 mock_connect.result = error;
208 writes.clear();
209 reads.clear();
210 break;
211 case SEND_CLIENT_HELLO_ERROR: {
212 // Use a fixed index for repeatability.
213 size_t index = 100 % writes.size();
214 writes[index].result = error;
215 writes[index].data = NULL;
216 writes[index].data_len = 0;
217 writes.resize(index + 1);
218 reads.clear();
219 break;
221 case VERIFY_SERVER_HELLO_ERROR: {
222 // Use a fixed index for repeatability.
223 size_t index = 50 % reads.size();
224 if (error == ERR_MALFORMED_SERVER_HELLO) {
225 static const char kBadData[] = "BAD_DATA";
226 reads[index].data = kBadData;
227 reads[index].data_len = arraysize(kBadData);
228 } else {
229 reads[index].result = error;
230 reads[index].data = NULL;
231 reads[index].data_len = 0;
233 reads.resize(index + 1);
234 if (error ==
235 net::ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ) {
236 static const char kDummyData[] = "DUMMY";
237 reads.push_back(net::MockRead(mode, kDummyData));
239 break;
242 SetData(mock_connect, &reads, &writes);
244 FakeSSLClientSocket fake_ssl_client_socket(MakeClientSocket());
246 // The two errors below are interpreted by FakeSSLClientSocket as
247 // an unexpected event.
248 int expected_status =
249 ((error == net::ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ) ||
250 (error == ERR_MALFORMED_SERVER_HELLO)) ?
251 net::ERR_UNEXPECTED : error;
253 net::TestCompletionCallback test_completion_callback;
254 int status = fake_ssl_client_socket.Connect(
255 test_completion_callback.callback());
256 EXPECT_FALSE(fake_ssl_client_socket.IsConnected());
257 ExpectStatus(mode, expected_status, status, &test_completion_callback);
258 EXPECT_FALSE(fake_ssl_client_socket.IsConnected());
261 void RunUnsuccessfulHandshakeTest(
262 int error, HandshakeErrorLocation location) {
263 RunUnsuccessfulHandshakeTestHelper(net::SYNCHRONOUS, error, location);
264 RunUnsuccessfulHandshakeTestHelper(net::ASYNC, error, location);
267 // MockTCPClientSocket needs a message loop.
268 base::MessageLoop message_loop_;
270 net::MockClientSocketFactory mock_client_socket_factory_;
271 scoped_ptr<net::StaticSocketDataProvider> static_socket_data_provider_;
274 TEST_F(FakeSSLClientSocketTest, PassThroughMethods) {
275 scoped_ptr<MockClientSocket> mock_client_socket(new MockClientSocket());
276 const int kReceiveBufferSize = 10;
277 const int kSendBufferSize = 20;
278 net::IPEndPoint ip_endpoint(net::IPAddressNumber(net::kIPv4AddressSize), 80);
279 const int kPeerAddress = 30;
280 net::BoundNetLog net_log;
281 EXPECT_CALL(*mock_client_socket, SetReceiveBufferSize(kReceiveBufferSize));
282 EXPECT_CALL(*mock_client_socket, SetSendBufferSize(kSendBufferSize));
283 EXPECT_CALL(*mock_client_socket, GetPeerAddress(&ip_endpoint)).
284 WillOnce(Return(kPeerAddress));
285 EXPECT_CALL(*mock_client_socket, NetLog()).WillOnce(ReturnRef(net_log));
286 EXPECT_CALL(*mock_client_socket, SetSubresourceSpeculation());
287 EXPECT_CALL(*mock_client_socket, SetOmniboxSpeculation());
289 // Takes ownership of |mock_client_socket|.
290 FakeSSLClientSocket fake_ssl_client_socket(mock_client_socket.Pass());
291 fake_ssl_client_socket.SetReceiveBufferSize(kReceiveBufferSize);
292 fake_ssl_client_socket.SetSendBufferSize(kSendBufferSize);
293 EXPECT_EQ(kPeerAddress,
294 fake_ssl_client_socket.GetPeerAddress(&ip_endpoint));
295 EXPECT_EQ(&net_log, &fake_ssl_client_socket.NetLog());
296 fake_ssl_client_socket.SetSubresourceSpeculation();
297 fake_ssl_client_socket.SetOmniboxSpeculation();
300 TEST_F(FakeSSLClientSocketTest, SuccessfulHandshakeSync) {
301 for (size_t i = 1; i < 100; i += 3) {
302 SCOPED_TRACE(i);
303 for (size_t j = 1; j < 100; j += 5) {
304 SCOPED_TRACE(j);
305 RunSuccessfulHandshakeTest(net::SYNCHRONOUS, i, j, 0);
310 TEST_F(FakeSSLClientSocketTest, SuccessfulHandshakeAsync) {
311 for (size_t i = 1; i < 100; i += 7) {
312 SCOPED_TRACE(i);
313 for (size_t j = 1; j < 100; j += 9) {
314 SCOPED_TRACE(j);
315 RunSuccessfulHandshakeTest(net::ASYNC, i, j, 0);
320 TEST_F(FakeSSLClientSocketTest, ResetSocket) {
321 RunSuccessfulHandshakeTest(net::ASYNC, 1, 2, 3);
324 TEST_F(FakeSSLClientSocketTest, UnsuccessfulHandshakeConnectError) {
325 RunUnsuccessfulHandshakeTest(net::ERR_ACCESS_DENIED, CONNECT_ERROR);
328 TEST_F(FakeSSLClientSocketTest, UnsuccessfulHandshakeWriteError) {
329 RunUnsuccessfulHandshakeTest(net::ERR_OUT_OF_MEMORY,
330 SEND_CLIENT_HELLO_ERROR);
333 TEST_F(FakeSSLClientSocketTest, UnsuccessfulHandshakeReadError) {
334 RunUnsuccessfulHandshakeTest(net::ERR_CONNECTION_CLOSED,
335 VERIFY_SERVER_HELLO_ERROR);
338 TEST_F(FakeSSLClientSocketTest, PeerClosedDuringHandshake) {
339 RunUnsuccessfulHandshakeTest(
340 net::ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ,
341 VERIFY_SERVER_HELLO_ERROR);
344 TEST_F(FakeSSLClientSocketTest, MalformedServerHello) {
345 RunUnsuccessfulHandshakeTest(ERR_MALFORMED_SERVER_HELLO,
346 VERIFY_SERVER_HELLO_ERROR);
349 } // namespace
351 } // namespace jingle_glue