|  | // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h" | 
|  |  | 
|  | #include <algorithm> | 
|  | #include <memory> | 
|  |  | 
|  | #include "third_party/boringssl/src/include/openssl/sha.h" | 
|  | #include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h" | 
|  | #include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h" | 
|  | #include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h" | 
|  | #include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h" | 
|  | #include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h" | 
|  | #include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h" | 
|  | #include "net/third_party/quiche/src/quic/core/quic_data_writer.h" | 
|  | #include "net/third_party/quiche/src/quic/core/quic_framer.h" | 
|  | #include "net/third_party/quiche/src/quic/core/quic_packet_creator.h" | 
|  | #include "net/third_party/quiche/src/quic/core/quic_utils.h" | 
|  | #include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h" | 
|  | #include "net/third_party/quiche/src/quic/platform/api/quic_endian.h" | 
|  | #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" | 
|  | #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h" | 
|  | #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" | 
|  | #include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h" | 
|  | #include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h" | 
|  | #include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h" | 
|  | #include "net/third_party/quiche/src/spdy/core/spdy_frame_builder.h" | 
|  |  | 
|  | using testing::_; | 
|  | using testing::Invoke; | 
|  |  | 
|  | namespace quic { | 
|  | namespace test { | 
|  |  | 
|  | QuicConnectionId TestConnectionId() { | 
|  | // Chosen by fair dice roll. | 
|  | // Guaranteed to be random. | 
|  | return TestConnectionId(42); | 
|  | } | 
|  |  | 
|  | QuicConnectionId TestConnectionId(uint64_t connection_number) { | 
|  | const uint64_t connection_id64_net = | 
|  | QuicEndian::HostToNet64(connection_number); | 
|  | return QuicConnectionId(reinterpret_cast<const char*>(&connection_id64_net), | 
|  | sizeof(connection_id64_net)); | 
|  | } | 
|  |  | 
|  | uint64_t TestConnectionIdToUInt64(QuicConnectionId connection_id) { | 
|  | DCHECK_EQ(connection_id.length(), kQuicDefaultConnectionIdLength); | 
|  | uint64_t connection_id64_net = 0; | 
|  | memcpy(&connection_id64_net, connection_id.data(), | 
|  | std::min<size_t>(static_cast<size_t>(connection_id.length()), | 
|  | sizeof(connection_id64_net))); | 
|  | return QuicEndian::NetToHost64(connection_id64_net); | 
|  | } | 
|  |  | 
|  | QuicAckFrame InitAckFrame(const std::vector<QuicAckBlock>& ack_blocks) { | 
|  | DCHECK_GT(ack_blocks.size(), 0u); | 
|  |  | 
|  | QuicAckFrame ack; | 
|  | QuicPacketNumber end_of_previous_block(1); | 
|  | for (const QuicAckBlock& block : ack_blocks) { | 
|  | DCHECK_GE(block.start, end_of_previous_block); | 
|  | DCHECK_GT(block.limit, block.start); | 
|  | ack.packets.AddRange(block.start, block.limit); | 
|  | end_of_previous_block = block.limit; | 
|  | } | 
|  |  | 
|  | ack.largest_acked = ack.packets.Max(); | 
|  |  | 
|  | return ack; | 
|  | } | 
|  |  | 
|  | QuicAckFrame InitAckFrame(uint64_t largest_acked) { | 
|  | return InitAckFrame(QuicPacketNumber(largest_acked)); | 
|  | } | 
|  |  | 
|  | QuicAckFrame InitAckFrame(QuicPacketNumber largest_acked) { | 
|  | return InitAckFrame({{QuicPacketNumber(1), largest_acked + 1}}); | 
|  | } | 
|  |  | 
|  | QuicAckFrame MakeAckFrameWithAckBlocks(size_t num_ack_blocks, | 
|  | uint64_t least_unacked) { | 
|  | QuicAckFrame ack; | 
|  | ack.largest_acked = QuicPacketNumber(2 * num_ack_blocks + least_unacked); | 
|  | // Add enough received packets to get num_ack_blocks ack blocks. | 
|  | for (QuicPacketNumber i = QuicPacketNumber(2); | 
|  | i < QuicPacketNumber(2 * num_ack_blocks + 1); i += 2) { | 
|  | ack.packets.Add(i + least_unacked); | 
|  | } | 
|  | return ack; | 
|  | } | 
|  |  | 
|  | std::unique_ptr<QuicPacket> BuildUnsizedDataPacket( | 
|  | QuicFramer* framer, | 
|  | const QuicPacketHeader& header, | 
|  | const QuicFrames& frames) { | 
|  | const size_t max_plaintext_size = framer->GetMaxPlaintextSize(kMaxPacketSize); | 
|  | size_t packet_size = GetPacketHeaderSize(framer->transport_version(), header); | 
|  | for (size_t i = 0; i < frames.size(); ++i) { | 
|  | DCHECK_LE(packet_size, max_plaintext_size); | 
|  | bool first_frame = i == 0; | 
|  | bool last_frame = i == frames.size() - 1; | 
|  | const size_t frame_size = framer->GetSerializedFrameLength( | 
|  | frames[i], max_plaintext_size - packet_size, first_frame, last_frame, | 
|  | header.packet_number_length); | 
|  | DCHECK(frame_size); | 
|  | packet_size += frame_size; | 
|  | } | 
|  | return BuildUnsizedDataPacket(framer, header, frames, packet_size); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<QuicPacket> BuildUnsizedDataPacket( | 
|  | QuicFramer* framer, | 
|  | const QuicPacketHeader& header, | 
|  | const QuicFrames& frames, | 
|  | size_t packet_size) { | 
|  | char* buffer = new char[packet_size]; | 
|  | size_t length = framer->BuildDataPacket(header, frames, buffer, packet_size, | 
|  | ENCRYPTION_NONE); | 
|  | DCHECK_NE(0u, length); | 
|  | // Re-construct the data packet with data ownership. | 
|  | return QuicMakeUnique<QuicPacket>( | 
|  | buffer, length, /* owns_buffer */ true, | 
|  | GetIncludedDestinationConnectionIdLength(header), | 
|  | GetIncludedSourceConnectionIdLength(header), header.version_flag, | 
|  | header.nonce != nullptr, header.packet_number_length, | 
|  | header.retry_token_length_length, header.retry_token.length(), | 
|  | header.length_length); | 
|  | } | 
|  |  | 
|  | QuicString Sha1Hash(QuicStringPiece data) { | 
|  | char buffer[SHA_DIGEST_LENGTH]; | 
|  | SHA1(reinterpret_cast<const uint8_t*>(data.data()), data.size(), | 
|  | reinterpret_cast<uint8_t*>(buffer)); | 
|  | return QuicString(buffer, QUIC_ARRAYSIZE(buffer)); | 
|  | } | 
|  |  | 
|  | uint64_t SimpleRandom::RandUint64() { | 
|  | QuicString hash = | 
|  | Sha1Hash(QuicStringPiece(reinterpret_cast<char*>(&seed_), sizeof(seed_))); | 
|  | DCHECK_EQ(static_cast<size_t>(SHA_DIGEST_LENGTH), hash.length()); | 
|  | memcpy(&seed_, hash.data(), sizeof(seed_)); | 
|  | return seed_; | 
|  | } | 
|  |  | 
|  | void SimpleRandom::RandBytes(void* data, size_t len) { | 
|  | uint8_t* real_data = static_cast<uint8_t*>(data); | 
|  | for (size_t offset = 0; offset < len; offset++) { | 
|  | real_data[offset] = RandUint64() & 0xff; | 
|  | } | 
|  | } | 
|  |  | 
|  | MockFramerVisitor::MockFramerVisitor() { | 
|  | // By default, we want to accept packets. | 
|  | ON_CALL(*this, OnProtocolVersionMismatch(_, _)) | 
|  | .WillByDefault(testing::Return(false)); | 
|  |  | 
|  | // By default, we want to accept packets. | 
|  | ON_CALL(*this, OnUnauthenticatedHeader(_)) | 
|  | .WillByDefault(testing::Return(true)); | 
|  |  | 
|  | ON_CALL(*this, OnUnauthenticatedPublicHeader(_)) | 
|  | .WillByDefault(testing::Return(true)); | 
|  |  | 
|  | ON_CALL(*this, OnPacketHeader(_)).WillByDefault(testing::Return(true)); | 
|  |  | 
|  | ON_CALL(*this, OnStreamFrame(_)).WillByDefault(testing::Return(true)); | 
|  |  | 
|  | ON_CALL(*this, OnCryptoFrame(_)).WillByDefault(testing::Return(true)); | 
|  |  | 
|  | ON_CALL(*this, OnStopWaitingFrame(_)).WillByDefault(testing::Return(true)); | 
|  |  | 
|  | ON_CALL(*this, OnPaddingFrame(_)).WillByDefault(testing::Return(true)); | 
|  |  | 
|  | ON_CALL(*this, OnPingFrame(_)).WillByDefault(testing::Return(true)); | 
|  |  | 
|  | ON_CALL(*this, OnRstStreamFrame(_)).WillByDefault(testing::Return(true)); | 
|  |  | 
|  | ON_CALL(*this, OnConnectionCloseFrame(_)) | 
|  | .WillByDefault(testing::Return(true)); | 
|  |  | 
|  | ON_CALL(*this, OnApplicationCloseFrame(_)) | 
|  | .WillByDefault(testing::Return(true)); | 
|  |  | 
|  | ON_CALL(*this, OnStopSendingFrame(_)).WillByDefault(testing::Return(true)); | 
|  |  | 
|  | ON_CALL(*this, OnPathChallengeFrame(_)).WillByDefault(testing::Return(true)); | 
|  |  | 
|  | ON_CALL(*this, OnPathResponseFrame(_)).WillByDefault(testing::Return(true)); | 
|  |  | 
|  | ON_CALL(*this, OnGoAwayFrame(_)).WillByDefault(testing::Return(true)); | 
|  | ON_CALL(*this, OnMaxStreamIdFrame(_)).WillByDefault(testing::Return(true)); | 
|  | ON_CALL(*this, OnStreamIdBlockedFrame(_)) | 
|  | .WillByDefault(testing::Return(true)); | 
|  | } | 
|  |  | 
|  | MockFramerVisitor::~MockFramerVisitor() {} | 
|  |  | 
|  | bool NoOpFramerVisitor::OnProtocolVersionMismatch(ParsedQuicVersion version, | 
|  | PacketHeaderFormat form) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnUnauthenticatedPublicHeader( | 
|  | const QuicPacketHeader& header) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnUnauthenticatedHeader( | 
|  | const QuicPacketHeader& header) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnPacketHeader(const QuicPacketHeader& header) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void NoOpFramerVisitor::OnCoalescedPacket(const QuicEncryptedPacket& packet) {} | 
|  |  | 
|  | bool NoOpFramerVisitor::OnStreamFrame(const QuicStreamFrame& frame) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnCryptoFrame(const QuicCryptoFrame& frame) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnAckFrameStart(QuicPacketNumber largest_acked, | 
|  | QuicTime::Delta ack_delay_time) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnAckRange(QuicPacketNumber start, | 
|  | QuicPacketNumber end) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnAckTimestamp(QuicPacketNumber packet_number, | 
|  | QuicTime timestamp) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnAckFrameEnd(QuicPacketNumber start) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnStopWaitingFrame(const QuicStopWaitingFrame& frame) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnPaddingFrame(const QuicPaddingFrame& frame) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnPingFrame(const QuicPingFrame& frame) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnRstStreamFrame(const QuicRstStreamFrame& frame) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnConnectionCloseFrame( | 
|  | const QuicConnectionCloseFrame& frame) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnApplicationCloseFrame( | 
|  | const QuicApplicationCloseFrame& frame) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnNewConnectionIdFrame( | 
|  | const QuicNewConnectionIdFrame& frame) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnRetireConnectionIdFrame( | 
|  | const QuicRetireConnectionIdFrame& frame) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnNewTokenFrame(const QuicNewTokenFrame& frame) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnStopSendingFrame(const QuicStopSendingFrame& frame) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnPathChallengeFrame( | 
|  | const QuicPathChallengeFrame& frame) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnPathResponseFrame( | 
|  | const QuicPathResponseFrame& frame) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnGoAwayFrame(const QuicGoAwayFrame& frame) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnStreamIdBlockedFrame( | 
|  | const QuicStreamIdBlockedFrame& frame) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnWindowUpdateFrame( | 
|  | const QuicWindowUpdateFrame& frame) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnBlockedFrame(const QuicBlockedFrame& frame) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::OnMessageFrame(const QuicMessageFrame& frame) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NoOpFramerVisitor::IsValidStatelessResetToken(QuicUint128 token) const { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | MockQuicConnectionVisitor::MockQuicConnectionVisitor() {} | 
|  |  | 
|  | MockQuicConnectionVisitor::~MockQuicConnectionVisitor() {} | 
|  |  | 
|  | MockQuicConnectionHelper::MockQuicConnectionHelper() {} | 
|  |  | 
|  | MockQuicConnectionHelper::~MockQuicConnectionHelper() {} | 
|  |  | 
|  | const QuicClock* MockQuicConnectionHelper::GetClock() const { | 
|  | return &clock_; | 
|  | } | 
|  |  | 
|  | QuicRandom* MockQuicConnectionHelper::GetRandomGenerator() { | 
|  | return &random_generator_; | 
|  | } | 
|  |  | 
|  | QuicAlarm* MockAlarmFactory::CreateAlarm(QuicAlarm::Delegate* delegate) { | 
|  | return new MockAlarmFactory::TestAlarm( | 
|  | QuicArenaScopedPtr<QuicAlarm::Delegate>(delegate)); | 
|  | } | 
|  |  | 
|  | QuicArenaScopedPtr<QuicAlarm> MockAlarmFactory::CreateAlarm( | 
|  | QuicArenaScopedPtr<QuicAlarm::Delegate> delegate, | 
|  | QuicConnectionArena* arena) { | 
|  | if (arena != nullptr) { | 
|  | return arena->New<TestAlarm>(std::move(delegate)); | 
|  | } else { | 
|  | return QuicArenaScopedPtr<TestAlarm>(new TestAlarm(std::move(delegate))); | 
|  | } | 
|  | } | 
|  |  | 
|  | QuicBufferAllocator* MockQuicConnectionHelper::GetStreamSendBufferAllocator() { | 
|  | return &buffer_allocator_; | 
|  | } | 
|  |  | 
|  | void MockQuicConnectionHelper::AdvanceTime(QuicTime::Delta delta) { | 
|  | clock_.AdvanceTime(delta); | 
|  | } | 
|  |  | 
|  | MockQuicConnection::MockQuicConnection(MockQuicConnectionHelper* helper, | 
|  | MockAlarmFactory* alarm_factory, | 
|  | Perspective perspective) | 
|  | : MockQuicConnection(TestConnectionId(), | 
|  | QuicSocketAddress(TestPeerIPAddress(), kTestPort), | 
|  | helper, | 
|  | alarm_factory, | 
|  | perspective, | 
|  | ParsedVersionOfIndex(CurrentSupportedVersions(), 0)) {} | 
|  |  | 
|  | MockQuicConnection::MockQuicConnection(QuicSocketAddress address, | 
|  | MockQuicConnectionHelper* helper, | 
|  | MockAlarmFactory* alarm_factory, | 
|  | Perspective perspective) | 
|  | : MockQuicConnection(TestConnectionId(), | 
|  | address, | 
|  | helper, | 
|  | alarm_factory, | 
|  | perspective, | 
|  | ParsedVersionOfIndex(CurrentSupportedVersions(), 0)) {} | 
|  |  | 
|  | MockQuicConnection::MockQuicConnection(QuicConnectionId connection_id, | 
|  | MockQuicConnectionHelper* helper, | 
|  | MockAlarmFactory* alarm_factory, | 
|  | Perspective perspective) | 
|  | : MockQuicConnection(connection_id, | 
|  | QuicSocketAddress(TestPeerIPAddress(), kTestPort), | 
|  | helper, | 
|  | alarm_factory, | 
|  | perspective, | 
|  | ParsedVersionOfIndex(CurrentSupportedVersions(), 0)) {} | 
|  |  | 
|  | MockQuicConnection::MockQuicConnection( | 
|  | MockQuicConnectionHelper* helper, | 
|  | MockAlarmFactory* alarm_factory, | 
|  | Perspective perspective, | 
|  | const ParsedQuicVersionVector& supported_versions) | 
|  | : MockQuicConnection(TestConnectionId(), | 
|  | QuicSocketAddress(TestPeerIPAddress(), kTestPort), | 
|  | helper, | 
|  | alarm_factory, | 
|  | perspective, | 
|  | supported_versions) {} | 
|  |  | 
|  | MockQuicConnection::MockQuicConnection( | 
|  | QuicConnectionId connection_id, | 
|  | QuicSocketAddress address, | 
|  | MockQuicConnectionHelper* helper, | 
|  | MockAlarmFactory* alarm_factory, | 
|  | Perspective perspective, | 
|  | const ParsedQuicVersionVector& supported_versions) | 
|  | : QuicConnection(connection_id, | 
|  | address, | 
|  | helper, | 
|  | alarm_factory, | 
|  | new testing::NiceMock<MockPacketWriter>(), | 
|  | /* owns_writer= */ true, | 
|  | perspective, | 
|  | supported_versions) { | 
|  | ON_CALL(*this, OnError(_)) | 
|  | .WillByDefault( | 
|  | Invoke(this, &PacketSavingConnection::QuicConnection_OnError)); | 
|  | ON_CALL(*this, SendCryptoData(_, _, _)) | 
|  | .WillByDefault( | 
|  | Invoke(this, &MockQuicConnection::QuicConnection_SendCryptoData)); | 
|  |  | 
|  | SetSelfAddress(QuicSocketAddress(QuicIpAddress::Any4(), 5)); | 
|  | } | 
|  |  | 
|  | MockQuicConnection::~MockQuicConnection() {} | 
|  |  | 
|  | void MockQuicConnection::AdvanceTime(QuicTime::Delta delta) { | 
|  | static_cast<MockQuicConnectionHelper*>(helper())->AdvanceTime(delta); | 
|  | } | 
|  |  | 
|  | bool MockQuicConnection::OnProtocolVersionMismatch(ParsedQuicVersion version, | 
|  | PacketHeaderFormat form) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | PacketSavingConnection::PacketSavingConnection(MockQuicConnectionHelper* helper, | 
|  | MockAlarmFactory* alarm_factory, | 
|  | Perspective perspective) | 
|  | : MockQuicConnection(helper, alarm_factory, perspective) {} | 
|  |  | 
|  | PacketSavingConnection::PacketSavingConnection( | 
|  | MockQuicConnectionHelper* helper, | 
|  | MockAlarmFactory* alarm_factory, | 
|  | Perspective perspective, | 
|  | const ParsedQuicVersionVector& supported_versions) | 
|  | : MockQuicConnection(helper, | 
|  | alarm_factory, | 
|  | perspective, | 
|  | supported_versions) {} | 
|  |  | 
|  | PacketSavingConnection::~PacketSavingConnection() {} | 
|  |  | 
|  | void PacketSavingConnection::SendOrQueuePacket(SerializedPacket* packet) { | 
|  | encrypted_packets_.push_back(QuicMakeUnique<QuicEncryptedPacket>( | 
|  | CopyBuffer(*packet), packet->encrypted_length, true)); | 
|  | clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10)); | 
|  | // Transfer ownership of the packet to the SentPacketManager and the | 
|  | // ack notifier to the AckNotifierManager. | 
|  | QuicConnectionPeer::GetSentPacketManager(this)->OnPacketSent( | 
|  | packet, QuicPacketNumber(), clock_.ApproximateNow(), NOT_RETRANSMISSION, | 
|  | HAS_RETRANSMITTABLE_DATA); | 
|  | } | 
|  |  | 
|  | MockQuicSession::MockQuicSession(QuicConnection* connection) | 
|  | : MockQuicSession(connection, true) {} | 
|  |  | 
|  | MockQuicSession::MockQuicSession(QuicConnection* connection, | 
|  | bool create_mock_crypto_stream) | 
|  | : QuicSession(connection, | 
|  | nullptr, | 
|  | DefaultQuicConfig(), | 
|  | CurrentSupportedVersions()) { | 
|  | if (create_mock_crypto_stream) { | 
|  | crypto_stream_ = QuicMakeUnique<MockQuicCryptoStream>(this); | 
|  | } | 
|  | ON_CALL(*this, WritevData(_, _, _, _, _)) | 
|  | .WillByDefault(testing::Return(QuicConsumedData(0, false))); | 
|  | } | 
|  |  | 
|  | MockQuicSession::~MockQuicSession() { | 
|  | delete connection(); | 
|  | } | 
|  |  | 
|  | QuicCryptoStream* MockQuicSession::GetMutableCryptoStream() { | 
|  | return crypto_stream_.get(); | 
|  | } | 
|  |  | 
|  | const QuicCryptoStream* MockQuicSession::GetCryptoStream() const { | 
|  | return crypto_stream_.get(); | 
|  | } | 
|  |  | 
|  | void MockQuicSession::SetCryptoStream(QuicCryptoStream* crypto_stream) { | 
|  | crypto_stream_.reset(crypto_stream); | 
|  | } | 
|  |  | 
|  | // static | 
|  | QuicConsumedData MockQuicSession::ConsumeData(QuicStream* stream, | 
|  | QuicStreamId /*id*/, | 
|  | size_t write_length, | 
|  | QuicStreamOffset offset, | 
|  | StreamSendingState state) { | 
|  | if (write_length > 0) { | 
|  | auto buf = QuicMakeUnique<char[]>(write_length); | 
|  | QuicDataWriter writer(write_length, buf.get(), HOST_BYTE_ORDER); | 
|  | stream->WriteStreamData(offset, write_length, &writer); | 
|  | } else { | 
|  | DCHECK(state != NO_FIN); | 
|  | } | 
|  | return QuicConsumedData(write_length, state != NO_FIN); | 
|  | } | 
|  |  | 
|  | MockQuicCryptoStream::MockQuicCryptoStream(QuicSession* session) | 
|  | : QuicCryptoStream(session), params_(new QuicCryptoNegotiatedParameters) {} | 
|  |  | 
|  | MockQuicCryptoStream::~MockQuicCryptoStream() {} | 
|  |  | 
|  | bool MockQuicCryptoStream::encryption_established() const { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool MockQuicCryptoStream::handshake_confirmed() const { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | const QuicCryptoNegotiatedParameters& | 
|  | MockQuicCryptoStream::crypto_negotiated_params() const { | 
|  | return *params_; | 
|  | } | 
|  |  | 
|  | CryptoMessageParser* MockQuicCryptoStream::crypto_message_parser() { | 
|  | return &crypto_framer_; | 
|  | } | 
|  |  | 
|  | MockQuicSpdySession::MockQuicSpdySession(QuicConnection* connection) | 
|  | : MockQuicSpdySession(connection, true) {} | 
|  |  | 
|  | MockQuicSpdySession::MockQuicSpdySession(QuicConnection* connection, | 
|  | bool create_mock_crypto_stream) | 
|  | : QuicSpdySession(connection, | 
|  | nullptr, | 
|  | DefaultQuicConfig(), | 
|  | connection->supported_versions()) { | 
|  | if (create_mock_crypto_stream) { | 
|  | crypto_stream_ = QuicMakeUnique<MockQuicCryptoStream>(this); | 
|  | } | 
|  |  | 
|  | ON_CALL(*this, WritevData(_, _, _, _, _)) | 
|  | .WillByDefault(testing::Return(QuicConsumedData(0, false))); | 
|  | } | 
|  |  | 
|  | MockQuicSpdySession::~MockQuicSpdySession() { | 
|  | delete connection(); | 
|  | } | 
|  |  | 
|  | QuicCryptoStream* MockQuicSpdySession::GetMutableCryptoStream() { | 
|  | return crypto_stream_.get(); | 
|  | } | 
|  |  | 
|  | const QuicCryptoStream* MockQuicSpdySession::GetCryptoStream() const { | 
|  | return crypto_stream_.get(); | 
|  | } | 
|  |  | 
|  | void MockQuicSpdySession::SetCryptoStream(QuicCryptoStream* crypto_stream) { | 
|  | crypto_stream_.reset(crypto_stream); | 
|  | } | 
|  |  | 
|  | TestQuicSpdyServerSession::TestQuicSpdyServerSession( | 
|  | QuicConnection* connection, | 
|  | const QuicConfig& config, | 
|  | const ParsedQuicVersionVector& supported_versions, | 
|  | const QuicCryptoServerConfig* crypto_config, | 
|  | QuicCompressedCertsCache* compressed_certs_cache) | 
|  | : QuicServerSessionBase(config, | 
|  | supported_versions, | 
|  | connection, | 
|  | &visitor_, | 
|  | &helper_, | 
|  | crypto_config, | 
|  | compressed_certs_cache) { | 
|  | Initialize(); | 
|  | ON_CALL(helper_, GenerateConnectionIdForReject(_, _)) | 
|  | .WillByDefault(testing::Return( | 
|  | QuicUtils::CreateRandomConnectionId(connection->random_generator()))); | 
|  | ON_CALL(helper_, CanAcceptClientHello(_, _, _, _, _)) | 
|  | .WillByDefault(testing::Return(true)); | 
|  | } | 
|  |  | 
|  | TestQuicSpdyServerSession::~TestQuicSpdyServerSession() { | 
|  | delete connection(); | 
|  | } | 
|  |  | 
|  | QuicCryptoServerStreamBase* | 
|  | TestQuicSpdyServerSession::CreateQuicCryptoServerStream( | 
|  | const QuicCryptoServerConfig* crypto_config, | 
|  | QuicCompressedCertsCache* compressed_certs_cache) { | 
|  | return new QuicCryptoServerStream( | 
|  | crypto_config, compressed_certs_cache, | 
|  | GetQuicReloadableFlag(enable_quic_stateless_reject_support), this, | 
|  | &helper_); | 
|  | } | 
|  |  | 
|  | void TestQuicSpdyServerSession::OnCryptoHandshakeEvent( | 
|  | CryptoHandshakeEvent event) { | 
|  | QuicSession::OnCryptoHandshakeEvent(event); | 
|  | } | 
|  |  | 
|  | QuicCryptoServerStream* TestQuicSpdyServerSession::GetMutableCryptoStream() { | 
|  | return static_cast<QuicCryptoServerStream*>( | 
|  | QuicServerSessionBase::GetMutableCryptoStream()); | 
|  | } | 
|  |  | 
|  | const QuicCryptoServerStream* TestQuicSpdyServerSession::GetCryptoStream() | 
|  | const { | 
|  | return static_cast<const QuicCryptoServerStream*>( | 
|  | QuicServerSessionBase::GetCryptoStream()); | 
|  | } | 
|  |  | 
|  | TestQuicSpdyClientSession::TestQuicSpdyClientSession( | 
|  | QuicConnection* connection, | 
|  | const QuicConfig& config, | 
|  | const ParsedQuicVersionVector& supported_versions, | 
|  | const QuicServerId& server_id, | 
|  | QuicCryptoClientConfig* crypto_config) | 
|  | : QuicSpdyClientSessionBase(connection, | 
|  | &push_promise_index_, | 
|  | config, | 
|  | supported_versions) { | 
|  | crypto_stream_ = QuicMakeUnique<QuicCryptoClientStream>( | 
|  | server_id, this, crypto_test_utils::ProofVerifyContextForTesting(), | 
|  | crypto_config, this); | 
|  | Initialize(); | 
|  | } | 
|  |  | 
|  | TestQuicSpdyClientSession::~TestQuicSpdyClientSession() {} | 
|  |  | 
|  | bool TestQuicSpdyClientSession::IsAuthorized(const QuicString& authority) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void TestQuicSpdyClientSession::OnCryptoHandshakeEvent( | 
|  | CryptoHandshakeEvent event) { | 
|  | QuicSession::OnCryptoHandshakeEvent(event); | 
|  | } | 
|  |  | 
|  | QuicCryptoClientStream* TestQuicSpdyClientSession::GetMutableCryptoStream() { | 
|  | return crypto_stream_.get(); | 
|  | } | 
|  |  | 
|  | const QuicCryptoClientStream* TestQuicSpdyClientSession::GetCryptoStream() | 
|  | const { | 
|  | return crypto_stream_.get(); | 
|  | } | 
|  |  | 
|  | TestPushPromiseDelegate::TestPushPromiseDelegate(bool match) | 
|  | : match_(match), rendezvous_fired_(false), rendezvous_stream_(nullptr) {} | 
|  |  | 
|  | bool TestPushPromiseDelegate::CheckVary( | 
|  | const spdy::SpdyHeaderBlock& client_request, | 
|  | const spdy::SpdyHeaderBlock& promise_request, | 
|  | const spdy::SpdyHeaderBlock& promise_response) { | 
|  | QUIC_DVLOG(1) << "match " << match_; | 
|  | return match_; | 
|  | } | 
|  |  | 
|  | void TestPushPromiseDelegate::OnRendezvousResult(QuicSpdyStream* stream) { | 
|  | rendezvous_fired_ = true; | 
|  | rendezvous_stream_ = stream; | 
|  | } | 
|  |  | 
|  | MockPacketWriter::MockPacketWriter() { | 
|  | ON_CALL(*this, GetMaxPacketSize(_)) | 
|  | .WillByDefault(testing::Return(kMaxPacketSize)); | 
|  | ON_CALL(*this, IsBatchMode()).WillByDefault(testing::Return(false)); | 
|  | ON_CALL(*this, GetNextWriteLocation(_, _)) | 
|  | .WillByDefault(testing::Return(nullptr)); | 
|  | ON_CALL(*this, Flush()) | 
|  | .WillByDefault(testing::Return(WriteResult(WRITE_STATUS_OK, 0))); | 
|  | } | 
|  |  | 
|  | MockPacketWriter::~MockPacketWriter() {} | 
|  |  | 
|  | MockSendAlgorithm::MockSendAlgorithm() {} | 
|  |  | 
|  | MockSendAlgorithm::~MockSendAlgorithm() {} | 
|  |  | 
|  | MockLossAlgorithm::MockLossAlgorithm() {} | 
|  |  | 
|  | MockLossAlgorithm::~MockLossAlgorithm() {} | 
|  |  | 
|  | MockAckListener::MockAckListener() {} | 
|  |  | 
|  | MockAckListener::~MockAckListener() {} | 
|  |  | 
|  | MockNetworkChangeVisitor::MockNetworkChangeVisitor() {} | 
|  |  | 
|  | MockNetworkChangeVisitor::~MockNetworkChangeVisitor() {} | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | QuicString HexDumpWithMarks(const char* data, | 
|  | int length, | 
|  | const bool* marks, | 
|  | int mark_length) { | 
|  | static const char kHexChars[] = "0123456789abcdef"; | 
|  | static const int kColumns = 4; | 
|  |  | 
|  | const int kSizeLimit = 1024; | 
|  | if (length > kSizeLimit || mark_length > kSizeLimit) { | 
|  | QUIC_LOG(ERROR) << "Only dumping first " << kSizeLimit << " bytes."; | 
|  | length = std::min(length, kSizeLimit); | 
|  | mark_length = std::min(mark_length, kSizeLimit); | 
|  | } | 
|  |  | 
|  | QuicString hex; | 
|  | for (const char* row = data; length > 0; | 
|  | row += kColumns, length -= kColumns) { | 
|  | for (const char* p = row; p < row + 4; ++p) { | 
|  | if (p < row + length) { | 
|  | const bool mark = | 
|  | (marks && (p - data) < mark_length && marks[p - data]); | 
|  | hex += mark ? '*' : ' '; | 
|  | hex += kHexChars[(*p & 0xf0) >> 4]; | 
|  | hex += kHexChars[*p & 0x0f]; | 
|  | hex += mark ? '*' : ' '; | 
|  | } else { | 
|  | hex += "    "; | 
|  | } | 
|  | } | 
|  | hex = hex + "  "; | 
|  |  | 
|  | for (const char* p = row; p < row + 4 && p < row + length; ++p) { | 
|  | hex += (*p >= 0x20 && *p <= 0x7f) ? (*p) : '.'; | 
|  | } | 
|  |  | 
|  | hex = hex + '\n'; | 
|  | } | 
|  | return hex; | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | QuicIpAddress TestPeerIPAddress() { | 
|  | return QuicIpAddress::Loopback4(); | 
|  | } | 
|  |  | 
|  | ParsedQuicVersion QuicVersionMax() { | 
|  | return AllSupportedVersions().front(); | 
|  | } | 
|  |  | 
|  | ParsedQuicVersion QuicVersionMin() { | 
|  | return AllSupportedVersions().back(); | 
|  | } | 
|  |  | 
|  | QuicTransportVersion QuicTransportVersionMax() { | 
|  | return AllSupportedTransportVersions().front(); | 
|  | } | 
|  |  | 
|  | QuicTransportVersion QuicTransportVersionMin() { | 
|  | return AllSupportedTransportVersions().back(); | 
|  | } | 
|  |  | 
|  | QuicEncryptedPacket* ConstructEncryptedPacket( | 
|  | QuicConnectionId destination_connection_id, | 
|  | QuicConnectionId source_connection_id, | 
|  | bool version_flag, | 
|  | bool reset_flag, | 
|  | uint64_t packet_number, | 
|  | const QuicString& data) { | 
|  | return ConstructEncryptedPacket( | 
|  | destination_connection_id, source_connection_id, version_flag, reset_flag, | 
|  | packet_number, data, CONNECTION_ID_PRESENT, CONNECTION_ID_ABSENT, | 
|  | PACKET_4BYTE_PACKET_NUMBER); | 
|  | } | 
|  |  | 
|  | QuicEncryptedPacket* ConstructEncryptedPacket( | 
|  | QuicConnectionId destination_connection_id, | 
|  | QuicConnectionId source_connection_id, | 
|  | bool version_flag, | 
|  | bool reset_flag, | 
|  | uint64_t packet_number, | 
|  | const QuicString& data, | 
|  | QuicConnectionIdIncluded destination_connection_id_included, | 
|  | QuicConnectionIdIncluded source_connection_id_included, | 
|  | QuicPacketNumberLength packet_number_length) { | 
|  | return ConstructEncryptedPacket( | 
|  | destination_connection_id, source_connection_id, version_flag, reset_flag, | 
|  | packet_number, data, destination_connection_id_included, | 
|  | source_connection_id_included, packet_number_length, nullptr); | 
|  | } | 
|  |  | 
|  | QuicEncryptedPacket* ConstructEncryptedPacket( | 
|  | QuicConnectionId destination_connection_id, | 
|  | QuicConnectionId source_connection_id, | 
|  | bool version_flag, | 
|  | bool reset_flag, | 
|  | uint64_t packet_number, | 
|  | const QuicString& data, | 
|  | QuicConnectionIdIncluded destination_connection_id_included, | 
|  | QuicConnectionIdIncluded source_connection_id_included, | 
|  | QuicPacketNumberLength packet_number_length, | 
|  | ParsedQuicVersionVector* versions) { | 
|  | return ConstructEncryptedPacket( | 
|  | destination_connection_id, source_connection_id, version_flag, reset_flag, | 
|  | packet_number, data, destination_connection_id_included, | 
|  | source_connection_id_included, packet_number_length, versions, | 
|  | Perspective::IS_CLIENT); | 
|  | } | 
|  | QuicEncryptedPacket* ConstructEncryptedPacket( | 
|  | QuicConnectionId destination_connection_id, | 
|  | QuicConnectionId source_connection_id, | 
|  | bool version_flag, | 
|  | bool reset_flag, | 
|  | uint64_t packet_number, | 
|  | const QuicString& data, | 
|  | QuicConnectionIdIncluded destination_connection_id_included, | 
|  | QuicConnectionIdIncluded source_connection_id_included, | 
|  | QuicPacketNumberLength packet_number_length, | 
|  | ParsedQuicVersionVector* versions, | 
|  | Perspective perspective) { | 
|  | QuicPacketHeader header; | 
|  | header.destination_connection_id = destination_connection_id; | 
|  | header.destination_connection_id_included = | 
|  | destination_connection_id_included; | 
|  | header.source_connection_id = source_connection_id; | 
|  | header.source_connection_id_included = source_connection_id_included; | 
|  | header.version_flag = version_flag; | 
|  | header.reset_flag = reset_flag; | 
|  | header.packet_number_length = packet_number_length; | 
|  | header.packet_number = QuicPacketNumber(packet_number); | 
|  | ParsedQuicVersionVector supported_versions = CurrentSupportedVersions(); | 
|  | if (!versions) { | 
|  | versions = &supported_versions; | 
|  | } | 
|  | if (QuicVersionHasLongHeaderLengths((*versions)[0].transport_version) && | 
|  | version_flag) { | 
|  | header.retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_1; | 
|  | header.length_length = VARIABLE_LENGTH_INTEGER_LENGTH_2; | 
|  | } | 
|  |  | 
|  | QuicFrames frames; | 
|  | QuicFramer framer(*versions, QuicTime::Zero(), perspective, | 
|  | kQuicDefaultConnectionIdLength); | 
|  | if ((*versions)[0].transport_version < QUIC_VERSION_47) { | 
|  | QuicFrame frame(QuicStreamFrame( | 
|  | QuicUtils::GetCryptoStreamId((*versions)[0].transport_version), false, | 
|  | 0, QuicStringPiece(data))); | 
|  | frames.push_back(frame); | 
|  | } else { | 
|  | QuicFrame frame(new QuicCryptoFrame(ENCRYPTION_NONE, 0, data)); | 
|  | frames.push_back(frame); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<QuicPacket> packet( | 
|  | BuildUnsizedDataPacket(&framer, header, frames)); | 
|  | EXPECT_TRUE(packet != nullptr); | 
|  | char* buffer = new char[kMaxPacketSize]; | 
|  | size_t encrypted_length = | 
|  | framer.EncryptPayload(ENCRYPTION_NONE, QuicPacketNumber(packet_number), | 
|  | *packet, buffer, kMaxPacketSize); | 
|  | EXPECT_NE(0u, encrypted_length); | 
|  | DeleteFrames(&frames); | 
|  | return new QuicEncryptedPacket(buffer, encrypted_length, true); | 
|  | } | 
|  |  | 
|  | QuicReceivedPacket* ConstructReceivedPacket( | 
|  | const QuicEncryptedPacket& encrypted_packet, | 
|  | QuicTime receipt_time) { | 
|  | char* buffer = new char[encrypted_packet.length()]; | 
|  | memcpy(buffer, encrypted_packet.data(), encrypted_packet.length()); | 
|  | return new QuicReceivedPacket(buffer, encrypted_packet.length(), receipt_time, | 
|  | true); | 
|  | } | 
|  |  | 
|  | QuicEncryptedPacket* ConstructMisFramedEncryptedPacket( | 
|  | QuicConnectionId destination_connection_id, | 
|  | QuicConnectionId source_connection_id, | 
|  | bool version_flag, | 
|  | bool reset_flag, | 
|  | uint64_t packet_number, | 
|  | const QuicString& data, | 
|  | QuicConnectionIdIncluded destination_connection_id_included, | 
|  | QuicConnectionIdIncluded source_connection_id_included, | 
|  | QuicPacketNumberLength packet_number_length, | 
|  | ParsedQuicVersionVector* versions, | 
|  | Perspective perspective) { | 
|  | QuicPacketHeader header; | 
|  | header.destination_connection_id = destination_connection_id; | 
|  | header.destination_connection_id_included = | 
|  | destination_connection_id_included; | 
|  | header.source_connection_id = source_connection_id; | 
|  | header.source_connection_id_included = source_connection_id_included; | 
|  | header.version_flag = version_flag; | 
|  | header.reset_flag = reset_flag; | 
|  | header.packet_number_length = packet_number_length; | 
|  | header.packet_number = QuicPacketNumber(packet_number); | 
|  | QuicFrame frame(QuicStreamFrame(1, false, 0, QuicStringPiece(data))); | 
|  | QuicFrames frames; | 
|  | frames.push_back(frame); | 
|  | QuicFramer framer(versions != nullptr ? *versions : AllSupportedVersions(), | 
|  | QuicTime::Zero(), perspective, | 
|  | kQuicDefaultConnectionIdLength); | 
|  |  | 
|  | std::unique_ptr<QuicPacket> packet( | 
|  | BuildUnsizedDataPacket(&framer, header, frames)); | 
|  | EXPECT_TRUE(packet != nullptr); | 
|  |  | 
|  | // Now set the frame type to 0x1F, which is an invalid frame type. | 
|  | reinterpret_cast<unsigned char*>( | 
|  | packet->mutable_data())[GetStartOfEncryptedData( | 
|  | framer.transport_version(), | 
|  | GetIncludedDestinationConnectionIdLength(header), | 
|  | GetIncludedSourceConnectionIdLength(header), version_flag, | 
|  | false /* no diversification nonce */, packet_number_length, | 
|  | VARIABLE_LENGTH_INTEGER_LENGTH_0, 0, VARIABLE_LENGTH_INTEGER_LENGTH_0)] = | 
|  | 0x1F; | 
|  |  | 
|  | char* buffer = new char[kMaxPacketSize]; | 
|  | size_t encrypted_length = | 
|  | framer.EncryptPayload(ENCRYPTION_NONE, QuicPacketNumber(packet_number), | 
|  | *packet, buffer, kMaxPacketSize); | 
|  | EXPECT_NE(0u, encrypted_length); | 
|  | return new QuicEncryptedPacket(buffer, encrypted_length, true); | 
|  | } | 
|  |  | 
|  | void CompareCharArraysWithHexError(const QuicString& description, | 
|  | const char* actual, | 
|  | const int actual_len, | 
|  | const char* expected, | 
|  | const int expected_len) { | 
|  | EXPECT_EQ(actual_len, expected_len); | 
|  | const int min_len = std::min(actual_len, expected_len); | 
|  | const int max_len = std::max(actual_len, expected_len); | 
|  | std::unique_ptr<bool[]> marks(new bool[max_len]); | 
|  | bool identical = (actual_len == expected_len); | 
|  | for (int i = 0; i < min_len; ++i) { | 
|  | if (actual[i] != expected[i]) { | 
|  | marks[i] = true; | 
|  | identical = false; | 
|  | } else { | 
|  | marks[i] = false; | 
|  | } | 
|  | } | 
|  | for (int i = min_len; i < max_len; ++i) { | 
|  | marks[i] = true; | 
|  | } | 
|  | if (identical) | 
|  | return; | 
|  | ADD_FAILURE() << "Description:\n" | 
|  | << description << "\n\nExpected:\n" | 
|  | << HexDumpWithMarks(expected, expected_len, marks.get(), | 
|  | max_len) | 
|  | << "\nActual:\n" | 
|  | << HexDumpWithMarks(actual, actual_len, marks.get(), max_len); | 
|  | } | 
|  |  | 
|  | size_t GetPacketLengthForOneStream( | 
|  | QuicTransportVersion version, | 
|  | bool include_version, | 
|  | bool include_diversification_nonce, | 
|  | QuicConnectionIdLength destination_connection_id_length, | 
|  | QuicConnectionIdLength source_connection_id_length, | 
|  | QuicPacketNumberLength packet_number_length, | 
|  | QuicVariableLengthIntegerLength retry_token_length_length, | 
|  | QuicVariableLengthIntegerLength length_length, | 
|  | size_t* payload_length) { | 
|  | *payload_length = 1; | 
|  | const size_t stream_length = | 
|  | NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(*payload_length) + | 
|  | QuicPacketCreator::StreamFramePacketOverhead( | 
|  | version, destination_connection_id_length, | 
|  | source_connection_id_length, include_version, | 
|  | include_diversification_nonce, packet_number_length, | 
|  | retry_token_length_length, length_length, 0u); | 
|  | const size_t ack_length = | 
|  | NullEncrypter(Perspective::IS_CLIENT) | 
|  | .GetCiphertextSize(QuicFramer::GetMinAckFrameSize( | 
|  | version, PACKET_1BYTE_PACKET_NUMBER)) + | 
|  | GetPacketHeaderSize(version, destination_connection_id_length, | 
|  | source_connection_id_length, include_version, | 
|  | include_diversification_nonce, packet_number_length, | 
|  | retry_token_length_length, 0, length_length); | 
|  | if (stream_length < ack_length) { | 
|  | *payload_length = 1 + ack_length - stream_length; | 
|  | } | 
|  |  | 
|  | return NullEncrypter(Perspective::IS_CLIENT) | 
|  | .GetCiphertextSize(*payload_length) + | 
|  | QuicPacketCreator::StreamFramePacketOverhead( | 
|  | version, destination_connection_id_length, | 
|  | source_connection_id_length, include_version, | 
|  | include_diversification_nonce, packet_number_length, | 
|  | retry_token_length_length, length_length, 0u); | 
|  | } | 
|  |  | 
|  | QuicConfig DefaultQuicConfig() { | 
|  | QuicConfig config; | 
|  | config.SetInitialStreamFlowControlWindowToSend( | 
|  | kInitialStreamFlowControlWindowForTest); | 
|  | config.SetInitialSessionFlowControlWindowToSend( | 
|  | kInitialSessionFlowControlWindowForTest); | 
|  | QuicConfigPeer::SetReceivedMaxIncomingDynamicStreams( | 
|  | &config, kDefaultMaxStreamsPerConnection); | 
|  | // Default enable NSTP. | 
|  | // This is unnecessary for versions > 44 | 
|  | if (!config.HasClientSentConnectionOption(quic::kNSTP, | 
|  | quic::Perspective::IS_CLIENT)) { | 
|  | quic::QuicTagVector connection_options; | 
|  | connection_options.push_back(quic::kNSTP); | 
|  | config.SetConnectionOptionsToSend(connection_options); | 
|  | } | 
|  | return config; | 
|  | } | 
|  |  | 
|  | QuicConfig DefaultQuicConfigStatelessRejects() { | 
|  | QuicConfig config = DefaultQuicConfig(); | 
|  | QuicTagVector copt; | 
|  | copt.push_back(kSREJ); | 
|  | config.SetConnectionOptionsToSend(copt); | 
|  | return config; | 
|  | } | 
|  |  | 
|  | QuicTransportVersionVector SupportedTransportVersions( | 
|  | QuicTransportVersion version) { | 
|  | QuicTransportVersionVector versions; | 
|  | versions.push_back(version); | 
|  | return versions; | 
|  | } | 
|  |  | 
|  | ParsedQuicVersionVector SupportedVersions(ParsedQuicVersion version) { | 
|  | ParsedQuicVersionVector versions; | 
|  | versions.push_back(version); | 
|  | return versions; | 
|  | } | 
|  |  | 
|  | MockQuicConnectionDebugVisitor::MockQuicConnectionDebugVisitor() {} | 
|  |  | 
|  | MockQuicConnectionDebugVisitor::~MockQuicConnectionDebugVisitor() {} | 
|  |  | 
|  | MockReceivedPacketManager::MockReceivedPacketManager(QuicConnectionStats* stats) | 
|  | : QuicReceivedPacketManager(stats) {} | 
|  |  | 
|  | MockReceivedPacketManager::~MockReceivedPacketManager() {} | 
|  |  | 
|  | MockConnectionCloseDelegate::MockConnectionCloseDelegate() {} | 
|  |  | 
|  | MockConnectionCloseDelegate::~MockConnectionCloseDelegate() {} | 
|  |  | 
|  | MockPacketCreatorDelegate::MockPacketCreatorDelegate() {} | 
|  | MockPacketCreatorDelegate::~MockPacketCreatorDelegate() {} | 
|  |  | 
|  | MockSessionNotifier::MockSessionNotifier() {} | 
|  | MockSessionNotifier::~MockSessionNotifier() {} | 
|  |  | 
|  | void CreateClientSessionForTest( | 
|  | QuicServerId server_id, | 
|  | bool supports_stateless_rejects, | 
|  | QuicTime::Delta connection_start_time, | 
|  | const ParsedQuicVersionVector& supported_versions, | 
|  | MockQuicConnectionHelper* helper, | 
|  | MockAlarmFactory* alarm_factory, | 
|  | QuicCryptoClientConfig* crypto_client_config, | 
|  | PacketSavingConnection** client_connection, | 
|  | TestQuicSpdyClientSession** client_session) { | 
|  | CHECK(crypto_client_config); | 
|  | CHECK(client_connection); | 
|  | CHECK(client_session); | 
|  | CHECK(!connection_start_time.IsZero()) | 
|  | << "Connections must start at non-zero times, otherwise the " | 
|  | << "strike-register will be unhappy."; | 
|  |  | 
|  | QuicConfig config = supports_stateless_rejects | 
|  | ? DefaultQuicConfigStatelessRejects() | 
|  | : DefaultQuicConfig(); | 
|  | *client_connection = new PacketSavingConnection( | 
|  | helper, alarm_factory, Perspective::IS_CLIENT, supported_versions); | 
|  | *client_session = new TestQuicSpdyClientSession(*client_connection, config, | 
|  | supported_versions, server_id, | 
|  | crypto_client_config); | 
|  | (*client_connection)->AdvanceTime(connection_start_time); | 
|  | } | 
|  |  | 
|  | void CreateServerSessionForTest( | 
|  | QuicServerId server_id, | 
|  | QuicTime::Delta connection_start_time, | 
|  | ParsedQuicVersionVector supported_versions, | 
|  | MockQuicConnectionHelper* helper, | 
|  | MockAlarmFactory* alarm_factory, | 
|  | QuicCryptoServerConfig* server_crypto_config, | 
|  | QuicCompressedCertsCache* compressed_certs_cache, | 
|  | PacketSavingConnection** server_connection, | 
|  | TestQuicSpdyServerSession** server_session) { | 
|  | CHECK(server_crypto_config); | 
|  | CHECK(server_connection); | 
|  | CHECK(server_session); | 
|  | CHECK(!connection_start_time.IsZero()) | 
|  | << "Connections must start at non-zero times, otherwise the " | 
|  | << "strike-register will be unhappy."; | 
|  |  | 
|  | *server_connection = | 
|  | new PacketSavingConnection(helper, alarm_factory, Perspective::IS_SERVER, | 
|  | ParsedVersionOfIndex(supported_versions, 0)); | 
|  | *server_session = new TestQuicSpdyServerSession( | 
|  | *server_connection, DefaultQuicConfig(), supported_versions, | 
|  | server_crypto_config, compressed_certs_cache); | 
|  |  | 
|  | // We advance the clock initially because the default time is zero and the | 
|  | // strike register worries that we've just overflowed a uint32_t time. | 
|  | (*server_connection)->AdvanceTime(connection_start_time); | 
|  | } | 
|  |  | 
|  | QuicStreamId GetNthClientInitiatedBidirectionalStreamId( | 
|  | QuicTransportVersion version, | 
|  | int n) { | 
|  | return QuicUtils::GetFirstBidirectionalStreamId(version, | 
|  | Perspective::IS_CLIENT) + | 
|  | // + 1 because spdy_session contains headers stream. | 
|  | QuicUtils::StreamIdDelta(version) * (n + 1); | 
|  | } | 
|  |  | 
|  | QuicStreamId GetNthServerInitiatedBidirectionalStreamId( | 
|  | QuicTransportVersion version, | 
|  | int n) { | 
|  | return QuicUtils::GetFirstBidirectionalStreamId(version, | 
|  | Perspective::IS_SERVER) + | 
|  | QuicUtils::StreamIdDelta(version) * n; | 
|  | } | 
|  |  | 
|  | QuicStreamId GetNthServerInitiatedUnidirectionalStreamId( | 
|  | QuicTransportVersion version, | 
|  | int n) { | 
|  | return QuicUtils::GetFirstUnidirectionalStreamId(version, | 
|  | Perspective::IS_SERVER) + | 
|  | QuicUtils::StreamIdDelta(version) * n; | 
|  | } | 
|  |  | 
|  | StreamType DetermineStreamType(QuicStreamId id, | 
|  | QuicTransportVersion version, | 
|  | Perspective perspective, | 
|  | bool is_incoming, | 
|  | StreamType default_type) { | 
|  | return version == QUIC_VERSION_99 | 
|  | ? QuicUtils::GetStreamType(id, perspective, is_incoming) | 
|  | : default_type; | 
|  | } | 
|  |  | 
|  | QuicMemSliceSpan MakeSpan(QuicBufferAllocator* allocator, | 
|  | QuicStringPiece message_data, | 
|  | QuicMemSliceStorage* storage) { | 
|  | if (message_data.length() == 0) { | 
|  | *storage = QuicMemSliceStorage(nullptr, 0, allocator, kMaxPacketSize); | 
|  | return storage->ToSpan(); | 
|  | } | 
|  | struct iovec iov = {const_cast<char*>(message_data.data()), | 
|  | message_data.length()}; | 
|  | *storage = QuicMemSliceStorage(&iov, 1, allocator, kMaxPacketSize); | 
|  | return storage->ToSpan(); | 
|  | } | 
|  |  | 
|  | }  // namespace test | 
|  | }  // namespace quic |