tls_socket_unittest.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file. 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/api/socket/tls_socket.h" 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <deque> 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <utility> 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/strings/string_piece.h" 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/base/address_list.h" 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/base/completion_callback.h" 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/base/io_buffer.h" 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/base/net_errors.h" 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/base/rand_callback.h" 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/socket/ssl_client_socket.h" 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/socket/tcp_client_socket.h" 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using testing::_; 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using testing::DoAll; 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using testing::Invoke; 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using testing::Gt; 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using testing::Return; 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using testing::SaveArg; 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using testing::WithArgs; 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using base::StringPiece; 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace extensions { 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class MockSSLClientSocket : public net::SSLClientSocket { 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public: 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MockSSLClientSocket() {} 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD0(Disconnect, void()); 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD3(Read, 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int(net::IOBuffer* buf, 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int buf_len, 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const net::CompletionCallback& callback)); 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD3(Write, 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int(net::IOBuffer* buf, 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int buf_len, 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const net::CompletionCallback& callback)); 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD1(SetReceiveBufferSize, int(int32)); 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD1(SetSendBufferSize, int(int32)); 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD1(Connect, int(const CompletionCallback&)); 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_CONST_METHOD0(IsConnectedAndIdle, bool()); 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_CONST_METHOD1(GetPeerAddress, int(net::IPEndPoint*)); 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_CONST_METHOD1(GetLocalAddress, int(net::IPEndPoint*)); 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_CONST_METHOD0(NetLog, const net::BoundNetLog&()); 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD0(SetSubresourceSpeculation, void()); 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD0(SetOmniboxSpeculation, void()); 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_CONST_METHOD0(WasEverUsed, bool()); 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_CONST_METHOD0(UsingTCPFastOpen, bool()); 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD1(GetSSLInfo, bool(net::SSLInfo*)); 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD5(ExportKeyingMaterial, 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int(const StringPiece&, 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool, 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const StringPiece&, 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) unsigned char*, 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) unsigned int)); 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD1(GetTLSUniqueChannelBinding, int(std::string*)); 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_CONST_METHOD0(InSessionCache, bool()); 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD1(SetHandshakeCompletionCallback, void(const base::Closure&)); 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD1(GetSSLCertRequestInfo, void(net::SSLCertRequestInfo*)); 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD1(GetNextProto, 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::SSLClientSocket::NextProtoStatus(std::string*)); 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_CONST_METHOD0(GetUnverifiedServerCertificateChain, 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<net::X509Certificate>()); 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_CONST_METHOD0(GetChannelIDService, net::ChannelIDService*()); 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual bool IsConnected() const OVERRIDE { return true; } 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private: 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MockSSLClientSocket); 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class MockTCPSocket : public net::TCPClientSocket { 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public: 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) explicit MockTCPSocket(const net::AddressList& address_list) 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : net::TCPClientSocket(address_list, NULL, net::NetLog::Source()) {} 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD3(Read, 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int(net::IOBuffer* buf, 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int buf_len, 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const net::CompletionCallback& callback)); 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD3(Write, 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int(net::IOBuffer* buf, 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int buf_len, 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const net::CompletionCallback& callback)); 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD2(SetKeepAlive, bool(bool enable, int delay)); 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD1(SetNoDelay, bool(bool no_delay)); 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual bool IsConnected() const OVERRIDE { return true; } 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private: 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MockTCPSocket); 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CompleteHandler { 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public: 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CompleteHandler() {} 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD1(OnComplete, void(int result_code)); 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD2(OnReadComplete, 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void(int result_code, scoped_refptr<net::IOBuffer> io_buffer)); 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD2(OnAccept, void(int, net::TCPClientSocket*)); 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private: 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(CompleteHandler); 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class TLSSocketTest : public ::testing::Test { 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public: 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) TLSSocketTest() {} 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual void SetUp() { 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::AddressList address_list; 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // |ssl_socket_| is owned by |socket_|. TLSSocketTest keeps a pointer to 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // it to expect invocations from TLSSocket to |ssl_socket_|. 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<MockSSLClientSocket> ssl_sock(new MockSSLClientSocket); 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ssl_socket_ = ssl_sock.get(); 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket_.reset(new TLSSocket(ssl_sock.PassAs<net::StreamSocket>(), 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "test_extension_id")); 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(*ssl_socket_, Disconnect()).Times(1); 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }; 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual void TearDown() { 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ssl_socket_ = NULL; 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket_.reset(); 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }; 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) protected: 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MockSSLClientSocket* ssl_socket_; 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<TLSSocket> socket_; 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Verify that a Read() on TLSSocket will pass through into a Read() on 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// |ssl_socket_| and invoke its completion callback. 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(TLSSocketTest, TestTLSSocketRead) { 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CompleteHandler handler; 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(*ssl_socket_, Read(_, _, _)).Times(1); 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(handler, OnReadComplete(_, _)).Times(1); 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int count = 512; 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket_->Read( 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) count, 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&CompleteHandler::OnReadComplete, base::Unretained(&handler))); 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Verify that a Write() on a TLSSocket will pass through to Write() 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// invocations on |ssl_socket_|, handling partial writes correctly, and calls 1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// the completion callback correctly. 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(TLSSocketTest, TestTLSSocketWrite) { 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CompleteHandler handler; 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::CompletionCallback callback; 1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(*ssl_socket_, Write(_, _, _)).Times(2).WillRepeatedly( 1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DoAll(SaveArg<2>(&callback), Return(128))); 1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(handler, OnComplete(_)).Times(1); 1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<net::IOBufferWithSize> io_buffer( 1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new net::IOBufferWithSize(256)); 1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket_->Write( 1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) io_buffer.get(), 1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) io_buffer->size(), 1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&CompleteHandler::OnComplete, base::Unretained(&handler))); 1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Simulate a blocked Write, and verify that, when simulating the Write going 1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// through, the callback gets invoked. 1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(TLSSocketTest, TestTLSSocketBlockedWrite) { 1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CompleteHandler handler; 1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::CompletionCallback callback; 1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Return ERR_IO_PENDING to say the Write()'s blocked. Save the |callback| 1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Write()'s passed. 1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(*ssl_socket_, Write(_, _, _)).Times(2).WillRepeatedly( 1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DoAll(SaveArg<2>(&callback), Return(net::ERR_IO_PENDING))); 1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<net::IOBufferWithSize> io_buffer(new net::IOBufferWithSize(42)); 1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket_->Write( 1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) io_buffer.get(), 1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) io_buffer->size(), 1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&CompleteHandler::OnComplete, base::Unretained(&handler))); 1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // After the simulated asynchronous writes come back (via calls to 1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // callback.Run()), hander's OnComplete() should get invoked with the total 1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // amount written. 1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(handler, OnComplete(42)).Times(1); 1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) callback.Run(40); 1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) callback.Run(2); 1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Simulate multiple blocked Write()s. 1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(TLSSocketTest, TestTLSSocketBlockedWriteReentry) { 1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int kNumIOs = 5; 1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CompleteHandler handlers[kNumIOs]; 1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::CompletionCallback callback; 1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<net::IOBufferWithSize> io_buffers[kNumIOs]; 2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The implementation of TLSSocket::Write() is inherited from 2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Socket::Write(), which implements an internal write queue that wraps 2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // TLSSocket::WriteImpl(). Each call from TLSSocket::WriteImpl() will invoke 2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // |ssl_socket_|'s Write() (mocked here). Save the |callback| (assume they 2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // will all be equivalent), and return ERR_IO_PENDING, to indicate a blocked 2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // request. The mocked SSLClientSocket::Write() will get one request per 2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // TLSSocket::Write() request invoked on |socket_| below. 2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(*ssl_socket_, Write(_, _, _)).Times(kNumIOs).WillRepeatedly( 2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DoAll(SaveArg<2>(&callback), Return(net::ERR_IO_PENDING))); 2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Send out |kNuMIOs| requests, each with a different size. 2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (int i = 0; i < kNumIOs; i++) { 2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) io_buffers[i] = new net::IOBufferWithSize(128 + i * 50); 2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket_->Write(io_buffers[i].get(), 2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) io_buffers[i]->size(), 2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&CompleteHandler::OnComplete, 2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Unretained(&handlers[i]))); 2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Set up expectations on all |kNumIOs| handlers. 2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(handlers[i], OnComplete(io_buffers[i]->size())).Times(1); 2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Finish each pending I/O. This should satisfy the expectations on the 2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // handlers. 2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (int i = 0; i < kNumIOs; i++) { 2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) callback.Run(128 + i * 50); 2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)typedef std::pair<net::CompletionCallback, int> PendingCallback; 2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CallbackList : public std::deque<PendingCallback> { 2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public: 2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void append(const net::CompletionCallback& cb, int arg) { 2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) push_back(std::make_pair(cb, arg)); 2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Simulate Write()s above and below a SSLClientSocket size limit. 2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(TLSSocketTest, TestTLSSocketLargeWrites) { 2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int kSizeIncrement = 4096; 2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int kNumIncrements = 10; 2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int kFragmentIncrement = 4; 2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int kSizeLimit = kSizeIncrement * kFragmentIncrement; 2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::CompletionCallback callback; 2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CompleteHandler handler; 2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<net::IOBufferWithSize> io_buffers[kNumIncrements]; 2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CallbackList pending_callbacks; 2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t total_bytes_requested = 0; 2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t total_bytes_written = 0; 2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Some implementations of SSLClientSocket may have write-size limits (e.g, 2535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // max 1 TLS record, which is 16k). This test mocks a size limit at 2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // |kSizeIncrement| and calls Write() above and below that limit. It 2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // simulates SSLClientSocket::Write() behavior in only writing up to the size 2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // limit, requiring additional calls for the remaining data to be sent. 2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Socket::Write() (and supporting methods) execute the additional calls as 2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // needed. This test verifies that this inherited implementation does 2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // properly issue additional calls, and that the total amount returned from 2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // all mocked SSLClientSocket::Write() calls is the same as originally 2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // requested. 2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // |ssl_socket_|'s Write() will write at most |kSizeLimit| bytes. The 2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // inherited Socket::Write() will repeatedly call |ssl_socket_|'s Write() 2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // until the entire original request is sent. Socket::Write() will queue any 2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // additional write requests until the current request is complete. A 2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // request is complete when the callback passed to Socket::WriteImpl() is 2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // invoked with an argument equal to the original number of bytes requested 2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // from Socket::Write(). If the callback is invoked with a smaller number, 2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Socket::WriteImpl() will get repeatedly invoked until the sum of the 2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // callbacks' arguments is equal to the original requested amount. 2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(*ssl_socket_, Write(_, _, _)).WillRepeatedly( 2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DoAll(WithArgs<2, 1>(Invoke(&pending_callbacks, &CallbackList::append)), 2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Return(net::ERR_IO_PENDING))); 2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Observe what comes back from Socket::Write() here. 2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(handler, OnComplete(Gt(0))).Times(kNumIncrements); 2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Send out |kNumIncrements| requests, each with a different size. The 2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // last request is the same size as the first, and the ones in the middle 2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // are monotonically increasing from the first. 2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (int i = 0; i < kNumIncrements; i++) { 2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const bool last = i == (kNumIncrements - 1); 2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) io_buffers[i] = new net::IOBufferWithSize(last ? kSizeIncrement 2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : kSizeIncrement * (i + 1)); 2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) total_bytes_requested += io_buffers[i]->size(); 2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Invoke Socket::Write(). This will invoke |ssl_socket_|'s Write(), which 2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // this test mocks out. That mocked Write() is in an asynchronous waiting 2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // state until the passed callback (saved in the EXPECT_CALL for 2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // |ssl_socket_|'s Write()) is invoked. 2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket_->Write( 2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) io_buffers[i].get(), 2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) io_buffers[i]->size(), 2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&CompleteHandler::OnComplete, base::Unretained(&handler))); 2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Invoke callbacks for pending I/Os. These can synchronously invoke more of 2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // |ssl_socket_|'s Write() as needed. The callback checks how much is left 3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // in the request, and then starts issuing any queued Socket::Write() 3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // invocations. 3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while (!pending_callbacks.empty()) { 3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PendingCallback cb = pending_callbacks.front(); 3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pending_callbacks.pop_front(); 3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int amount_written_invocation = std::min(kSizeLimit, cb.second); 3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) total_bytes_written += amount_written_invocation; 3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cb.first.Run(amount_written_invocation); 3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ASSERT_EQ(total_bytes_requested, total_bytes_written) 3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << "There should be exactly as many bytes written as originally " 3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << "requested to Write()."; 3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} // namespace extensions 317