diff options
Diffstat (limited to 'chromium/net/quic/test_tools/quic_test_utils.cc')
-rw-r--r-- | chromium/net/quic/test_tools/quic_test_utils.cc | 453 |
1 files changed, 453 insertions, 0 deletions
diff --git a/chromium/net/quic/test_tools/quic_test_utils.cc b/chromium/net/quic/test_tools/quic_test_utils.cc new file mode 100644 index 00000000000..2562b07d599 --- /dev/null +++ b/chromium/net/quic/test_tools/quic_test_utils.cc @@ -0,0 +1,453 @@ +// 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/quic/test_tools/quic_test_utils.h" + +#include "base/stl_util.h" +#include "net/quic/crypto/crypto_framer.h" +#include "net/quic/crypto/crypto_handshake.h" +#include "net/quic/crypto/crypto_utils.h" +#include "net/quic/crypto/null_encrypter.h" +#include "net/quic/crypto/quic_decrypter.h" +#include "net/quic/crypto/quic_encrypter.h" +#include "net/quic/quic_framer.h" +#include "net/quic/quic_packet_creator.h" +#include "net/spdy/spdy_frame_builder.h" + +using base::StringPiece; +using std::max; +using std::min; +using std::string; +using testing::_; + +namespace net { +namespace test { +namespace { + +// No-op alarm implementation used by MockHelper. +class TestAlarm : public QuicAlarm { + public: + explicit TestAlarm(QuicAlarm::Delegate* delegate) + : QuicAlarm(delegate) { + } + + virtual void SetImpl() OVERRIDE {} + virtual void CancelImpl() OVERRIDE {} +}; + +} // namespace + +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, OnPacketHeader(_)) + .WillByDefault(testing::Return(true)); + + ON_CALL(*this, OnStreamFrame(_)) + .WillByDefault(testing::Return(true)); + + ON_CALL(*this, OnAckFrame(_)) + .WillByDefault(testing::Return(true)); + + ON_CALL(*this, OnCongestionFeedbackFrame(_)) + .WillByDefault(testing::Return(true)); + + ON_CALL(*this, OnRstStreamFrame(_)) + .WillByDefault(testing::Return(true)); + + ON_CALL(*this, OnConnectionCloseFrame(_)) + .WillByDefault(testing::Return(true)); + + ON_CALL(*this, OnGoAwayFrame(_)) + .WillByDefault(testing::Return(true)); +} + +MockFramerVisitor::~MockFramerVisitor() { +} + +bool NoOpFramerVisitor::OnProtocolVersionMismatch(QuicVersion version) { + return false; +} + +bool NoOpFramerVisitor::OnPacketHeader(const QuicPacketHeader& header) { + return true; +} + +bool NoOpFramerVisitor::OnStreamFrame(const QuicStreamFrame& frame) { + return true; +} + +bool NoOpFramerVisitor::OnAckFrame(const QuicAckFrame& frame) { + return true; +} + +bool NoOpFramerVisitor::OnCongestionFeedbackFrame( + const QuicCongestionFeedbackFrame& frame) { + return true; +} + +bool NoOpFramerVisitor::OnRstStreamFrame( + const QuicRstStreamFrame& frame) { + return true; +} + +bool NoOpFramerVisitor::OnConnectionCloseFrame( + const QuicConnectionCloseFrame& frame) { + return true; +} + +bool NoOpFramerVisitor::OnGoAwayFrame(const QuicGoAwayFrame& frame) { + return true; +} + +FramerVisitorCapturingFrames::FramerVisitorCapturingFrames() : frame_count_(0) { +} + +FramerVisitorCapturingFrames::~FramerVisitorCapturingFrames() { +} + +bool FramerVisitorCapturingFrames::OnPacketHeader( + const QuicPacketHeader& header) { + header_ = header; + frame_count_ = 0; + return true; +} + +bool FramerVisitorCapturingFrames::OnStreamFrame(const QuicStreamFrame& frame) { + // TODO(ianswett): Own the underlying string, so it will not exist outside + // this callback. + stream_frames_.push_back(frame); + ++frame_count_; + return true; +} + +bool FramerVisitorCapturingFrames::OnAckFrame(const QuicAckFrame& frame) { + ack_.reset(new QuicAckFrame(frame)); + ++frame_count_; + return true; +} + +bool FramerVisitorCapturingFrames::OnCongestionFeedbackFrame( + const QuicCongestionFeedbackFrame& frame) { + feedback_.reset(new QuicCongestionFeedbackFrame(frame)); + ++frame_count_; + return true; +} + +bool FramerVisitorCapturingFrames::OnRstStreamFrame( + const QuicRstStreamFrame& frame) { + rst_.reset(new QuicRstStreamFrame(frame)); + ++frame_count_; + return true; +} + +bool FramerVisitorCapturingFrames::OnConnectionCloseFrame( + const QuicConnectionCloseFrame& frame) { + close_.reset(new QuicConnectionCloseFrame(frame)); + ++frame_count_; + return true; +} + +bool FramerVisitorCapturingFrames::OnGoAwayFrame(const QuicGoAwayFrame& frame) { + goaway_.reset(new QuicGoAwayFrame(frame)); + ++frame_count_; + return true; +} + +void FramerVisitorCapturingFrames::OnVersionNegotiationPacket( + const QuicVersionNegotiationPacket& packet) { + version_negotiation_packet_.reset(new QuicVersionNegotiationPacket(packet)); + frame_count_ = 0; +} + +FramerVisitorCapturingPublicReset::FramerVisitorCapturingPublicReset() { +} + +FramerVisitorCapturingPublicReset::~FramerVisitorCapturingPublicReset() { +} + +void FramerVisitorCapturingPublicReset::OnPublicResetPacket( + const QuicPublicResetPacket& public_reset) { + public_reset_packet_ = public_reset; +} + +MockConnectionVisitor::MockConnectionVisitor() { +} + +MockConnectionVisitor::~MockConnectionVisitor() { +} + +MockHelper::MockHelper() { +} + +MockHelper::~MockHelper() { +} + +const QuicClock* MockHelper::GetClock() const { + return &clock_; +} + +QuicRandom* MockHelper::GetRandomGenerator() { + return &random_generator_; +} + +QuicAlarm* MockHelper::CreateAlarm(QuicAlarm::Delegate* delegate) { + return new TestAlarm(delegate); +} + +void MockHelper::AdvanceTime(QuicTime::Delta delta) { + clock_.AdvanceTime(delta); +} + +MockConnection::MockConnection(QuicGuid guid, + IPEndPoint address, + bool is_server) + : QuicConnection(guid, address, new testing::NiceMock<MockHelper>(), + is_server, QuicVersionMax()), + has_mock_helper_(true) { +} + +MockConnection::MockConnection(QuicGuid guid, + IPEndPoint address, + QuicConnectionHelperInterface* helper, + bool is_server) + : QuicConnection(guid, address, helper, is_server, QuicVersionMax()), + has_mock_helper_(false) { +} + +MockConnection::~MockConnection() { +} + +void MockConnection::AdvanceTime(QuicTime::Delta delta) { + CHECK(has_mock_helper_) << "Cannot advance time unless a MockClock is being" + " used"; + static_cast<MockHelper*>(helper())->AdvanceTime(delta); +} + +PacketSavingConnection::PacketSavingConnection(QuicGuid guid, + IPEndPoint address, + bool is_server) + : MockConnection(guid, address, is_server) { +} + +PacketSavingConnection::~PacketSavingConnection() { + STLDeleteElements(&packets_); + STLDeleteElements(&encrypted_packets_); +} + +bool PacketSavingConnection::SendOrQueuePacket( + EncryptionLevel level, + QuicPacketSequenceNumber sequence_number, + QuicPacket* packet, + QuicPacketEntropyHash entropy_hash, + HasRetransmittableData retransmittable) { + packets_.push_back(packet); + QuicEncryptedPacket* encrypted = + framer_.EncryptPacket(level, sequence_number, *packet); + encrypted_packets_.push_back(encrypted); + return true; +} + +MockSession::MockSession(QuicConnection* connection, bool is_server) + : QuicSession(connection, DefaultQuicConfig(), is_server) { + ON_CALL(*this, WriteData(_, _, _, _)) + .WillByDefault(testing::Return(QuicConsumedData(0, false))); +} + +MockSession::~MockSession() { +} + +TestSession::TestSession(QuicConnection* connection, + const QuicConfig& config, + bool is_server) + : QuicSession(connection, config, is_server), + crypto_stream_(NULL) { +} + +TestSession::~TestSession() {} + +void TestSession::SetCryptoStream(QuicCryptoStream* stream) { + crypto_stream_ = stream; +} + +QuicCryptoStream* TestSession::GetCryptoStream() { + return crypto_stream_; +} + +MockSendAlgorithm::MockSendAlgorithm() { +} + +MockSendAlgorithm::~MockSendAlgorithm() { +} + +namespace { + +string 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) { + LOG(ERROR) << "Only dumping first " << kSizeLimit << " bytes."; + length = min(length, kSizeLimit); + mark_length = min(mark_length, kSizeLimit); + } + + string 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 + +void CompareCharArraysWithHexError( + const string& description, + const char* actual, + const int actual_len, + const char* expected, + const int expected_len) { + const int min_len = min(actual_len, expected_len); + const int max_len = max(actual_len, expected_len); + scoped_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); +} + +void CompareQuicDataWithHexError( + const string& description, + QuicData* actual, + QuicData* expected) { + CompareCharArraysWithHexError( + description, + actual->data(), actual->length(), + expected->data(), expected->length()); +} + +static QuicPacket* ConstructPacketFromHandshakeMessage( + QuicGuid guid, + const CryptoHandshakeMessage& message, + bool should_include_version) { + CryptoFramer crypto_framer; + scoped_ptr<QuicData> data(crypto_framer.ConstructHandshakeMessage(message)); + QuicFramer quic_framer(QuicVersionMax(), QuicTime::Zero(), false); + + QuicPacketHeader header; + header.public_header.guid = guid; + header.public_header.reset_flag = false; + header.public_header.version_flag = should_include_version; + header.packet_sequence_number = 1; + header.entropy_flag = false; + header.entropy_hash = 0; + header.fec_flag = false; + header.fec_group = 0; + + QuicStreamFrame stream_frame(kCryptoStreamId, false, 0, + data->AsStringPiece()); + + QuicFrame frame(&stream_frame); + QuicFrames frames; + frames.push_back(frame); + return quic_framer.BuildUnsizedDataPacket(header, frames).packet; +} + +QuicPacket* ConstructHandshakePacket(QuicGuid guid, QuicTag tag) { + CryptoHandshakeMessage message; + message.set_tag(tag); + return ConstructPacketFromHandshakeMessage(guid, message, false); +} + +size_t GetPacketLengthForOneStream(QuicVersion version, + bool include_version, + InFecGroup is_in_fec_group, + size_t* payload_length) { + *payload_length = 1; + const size_t stream_length = + NullEncrypter().GetCiphertextSize(*payload_length) + + QuicPacketCreator::StreamFramePacketOverhead( + version, PACKET_8BYTE_GUID, include_version, + PACKET_6BYTE_SEQUENCE_NUMBER, is_in_fec_group); + const size_t ack_length = NullEncrypter().GetCiphertextSize( + QuicFramer::GetMinAckFrameSize()) + + GetPacketHeaderSize(PACKET_8BYTE_GUID, include_version, + PACKET_6BYTE_SEQUENCE_NUMBER, is_in_fec_group); + if (stream_length < ack_length) { + *payload_length = 1 + ack_length - stream_length; + } + + return NullEncrypter().GetCiphertextSize(*payload_length) + + QuicPacketCreator::StreamFramePacketOverhead( + version, PACKET_8BYTE_GUID, include_version, + PACKET_6BYTE_SEQUENCE_NUMBER, is_in_fec_group); +} + +// Size in bytes of the stream frame fields for an arbitrary StreamID and +// offset and the last frame in a packet. +size_t GetMinStreamFrameSize(QuicVersion version) { + return kQuicFrameTypeSize + kQuicMaxStreamIdSize + kQuicMaxStreamOffsetSize; +} + +QuicPacketEntropyHash TestEntropyCalculator::EntropyHash( + QuicPacketSequenceNumber sequence_number) const { + return 1u; +} + +QuicConfig DefaultQuicConfig() { + QuicConfig config; + config.SetDefaults(); + return config; +} + +bool TestDecompressorVisitor::OnDecompressedData(StringPiece data) { + data.AppendToString(&data_); + return true; +} + +void TestDecompressorVisitor::OnDecompressionError() { + error_ = true; +} + +} // namespace test +} // namespace net |