| Index: net/spdy/spdy_framer_test.cc
|
| diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc
|
| deleted file mode 100644
|
| index c2979131cf9d1e03845340d26c073061b5682797..0000000000000000000000000000000000000000
|
| --- a/net/spdy/spdy_framer_test.cc
|
| +++ /dev/null
|
| @@ -1,5944 +0,0 @@
|
| -// 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 <algorithm>
|
| -#include <iostream>
|
| -#include <limits>
|
| -
|
| -#include "base/compiler_specific.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "net/spdy/hpack_output_stream.h"
|
| -#include "net/spdy/mock_spdy_framer_visitor.h"
|
| -#include "net/spdy/spdy_frame_builder.h"
|
| -#include "net/spdy/spdy_frame_reader.h"
|
| -#include "net/spdy/spdy_framer.h"
|
| -#include "net/spdy/spdy_protocol.h"
|
| -#include "net/spdy/spdy_test_utils.h"
|
| -#include "testing/gmock/include/gmock/gmock.h"
|
| -#include "testing/platform_test.h"
|
| -
|
| -using std::string;
|
| -using testing::_;
|
| -
|
| -namespace net {
|
| -
|
| -namespace test {
|
| -
|
| -static const size_t kMaxDecompressedSize = 1024;
|
| -
|
| -class MockDebugVisitor : public SpdyFramerDebugVisitorInterface {
|
| - public:
|
| - MOCK_METHOD4(OnSendCompressedFrame, void(SpdyStreamId stream_id,
|
| - SpdyFrameType type,
|
| - size_t payload_len,
|
| - size_t frame_len));
|
| -
|
| - MOCK_METHOD3(OnReceiveCompressedFrame, void(SpdyStreamId stream_id,
|
| - SpdyFrameType type,
|
| - size_t frame_len));
|
| -};
|
| -
|
| -class SpdyFramerTestUtil {
|
| - public:
|
| - // Decompress a single frame using the decompression context held by
|
| - // the SpdyFramer. The implemention is meant for use only in tests
|
| - // and will CHECK fail if the input is anything other than a single,
|
| - // well-formed compressed frame.
|
| - //
|
| - // Returns a new decompressed SpdyFrame.
|
| - template<class SpdyFrameType> static SpdyFrame* DecompressFrame(
|
| - SpdyFramer* framer, const SpdyFrameType& frame) {
|
| - DecompressionVisitor visitor(framer->protocol_version());
|
| - framer->set_visitor(&visitor);
|
| - CHECK_EQ(frame.size(), framer->ProcessInput(frame.data(), frame.size()));
|
| - CHECK_EQ(SpdyFramer::SPDY_RESET, framer->state());
|
| - framer->set_visitor(NULL);
|
| -
|
| - char* buffer = visitor.ReleaseBuffer();
|
| - CHECK(buffer != NULL);
|
| - SpdyFrame* decompressed_frame = new SpdyFrame(buffer, visitor.size(), true);
|
| - SetFrameLength(decompressed_frame,
|
| - visitor.size() - framer->GetControlFrameHeaderSize(),
|
| - framer->protocol_version());
|
| - return decompressed_frame;
|
| - }
|
| -
|
| - class DecompressionVisitor : public SpdyFramerVisitorInterface {
|
| - public:
|
| - explicit DecompressionVisitor(SpdyMajorVersion version)
|
| - : version_(version), size_(0), finished_(false) {}
|
| -
|
| - void ResetBuffer() {
|
| - CHECK(buffer_.get() == NULL);
|
| - CHECK_EQ(0u, size_);
|
| - CHECK(!finished_);
|
| - buffer_.reset(new char[kMaxDecompressedSize]);
|
| - }
|
| -
|
| - void OnError(SpdyFramer* framer) override { LOG(FATAL); }
|
| - void OnDataFrameHeader(SpdyStreamId stream_id,
|
| - size_t length,
|
| - bool fin) override {
|
| - LOG(FATAL) << "Unexpected data frame header";
|
| - }
|
| - void OnStreamFrameData(SpdyStreamId stream_id,
|
| - const char* data,
|
| - size_t len,
|
| - bool fin) override {
|
| - LOG(FATAL);
|
| - }
|
| -
|
| - bool OnControlFrameHeaderData(SpdyStreamId stream_id,
|
| - const char* header_data,
|
| - size_t len) override {
|
| - CHECK(buffer_.get() != NULL);
|
| - CHECK_GE(kMaxDecompressedSize, size_ + len);
|
| - CHECK(!finished_);
|
| - if (len != 0) {
|
| - memcpy(buffer_.get() + size_, header_data, len);
|
| - size_ += len;
|
| - } else {
|
| - // Done.
|
| - finished_ = true;
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - void OnSynStream(SpdyStreamId stream_id,
|
| - SpdyStreamId associated_stream_id,
|
| - SpdyPriority priority,
|
| - bool fin,
|
| - bool unidirectional) override {
|
| - SpdyFramer framer(version_);
|
| - framer.set_enable_compression(false);
|
| - SpdySynStreamIR syn_stream(stream_id);
|
| - syn_stream.set_associated_to_stream_id(associated_stream_id);
|
| - syn_stream.set_priority(priority);
|
| - syn_stream.set_fin(fin);
|
| - syn_stream.set_unidirectional(unidirectional);
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
|
| - ResetBuffer();
|
| - memcpy(buffer_.get(), frame->data(), framer.GetSynStreamMinimumSize());
|
| - size_ += framer.GetSynStreamMinimumSize();
|
| - }
|
| -
|
| - void OnSynReply(SpdyStreamId stream_id, bool fin) override {
|
| - SpdyFramer framer(version_);
|
| - framer.set_enable_compression(false);
|
| - SpdyHeadersIR headers(stream_id);
|
| - headers.set_fin(fin);
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
|
| - ResetBuffer();
|
| - memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
|
| - size_ += framer.GetSynStreamMinimumSize();
|
| - }
|
| -
|
| - void OnRstStream(SpdyStreamId stream_id,
|
| - SpdyRstStreamStatus status) override {
|
| - LOG(FATAL);
|
| - }
|
| - void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {
|
| - LOG(FATAL);
|
| - }
|
| - void OnPing(SpdyPingId unique_id, bool is_ack) override { LOG(FATAL); }
|
| - void OnSettingsEnd() override { LOG(FATAL); }
|
| - void OnGoAway(SpdyStreamId last_accepted_stream_id,
|
| - SpdyGoAwayStatus status) override {
|
| - LOG(FATAL);
|
| - }
|
| -
|
| - void OnHeaders(SpdyStreamId stream_id, bool has_priority,
|
| - SpdyPriority priority, bool fin, bool end) override {
|
| - SpdyFramer framer(version_);
|
| - framer.set_enable_compression(false);
|
| - SpdyHeadersIR headers(stream_id);
|
| - headers.set_has_priority(has_priority);
|
| - if (headers.has_priority()) {
|
| - headers.set_priority(priority);
|
| - }
|
| - headers.set_fin(fin);
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
|
| - ResetBuffer();
|
| - memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
|
| - size_ += framer.GetHeadersMinimumSize();
|
| - }
|
| -
|
| - virtual void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) {
|
| - LOG(FATAL);
|
| - }
|
| -
|
| - void OnPushPromise(SpdyStreamId stream_id,
|
| - SpdyStreamId promised_stream_id,
|
| - bool end) override {
|
| - SpdyFramer framer(version_);
|
| - framer.set_enable_compression(false);
|
| - SpdyPushPromiseIR push_promise(stream_id, promised_stream_id);
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializePushPromise(push_promise));
|
| - ResetBuffer();
|
| - memcpy(buffer_.get(), frame->data(), framer.GetPushPromiseMinimumSize());
|
| - size_ += framer.GetPushPromiseMinimumSize();
|
| - }
|
| -
|
| - void OnContinuation(SpdyStreamId stream_id, bool end) override {
|
| - LOG(FATAL);
|
| - }
|
| -
|
| - void OnPriority(SpdyStreamId stream_id,
|
| - SpdyStreamId parent_stream_id,
|
| - uint8 weight,
|
| - bool exclusive) override {
|
| - // Do nothing.
|
| - }
|
| -
|
| - bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
|
| - LOG(FATAL);
|
| - return false;
|
| - }
|
| -
|
| - char* ReleaseBuffer() {
|
| - CHECK(finished_);
|
| - return buffer_.release();
|
| - }
|
| -
|
| - void OnWindowUpdate(SpdyStreamId stream_id,
|
| - uint32 delta_window_size) override {
|
| - LOG(FATAL);
|
| - }
|
| -
|
| - size_t size() const {
|
| - CHECK(finished_);
|
| - return size_;
|
| - }
|
| -
|
| - private:
|
| - SpdyMajorVersion version_;
|
| - scoped_ptr<char[]> buffer_;
|
| - size_t size_;
|
| - bool finished_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(DecompressionVisitor);
|
| - };
|
| -
|
| - private:
|
| - DISALLOW_COPY_AND_ASSIGN(SpdyFramerTestUtil);
|
| -};
|
| -
|
| -class TestSpdyVisitor : public SpdyFramerVisitorInterface,
|
| - public SpdyFramerDebugVisitorInterface {
|
| - public:
|
| - // This is larger than our max frame size because header blocks that
|
| - // are too long can spill over into CONTINUATION frames.
|
| - static const size_t kDefaultHeaderBufferSize = 16 * 1024 * 1024;
|
| -
|
| - explicit TestSpdyVisitor(SpdyMajorVersion version)
|
| - : framer_(version),
|
| - use_compression_(false),
|
| - error_count_(0),
|
| - syn_frame_count_(0),
|
| - syn_reply_frame_count_(0),
|
| - headers_frame_count_(0),
|
| - push_promise_frame_count_(0),
|
| - goaway_count_(0),
|
| - setting_count_(0),
|
| - settings_ack_sent_(0),
|
| - settings_ack_received_(0),
|
| - continuation_count_(0),
|
| - altsvc_count_(0),
|
| - priority_count_(0),
|
| - test_altsvc_ir_(0),
|
| - on_unknown_frame_result_(false),
|
| - last_window_update_stream_(0),
|
| - last_window_update_delta_(0),
|
| - last_push_promise_stream_(0),
|
| - last_push_promise_promised_stream_(0),
|
| - data_bytes_(0),
|
| - fin_frame_count_(0),
|
| - fin_opaque_data_(),
|
| - fin_flag_count_(0),
|
| - zero_length_data_frame_count_(0),
|
| - control_frame_header_data_count_(0),
|
| - zero_length_control_frame_header_data_count_(0),
|
| - data_frame_count_(0),
|
| - last_payload_len_(0),
|
| - last_frame_len_(0),
|
| - header_buffer_(new char[kDefaultHeaderBufferSize]),
|
| - header_buffer_length_(0),
|
| - header_buffer_size_(kDefaultHeaderBufferSize),
|
| - header_stream_id_(static_cast<SpdyStreamId>(-1)),
|
| - header_control_type_(DATA),
|
| - header_buffer_valid_(false) {}
|
| -
|
| - void OnError(SpdyFramer* f) override {
|
| - LOG(INFO) << "SpdyFramer Error: "
|
| - << SpdyFramer::ErrorCodeToString(f->error_code());
|
| - ++error_count_;
|
| - }
|
| -
|
| - void OnDataFrameHeader(SpdyStreamId stream_id,
|
| - size_t length,
|
| - bool fin) override {
|
| - ++data_frame_count_;
|
| - header_stream_id_ = stream_id;
|
| - }
|
| -
|
| - void OnStreamFrameData(SpdyStreamId stream_id,
|
| - const char* data,
|
| - size_t len,
|
| - bool fin) override {
|
| - EXPECT_EQ(header_stream_id_, stream_id);
|
| - if (len == 0)
|
| - ++zero_length_data_frame_count_;
|
| -
|
| - data_bytes_ += len;
|
| - std::cerr << "OnStreamFrameData(" << stream_id << ", \"";
|
| - if (len > 0) {
|
| - for (size_t i = 0 ; i < len; ++i) {
|
| - std::cerr << std::hex << (0xFF & static_cast<unsigned int>(data[i]))
|
| - << std::dec;
|
| - }
|
| - }
|
| - std::cerr << "\", " << len << ")\n";
|
| - }
|
| -
|
| - bool OnControlFrameHeaderData(SpdyStreamId stream_id,
|
| - const char* header_data,
|
| - size_t len) override {
|
| - ++control_frame_header_data_count_;
|
| - CHECK_EQ(header_stream_id_, stream_id);
|
| - if (len == 0) {
|
| - ++zero_length_control_frame_header_data_count_;
|
| - // Indicates end-of-header-block.
|
| - headers_.clear();
|
| - CHECK(header_buffer_valid_);
|
| - size_t parsed_length = framer_.ParseHeaderBlockInBuffer(
|
| - header_buffer_.get(), header_buffer_length_, &headers_);
|
| - LOG_IF(DFATAL, header_buffer_length_ != parsed_length)
|
| - << "Check failed: header_buffer_length_ == parsed_length "
|
| - << "(" << header_buffer_length_ << " vs. " << parsed_length << ")";
|
| - return true;
|
| - }
|
| - const size_t available = header_buffer_size_ - header_buffer_length_;
|
| - if (len > available) {
|
| - header_buffer_valid_ = false;
|
| - return false;
|
| - }
|
| - memcpy(header_buffer_.get() + header_buffer_length_, header_data, len);
|
| - header_buffer_length_ += len;
|
| - return true;
|
| - }
|
| -
|
| - void OnSynStream(SpdyStreamId stream_id,
|
| - SpdyStreamId associated_stream_id,
|
| - SpdyPriority priority,
|
| - bool fin,
|
| - bool unidirectional) override {
|
| - ++syn_frame_count_;
|
| - if (framer_.protocol_version() > SPDY3) {
|
| - InitHeaderStreaming(HEADERS, stream_id);
|
| - } else {
|
| - InitHeaderStreaming(SYN_STREAM, stream_id);
|
| - }
|
| - if (fin) {
|
| - ++fin_flag_count_;
|
| - }
|
| - }
|
| -
|
| - void OnSynReply(SpdyStreamId stream_id, bool fin) override {
|
| - ++syn_reply_frame_count_;
|
| - if (framer_.protocol_version() > SPDY3) {
|
| - InitHeaderStreaming(HEADERS, stream_id);
|
| - } else {
|
| - InitHeaderStreaming(SYN_REPLY, stream_id);
|
| - }
|
| - if (fin) {
|
| - ++fin_flag_count_;
|
| - }
|
| - }
|
| -
|
| - void OnRstStream(SpdyStreamId stream_id,
|
| - SpdyRstStreamStatus status) override {
|
| - ++fin_frame_count_;
|
| - }
|
| -
|
| - bool OnRstStreamFrameData(const char* rst_stream_data, size_t len) override {
|
| - if ((rst_stream_data != NULL) && (len > 0)) {
|
| - fin_opaque_data_ += string(rst_stream_data, len);
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {
|
| - ++setting_count_;
|
| - }
|
| -
|
| - void OnSettingsAck() override {
|
| - DCHECK_LT(SPDY3, framer_.protocol_version());
|
| - ++settings_ack_received_;
|
| - }
|
| -
|
| - void OnSettingsEnd() override {
|
| - if (framer_.protocol_version() <= SPDY3) { return; }
|
| - ++settings_ack_sent_;
|
| - }
|
| -
|
| - void OnPing(SpdyPingId unique_id, bool is_ack) override { DLOG(FATAL); }
|
| -
|
| - void OnGoAway(SpdyStreamId last_accepted_stream_id,
|
| - SpdyGoAwayStatus status) override {
|
| - ++goaway_count_;
|
| - }
|
| -
|
| - void OnHeaders(SpdyStreamId stream_id, bool has_priority,
|
| - SpdyPriority priority, bool fin, bool end) override {
|
| - ++headers_frame_count_;
|
| - InitHeaderStreaming(HEADERS, stream_id);
|
| - if (fin) {
|
| - ++fin_flag_count_;
|
| - }
|
| - }
|
| -
|
| - void OnWindowUpdate(SpdyStreamId stream_id,
|
| - uint32 delta_window_size) override {
|
| - last_window_update_stream_ = stream_id;
|
| - last_window_update_delta_ = delta_window_size;
|
| - }
|
| -
|
| - void OnPushPromise(SpdyStreamId stream_id,
|
| - SpdyStreamId promised_stream_id,
|
| - bool end) override {
|
| - ++push_promise_frame_count_;
|
| - InitHeaderStreaming(PUSH_PROMISE, stream_id);
|
| - last_push_promise_stream_ = stream_id;
|
| - last_push_promise_promised_stream_ = promised_stream_id;
|
| - }
|
| -
|
| - void OnContinuation(SpdyStreamId stream_id, bool end) override {
|
| - ++continuation_count_;
|
| - }
|
| -
|
| - void OnAltSvc(SpdyStreamId stream_id,
|
| - uint32 max_age,
|
| - uint16 port,
|
| - StringPiece protocol_id,
|
| - StringPiece host,
|
| - StringPiece origin) override {
|
| - test_altsvc_ir_.set_stream_id(stream_id);
|
| - test_altsvc_ir_.set_max_age(max_age);
|
| - test_altsvc_ir_.set_port(port);
|
| - test_altsvc_ir_.set_protocol_id(protocol_id.as_string());
|
| - test_altsvc_ir_.set_host(host.as_string());
|
| - if (origin.length() > 0) {
|
| - test_altsvc_ir_.set_origin(origin.as_string());
|
| - }
|
| - ++altsvc_count_;
|
| - }
|
| -
|
| - void OnPriority(SpdyStreamId stream_id,
|
| - SpdyStreamId parent_stream_id,
|
| - uint8 weight,
|
| - bool exclusive) override {
|
| - ++priority_count_;
|
| - }
|
| -
|
| - bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
|
| - DLOG(INFO) << "Unknown frame type " << frame_type;
|
| - return on_unknown_frame_result_;
|
| - }
|
| -
|
| - void OnSendCompressedFrame(SpdyStreamId stream_id,
|
| - SpdyFrameType type,
|
| - size_t payload_len,
|
| - size_t frame_len) override {
|
| - last_payload_len_ = payload_len;
|
| - last_frame_len_ = frame_len;
|
| - }
|
| -
|
| - void OnReceiveCompressedFrame(SpdyStreamId stream_id,
|
| - SpdyFrameType type,
|
| - size_t frame_len) override {
|
| - last_frame_len_ = frame_len;
|
| - }
|
| -
|
| - // Convenience function which runs a framer simulation with particular input.
|
| - void SimulateInFramer(const unsigned char* input, size_t size) {
|
| - framer_.set_enable_compression(use_compression_);
|
| - framer_.set_visitor(this);
|
| - size_t input_remaining = size;
|
| - const char* input_ptr = reinterpret_cast<const char*>(input);
|
| - while (input_remaining > 0 &&
|
| - framer_.error_code() == SpdyFramer::SPDY_NO_ERROR) {
|
| - // To make the tests more interesting, we feed random (amd small) chunks
|
| - // into the framer. This simulates getting strange-sized reads from
|
| - // the socket.
|
| - const size_t kMaxReadSize = 32;
|
| - size_t bytes_read =
|
| - (rand() % std::min(input_remaining, kMaxReadSize)) + 1;
|
| - size_t bytes_processed = framer_.ProcessInput(input_ptr, bytes_read);
|
| - input_remaining -= bytes_processed;
|
| - input_ptr += bytes_processed;
|
| - }
|
| - }
|
| -
|
| - void InitHeaderStreaming(SpdyFrameType header_control_type,
|
| - SpdyStreamId stream_id) {
|
| - if (!SpdyConstants::IsValidFrameType(framer_.protocol_version(),
|
| - SpdyConstants::SerializeFrameType(framer_.protocol_version(),
|
| - header_control_type))) {
|
| - DLOG(FATAL) << "Attempted to init header streaming with "
|
| - << "invalid control frame type: "
|
| - << header_control_type;
|
| - }
|
| - memset(header_buffer_.get(), 0, header_buffer_size_);
|
| - header_buffer_length_ = 0;
|
| - header_stream_id_ = stream_id;
|
| - header_control_type_ = header_control_type;
|
| - header_buffer_valid_ = true;
|
| - DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream);
|
| - }
|
| -
|
| - // Override the default buffer size (16K). Call before using the framer!
|
| - void set_header_buffer_size(size_t header_buffer_size) {
|
| - header_buffer_size_ = header_buffer_size;
|
| - header_buffer_.reset(new char[header_buffer_size]);
|
| - }
|
| -
|
| - // Largest control frame that the SPDY implementation sends, including the
|
| - // size of the header.
|
| - static size_t sent_control_frame_max_size() {
|
| - return SpdyFramer::kMaxControlFrameSize;
|
| - }
|
| -
|
| - static size_t header_data_chunk_max_size() {
|
| - return SpdyFramer::kHeaderDataChunkMaxSize;
|
| - }
|
| -
|
| - SpdyFramer framer_;
|
| - bool use_compression_;
|
| -
|
| - // Counters from the visitor callbacks.
|
| - int error_count_;
|
| - int syn_frame_count_;
|
| - int syn_reply_frame_count_;
|
| - int headers_frame_count_;
|
| - int push_promise_frame_count_;
|
| - int goaway_count_;
|
| - int setting_count_;
|
| - int settings_ack_sent_;
|
| - int settings_ack_received_;
|
| - int continuation_count_;
|
| - int altsvc_count_;
|
| - int priority_count_;
|
| - SpdyAltSvcIR test_altsvc_ir_;
|
| - bool on_unknown_frame_result_;
|
| - SpdyStreamId last_window_update_stream_;
|
| - uint32 last_window_update_delta_;
|
| - SpdyStreamId last_push_promise_stream_;
|
| - SpdyStreamId last_push_promise_promised_stream_;
|
| - int data_bytes_;
|
| - int fin_frame_count_; // The count of RST_STREAM type frames received.
|
| - string fin_opaque_data_;
|
| - int fin_flag_count_; // The count of frames with the FIN flag set.
|
| - int zero_length_data_frame_count_; // The count of zero-length data frames.
|
| - int control_frame_header_data_count_; // The count of chunks received.
|
| - // The count of zero-length control frame header data chunks received.
|
| - int zero_length_control_frame_header_data_count_;
|
| - int data_frame_count_;
|
| - size_t last_payload_len_;
|
| - size_t last_frame_len_;
|
| -
|
| - // Header block streaming state:
|
| - scoped_ptr<char[]> header_buffer_;
|
| - size_t header_buffer_length_;
|
| - size_t header_buffer_size_;
|
| - SpdyStreamId header_stream_id_;
|
| - SpdyFrameType header_control_type_;
|
| - bool header_buffer_valid_;
|
| - SpdyHeaderBlock headers_;
|
| -};
|
| -
|
| -// Retrieves serialized headers from a HEADERS or SYN_STREAM frame.
|
| -base::StringPiece GetSerializedHeaders(const SpdyFrame* frame,
|
| - const SpdyFramer& framer) {
|
| - SpdyFrameReader reader(frame->data(), frame->size());
|
| - if (framer.protocol_version() > SPDY3) {
|
| - reader.Seek(3); // Seek past the frame length.
|
| - } else {
|
| - reader.Seek(2); // Seek past the frame length.
|
| - }
|
| - SpdyFrameType frame_type;
|
| - if (framer.protocol_version() > SPDY3) {
|
| - uint8 serialized_type;
|
| - reader.ReadUInt8(&serialized_type);
|
| - frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
|
| - serialized_type);
|
| - DCHECK_EQ(HEADERS, frame_type);
|
| - uint8 flags;
|
| - reader.ReadUInt8(&flags);
|
| - if (flags & HEADERS_FLAG_PRIORITY) {
|
| - frame_type = SYN_STREAM;
|
| - }
|
| - } else {
|
| - uint16 serialized_type;
|
| - reader.ReadUInt16(&serialized_type);
|
| - frame_type = SpdyConstants::ParseFrameType(framer.protocol_version(),
|
| - serialized_type);
|
| - DCHECK(frame_type == HEADERS ||
|
| - frame_type == SYN_STREAM) << frame_type;
|
| - }
|
| -
|
| - if (frame_type == SYN_STREAM) {
|
| - return StringPiece(frame->data() + framer.GetSynStreamMinimumSize(),
|
| - frame->size() - framer.GetSynStreamMinimumSize());
|
| - } else {
|
| - return StringPiece(frame->data() + framer.GetHeadersMinimumSize(),
|
| - frame->size() - framer.GetHeadersMinimumSize());
|
| - }
|
| -}
|
| -
|
| -} // namespace test
|
| -
|
| -} // namespace net
|
| -
|
| -using net::test::SetFrameLength;
|
| -using net::test::SetFrameFlags;
|
| -using net::test::CompareCharArraysWithHexError;
|
| -using net::test::SpdyFramerTestUtil;
|
| -using net::test::TestSpdyVisitor;
|
| -using net::test::GetSerializedHeaders;
|
| -
|
| -namespace net {
|
| -
|
| -class SpdyFramerTest : public ::testing::TestWithParam<SpdyMajorVersion> {
|
| - protected:
|
| - void SetUp() override {
|
| - spdy_version_ = GetParam();
|
| - spdy_version_ch_ = static_cast<unsigned char>(
|
| - SpdyConstants::SerializeMajorVersion(spdy_version_));
|
| - }
|
| -
|
| - void CompareFrame(const string& description,
|
| - const SpdyFrame& actual_frame,
|
| - const unsigned char* expected,
|
| - const int expected_len) {
|
| - const unsigned char* actual =
|
| - reinterpret_cast<const unsigned char*>(actual_frame.data());
|
| - CompareCharArraysWithHexError(
|
| - description, actual, actual_frame.size(), expected, expected_len);
|
| - }
|
| -
|
| - void CompareFrames(const string& description,
|
| - const SpdyFrame& expected_frame,
|
| - const SpdyFrame& actual_frame) {
|
| - CompareCharArraysWithHexError(
|
| - description,
|
| - reinterpret_cast<const unsigned char*>(expected_frame.data()),
|
| - expected_frame.size(),
|
| - reinterpret_cast<const unsigned char*>(actual_frame.data()),
|
| - actual_frame.size());
|
| - }
|
| -
|
| - // Returns true if the two header blocks have equivalent content.
|
| - bool CompareHeaderBlocks(const SpdyHeaderBlock* expected,
|
| - const SpdyHeaderBlock* actual) {
|
| - if (expected->size() != actual->size()) {
|
| - LOG(ERROR) << "Expected " << expected->size() << " headers; actually got "
|
| - << actual->size() << ".";
|
| - return false;
|
| - }
|
| - for (SpdyHeaderBlock::const_iterator it = expected->begin();
|
| - it != expected->end();
|
| - ++it) {
|
| - SpdyHeaderBlock::const_iterator it2 = actual->find(it->first);
|
| - if (it2 == actual->end()) {
|
| - LOG(ERROR) << "Expected header name '" << it->first << "'.";
|
| - return false;
|
| - }
|
| - if (it->second.compare(it2->second) != 0) {
|
| - LOG(ERROR) << "Expected header named '" << it->first
|
| - << "' to have a value of '" << it->second
|
| - << "'. The actual value received was '" << it2->second
|
| - << "'.";
|
| - return false;
|
| - }
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - bool IsSpdy2() { return spdy_version_ == SPDY2; }
|
| - bool IsSpdy3() { return spdy_version_ == SPDY3; }
|
| - bool IsSpdy4() { return spdy_version_ == SPDY4; }
|
| -
|
| - // Version of SPDY protocol to be used.
|
| - SpdyMajorVersion spdy_version_;
|
| - unsigned char spdy_version_ch_;
|
| -};
|
| -
|
| -// All tests are run with 3 different SPDY versions: SPDY/2, SPDY/3, SPDY/4.
|
| -INSTANTIATE_TEST_CASE_P(SpdyFramerTests,
|
| - SpdyFramerTest,
|
| - ::testing::Values(SPDY2, SPDY3, SPDY4));
|
| -
|
| -// Test that we ignore cookie where both name and value are empty.
|
| -TEST_P(SpdyFramerTest, HeaderBlockWithEmptyCookie) {
|
| - if (spdy_version_ > SPDY3) {
|
| - // Not implemented for hpack.
|
| - return;
|
| - }
|
| -
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_enable_compression(true);
|
| - SpdyHeadersIR headers(1);
|
| - headers.set_priority(1);
|
| - headers.SetHeader("cookie",
|
| - "=; key=value; ; = ; foo; bar=; ; = ; k2=v2 ; =");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
|
| - EXPECT_TRUE(frame.get() != NULL);
|
| -
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = true;
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(frame->data()),
|
| - frame->size());
|
| -
|
| - EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
|
| - EXPECT_FALSE(CompareHeaderBlocks(&headers.name_value_block(),
|
| - &visitor.headers_));
|
| - EXPECT_EQ(1u, visitor.headers_.size());
|
| - EXPECT_EQ("key=value; foo; bar=; k2=v2 ", visitor.headers_["cookie"]);
|
| -}
|
| -
|
| -// Test that we can encode and decode a SpdyHeaderBlock in serialized form.
|
| -TEST_P(SpdyFramerTest, HeaderBlockInBuffer) {
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_enable_compression(false);
|
| -
|
| - // Encode the header block into a Headers frame.
|
| - SpdyHeadersIR headers(1);
|
| - headers.set_priority(1);
|
| - headers.SetHeader("alpha", "beta");
|
| - headers.SetHeader("gamma", "charlie");
|
| - headers.SetHeader("cookie", "key1=value1; key2=value2");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
|
| - EXPECT_TRUE(frame.get() != NULL);
|
| -
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = false;
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(frame->data()),
|
| - frame->size());
|
| -
|
| - EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
|
| - EXPECT_TRUE(CompareHeaderBlocks(&headers.name_value_block(),
|
| - &visitor.headers_));
|
| -}
|
| -
|
| -// Test that if there's not a full frame, we fail to parse it.
|
| -TEST_P(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_enable_compression(false);
|
| -
|
| - // Encode the header block into a Headers frame.
|
| - SpdyHeadersIR headers(1);
|
| - headers.set_priority(1);
|
| - headers.SetHeader("alpha", "beta");
|
| - headers.SetHeader("gamma", "charlie");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers));
|
| - EXPECT_TRUE(frame.get() != NULL);
|
| -
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = false;
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(frame->data()),
|
| - frame->size() - 2);
|
| -
|
| - EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
|
| - EXPECT_EQ(0u, visitor.headers_.size());
|
| -}
|
| -
|
| -// Test that if we receive a SYN_REPLY with stream ID zero, we signal an error
|
| -// (but don't crash).
|
| -TEST_P(SpdyFramerTest, SynReplyWithStreamIdZero) {
|
| - if (spdy_version_ > SPDY3) {
|
| - return;
|
| - }
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - SpdySynReplyIR syn_reply(0);
|
| - syn_reply.SetHeader("alpha", "beta");
|
| - scoped_ptr<SpdySerializedFrame> frame(framer.SerializeSynReply(syn_reply));
|
| - ASSERT_TRUE(frame.get() != NULL);
|
| -
|
| - // We shouldn't have to read the whole frame before we signal an error.
|
| - EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
|
| - EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
|
| - EXPECT_TRUE(framer.HasError());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| -}
|
| -
|
| -// Test that if we receive a HEADERS with stream ID zero, we signal an error
|
| -// (but don't crash).
|
| -TEST_P(SpdyFramerTest, HeadersWithStreamIdZero) {
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - SpdyHeadersIR headers_ir(0);
|
| - headers_ir.SetHeader("alpha", "beta");
|
| - scoped_ptr<SpdySerializedFrame> frame(framer.SerializeHeaders(headers_ir));
|
| - ASSERT_TRUE(frame.get() != NULL);
|
| -
|
| - // We shouldn't have to read the whole frame before we signal an error.
|
| - EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
|
| - EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
|
| - EXPECT_TRUE(framer.HasError());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| -}
|
| -
|
| -// Test that if we receive a PUSH_PROMISE with stream ID zero, we signal an
|
| -// error (but don't crash).
|
| -TEST_P(SpdyFramerTest, PushPromiseWithStreamIdZero) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - SpdyPushPromiseIR push_promise(0, 4);
|
| - push_promise.SetHeader("alpha", "beta");
|
| - scoped_ptr<SpdySerializedFrame> frame(
|
| - framer.SerializePushPromise(push_promise));
|
| - ASSERT_TRUE(frame.get() != NULL);
|
| -
|
| - // We shouldn't have to read the whole frame before we signal an error.
|
| - EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
|
| - EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
|
| - EXPECT_TRUE(framer.HasError());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| -}
|
| -
|
| -// Test that if we receive a PUSH_PROMISE with promised stream ID zero, we
|
| -// signal an error (but don't crash).
|
| -TEST_P(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - SpdyPushPromiseIR push_promise(3, 0);
|
| - push_promise.SetHeader("alpha", "beta");
|
| - scoped_ptr<SpdySerializedFrame> frame(
|
| - framer.SerializePushPromise(push_promise));
|
| - ASSERT_TRUE(frame.get() != NULL);
|
| -
|
| - // We shouldn't have to read the whole frame before we signal an error.
|
| - EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
|
| - EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
|
| - EXPECT_TRUE(framer.HasError());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, DuplicateHeader) {
|
| - if (spdy_version_ > SPDY3) {
|
| - // TODO(jgraettinger): Punting on this because we haven't determined
|
| - // whether duplicate HPACK headers other than Cookie are an error.
|
| - // If they are, this will need to be updated to use HpackOutputStream.
|
| - return;
|
| - }
|
| - SpdyFramer framer(spdy_version_);
|
| - // Frame builder with plentiful buffer size.
|
| - SpdyFrameBuilder frame(1024, spdy_version_);
|
| - if (spdy_version_ <= SPDY3) {
|
| - frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
|
| - frame.WriteUInt32(3); // stream_id
|
| - frame.WriteUInt32(0); // associated stream id
|
| - frame.WriteUInt16(0); // Priority.
|
| - } else {
|
| - frame.BeginNewFrame(framer, HEADERS, HEADERS_FLAG_PRIORITY, 3);
|
| - frame.WriteUInt32(framer.GetHighestPriority());
|
| - }
|
| -
|
| - if (IsSpdy2()) {
|
| - frame.WriteUInt16(2); // Number of headers.
|
| - frame.WriteString("name");
|
| - frame.WriteString("value1");
|
| - frame.WriteString("name");
|
| - frame.WriteString("value2");
|
| - } else {
|
| - frame.WriteUInt32(2); // Number of headers.
|
| - frame.WriteStringPiece32("name");
|
| - frame.WriteStringPiece32("value1");
|
| - frame.WriteStringPiece32("name");
|
| - frame.WriteStringPiece32("value2");
|
| - }
|
| - // write the length
|
| - frame.RewriteLength(framer);
|
| -
|
| - SpdyHeaderBlock new_headers;
|
| - framer.set_enable_compression(false);
|
| - scoped_ptr<SpdyFrame> control_frame(frame.take());
|
| - base::StringPiece serialized_headers =
|
| - GetSerializedHeaders(control_frame.get(), framer);
|
| - // This should fail because duplicate headers are verboten by the spec.
|
| - EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
|
| - serialized_headers.size(),
|
| - &new_headers));
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, MultiValueHeader) {
|
| - SpdyFramer framer(spdy_version_);
|
| - // Frame builder with plentiful buffer size.
|
| - SpdyFrameBuilder frame(1024, spdy_version_);
|
| - if (spdy_version_ <= SPDY3) {
|
| - frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
|
| - frame.WriteUInt32(3); // stream_id
|
| - frame.WriteUInt32(0); // associated stream id
|
| - frame.WriteUInt16(0); // Priority.
|
| - } else {
|
| - frame.BeginNewFrame(framer,
|
| - HEADERS,
|
| - HEADERS_FLAG_PRIORITY | HEADERS_FLAG_END_HEADERS,
|
| - 3);
|
| - frame.WriteUInt32(0); // Priority exclusivity and dependent stream.
|
| - frame.WriteUInt8(255); // Priority weight.
|
| - }
|
| -
|
| - string value("value1\0value2", 13);
|
| - if (IsSpdy2()) {
|
| - frame.WriteUInt16(1); // Number of headers.
|
| - frame.WriteString("name");
|
| - frame.WriteString(value);
|
| - } else if (spdy_version_ > SPDY3) {
|
| - // TODO(jgraettinger): If this pattern appears again, move to test class.
|
| - std::map<string, string> header_set;
|
| - header_set["name"] = value;
|
| - string buffer;
|
| - HpackEncoder encoder(ObtainHpackHuffmanTable());
|
| - encoder.EncodeHeaderSetWithoutCompression(header_set, &buffer);
|
| - frame.WriteBytes(&buffer[0], buffer.size());
|
| - } else {
|
| - frame.WriteUInt32(1); // Number of headers.
|
| - frame.WriteStringPiece32("name");
|
| - frame.WriteStringPiece32(value);
|
| - }
|
| - // write the length
|
| - frame.RewriteLength(framer);
|
| -
|
| - framer.set_enable_compression(false);
|
| - scoped_ptr<SpdyFrame> control_frame(frame.take());
|
| -
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = false;
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(control_frame->data()),
|
| - control_frame->size());
|
| -
|
| - EXPECT_THAT(visitor.headers_,
|
| - testing::ElementsAre(testing::Pair("name", value)));
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, BasicCompression) {
|
| - if (spdy_version_ > SPDY3) {
|
| - // Deflate compression doesn't apply to HPACK.
|
| - return;
|
| - }
|
| - scoped_ptr<TestSpdyVisitor> visitor(new TestSpdyVisitor(spdy_version_));
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_debug_visitor(visitor.get());
|
| - SpdySynStreamIR syn_stream(1);
|
| - syn_stream.set_priority(1);
|
| - syn_stream.SetHeader("server", "SpdyServer 1.0");
|
| - syn_stream.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
|
| - syn_stream.SetHeader("status", "200");
|
| - syn_stream.SetHeader("version", "HTTP/1.1");
|
| - syn_stream.SetHeader("content-type", "text/html");
|
| - syn_stream.SetHeader("content-length", "12");
|
| - scoped_ptr<SpdyFrame> frame1(framer.SerializeSynStream(syn_stream));
|
| - size_t uncompressed_size1 = visitor->last_payload_len_;
|
| - size_t compressed_size1 =
|
| - visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
|
| - if (IsSpdy2()) {
|
| - EXPECT_EQ(139u, uncompressed_size1);
|
| -#if defined(USE_SYSTEM_ZLIB)
|
| - EXPECT_EQ(155u, compressed_size1);
|
| -#else // !defined(USE_SYSTEM_ZLIB)
|
| - EXPECT_EQ(135u, compressed_size1);
|
| -#endif // !defined(USE_SYSTEM_ZLIB)
|
| - } else {
|
| - EXPECT_EQ(165u, uncompressed_size1);
|
| -#if defined(USE_SYSTEM_ZLIB)
|
| - EXPECT_EQ(181u, compressed_size1);
|
| -#else // !defined(USE_SYSTEM_ZLIB)
|
| - EXPECT_EQ(117u, compressed_size1);
|
| -#endif // !defined(USE_SYSTEM_ZLIB)
|
| - }
|
| - scoped_ptr<SpdyFrame> frame2(framer.SerializeSynStream(syn_stream));
|
| - size_t uncompressed_size2 = visitor->last_payload_len_;
|
| - size_t compressed_size2 =
|
| - visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
|
| -
|
| - // Expect the second frame to be more compact than the first.
|
| - EXPECT_LE(frame2->size(), frame1->size());
|
| -
|
| - // Decompress the first frame
|
| - scoped_ptr<SpdyFrame> frame3(
|
| - SpdyFramerTestUtil::DecompressFrame(&framer, *frame1));
|
| -
|
| - // Decompress the second frame
|
| - visitor.reset(new TestSpdyVisitor(spdy_version_));
|
| - framer.set_debug_visitor(visitor.get());
|
| - scoped_ptr<SpdyFrame> frame4(
|
| - SpdyFramerTestUtil::DecompressFrame(&framer, *frame2));
|
| - size_t uncompressed_size4 =
|
| - frame4->size() - framer.GetSynStreamMinimumSize();
|
| - size_t compressed_size4 =
|
| - visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
|
| - if (IsSpdy2()) {
|
| - EXPECT_EQ(139u, uncompressed_size4);
|
| -#if defined(USE_SYSTEM_ZLIB)
|
| - EXPECT_EQ(149u, compressed_size4);
|
| -#else // !defined(USE_SYSTEM_ZLIB)
|
| - EXPECT_EQ(101u, compressed_size4);
|
| -#endif // !defined(USE_SYSTEM_ZLIB)
|
| - } else {
|
| - EXPECT_EQ(165u, uncompressed_size4);
|
| -#if defined(USE_SYSTEM_ZLIB)
|
| - EXPECT_EQ(175u, compressed_size4);
|
| -#else // !defined(USE_SYSTEM_ZLIB)
|
| - EXPECT_EQ(102u, compressed_size4);
|
| -#endif // !defined(USE_SYSTEM_ZLIB)
|
| - }
|
| -
|
| - EXPECT_EQ(uncompressed_size1, uncompressed_size2);
|
| - EXPECT_EQ(uncompressed_size1, uncompressed_size4);
|
| - EXPECT_EQ(compressed_size2, compressed_size4);
|
| -
|
| - // Expect frames 3 & 4 to be the same.
|
| - CompareFrames("Uncompressed SYN_STREAM", *frame3, *frame4);
|
| -
|
| - // Expect frames 3 to be the same as a uncompressed frame created
|
| - // from scratch.
|
| - framer.set_enable_compression(false);
|
| - scoped_ptr<SpdyFrame> uncompressed_frame(
|
| - framer.SerializeSynStream(syn_stream));
|
| - CompareFrames("Uncompressed SYN_STREAM", *frame3, *uncompressed_frame);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, CompressEmptyHeaders) {
|
| - // See crbug.com/172383
|
| - SpdyHeadersIR headers(1);
|
| - headers.SetHeader("server", "SpdyServer 1.0");
|
| - headers.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
|
| - headers.SetHeader("status", "200");
|
| - headers.SetHeader("version", "HTTP/1.1");
|
| - headers.SetHeader("content-type", "text/html");
|
| - headers.SetHeader("content-length", "12");
|
| - headers.SetHeader("x-empty-header", "");
|
| -
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_enable_compression(true);
|
| - scoped_ptr<SpdyFrame> frame1(framer.SerializeHeaders(headers));
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, Basic) {
|
| - const unsigned char kV2Input[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
|
| - 0x00, 0x00, 0x00, 0x14,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x02, 'h', 'h',
|
| - 0x00, 0x02, 'v', 'v',
|
| -
|
| - 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
|
| - 0x00, 0x00, 0x00, 0x18,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 0x00, 0x02, 'h', '2',
|
| - 0x00, 0x02, 'v', '2',
|
| - 0x00, 0x02, 'h', '3',
|
| - 0x00, 0x02, 'v', '3',
|
| -
|
| - 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
|
| - 0x00, 0x00, 0x00, 0x0c,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| -
|
| - 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
|
| - 0x00, 0x00, 0x00, 0x0c,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| -
|
| - 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| -
|
| - 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
|
| - 0x00, 0x00, 0x00, 0x04,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| -
|
| - 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
|
| -
|
| - 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
|
| - 0x00, 0x00, 0x00, 0x00,
|
| -
|
| - 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
|
| - };
|
| -
|
| - const unsigned char kV3Input[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
|
| - 0x00, 0x00, 0x00, 0x1a,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x01, 0x00, 0x00,
|
| - 0x00, 0x02, 'h', 'h',
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 'v', 'v',
|
| -
|
| - 0x80, spdy_version_ch_, 0x00, 0x08, // HEADERS on Stream #1
|
| - 0x00, 0x00, 0x00, 0x20,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 'h', '2',
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 'v', '2', 0x00, 0x00,
|
| - 0x00, 0x02, 'h', '3',
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 'v', '3',
|
| -
|
| - 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
|
| - 0x00, 0x00, 0x00, 0x0c,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| -
|
| - 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #3
|
| - 0x00, 0x00, 0x00, 0x0e,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00,
|
| -
|
| - 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| -
|
| - 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
|
| - 0x00, 0x00, 0x00, 0x04,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| -
|
| - 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #1
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
|
| -
|
| - 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
|
| - 0x00, 0x00, 0x00, 0x00,
|
| -
|
| - 0x80, spdy_version_ch_, 0x00, 0x03, // RST_STREAM on Stream #3
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 0x00, 0x00, 0x00, 0x05, // RST_STREAM_CANCEL
|
| - };
|
| -
|
| - // SYN_STREAM doesn't exist in SPDY4, so instead we send
|
| - // HEADERS frames with PRIORITY and END_HEADERS set.
|
| - const unsigned char kV4Input[] = {
|
| - 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
|
| - 0x24, 0x00, 0x00, 0x00,
|
| - 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
|
| - 0x00, 0x82, // :method: GET
|
| -
|
| - 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
|
| - 0x04, 0x00, 0x00, 0x00, // Stream 1
|
| - 0x01, 0x8c, // :status: 200
|
| -
|
| - 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x01, 0xde, 0xad, 0xbe,
|
| - 0xef, 0xde, 0xad, 0xbe,
|
| - 0xef, 0xde, 0xad, 0xbe,
|
| - 0xef,
|
| -
|
| - 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
|
| - 0x24, 0x00, 0x00, 0x00,
|
| - 0x03, 0x00, 0x00, 0x00, // Stream 3, Priority 0
|
| - 0x00, 0x82, // :method: GET
|
| -
|
| - 0x00, 0x00, 0x08, 0x00, // DATA on Stream #3
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x03, 0xde, 0xad, 0xbe,
|
| - 0xef, 0xde, 0xad, 0xbe,
|
| - 0xef,
|
| -
|
| - 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x01, 0xde, 0xad, 0xbe,
|
| - 0xef,
|
| -
|
| - 0x00, 0x00, 0x04, 0x03, // RST_STREAM on Stream #1
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x01, 0x00, 0x00, 0x00,
|
| - 0x08, // RST_STREAM_CANCEL
|
| -
|
| - 0x00, 0x00, 0x00, 0x00, // DATA on Stream #3
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x03,
|
| -
|
| - 0x00, 0x00, 0x0f, 0x03, // RST_STREAM on Stream #3
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x03, 0x00, 0x00, 0x00, // RST_STREAM_CANCEL
|
| - 0x08, 0x52, 0x45, 0x53, // opaque data
|
| - 0x45, 0x54, 0x53, 0x54,
|
| - 0x52, 0x45, 0x41, 0x4d,
|
| - };
|
| -
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - if (IsSpdy2()) {
|
| - visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
|
| - } else if (IsSpdy3()) {
|
| - visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
|
| - } else {
|
| - visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
|
| - }
|
| -
|
| - EXPECT_EQ(0, visitor.syn_reply_frame_count_);
|
| - EXPECT_EQ(24, visitor.data_bytes_);
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - EXPECT_EQ(2, visitor.fin_frame_count_);
|
| -
|
| - if (IsSpdy4()) {
|
| - EXPECT_EQ(3, visitor.headers_frame_count_);
|
| - EXPECT_EQ(0, visitor.syn_frame_count_);
|
| - base::StringPiece reset_stream = "RESETSTREAM";
|
| - EXPECT_EQ(reset_stream, visitor.fin_opaque_data_);
|
| - } else {
|
| - EXPECT_EQ(1, visitor.headers_frame_count_);
|
| - EXPECT_EQ(2, visitor.syn_frame_count_);
|
| - EXPECT_TRUE(visitor.fin_opaque_data_.empty());
|
| - }
|
| -
|
| - EXPECT_EQ(0, visitor.fin_flag_count_);
|
| - EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
|
| - EXPECT_EQ(4, visitor.data_frame_count_);
|
| - visitor.fin_opaque_data_.clear();
|
| -}
|
| -
|
| -// Test that the FIN flag on a data frame signifies EOF.
|
| -TEST_P(SpdyFramerTest, FinOnDataFrame) {
|
| - const unsigned char kV2Input[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
|
| - 0x00, 0x00, 0x00, 0x14,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x02, 'h', 'h',
|
| - 0x00, 0x02, 'v', 'v',
|
| -
|
| - 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
|
| - 0x00, 0x00, 0x00, 0x10,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x02, 'a', 'a',
|
| - 0x00, 0x02, 'b', 'b',
|
| -
|
| - 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
|
| - 0x00, 0x00, 0x00, 0x0c,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| -
|
| - 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
|
| - 0x01, 0x00, 0x00, 0x04,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| - };
|
| - const unsigned char kV3Input[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x01, // SYN Stream #1
|
| - 0x00, 0x00, 0x00, 0x1a,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x01, 0x00, 0x00,
|
| - 0x00, 0x02, 'h', 'h',
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 'v', 'v',
|
| -
|
| - 0x80, spdy_version_ch_, 0x00, 0x02, // SYN REPLY Stream #1
|
| - 0x00, 0x00, 0x00, 0x14,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 'a', 'a', 0x00, 0x00,
|
| - 0x00, 0x02, 'b', 'b',
|
| -
|
| - 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
|
| - 0x00, 0x00, 0x00, 0x0c,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| -
|
| - 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
|
| - 0x01, 0x00, 0x00, 0x04,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| - };
|
| -
|
| - // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
|
| - // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
|
| - const unsigned char kV4Input[] = {
|
| - 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
|
| - 0x24, 0x00, 0x00, 0x00, // Stream 1
|
| - 0x01, 0x00, 0x00, 0x00, // Priority 0
|
| - 0x00, 0x82, // :method: GET
|
| -
|
| - 0x00, 0x00, 0x01, 0x01, // HEADERS: END_HEADERS
|
| - 0x04, 0x00, 0x00, 0x00, // Stream 1
|
| - 0x01, 0x8c, // :status: 200
|
| -
|
| - 0x00, 0x00, 0x0c, 0x00, // DATA on Stream #1
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x01, 0xde, 0xad, 0xbe,
|
| - 0xef, 0xde, 0xad, 0xbe,
|
| - 0xef, 0xde, 0xad, 0xbe,
|
| - 0xef,
|
| -
|
| - 0x00, 0x00, 0x04, 0x00, // DATA on Stream #1, with FIN
|
| - 0x01, 0x00, 0x00, 0x00,
|
| - 0x01, 0xde, 0xad, 0xbe,
|
| - 0xef,
|
| - };
|
| -
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - if (IsSpdy2()) {
|
| - visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
|
| - } else if (IsSpdy3()) {
|
| - visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
|
| - } else {
|
| - visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
|
| - }
|
| -
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - if (IsSpdy4()) {
|
| - EXPECT_EQ(0, visitor.syn_frame_count_);
|
| - EXPECT_EQ(0, visitor.syn_reply_frame_count_);
|
| - EXPECT_EQ(2, visitor.headers_frame_count_);
|
| - } else {
|
| - EXPECT_EQ(1, visitor.syn_frame_count_);
|
| - EXPECT_EQ(1, visitor.syn_reply_frame_count_);
|
| - EXPECT_EQ(0, visitor.headers_frame_count_);
|
| - }
|
| - EXPECT_EQ(16, visitor.data_bytes_);
|
| - EXPECT_EQ(0, visitor.fin_frame_count_);
|
| - EXPECT_EQ(0, visitor.fin_flag_count_);
|
| - EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
|
| - EXPECT_EQ(2, visitor.data_frame_count_);
|
| -}
|
| -
|
| -// Test that the FIN flag on a SYN reply frame signifies EOF.
|
| -TEST_P(SpdyFramerTest, FinOnSynReplyFrame) {
|
| - const unsigned char kV2Input[] = {
|
| - 0x80, spdy_version_ch_, 0x00, // SYN Stream #1
|
| - 0x01, 0x00, 0x00, 0x00,
|
| - 0x14, 0x00, 0x00, 0x00,
|
| - 0x01, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x01, 0x00, 0x02, 'h',
|
| - 'h', 0x00, 0x02, 'v',
|
| - 'v',
|
| -
|
| - 0x80, spdy_version_ch_, 0x00, // SYN REPLY Stream #1
|
| - 0x02, 0x01, 0x00, 0x00,
|
| - 0x10, 0x00, 0x00, 0x00,
|
| - 0x01, 0x00, 0x00, 0x00,
|
| - 0x01, 0x00, 0x02, 'a',
|
| - 'a', 0x00, 0x02, 'b',
|
| - 'b',
|
| - };
|
| - const unsigned char kV3Input[] = {
|
| - 0x80, spdy_version_ch_, 0x00, // SYN Stream #1
|
| - 0x01, 0x00, 0x00, 0x00,
|
| - 0x1a, 0x00, 0x00, 0x00,
|
| - 0x01, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x01, 0x00,
|
| - 0x00, 0x00, 0x02, 'h',
|
| - 'h', 0x00, 0x00, 0x00,
|
| - 0x02, 'v', 'v',
|
| -
|
| - 0x80, spdy_version_ch_, 0x00, // SYN REPLY Stream #1
|
| - 0x02, 0x01, 0x00, 0x00,
|
| - 0x14, 0x00, 0x00, 0x00,
|
| - 0x01, 0x00, 0x00, 0x00,
|
| - 0x01, 0x00, 0x00, 0x00,
|
| - 0x02, 'a', 'a', 0x00,
|
| - 0x00, 0x00, 0x02, 'b',
|
| - 'b',
|
| - };
|
| -
|
| - // SYN_STREAM and SYN_REPLY don't exist in SPDY4, so instead we send
|
| - // HEADERS frames with PRIORITY(SYN_STREAM only) and END_HEADERS set.
|
| - const unsigned char kV4Input[] = {
|
| - 0x00, 0x00, 0x05, 0x01, // HEADERS: PRIORITY | END_HEADERS
|
| - 0x24, 0x00, 0x00, 0x00,
|
| - 0x01, 0x00, 0x00, 0x00, // Stream 1, Priority 0
|
| - 0x00, 0x82, // :method: GET
|
| -
|
| - 0x00, 0x00, 0x01, 0x01, // HEADERS: FIN | END_HEADERS
|
| - 0x05, 0x00, 0x00, 0x00,
|
| - 0x01, 0x8c, // Stream 1, :status: 200
|
| - };
|
| -
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - if (IsSpdy2()) {
|
| - visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
|
| - } else if (IsSpdy3()) {
|
| - visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
|
| - } else {
|
| - visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
|
| - }
|
| -
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - if (IsSpdy4()) {
|
| - EXPECT_EQ(0, visitor.syn_frame_count_);
|
| - EXPECT_EQ(0, visitor.syn_reply_frame_count_);
|
| - EXPECT_EQ(2, visitor.headers_frame_count_);
|
| - } else {
|
| - EXPECT_EQ(1, visitor.syn_frame_count_);
|
| - EXPECT_EQ(1, visitor.syn_reply_frame_count_);
|
| - EXPECT_EQ(0, visitor.headers_frame_count_);
|
| - }
|
| - EXPECT_EQ(0, visitor.data_bytes_);
|
| - EXPECT_EQ(0, visitor.fin_frame_count_);
|
| - EXPECT_EQ(1, visitor.fin_flag_count_);
|
| - EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
|
| - EXPECT_EQ(0, visitor.data_frame_count_);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, HeaderCompression) {
|
| - if (spdy_version_ > SPDY3) {
|
| - // Deflate compression doesn't apply to HPACK.
|
| - return;
|
| - }
|
| - SpdyFramer send_framer(spdy_version_);
|
| - SpdyFramer recv_framer(spdy_version_);
|
| -
|
| - send_framer.set_enable_compression(true);
|
| - recv_framer.set_enable_compression(true);
|
| -
|
| - const char kHeader1[] = "header1";
|
| - const char kHeader2[] = "header2";
|
| - const char kHeader3[] = "header3";
|
| - const char kValue1[] = "value1";
|
| - const char kValue2[] = "value2";
|
| - const char kValue3[] = "value3";
|
| -
|
| - // SYN_STREAM #1
|
| - SpdyHeaderBlock block;
|
| - block[kHeader1] = kValue1;
|
| - block[kHeader2] = kValue2;
|
| - SpdySynStreamIR syn_ir_1(1);
|
| - syn_ir_1.set_name_value_block(block);
|
| - scoped_ptr<SpdyFrame> syn_frame_1(send_framer.SerializeFrame(syn_ir_1));
|
| - EXPECT_TRUE(syn_frame_1.get() != NULL);
|
| -
|
| - // SYN_STREAM #2
|
| - block[kHeader3] = kValue3;
|
| - SpdySynStreamIR syn_stream(3);
|
| - syn_stream.set_name_value_block(block);
|
| - scoped_ptr<SpdyFrame> syn_frame_2(send_framer.SerializeSynStream(syn_stream));
|
| - EXPECT_TRUE(syn_frame_2.get() != NULL);
|
| -
|
| - // Now start decompressing
|
| - scoped_ptr<SpdyFrame> decompressed;
|
| - scoped_ptr<SpdyFrame> uncompressed;
|
| - base::StringPiece serialized_headers;
|
| - SpdyHeaderBlock decompressed_headers;
|
| -
|
| - // Decompress SYN_STREAM #1
|
| - decompressed.reset(
|
| - SpdyFramerTestUtil::DecompressFrame(&recv_framer, *syn_frame_1));
|
| - EXPECT_TRUE(decompressed.get() != NULL);
|
| - serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
|
| - EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
|
| - serialized_headers.size(),
|
| - &decompressed_headers));
|
| - EXPECT_EQ(2u, decompressed_headers.size());
|
| - EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
|
| - EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
|
| -
|
| - // Decompress SYN_STREAM #2
|
| - decompressed.reset(
|
| - SpdyFramerTestUtil::DecompressFrame(&recv_framer, *syn_frame_2));
|
| - EXPECT_TRUE(decompressed.get() != NULL);
|
| - serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
|
| - decompressed_headers.clear();
|
| - EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
|
| - serialized_headers.size(),
|
| - &decompressed_headers));
|
| - EXPECT_EQ(3u, decompressed_headers.size());
|
| - EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
|
| - EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
|
| - EXPECT_EQ(kValue3, decompressed_headers[kHeader3]);
|
| -}
|
| -
|
| -// Verify we can decompress the stream even if handed over to the
|
| -// framer 1 byte at a time.
|
| -TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
|
| - SpdyFramer send_framer(spdy_version_);
|
| -
|
| - send_framer.set_enable_compression(true);
|
| -
|
| - const char kHeader1[] = "header1";
|
| - const char kHeader2[] = "header2";
|
| - const char kValue1[] = "value1";
|
| - const char kValue2[] = "value2";
|
| -
|
| - SpdyHeadersIR headers(1);
|
| - headers.SetHeader(kHeader1, kValue1);
|
| - headers.SetHeader(kHeader2, kValue2);
|
| - scoped_ptr<SpdyFrame> headers_frame(send_framer.SerializeHeaders(headers));
|
| - EXPECT_TRUE(headers_frame.get() != NULL);
|
| -
|
| - const char bytes[] = "this is a test test test test test!";
|
| - SpdyDataIR data_ir(1, StringPiece(bytes, arraysize(bytes)));
|
| - data_ir.set_fin(true);
|
| - scoped_ptr<SpdyFrame> send_frame(send_framer.SerializeData(data_ir));
|
| - EXPECT_TRUE(send_frame.get() != NULL);
|
| -
|
| - // Run the inputs through the framer.
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = true;
|
| - const unsigned char* data;
|
| - data = reinterpret_cast<const unsigned char*>(headers_frame->data());
|
| - for (size_t idx = 0; idx < headers_frame->size(); ++idx) {
|
| - visitor.SimulateInFramer(data + idx, 1);
|
| - ASSERT_EQ(0, visitor.error_count_);
|
| - }
|
| - data = reinterpret_cast<const unsigned char*>(send_frame->data());
|
| - for (size_t idx = 0; idx < send_frame->size(); ++idx) {
|
| - visitor.SimulateInFramer(data + idx, 1);
|
| - ASSERT_EQ(0, visitor.error_count_);
|
| - }
|
| -
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - EXPECT_EQ(0, visitor.syn_frame_count_);
|
| - EXPECT_EQ(0, visitor.syn_reply_frame_count_);
|
| - EXPECT_EQ(1, visitor.headers_frame_count_);
|
| - EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_));
|
| - EXPECT_EQ(0, visitor.fin_frame_count_);
|
| - EXPECT_EQ(0, visitor.fin_flag_count_);
|
| - EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
|
| - EXPECT_EQ(1, visitor.data_frame_count_);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, WindowUpdateFrame) {
|
| - SpdyFramer framer(spdy_version_);
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
|
| - SpdyWindowUpdateIR(1, 0x12345678)));
|
| -
|
| - const char kDescription[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678";
|
| - const unsigned char kV3FrameData[] = { // Also applies for V2.
|
| - 0x80, spdy_version_ch_, 0x00, 0x09,
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x12, 0x34, 0x56, 0x78
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x04, 0x08,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x01, 0x12, 0x34, 0x56,
|
| - 0x78
|
| - };
|
| -
|
| - if (IsSpdy4()) {
|
| - CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - } else {
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - }
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, CreateDataFrame) {
|
| - SpdyFramer framer(spdy_version_);
|
| -
|
| - {
|
| - const char kDescription[] = "'hello' data frame, no FIN";
|
| - const unsigned char kV3FrameData[] = { // Also applies for V2.
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x05,
|
| - 'h', 'e', 'l', 'l',
|
| - 'o'
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x05, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x01, 'h', 'e', 'l',
|
| - 'l', 'o'
|
| - };
|
| - const char bytes[] = "hello";
|
| -
|
| - SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
|
| - if (IsSpdy4()) {
|
| - CompareFrame(
|
| - kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - } else {
|
| - CompareFrame(
|
| - kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - }
|
| -
|
| - SpdyDataIR data_header_ir(1);
|
| - data_header_ir.SetDataShallow(base::StringPiece(bytes, strlen(bytes)));
|
| - frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(
|
| - data_header_ir));
|
| - CompareCharArraysWithHexError(
|
| - kDescription,
|
| - reinterpret_cast<const unsigned char*>(frame->data()),
|
| - framer.GetDataFrameMinimumSize(),
|
| - IsSpdy4() ? kV4FrameData : kV3FrameData,
|
| - framer.GetDataFrameMinimumSize());
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] = "'hello' data frame with more padding, no FIN";
|
| - const unsigned char kV3FrameData[] = { // Also applies for V2.
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x05,
|
| - 'h', 'e', 'l', 'l',
|
| - 'o'
|
| - };
|
| -
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0xfd, 0x00, // Length = 253. PADDED set.
|
| - 0x08, 0x00, 0x00, 0x00,
|
| - 0x01, 0xf7, // Pad length field.
|
| - 'h', 'e', 'l', 'l', // Data
|
| - 'o',
|
| - // Padding of 247 0x00(s).
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - };
|
| - const char bytes[] = "hello";
|
| -
|
| - SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
|
| - // 247 zeros and the pad length field make the overall padding to be 248
|
| - // bytes.
|
| - data_ir.set_padding_len(248);
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
|
| - if (IsSpdy4()) {
|
| - CompareFrame(
|
| - kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - } else {
|
| - CompareFrame(
|
| - kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - }
|
| -
|
| - frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
|
| - CompareCharArraysWithHexError(
|
| - kDescription,
|
| - reinterpret_cast<const unsigned char*>(frame->data()),
|
| - framer.GetDataFrameMinimumSize(),
|
| - IsSpdy4() ? kV4FrameData : kV3FrameData,
|
| - framer.GetDataFrameMinimumSize());
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] = "'hello' data frame with few padding, no FIN";
|
| - const unsigned char kV3FrameData[] = { // Also applies for V2.
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x05,
|
| - 'h', 'e', 'l', 'l',
|
| - 'o'
|
| - };
|
| -
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x0d, 0x00, // Length = 13. PADDED set.
|
| - 0x08, 0x00, 0x00, 0x00,
|
| - 0x01, 0x07, // Pad length field.
|
| - 'h', 'e', 'l', 'l', // Data
|
| - 'o',
|
| - 0x00, 0x00, 0x00, 0x00, // Padding
|
| - 0x00, 0x00, 0x00
|
| - };
|
| - const char bytes[] = "hello";
|
| -
|
| - SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
|
| - // 7 zeros and the pad length field make the overall padding to be 8 bytes.
|
| - data_ir.set_padding_len(8);
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
|
| - if (IsSpdy4()) {
|
| - CompareFrame(
|
| - kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - } else {
|
| - CompareFrame(
|
| - kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - }
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] =
|
| - "'hello' data frame with 1 byte padding, no FIN";
|
| - const unsigned char kV3FrameData[] = { // Also applies for V2.
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x05,
|
| - 'h', 'e', 'l', 'l',
|
| - 'o'
|
| - };
|
| -
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x06, 0x00, // Length = 6. PADDED set.
|
| - 0x08, 0x00, 0x00, 0x00,
|
| - 0x01, 0x00, // Pad length field.
|
| - 'h', 'e', 'l', 'l', // Data
|
| - 'o',
|
| - };
|
| - const char bytes[] = "hello";
|
| -
|
| - SpdyDataIR data_ir(1, StringPiece(bytes, strlen(bytes)));
|
| - // The pad length field itself is used for the 1-byte padding and no padding
|
| - // payload is needed.
|
| - data_ir.set_padding_len(1);
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
|
| - if (IsSpdy4()) {
|
| - CompareFrame(
|
| - kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - } else {
|
| - CompareFrame(
|
| - kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - }
|
| -
|
| - frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
|
| - CompareCharArraysWithHexError(
|
| - kDescription,
|
| - reinterpret_cast<const unsigned char*>(frame->data()),
|
| - framer.GetDataFrameMinimumSize(),
|
| - IsSpdy4() ? kV4FrameData : kV3FrameData,
|
| - framer.GetDataFrameMinimumSize());
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] = "Data frame with negative data byte, no FIN";
|
| - const unsigned char kV3FrameData[] = { // Also applies for V2.
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0xff
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x01, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0xff
|
| - };
|
| - SpdyDataIR data_ir(1, StringPiece("\xff", 1));
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
|
| - if (IsSpdy4()) {
|
| - CompareFrame(
|
| - kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - } else {
|
| - CompareFrame(
|
| - kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - }
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] = "'hello' data frame, with FIN";
|
| - const unsigned char kV3FrameData[] = { // Also applies for V2.
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x01, 0x00, 0x00, 0x05,
|
| - 'h', 'e', 'l', 'l',
|
| - 'o'
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x05, 0x00,
|
| - 0x01, 0x00, 0x00, 0x00,
|
| - 0x01, 'h', 'e', 'l',
|
| - 'l', 'o'
|
| - };
|
| - SpdyDataIR data_ir(1, StringPiece("hello", 5));
|
| - data_ir.set_fin(true);
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
|
| - if (IsSpdy4()) {
|
| - CompareFrame(
|
| - kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - } else {
|
| - CompareFrame(
|
| - kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - }
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] = "Empty data frame";
|
| - const unsigned char kV3FrameData[] = { // Also applies for V2.
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x01,
|
| - };
|
| - SpdyDataIR data_ir(1, StringPiece());
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
|
| - if (IsSpdy4()) {
|
| - CompareFrame(
|
| - kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - } else {
|
| - CompareFrame(
|
| - kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - }
|
| -
|
| - frame.reset(framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir));
|
| - CompareCharArraysWithHexError(
|
| - kDescription,
|
| - reinterpret_cast<const unsigned char*>(frame->data()),
|
| - framer.GetDataFrameMinimumSize(),
|
| - IsSpdy4() ? kV4FrameData : kV3FrameData,
|
| - framer.GetDataFrameMinimumSize());
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] = "Data frame with max stream ID";
|
| - const unsigned char kV3FrameData[] = { // Also applies for V2.
|
| - 0x7f, 0xff, 0xff, 0xff,
|
| - 0x01, 0x00, 0x00, 0x05,
|
| - 'h', 'e', 'l', 'l',
|
| - 'o'
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x05, 0x00,
|
| - 0x01, 0x7f, 0xff, 0xff,
|
| - 0xff, 'h', 'e', 'l',
|
| - 'l', 'o'
|
| - };
|
| - SpdyDataIR data_ir(0x7fffffff, "hello");
|
| - data_ir.set_fin(true);
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
|
| - if (IsSpdy4()) {
|
| - CompareFrame(
|
| - kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - } else {
|
| - CompareFrame(
|
| - kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - }
|
| - }
|
| -
|
| - if (!IsSpdy4()) {
|
| - // This test does not apply to SPDY 4 because the max frame size is smaller
|
| - // than 4MB.
|
| - const char kDescription[] = "Large data frame";
|
| - const int kDataSize = 4 * 1024 * 1024; // 4 MB
|
| - const string kData(kDataSize, 'A');
|
| - const unsigned char kFrameHeader[] = {
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x01, 0x40, 0x00, 0x00,
|
| - };
|
| -
|
| - const int kFrameSize = arraysize(kFrameHeader) + kDataSize;
|
| - scoped_ptr<unsigned char[]> expected_frame_data(
|
| - new unsigned char[kFrameSize]);
|
| - memcpy(expected_frame_data.get(), kFrameHeader, arraysize(kFrameHeader));
|
| - memset(expected_frame_data.get() + arraysize(kFrameHeader), 'A', kDataSize);
|
| -
|
| - SpdyDataIR data_ir(1, StringPiece(kData.data(), kData.size()));
|
| - data_ir.set_fin(true);
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
|
| - CompareFrame(kDescription, *frame, expected_frame_data.get(), kFrameSize);
|
| - }
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
|
| - if (!IsSpdy2() && !IsSpdy3()) {
|
| - // SYN_STREAM unsupported in SPDY>3
|
| - return;
|
| - }
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_enable_compression(false);
|
| -
|
| - {
|
| - const char kDescription[] = "SYN_STREAM frame, lowest pri, no FIN";
|
| -
|
| - const unsigned char kPri = IsSpdy2() ? 0xC0 : 0xE0;
|
| - const unsigned char kV2FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x20,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - kPri, 0x00, 0x00, 0x02,
|
| - 0x00, 0x03, 'b', 'a',
|
| - 'r', 0x00, 0x03, 'f',
|
| - 'o', 'o', 0x00, 0x03,
|
| - 'f', 'o', 'o', 0x00,
|
| - 0x03, 'b', 'a', 'r'
|
| - };
|
| - const unsigned char kV3FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x2a,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - kPri, 0x00, 0x00, 0x00,
|
| - 0x00, 0x02, 0x00, 0x00,
|
| - 0x00, 0x03, 'b', 'a',
|
| - 'r', 0x00, 0x00, 0x00,
|
| - 0x03, 'f', 'o', 'o',
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 'f', 'o', 'o', 0x00,
|
| - 0x00, 0x00, 0x03, 'b',
|
| - 'a', 'r'
|
| - };
|
| - SpdySynStreamIR syn_stream(1);
|
| - syn_stream.set_priority(framer.GetLowestPriority());
|
| - syn_stream.SetHeader("bar", "foo");
|
| - syn_stream.SetHeader("foo", "bar");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
|
| - if (IsSpdy2()) {
|
| - CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
|
| - } else if (IsSpdy3()) {
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - } else {
|
| - LOG(FATAL) << "Unsupported version in test.";
|
| - }
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] =
|
| - "SYN_STREAM frame with a 0-length header name, highest pri, FIN, "
|
| - "max stream ID";
|
| -
|
| - const unsigned char kV2FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x01,
|
| - 0x01, 0x00, 0x00, 0x1D,
|
| - 0x7f, 0xff, 0xff, 0xff,
|
| - 0x7f, 0xff, 0xff, 0xff,
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 'f', 'o', 'o', 0x00,
|
| - 0x03, 'f', 'o', 'o',
|
| - 0x00, 0x03, 'b', 'a',
|
| - 'r'
|
| - };
|
| - const unsigned char kV3FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x01,
|
| - 0x01, 0x00, 0x00, 0x27,
|
| - 0x7f, 0xff, 0xff, 0xff,
|
| - 0x7f, 0xff, 0xff, 0xff,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x02, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x03, 'f', 'o',
|
| - 'o', 0x00, 0x00, 0x00,
|
| - 0x03, 'f', 'o', 'o',
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 'b', 'a', 'r'
|
| - };
|
| - SpdySynStreamIR syn_stream(0x7fffffff);
|
| - syn_stream.set_associated_to_stream_id(0x7fffffff);
|
| - syn_stream.set_priority(framer.GetHighestPriority());
|
| - syn_stream.set_fin(true);
|
| - syn_stream.SetHeader("", "foo");
|
| - syn_stream.SetHeader("foo", "bar");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
|
| - if (IsSpdy2()) {
|
| - CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
|
| - } else if (IsSpdy3()) {
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - } else {
|
| - LOG(FATAL) << "Unsupported version in test.";
|
| - }
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] =
|
| - "SYN_STREAM frame with a 0-length header val, high pri, FIN, "
|
| - "max stream ID";
|
| -
|
| - const unsigned char kPri = IsSpdy2() ? 0x40 : 0x20;
|
| - const unsigned char kV2FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x01,
|
| - 0x01, 0x00, 0x00, 0x1D,
|
| - 0x7f, 0xff, 0xff, 0xff,
|
| - 0x7f, 0xff, 0xff, 0xff,
|
| - kPri, 0x00, 0x00, 0x02,
|
| - 0x00, 0x03, 'b', 'a',
|
| - 'r', 0x00, 0x03, 'f',
|
| - 'o', 'o', 0x00, 0x03,
|
| - 'f', 'o', 'o', 0x00,
|
| - 0x00
|
| - };
|
| - const unsigned char kV3FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x01,
|
| - 0x01, 0x00, 0x00, 0x27,
|
| - 0x7f, 0xff, 0xff, 0xff,
|
| - 0x7f, 0xff, 0xff, 0xff,
|
| - kPri, 0x00, 0x00, 0x00,
|
| - 0x00, 0x02, 0x00, 0x00,
|
| - 0x00, 0x03, 'b', 'a',
|
| - 'r', 0x00, 0x00, 0x00,
|
| - 0x03, 'f', 'o', 'o',
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 'f', 'o', 'o', 0x00,
|
| - 0x00, 0x00, 0x00
|
| - };
|
| - SpdySynStreamIR syn_stream(0x7fffffff);
|
| - syn_stream.set_associated_to_stream_id(0x7fffffff);
|
| - syn_stream.set_priority(1);
|
| - syn_stream.set_fin(true);
|
| - syn_stream.SetHeader("bar", "foo");
|
| - syn_stream.SetHeader("foo", "");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
|
| - if (IsSpdy2()) {
|
| - CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
|
| - } else if (IsSpdy3()) {
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - } else {
|
| - LOG(FATAL) << "Unsupported version in test.";
|
| - }
|
| - }
|
| -}
|
| -
|
| -// TODO(phajdan.jr): Clean up after we no longer need
|
| -// to workaround http://crbug.com/139744.
|
| -#if !defined(USE_SYSTEM_ZLIB)
|
| -TEST_P(SpdyFramerTest, CreateSynStreamCompressed) {
|
| - if (!IsSpdy2() && !IsSpdy3()) {
|
| - // SYN_STREAM not supported for SPDY>3
|
| - return;
|
| - }
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_enable_compression(true);
|
| -
|
| - {
|
| - const char kDescription[] =
|
| - "SYN_STREAM frame, low pri, no FIN";
|
| - const SpdyPriority priority = IsSpdy2() ? 2 : 4;
|
| -
|
| - const unsigned char kV2FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x36,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x80, 0x00, 0x38, 0xea,
|
| - 0xdf, 0xa2, 0x51, 0xb2,
|
| - 0x62, 0x60, 0x62, 0x60,
|
| - 0x4e, 0x4a, 0x2c, 0x62,
|
| - 0x60, 0x06, 0x08, 0xa0,
|
| - 0xb4, 0xfc, 0x7c, 0x80,
|
| - 0x00, 0x62, 0x60, 0x4e,
|
| - 0xcb, 0xcf, 0x67, 0x60,
|
| - 0x06, 0x08, 0xa0, 0xa4,
|
| - 0xc4, 0x22, 0x80, 0x00,
|
| - 0x02, 0x00, 0x00, 0x00,
|
| - 0xff, 0xff,
|
| - };
|
| - const unsigned char kV3FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x37,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x80, 0x00, 0x38, 0xEA,
|
| - 0xE3, 0xC6, 0xA7, 0xC2,
|
| - 0x02, 0xE5, 0x0E, 0x50,
|
| - 0xC2, 0x4B, 0x4A, 0x04,
|
| - 0xE5, 0x0B, 0x66, 0x80,
|
| - 0x00, 0x4A, 0xCB, 0xCF,
|
| - 0x07, 0x08, 0x20, 0x10,
|
| - 0x95, 0x96, 0x9F, 0x0F,
|
| - 0xA2, 0x00, 0x02, 0x28,
|
| - 0x29, 0xB1, 0x08, 0x20,
|
| - 0x80, 0x00, 0x00, 0x00,
|
| - 0x00, 0xFF, 0xFF,
|
| - };
|
| - const unsigned char kV2SIMDFrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x33,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x80, 0x00, 0x38, 0xea,
|
| - 0xdf, 0xa2, 0x51, 0xb2,
|
| - 0x62, 0x60, 0x62, 0x60,
|
| - 0x4e, 0x4a, 0x2c, 0x62,
|
| - 0x60, 0x06, 0x08, 0xa0,
|
| - 0xb4, 0xfc, 0x7c, 0x80,
|
| - 0x00, 0x62, 0x60, 0x06,
|
| - 0x13, 0x00, 0x01, 0x94,
|
| - 0x94, 0x58, 0x04, 0x10,
|
| - 0x40, 0x00, 0x00, 0x00,
|
| - 0x00, 0xff, 0xff,
|
| - };
|
| - const unsigned char kV3SIMDFrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x32,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x80, 0x00, 0x38, 0xea,
|
| - 0xe3, 0xc6, 0xa7, 0xc2,
|
| - 0x02, 0xe5, 0x0e, 0x50,
|
| - 0xc2, 0x4b, 0x4a, 0x04,
|
| - 0xe5, 0x0b, 0x66, 0x80,
|
| - 0x00, 0x4a, 0xcb, 0xcf,
|
| - 0x07, 0x08, 0x20, 0x24,
|
| - 0x0a, 0x20, 0x80, 0x92,
|
| - 0x12, 0x8b, 0x00, 0x02,
|
| - 0x08, 0x00, 0x00, 0x00,
|
| - 0xff, 0xff,
|
| - };
|
| -
|
| - SpdySynStreamIR syn_stream(1);
|
| - syn_stream.set_priority(priority);
|
| - syn_stream.SetHeader("bar", "foo");
|
| - syn_stream.SetHeader("foo", "bar");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
|
| - const unsigned char* frame_data =
|
| - reinterpret_cast<const unsigned char*>(frame->data());
|
| - if (IsSpdy2()) {
|
| - // Try comparing with SIMD version, if that fails, do a failing check
|
| - // with pretty printing against non-SIMD version
|
| - if (memcmp(frame_data,
|
| - kV2SIMDFrameData,
|
| - std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
|
| - CompareCharArraysWithHexError(kDescription,
|
| - frame_data,
|
| - frame->size(),
|
| - kV2FrameData,
|
| - arraysize(kV2FrameData));
|
| - }
|
| - } else if (IsSpdy3()) {
|
| - if (memcmp(frame_data,
|
| - kV3SIMDFrameData,
|
| - std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
|
| - CompareCharArraysWithHexError(kDescription,
|
| - frame_data,
|
| - frame->size(),
|
| - kV3FrameData,
|
| - arraysize(kV3FrameData));
|
| - }
|
| - } else {
|
| - LOG(FATAL) << "Unsupported version in test.";
|
| - }
|
| - }
|
| -}
|
| -#endif // !defined(USE_SYSTEM_ZLIB)
|
| -
|
| -TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
|
| - if (spdy_version_ > SPDY3) {
|
| - // SYN_REPLY unsupported in SPDY>3
|
| - return;
|
| - }
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_enable_compression(false);
|
| -
|
| - {
|
| - const char kDescription[] = "SYN_REPLY frame, no FIN";
|
| -
|
| - const unsigned char kV2FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x02,
|
| - 0x00, 0x00, 0x00, 0x1C,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 0x00, 0x03, 'b', 'a',
|
| - 'r', 0x00, 0x03, 'f',
|
| - 'o', 'o', 0x00, 0x03,
|
| - 'f', 'o', 'o', 0x00,
|
| - 0x03, 'b', 'a', 'r'
|
| - };
|
| - const unsigned char kV3FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x02,
|
| - 0x00, 0x00, 0x00, 0x24,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 'b', 'a', 'r', 0x00,
|
| - 0x00, 0x00, 0x03, 'f',
|
| - 'o', 'o', 0x00, 0x00,
|
| - 0x00, 0x03, 'f', 'o',
|
| - 'o', 0x00, 0x00, 0x00,
|
| - 0x03, 'b', 'a', 'r'
|
| - };
|
| - SpdySynReplyIR syn_reply(1);
|
| - syn_reply.SetHeader("bar", "foo");
|
| - syn_reply.SetHeader("foo", "bar");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
|
| - if (IsSpdy2()) {
|
| - CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
|
| - } else if (IsSpdy3()) {
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - } else {
|
| - LOG(FATAL) << "Unsupported version in test.";
|
| - }
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] =
|
| - "SYN_REPLY frame with a 0-length header name, FIN, max stream ID";
|
| -
|
| - const unsigned char kV2FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x02,
|
| - 0x01, 0x00, 0x00, 0x19,
|
| - 0x7f, 0xff, 0xff, 0xff,
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 'f', 'o', 'o', 0x00,
|
| - 0x03, 'f', 'o', 'o',
|
| - 0x00, 0x03, 'b', 'a',
|
| - 'r'
|
| - };
|
| - const unsigned char kV3FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x02,
|
| - 0x01, 0x00, 0x00, 0x21,
|
| - 0x7f, 0xff, 0xff, 0xff,
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 'f', 'o', 'o', 0x00,
|
| - 0x00, 0x00, 0x03, 'f',
|
| - 'o', 'o', 0x00, 0x00,
|
| - 0x00, 0x03, 'b', 'a',
|
| - 'r'
|
| - };
|
| - SpdySynReplyIR syn_reply(0x7fffffff);
|
| - syn_reply.set_fin(true);
|
| - syn_reply.SetHeader("", "foo");
|
| - syn_reply.SetHeader("foo", "bar");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
|
| - if (IsSpdy2()) {
|
| - CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
|
| - } else if (IsSpdy3()) {
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - } else {
|
| - LOG(FATAL) << "Unsupported version in test.";
|
| - }
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] =
|
| - "SYN_REPLY frame with a 0-length header val, FIN, max stream ID";
|
| -
|
| - const unsigned char kV2FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x02,
|
| - 0x01, 0x00, 0x00, 0x19,
|
| - 0x7f, 0xff, 0xff, 0xff,
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 0x00, 0x03, 'b', 'a',
|
| - 'r', 0x00, 0x03, 'f',
|
| - 'o', 'o', 0x00, 0x03,
|
| - 'f', 'o', 'o', 0x00,
|
| - 0x00
|
| - };
|
| - const unsigned char kV3FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x02,
|
| - 0x01, 0x00, 0x00, 0x21,
|
| - 0x7f, 0xff, 0xff, 0xff,
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 'b', 'a', 'r', 0x00,
|
| - 0x00, 0x00, 0x03, 'f',
|
| - 'o', 'o', 0x00, 0x00,
|
| - 0x00, 0x03, 'f', 'o',
|
| - 'o', 0x00, 0x00, 0x00,
|
| - 0x00
|
| - };
|
| - SpdySynReplyIR syn_reply(0x7fffffff);
|
| - syn_reply.set_fin(true);
|
| - syn_reply.SetHeader("bar", "foo");
|
| - syn_reply.SetHeader("foo", "");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
|
| - if (IsSpdy2()) {
|
| - CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
|
| - } else if (IsSpdy3()) {
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - } else {
|
| - LOG(FATAL) << "Unsupported version in test.";
|
| - }
|
| - }
|
| -}
|
| -
|
| -// TODO(phajdan.jr): Clean up after we no longer need
|
| -// to workaround http://crbug.com/139744.
|
| -#if !defined(USE_SYSTEM_ZLIB)
|
| -TEST_P(SpdyFramerTest, CreateSynReplyCompressed) {
|
| - if (spdy_version_ > SPDY3) {
|
| - // SYN_REPLY unsupported in SPDY>3
|
| - return;
|
| - }
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_enable_compression(true);
|
| -
|
| - {
|
| - const char kDescription[] = "SYN_REPLY frame, no FIN";
|
| -
|
| - const unsigned char kV2FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x02,
|
| - 0x00, 0x00, 0x00, 0x32,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x38, 0xea,
|
| - 0xdf, 0xa2, 0x51, 0xb2,
|
| - 0x62, 0x60, 0x62, 0x60,
|
| - 0x4e, 0x4a, 0x2c, 0x62,
|
| - 0x60, 0x06, 0x08, 0xa0,
|
| - 0xb4, 0xfc, 0x7c, 0x80,
|
| - 0x00, 0x62, 0x60, 0x4e,
|
| - 0xcb, 0xcf, 0x67, 0x60,
|
| - 0x06, 0x08, 0xa0, 0xa4,
|
| - 0xc4, 0x22, 0x80, 0x00,
|
| - 0x02, 0x00, 0x00, 0x00,
|
| - 0xff, 0xff,
|
| - };
|
| - const unsigned char kV3FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x02,
|
| - 0x00, 0x00, 0x00, 0x31,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x38, 0xea, 0xe3, 0xc6,
|
| - 0xa7, 0xc2, 0x02, 0xe5,
|
| - 0x0e, 0x50, 0xc2, 0x4b,
|
| - 0x4a, 0x04, 0xe5, 0x0b,
|
| - 0x66, 0x80, 0x00, 0x4a,
|
| - 0xcb, 0xcf, 0x07, 0x08,
|
| - 0x20, 0x10, 0x95, 0x96,
|
| - 0x9f, 0x0f, 0xa2, 0x00,
|
| - 0x02, 0x28, 0x29, 0xb1,
|
| - 0x08, 0x20, 0x80, 0x00,
|
| - 0x00, 0x00, 0x00, 0xff,
|
| - 0xff,
|
| - };
|
| - const unsigned char kV2SIMDFrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x02,
|
| - 0x00, 0x00, 0x00, 0x2f,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x38, 0xea,
|
| - 0xdf, 0xa2, 0x51, 0xb2,
|
| - 0x62, 0x60, 0x62, 0x60,
|
| - 0x4e, 0x4a, 0x2c, 0x62,
|
| - 0x60, 0x06, 0x08, 0xa0,
|
| - 0xb4, 0xfc, 0x7c, 0x80,
|
| - 0x00, 0x62, 0x60, 0x06,
|
| - 0x13, 0x00, 0x01, 0x94,
|
| - 0x94, 0x58, 0x04, 0x10,
|
| - 0x40, 0x00, 0x00, 0x00,
|
| - 0x00, 0xff, 0xff,
|
| - };
|
| - const unsigned char kV3SIMDFrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x02,
|
| - 0x00, 0x00, 0x00, 0x2c,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x38, 0xea, 0xe3, 0xc6,
|
| - 0xa7, 0xc2, 0x02, 0xe5,
|
| - 0x0e, 0x50, 0xc2, 0x4b,
|
| - 0x4a, 0x04, 0xe5, 0x0b,
|
| - 0x66, 0x80, 0x00, 0x4a,
|
| - 0xcb, 0xcf, 0x07, 0x08,
|
| - 0x20, 0x24, 0x0a, 0x20,
|
| - 0x80, 0x92, 0x12, 0x8b,
|
| - 0x00, 0x02, 0x08, 0x00,
|
| - 0x00, 0x00, 0xff, 0xff,
|
| - };
|
| -
|
| - SpdySynReplyIR syn_reply(1);
|
| - syn_reply.SetHeader("bar", "foo");
|
| - syn_reply.SetHeader("foo", "bar");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
|
| - const unsigned char* frame_data =
|
| - reinterpret_cast<const unsigned char*>(frame->data());
|
| - if (IsSpdy2()) {
|
| - // Try comparing with SIMD version, if that fails, do a failing check
|
| - // with pretty printing against non-SIMD version
|
| - if (memcmp(frame_data,
|
| - kV2SIMDFrameData,
|
| - std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
|
| - CompareCharArraysWithHexError(kDescription,
|
| - frame_data,
|
| - frame->size(),
|
| - kV2FrameData,
|
| - arraysize(kV2FrameData));
|
| - }
|
| - } else if (IsSpdy3()) {
|
| - if (memcmp(frame_data,
|
| - kV3SIMDFrameData,
|
| - std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
|
| - CompareCharArraysWithHexError(kDescription,
|
| - frame_data,
|
| - frame->size(),
|
| - kV3FrameData,
|
| - arraysize(kV3FrameData));
|
| - }
|
| - } else {
|
| - LOG(FATAL) << "Unsupported version in test.";
|
| - }
|
| - }
|
| -}
|
| -#endif // !defined(USE_SYSTEM_ZLIB)
|
| -
|
| -TEST_P(SpdyFramerTest, CreateRstStream) {
|
| - SpdyFramer framer(spdy_version_);
|
| -
|
| - {
|
| - const char kDescription[] = "RST_STREAM frame";
|
| - const unsigned char kV3FrameData[] = { // Also applies for V2.
|
| - 0x80, spdy_version_ch_, 0x00, 0x03,
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x07, 0x03,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x01, 0x00, 0x00, 0x00,
|
| - 0x01, 0x52, 0x53, 0x54
|
| - };
|
| - SpdyRstStreamIR rst_stream(1, RST_STREAM_PROTOCOL_ERROR, "RST");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
|
| - if (IsSpdy4()) {
|
| - CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - } else {
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - }
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] = "RST_STREAM frame with max stream ID";
|
| - const unsigned char kV3FrameData[] = { // Also applies for V2.
|
| - 0x80, spdy_version_ch_, 0x00, 0x03,
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - 0x7f, 0xff, 0xff, 0xff,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x04, 0x03,
|
| - 0x00, 0x7f, 0xff, 0xff,
|
| - 0xff, 0x00, 0x00, 0x00,
|
| - 0x01,
|
| - };
|
| - SpdyRstStreamIR rst_stream(0x7FFFFFFF,
|
| - RST_STREAM_PROTOCOL_ERROR,
|
| - "");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
|
| - if (IsSpdy4()) {
|
| - CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - } else {
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - }
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] = "RST_STREAM frame with max status code";
|
| - const unsigned char kV3FrameData[] = { // Also applies for V2.
|
| - 0x80, spdy_version_ch_, 0x00, 0x03,
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - 0x7f, 0xff, 0xff, 0xff,
|
| - 0x00, 0x00, 0x00, 0x06,
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x04, 0x03,
|
| - 0x00, 0x7f, 0xff, 0xff,
|
| - 0xff, 0x00, 0x00, 0x00,
|
| - 0x02,
|
| - };
|
| - SpdyRstStreamIR rst_stream(0x7FFFFFFF,
|
| - RST_STREAM_INTERNAL_ERROR,
|
| - "");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
|
| - if (IsSpdy4()) {
|
| - CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - } else {
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - }
|
| - }
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, CreateSettings) {
|
| - SpdyFramer framer(spdy_version_);
|
| -
|
| - {
|
| - const char kDescription[] = "Network byte order SETTINGS frame";
|
| -
|
| - const unsigned char kV2FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x04,
|
| - 0x00, 0x00, 0x00, 0x0c,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x07, 0x00, 0x00, 0x01,
|
| - 0x0a, 0x0b, 0x0c, 0x0d,
|
| - };
|
| - const unsigned char kV3FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x04,
|
| - 0x00, 0x00, 0x00, 0x0c,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x01, 0x00, 0x00, 0x07,
|
| - 0x0a, 0x0b, 0x0c, 0x0d,
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x06, 0x04,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x04, 0x0a,
|
| - 0x0b, 0x0c, 0x0d,
|
| - };
|
| -
|
| - uint32 kValue = 0x0a0b0c0d;
|
| - SpdySettingsIR settings_ir;
|
| -
|
| - SpdySettingsFlags kFlags = static_cast<SpdySettingsFlags>(0x01);
|
| - SpdySettingsIds kId = SETTINGS_INITIAL_WINDOW_SIZE;
|
| - SettingsMap settings;
|
| - settings[kId] = SettingsFlagsAndValue(kFlags, kValue);
|
| - EXPECT_EQ(kFlags, settings[kId].first);
|
| - EXPECT_EQ(kValue, settings[kId].second);
|
| - settings_ir.AddSetting(kId,
|
| - kFlags & SETTINGS_FLAG_PLEASE_PERSIST,
|
| - kFlags & SETTINGS_FLAG_PERSISTED,
|
| - kValue);
|
| -
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
|
| - if (IsSpdy2()) {
|
| - CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
|
| - } else if (IsSpdy3()) {
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - } else {
|
| - CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - }
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] = "Basic SETTINGS frame";
|
| -
|
| - const unsigned char kV2FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x04,
|
| - 0x00, 0x00, 0x00, 0x24,
|
| - 0x00, 0x00, 0x00, 0x04,
|
| - 0x01, 0x00, 0x00, 0x00, // 1st Setting
|
| - 0x00, 0x00, 0x00, 0x05,
|
| - 0x02, 0x00, 0x00, 0x00, // 2nd Setting
|
| - 0x00, 0x00, 0x00, 0x06,
|
| - 0x03, 0x00, 0x00, 0x00, // 3rd Setting
|
| - 0x00, 0x00, 0x00, 0x07,
|
| - 0x04, 0x00, 0x00, 0x00, // 4th Setting
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - };
|
| - const unsigned char kV3FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x04,
|
| - 0x00, 0x00, 0x00, 0x24,
|
| - 0x00, 0x00, 0x00, 0x04,
|
| - 0x00, 0x00, 0x00, 0x01, // 1st Setting
|
| - 0x00, 0x00, 0x00, 0x05,
|
| - 0x00, 0x00, 0x00, 0x02, // 2nd Setting
|
| - 0x00, 0x00, 0x00, 0x06,
|
| - 0x00, 0x00, 0x00, 0x03, // 3rd Setting
|
| - 0x00, 0x00, 0x00, 0x07,
|
| - 0x00, 0x00, 0x00, 0x04, // 4th Setting
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - };
|
| - // These end up seemingly out of order because of the way that our internal
|
| - // ordering for settings_ir works. HTTP2 has no requirement on ordering on
|
| - // the wire.
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x18, 0x04,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x03, // 3rd Setting
|
| - 0x00, 0x00, 0x00, 0x07,
|
| - 0x00, 0x04, // 4th Setting
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - 0x00, 0x01, // 1st Setting
|
| - 0x00, 0x00, 0x00, 0x05,
|
| - 0x00, 0x02, // 2nd Setting
|
| - 0x00, 0x00, 0x00, 0x06,
|
| - };
|
| -
|
| - SpdySettingsIR settings_ir;
|
| - settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
|
| - false, // persist
|
| - false, // persisted
|
| - 5);
|
| - settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
|
| - false, // persist
|
| - false, // persisted
|
| - 6);
|
| - settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
|
| - false, // persist
|
| - false, // persisted
|
| - 7);
|
| - settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 4),
|
| - false, // persist
|
| - false, // persisted
|
| - 8);
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
|
| -
|
| - if (IsSpdy2()) {
|
| - CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
|
| - } else if (IsSpdy3()) {
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - } else {
|
| - CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - }
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] = "Empty SETTINGS frame";
|
| -
|
| - const unsigned char kV3FrameData[] = { // Also applies for V2.
|
| - 0x80, spdy_version_ch_, 0x00, 0x04,
|
| - 0x00, 0x00, 0x00, 0x04,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x00, 0x04,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00,
|
| - };
|
| - SpdySettingsIR settings_ir;
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
|
| - if (IsSpdy4()) {
|
| - CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - } else {
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - }
|
| - }
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, CreatePingFrame) {
|
| - SpdyFramer framer(spdy_version_);
|
| -
|
| - {
|
| - const char kDescription[] = "PING frame";
|
| - const unsigned char kV3FrameData[] = { // Also applies for V2.
|
| - 0x80, spdy_version_ch_, 0x00, 0x06,
|
| - 0x00, 0x00, 0x00, 0x04,
|
| - 0x12, 0x34, 0x56, 0x78,
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x08, 0x06,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x12, 0x34, 0x56,
|
| - 0x78, 0x9a, 0xbc, 0xde,
|
| - 0xff,
|
| - };
|
| - const unsigned char kV4FrameDataWithAck[] = {
|
| - 0x00, 0x00, 0x08, 0x06,
|
| - 0x01, 0x00, 0x00, 0x00,
|
| - 0x00, 0x12, 0x34, 0x56,
|
| - 0x78, 0x9a, 0xbc, 0xde,
|
| - 0xff,
|
| - };
|
| - scoped_ptr<SpdyFrame> frame;
|
| - if (IsSpdy4()) {
|
| - const SpdyPingId kPingId = 0x123456789abcdeffULL;
|
| - SpdyPingIR ping_ir(kPingId);
|
| - // Tests SpdyPingIR when the ping is not an ack.
|
| - ASSERT_FALSE(ping_ir.is_ack());
|
| - frame.reset(framer.SerializePing(ping_ir));
|
| - CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| -
|
| - // Tests SpdyPingIR when the ping is an ack.
|
| - ping_ir.set_is_ack(true);
|
| - frame.reset(framer.SerializePing(ping_ir));
|
| - CompareFrame(kDescription, *frame,
|
| - kV4FrameDataWithAck, arraysize(kV4FrameDataWithAck));
|
| -
|
| - } else {
|
| - frame.reset(framer.SerializePing(SpdyPingIR(0x12345678ull)));
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - }
|
| - }
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, CreateGoAway) {
|
| - SpdyFramer framer(spdy_version_);
|
| -
|
| - {
|
| - const char kDescription[] = "GOAWAY frame";
|
| - const unsigned char kV2FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x07,
|
| - 0x00, 0x00, 0x00, 0x04,
|
| - 0x00, 0x00, 0x00, 0x00, // Stream Id
|
| - };
|
| - const unsigned char kV3FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x07,
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - 0x00, 0x00, 0x00, 0x00, // Stream Id
|
| - 0x00, 0x00, 0x00, 0x00, // Status
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x0a, 0x07,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, // Stream id
|
| - 0x00, 0x00, 0x00, 0x00, // Status
|
| - 0x00, 0x47, 0x41, // Opaque Description
|
| - };
|
| - SpdyGoAwayIR goaway_ir(0, GOAWAY_OK, "GA");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
|
| - if (IsSpdy2()) {
|
| - CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
|
| - } else if (IsSpdy3()) {
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - } else {
|
| - CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - }
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] = "GOAWAY frame with max stream ID, status";
|
| - const unsigned char kV2FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x07,
|
| - 0x00, 0x00, 0x00, 0x04,
|
| - 0x7f, 0xff, 0xff, 0xff, // Stream Id
|
| - };
|
| - const unsigned char kV3FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x07,
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - 0x7f, 0xff, 0xff, 0xff, // Stream Id
|
| - 0x00, 0x00, 0x00, 0x01, // Status: PROTOCOL_ERROR.
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x0a, 0x07,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x7f, 0xff, 0xff, // Stream Id
|
| - 0xff, 0x00, 0x00, 0x00, // Status: INTERNAL_ERROR.
|
| - 0x02, 0x47, 0x41, // Opaque Description
|
| - };
|
| - SpdyGoAwayIR goaway_ir(0x7FFFFFFF, GOAWAY_INTERNAL_ERROR, "GA");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
|
| - if (IsSpdy2()) {
|
| - CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
|
| - } else if (IsSpdy3()) {
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - } else {
|
| - CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - }
|
| - }
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_enable_compression(false);
|
| -
|
| - {
|
| - const char kDescription[] = "HEADERS frame, no FIN";
|
| -
|
| - const unsigned char kV2FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x08,
|
| - 0x00, 0x00, 0x00, 0x1C,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 0x00, 0x03, 'b', 'a',
|
| - 'r', 0x00, 0x03, 'f',
|
| - 'o', 'o', 0x00, 0x03,
|
| - 'f', 'o', 'o', 0x00,
|
| - 0x03, 'b', 'a', 'r'
|
| - };
|
| - const unsigned char kV3FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x08,
|
| - 0x00, 0x00, 0x00, 0x24,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 'b', 'a', 'r', 0x00,
|
| - 0x00, 0x00, 0x03, 'f',
|
| - 'o', 'o', 0x00, 0x00,
|
| - 0x00, 0x03, 'f', 'o',
|
| - 'o', 0x00, 0x00, 0x00,
|
| - 0x03, 'b', 'a', 'r'
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x12, 0x01, // Headers: END_HEADERS
|
| - 0x04, 0x00, 0x00, 0x00, // Stream 1
|
| - 0x01, 0x00, 0x03, 0x62, // @.ba
|
| - 0x61, 0x72, 0x03, 0x66, // r.fo
|
| - 0x6f, 0x6f, 0x00, 0x03, // o@.f
|
| - 0x66, 0x6f, 0x6f, 0x03, // oo.b
|
| - 0x62, 0x61, 0x72, // ar
|
| - };
|
| - SpdyHeadersIR headers_ir(1);
|
| - headers_ir.SetHeader("bar", "foo");
|
| - headers_ir.SetHeader("foo", "bar");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
|
| - if (IsSpdy2()) {
|
| - CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
|
| - } else if (IsSpdy3()) {
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - } else {
|
| - CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - }
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] =
|
| - "HEADERS frame with a 0-length header name, FIN, max stream ID";
|
| -
|
| - const unsigned char kV2FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x08,
|
| - 0x01, 0x00, 0x00, 0x19,
|
| - 0x7f, 0xff, 0xff, 0xff,
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 'f', 'o', 'o', 0x00,
|
| - 0x03, 'f', 'o', 'o',
|
| - 0x00, 0x03, 'b', 'a',
|
| - 'r'
|
| - };
|
| - const unsigned char kV3FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x08,
|
| - 0x01, 0x00, 0x00, 0x21,
|
| - 0x7f, 0xff, 0xff, 0xff,
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 'f', 'o', 'o', 0x00,
|
| - 0x00, 0x00, 0x03, 'f',
|
| - 'o', 'o', 0x00, 0x00,
|
| - 0x00, 0x03, 'b', 'a',
|
| - 'r'
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
|
| - 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
|
| - 0xff, 0x00, 0x00, 0x03, // @..
|
| - 0x66, 0x6f, 0x6f, 0x00, // foo@
|
| - 0x03, 0x66, 0x6f, 0x6f, // .foo
|
| - 0x03, 0x62, 0x61, 0x72, // .bar
|
| - };
|
| - SpdyHeadersIR headers_ir(0x7fffffff);
|
| - headers_ir.set_fin(true);
|
| - headers_ir.SetHeader("", "foo");
|
| - headers_ir.SetHeader("foo", "bar");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
|
| - if (IsSpdy2()) {
|
| - CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
|
| - } else if (IsSpdy3()) {
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - } else {
|
| - CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - }
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] =
|
| - "HEADERS frame with a 0-length header val, FIN, max stream ID";
|
| -
|
| - const unsigned char kV2FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x08,
|
| - 0x01, 0x00, 0x00, 0x19,
|
| - 0x7f, 0xff, 0xff, 0xff,
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 0x00, 0x03, 'b', 'a',
|
| - 'r', 0x00, 0x03, 'f',
|
| - 'o', 'o', 0x00, 0x03,
|
| - 'f', 'o', 'o', 0x00,
|
| - 0x00
|
| - };
|
| - const unsigned char kV3FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x08,
|
| - 0x01, 0x00, 0x00, 0x21,
|
| - 0x7f, 0xff, 0xff, 0xff,
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 'b', 'a', 'r', 0x00,
|
| - 0x00, 0x00, 0x03, 'f',
|
| - 'o', 'o', 0x00, 0x00,
|
| - 0x00, 0x03, 'f', 'o',
|
| - 'o', 0x00, 0x00, 0x00,
|
| - 0x00
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x0f, 0x01, // Headers: FIN | END_HEADERS
|
| - 0x05, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
|
| - 0xff, 0x00, 0x03, 0x62, // @.b
|
| - 0x61, 0x72, 0x03, 0x66, // ar.f
|
| - 0x6f, 0x6f, 0x00, 0x03, // oo@.
|
| - 0x66, 0x6f, 0x6f, 0x00, // foo.
|
| - };
|
| - SpdyHeadersIR headers_ir(0x7fffffff);
|
| - headers_ir.set_fin(true);
|
| - headers_ir.SetHeader("bar", "foo");
|
| - headers_ir.SetHeader("foo", "");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
|
| - if (IsSpdy2()) {
|
| - CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
|
| - } else if (IsSpdy3()) {
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - } else {
|
| - CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - }
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] =
|
| - "HEADERS frame with a 0-length header val, FIN, max stream ID, pri";
|
| -
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x14, 0x01, // Headers: FIN | END_HEADERS | PRIORITY
|
| - 0x25, 0x7f, 0xff, 0xff, // Stream 0x7fffffff
|
| - 0xff, 0x00, 0x00, 0x00, // parent stream
|
| - 0x00, 0xdb, // weight
|
| - 0x00, 0x03, 0x62, 0x61, // @.ba
|
| - 0x72, 0x03, 0x66, 0x6f, // r.fo
|
| - 0x6f, 0x00, 0x03, 0x66, // o@.f
|
| - 0x6f, 0x6f, 0x00, // oo.
|
| - };
|
| - SpdyHeadersIR headers_ir(0x7fffffff);
|
| - headers_ir.set_fin(true);
|
| - headers_ir.set_priority(1);
|
| - headers_ir.set_has_priority(true);
|
| - headers_ir.SetHeader("bar", "foo");
|
| - headers_ir.SetHeader("foo", "");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
|
| - if (IsSpdy2() || IsSpdy3()) {
|
| - // HEADERS with priority not supported.
|
| - } else {
|
| - CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - }
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] =
|
| - "HEADERS frame with a 0-length header name, FIN, max stream ID, padded";
|
| -
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x15, 0x01, // Headers
|
| - 0x0d, 0x7f, 0xff, 0xff, // FIN | END_HEADERS | PADDED, Stream
|
| - // 0x7fffffff
|
| - 0xff, 0x05, 0x00, 0x00, // Pad length field
|
| - 0x03, 0x66, 0x6f, 0x6f, // .foo
|
| - 0x00, 0x03, 0x66, 0x6f, // @.fo
|
| - 0x6f, 0x03, 0x62, 0x61, // o.ba
|
| - 0x72, // r
|
| - // Padding payload
|
| - 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - };
|
| - SpdyHeadersIR headers_ir(0x7fffffff);
|
| - headers_ir.set_fin(true);
|
| - headers_ir.SetHeader("", "foo");
|
| - headers_ir.SetHeader("foo", "bar");
|
| - headers_ir.set_padding_len(6);
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
|
| - if (IsSpdy2() || IsSpdy3()) {
|
| - // Padding is not supported.
|
| - } else {
|
| - CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - }
|
| - }
|
| -}
|
| -
|
| -// TODO(phajdan.jr): Clean up after we no longer need
|
| -// to workaround http://crbug.com/139744.
|
| -#if !defined(USE_SYSTEM_ZLIB)
|
| -TEST_P(SpdyFramerTest, CreateHeadersCompressed) {
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_enable_compression(true);
|
| -
|
| - {
|
| - const char kDescription[] = "HEADERS frame, no FIN";
|
| -
|
| - const unsigned char kV2FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x08,
|
| - 0x00, 0x00, 0x00, 0x32,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x38, 0xea,
|
| - 0xdf, 0xa2, 0x51, 0xb2,
|
| - 0x62, 0x60, 0x62, 0x60,
|
| - 0x4e, 0x4a, 0x2c, 0x62,
|
| - 0x60, 0x06, 0x08, 0xa0,
|
| - 0xb4, 0xfc, 0x7c, 0x80,
|
| - 0x00, 0x62, 0x60, 0x4e,
|
| - 0xcb, 0xcf, 0x67, 0x60,
|
| - 0x06, 0x08, 0xa0, 0xa4,
|
| - 0xc4, 0x22, 0x80, 0x00,
|
| - 0x02, 0x00, 0x00, 0x00,
|
| - 0xff, 0xff,
|
| - };
|
| - const unsigned char kV3FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x08,
|
| - 0x00, 0x00, 0x00, 0x31,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x38, 0xea, 0xe3, 0xc6,
|
| - 0xa7, 0xc2, 0x02, 0xe5,
|
| - 0x0e, 0x50, 0xc2, 0x4b,
|
| - 0x4a, 0x04, 0xe5, 0x0b,
|
| - 0x66, 0x80, 0x00, 0x4a,
|
| - 0xcb, 0xcf, 0x07, 0x08,
|
| - 0x20, 0x10, 0x95, 0x96,
|
| - 0x9f, 0x0f, 0xa2, 0x00,
|
| - 0x02, 0x28, 0x29, 0xb1,
|
| - 0x08, 0x20, 0x80, 0x00,
|
| - 0x00, 0x00, 0x00, 0xff,
|
| - 0xff,
|
| - };
|
| - const unsigned char kV2SIMDFrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x08,
|
| - 0x00, 0x00, 0x00, 0x2f,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x38, 0xea,
|
| - 0xdf, 0xa2, 0x51, 0xb2,
|
| - 0x62, 0x60, 0x62, 0x60,
|
| - 0x4e, 0x4a, 0x2c, 0x62,
|
| - 0x60, 0x06, 0x08, 0xa0,
|
| - 0xb4, 0xfc, 0x7c, 0x80,
|
| - 0x00, 0x62, 0x60, 0x06,
|
| - 0x13, 0x00, 0x01, 0x94,
|
| - 0x94, 0x58, 0x04, 0x10,
|
| - 0x40, 0x00, 0x00, 0x00,
|
| - 0x00, 0xff, 0xff,
|
| - };
|
| - const unsigned char kV3SIMDFrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x08,
|
| - 0x00, 0x00, 0x00, 0x2c,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x38, 0xea, 0xe3, 0xc6,
|
| - 0xa7, 0xc2, 0x02, 0xe5,
|
| - 0x0e, 0x50, 0xc2, 0x4b,
|
| - 0x4a, 0x04, 0xe5, 0x0b,
|
| - 0x66, 0x80, 0x00, 0x4a,
|
| - 0xcb, 0xcf, 0x07, 0x08,
|
| - 0x20, 0x24, 0x0a, 0x20,
|
| - 0x80, 0x92, 0x12, 0x8b,
|
| - 0x00, 0x02, 0x08, 0x00,
|
| - 0x00, 0x00, 0xff, 0xff,
|
| - };
|
| -
|
| - SpdyHeadersIR headers_ir(1);
|
| - headers_ir.SetHeader("bar", "foo");
|
| - headers_ir.SetHeader("foo", "bar");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
|
| - const unsigned char* frame_data =
|
| - reinterpret_cast<const unsigned char*>(frame->data());
|
| - if (IsSpdy2()) {
|
| - // Try comparing with SIMD version, if that fails, do a failing check
|
| - // with pretty printing against non-SIMD version
|
| - if (memcmp(frame_data,
|
| - kV2SIMDFrameData,
|
| - std::min(arraysize(kV2SIMDFrameData), frame->size())) != 0) {
|
| - CompareCharArraysWithHexError(kDescription,
|
| - frame_data,
|
| - frame->size(),
|
| - kV2FrameData,
|
| - arraysize(kV2FrameData));
|
| - }
|
| - } else if (IsSpdy3()) {
|
| - if (memcmp(frame_data,
|
| - kV3SIMDFrameData,
|
| - std::min(arraysize(kV3SIMDFrameData), frame->size())) != 0) {
|
| - CompareCharArraysWithHexError(kDescription,
|
| - frame_data,
|
| - frame->size(),
|
| - kV3FrameData,
|
| - arraysize(kV3FrameData));
|
| - }
|
| - } else {
|
| - // Deflate compression doesn't apply to HPACK.
|
| - }
|
| - }
|
| -}
|
| -#endif // !defined(USE_SYSTEM_ZLIB)
|
| -
|
| -TEST_P(SpdyFramerTest, CreateWindowUpdate) {
|
| - SpdyFramer framer(spdy_version_);
|
| -
|
| - {
|
| - const char kDescription[] = "WINDOW_UPDATE frame";
|
| - const unsigned char kV3FrameData[] = { // Also applies for V2.
|
| - 0x80, spdy_version_ch_, 0x00, 0x09,
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x04, 0x08,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x01, 0x00, 0x00, 0x00,
|
| - 0x01,
|
| - };
|
| - scoped_ptr<SpdyFrame> frame(
|
| - framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 1)));
|
| - if (IsSpdy4()) {
|
| - CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - } else {
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - }
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] = "WINDOW_UPDATE frame with max stream ID";
|
| - const unsigned char kV3FrameData[] = { // Also applies for V2.
|
| - 0x80, spdy_version_ch_, 0x00, 0x09,
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - 0x7f, 0xff, 0xff, 0xff,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x04, 0x08,
|
| - 0x00, 0x7f, 0xff, 0xff,
|
| - 0xff, 0x00, 0x00, 0x00,
|
| - 0x01,
|
| - };
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
|
| - SpdyWindowUpdateIR(0x7FFFFFFF, 1)));
|
| - if (IsSpdy4()) {
|
| - CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - } else {
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - }
|
| - }
|
| -
|
| - {
|
| - const char kDescription[] = "WINDOW_UPDATE frame with max window delta";
|
| - const unsigned char kV3FrameData[] = { // Also applies for V2.
|
| - 0x80, spdy_version_ch_, 0x00, 0x09,
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x7f, 0xff, 0xff, 0xff,
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x04, 0x08,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x01, 0x7f, 0xff, 0xff,
|
| - 0xff,
|
| - };
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
|
| - SpdyWindowUpdateIR(1, 0x7FFFFFFF)));
|
| - if (IsSpdy4()) {
|
| - CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
|
| - } else {
|
| - CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
|
| - }
|
| - }
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, SerializeBlocked) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - SpdyFramer framer(spdy_version_);
|
| -
|
| - const char kDescription[] = "BLOCKED frame";
|
| - const unsigned char kType = static_cast<unsigned char>(
|
| - SpdyConstants::SerializeFrameType(spdy_version_, BLOCKED));
|
| - const unsigned char kFrameData[] = {
|
| - 0x00, 0x00, 0x00, kType, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - };
|
| - SpdyBlockedIR blocked_ir(0);
|
| - scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
|
| - CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, CreateBlocked) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - SpdyFramer framer(spdy_version_);
|
| -
|
| - const char kDescription[] = "BLOCKED frame";
|
| - const SpdyStreamId kStreamId = 3;
|
| -
|
| - scoped_ptr<SpdySerializedFrame> frame_serialized(
|
| - framer.SerializeBlocked(SpdyBlockedIR(kStreamId)));
|
| - SpdyBlockedIR blocked_ir(kStreamId);
|
| - scoped_ptr<SpdySerializedFrame> frame_created(
|
| - framer.SerializeFrame(blocked_ir));
|
| -
|
| - CompareFrames(kDescription, *frame_serialized, *frame_created);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - {
|
| - // Test framing PUSH_PROMISE without padding.
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_enable_compression(false);
|
| - const char kDescription[] = "PUSH_PROMISE frame without padding";
|
| -
|
| - const unsigned char kFrameData[] = {
|
| - 0x00, 0x00, 0x16, 0x05, // PUSH_PROMISE
|
| - 0x04, 0x00, 0x00, 0x00, // END_HEADERS
|
| - 0x2a, 0x00, 0x00, 0x00, // Stream 42
|
| - 0x39, 0x00, 0x03, 0x62, // Promised stream 57, @.b
|
| - 0x61, 0x72, 0x03, 0x66, // ar.f
|
| - 0x6f, 0x6f, 0x00, 0x03, // oo@.
|
| - 0x66, 0x6f, 0x6f, 0x03, // foo.
|
| - 0x62, 0x61, 0x72, // bar
|
| - };
|
| -
|
| - SpdyPushPromiseIR push_promise(42, 57);
|
| - push_promise.SetHeader("bar", "foo");
|
| - push_promise.SetHeader("foo", "bar");
|
| - scoped_ptr<SpdySerializedFrame> frame(
|
| - framer.SerializePushPromise(push_promise));
|
| - CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| - }
|
| -
|
| - {
|
| - // Test framing PUSH_PROMISE with one byte of padding.
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_enable_compression(false);
|
| - const char kDescription[] = "PUSH_PROMISE frame with one byte of padding";
|
| -
|
| - const unsigned char kFrameData[] = {
|
| - 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
|
| - 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
|
| - 0x2a, 0x00, 0x00, 0x00, // Stream 42, Pad length field
|
| - 0x00, 0x39, 0x00, 0x03, // Promised stream 57
|
| - 0x62, 0x61, 0x72, 0x03, // bar.
|
| - 0x66, 0x6f, 0x6f, 0x00, // foo@
|
| - 0x03, 0x66, 0x6f, 0x6f, // .foo
|
| - 0x03, 0x62, 0x61, 0x72, // .bar
|
| - };
|
| -
|
| - SpdyPushPromiseIR push_promise(42, 57);
|
| - push_promise.set_padding_len(1);
|
| - push_promise.SetHeader("bar", "foo");
|
| - push_promise.SetHeader("foo", "bar");
|
| - scoped_ptr<SpdySerializedFrame> frame(
|
| - framer.SerializePushPromise(push_promise));
|
| - CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| - }
|
| -
|
| - {
|
| - // Test framing PUSH_PROMISE with 177 bytes of padding.
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_enable_compression(false);
|
| - const char kDescription[] = "PUSH_PROMISE frame with 177 bytes of padding";
|
| -
|
| - const unsigned char kFrameData[] = {
|
| - 0x00, 0x00, 0xc7, 0x05, // PUSH_PROMISE
|
| - 0x0c, 0x00, 0x00, 0x00, // END_HEADERS | PADDED
|
| - 0x2a, 0xb0, 0x00, 0x00, // Stream 42, Pad length field
|
| - 0x00, 0x39, 0x00, 0x03, // Promised stream 57
|
| - 0x62, 0x61, 0x72, 0x03, // bar.
|
| - 0x66, 0x6f, 0x6f, 0x00, // foo@
|
| - 0x03, 0x66, 0x6f, 0x6f, // .foo
|
| - 0x03, 0x62, 0x61, 0x72, // .bar
|
| - // Padding of 176 0x00(s).
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
| - };
|
| -
|
| - SpdyPushPromiseIR push_promise(42, 57);
|
| - push_promise.set_padding_len(177);
|
| - push_promise.SetHeader("bar", "foo");
|
| - push_promise.SetHeader("foo", "bar");
|
| - scoped_ptr<SpdySerializedFrame> frame(
|
| - framer.SerializePushPromise(push_promise));
|
| - CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| - }
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_enable_compression(false);
|
| - const char kDescription[] = "CONTINUATION frame";
|
| -
|
| - const unsigned char kFrameData[] = {
|
| - 0x00, 0x00, 0x12, 0x09, 0x00, // CONTINUATION
|
| - 0x00, 0x00, 0x00, 0x2a, // Stream 42
|
| - 0x00, 0x03, 0x62, 0x61, // @.ba
|
| - 0x72, 0x03, 0x66, 0x6f, // r.fo
|
| - 0x6f, 0x00, 0x03, 0x66, // o@.f
|
| - 0x6f, 0x6f, 0x03, 0x62, // oo.b
|
| - 0x61, 0x72, // ar
|
| - };
|
| -
|
| - SpdyContinuationIR continuation(42);
|
| - continuation.SetHeader("bar", "foo");
|
| - continuation.SetHeader("foo", "bar");
|
| - scoped_ptr<SpdySerializedFrame> frame(
|
| - framer.SerializeContinuation(continuation));
|
| - CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - {
|
| - // Test framing in a case such that a PUSH_PROMISE frame, with one byte of
|
| - // padding, cannot hold all the data payload, which is overflowed to the
|
| - // consecutive CONTINUATION frame.
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_enable_compression(false);
|
| - const char kDescription[] =
|
| - "PUSH_PROMISE and CONTINUATION frames with one byte of padding";
|
| -
|
| - const unsigned char kPartialPushPromiseFrameData[] = {
|
| - 0x00, 0x03, 0xf7, 0x05, // PUSH_PROMISE
|
| - 0x08, 0x00, 0x00, 0x00, // PADDED
|
| - 0x2a, 0x00, 0x00, 0x00, // Stream 42
|
| - 0x00, 0x39, 0x00, 0x03, // Promised stream 57
|
| - 0x78, 0x78, 0x78, 0x7f, // xxx.
|
| - 0x81, 0x07, 0x78, 0x78, // ..xx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, // xx
|
| - };
|
| -
|
| - const unsigned char kContinuationFrameData[] = {
|
| - 0x00, 0x00, 0x16, 0x09, // CONTINUATION
|
| - 0x04, 0x00, 0x00, 0x00, // END_HEADERS
|
| - 0x2a, 0x78, 0x78, 0x78, // Stream 42, xxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78, 0x78, 0x78, // xxxx
|
| - 0x78, 0x78,
|
| - };
|
| -
|
| - SpdyPushPromiseIR push_promise(42, 57);
|
| - push_promise.set_padding_len(1);
|
| - string big_value(TestSpdyVisitor::sent_control_frame_max_size(), 'x');
|
| - push_promise.SetHeader("xxx", big_value);
|
| - scoped_ptr<SpdySerializedFrame> frame(
|
| - framer.SerializePushPromise(push_promise));
|
| -
|
| - // The entire frame should look like below:
|
| - // Name Length in Byte
|
| - // ------------------------------------------- Begin of PUSH_PROMISE frame
|
| - // PUSH_PROMISE header 9
|
| - // Pad length field 1
|
| - // Promised stream 4
|
| - // Length field of key 2
|
| - // Content of key 3
|
| - // Length field of value 3
|
| - // Part of big_value 16361
|
| - // ------------------------------------------- Begin of CONTINUATION frame
|
| - // CONTINUATION header 9
|
| - // Remaining of big_value 22
|
| - // ------------------------------------------- End
|
| -
|
| - // Length of everything listed above except big_value.
|
| - int len_non_data_payload = 31;
|
| - EXPECT_EQ(
|
| - TestSpdyVisitor::sent_control_frame_max_size() + len_non_data_payload,
|
| - frame->size());
|
| -
|
| - // Partially compare the PUSH_PROMISE frame against the template.
|
| - const unsigned char* frame_data =
|
| - reinterpret_cast<const unsigned char*>(frame->data());
|
| - CompareCharArraysWithHexError(kDescription,
|
| - frame_data,
|
| - arraysize(kPartialPushPromiseFrameData),
|
| - kPartialPushPromiseFrameData,
|
| - arraysize(kPartialPushPromiseFrameData));
|
| -
|
| - // Compare the CONTINUATION frame against the template.
|
| - frame_data += TestSpdyVisitor::sent_control_frame_max_size();
|
| - CompareCharArraysWithHexError(kDescription,
|
| - frame_data,
|
| - arraysize(kContinuationFrameData),
|
| - kContinuationFrameData,
|
| - arraysize(kContinuationFrameData));
|
| - }
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, CreateAltSvc) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - SpdyFramer framer(spdy_version_);
|
| -
|
| - const char kDescription[] = "ALTSVC frame";
|
| - const unsigned char kType = static_cast<unsigned char>(
|
| - SpdyConstants::SerializeFrameType(spdy_version_, ALTSVC));
|
| - const unsigned char kFrameData[] = {
|
| - 0x00, 0x00, 0x17, kType, 0x00,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 0x00, 0x00, 0x00, 0x05,
|
| - 0x01, 0xbb, 0x00, 0x04, // Port = 443
|
| - 'p', 'i', 'd', '1', // Protocol-ID
|
| - 0x04, 'h', 'o', 's',
|
| - 't', 'o', 'r', 'i',
|
| - 'g', 'i', 'n',
|
| - };
|
| - SpdyAltSvcIR altsvc_ir(3);
|
| - altsvc_ir.set_max_age(5);
|
| - altsvc_ir.set_port(443);
|
| - altsvc_ir.set_protocol_id("pid1");
|
| - altsvc_ir.set_host("host");
|
| - altsvc_ir.set_origin("origin");
|
| - scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
|
| - CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, CreatePriority) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - SpdyFramer framer(spdy_version_);
|
| -
|
| - const char kDescription[] = "PRIORITY frame";
|
| - const unsigned char kType = static_cast<unsigned char>(
|
| - SpdyConstants::SerializeFrameType(spdy_version_, PRIORITY));
|
| - const unsigned char kFrameData[] = {
|
| - 0x00, 0x00, 0x05, kType, 0x00,
|
| - 0x00, 0x00, 0x00, 0x02, // Stream ID = 2
|
| - 0x80, 0x00, 0x00, 0x01, // Exclusive dependency, parent stream ID = 1
|
| - 0x10, // Weight = 16
|
| - };
|
| - SpdyPriorityIR priority_ir(2, 1, 16, true);
|
| - scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(priority_ir));
|
| - CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ReadCompressedSynStreamHeaderBlock) {
|
| - if (spdy_version_ > SPDY3) {
|
| - // SYN_STREAM not supported in SPDY>3
|
| - return;
|
| - }
|
| - SpdyFramer framer(spdy_version_);
|
| - SpdySynStreamIR syn_stream(1);
|
| - syn_stream.set_priority(1);
|
| - syn_stream.SetHeader("aa", "vv");
|
| - syn_stream.SetHeader("bb", "ww");
|
| - SpdyHeaderBlock headers = syn_stream.name_value_block();
|
| - scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
|
| - EXPECT_TRUE(control_frame.get() != NULL);
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = true;
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(control_frame->data()),
|
| - control_frame->size());
|
| - EXPECT_EQ(1, visitor.syn_frame_count_);
|
| - EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ReadCompressedSynReplyHeaderBlock) {
|
| - if (spdy_version_ > SPDY3) {
|
| - return;
|
| - }
|
| - SpdyFramer framer(spdy_version_);
|
| - SpdySynReplyIR syn_reply(1);
|
| - syn_reply.SetHeader("alpha", "beta");
|
| - syn_reply.SetHeader("gamma", "delta");
|
| - SpdyHeaderBlock headers = syn_reply.name_value_block();
|
| - scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynReply(syn_reply));
|
| - EXPECT_TRUE(control_frame.get() != NULL);
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = true;
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(control_frame->data()),
|
| - control_frame->size());
|
| - if (IsSpdy4()) {
|
| - EXPECT_EQ(0, visitor.syn_reply_frame_count_);
|
| - EXPECT_EQ(1, visitor.headers_frame_count_);
|
| - } else {
|
| - EXPECT_EQ(1, visitor.syn_reply_frame_count_);
|
| - EXPECT_EQ(0, visitor.headers_frame_count_);
|
| - }
|
| - EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) {
|
| - SpdyFramer framer(spdy_version_);
|
| - SpdyHeadersIR headers_ir(1);
|
| - headers_ir.SetHeader("alpha", "beta");
|
| - headers_ir.SetHeader("gamma", "delta");
|
| - SpdyHeaderBlock headers = headers_ir.name_value_block();
|
| - scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
|
| - EXPECT_TRUE(control_frame.get() != NULL);
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = true;
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(control_frame->data()),
|
| - control_frame->size());
|
| - EXPECT_EQ(1, visitor.headers_frame_count_);
|
| - // control_frame_header_data_count_ depends on the random sequence
|
| - // produced by rand(), so adding, removing or running single tests
|
| - // alters this value. The best we can do is assert that it happens
|
| - // at least twice.
|
| - EXPECT_LE(2, visitor.control_frame_header_data_count_);
|
| - EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
|
| - EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
|
| - EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) {
|
| - SpdyFramer framer(spdy_version_);
|
| - SpdyHeadersIR headers_ir(1);
|
| - headers_ir.set_fin(true);
|
| - headers_ir.SetHeader("alpha", "beta");
|
| - headers_ir.SetHeader("gamma", "delta");
|
| - SpdyHeaderBlock headers = headers_ir.name_value_block();
|
| - scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers_ir));
|
| - EXPECT_TRUE(control_frame.get() != NULL);
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = true;
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(control_frame->data()),
|
| - control_frame->size());
|
| - EXPECT_EQ(1, visitor.headers_frame_count_);
|
| - // control_frame_header_data_count_ depends on the random sequence
|
| - // produced by rand(), so adding, removing or running single tests
|
| - // alters this value. The best we can do is assert that it happens
|
| - // at least twice.
|
| - EXPECT_LE(2, visitor.control_frame_header_data_count_);
|
| - EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
|
| - EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
|
| - EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) {
|
| - if (spdy_version_ > SPDY3) {
|
| - // TODO(jgraettinger): This test setup doesn't work with HPACK.
|
| - return;
|
| - }
|
| - // First find the size of the header value in order to just reach the control
|
| - // frame max size.
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_enable_compression(false);
|
| - SpdySynStreamIR syn_stream(1);
|
| - syn_stream.set_priority(1);
|
| - syn_stream.SetHeader("aa", "");
|
| - scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
|
| - const size_t kBigValueSize =
|
| - TestSpdyVisitor::sent_control_frame_max_size() - control_frame->size();
|
| -
|
| - // Create a frame at exactly that size.
|
| - string big_value(kBigValueSize, 'x');
|
| - syn_stream.SetHeader("aa", big_value);
|
| - control_frame.reset(framer.SerializeSynStream(syn_stream));
|
| - EXPECT_TRUE(control_frame.get() != NULL);
|
| - EXPECT_EQ(TestSpdyVisitor::sent_control_frame_max_size(),
|
| - control_frame->size());
|
| -
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(control_frame->data()),
|
| - control_frame->size());
|
| - EXPECT_TRUE(visitor.header_buffer_valid_);
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - EXPECT_EQ(1, visitor.syn_frame_count_);
|
| - EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
|
| - EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
|
| - EXPECT_LT(kBigValueSize, visitor.header_buffer_length_);
|
| -}
|
| -
|
| -// This test is disabled because Chromium is willing to accept control frames up
|
| -// to the maximum size allowed by the specification, and SpdyFrameBuilder is not
|
| -// capable of building larger frames.
|
| -TEST_P(SpdyFramerTest, DISABLED_ControlFrameTooLarge) {
|
| - if (spdy_version_ > SPDY3) {
|
| - // TODO(jgraettinger): This test setup doesn't work with HPACK.
|
| - return;
|
| - }
|
| - // First find the size of the header value in order to just reach the control
|
| - // frame max size.
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_enable_compression(false);
|
| - SpdySynStreamIR syn_stream(1);
|
| - syn_stream.SetHeader("aa", "");
|
| - syn_stream.set_priority(1);
|
| - scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
|
| - const size_t kBigValueSize =
|
| - SpdyConstants::GetFrameMaximumSize(spdy_version_) -
|
| - control_frame->size() + 1;
|
| -
|
| - // Create a frame at exatly that size.
|
| - string big_value(kBigValueSize, 'x');
|
| - syn_stream.SetHeader("aa", big_value);
|
| - // Upstream branches here and wraps SPDY4 with EXPECT_DEBUG_DFATAL. We
|
| - // neither support that in Chromium, nor do we use the same DFATAL (see
|
| - // SpdyFrameBuilder::WriteFramePrefix()).
|
| - control_frame.reset(framer.SerializeSynStream(syn_stream));
|
| -
|
| - EXPECT_TRUE(control_frame.get() != NULL);
|
| - EXPECT_EQ(SpdyConstants::GetFrameMaximumSize(spdy_version_) + 1,
|
| - control_frame->size());
|
| -
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(control_frame->data()),
|
| - control_frame->size());
|
| - EXPECT_FALSE(visitor.header_buffer_valid_);
|
| - EXPECT_EQ(1, visitor.error_count_);
|
| - EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
|
| - visitor.framer_.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - EXPECT_EQ(0, visitor.syn_frame_count_);
|
| - EXPECT_EQ(0u, visitor.header_buffer_length_);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_enable_compression(false);
|
| - SpdyHeadersIR headers(1);
|
| - headers.set_padding_len(256);
|
| -
|
| - // Exact payload length will change with HPACK, but this should be long
|
| - // enough to cause an overflow.
|
| - const size_t kBigValueSize = kControlFrameSizeLimit;
|
| - string big_value(kBigValueSize, 'x');
|
| - headers.SetHeader("aa", big_value);
|
| - scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
|
| - EXPECT_TRUE(control_frame.get() != NULL);
|
| - EXPECT_GT(control_frame->size(),
|
| - TestSpdyVisitor::sent_control_frame_max_size());
|
| -
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(control_frame->data()),
|
| - control_frame->size());
|
| - EXPECT_TRUE(visitor.header_buffer_valid_);
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - EXPECT_EQ(1, visitor.headers_frame_count_);
|
| - EXPECT_EQ(16, visitor.continuation_count_);
|
| - EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, TooLargePushPromiseFrameUsesContinuation) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_enable_compression(false);
|
| - SpdyPushPromiseIR push_promise(1, 2);
|
| - push_promise.set_padding_len(256);
|
| -
|
| - // Exact payload length will change with HPACK, but this should be long
|
| - // enough to cause an overflow.
|
| - const size_t kBigValueSize = kControlFrameSizeLimit;
|
| - string big_value(kBigValueSize, 'x');
|
| - push_promise.SetHeader("aa", big_value);
|
| - scoped_ptr<SpdyFrame> control_frame(
|
| - framer.SerializePushPromise(push_promise));
|
| - EXPECT_TRUE(control_frame.get() != NULL);
|
| - EXPECT_GT(control_frame->size(),
|
| - TestSpdyVisitor::sent_control_frame_max_size());
|
| -
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(control_frame->data()),
|
| - control_frame->size());
|
| - EXPECT_TRUE(visitor.header_buffer_valid_);
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - EXPECT_EQ(1, visitor.push_promise_frame_count_);
|
| - EXPECT_EQ(16, visitor.continuation_count_);
|
| - EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
|
| -}
|
| -
|
| -// Check that the framer stops delivering header data chunks once the visitor
|
| -// declares it doesn't want any more. This is important to guard against
|
| -// "zip bomb" types of attacks.
|
| -TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) {
|
| - const size_t kHeaderBufferChunks = 4;
|
| - const size_t kHeaderBufferSize =
|
| - TestSpdyVisitor::header_data_chunk_max_size() * kHeaderBufferChunks;
|
| - const size_t kBigValueSize = kHeaderBufferSize * 2;
|
| - string big_value(kBigValueSize, 'x');
|
| - SpdyFramer framer(spdy_version_);
|
| - SpdyHeadersIR headers(1);
|
| - headers.set_priority(1);
|
| - headers.set_fin(true);
|
| - headers.SetHeader("aa", big_value);
|
| - scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
|
| - EXPECT_TRUE(control_frame.get() != NULL);
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.set_header_buffer_size(kHeaderBufferSize);
|
| - visitor.use_compression_ = true;
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(control_frame->data()),
|
| - control_frame->size());
|
| - EXPECT_FALSE(visitor.header_buffer_valid_);
|
| - EXPECT_EQ(1, visitor.error_count_);
|
| - EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
|
| - visitor.framer_.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| -
|
| - // The framer should have stoped delivering chunks after the visitor
|
| - // signaled "stop" by returning false from OnControlFrameHeaderData().
|
| - //
|
| - // control_frame_header_data_count_ depends on the random sequence
|
| - // produced by rand(), so adding, removing or running single tests
|
| - // alters this value. The best we can do is assert that it happens
|
| - // at least kHeaderBufferChunks + 1.
|
| - EXPECT_LE(kHeaderBufferChunks + 1,
|
| - static_cast<unsigned>(visitor.control_frame_header_data_count_));
|
| - EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
|
| -
|
| - // The framer should not have sent half-close to the visitor.
|
| - EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, DecompressCorruptHeaderBlock) {
|
| - if (spdy_version_ > SPDY3) {
|
| - // Deflate compression doesn't apply to HPACK.
|
| - return;
|
| - }
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_enable_compression(false);
|
| - // Construct a SYN_STREAM control frame without compressing the header block,
|
| - // and have the framer try to decompress it. This will cause the framer to
|
| - // deal with a decompression error.
|
| - SpdySynStreamIR syn_stream(1);
|
| - syn_stream.set_priority(1);
|
| - syn_stream.SetHeader("aa", "alpha beta gamma delta");
|
| - scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = true;
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(control_frame->data()),
|
| - control_frame->size());
|
| - EXPECT_EQ(1, visitor.error_count_);
|
| - EXPECT_EQ(SpdyFramer::SPDY_DECOMPRESS_FAILURE, visitor.framer_.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - EXPECT_EQ(0u, visitor.header_buffer_length_);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) {
|
| - SpdyFramer framer(spdy_version_);
|
| - // Create a GoAway frame that has a few extra bytes at the end.
|
| - // We create enough overhead to overflow the framer's control frame buffer.
|
| - ASSERT_LE(SpdyFramer::kControlFrameBufferSize, 250u);
|
| - const size_t length = SpdyFramer::kControlFrameBufferSize + 1;
|
| - const unsigned char kV3FrameData[] = { // Also applies for V2.
|
| - 0x80, spdy_version_ch_, 0x00, 0x07,
|
| - 0x00, 0x00, 0x00, static_cast<unsigned char>(length),
|
| - 0x00, 0x00, 0x00, 0x00, // Stream ID
|
| - 0x00, 0x00, 0x00, 0x00, // Status
|
| - };
|
| -
|
| - // SPDY version 4 and up GOAWAY frames are only bound to a minimal length,
|
| - // since it may carry opaque data. Verify that minimal length is tested.
|
| - ASSERT_GT(framer.GetGoAwayMinimumSize(), framer.GetControlFrameHeaderSize());
|
| - const size_t less_than_min_length =
|
| - framer.GetGoAwayMinimumSize() - framer.GetControlFrameHeaderSize() - 1;
|
| - ASSERT_LE(less_than_min_length, std::numeric_limits<unsigned char>::max());
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, static_cast<unsigned char>(less_than_min_length), 0x07,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, // Stream Id
|
| - 0x00, 0x00, 0x00, 0x00, // Status
|
| - 0x00,
|
| - };
|
| - const size_t pad_length =
|
| - length + framer.GetControlFrameHeaderSize() -
|
| - (IsSpdy4() ? sizeof(kV4FrameData) : sizeof(kV3FrameData));
|
| - string pad(pad_length, 'A');
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| -
|
| - if (IsSpdy4()) {
|
| - visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
|
| - } else {
|
| - visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
|
| - }
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<const unsigned char*>(pad.c_str()),
|
| - pad.length());
|
| -
|
| - EXPECT_EQ(1, visitor.error_count_); // This generated an error.
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
|
| - visitor.framer_.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - EXPECT_EQ(0, visitor.goaway_count_); // Frame not parsed.
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ReadZeroLenSettingsFrame) {
|
| - SpdyFramer framer(spdy_version_);
|
| - SpdySettingsIR settings_ir;
|
| - scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
|
| - SetFrameLength(control_frame.get(), 0, spdy_version_);
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = false;
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(control_frame->data()),
|
| - framer.GetControlFrameHeaderSize());
|
| - if (spdy_version_ <= SPDY3) {
|
| - // Should generate an error, since zero-len settings frames are unsupported.
|
| - EXPECT_EQ(1, visitor.error_count_);
|
| - } else {
|
| - // Zero-len settings frames are permitted as of SPDY 4.
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - }
|
| -}
|
| -
|
| -// Tests handling of SETTINGS frames with invalid length.
|
| -TEST_P(SpdyFramerTest, ReadBogusLenSettingsFrame) {
|
| - SpdyFramer framer(spdy_version_);
|
| - SpdySettingsIR settings_ir;
|
| -
|
| - // Add a setting to pad the frame so that we don't get a buffer overflow when
|
| - // calling SimulateInFramer() below.
|
| - settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE,
|
| - false,
|
| - false,
|
| - 0x00000002);
|
| - scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
|
| - const size_t kNewLength = 14;
|
| - SetFrameLength(control_frame.get(), kNewLength, spdy_version_);
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = false;
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(control_frame->data()),
|
| - framer.GetControlFrameHeaderSize() + kNewLength);
|
| - // Should generate an error, since its not possible to have a
|
| - // settings frame of length kNewLength.
|
| - EXPECT_EQ(1, visitor.error_count_);
|
| -}
|
| -
|
| -// Tests handling of SETTINGS frames larger than the frame buffer size.
|
| -TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) {
|
| - SpdyFramer framer(spdy_version_);
|
| - SpdySettingsIR settings_ir;
|
| - settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
|
| - false, // persist
|
| - false, // persisted
|
| - 5);
|
| - settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 2),
|
| - false, // persist
|
| - false, // persisted
|
| - 6);
|
| - settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 3),
|
| - false, // persist
|
| - false, // persisted
|
| - 7);
|
| -
|
| - scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
|
| - EXPECT_LT(SpdyFramer::kControlFrameBufferSize,
|
| - control_frame->size());
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = false;
|
| -
|
| - // Read all at once.
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(control_frame->data()),
|
| - control_frame->size());
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - EXPECT_EQ(3, visitor.setting_count_);
|
| - if (spdy_version_ > SPDY3) {
|
| - EXPECT_EQ(1, visitor.settings_ack_sent_);
|
| - }
|
| -
|
| - // Read data in small chunks.
|
| - size_t framed_data = 0;
|
| - size_t unframed_data = control_frame->size();
|
| - size_t kReadChunkSize = 5; // Read five bytes at a time.
|
| - while (unframed_data > 0) {
|
| - size_t to_read = std::min(kReadChunkSize, unframed_data);
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
|
| - to_read);
|
| - unframed_data -= to_read;
|
| - framed_data += to_read;
|
| - }
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - EXPECT_EQ(3 * 2, visitor.setting_count_);
|
| - if (spdy_version_ > SPDY3) {
|
| - EXPECT_EQ(2, visitor.settings_ack_sent_);
|
| - }
|
| -}
|
| -
|
| -// Tests handling of SETTINGS frame with duplicate entries.
|
| -TEST_P(SpdyFramerTest, ReadDuplicateSettings) {
|
| - SpdyFramer framer(spdy_version_);
|
| -
|
| - const unsigned char kV2FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x04,
|
| - 0x00, 0x00, 0x00, 0x1C,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 0x01, 0x00, 0x00, 0x00, // 1st Setting
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 0x01, 0x00, 0x00, 0x00, // 2nd (duplicate) Setting
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - };
|
| - const unsigned char kV3FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x04,
|
| - 0x00, 0x00, 0x00, 0x1C,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 0x00, 0x00, 0x00, 0x01, // 1st Setting
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 0x00, 0x00, 0x00, 0x01, // 2nd (duplicate) Setting
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 0x00, 0x00, 0x00, 0x03, // 3rd (unprocessed) Setting
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x12, 0x04,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x01, // 1st Setting
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 0x00, 0x01, // 2nd (duplicate) Setting
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 0x00, 0x03, // 3rd (unprocessed) Setting
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - };
|
| -
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = false;
|
| - if (IsSpdy2()) {
|
| - visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
|
| - } else if (IsSpdy3()) {
|
| - visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
|
| - } else {
|
| - visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
|
| - }
|
| -
|
| - if (!IsSpdy4()) {
|
| - EXPECT_EQ(1, visitor.setting_count_);
|
| - EXPECT_EQ(1, visitor.error_count_);
|
| - } else {
|
| - // In SPDY 4+, duplicate settings are allowed;
|
| - // each setting replaces the previous value for that setting.
|
| - EXPECT_EQ(3, visitor.setting_count_);
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - EXPECT_EQ(1, visitor.settings_ack_sent_);
|
| - }
|
| -}
|
| -
|
| -// Tests handling of SETTINGS frame with a setting we don't recognize.
|
| -TEST_P(SpdyFramerTest, ReadUnknownSettingsId) {
|
| - SpdyFramer framer(spdy_version_);
|
| -
|
| - const unsigned char kV2FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x04,
|
| - 0x00, 0x00, 0x00, 0x1C,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x10, 0x00, 0x00, 0x00, // 1st Setting
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - };
|
| - const unsigned char kV3FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x04,
|
| - 0x00, 0x00, 0x00, 0x1C,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, 0x10, // 1st Setting
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x06, 0x04,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x10, // 1st Setting
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - };
|
| -
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = false;
|
| - if (IsSpdy2()) {
|
| - visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
|
| - } else if (IsSpdy3()) {
|
| - visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
|
| - } else {
|
| - visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
|
| - }
|
| -
|
| - if (!IsSpdy4()) {
|
| - EXPECT_EQ(0, visitor.setting_count_);
|
| - EXPECT_EQ(1, visitor.error_count_);
|
| - } else {
|
| - // In SPDY 4+, we ignore unknown settings because of extensions.
|
| - EXPECT_EQ(0, visitor.setting_count_);
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - }
|
| -}
|
| -
|
| -// Tests handling of SETTINGS frame with entries out of order.
|
| -TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) {
|
| - SpdyFramer framer(spdy_version_);
|
| -
|
| - const unsigned char kV2FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x04,
|
| - 0x00, 0x00, 0x00, 0x1C,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 0x02, 0x00, 0x00, 0x00, // 1st Setting
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 0x01, 0x00, 0x00, 0x00, // 2nd (out of order) Setting
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 0x03, 0x00, 0x00, 0x00, // 3rd (unprocessed) Setting
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - };
|
| - const unsigned char kV3FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x04,
|
| - 0x00, 0x00, 0x00, 0x1C,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 0x00, 0x00, 0x00, 0x02, // 1st Setting
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 0x00, 0x00, 0x00, 0x01, // 2nd (out of order) Setting
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 0x00, 0x00, 0x01, 0x03, // 3rd (unprocessed) Setting
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x12, 0x04,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x02, // 1st Setting
|
| - 0x00, 0x00, 0x00, 0x02,
|
| - 0x00, 0x01, // 2nd (out of order) Setting
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 0x00, 0x03, // 3rd (unprocessed) Setting
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - };
|
| -
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = false;
|
| - if (IsSpdy2()) {
|
| - visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
|
| - } else if (IsSpdy3()) {
|
| - visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
|
| - } else {
|
| - visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
|
| - }
|
| -
|
| - if (!IsSpdy4()) {
|
| - EXPECT_EQ(1, visitor.setting_count_);
|
| - EXPECT_EQ(1, visitor.error_count_);
|
| - } else {
|
| - // In SPDY 4+, settings are allowed in any order.
|
| - EXPECT_EQ(3, visitor.setting_count_);
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - }
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ProcessSettingsAckFrame) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| - SpdyFramer framer(spdy_version_);
|
| -
|
| - const unsigned char kFrameData[] = {
|
| - 0x00, 0x00, 0x00, 0x04, 0x01,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - };
|
| -
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = false;
|
| - visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
|
| -
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - EXPECT_EQ(0, visitor.setting_count_);
|
| - EXPECT_EQ(1, visitor.settings_ack_received_);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - const int kPaddingLen = 119;
|
| - const char data_payload[] = "hello";
|
| -
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - SpdyDataIR data_ir(1, StringPiece(data_payload, strlen(data_payload)));
|
| - data_ir.set_padding_len(kPaddingLen);
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
|
| - ASSERT_TRUE(frame.get() != NULL);
|
| -
|
| - int bytes_consumed = 0;
|
| -
|
| - // Send the frame header.
|
| - EXPECT_CALL(visitor, OnDataFrameHeader(1,
|
| - kPaddingLen + strlen(data_payload),
|
| - false));
|
| - CHECK_EQ(framer.GetDataFrameMinimumSize(),
|
| - framer.ProcessInput(frame->data(),
|
| - framer.GetDataFrameMinimumSize()));
|
| - CHECK_EQ(framer.state(), SpdyFramer::SPDY_READ_DATA_FRAME_PADDING_LENGTH);
|
| - CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
|
| - bytes_consumed += framer.GetDataFrameMinimumSize();
|
| -
|
| - // Send the padding length field.
|
| - CHECK_EQ(1u, framer.ProcessInput(frame->data() + bytes_consumed, 1));
|
| - CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
|
| - CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
|
| - bytes_consumed += 1;
|
| -
|
| - // Send the first two bytes of the data payload, i.e., "he".
|
| - EXPECT_CALL(visitor, OnStreamFrameData(1, _, 2, false));
|
| - CHECK_EQ(2u, framer.ProcessInput(frame->data() + bytes_consumed, 2));
|
| - CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
|
| - CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
|
| - bytes_consumed += 2;
|
| -
|
| - // Send the rest three bytes of the data payload, i.e., "llo".
|
| - EXPECT_CALL(visitor, OnStreamFrameData(1, _, 3, false));
|
| - CHECK_EQ(3u, framer.ProcessInput(frame->data() + bytes_consumed, 3));
|
| - CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
|
| - CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
|
| - bytes_consumed += 3;
|
| -
|
| - // Send the first 100 bytes of the padding payload.
|
| - EXPECT_CALL(visitor, OnStreamFrameData(1, NULL, 100, false));
|
| - CHECK_EQ(100u, framer.ProcessInput(frame->data() + bytes_consumed, 100));
|
| - CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
|
| - CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
|
| - bytes_consumed += 100;
|
| -
|
| - // Send rest of the padding payload.
|
| - EXPECT_CALL(visitor, OnStreamFrameData(1, NULL, 18, false));
|
| - CHECK_EQ(18u, framer.ProcessInput(frame->data() + bytes_consumed, 18));
|
| - CHECK_EQ(framer.state(), SpdyFramer::SPDY_RESET);
|
| - CHECK_EQ(framer.error_code(), SpdyFramer::SPDY_NO_ERROR);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ReadWindowUpdate) {
|
| - SpdyFramer framer(spdy_version_);
|
| - scoped_ptr<SpdyFrame> control_frame(
|
| - framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(control_frame->data()),
|
| - control_frame->size());
|
| - EXPECT_EQ(1u, visitor.last_window_update_stream_);
|
| - EXPECT_EQ(2u, visitor.last_window_update_delta_);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ReceiveCredentialFrame) {
|
| - if (!IsSpdy3()) {
|
| - return;
|
| - }
|
| - SpdyFramer framer(spdy_version_);
|
| - const unsigned char kV3FrameData[] = { // Also applies for V2.
|
| - 0x80, spdy_version_ch_, 0x00, 0x0A,
|
| - 0x00, 0x00, 0x00, 0x33,
|
| - 0x00, 0x03, 0x00, 0x00,
|
| - 0x00, 0x05, 'p', 'r',
|
| - 'o', 'o', 'f', 0x00,
|
| - 0x00, 0x00, 0x06, 'a',
|
| - ' ', 'c', 'e', 'r',
|
| - 't', 0x00, 0x00, 0x00,
|
| - 0x0C, 'a', 'n', 'o',
|
| - 't', 'h', 'e', 'r',
|
| - ' ', 'c', 'e', 'r',
|
| - 't', 0x00, 0x00, 0x00,
|
| - 0x0A, 'f', 'i', 'n',
|
| - 'a', 'l', ' ', 'c',
|
| - 'e', 'r', 't',
|
| - };
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = false;
|
| - visitor.SimulateInFramer(kV3FrameData, arraysize(kV3FrameData));
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ReadCredentialFrameFollowedByAnotherFrame) {
|
| - if (!IsSpdy3()) {
|
| - return;
|
| - }
|
| - SpdyFramer framer(spdy_version_);
|
| - const unsigned char kV3FrameData[] = { // Also applies for V2.
|
| - 0x80, spdy_version_ch_, 0x00, 0x0A,
|
| - 0x00, 0x00, 0x00, 0x33,
|
| - 0x00, 0x03, 0x00, 0x00,
|
| - 0x00, 0x05, 'p', 'r',
|
| - 'o', 'o', 'f', 0x00,
|
| - 0x00, 0x00, 0x06, 'a',
|
| - ' ', 'c', 'e', 'r',
|
| - 't', 0x00, 0x00, 0x00,
|
| - 0x0C, 'a', 'n', 'o',
|
| - 't', 'h', 'e', 'r',
|
| - ' ', 'c', 'e', 'r',
|
| - 't', 0x00, 0x00, 0x00,
|
| - 0x0A, 'f', 'i', 'n',
|
| - 'a', 'l', ' ', 'c',
|
| - 'e', 'r', 't',
|
| - };
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = false;
|
| - string multiple_frame_data(reinterpret_cast<const char*>(kV3FrameData),
|
| - arraysize(kV3FrameData));
|
| - scoped_ptr<SpdyFrame> control_frame(
|
| - framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
|
| - multiple_frame_data.append(string(control_frame->data(),
|
| - control_frame->size()));
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned const char*>(multiple_frame_data.data()),
|
| - multiple_frame_data.length());
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - EXPECT_EQ(1u, visitor.last_window_update_stream_);
|
| - EXPECT_EQ(2u, visitor.last_window_update_delta_);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ReadCompressedPushPromise) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - SpdyFramer framer(spdy_version_);
|
| - SpdyPushPromiseIR push_promise(42, 57);
|
| - push_promise.SetHeader("foo", "bar");
|
| - push_promise.SetHeader("bar", "foofoo");
|
| - SpdyHeaderBlock headers = push_promise.name_value_block();
|
| - scoped_ptr<SpdySerializedFrame> frame(
|
| - framer.SerializePushPromise(push_promise));
|
| - EXPECT_TRUE(frame.get() != NULL);
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = true;
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(frame->data()),
|
| - frame->size());
|
| - EXPECT_EQ(42u, visitor.last_push_promise_stream_);
|
| - EXPECT_EQ(57u, visitor.last_push_promise_promised_stream_);
|
| - EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ReadHeadersWithContinuation) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - const unsigned char kInput[] = {
|
| - 0x00, 0x00, 0x14, 0x01, 0x08, // HEADERS: PADDED
|
| - 0x00, 0x00, 0x00, 0x01, // Stream 1
|
| - 0x03, // Padding of 3.
|
| - 0x00, 0x06, 0x63, 0x6f,
|
| - 0x6f, 0x6b, 0x69, 0x65,
|
| - 0x07, 0x66, 0x6f, 0x6f,
|
| - 0x3d, 0x62, 0x61, 0x72,
|
| - 0x00, 0x00, 0x00,
|
| -
|
| - 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
|
| - 0x00, 0x00, 0x00, 0x01, // Stream 1
|
| - 0x00, 0x06, 0x63, 0x6f,
|
| - 0x6f, 0x6b, 0x69, 0x65,
|
| - 0x08, 0x62, 0x61, 0x7a,
|
| - 0x3d, 0x62, 0x69, 0x6e,
|
| - 0x67, 0x00, 0x06, 0x63,
|
| -
|
| - 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
|
| - 0x00, 0x00, 0x00, 0x01, // Stream 1
|
| - 0x6f, 0x6f, 0x6b, 0x69,
|
| - 0x65, 0x00, 0x00, 0x04,
|
| - 0x6e, 0x61, 0x6d, 0x65,
|
| - 0x05, 0x76, 0x61, 0x6c,
|
| - 0x75, 0x65,
|
| - };
|
| -
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.SimulateInFramer(kInput, sizeof(kInput));
|
| -
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - EXPECT_EQ(1, visitor.headers_frame_count_);
|
| - EXPECT_EQ(2, visitor.continuation_count_);
|
| - EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
|
| - EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
|
| -
|
| - EXPECT_THAT(visitor.headers_,
|
| - testing::ElementsAre(
|
| - testing::Pair("cookie", "foo=bar; baz=bing; "),
|
| - testing::Pair("name", "value")));
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ReadHeadersWithContinuationAndFin) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - const unsigned char kInput[] = {
|
| - 0x00, 0x00, 0x10, 0x01, 0x01, // HEADERS: FIN
|
| - 0x00, 0x00, 0x00, 0x01, // Stream 1
|
| - 0x00, 0x06, 0x63, 0x6f,
|
| - 0x6f, 0x6b, 0x69, 0x65,
|
| - 0x07, 0x66, 0x6f, 0x6f,
|
| - 0x3d, 0x62, 0x61, 0x72,
|
| -
|
| - 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
|
| - 0x00, 0x00, 0x00, 0x01, // Stream 1
|
| - 0x00, 0x06, 0x63, 0x6f,
|
| - 0x6f, 0x6b, 0x69, 0x65,
|
| - 0x08, 0x62, 0x61, 0x7a,
|
| - 0x3d, 0x62, 0x69, 0x6e,
|
| - 0x67, 0x00, 0x06, 0x63,
|
| -
|
| - 0x00, 0x00, 0x12, 0x09, 0x04, // CONTINUATION: END_HEADERS
|
| - 0x00, 0x00, 0x00, 0x01, // Stream 1
|
| - 0x6f, 0x6f, 0x6b, 0x69,
|
| - 0x65, 0x00, 0x00, 0x04,
|
| - 0x6e, 0x61, 0x6d, 0x65,
|
| - 0x05, 0x76, 0x61, 0x6c,
|
| - 0x75, 0x65,
|
| - };
|
| -
|
| - SpdyFramer framer(spdy_version_);
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.SimulateInFramer(kInput, sizeof(kInput));
|
| -
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - EXPECT_EQ(1, visitor.headers_frame_count_);
|
| - EXPECT_EQ(2, visitor.continuation_count_);
|
| - EXPECT_EQ(1, visitor.fin_flag_count_);
|
| - EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
|
| - EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
|
| -
|
| - EXPECT_THAT(visitor.headers_,
|
| - testing::ElementsAre(
|
| - testing::Pair("cookie", "foo=bar; baz=bing; "),
|
| - testing::Pair("name", "value")));
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - const unsigned char kInput[] = {
|
| - 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
|
| - 0x08, 0x00, 0x00, 0x00, // PADDED
|
| - 0x01, 0x02, 0x00, 0x00, // Stream 1, Pad length field
|
| - 0x00, 0x2A, 0x00, 0x06, // Promised stream 42
|
| - 0x63, 0x6f, 0x6f, 0x6b,
|
| - 0x69, 0x65, 0x07, 0x66,
|
| - 0x6f, 0x6f, 0x3d, 0x62,
|
| - 0x61, 0x72, 0x00, 0x00,
|
| -
|
| - 0x00, 0x00, 0x14, 0x09, // CONTINUATION
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x01, 0x00, 0x06, 0x63, // Stream 1
|
| - 0x6f, 0x6f, 0x6b, 0x69,
|
| - 0x65, 0x08, 0x62, 0x61,
|
| - 0x7a, 0x3d, 0x62, 0x69,
|
| - 0x6e, 0x67, 0x00, 0x06,
|
| - 0x63,
|
| -
|
| - 0x00, 0x00, 0x12, 0x09, // CONTINUATION
|
| - 0x04, 0x00, 0x00, 0x00, // END_HEADERS
|
| - 0x01, 0x6f, 0x6f, 0x6b, // Stream 1
|
| - 0x69, 0x65, 0x00, 0x00,
|
| - 0x04, 0x6e, 0x61, 0x6d,
|
| - 0x65, 0x05, 0x76, 0x61,
|
| - 0x6c, 0x75, 0x65,
|
| - };
|
| -
|
| - SpdyFramer framer(spdy_version_);
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.SimulateInFramer(kInput, sizeof(kInput));
|
| -
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - EXPECT_EQ(1u, visitor.last_push_promise_stream_);
|
| - EXPECT_EQ(42u, visitor.last_push_promise_promised_stream_);
|
| - EXPECT_EQ(2, visitor.continuation_count_);
|
| - EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
|
| - EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
|
| -
|
| - EXPECT_THAT(visitor.headers_,
|
| - testing::ElementsAre(
|
| - testing::Pair("cookie", "foo=bar; baz=bing; "),
|
| - testing::Pair("name", "value")));
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ReadContinuationWithWrongStreamId) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - const unsigned char kInput[] = {
|
| - 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
|
| - 0x00, 0x00, 0x00, 0x01, // Stream 1
|
| - 0x00, 0x06, 0x63, 0x6f,
|
| - 0x6f, 0x6b, 0x69, 0x65,
|
| - 0x07, 0x66, 0x6f, 0x6f,
|
| - 0x3d, 0x62, 0x61, 0x72,
|
| -
|
| - 0x00, 0x00, 0x14, 0x09, 0x00, // CONTINUATION
|
| - 0x00, 0x00, 0x00, 0x02, // Stream 2
|
| - 0x00, 0x06, 0x63, 0x6f,
|
| - 0x6f, 0x6b, 0x69, 0x65,
|
| - 0x08, 0x62, 0x61, 0x7a,
|
| - 0x3d, 0x62, 0x69, 0x6e,
|
| - 0x67, 0x00, 0x06, 0x63,
|
| - };
|
| -
|
| - SpdyFramer framer(spdy_version_);
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| - visitor.SimulateInFramer(kInput, sizeof(kInput));
|
| -
|
| - EXPECT_EQ(1, visitor.error_count_);
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
|
| - visitor.framer_.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - EXPECT_EQ(1, visitor.headers_frame_count_);
|
| - EXPECT_EQ(0, visitor.continuation_count_);
|
| - EXPECT_EQ(0u, visitor.header_buffer_length_);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ReadContinuationOutOfOrder) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - const unsigned char kInput[] = {
|
| - 0x00, 0x00, 0x18, 0x09, 0x00, // CONTINUATION
|
| - 0x00, 0x00, 0x00, 0x01, // Stream 1
|
| - 0x00, 0x06, 0x63, 0x6f,
|
| - 0x6f, 0x6b, 0x69, 0x65,
|
| - 0x07, 0x66, 0x6f, 0x6f,
|
| - 0x3d, 0x62, 0x61, 0x72,
|
| - };
|
| -
|
| - SpdyFramer framer(spdy_version_);
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| - visitor.SimulateInFramer(kInput, sizeof(kInput));
|
| -
|
| - EXPECT_EQ(1, visitor.error_count_);
|
| - EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
|
| - visitor.framer_.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - EXPECT_EQ(0, visitor.continuation_count_);
|
| - EXPECT_EQ(0u, visitor.header_buffer_length_);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ExpectContinuationReceiveData) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - const unsigned char kInput[] = {
|
| - 0x00, 0x00, 0x10, 0x01, 0x00, // HEADERS
|
| - 0x00, 0x00, 0x00, 0x01, // Stream 1
|
| - 0x00, 0x06, 0x63, 0x6f,
|
| - 0x6f, 0x6b, 0x69, 0x65,
|
| - 0x07, 0x66, 0x6f, 0x6f,
|
| - 0x3d, 0x62, 0x61, 0x72,
|
| -
|
| - 0x00, 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
|
| - 0x00, 0x00, 0x00, 0x04,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| - };
|
| -
|
| - SpdyFramer framer(spdy_version_);
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| - visitor.SimulateInFramer(kInput, sizeof(kInput));
|
| -
|
| - EXPECT_EQ(1, visitor.error_count_);
|
| - EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
|
| - visitor.framer_.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - EXPECT_EQ(1, visitor.headers_frame_count_);
|
| - EXPECT_EQ(0, visitor.continuation_count_);
|
| - EXPECT_EQ(0u, visitor.header_buffer_length_);
|
| - EXPECT_EQ(0, visitor.data_frame_count_);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ExpectContinuationReceiveControlFrame) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - const unsigned char kInput[] = {
|
| - 0x00, 0x00, 0x18, 0x01, 0x00, // HEADERS
|
| - 0x00, 0x00, 0x00, 0x01, // Stream 1
|
| - 0x00, 0x06, 0x63, 0x6f,
|
| - 0x6f, 0x6b, 0x69, 0x65,
|
| - 0x07, 0x66, 0x6f, 0x6f,
|
| - 0x3d, 0x62, 0x61, 0x72,
|
| -
|
| - 0x00, 0x00, 0x1c, 0x08, 0x00, // HEADERS
|
| - 0x00, 0x00, 0x00, 0x01, // Stream 1
|
| - 0x00, 0x06, 0x63, 0x6f, // (Note this is a valid continued encoding).
|
| - 0x6f, 0x6b, 0x69, 0x65,
|
| - 0x08, 0x62, 0x61, 0x7a,
|
| - 0x3d, 0x62, 0x69, 0x6e,
|
| - 0x67, 0x00, 0x06, 0x63,
|
| - };
|
| -
|
| - SpdyFramer framer(spdy_version_);
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| - visitor.SimulateInFramer(kInput, sizeof(kInput));
|
| -
|
| - EXPECT_EQ(1, visitor.error_count_);
|
| - EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
|
| - visitor.framer_.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - EXPECT_EQ(1, visitor.headers_frame_count_);
|
| - EXPECT_EQ(0, visitor.continuation_count_);
|
| - EXPECT_EQ(0u, visitor.header_buffer_length_);
|
| - EXPECT_EQ(0, visitor.data_frame_count_);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, EndSegmentOnDataFrame) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| - const unsigned char kInput[] = {
|
| - 0x00, 0x00, 0x0c, 0x00, 0x02, // DATA: END_SEGMENT
|
| - 0x00, 0x00, 0x00, 0x01, // Stream 1
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| - };
|
| -
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.SimulateInFramer(kInput, sizeof(kInput));
|
| -
|
| - // TODO(jgraettinger): Verify END_SEGMENT when support is added.
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - EXPECT_EQ(12, visitor.data_bytes_);
|
| - EXPECT_EQ(0, visitor.fin_frame_count_);
|
| - EXPECT_EQ(0, visitor.fin_flag_count_);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, EndSegmentOnHeadersFrame) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| - const unsigned char kInput[] = {
|
| - 0x00, 0x00, 0x10, 0x01, 0x06, // HEADERS: END_SEGMENT | END_HEADERS
|
| - 0x00, 0x00, 0x00, 0x01, // Stream 1
|
| - 0x00, 0x06, 0x63, 0x6f,
|
| - 0x6f, 0x6b, 0x69, 0x65,
|
| - 0x07, 0x66, 0x6f, 0x6f,
|
| - 0x3d, 0x62, 0x61, 0x72,
|
| - };
|
| -
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.SimulateInFramer(kInput, sizeof(kInput));
|
| -
|
| - // TODO(jgraettinger): Verify END_SEGMENT when support is added.
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - EXPECT_EQ(1, visitor.headers_frame_count_);
|
| - EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
|
| -
|
| - EXPECT_THAT(visitor.headers_,
|
| - testing::ElementsAre(testing::Pair("cookie", "foo=bar")));
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ReadGarbage) {
|
| - SpdyFramer framer(spdy_version_);
|
| - unsigned char garbage_frame[256];
|
| - memset(garbage_frame, ~0, sizeof(garbage_frame));
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = false;
|
| - visitor.SimulateInFramer(garbage_frame, sizeof(garbage_frame));
|
| - EXPECT_EQ(1, visitor.error_count_);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ReadUnknownExtensionFrame) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| - SpdyFramer framer(spdy_version_);
|
| -
|
| - // The unrecognized frame type should still have a valid length.
|
| - const unsigned char unknown_frame[] = {
|
| - 0x00, 0x00, 0x08, 0xff, 0xff,
|
| - 0xff, 0xff, 0xff, 0xff,
|
| - 0xff, 0xff, 0xff, 0xff,
|
| - 0xff, 0xff, 0xff, 0xff,
|
| - };
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| -
|
| - // Simulate the case where the stream id validation checks out.
|
| - visitor.on_unknown_frame_result_ = true;
|
| - visitor.use_compression_ = false;
|
| - visitor.SimulateInFramer(unknown_frame, arraysize(unknown_frame));
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| -
|
| - // Follow it up with a valid control frame to make sure we handle
|
| - // subsequent frames correctly.
|
| - SpdySettingsIR settings_ir;
|
| - settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1),
|
| - false, // persist
|
| - false, // persisted
|
| - 10);
|
| - scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(control_frame->data()),
|
| - control_frame->size());
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - EXPECT_EQ(1u, static_cast<unsigned>(visitor.setting_count_));
|
| - EXPECT_EQ(1u, static_cast<unsigned>(visitor.settings_ack_sent_));
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ReadGarbageWithValidLength) {
|
| - if (!IsSpdy4()) {
|
| - return;
|
| - }
|
| - SpdyFramer framer(spdy_version_);
|
| - const unsigned char kFrameData[] = {
|
| - 0x00, 0x00, 0x08, 0xff, 0xff,
|
| - 0xff, 0xff, 0xff, 0xff,
|
| - 0xff, 0xff, 0xff, 0xff,
|
| - 0xff, 0xff, 0xff, 0xff,
|
| - };
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = false;
|
| - visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
|
| - EXPECT_EQ(1, visitor.error_count_);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ReadGarbageWithValidVersion) {
|
| - if (IsSpdy4()) {
|
| - // Not valid for SPDY 4 since there is no version field.
|
| - return;
|
| - }
|
| - SpdyFramer framer(spdy_version_);
|
| - const unsigned char kFrameData[] = {
|
| - 0x80, spdy_version_ch_, 0xff, 0xff,
|
| - 0xff, 0xff, 0xff, 0xff,
|
| - };
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = false;
|
| - visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
|
| - EXPECT_EQ(1, visitor.error_count_);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ReadGarbageHPACKEncoding) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| - const unsigned char kInput[] = {
|
| - 0x00, 0x12, 0x01, 0x04, // HEADER: END_HEADERS
|
| - 0x00, 0x00, 0x00, 0x01, // Stream 1
|
| - 0xef, 0xef, 0xff, 0xff,
|
| - 0xff, 0xff, 0xff, 0xff,
|
| - 0xff, 0xff, 0xff, 0xff,
|
| - 0xff, 0xff, 0xff, 0xff,
|
| - 0xff, 0xff,
|
| - };
|
| -
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.SimulateInFramer(kInput, arraysize(kInput));
|
| - EXPECT_EQ(1, visitor.error_count_);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, SizesTest) {
|
| - SpdyFramer framer(spdy_version_);
|
| - if (IsSpdy4()) {
|
| - EXPECT_EQ(9u, framer.GetDataFrameMinimumSize());
|
| - EXPECT_EQ(9u, framer.GetControlFrameHeaderSize());
|
| - EXPECT_EQ(14u, framer.GetSynStreamMinimumSize());
|
| - EXPECT_EQ(9u, framer.GetSynReplyMinimumSize());
|
| - EXPECT_EQ(13u, framer.GetRstStreamMinimumSize());
|
| - EXPECT_EQ(9u, framer.GetSettingsMinimumSize());
|
| - EXPECT_EQ(17u, framer.GetPingSize());
|
| - EXPECT_EQ(17u, framer.GetGoAwayMinimumSize());
|
| - EXPECT_EQ(9u, framer.GetHeadersMinimumSize());
|
| - EXPECT_EQ(13u, framer.GetWindowUpdateSize());
|
| - EXPECT_EQ(9u, framer.GetBlockedSize());
|
| - EXPECT_EQ(13u, framer.GetPushPromiseMinimumSize());
|
| - EXPECT_EQ(18u, framer.GetAltSvcMinimumSize());
|
| - EXPECT_EQ(9u, framer.GetFrameMinimumSize());
|
| - EXPECT_EQ(16393u, framer.GetFrameMaximumSize());
|
| - EXPECT_EQ(16384u, framer.GetDataFrameMaximumPayload());
|
| - } else {
|
| - EXPECT_EQ(8u, framer.GetDataFrameMinimumSize());
|
| - EXPECT_EQ(8u, framer.GetControlFrameHeaderSize());
|
| - EXPECT_EQ(18u, framer.GetSynStreamMinimumSize());
|
| - EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetSynReplyMinimumSize());
|
| - EXPECT_EQ(16u, framer.GetRstStreamMinimumSize());
|
| - EXPECT_EQ(12u, framer.GetSettingsMinimumSize());
|
| - EXPECT_EQ(12u, framer.GetPingSize());
|
| - EXPECT_EQ(IsSpdy2() ? 12u : 16u, framer.GetGoAwayMinimumSize());
|
| - EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetHeadersMinimumSize());
|
| - EXPECT_EQ(16u, framer.GetWindowUpdateSize());
|
| - EXPECT_EQ(8u, framer.GetFrameMinimumSize());
|
| - EXPECT_EQ(16777223u, framer.GetFrameMaximumSize());
|
| - EXPECT_EQ(16777215u, framer.GetDataFrameMaximumPayload());
|
| - }
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, StateToStringTest) {
|
| - EXPECT_STREQ("ERROR",
|
| - SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR));
|
| - EXPECT_STREQ("AUTO_RESET",
|
| - SpdyFramer::StateToString(SpdyFramer::SPDY_AUTO_RESET));
|
| - EXPECT_STREQ("RESET",
|
| - SpdyFramer::StateToString(SpdyFramer::SPDY_RESET));
|
| - EXPECT_STREQ("READING_COMMON_HEADER",
|
| - SpdyFramer::StateToString(
|
| - SpdyFramer::SPDY_READING_COMMON_HEADER));
|
| - EXPECT_STREQ("CONTROL_FRAME_PAYLOAD",
|
| - SpdyFramer::StateToString(
|
| - SpdyFramer::SPDY_CONTROL_FRAME_PAYLOAD));
|
| - EXPECT_STREQ("IGNORE_REMAINING_PAYLOAD",
|
| - SpdyFramer::StateToString(
|
| - SpdyFramer::SPDY_IGNORE_REMAINING_PAYLOAD));
|
| - EXPECT_STREQ("FORWARD_STREAM_FRAME",
|
| - SpdyFramer::StateToString(
|
| - SpdyFramer::SPDY_FORWARD_STREAM_FRAME));
|
| - EXPECT_STREQ("SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK",
|
| - SpdyFramer::StateToString(
|
| - SpdyFramer::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK));
|
| - EXPECT_STREQ("SPDY_CONTROL_FRAME_HEADER_BLOCK",
|
| - SpdyFramer::StateToString(
|
| - SpdyFramer::SPDY_CONTROL_FRAME_HEADER_BLOCK));
|
| - EXPECT_STREQ("SPDY_SETTINGS_FRAME_PAYLOAD",
|
| - SpdyFramer::StateToString(
|
| - SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD));
|
| - EXPECT_STREQ("SPDY_ALTSVC_FRAME_PAYLOAD",
|
| - SpdyFramer::StateToString(
|
| - SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD));
|
| - EXPECT_STREQ("UNKNOWN_STATE",
|
| - SpdyFramer::StateToString(
|
| - SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD + 1));
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ErrorCodeToStringTest) {
|
| - EXPECT_STREQ("NO_ERROR",
|
| - SpdyFramer::ErrorCodeToString(SpdyFramer::SPDY_NO_ERROR));
|
| - EXPECT_STREQ("INVALID_CONTROL_FRAME",
|
| - SpdyFramer::ErrorCodeToString(
|
| - SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
|
| - EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
|
| - SpdyFramer::ErrorCodeToString(
|
| - SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
|
| - EXPECT_STREQ("ZLIB_INIT_FAILURE",
|
| - SpdyFramer::ErrorCodeToString(
|
| - SpdyFramer::SPDY_ZLIB_INIT_FAILURE));
|
| - EXPECT_STREQ("UNSUPPORTED_VERSION",
|
| - SpdyFramer::ErrorCodeToString(
|
| - SpdyFramer::SPDY_UNSUPPORTED_VERSION));
|
| - EXPECT_STREQ("DECOMPRESS_FAILURE",
|
| - SpdyFramer::ErrorCodeToString(
|
| - SpdyFramer::SPDY_DECOMPRESS_FAILURE));
|
| - EXPECT_STREQ("COMPRESS_FAILURE",
|
| - SpdyFramer::ErrorCodeToString(
|
| - SpdyFramer::SPDY_COMPRESS_FAILURE));
|
| - EXPECT_STREQ("SPDY_INVALID_DATA_FRAME_FLAGS",
|
| - SpdyFramer::ErrorCodeToString(
|
| - SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
|
| - EXPECT_STREQ("SPDY_INVALID_CONTROL_FRAME_FLAGS",
|
| - SpdyFramer::ErrorCodeToString(
|
| - SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS));
|
| - EXPECT_STREQ("UNKNOWN_ERROR",
|
| - SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR));
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, StatusCodeToStringTest) {
|
| - EXPECT_STREQ("INVALID",
|
| - SpdyFramer::StatusCodeToString(RST_STREAM_INVALID));
|
| - EXPECT_STREQ("PROTOCOL_ERROR",
|
| - SpdyFramer::StatusCodeToString(RST_STREAM_PROTOCOL_ERROR));
|
| - EXPECT_STREQ("INVALID_STREAM",
|
| - SpdyFramer::StatusCodeToString(RST_STREAM_INVALID_STREAM));
|
| - EXPECT_STREQ("REFUSED_STREAM",
|
| - SpdyFramer::StatusCodeToString(RST_STREAM_REFUSED_STREAM));
|
| - EXPECT_STREQ("UNSUPPORTED_VERSION",
|
| - SpdyFramer::StatusCodeToString(RST_STREAM_UNSUPPORTED_VERSION));
|
| - EXPECT_STREQ("CANCEL",
|
| - SpdyFramer::StatusCodeToString(RST_STREAM_CANCEL));
|
| - EXPECT_STREQ("INTERNAL_ERROR",
|
| - SpdyFramer::StatusCodeToString(RST_STREAM_INTERNAL_ERROR));
|
| - EXPECT_STREQ("FLOW_CONTROL_ERROR",
|
| - SpdyFramer::StatusCodeToString(RST_STREAM_FLOW_CONTROL_ERROR));
|
| - EXPECT_STREQ("UNKNOWN_STATUS",
|
| - SpdyFramer::StatusCodeToString(-1));
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, FrameTypeToStringTest) {
|
| - EXPECT_STREQ("DATA",
|
| - SpdyFramer::FrameTypeToString(DATA));
|
| - EXPECT_STREQ("SYN_STREAM",
|
| - SpdyFramer::FrameTypeToString(SYN_STREAM));
|
| - EXPECT_STREQ("SYN_REPLY",
|
| - SpdyFramer::FrameTypeToString(SYN_REPLY));
|
| - EXPECT_STREQ("RST_STREAM",
|
| - SpdyFramer::FrameTypeToString(RST_STREAM));
|
| - EXPECT_STREQ("SETTINGS",
|
| - SpdyFramer::FrameTypeToString(SETTINGS));
|
| - EXPECT_STREQ("PING",
|
| - SpdyFramer::FrameTypeToString(PING));
|
| - EXPECT_STREQ("GOAWAY",
|
| - SpdyFramer::FrameTypeToString(GOAWAY));
|
| - EXPECT_STREQ("HEADERS",
|
| - SpdyFramer::FrameTypeToString(HEADERS));
|
| - EXPECT_STREQ("WINDOW_UPDATE",
|
| - SpdyFramer::FrameTypeToString(WINDOW_UPDATE));
|
| - EXPECT_STREQ("PUSH_PROMISE",
|
| - SpdyFramer::FrameTypeToString(PUSH_PROMISE));
|
| - EXPECT_STREQ("CREDENTIAL",
|
| - SpdyFramer::FrameTypeToString(CREDENTIAL));
|
| - EXPECT_STREQ("CONTINUATION",
|
| - SpdyFramer::FrameTypeToString(CONTINUATION));
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, CatchProbableHttpResponse) {
|
| - if (IsSpdy4()) {
|
| - // TODO(hkhalil): catch probable HTTP response in SPDY 4?
|
| - return;
|
| - }
|
| - {
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - EXPECT_CALL(visitor, OnError(_));
|
| - framer.ProcessInput("HTTP/1.1", 8);
|
| - EXPECT_TRUE(framer.probable_http_response());
|
| - EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - }
|
| - {
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - EXPECT_CALL(visitor, OnError(_));
|
| - framer.ProcessInput("HTTP/1.0", 8);
|
| - EXPECT_TRUE(framer.probable_http_response());
|
| - EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - }
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) {
|
| - if (spdy_version_ > SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - uint8 flags = 0;
|
| - do {
|
| - SCOPED_TRACE(testing::Message() << "Flags " << flags);
|
| -
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - SpdyDataIR data_ir(1, StringPiece("hello", 5));
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
|
| - SetFrameFlags(frame.get(), flags, spdy_version_);
|
| -
|
| - if (flags & ~DATA_FLAG_FIN) {
|
| - EXPECT_CALL(visitor, OnError(_));
|
| - } else {
|
| - EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
|
| - EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
|
| - if (flags & DATA_FLAG_FIN) {
|
| - EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
|
| - }
|
| - }
|
| -
|
| - framer.ProcessInput(frame->data(), frame->size());
|
| - if (flags & ~DATA_FLAG_FIN) {
|
| - EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS,
|
| - framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - } else {
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - }
|
| - } while (++flags != 0);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, DataFrameFlagsV4) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - uint8 valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT |
|
| - DATA_FLAG_PADDED;
|
| -
|
| - uint8 flags = 0;
|
| - do {
|
| - SCOPED_TRACE(testing::Message() << "Flags " << flags);
|
| -
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - SpdyDataIR data_ir(1, StringPiece("hello", 5));
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir));
|
| - SetFrameFlags(frame.get(), flags, spdy_version_);
|
| -
|
| - if (flags & ~valid_data_flags) {
|
| - EXPECT_CALL(visitor, OnError(_));
|
| - } else {
|
| - EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
|
| - if (flags & DATA_FLAG_PADDED) {
|
| - // Expect Error since we don't set padded in payload.
|
| - EXPECT_CALL(visitor, OnError(_));
|
| - } else {
|
| - EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
|
| - if (flags & DATA_FLAG_FIN) {
|
| - EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
|
| - }
|
| - }
|
| - }
|
| -
|
| - framer.ProcessInput(frame->data(), frame->size());
|
| - if ((flags & ~valid_data_flags) || (flags & DATA_FLAG_PADDED)) {
|
| - EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS,
|
| - framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - } else {
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - }
|
| - } while (++flags != 0);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, SynStreamFrameFlags) {
|
| - if (!IsSpdy2() && !IsSpdy3()) {
|
| - // SYN_STREAM not supported in SPDY>3
|
| - return;
|
| - }
|
| - uint8 flags = 0;
|
| - do {
|
| - SCOPED_TRACE(testing::Message() << "Flags " << flags);
|
| -
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - testing::StrictMock<test::MockDebugVisitor> debug_visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| - framer.set_debug_visitor(&debug_visitor);
|
| -
|
| - EXPECT_CALL(debug_visitor, OnSendCompressedFrame(8, SYN_STREAM, _, _));
|
| -
|
| - SpdySynStreamIR syn_stream(8);
|
| - syn_stream.set_associated_to_stream_id(3);
|
| - syn_stream.set_priority(1);
|
| - syn_stream.SetHeader("foo", "bar");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
|
| - SetFrameFlags(frame.get(), flags, spdy_version_);
|
| -
|
| - if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
|
| - EXPECT_CALL(visitor, OnError(_));
|
| - } else {
|
| - EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(8, SYN_STREAM, _));
|
| - EXPECT_CALL(visitor, OnSynStream(8, 3, 1, flags & CONTROL_FLAG_FIN,
|
| - flags & CONTROL_FLAG_UNIDIRECTIONAL));
|
| - EXPECT_CALL(visitor, OnControlFrameHeaderData(8, _, _))
|
| - .WillRepeatedly(testing::Return(true));
|
| - if (flags & DATA_FLAG_FIN) {
|
| - EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
|
| - } else {
|
| - // Do not close the stream if we are expecting a CONTINUATION frame.
|
| - EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
|
| - }
|
| - }
|
| -
|
| - framer.ProcessInput(frame->data(), frame->size());
|
| - if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
|
| - EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
|
| - framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - } else {
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - }
|
| - } while (++flags != 0);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, SynReplyFrameFlags) {
|
| - if (!IsSpdy2() && !IsSpdy3()) {
|
| - // SYN_REPLY not supported in SPDY>3
|
| - return;
|
| - }
|
| - uint8 flags = 0;
|
| - do {
|
| - SCOPED_TRACE(testing::Message() << "Flags " << flags);
|
| -
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - SpdySynReplyIR syn_reply(37);
|
| - syn_reply.SetHeader("foo", "bar");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply));
|
| - SetFrameFlags(frame.get(), flags, spdy_version_);
|
| -
|
| - if (flags & ~CONTROL_FLAG_FIN) {
|
| - EXPECT_CALL(visitor, OnError(_));
|
| - } else {
|
| - EXPECT_CALL(visitor, OnSynReply(37, flags & CONTROL_FLAG_FIN));
|
| - EXPECT_CALL(visitor, OnControlFrameHeaderData(37, _, _))
|
| - .WillRepeatedly(testing::Return(true));
|
| - if (flags & DATA_FLAG_FIN) {
|
| - EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
|
| - }
|
| - }
|
| -
|
| - framer.ProcessInput(frame->data(), frame->size());
|
| - if (flags & ~CONTROL_FLAG_FIN) {
|
| - EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
|
| - framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - } else {
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - }
|
| - } while (++flags != 0);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, RstStreamFrameFlags) {
|
| - uint8 flags = 0;
|
| - do {
|
| - SCOPED_TRACE(testing::Message() << "Flags " << flags);
|
| -
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - SpdyRstStreamIR rst_stream(13, RST_STREAM_CANCEL, "");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeRstStream(rst_stream));
|
| - SetFrameFlags(frame.get(), flags, spdy_version_);
|
| -
|
| - if (flags != 0) {
|
| - EXPECT_CALL(visitor, OnError(_));
|
| - } else {
|
| - EXPECT_CALL(visitor, OnRstStream(13, RST_STREAM_CANCEL));
|
| - }
|
| -
|
| - framer.ProcessInput(frame->data(), frame->size());
|
| - if (flags != 0) {
|
| - EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
|
| - framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - } else {
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - }
|
| - } while (++flags != 0);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, SettingsFrameFlagsOldFormat) {
|
| - if (spdy_version_ > SPDY3) { return; }
|
| - uint8 flags = 0;
|
| - do {
|
| - SCOPED_TRACE(testing::Message() << "Flags " << flags);
|
| -
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - SpdySettingsIR settings_ir;
|
| - settings_ir.AddSetting(SETTINGS_UPLOAD_BANDWIDTH,
|
| - false,
|
| - false,
|
| - 54321);
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
|
| - SetFrameFlags(frame.get(), flags, spdy_version_);
|
| -
|
| - if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
|
| - EXPECT_CALL(visitor, OnError(_));
|
| - } else {
|
| - EXPECT_CALL(visitor, OnSettings(
|
| - flags & SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS));
|
| - EXPECT_CALL(visitor, OnSetting(SETTINGS_UPLOAD_BANDWIDTH,
|
| - SETTINGS_FLAG_NONE, 54321));
|
| - EXPECT_CALL(visitor, OnSettingsEnd());
|
| - }
|
| -
|
| - framer.ProcessInput(frame->data(), frame->size());
|
| - if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
|
| - EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
|
| - framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - } else {
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - }
|
| - } while (++flags != 0);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, SettingsFrameFlags) {
|
| - if (spdy_version_ <= SPDY3) { return; }
|
| - uint8 flags = 0;
|
| - do {
|
| - SCOPED_TRACE(testing::Message() << "Flags " << flags);
|
| -
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - SpdySettingsIR settings_ir;
|
| - settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 0, 16);
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeSettings(settings_ir));
|
| - SetFrameFlags(frame.get(), flags, spdy_version_);
|
| -
|
| - if (flags != 0) {
|
| - EXPECT_CALL(visitor, OnError(_));
|
| - } else {
|
| - EXPECT_CALL(visitor, OnSettings(flags & SETTINGS_FLAG_ACK));
|
| - EXPECT_CALL(visitor, OnSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0, 16));
|
| - EXPECT_CALL(visitor, OnSettingsEnd());
|
| - }
|
| -
|
| - framer.ProcessInput(frame->data(), frame->size());
|
| - if (flags & ~SETTINGS_FLAG_ACK) {
|
| - EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
|
| - framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - } else if (flags & SETTINGS_FLAG_ACK) {
|
| - // The frame is invalid because ACK frames should have no payload.
|
| - EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
|
| - framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - } else {
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - }
|
| - } while (++flags != 0);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, GoawayFrameFlags) {
|
| - uint8 flags = 0;
|
| - do {
|
| - SCOPED_TRACE(testing::Message() << "Flags " << flags);
|
| -
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - SpdyGoAwayIR goaway_ir(97, GOAWAY_OK, "test");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeGoAway(goaway_ir));
|
| - SetFrameFlags(frame.get(), flags, spdy_version_);
|
| -
|
| - if (flags != 0) {
|
| - EXPECT_CALL(visitor, OnError(_));
|
| - } else {
|
| - EXPECT_CALL(visitor, OnGoAway(97, GOAWAY_OK));
|
| - }
|
| -
|
| - framer.ProcessInput(frame->data(), frame->size());
|
| - if (flags != 0) {
|
| - EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
|
| - framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - } else {
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - }
|
| - } while (++flags != 0);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, HeadersFrameFlags) {
|
| - uint8 flags = 0;
|
| - do {
|
| - SCOPED_TRACE(testing::Message() << "Flags " << flags);
|
| -
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - SpdyHeadersIR headers_ir(57);
|
| - if (IsSpdy4() && (flags & HEADERS_FLAG_PRIORITY)) {
|
| - headers_ir.set_priority(3);
|
| - headers_ir.set_has_priority(true);
|
| - }
|
| - headers_ir.SetHeader("foo", "bar");
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir));
|
| - uint8 set_flags = flags;
|
| - if (IsSpdy4()) {
|
| - // TODO(jgraettinger): Add padding to SpdyHeadersIR,
|
| - // and implement framing.
|
| - set_flags &= ~HEADERS_FLAG_PADDED;
|
| - }
|
| - SetFrameFlags(frame.get(), set_flags, spdy_version_);
|
| -
|
| - if (!IsSpdy4() && flags & ~CONTROL_FLAG_FIN) {
|
| - EXPECT_CALL(visitor, OnError(_));
|
| - } else if (IsSpdy4() && flags & ~(CONTROL_FLAG_FIN |
|
| - HEADERS_FLAG_END_HEADERS |
|
| - HEADERS_FLAG_END_SEGMENT |
|
| - HEADERS_FLAG_PADDED |
|
| - HEADERS_FLAG_PRIORITY)) {
|
| - EXPECT_CALL(visitor, OnError(_));
|
| - } else {
|
| - if (spdy_version_ > SPDY3 && flags & HEADERS_FLAG_PRIORITY) {
|
| - EXPECT_CALL(visitor, OnHeaders(57, // stream id
|
| - true, // has priority?
|
| - 3, // priority
|
| - flags & CONTROL_FLAG_FIN, // fin?
|
| - (flags & HEADERS_FLAG_END_HEADERS) ||
|
| - !IsSpdy4())); // end headers?
|
| - } else {
|
| - EXPECT_CALL(visitor, OnHeaders(57, false, 0,
|
| - flags & CONTROL_FLAG_FIN,
|
| - (flags & HEADERS_FLAG_END_HEADERS) ||
|
| - !IsSpdy4()));
|
| - }
|
| - EXPECT_CALL(visitor, OnControlFrameHeaderData(57, _, _))
|
| - .WillRepeatedly(testing::Return(true));
|
| - if (flags & DATA_FLAG_FIN && (!IsSpdy4() ||
|
| - flags & HEADERS_FLAG_END_HEADERS)) {
|
| - EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
|
| - } else {
|
| - // Do not close the stream if we are expecting a CONTINUATION frame.
|
| - EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true)).Times(0);
|
| - }
|
| - }
|
| -
|
| - framer.ProcessInput(frame->data(), frame->size());
|
| - if (!IsSpdy4() && flags & ~CONTROL_FLAG_FIN) {
|
| - EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
|
| - framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - } else if (IsSpdy4() && flags & ~(CONTROL_FLAG_FIN |
|
| - HEADERS_FLAG_END_HEADERS |
|
| - HEADERS_FLAG_END_SEGMENT |
|
| - HEADERS_FLAG_PADDED |
|
| - HEADERS_FLAG_PRIORITY)) {
|
| - EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
|
| - framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - } else if (IsSpdy4() && ~(flags & HEADERS_FLAG_END_HEADERS)) {
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - } else {
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - }
|
| - } while (++flags != 0);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, PingFrameFlags) {
|
| - uint8 flags = 0;
|
| - do {
|
| - SCOPED_TRACE(testing::Message() << "Flags " << flags);
|
| -
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializePing(SpdyPingIR(42)));
|
| - SetFrameFlags(frame.get(), flags, spdy_version_);
|
| -
|
| - if (spdy_version_ > SPDY3 &&
|
| - flags == PING_FLAG_ACK) {
|
| - EXPECT_CALL(visitor, OnPing(42, true));
|
| - } else if (flags == 0) {
|
| - EXPECT_CALL(visitor, OnPing(42, false));
|
| - } else {
|
| - EXPECT_CALL(visitor, OnError(_));
|
| - }
|
| -
|
| - framer.ProcessInput(frame->data(), frame->size());
|
| - if ((spdy_version_ > SPDY3 && flags == PING_FLAG_ACK) ||
|
| - flags == 0) {
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - } else {
|
| - EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
|
| - framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - }
|
| - } while (++flags != 0);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) {
|
| - uint8 flags = 0;
|
| - do {
|
| - SCOPED_TRACE(testing::Message() << "Flags " << flags);
|
| -
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeWindowUpdate(
|
| - SpdyWindowUpdateIR(4, 1024)));
|
| - SetFrameFlags(frame.get(), flags, spdy_version_);
|
| -
|
| - if (flags != 0) {
|
| - EXPECT_CALL(visitor, OnError(_));
|
| - } else {
|
| - EXPECT_CALL(visitor, OnWindowUpdate(4, 1024));
|
| - }
|
| -
|
| - framer.ProcessInput(frame->data(), frame->size());
|
| - if (flags != 0) {
|
| - EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
|
| - framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - } else {
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - }
|
| - } while (++flags != 0);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - uint8 flags = 0;
|
| - do {
|
| - SCOPED_TRACE(testing::Message() << "Flags " << flags);
|
| -
|
| - testing::StrictMock<net::test::MockSpdyFramerVisitor> visitor;
|
| - testing::StrictMock<net::test::MockDebugVisitor> debug_visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| - framer.set_debug_visitor(&debug_visitor);
|
| -
|
| - EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, PUSH_PROMISE, _, _));
|
| -
|
| - SpdyPushPromiseIR push_promise(42, 57);
|
| - push_promise.SetHeader("foo", "bar");
|
| - scoped_ptr<SpdySerializedFrame> frame(
|
| - framer.SerializePushPromise(push_promise));
|
| - // TODO(jgraettinger): Add padding to SpdyPushPromiseIR,
|
| - // and implement framing.
|
| - SetFrameFlags(frame.get(), flags & ~HEADERS_FLAG_PADDED, spdy_version_);
|
| -
|
| - if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
|
| - EXPECT_CALL(visitor, OnError(_));
|
| - } else {
|
| - EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, PUSH_PROMISE, _));
|
| - EXPECT_CALL(visitor, OnPushPromise(42, 57,
|
| - flags & PUSH_PROMISE_FLAG_END_PUSH_PROMISE));
|
| - EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
|
| - .WillRepeatedly(testing::Return(true));
|
| - }
|
| -
|
| - framer.ProcessInput(frame->data(), frame->size());
|
| - if (flags & ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
|
| - EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
|
| - framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - } else {
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - }
|
| - } while (++flags != 0);
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, ContinuationFrameFlags) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - uint8 flags = 0;
|
| - do {
|
| - SCOPED_TRACE(testing::Message() << "Flags " << flags);
|
| -
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - testing::StrictMock<net::test::MockDebugVisitor> debug_visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| - framer.set_debug_visitor(&debug_visitor);
|
| -
|
| - EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, HEADERS, _, _));
|
| - EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, HEADERS, _));
|
| - EXPECT_CALL(visitor, OnHeaders(42, false, 0, 0, false));
|
| - EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
|
| - .WillRepeatedly(testing::Return(true));
|
| -
|
| - SpdyHeadersIR headers_ir(42);
|
| - headers_ir.SetHeader("foo", "bar");
|
| - scoped_ptr<SpdyFrame> frame0(framer.SerializeHeaders(headers_ir));
|
| - SetFrameFlags(frame0.get(), 0, spdy_version_);
|
| -
|
| - SpdyContinuationIR continuation(42);
|
| - continuation.SetHeader("foo", "bar");
|
| - scoped_ptr<SpdySerializedFrame> frame(
|
| - framer.SerializeContinuation(continuation));
|
| - SetFrameFlags(frame.get(), flags, spdy_version_);
|
| -
|
| - if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
|
| - EXPECT_CALL(visitor, OnError(_));
|
| - } else {
|
| - EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, CONTINUATION, _));
|
| - EXPECT_CALL(visitor, OnContinuation(42,
|
| - flags & HEADERS_FLAG_END_HEADERS));
|
| - EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
|
| - .WillRepeatedly(testing::Return(true));
|
| - }
|
| -
|
| - framer.ProcessInput(frame0->data(), frame0->size());
|
| - framer.ProcessInput(frame->data(), frame->size());
|
| - if (flags & ~(HEADERS_FLAG_END_HEADERS)) {
|
| - EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
|
| - framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - } else {
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - }
|
| - } while (++flags != 0);
|
| -}
|
| -
|
| -// TODO(mlavan): Add TEST_P(SpdyFramerTest, AltSvcFrameFlags)
|
| -
|
| -// TODO(hkhalil): Add TEST_P(SpdyFramerTest, BlockedFrameFlags)
|
| -
|
| -TEST_P(SpdyFramerTest, EmptySynStream) {
|
| - if (!IsSpdy2() && !IsSpdy3()) {
|
| - // SYN_STREAM not supported in SPDY>3.
|
| - return;
|
| - }
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - testing::StrictMock<test::MockDebugVisitor> debug_visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| - framer.set_debug_visitor(&debug_visitor);
|
| -
|
| - EXPECT_CALL(debug_visitor, OnSendCompressedFrame(1, SYN_STREAM, _, _));
|
| -
|
| - SpdySynStreamIR syn_stream(1);
|
| - syn_stream.set_priority(1);
|
| - scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream));
|
| - // Adjust size to remove the name/value block.
|
| - SetFrameLength(
|
| - frame.get(),
|
| - framer.GetSynStreamMinimumSize() - framer.GetControlFrameHeaderSize(),
|
| - spdy_version_);
|
| -
|
| - EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(1, SYN_STREAM, _));
|
| - EXPECT_CALL(visitor, OnSynStream(1, 0, 1, false, false));
|
| - EXPECT_CALL(visitor, OnControlFrameHeaderData(1, NULL, 0));
|
| -
|
| - framer.ProcessInput(frame->data(), framer.GetSynStreamMinimumSize());
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, SettingsFlagsAndId) {
|
| - const uint32 kId = 0x020304;
|
| - const uint32 kFlags = 0x01;
|
| - const uint32 kWireFormat = htonl(IsSpdy2() ? 0x04030201 : 0x01020304);
|
| -
|
| - SettingsFlagsAndId id_and_flags =
|
| - SettingsFlagsAndId::FromWireFormat(spdy_version_, kWireFormat);
|
| - EXPECT_EQ(kId, id_and_flags.id());
|
| - EXPECT_EQ(kFlags, id_and_flags.flags());
|
| - EXPECT_EQ(kWireFormat, id_and_flags.GetWireFormat(spdy_version_));
|
| -}
|
| -
|
| -// Test handling of a RST_STREAM with out-of-bounds status codes.
|
| -TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
|
| - const unsigned char kRstStreamStatusTooLow = 0x00;
|
| - const unsigned char kRstStreamStatusTooHigh = 0xff;
|
| - const unsigned char kV3RstStreamInvalid[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x03,
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, kRstStreamStatusTooLow
|
| - };
|
| - const unsigned char kV4RstStreamInvalid[] = {
|
| - 0x00, 0x00, 0x04, 0x03,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x01, 0x00, 0x00, 0x00,
|
| - kRstStreamStatusTooLow
|
| - };
|
| -
|
| - const unsigned char kV3RstStreamNumStatusCodes[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x03,
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - 0x00, 0x00, 0x00, kRstStreamStatusTooHigh
|
| - };
|
| - const unsigned char kV4RstStreamNumStatusCodes[] = {
|
| - 0x00, 0x00, 0x04, 0x03,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x01, 0x00, 0x00, 0x00,
|
| - kRstStreamStatusTooHigh
|
| - };
|
| -
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - if (IsSpdy4()) {
|
| - EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
|
| - framer.ProcessInput(reinterpret_cast<const char*>(kV4RstStreamInvalid),
|
| - arraysize(kV4RstStreamInvalid));
|
| - } else {
|
| - EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
|
| - framer.ProcessInput(reinterpret_cast<const char*>(kV3RstStreamInvalid),
|
| - arraysize(kV3RstStreamInvalid));
|
| - }
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| -
|
| -
|
| - framer.Reset();
|
| -
|
| - if (IsSpdy4()) {
|
| - EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INTERNAL_ERROR));
|
| - framer.ProcessInput(
|
| - reinterpret_cast<const char*>(kV4RstStreamNumStatusCodes),
|
| - arraysize(kV4RstStreamNumStatusCodes));
|
| - } else {
|
| - EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
|
| - framer.ProcessInput(
|
| - reinterpret_cast<const char*>(kV3RstStreamNumStatusCodes),
|
| - arraysize(kV3RstStreamNumStatusCodes));
|
| - }
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| -}
|
| -
|
| -// Test handling of GOAWAY frames with out-of-bounds status code.
|
| -TEST_P(SpdyFramerTest, GoAwayStatusBounds) {
|
| - if (spdy_version_ <= SPDY2) {
|
| - return;
|
| - }
|
| - SpdyFramer framer(spdy_version_);
|
| -
|
| - const unsigned char kV3FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x07,
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - 0x00, 0x00, 0x00, 0x01, // Stream Id
|
| - 0xff, 0xff, 0xff, 0xff, // Status
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x0a, 0x07,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00, // Stream id
|
| - 0x01, 0xff, 0xff, 0xff, // Status
|
| - 0xff, 0x47, 0x41, // Opaque Description
|
| - };
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - framer.set_visitor(&visitor);
|
| -
|
| - if (IsSpdy3()) {
|
| - EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_OK));
|
| - framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
|
| - arraysize(kV3FrameData));
|
| - } else {
|
| - EXPECT_CALL(visitor, OnGoAway(1, GOAWAY_INTERNAL_ERROR));
|
| - framer.ProcessInput(reinterpret_cast<const char*>(kV4FrameData),
|
| - arraysize(kV4FrameData));
|
| - }
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| -}
|
| -
|
| -// Tests handling of a GOAWAY frame with out-of-bounds stream ID.
|
| -TEST_P(SpdyFramerTest, GoAwayStreamIdBounds) {
|
| - const unsigned char kV2FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x07,
|
| - 0x00, 0x00, 0x00, 0x04,
|
| - 0xff, 0xff, 0xff, 0xff,
|
| - };
|
| - const unsigned char kV3FrameData[] = {
|
| - 0x80, spdy_version_ch_, 0x00, 0x07,
|
| - 0x00, 0x00, 0x00, 0x08,
|
| - 0xff, 0xff, 0xff, 0xff,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - };
|
| - const unsigned char kV4FrameData[] = {
|
| - 0x00, 0x00, 0x08, 0x07,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0xff, 0xff, 0xff,
|
| - 0xff, 0x00, 0x00, 0x00,
|
| - 0x00,
|
| - };
|
| -
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - EXPECT_CALL(visitor, OnGoAway(0x7fffffff, GOAWAY_OK));
|
| - if (IsSpdy2()) {
|
| - framer.ProcessInput(reinterpret_cast<const char*>(kV2FrameData),
|
| - arraysize(kV2FrameData));
|
| - } else if (IsSpdy3()) {
|
| - framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
|
| - arraysize(kV3FrameData));
|
| - } else {
|
| - framer.ProcessInput(reinterpret_cast<const char*>(kV4FrameData),
|
| - arraysize(kV4FrameData));
|
| - }
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, OnBlocked) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - const SpdyStreamId kStreamId = 0;
|
| -
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - EXPECT_CALL(visitor, OnBlocked(kStreamId));
|
| -
|
| - SpdyBlockedIR blocked_ir(0);
|
| - scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
|
| - framer.ProcessInput(frame->data(), framer.GetBlockedSize());
|
| -
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, OnAltSvc) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - const SpdyStreamId kStreamId = 1;
|
| -
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - EXPECT_CALL(visitor, OnAltSvc(kStreamId,
|
| - 10,
|
| - 443,
|
| - StringPiece("pid"),
|
| - StringPiece("h1"),
|
| - StringPiece("o1")));
|
| -
|
| - SpdyAltSvcIR altsvc_ir(1);
|
| - altsvc_ir.set_max_age(10);
|
| - altsvc_ir.set_port(443);
|
| - altsvc_ir.set_protocol_id("pid");
|
| - altsvc_ir.set_host("h1");
|
| - altsvc_ir.set_origin("o1");
|
| - scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
|
| - framer.ProcessInput(frame->data(), framer.GetAltSvcMinimumSize() +
|
| - altsvc_ir.protocol_id().length() +
|
| - altsvc_ir.host().length() +
|
| - altsvc_ir.origin().length());
|
| -
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, OnAltSvcNoOrigin) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - const SpdyStreamId kStreamId = 1;
|
| -
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - EXPECT_CALL(visitor, OnAltSvc(kStreamId,
|
| - 10,
|
| - 443,
|
| - StringPiece("pid"),
|
| - StringPiece("h1"),
|
| - StringPiece("")));
|
| -
|
| - SpdyAltSvcIR altsvc_ir(1);
|
| - altsvc_ir.set_max_age(10);
|
| - altsvc_ir.set_port(443);
|
| - altsvc_ir.set_protocol_id("pid");
|
| - altsvc_ir.set_host("h1");
|
| - scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(altsvc_ir));
|
| - framer.ProcessInput(frame->data(), framer.GetAltSvcMinimumSize() +
|
| - altsvc_ir.protocol_id().length() +
|
| - altsvc_ir.host().length());
|
| -
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, OnAltSvcBadLengths) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - const unsigned char kType = static_cast<unsigned char>(
|
| - SpdyConstants::SerializeFrameType(spdy_version_, ALTSVC));
|
| - {
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - const unsigned char kFrameDataLargePIDLen[] = {
|
| - 0x00, 0x00, 0x17, kType, 0x00,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 0x00, 0x00, 0x00, 0x05,
|
| - 0x01, 0xbb, 0x00, 0x05, // Port = 443
|
| - 'p', 'i', 'd', '1', // Protocol-ID
|
| - 0x04, 'h', 'o', 's',
|
| - 't', 'o', 'r', 'i',
|
| - 'g', 'i', 'n',
|
| - };
|
| -
|
| - visitor.SimulateInFramer(kFrameDataLargePIDLen,
|
| - sizeof(kFrameDataLargePIDLen));
|
| - EXPECT_EQ(1, visitor.error_count_);
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
|
| - visitor.framer_.error_code());
|
| - }
|
| -
|
| - {
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| - const unsigned char kFrameDataPIDLenLargerThanFrame[] = {
|
| - 0x00, 0x00, 0x17, kType, 0x00,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 0x00, 0x00, 0x00, 0x05,
|
| - 0x01, 0xbb, 0x00, 0x99, // Port = 443
|
| - 'p', 'i', 'd', '1', // Protocol-ID
|
| - 0x04, 'h', 'o', 's',
|
| - 't', 'o', 'r', 'i',
|
| - 'g', 'i', 'n',
|
| - };
|
| -
|
| - visitor.SimulateInFramer(kFrameDataPIDLenLargerThanFrame,
|
| - sizeof(kFrameDataPIDLenLargerThanFrame));
|
| - EXPECT_EQ(1, visitor.error_count_);
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
|
| - visitor.framer_.error_code());
|
| - }
|
| -
|
| - {
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| -
|
| - const unsigned char kFrameDataLargeHostLen[] = {
|
| - 0x00, 0x00, 0x17, kType, 0x00,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 0x00, 0x00, 0x00, 0x05,
|
| - 0x01, 0xbb, 0x00, 0x04, // Port = 443
|
| - 'p', 'i', 'd', '1', // Protocol-ID
|
| - 0x0f, 'h', 'o', 's',
|
| - 't', 'o', 'r', 'i',
|
| - 'g', 'i', 'n',
|
| - };
|
| -
|
| - visitor.SimulateInFramer(kFrameDataLargeHostLen,
|
| - sizeof(kFrameDataLargeHostLen));
|
| - EXPECT_EQ(1, visitor.error_count_);
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
|
| - visitor.framer_.error_code());
|
| - }
|
| -
|
| - {
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - SpdyFramer framer(spdy_version_);
|
| - framer.set_visitor(&visitor);
|
| - const unsigned char kFrameDataSmallPIDLen[] = {
|
| - 0x00, 0x00, 0x17, kType, 0x00,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 0x00, 0x00, 0x00, 0x05,
|
| - 0x01, 0xbb, 0x00, 0x01, // Port = 443
|
| - 'p', 'i', 'd', '1', // Protocol-ID
|
| - 0x04, 'h', 'o', 's',
|
| - 't', 'o', 'r', 'i',
|
| - 'g', 'i', 'n',
|
| - };
|
| -
|
| - visitor.SimulateInFramer(kFrameDataSmallPIDLen,
|
| - sizeof(kFrameDataSmallPIDLen));
|
| - EXPECT_EQ(1, visitor.error_count_);
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
|
| - visitor.framer_.error_code());
|
| - }
|
| -}
|
| -
|
| -// Tests handling of ALTSVC frames delivered in small chunks.
|
| -TEST_P(SpdyFramerTest, ReadChunkedAltSvcFrame) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| - SpdyFramer framer(spdy_version_);
|
| - SpdyAltSvcIR altsvc_ir(1);
|
| - altsvc_ir.set_max_age(20);
|
| - altsvc_ir.set_port(443);
|
| - altsvc_ir.set_protocol_id("protocolid");
|
| - altsvc_ir.set_host("hostname");
|
| -
|
| - scoped_ptr<SpdyFrame> control_frame(framer.SerializeAltSvc(altsvc_ir));
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.use_compression_ = false;
|
| -
|
| - // Read data in small chunks.
|
| - size_t framed_data = 0;
|
| - size_t unframed_data = control_frame->size();
|
| - size_t kReadChunkSize = 5; // Read five bytes at a time.
|
| - while (unframed_data > 0) {
|
| - size_t to_read = std::min(kReadChunkSize, unframed_data);
|
| - visitor.SimulateInFramer(
|
| - reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
|
| - to_read);
|
| - unframed_data -= to_read;
|
| - framed_data += to_read;
|
| - }
|
| - EXPECT_EQ(0, visitor.error_count_);
|
| - EXPECT_EQ(1, visitor.altsvc_count_);
|
| - EXPECT_EQ(20u, visitor.test_altsvc_ir_.max_age());
|
| - EXPECT_EQ(443u, visitor.test_altsvc_ir_.port());
|
| - EXPECT_EQ("protocolid", visitor.test_altsvc_ir_.protocol_id());
|
| - EXPECT_EQ("hostname", visitor.test_altsvc_ir_.host());
|
| -}
|
| -
|
| -// Tests handling of PRIORITY frames.
|
| -TEST_P(SpdyFramerTest, ReadPriority) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| - SpdyFramer framer(spdy_version_);
|
| - SpdyPriorityIR priority(3, 1, 255, false);
|
| - scoped_ptr<SpdySerializedFrame> frame(framer.SerializePriority(priority));
|
| - testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
|
| - framer.set_visitor(&visitor);
|
| - EXPECT_CALL(visitor, OnPriority(3, 1, 255, false));
|
| - framer.ProcessInput(frame->data(), frame->size());
|
| -
|
| - EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
|
| - << SpdyFramer::ErrorCodeToString(framer.error_code());
|
| - // TODO(mlavan): once we actually maintain a priority tree,
|
| - // check that state is adjusted correctly.
|
| -}
|
| -
|
| -TEST_P(SpdyFramerTest, PriorityWeightMapping) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| - SpdyFramer framer(spdy_version_);
|
| -
|
| - EXPECT_EQ(255u, framer.MapPriorityToWeight(0));
|
| - EXPECT_EQ(219u, framer.MapPriorityToWeight(1));
|
| - EXPECT_EQ(182u, framer.MapPriorityToWeight(2));
|
| - EXPECT_EQ(146u, framer.MapPriorityToWeight(3));
|
| - EXPECT_EQ(109u, framer.MapPriorityToWeight(4));
|
| - EXPECT_EQ(73u, framer.MapPriorityToWeight(5));
|
| - EXPECT_EQ(36u, framer.MapPriorityToWeight(6));
|
| - EXPECT_EQ(0u, framer.MapPriorityToWeight(7));
|
| -
|
| - EXPECT_EQ(0u, framer.MapWeightToPriority(255));
|
| - EXPECT_EQ(0u, framer.MapWeightToPriority(220));
|
| - EXPECT_EQ(1u, framer.MapWeightToPriority(219));
|
| - EXPECT_EQ(1u, framer.MapWeightToPriority(183));
|
| - EXPECT_EQ(2u, framer.MapWeightToPriority(182));
|
| - EXPECT_EQ(2u, framer.MapWeightToPriority(147));
|
| - EXPECT_EQ(3u, framer.MapWeightToPriority(146));
|
| - EXPECT_EQ(3u, framer.MapWeightToPriority(110));
|
| - EXPECT_EQ(4u, framer.MapWeightToPriority(109));
|
| - EXPECT_EQ(4u, framer.MapWeightToPriority(74));
|
| - EXPECT_EQ(5u, framer.MapWeightToPriority(73));
|
| - EXPECT_EQ(5u, framer.MapWeightToPriority(37));
|
| - EXPECT_EQ(6u, framer.MapWeightToPriority(36));
|
| - EXPECT_EQ(6u, framer.MapWeightToPriority(1));
|
| - EXPECT_EQ(7u, framer.MapWeightToPriority(0));
|
| -}
|
| -
|
| -// Tests handling of PRIORITY frame with incorrect size.
|
| -TEST_P(SpdyFramerTest, ReadIncorrectlySizedPriority) {
|
| - if (spdy_version_ <= SPDY3) {
|
| - return;
|
| - }
|
| -
|
| - // PRIORITY frame of size 4, which isn't correct.
|
| - const unsigned char kFrameData[] = {
|
| - 0x00, 0x00, 0x04, 0x02, 0x00,
|
| - 0x00, 0x00, 0x00, 0x03,
|
| - 0x00, 0x00, 0x00, 0x01,
|
| - };
|
| -
|
| - TestSpdyVisitor visitor(spdy_version_);
|
| - visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
|
| -
|
| - EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
|
| - EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
|
| - visitor.framer_.error_code())
|
| - << SpdyFramer::ErrorCodeToString(visitor.framer_.error_code());
|
| -}
|
| -
|
| -} // namespace net
|
|
|