Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1292)

Unified Diff: net/quic/quic_chromium_client_session_test.cc

Issue 1327923002: Migrates QUIC sessions to a new network when old network is (about to be) disconnected. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@home
Patch Set: Rebase. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/quic/quic_chromium_client_session.cc ('k') | net/quic/quic_connection.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/quic/quic_chromium_client_session_test.cc
diff --git a/net/quic/quic_chromium_client_session_test.cc b/net/quic/quic_chromium_client_session_test.cc
index ba831efa0c48428763395b3634873c1f1364bef6..356b69a69efc6b7ceb852635147bc52e0ae772f1 100644
--- a/net/quic/quic_chromium_client_session_test.cc
+++ b/net/quic/quic_chromium_client_session_test.cc
@@ -22,13 +22,19 @@
#include "net/quic/crypto/quic_decrypter.h"
#include "net/quic/crypto/quic_encrypter.h"
#include "net/quic/crypto/quic_server_info.h"
+#include "net/quic/quic_connection_helper.h"
#include "net/quic/quic_crypto_client_stream_factory.h"
+#include "net/quic/quic_default_packet_writer.h"
#include "net/quic/quic_flags.h"
+#include "net/quic/quic_http_utils.h"
#include "net/quic/quic_packet_reader.h"
+#include "net/quic/quic_packet_writer.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/test_tools/crypto_test_utils.h"
+#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
#include "net/quic/test_tools/quic_chromium_client_session_peer.h"
#include "net/quic/test_tools/quic_spdy_session_peer.h"
+#include "net/quic/test_tools/quic_test_packet_maker.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/quic/test_tools/simple_quic_framer.h"
#include "net/socket/socket_test_util.h"
@@ -42,74 +48,106 @@ namespace net {
namespace test {
namespace {
+const IPEndPoint kIpEndPoint(IPAddressNumber(kIPv4AddressSize, 0), 0);
const char kServerHostname[] = "test.example.com";
const uint16_t kServerPort = 443;
+const size_t kMaxReadersPerQuicSession = 5;
+
+class DefaultPacketWriterFactory : public QuicConnection::PacketWriterFactory {
+ public:
+ explicit DefaultPacketWriterFactory(DatagramClientSocket* socket)
+ : socket_(socket) {}
+ ~DefaultPacketWriterFactory() override {}
+
+ QuicPacketWriter* Create(QuicConnection* connection) const override {
+ scoped_ptr<net::QuicDefaultPacketWriter> writer(
+ new net::QuicDefaultPacketWriter(socket_));
+ writer->SetConnection(connection);
+ return writer.release();
+ }
+
+ private:
+ DatagramClientSocket* socket_;
+};
class QuicChromiumClientSessionTest
: public ::testing::TestWithParam<QuicVersion> {
protected:
QuicChromiumClientSessionTest()
: crypto_config_(CryptoTestUtils::ProofVerifierForTesting()),
- connection_(new PacketSavingConnection(&helper_,
- Perspective::IS_CLIENT,
- SupportedVersions(GetParam()))),
- session_(
- connection_,
- GetSocket(),
- /*stream_factory=*/nullptr,
- QuicCryptoClientStreamFactory::GetDefaultFactory(),
- &clock_,
- &transport_security_state_,
- make_scoped_ptr((QuicServerInfo*)nullptr),
- QuicServerId(kServerHostname, kServerPort, PRIVACY_MODE_DISABLED),
- kQuicYieldAfterPacketsRead,
- QuicTime::Delta::FromMilliseconds(
- kQuicYieldAfterDurationMilliseconds),
- /*cert_verify_flags=*/0,
- DefaultQuicConfig(),
- &crypto_config_,
- "CONNECTION_UNKNOWN",
- base::TimeTicks::Now(),
- base::ThreadTaskRunnerHandle::Get().get(),
- /*socket_performance_watcher=*/nullptr,
- &net_log_) {
- session_.Initialize();
+ default_read_(new MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)),
+ socket_data_(
+ new SequencedSocketData(default_read_.get(), 1, nullptr, 0)),
+ random_(0),
+ helper_(base::ThreadTaskRunnerHandle::Get().get(), &clock_, &random_),
+ maker_(GetParam(), 0, &clock_, kServerHostname) {}
+
+ void Initialize() {
+ socket_factory_.AddSocketDataProvider(socket_data_.get());
+ scoped_ptr<DatagramClientSocket> socket =
+ socket_factory_.CreateDatagramClientSocket(DatagramSocket::DEFAULT_BIND,
+ base::Bind(&base::RandInt),
+ &net_log_, NetLog::Source());
+ socket->Connect(kIpEndPoint);
+ DefaultPacketWriterFactory writer_factory(socket.get());
+ QuicConnection* connection = new QuicConnection(
+ 0, kIpEndPoint, &helper_, writer_factory, true, Perspective::IS_CLIENT,
+ SupportedVersions(GetParam()));
+ session_.reset(new QuicChromiumClientSession(
+ connection, std::move(socket),
+ /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
+ &transport_security_state_, make_scoped_ptr((QuicServerInfo*)nullptr),
+ QuicServerId(kServerHostname, kServerPort, PRIVACY_MODE_DISABLED),
+ kQuicYieldAfterPacketsRead,
+ QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds),
+ /*cert_verify_flags=*/0, DefaultQuicConfig(), &crypto_config_,
+ "CONNECTION_UNKNOWN", base::TimeTicks::Now(),
+ base::ThreadTaskRunnerHandle::Get().get(),
+ /*socket_performance_watcher=*/nullptr, &net_log_));
+
+ scoped_refptr<X509Certificate> cert(
+ ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem"));
+ verify_details_.cert_verify_result.verified_cert = cert;
+ verify_details_.cert_verify_result.is_issued_by_known_root = true;
// Advance the time, because timers do not like uninitialized times.
- connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
+ clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
+ session_->Initialize();
+ session_->StartReading();
}
void TearDown() override {
- session_.CloseSessionOnError(ERR_ABORTED, QUIC_INTERNAL_ERROR);
+ session_->CloseSessionOnError(ERR_ABORTED, QUIC_INTERNAL_ERROR);
}
- scoped_ptr<DatagramClientSocket> GetSocket() {
- socket_factory_.AddSocketDataProvider(&socket_data_);
- return socket_factory_.CreateDatagramClientSocket(
- DatagramSocket::DEFAULT_BIND, base::Bind(&base::RandInt), &net_log_,
- NetLog::Source());
+ void CompleteCryptoHandshake() {
+ ASSERT_EQ(OK, session_->CryptoConnect(false, callback_.callback()));
}
- void CompleteCryptoHandshake() {
- ASSERT_EQ(ERR_IO_PENDING,
- session_.CryptoConnect(false, callback_.callback()));
- CryptoTestUtils::FakeServerOptions server_options;
- CryptoTestUtils::HandshakeWithFakeServer(
- &helper_, connection_, session_.GetCryptoStream(), server_options);
- ASSERT_EQ(OK, callback_.WaitForResult());
+ QuicPacketWriter* CreateQuicPacketWriter(DatagramClientSocket* socket,
+ QuicConnection* connection) const {
+ scoped_ptr<QuicDefaultPacketWriter> writer(
+ new QuicDefaultPacketWriter(socket));
+ writer->SetConnection(connection);
+ return writer.release();
}
- MockConnectionHelper helper_;
QuicCryptoClientConfig crypto_config_;
- PacketSavingConnection* connection_;
TestNetLog net_log_;
+ BoundTestNetLog bound_net_log_;
MockClientSocketFactory socket_factory_;
- StaticSocketDataProvider socket_data_;
- TransportSecurityState transport_security_state_;
- QuicChromiumClientSession session_;
+ scoped_ptr<MockRead> default_read_;
+ scoped_ptr<SequencedSocketData> socket_data_;
MockClock clock_;
MockRandom random_;
+ QuicConnectionHelper helper_;
+ scoped_ptr<DefaultPacketWriterFactory> writer_factory_;
+ TransportSecurityState transport_security_state_;
+ MockCryptoClientStreamFactory crypto_client_stream_factory_;
+ scoped_ptr<QuicChromiumClientSession> session_;
QuicConnectionVisitorInterface* visitor_;
TestCompletionCallback callback_;
+ QuicTestPacketMaker maker_;
+ ProofVerifyDetailsChromium verify_details_;
};
INSTANTIATE_TEST_CASE_P(Tests,
@@ -117,43 +155,62 @@ INSTANTIATE_TEST_CASE_P(Tests,
::testing::ValuesIn(QuicSupportedVersions()));
TEST_P(QuicChromiumClientSessionTest, CryptoConnect) {
+ Initialize();
CompleteCryptoHandshake();
}
TEST_P(QuicChromiumClientSessionTest, MaxNumStreams) {
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ scoped_ptr<QuicEncryptedPacket> client_rst(maker_.MakeRstPacket(
+ 1, true, kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT));
+ MockWrite writes[] = {
+ MockWrite(ASYNC, client_rst->data(), client_rst->length(), 1)};
+ socket_data_.reset(new SequencedSocketData(reads, arraysize(reads), writes,
+ arraysize(writes)));
+
+ Initialize();
CompleteCryptoHandshake();
+ const size_t kMaxOpenStreams = session_->get_max_open_streams();
std::vector<QuicReliableClientStream*> streams;
- for (size_t i = 0; i < kDefaultMaxStreamsPerConnection; i++) {
+ for (size_t i = 0; i < kMaxOpenStreams; i++) {
QuicReliableClientStream* stream =
- session_.CreateOutgoingDynamicStream(kDefaultPriority);
+ session_->CreateOutgoingDynamicStream(kDefaultPriority);
EXPECT_TRUE(stream);
streams.push_back(stream);
}
- EXPECT_FALSE(session_.CreateOutgoingDynamicStream(kDefaultPriority));
+ EXPECT_FALSE(session_->CreateOutgoingDynamicStream(kDefaultPriority));
- EXPECT_EQ(kDefaultMaxStreamsPerConnection,
- session_.GetNumOpenOutgoingStreams());
+ EXPECT_EQ(kMaxOpenStreams, session_->GetNumOpenOutgoingStreams());
// Close a stream and ensure I can now open a new one.
QuicStreamId stream_id = streams[0]->id();
- session_.CloseStream(stream_id);
+ session_->CloseStream(stream_id);
- EXPECT_FALSE(session_.CreateOutgoingDynamicStream(kDefaultPriority));
+ EXPECT_FALSE(session_->CreateOutgoingDynamicStream(kDefaultPriority));
QuicRstStreamFrame rst1(stream_id, QUIC_STREAM_NO_ERROR, 0);
- session_.OnRstStream(rst1);
- EXPECT_EQ(kDefaultMaxStreamsPerConnection - 1,
- session_.GetNumOpenOutgoingStreams());
- EXPECT_TRUE(session_.CreateOutgoingDynamicStream(kDefaultPriority));
+ session_->OnRstStream(rst1);
+ EXPECT_EQ(kMaxOpenStreams - 1, session_->GetNumOpenOutgoingStreams());
+ EXPECT_TRUE(session_->CreateOutgoingDynamicStream(kDefaultPriority));
}
TEST_P(QuicChromiumClientSessionTest, MaxNumStreamsViaRequest) {
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ scoped_ptr<QuicEncryptedPacket> client_rst(maker_.MakeRstPacket(
+ 1, true, kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT));
+ MockWrite writes[] = {
+ MockWrite(ASYNC, client_rst->data(), client_rst->length(), 1)};
+ socket_data_.reset(new SequencedSocketData(reads, arraysize(reads), writes,
+ arraysize(writes)));
+
+ Initialize();
CompleteCryptoHandshake();
+ const size_t kMaxOpenStreams = session_->get_max_open_streams();
std::vector<QuicReliableClientStream*> streams;
- for (size_t i = 0; i < kDefaultMaxStreamsPerConnection; i++) {
+ for (size_t i = 0; i < kMaxOpenStreams; i++) {
QuicReliableClientStream* stream =
- session_.CreateOutgoingDynamicStream(kDefaultPriority);
+ session_->CreateOutgoingDynamicStream(kDefaultPriority);
EXPECT_TRUE(stream);
streams.push_back(stream);
}
@@ -162,30 +219,32 @@ TEST_P(QuicChromiumClientSessionTest, MaxNumStreamsViaRequest) {
QuicChromiumClientSession::StreamRequest stream_request;
TestCompletionCallback callback;
ASSERT_EQ(ERR_IO_PENDING,
- stream_request.StartRequest(session_.GetWeakPtr(), &stream,
+ stream_request.StartRequest(session_->GetWeakPtr(), &stream,
callback.callback()));
// Close a stream and ensure I can now open a new one.
QuicStreamId stream_id = streams[0]->id();
- session_.CloseStream(stream_id);
+ session_->CloseStream(stream_id);
QuicRstStreamFrame rst1(stream_id, QUIC_STREAM_NO_ERROR, 0);
- session_.OnRstStream(rst1);
+ session_->OnRstStream(rst1);
ASSERT_TRUE(callback.have_result());
EXPECT_EQ(OK, callback.WaitForResult());
EXPECT_TRUE(stream != nullptr);
}
TEST_P(QuicChromiumClientSessionTest, GoAwayReceived) {
+ Initialize();
CompleteCryptoHandshake();
// After receiving a GoAway, I should no longer be able to create outgoing
// streams.
- session_.connection()->OnGoAwayFrame(
+ session_->connection()->OnGoAwayFrame(
QuicGoAwayFrame(QUIC_PEER_GOING_AWAY, 1u, "Going away."));
- EXPECT_EQ(nullptr, session_.CreateOutgoingDynamicStream(kDefaultPriority));
+ EXPECT_EQ(nullptr, session_->CreateOutgoingDynamicStream(kDefaultPriority));
}
TEST_P(QuicChromiumClientSessionTest, CanPool) {
+ Initialize();
// Load a cert that is valid for:
// www.example.org
// mail.example.org
@@ -197,16 +256,17 @@ TEST_P(QuicChromiumClientSessionTest, CanPool) {
ASSERT_TRUE(details.cert_verify_result.verified_cert.get());
CompleteCryptoHandshake();
- session_.OnProofVerifyDetailsAvailable(details);
+ session_->OnProofVerifyDetailsAvailable(details);
- EXPECT_TRUE(session_.CanPool("www.example.org", PRIVACY_MODE_DISABLED));
- EXPECT_FALSE(session_.CanPool("www.example.org", PRIVACY_MODE_ENABLED));
- EXPECT_TRUE(session_.CanPool("mail.example.org", PRIVACY_MODE_DISABLED));
- EXPECT_TRUE(session_.CanPool("mail.example.com", PRIVACY_MODE_DISABLED));
- EXPECT_FALSE(session_.CanPool("mail.google.com", PRIVACY_MODE_DISABLED));
+ EXPECT_TRUE(session_->CanPool("www.example.org", PRIVACY_MODE_DISABLED));
+ EXPECT_FALSE(session_->CanPool("www.example.org", PRIVACY_MODE_ENABLED));
+ EXPECT_TRUE(session_->CanPool("mail.example.org", PRIVACY_MODE_DISABLED));
+ EXPECT_TRUE(session_->CanPool("mail.example.com", PRIVACY_MODE_DISABLED));
+ EXPECT_FALSE(session_->CanPool("mail.google.com", PRIVACY_MODE_DISABLED));
}
TEST_P(QuicChromiumClientSessionTest, ConnectionPooledWithTlsChannelId) {
+ Initialize();
// Load a cert that is valid for:
// www.example.org
// mail.example.org
@@ -218,17 +278,19 @@ TEST_P(QuicChromiumClientSessionTest, ConnectionPooledWithTlsChannelId) {
ASSERT_TRUE(details.cert_verify_result.verified_cert.get());
CompleteCryptoHandshake();
- session_.OnProofVerifyDetailsAvailable(details);
- QuicChromiumClientSessionPeer::SetHostname(&session_, "www.example.org");
- QuicChromiumClientSessionPeer::SetChannelIDSent(&session_, true);
-
- EXPECT_TRUE(session_.CanPool("www.example.org", PRIVACY_MODE_DISABLED));
- EXPECT_TRUE(session_.CanPool("mail.example.org", PRIVACY_MODE_DISABLED));
- EXPECT_FALSE(session_.CanPool("mail.example.com", PRIVACY_MODE_DISABLED));
- EXPECT_FALSE(session_.CanPool("mail.google.com", PRIVACY_MODE_DISABLED));
+ session_->OnProofVerifyDetailsAvailable(details);
+ QuicChromiumClientSessionPeer::SetHostname(session_.get(), "www.example.org");
+ QuicChromiumClientSessionPeer::SetChannelIDSent(session_.get(), true);
+
+ EXPECT_TRUE(session_->CanPool("www.example.org", PRIVACY_MODE_DISABLED));
+ EXPECT_TRUE(session_->CanPool("mail.example.org", PRIVACY_MODE_DISABLED));
+ EXPECT_FALSE(session_->CanPool("mail.example.com", PRIVACY_MODE_DISABLED));
+ EXPECT_FALSE(session_->CanPool("mail.google.com", PRIVACY_MODE_DISABLED));
}
TEST_P(QuicChromiumClientSessionTest, ConnectionNotPooledWithDifferentPin) {
+ Initialize();
+
uint8_t primary_pin = 1;
uint8_t backup_pin = 2;
uint8_t bad_pin = 3;
@@ -245,14 +307,16 @@ TEST_P(QuicChromiumClientSessionTest, ConnectionNotPooledWithDifferentPin) {
ASSERT_TRUE(details.cert_verify_result.verified_cert.get());
CompleteCryptoHandshake();
- session_.OnProofVerifyDetailsAvailable(details);
- QuicChromiumClientSessionPeer::SetHostname(&session_, "www.example.org");
- QuicChromiumClientSessionPeer::SetChannelIDSent(&session_, true);
+ session_->OnProofVerifyDetailsAvailable(details);
+ QuicChromiumClientSessionPeer::SetHostname(session_.get(), "www.example.org");
+ QuicChromiumClientSessionPeer::SetChannelIDSent(session_.get(), true);
- EXPECT_FALSE(session_.CanPool("mail.example.org", PRIVACY_MODE_DISABLED));
+ EXPECT_FALSE(session_->CanPool("mail.example.org", PRIVACY_MODE_DISABLED));
}
TEST_P(QuicChromiumClientSessionTest, ConnectionPooledWithMatchingPin) {
+ Initialize();
+
uint8_t primary_pin = 1;
uint8_t backup_pin = 2;
AddPin(&transport_security_state_, "mail.example.org", primary_pin,
@@ -268,11 +332,208 @@ TEST_P(QuicChromiumClientSessionTest, ConnectionPooledWithMatchingPin) {
ASSERT_TRUE(details.cert_verify_result.verified_cert.get());
CompleteCryptoHandshake();
- session_.OnProofVerifyDetailsAvailable(details);
- QuicChromiumClientSessionPeer::SetHostname(&session_, "www.example.org");
- QuicChromiumClientSessionPeer::SetChannelIDSent(&session_, true);
+ session_->OnProofVerifyDetailsAvailable(details);
+ QuicChromiumClientSessionPeer::SetHostname(session_.get(), "www.example.org");
+ QuicChromiumClientSessionPeer::SetChannelIDSent(session_.get(), true);
+
+ EXPECT_TRUE(session_->CanPool("mail.example.org", PRIVACY_MODE_DISABLED));
+}
+
+TEST_P(QuicChromiumClientSessionTest, MigrateToSocket) {
+ Initialize();
+ CompleteCryptoHandshake();
+
+ char data[] = "ABCD";
+ scoped_ptr<QuicEncryptedPacket> ping(
+ maker_.MakePingPacket(1, /*include_version=*/false));
+ scoped_ptr<QuicEncryptedPacket> ack_and_data_out(maker_.MakeAckAndDataPacket(
+ 2, false, 5, 1, 1, false, 0, StringPiece(data)));
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ping->data(), ping->length(), 0),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING, 1)};
+ MockWrite writes[] = {MockWrite(SYNCHRONOUS, ping->data(), ping->length(), 2),
+ MockWrite(SYNCHRONOUS, ack_and_data_out->data(),
+ ack_and_data_out->length(), 3)};
+ StaticSocketDataProvider socket_data(reads, arraysize(reads), writes,
+ arraysize(writes));
+ socket_factory_.AddSocketDataProvider(&socket_data);
+
+ // Create connected socket.
+ scoped_ptr<DatagramClientSocket> new_socket =
+ socket_factory_.CreateDatagramClientSocket(DatagramSocket::DEFAULT_BIND,
+ base::Bind(&base::RandInt),
+ &net_log_, NetLog::Source());
+ EXPECT_EQ(OK, new_socket->Connect(kIpEndPoint));
+
+ // Create reader and writer.
+ scoped_ptr<QuicPacketReader> new_reader(new QuicPacketReader(
+ new_socket.get(), &clock_, session_.get(), kQuicYieldAfterPacketsRead,
+ QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds),
+ bound_net_log_.bound()));
+ scoped_ptr<QuicPacketWriter> new_writer(
+ CreateQuicPacketWriter(new_socket.get(), session_->connection()));
+
+ // Migrate session.
+ EXPECT_TRUE(session_->MigrateToSocket(
+ std::move(new_socket), std::move(new_reader), std::move(new_writer)));
+
+ // Write data to session.
+ struct iovec iov[1];
+ iov[0].iov_base = data;
+ iov[0].iov_len = 4;
+ session_->WritevData(5, QuicIOVector(iov, arraysize(iov), 4), 0, false,
+ MAY_FEC_PROTECT, nullptr);
+
+ EXPECT_TRUE(socket_data.AllReadDataConsumed());
+ EXPECT_TRUE(socket_data.AllWriteDataConsumed());
+}
+
+TEST_P(QuicChromiumClientSessionTest, MigrateToSocketMaxReaders) {
+ Initialize();
+ CompleteCryptoHandshake();
+
+ for (size_t i = 0; i < kMaxReadersPerQuicSession; ++i) {
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 1)};
+ scoped_ptr<QuicEncryptedPacket> ping_out(
+ maker_.MakePingPacket(i + 1, /*include_version=*/true));
+ MockWrite writes[] = {
+ MockWrite(SYNCHRONOUS, ping_out->data(), ping_out->length(), i + 2)};
+ StaticSocketDataProvider socket_data(reads, arraysize(reads), writes,
+ arraysize(writes));
+ socket_factory_.AddSocketDataProvider(&socket_data);
+
+ // Create connected socket.
+ scoped_ptr<DatagramClientSocket> new_socket =
+ socket_factory_.CreateDatagramClientSocket(DatagramSocket::DEFAULT_BIND,
+ base::Bind(&base::RandInt),
+ &net_log_, NetLog::Source());
+ EXPECT_EQ(OK, new_socket->Connect(kIpEndPoint));
+
+ // Create reader and writer.
+ scoped_ptr<QuicPacketReader> new_reader(new QuicPacketReader(
+ new_socket.get(), &clock_, session_.get(), kQuicYieldAfterPacketsRead,
+ QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds),
+ bound_net_log_.bound()));
+ scoped_ptr<QuicPacketWriter> new_writer(
+ CreateQuicPacketWriter(new_socket.get(), session_->connection()));
+
+ // Migrate session.
+ if (i < kMaxReadersPerQuicSession - 1) {
+ EXPECT_TRUE(session_->MigrateToSocket(
+ std::move(new_socket), std::move(new_reader), std::move(new_writer)));
+ EXPECT_TRUE(socket_data.AllReadDataConsumed());
+ EXPECT_TRUE(socket_data.AllWriteDataConsumed());
+ } else {
+ // Max readers exceeded.
+ EXPECT_FALSE(session_->MigrateToSocket(
+ std::move(new_socket), std::move(new_reader), std::move(new_writer)));
+
+ EXPECT_FALSE(socket_data.AllReadDataConsumed());
+ EXPECT_FALSE(socket_data.AllWriteDataConsumed());
+ }
+ }
+}
+
+TEST_P(QuicChromiumClientSessionTest, MigrateToSocketReadError) {
+ scoped_ptr<QuicEncryptedPacket> ping(
+ maker_.MakePingPacket(1, /*include_version=*/true));
+ MockRead old_reads[] = {
+ MockRead(SYNCHRONOUS, ping->data(), ping->length(), 0),
+ MockRead(ASYNC, ERR_IO_PENDING, 1), // causes reading to pause.
+ MockRead(ASYNC, ERR_NETWORK_CHANGED, 2)};
+ socket_data_.reset(
+ new SequencedSocketData(old_reads, arraysize(old_reads), nullptr, 0));
+ Initialize();
+ CompleteCryptoHandshake();
+
+ MockWrite writes[] = {
+ MockWrite(SYNCHRONOUS, ping->data(), ping->length(), 1)};
+ MockRead new_reads[] = {
+ MockRead(SYNCHRONOUS, ping->data(), ping->length(), 0),
+ MockRead(ASYNC, ERR_IO_PENDING, 2), // pause reading.
+ MockRead(ASYNC, ping->data(), ping->length(), 3),
+ MockRead(ASYNC, ERR_IO_PENDING, 4), // pause reading
+ MockRead(ASYNC, ERR_NETWORK_CHANGED, 5)};
+ SequencedSocketData new_socket_data(new_reads, arraysize(new_reads), writes,
+ arraysize(writes));
+ socket_factory_.AddSocketDataProvider(&new_socket_data);
+
+ // Create connected socket.
+ scoped_ptr<DatagramClientSocket> new_socket =
+ socket_factory_.CreateDatagramClientSocket(DatagramSocket::DEFAULT_BIND,
+ base::Bind(&base::RandInt),
+ &net_log_, NetLog::Source());
+ EXPECT_EQ(OK, new_socket->Connect(kIpEndPoint));
+
+ // Create reader and writer.
+ scoped_ptr<QuicPacketReader> new_reader(new QuicPacketReader(
+ new_socket.get(), &clock_, session_.get(), kQuicYieldAfterPacketsRead,
+ QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds),
+ bound_net_log_.bound()));
+ scoped_ptr<QuicPacketWriter> new_writer(
+ CreateQuicPacketWriter(new_socket.get(), session_->connection()));
+
+ // Store old socket and migrate session.
+ EXPECT_TRUE(session_->MigrateToSocket(
+ std::move(new_socket), std::move(new_reader), std::move(new_writer)));
+
+ // Read error on old socket does not impact session.
+ EXPECT_TRUE(socket_data_->IsPaused());
+ socket_data_->Resume();
+ EXPECT_TRUE(session_->connection()->connected());
+ EXPECT_TRUE(new_socket_data.IsPaused());
+ new_socket_data.Resume();
+
+ // Read error on new socket causes session close.
+ EXPECT_TRUE(new_socket_data.IsPaused());
+ EXPECT_TRUE(session_->connection()->connected());
+ new_socket_data.Resume();
+ EXPECT_FALSE(session_->connection()->connected());
+
+ EXPECT_TRUE(socket_data_->AllReadDataConsumed());
+ EXPECT_TRUE(socket_data_->AllWriteDataConsumed());
+ EXPECT_TRUE(new_socket_data.AllReadDataConsumed());
+ EXPECT_TRUE(new_socket_data.AllWriteDataConsumed());
+}
+
+TEST_P(QuicChromiumClientSessionTest, MigrateToSocketWriteError) {
+ Initialize();
+ CompleteCryptoHandshake();
- EXPECT_TRUE(session_.CanPool("mail.example.org", PRIVACY_MODE_DISABLED));
+ scoped_ptr<QuicEncryptedPacket> ping(
+ maker_.MakePingPacket(1, /*include_version=*/true));
+ MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+ MockWrite writes[] = {MockWrite(SYNCHRONOUS, ping->data(), ping->length(), 1),
+ MockWrite(SYNCHRONOUS, ERR_FAILED, 2)};
+ SequencedSocketData socket_data(reads, arraysize(reads), writes,
+ arraysize(writes));
+ socket_factory_.AddSocketDataProvider(&socket_data);
+
+ // Create connected socket.
+ scoped_ptr<DatagramClientSocket> new_socket =
+ socket_factory_.CreateDatagramClientSocket(DatagramSocket::DEFAULT_BIND,
+ base::Bind(&base::RandInt),
+ &net_log_, NetLog::Source());
+ EXPECT_EQ(OK, new_socket->Connect(kIpEndPoint));
+
+ // Create reader and writer.
+ scoped_ptr<QuicPacketReader> new_reader(new QuicPacketReader(
+ new_socket.get(), &clock_, session_.get(), kQuicYieldAfterPacketsRead,
+ QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds),
+ bound_net_log_.bound()));
+ scoped_ptr<QuicPacketWriter> new_writer(
+ CreateQuicPacketWriter(new_socket.get(), session_->connection()));
+
+ // Migrate session.
+ EXPECT_TRUE(session_->MigrateToSocket(
+ std::move(new_socket), std::move(new_reader), std::move(new_writer)));
+
+ // Write error on new socket causes session close.
+ EXPECT_TRUE(session_->connection()->connected());
+ session_->connection()->SendPing();
+ EXPECT_FALSE(session_->connection()->connected());
+
+ EXPECT_TRUE(socket_data.AllReadDataConsumed());
+ EXPECT_TRUE(socket_data.AllWriteDataConsumed());
}
} // namespace
« no previous file with comments | « net/quic/quic_chromium_client_session.cc ('k') | net/quic/quic_connection.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698