Chromium Code Reviews| Index: net/socket/ssl_client_socket_unittest.cc |
| diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc |
| index 2639870e81f36f4fefef5ad4626ced9bc629da13..c766b7c6178343c51cb9a7c796e8407b060cd065 100644 |
| --- a/net/socket/ssl_client_socket_unittest.cc |
| +++ b/net/socket/ssl_client_socket_unittest.cc |
| @@ -599,9 +599,7 @@ class SSLClientSocketTest : public PlatformTest { |
| } |
| protected: |
| - // Sets up a TCP connection to a HTTPS server. To actually do the SSL |
| - // handshake, follow up with call to CreateAndConnectSSLClientSocket() below. |
| - bool ConnectToTestServer(SpawnedTestServer::SSLOptions& ssl_options) { |
| + bool StartTestServer(const SpawnedTestServer::SSLOptions& ssl_options) { |
| test_server_.reset(new SpawnedTestServer( |
| SpawnedTestServer::TYPE_HTTPS, ssl_options, base::FilePath())); |
| if (!test_server_->Start()) { |
| @@ -613,6 +611,14 @@ class SSLClientSocketTest : public PlatformTest { |
| LOG(ERROR) << "Could not get SpawnedTestServer address list"; |
| return false; |
| } |
| + return true; |
| + } |
| + |
| + // Sets up a TCP connection to a HTTPS server. To actually do the SSL |
| + // handshake, follow up with call to CreateAndConnectSSLClientSocket() below. |
| + bool ConnectToTestServer(const SpawnedTestServer::SSLOptions& ssl_options) { |
| + if (!StartTestServer(ssl_options)) |
| + return false; |
| transport_.reset(new TCPClientSocket(addr_, &log_, NetLog::Source())); |
| int rv = callback_.GetResult(transport_->Connect(callback_.callback())); |
| @@ -660,12 +666,12 @@ class SSLClientSocketTest : public PlatformTest { |
| SSLClientSocketContext context_; |
| scoped_ptr<SSLClientSocket> sock_; |
| CapturingNetLog log_; |
| + AddressList addr_; |
| + scoped_ptr<SpawnedTestServer> test_server_; |
| private: |
| scoped_ptr<StreamSocket> transport_; |
| - scoped_ptr<SpawnedTestServer> test_server_; |
| TestCompletionCallback callback_; |
| - AddressList addr_; |
| }; |
| // Verifies the correctness of GetSSLCertRequestInfo. |
| @@ -713,58 +719,66 @@ class SSLClientSocketCertRequestInfoTest : public SSLClientSocketTest { |
| class SSLClientSocketFalseStartTest : public SSLClientSocketTest { |
| protected: |
| - void TestFalseStart(const SpawnedTestServer::SSLOptions& server_options, |
| - const SSLConfig& client_config, |
| - bool expect_false_start) { |
| - SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS, |
| - server_options, |
| - base::FilePath()); |
| - ASSERT_TRUE(test_server.Start()); |
| - |
| - AddressList addr; |
| - ASSERT_TRUE(test_server.GetAddressList(&addr)); |
| - |
| - TestCompletionCallback callback; |
| + void CreateAndConnectUpToServerFinished( |
|
Ryan Sleevi
2014/05/31 00:46:11
s/UpToServerFinished/UntilServerFinishedReceived?
davidben
2014/06/02 18:45:38
Done.
|
| + const SSLConfig& client_config, |
| + TestCompletionCallback* callback, |
| + FakeBlockingStreamSocket** out_raw_transport, |
|
Ryan Sleevi
2014/05/31 00:46:11
More documentation is needed here. My red alert al
davidben
2014/06/02 18:45:38
Documented. (The FakeBlockingStreamSocket annoying
|
| + scoped_ptr<SSLClientSocket>* out_sock) { |
| scoped_ptr<StreamSocket> real_transport( |
| - new TCPClientSocket(addr, NULL, NetLog::Source())); |
| + new TCPClientSocket(addr_, NULL, NetLog::Source())); |
| scoped_ptr<FakeBlockingStreamSocket> transport( |
| new FakeBlockingStreamSocket(real_transport.Pass())); |
| - int rv = callback.GetResult(transport->Connect(callback.callback())); |
| + int rv = callback->GetResult(transport->Connect(callback->callback())); |
| EXPECT_EQ(OK, rv); |
| FakeBlockingStreamSocket* raw_transport = transport.get(); |
| - scoped_ptr<SSLClientSocket> sock( |
| + scoped_ptr<SSLClientSocket> sock = |
| CreateSSLClientSocket(transport.PassAs<StreamSocket>(), |
| - test_server.host_port_pair(), |
| - client_config)); |
| + test_server_->host_port_pair(), |
| + client_config); |
| // Connect. Stop before the client processes the first server leg |
| // (ServerHello, etc.) |
| raw_transport->BlockReadResult(); |
| - rv = sock->Connect(callback.callback()); |
| + rv = sock->Connect(callback->callback()); |
| EXPECT_EQ(ERR_IO_PENDING, rv); |
| raw_transport->WaitForReadResult(); |
| // Release the ServerHello and wait for the client to write |
| // ClientKeyExchange, etc. (A proxy for waiting for the entirety of the |
| // server's leg to complete, since it may span multiple reads.) |
| - EXPECT_FALSE(callback.have_result()); |
| + EXPECT_FALSE(callback->have_result()); |
| raw_transport->BlockWrite(); |
| raw_transport->UnblockReadResult(); |
| raw_transport->WaitForWrite(); |
| // And, finally, release that and block the next server leg |
| - // (ChangeCipherSpec, Finished). Note: callback.have_result() may or may not |
| - // be true at this point depending on whether the SSL implementation waits |
| - // for the client second leg to clear the internal write buffer and hit the |
| - // network. |
| + // (ChangeCipherSpec, Finished). Note: callback->have_result() may or may |
| + // not be true at this point depending on whether the SSL implementation |
| + // waits for the client second leg to clear the internal write buffer and |
| + // hit the network. |
| raw_transport->BlockReadResult(); |
| raw_transport->UnblockWrite(); |
| + *out_raw_transport = raw_transport; |
| + *out_sock = sock.Pass(); |
| + } |
| + |
| + void TestFalseStart(const SpawnedTestServer::SSLOptions& server_options, |
| + const SSLConfig& client_config, |
| + bool expect_false_start) { |
| + ASSERT_TRUE(StartTestServer(server_options)); |
| + |
| + TestCompletionCallback callback; |
| + FakeBlockingStreamSocket* raw_transport; |
| + scoped_ptr<SSLClientSocket> sock; |
| + CreateAndConnectUpToServerFinished( |
| + client_config, &callback, &raw_transport, &sock); |
|
Ryan Sleevi
2014/05/31 00:46:11
DANGER: If you ever added an ASSERT_() to CreateAn
davidben
2014/06/02 18:45:38
Oh, so that's how you do it... done.
|
| + |
| if (expect_false_start) { |
| // When False Starting, the handshake should complete before receiving the |
| // Change Cipher Spec and Finished messages. |
| - rv = callback.GetResult(rv); |
| + int rv = callback.GetResult(ERR_IO_PENDING); |
|
Ryan Sleevi
2014/05/31 00:46:11
Just use
int rv = callback.WaitForResult();
no n
davidben
2014/06/02 18:45:38
Done.
|
| EXPECT_EQ(OK, rv); |
| EXPECT_TRUE(sock->IsConnected()); |
| @@ -2482,6 +2496,75 @@ TEST_F(SSLClientSocketFalseStartTest, NoForwardSecrecy) { |
| TestFalseStart(server_options, client_config, false); |
| } |
| +// Test that sessions are resumable after receiving the server Finished message. |
| +TEST_F(SSLClientSocketFalseStartTest, SessionResumption) { |
| + // Start a server. |
| + SpawnedTestServer::SSLOptions server_options; |
| + server_options.key_exchanges = |
| + SpawnedTestServer::SSLOptions::KEY_EXCHANGE_DHE_RSA; |
| + server_options.enable_npn = true; |
| + SSLConfig client_config; |
| + client_config.next_protos.push_back("http/1.1"); |
| + |
| + // Let a full handshake complete with False Start. |
| + TestFalseStart(server_options, client_config, true); |
| + |
| + // Make a second connection. |
| + TestCompletionCallback callback; |
| + scoped_ptr<StreamSocket> transport2( |
| + new TCPClientSocket(addr_, &log_, NetLog::Source())); |
| + EXPECT_EQ(OK, callback.GetResult(transport2->Connect(callback.callback()))); |
| + scoped_ptr<SSLClientSocket> sock2 = CreateSSLClientSocket( |
| + transport2.Pass(), test_server_->host_port_pair(), client_config); |
| + EXPECT_EQ(OK, callback.GetResult(sock2->Connect(callback.callback()))); |
| + |
| + // It should resume the session. |
| + SSLInfo ssl_info; |
| + EXPECT_TRUE(sock2->GetSSLInfo(&ssl_info)); |
| + EXPECT_EQ(SSLInfo::HANDSHAKE_RESUME, ssl_info.handshake_type); |
| +} |
| + |
| +// Test that sessions are not resumable before receiving the server Finished |
| +// message. |
| +TEST_F(SSLClientSocketFalseStartTest, NoSessionResumptionBeforeFinish) { |
| + // Start a server. |
| + SpawnedTestServer::SSLOptions server_options; |
| + server_options.key_exchanges = |
| + SpawnedTestServer::SSLOptions::KEY_EXCHANGE_DHE_RSA; |
| + server_options.enable_npn = true; |
| + ASSERT_TRUE(StartTestServer(server_options)); |
| + |
| + SSLConfig client_config; |
| + client_config.next_protos.push_back("http/1.1"); |
| + |
| + // Start a handshake up to the server Finished message. |
| + TestCompletionCallback callback; |
| + FakeBlockingStreamSocket* raw_transport1; |
| + scoped_ptr<SSLClientSocket> sock1; |
| + CreateAndConnectUpToServerFinished( |
| + client_config, &callback, &raw_transport1, &sock1); |
| + // The handshake should False Start. |
| + EXPECT_EQ(OK, callback.GetResult(ERR_IO_PENDING)); |
|
Ryan Sleevi
2014/05/31 00:46:11
ditto WaitForResult()
However, it's unclear to me
davidben
2014/06/02 18:45:38
Done. Also added a comment.
|
| + |
| + // Drop the old socket. This is needed because the Python test server can't |
| + // service two sockets in parallel. |
| + sock1.reset(); |
| + |
| + // Before the first connection receives ServerFinished, start a second |
| + // connection. |
| + scoped_ptr<StreamSocket> transport2( |
| + new TCPClientSocket(addr_, &log_, NetLog::Source())); |
| + EXPECT_EQ(OK, callback.GetResult(transport2->Connect(callback.callback()))); |
| + scoped_ptr<SSLClientSocket> sock2 = CreateSSLClientSocket( |
| + transport2.Pass(), test_server_->host_port_pair(), client_config); |
| + EXPECT_EQ(OK, callback.GetResult(sock2->Connect(callback.callback()))); |
| + |
| + // No session resumption. |
| + SSLInfo ssl_info; |
| + EXPECT_TRUE(sock2->GetSSLInfo(&ssl_info)); |
| + EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, ssl_info.handshake_type); |
| +} |
| + |
| // Connect to a server using channel id. It should allow the connection. |
| TEST_F(SSLClientSocketChannelIDTest, SendChannelID) { |
| SpawnedTestServer::SSLOptions ssl_options; |