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"
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/net_log.h"
16 #include "net/base/test_completion_callback.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
{
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
{
33 SEND_CLIENT_HELLO_ERROR
,
34 VERIFY_SERVER_HELLO_ERROR
,
37 // Private error codes appended to the net::Error set.
39 // An error representing a server hello that has been corrupted in
41 ERR_MALFORMED_SERVER_HELLO
= -15000,
44 // Used by PassThroughMethods test.
45 class MockClientSocket
: public net::StreamSocket
{
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
*));
73 // Break up |data| into a bunch of chunked MockReads/Writes and push
75 template <net::MockReadWriteType type
>
76 void AddChunkedOps(base::StringPiece data
, size_t chunk_size
, net::IoMode mode
,
77 std::vector
<net::MockReadWrite
<type
> >* ops
) {
78 DCHECK_GT(chunk_size
, 0U);
80 while (offset
< data
.size()) {
81 size_t bounded_chunk_size
= std::min(data
.size() - offset
, chunk_size
);
82 ops
->push_back(net::MockReadWrite
<type
>(mode
, data
.data() + offset
,
84 offset
+= bounded_chunk_size
;
88 class FakeSSLClientSocketTest
: public testing::Test
{
90 FakeSSLClientSocketTest() {}
92 ~FakeSSLClientSocketTest() override
{}
94 scoped_ptr
<net::StreamSocket
> MakeClientSocket() {
95 return mock_client_socket_factory_
.CreateTransportClientSocket(
96 net::AddressList(), NULL
, net::NetLog::Source());
99 void SetData(const net::MockConnect
& mock_connect
,
100 std::vector
<net::MockRead
>* reads
,
101 std::vector
<net::MockWrite
>* writes
) {
102 static_socket_data_provider_
.reset(
103 new net::StaticSocketDataProvider(
104 reads
->empty() ? NULL
: &*reads
->begin(), reads
->size(),
105 writes
->empty() ? NULL
: &*writes
->begin(), writes
->size()));
106 static_socket_data_provider_
->set_connect_data(mock_connect
);
107 mock_client_socket_factory_
.AddSocketDataProvider(
108 static_socket_data_provider_
.get());
112 net::IoMode mode
, int expected_status
, int immediate_status
,
113 net::TestCompletionCallback
* test_completion_callback
) {
114 if (mode
== net::ASYNC
) {
115 EXPECT_EQ(net::ERR_IO_PENDING
, immediate_status
);
116 int status
= test_completion_callback
->WaitForResult();
117 EXPECT_EQ(expected_status
, status
);
119 EXPECT_EQ(expected_status
, immediate_status
);
123 // Sets up the mock socket to generate a successful handshake
124 // (sliced up according to the parameters) and makes sure the
125 // FakeSSLClientSocket behaves as expected.
126 void RunSuccessfulHandshakeTest(
127 net::IoMode mode
, size_t read_chunk_size
, size_t write_chunk_size
,
129 base::StringPiece ssl_client_hello
=
130 FakeSSLClientSocket::GetSslClientHello();
131 base::StringPiece ssl_server_hello
=
132 FakeSSLClientSocket::GetSslServerHello();
134 net::MockConnect
mock_connect(mode
, net::OK
);
135 std::vector
<net::MockRead
> reads
;
136 std::vector
<net::MockWrite
> writes
;
137 static const char kReadTestData
[] = "read test data";
138 static const char kWriteTestData
[] = "write test data";
139 for (int i
= 0; i
< num_resets
+ 1; ++i
) {
141 AddChunkedOps(ssl_server_hello
, read_chunk_size
, mode
, &reads
);
142 AddChunkedOps(ssl_client_hello
, write_chunk_size
, mode
, &writes
);
144 net::MockRead(mode
, kReadTestData
, arraysize(kReadTestData
)));
146 net::MockWrite(mode
, kWriteTestData
, arraysize(kWriteTestData
)));
148 SetData(mock_connect
, &reads
, &writes
);
150 FakeSSLClientSocket
fake_ssl_client_socket(MakeClientSocket());
152 for (int i
= 0; i
< num_resets
+ 1; ++i
) {
154 net::TestCompletionCallback test_completion_callback
;
155 int status
= fake_ssl_client_socket
.Connect(
156 test_completion_callback
.callback());
157 if (mode
== net::ASYNC
) {
158 EXPECT_FALSE(fake_ssl_client_socket
.IsConnected());
160 ExpectStatus(mode
, net::OK
, status
, &test_completion_callback
);
161 if (fake_ssl_client_socket
.IsConnected()) {
162 int read_len
= arraysize(kReadTestData
);
163 int read_buf_len
= 2 * read_len
;
164 scoped_refptr
<net::IOBuffer
> read_buf(
165 new net::IOBuffer(read_buf_len
));
166 int read_status
= fake_ssl_client_socket
.Read(
167 read_buf
.get(), read_buf_len
, test_completion_callback
.callback());
168 ExpectStatus(mode
, read_len
, read_status
, &test_completion_callback
);
170 scoped_refptr
<net::IOBuffer
> write_buf(
171 new net::StringIOBuffer(kWriteTestData
));
173 fake_ssl_client_socket
.Write(write_buf
.get(),
174 arraysize(kWriteTestData
),
175 test_completion_callback
.callback());
176 ExpectStatus(mode
, arraysize(kWriteTestData
), write_status
,
177 &test_completion_callback
);
181 fake_ssl_client_socket
.Disconnect();
182 EXPECT_FALSE(fake_ssl_client_socket
.IsConnected());
186 // Sets up the mock socket to generate an unsuccessful handshake
187 // FakeSSLClientSocket fails as expected.
188 void RunUnsuccessfulHandshakeTestHelper(
189 net::IoMode mode
, int error
, HandshakeErrorLocation location
) {
190 DCHECK_NE(error
, net::OK
);
191 base::StringPiece ssl_client_hello
=
192 FakeSSLClientSocket::GetSslClientHello();
193 base::StringPiece ssl_server_hello
=
194 FakeSSLClientSocket::GetSslServerHello();
196 net::MockConnect
mock_connect(mode
, net::OK
);
197 std::vector
<net::MockRead
> reads
;
198 std::vector
<net::MockWrite
> writes
;
199 const size_t kChunkSize
= 1;
200 AddChunkedOps(ssl_server_hello
, kChunkSize
, mode
, &reads
);
201 AddChunkedOps(ssl_client_hello
, kChunkSize
, mode
, &writes
);
204 mock_connect
.result
= error
;
208 case SEND_CLIENT_HELLO_ERROR
: {
209 // Use a fixed index for repeatability.
210 size_t index
= 100 % writes
.size();
211 writes
[index
].result
= error
;
212 writes
[index
].data
= NULL
;
213 writes
[index
].data_len
= 0;
214 writes
.resize(index
+ 1);
218 case VERIFY_SERVER_HELLO_ERROR
: {
219 // Use a fixed index for repeatability.
220 size_t index
= 50 % reads
.size();
221 if (error
== ERR_MALFORMED_SERVER_HELLO
) {
222 static const char kBadData
[] = "BAD_DATA";
223 reads
[index
].data
= kBadData
;
224 reads
[index
].data_len
= arraysize(kBadData
);
226 reads
[index
].result
= error
;
227 reads
[index
].data
= NULL
;
228 reads
[index
].data_len
= 0;
230 reads
.resize(index
+ 1);
232 net::ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
) {
233 static const char kDummyData
[] = "DUMMY";
234 reads
.push_back(net::MockRead(mode
, kDummyData
));
239 SetData(mock_connect
, &reads
, &writes
);
241 FakeSSLClientSocket
fake_ssl_client_socket(MakeClientSocket());
243 // The two errors below are interpreted by FakeSSLClientSocket as
244 // an unexpected event.
245 int expected_status
=
246 ((error
== net::ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
) ||
247 (error
== ERR_MALFORMED_SERVER_HELLO
)) ?
248 net::ERR_UNEXPECTED
: error
;
250 net::TestCompletionCallback test_completion_callback
;
251 int status
= fake_ssl_client_socket
.Connect(
252 test_completion_callback
.callback());
253 EXPECT_FALSE(fake_ssl_client_socket
.IsConnected());
254 ExpectStatus(mode
, expected_status
, status
, &test_completion_callback
);
255 EXPECT_FALSE(fake_ssl_client_socket
.IsConnected());
258 void RunUnsuccessfulHandshakeTest(
259 int error
, HandshakeErrorLocation location
) {
260 RunUnsuccessfulHandshakeTestHelper(net::SYNCHRONOUS
, error
, location
);
261 RunUnsuccessfulHandshakeTestHelper(net::ASYNC
, error
, location
);
264 // MockTCPClientSocket needs a message loop.
265 base::MessageLoop message_loop_
;
267 net::MockClientSocketFactory mock_client_socket_factory_
;
268 scoped_ptr
<net::StaticSocketDataProvider
> static_socket_data_provider_
;
271 TEST_F(FakeSSLClientSocketTest
, PassThroughMethods
) {
272 scoped_ptr
<MockClientSocket
> mock_client_socket(new MockClientSocket());
273 const int kReceiveBufferSize
= 10;
274 const int kSendBufferSize
= 20;
275 net::IPEndPoint
ip_endpoint(net::IPAddressNumber(net::kIPv4AddressSize
), 80);
276 const int kPeerAddress
= 30;
277 net::BoundNetLog net_log
;
278 EXPECT_CALL(*mock_client_socket
, SetReceiveBufferSize(kReceiveBufferSize
));
279 EXPECT_CALL(*mock_client_socket
, SetSendBufferSize(kSendBufferSize
));
280 EXPECT_CALL(*mock_client_socket
, GetPeerAddress(&ip_endpoint
)).
281 WillOnce(Return(kPeerAddress
));
282 EXPECT_CALL(*mock_client_socket
, NetLog()).WillOnce(ReturnRef(net_log
));
283 EXPECT_CALL(*mock_client_socket
, SetSubresourceSpeculation());
284 EXPECT_CALL(*mock_client_socket
, SetOmniboxSpeculation());
286 // Takes ownership of |mock_client_socket|.
287 FakeSSLClientSocket
fake_ssl_client_socket(mock_client_socket
.Pass());
288 fake_ssl_client_socket
.SetReceiveBufferSize(kReceiveBufferSize
);
289 fake_ssl_client_socket
.SetSendBufferSize(kSendBufferSize
);
290 EXPECT_EQ(kPeerAddress
,
291 fake_ssl_client_socket
.GetPeerAddress(&ip_endpoint
));
292 EXPECT_EQ(&net_log
, &fake_ssl_client_socket
.NetLog());
293 fake_ssl_client_socket
.SetSubresourceSpeculation();
294 fake_ssl_client_socket
.SetOmniboxSpeculation();
297 TEST_F(FakeSSLClientSocketTest
, SuccessfulHandshakeSync
) {
298 for (size_t i
= 1; i
< 100; i
+= 3) {
300 for (size_t j
= 1; j
< 100; j
+= 5) {
302 RunSuccessfulHandshakeTest(net::SYNCHRONOUS
, i
, j
, 0);
307 TEST_F(FakeSSLClientSocketTest
, SuccessfulHandshakeAsync
) {
308 for (size_t i
= 1; i
< 100; i
+= 7) {
310 for (size_t j
= 1; j
< 100; j
+= 9) {
312 RunSuccessfulHandshakeTest(net::ASYNC
, i
, j
, 0);
317 TEST_F(FakeSSLClientSocketTest
, ResetSocket
) {
318 RunSuccessfulHandshakeTest(net::ASYNC
, 1, 2, 3);
321 TEST_F(FakeSSLClientSocketTest
, UnsuccessfulHandshakeConnectError
) {
322 RunUnsuccessfulHandshakeTest(net::ERR_ACCESS_DENIED
, CONNECT_ERROR
);
325 TEST_F(FakeSSLClientSocketTest
, UnsuccessfulHandshakeWriteError
) {
326 RunUnsuccessfulHandshakeTest(net::ERR_OUT_OF_MEMORY
,
327 SEND_CLIENT_HELLO_ERROR
);
330 TEST_F(FakeSSLClientSocketTest
, UnsuccessfulHandshakeReadError
) {
331 RunUnsuccessfulHandshakeTest(net::ERR_CONNECTION_CLOSED
,
332 VERIFY_SERVER_HELLO_ERROR
);
335 TEST_F(FakeSSLClientSocketTest
, PeerClosedDuringHandshake
) {
336 RunUnsuccessfulHandshakeTest(
337 net::ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
,
338 VERIFY_SERVER_HELLO_ERROR
);
341 TEST_F(FakeSSLClientSocketTest
, MalformedServerHello
) {
342 RunUnsuccessfulHandshakeTest(ERR_MALFORMED_SERVER_HELLO
,
343 VERIFY_SERVER_HELLO_ERROR
);
348 } // namespace jingle_glue