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.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
, bool(int32
));
54 MOCK_METHOD1(SetSendBufferSize
, bool(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 virtual ~FakeSSLClientSocketTest() {}
94 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
, 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
));
172 int write_status
= fake_ssl_client_socket
.Write(
173 write_buf
, arraysize(kWriteTestData
),
174 test_completion_callback
.callback());
175 ExpectStatus(mode
, arraysize(kWriteTestData
), write_status
,
176 &test_completion_callback
);
180 fake_ssl_client_socket
.Disconnect();
181 EXPECT_FALSE(fake_ssl_client_socket
.IsConnected());
185 // Sets up the mock socket to generate an unsuccessful handshake
186 // FakeSSLClientSocket fails as expected.
187 void RunUnsuccessfulHandshakeTestHelper(
188 net::IoMode mode
, int error
, HandshakeErrorLocation location
) {
189 DCHECK_NE(error
, net::OK
);
190 base::StringPiece ssl_client_hello
=
191 FakeSSLClientSocket::GetSslClientHello();
192 base::StringPiece ssl_server_hello
=
193 FakeSSLClientSocket::GetSslServerHello();
195 net::MockConnect
mock_connect(mode
, net::OK
);
196 std::vector
<net::MockRead
> reads
;
197 std::vector
<net::MockWrite
> writes
;
198 const size_t kChunkSize
= 1;
199 AddChunkedOps(ssl_server_hello
, kChunkSize
, mode
, &reads
);
200 AddChunkedOps(ssl_client_hello
, kChunkSize
, mode
, &writes
);
203 mock_connect
.result
= error
;
207 case SEND_CLIENT_HELLO_ERROR
: {
208 // Use a fixed index for repeatability.
209 size_t index
= 100 % writes
.size();
210 writes
[index
].result
= error
;
211 writes
[index
].data
= NULL
;
212 writes
[index
].data_len
= 0;
213 writes
.resize(index
+ 1);
217 case VERIFY_SERVER_HELLO_ERROR
: {
218 // Use a fixed index for repeatability.
219 size_t index
= 50 % reads
.size();
220 if (error
== ERR_MALFORMED_SERVER_HELLO
) {
221 static const char kBadData
[] = "BAD_DATA";
222 reads
[index
].data
= kBadData
;
223 reads
[index
].data_len
= arraysize(kBadData
);
225 reads
[index
].result
= error
;
226 reads
[index
].data
= NULL
;
227 reads
[index
].data_len
= 0;
229 reads
.resize(index
+ 1);
231 net::ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
) {
232 static const char kDummyData
[] = "DUMMY";
233 reads
.push_back(net::MockRead(mode
, kDummyData
));
238 SetData(mock_connect
, &reads
, &writes
);
240 FakeSSLClientSocket
fake_ssl_client_socket(MakeClientSocket());
242 // The two errors below are interpreted by FakeSSLClientSocket as
243 // an unexpected event.
244 int expected_status
=
245 ((error
== net::ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
) ||
246 (error
== ERR_MALFORMED_SERVER_HELLO
)) ?
247 net::ERR_UNEXPECTED
: error
;
249 net::TestCompletionCallback test_completion_callback
;
250 int status
= fake_ssl_client_socket
.Connect(
251 test_completion_callback
.callback());
252 EXPECT_FALSE(fake_ssl_client_socket
.IsConnected());
253 ExpectStatus(mode
, expected_status
, status
, &test_completion_callback
);
254 EXPECT_FALSE(fake_ssl_client_socket
.IsConnected());
257 void RunUnsuccessfulHandshakeTest(
258 int error
, HandshakeErrorLocation location
) {
259 RunUnsuccessfulHandshakeTestHelper(net::SYNCHRONOUS
, error
, location
);
260 RunUnsuccessfulHandshakeTestHelper(net::ASYNC
, error
, location
);
263 // MockTCPClientSocket needs a message loop.
264 MessageLoop message_loop_
;
266 net::MockClientSocketFactory mock_client_socket_factory_
;
267 scoped_ptr
<net::StaticSocketDataProvider
> static_socket_data_provider_
;
270 TEST_F(FakeSSLClientSocketTest
, PassThroughMethods
) {
271 MockClientSocket
* mock_client_socket
= new MockClientSocket();
272 const int kReceiveBufferSize
= 10;
273 const int kSendBufferSize
= 20;
274 net::IPEndPoint
ip_endpoint(net::IPAddressNumber(net::kIPv4AddressSize
), 80);
275 const int kPeerAddress
= 30;
276 net::BoundNetLog net_log
;
277 EXPECT_CALL(*mock_client_socket
, SetReceiveBufferSize(kReceiveBufferSize
));
278 EXPECT_CALL(*mock_client_socket
, SetSendBufferSize(kSendBufferSize
));
279 EXPECT_CALL(*mock_client_socket
, GetPeerAddress(&ip_endpoint
)).
280 WillOnce(Return(kPeerAddress
));
281 EXPECT_CALL(*mock_client_socket
, NetLog()).WillOnce(ReturnRef(net_log
));
282 EXPECT_CALL(*mock_client_socket
, SetSubresourceSpeculation());
283 EXPECT_CALL(*mock_client_socket
, SetOmniboxSpeculation());
285 // Takes ownership of |mock_client_socket|.
286 FakeSSLClientSocket
fake_ssl_client_socket(mock_client_socket
);
287 fake_ssl_client_socket
.SetReceiveBufferSize(kReceiveBufferSize
);
288 fake_ssl_client_socket
.SetSendBufferSize(kSendBufferSize
);
289 EXPECT_EQ(kPeerAddress
,
290 fake_ssl_client_socket
.GetPeerAddress(&ip_endpoint
));
291 EXPECT_EQ(&net_log
, &fake_ssl_client_socket
.NetLog());
292 fake_ssl_client_socket
.SetSubresourceSpeculation();
293 fake_ssl_client_socket
.SetOmniboxSpeculation();
296 TEST_F(FakeSSLClientSocketTest
, SuccessfulHandshakeSync
) {
297 for (size_t i
= 1; i
< 100; i
+= 3) {
299 for (size_t j
= 1; j
< 100; j
+= 5) {
301 RunSuccessfulHandshakeTest(net::SYNCHRONOUS
, i
, j
, 0);
306 TEST_F(FakeSSLClientSocketTest
, SuccessfulHandshakeAsync
) {
307 for (size_t i
= 1; i
< 100; i
+= 7) {
309 for (size_t j
= 1; j
< 100; j
+= 9) {
311 RunSuccessfulHandshakeTest(net::ASYNC
, i
, j
, 0);
316 TEST_F(FakeSSLClientSocketTest
, ResetSocket
) {
317 RunSuccessfulHandshakeTest(net::ASYNC
, 1, 2, 3);
320 TEST_F(FakeSSLClientSocketTest
, UnsuccessfulHandshakeConnectError
) {
321 RunUnsuccessfulHandshakeTest(net::ERR_ACCESS_DENIED
, CONNECT_ERROR
);
324 TEST_F(FakeSSLClientSocketTest
, UnsuccessfulHandshakeWriteError
) {
325 RunUnsuccessfulHandshakeTest(net::ERR_OUT_OF_MEMORY
,
326 SEND_CLIENT_HELLO_ERROR
);
329 TEST_F(FakeSSLClientSocketTest
, UnsuccessfulHandshakeReadError
) {
330 RunUnsuccessfulHandshakeTest(net::ERR_CONNECTION_CLOSED
,
331 VERIFY_SERVER_HELLO_ERROR
);
334 TEST_F(FakeSSLClientSocketTest
, PeerClosedDuringHandshake
) {
335 RunUnsuccessfulHandshakeTest(
336 net::ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
,
337 VERIFY_SERVER_HELLO_ERROR
);
340 TEST_F(FakeSSLClientSocketTest
, MalformedServerHello
) {
341 RunUnsuccessfulHandshakeTest(ERR_MALFORMED_SERVER_HELLO
,
342 VERIFY_SERVER_HELLO_ERROR
);
347 } // namespace jingle_glue