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

Unified Diff: net/spdy/spdy_framer_spdy2_test.cc

Issue 9689078: SPDY - unforked spdy_framer and spdy_protocol tests. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/spdy/spdy_framer_spdy2_test.cc
===================================================================
--- net/spdy/spdy_framer_spdy2_test.cc (revision 126410)
+++ net/spdy/spdy_framer_spdy2_test.cc (working copy)
@@ -1,2623 +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 "base/memory/scoped_ptr.h"
-#include "net/spdy/spdy_framer.h"
-#include "net/spdy/spdy_protocol.h"
-#include "net/spdy/spdy_frame_builder.h"
-#include "testing/platform_test.h"
-
-namespace {
-
-// Default SPDY version for unit tests.
-const int SPDY_VERSION_FOR_TESTS = 2;
-
-// The current default spdy version as a byte to be included in const
-// byte arrays below. Name choice is unfortunate, but better to fit to four
-// bytes than not.
-unsigned char kVer = SPDY_VERSION_FOR_TESTS;
-
-spdy::SpdySetting SpdySettingFromWireFormat(uint32 key, uint32 value) {
- return spdy::SpdySetting(
- spdy::SettingsFlagsAndId::FromWireFormat(SPDY_VERSION_FOR_TESTS, key),
- value);
-}
-
-} // namespace
-
-namespace spdy {
-
-namespace test_spdy2 {
-
-static const size_t kMaxDecompressedSize = 1024;
-
-class SpdyFramerTestUtil {
- public:
- // Decompress a single frame using the decompression context held by
- // the SpdyFramer. The implemention 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->set_visitor(&visitor);
- size_t input_size = frame.length() + SpdyFrame::kHeaderSize;
- CHECK_EQ(input_size, framer->ProcessInput(frame.data(), input_size));
- CHECK_EQ(SpdyFramer::SPDY_RESET, framer->state());
- framer->set_visitor(NULL);
-
- char* buffer = visitor.ReleaseBuffer();
- CHECK(buffer);
- SpdyFrame* decompressed_frame = new SpdyFrame(buffer, true);
- decompressed_frame->set_length(visitor.size() - SpdyFrame::kHeaderSize);
- return decompressed_frame;
- }
-
- class DecompressionVisitor : public SpdyFramerVisitorInterface {
- public:
- DecompressionVisitor()
- : buffer_(NULL), size_(0), finished_(false), allow_data_frames_(false) {
- }
-
- virtual void OnControl(const SpdyControlFrame* frame) {
- CHECK(frame->has_header_block());
- CHECK(!buffer_.get());
- CHECK_EQ(size_, 0u);
- CHECK(!finished_);
-
- int32 control_frame_header_size = 0;
- switch (frame->type()) {
- case SYN_STREAM:
- control_frame_header_size = SpdySynStreamControlFrame::size();
- break;
- case SYN_REPLY:
- control_frame_header_size = SpdySynReplyControlFrame::size();
- break;
- case HEADERS:
- control_frame_header_size = SpdyHeadersControlFrame::size();
- break;
- default:
- LOG(FATAL);
- return;
- }
-
- // Allocate space for the frame, and the copy header over.
- buffer_.reset(new char[kMaxDecompressedSize]);
- memcpy(buffer_.get(), frame->data(), control_frame_header_size);
- size_ += control_frame_header_size;
- }
-
- virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id,
- const char* header_data,
- size_t len) {
- 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;
- }
-
- virtual bool OnCredentialFrameData(const char* header_data,
- size_t len) {
- LOG(FATAL) << "Unexpected CREDENTIAL Frame";
- return false;
- }
-
- virtual void OnError(SpdyFramer* framer) { LOG(FATAL); }
- virtual void OnDataFrameHeader(const SpdyDataFrame* frame) {
- // For most tests, this class does not expect to see OnDataFrameHeader
- // calls. Individual tests can override this if they need to.
- if (!allow_data_frames_) {
- LOG(FATAL) << "Unexpected data frame header";
- }
- }
- virtual void OnStreamFrameData(SpdyStreamId stream_id,
- const char* data,
- size_t len) {
- LOG(FATAL);
- }
- virtual void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) {
- LOG(FATAL);
- }
-
- char* ReleaseBuffer() {
- CHECK(finished_);
- return buffer_.release();
- }
-
- size_t size() const {
- CHECK(finished_);
- return size_;
- }
- void set_allow_data_frames(bool allow) { allow_data_frames_ = allow; }
-
- private:
- scoped_array<char> buffer_;
- size_t size_;
- bool finished_;
- bool allow_data_frames_;
-
- DISALLOW_COPY_AND_ASSIGN(DecompressionVisitor);
- };
-
- DISALLOW_COPY_AND_ASSIGN(SpdyFramerTestUtil);
-};
-
-std::string HexDumpWithMarks(const unsigned char* data, int length,
- const bool* marks, int mark_length) {
- static const char kHexChars[] = "0123456789abcdef";
- static const int kColumns = 4;
-
- const int kSizeLimit = 1024;
- if (length > kSizeLimit || mark_length > kSizeLimit) {
- LOG(ERROR) << "Only dumping first " << kSizeLimit << " bytes.";
- length = std::min(length, kSizeLimit);
- mark_length = std::min(mark_length, kSizeLimit);
- }
-
- std::string hex;
- for (const unsigned char* row = data; length > 0;
- row += kColumns, length -= kColumns) {
- for (const unsigned char *p = row; p < row + 4; ++p) {
- if (p < row + length) {
- const bool mark =
- (marks && (p - data) < mark_length && marks[p - data]);
- hex += mark ? '*' : ' ';
- hex += kHexChars[(*p & 0xf0) >> 4];
- hex += kHexChars[*p & 0x0f];
- hex += mark ? '*' : ' ';
- } else {
- hex += " ";
- }
- }
- hex = hex + " ";
-
- for (const unsigned char *p = row; p < row + 4 && p < row + length; ++p)
- hex += (*p >= 0x20 && *p <= 0x7f) ? (*p) : '.';
-
- hex = hex + '\n';
- }
- return hex;
-}
-
-void CompareCharArraysWithHexError(
- const std::string& description,
- const unsigned char* actual,
- const int actual_len,
- const unsigned char* expected,
- const int expected_len) {
- const int min_len = std::min(actual_len, expected_len);
- const int max_len = std::max(actual_len, expected_len);
- scoped_array<bool> marks(new bool[max_len]);
- bool identical = (actual_len == expected_len);
- for (int i = 0; i < min_len; ++i) {
- if (actual[i] != expected[i]) {
- marks[i] = true;
- identical = false;
- } else {
- marks[i] = false;
- }
- }
- for (int i = min_len; i < max_len; ++i) {
- marks[i] = true;
- }
- if (identical) return;
- ADD_FAILURE()
- << "Description:\n"
- << description
- << "\n\nExpected:\n"
- << HexDumpWithMarks(expected, expected_len, marks.get(), max_len)
- << "\nActual:\n"
- << HexDumpWithMarks(actual, actual_len, marks.get(), max_len);
-}
-
-class TestSpdyVisitor : public SpdyFramerVisitorInterface {
- public:
- static const size_t kDefaultHeaderBufferSize = 64 * 1024;
- static const size_t kDefaultCredentialBufferSize = 16 * 1024;
-
- TestSpdyVisitor()
- : framer_(kVer),
- use_compression_(false),
- error_count_(0),
- syn_frame_count_(0),
- syn_reply_frame_count_(0),
- headers_frame_count_(0),
- goaway_count_(0),
- credential_count_(0),
- settings_frame_count_(0),
- setting_count_(0),
- data_bytes_(0),
- fin_frame_count_(0),
- fin_flag_count_(0),
- zero_length_data_frame_count_(0),
- header_blocks_count_(0),
- control_frame_header_data_count_(0),
- zero_length_control_frame_header_data_count_(0),
- data_frame_count_(0),
- header_buffer_(new char[kDefaultHeaderBufferSize]),
- header_buffer_length_(0),
- header_buffer_size_(kDefaultHeaderBufferSize),
- header_stream_id_(-1),
- header_control_type_(NUM_CONTROL_FRAME_TYPES),
- header_buffer_valid_(false),
- credential_buffer_(new char[kDefaultCredentialBufferSize]),
- credential_buffer_length_(0),
- credential_buffer_size_(kDefaultCredentialBufferSize) {
- }
-
- void OnError(SpdyFramer* f) {
- LOG(INFO) << "SpdyFramer Error: "
- << SpdyFramer::ErrorCodeToString(f->error_code());
- error_count_++;
- }
-
- void OnDataFrameHeader(const SpdyDataFrame* frame) {
- data_frame_count_++;
- header_stream_id_ = frame->stream_id();
- }
-
- void OnStreamFrameData(SpdyStreamId stream_id,
- const char* data,
- size_t len) {
- 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 & (unsigned int)data[i]) << std::dec;
- }
- }
- std::cerr << "\", " << len << ")\n";
- }
-
- void OnControl(const SpdyControlFrame* frame) {
- switch (frame->type()) {
- case SYN_STREAM:
- syn_frame_count_++;
- InitHeaderStreaming(frame);
- break;
- case SYN_REPLY:
- syn_reply_frame_count_++;
- InitHeaderStreaming(frame);
- break;
- case RST_STREAM:
- fin_frame_count_++;
- break;
- case HEADERS:
- headers_frame_count_++;
- InitHeaderStreaming(frame);
- break;
- case GOAWAY:
- goaway_count_++;
- break;
- case CREDENTIAL:
- credential_count_++;
- break;
- case SETTINGS:
- settings_frame_count_++;
- break;
- default:
- DLOG(FATAL); // Error!
- }
- if (frame->flags() & CONTROL_FLAG_FIN)
- ++fin_flag_count_;
- }
-
- virtual void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) {
- setting_count_++;
- }
-
- bool OnControlFrameHeaderData(SpdyStreamId stream_id,
- const char* header_data,
- size_t len) {
- ++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.
- CHECK(header_buffer_valid_);
- bool parsed_headers = framer_.ParseHeaderBlockInBuffer(
- header_buffer_.get(), header_buffer_length_, &headers_);
- DCHECK(parsed_headers);
- 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;
- }
-
- bool OnCredentialFrameData(const char* credential_data,
- size_t len) {
- if (len == 0) {
- if (!framer_.ParseCredentialData(credential_buffer_.get(),
- credential_buffer_length_,
- &credential_)) {
- ++error_count_;
- }
- return true;
- }
- const size_t available =
- credential_buffer_size_ - credential_buffer_length_;
- if (len > available) {
- return false;
- }
- memcpy(credential_buffer_.get() + credential_buffer_length_,
- credential_data, len);
- credential_buffer_length_ += len;
- return true;
- }
-
- // 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;
- if (framer_.state() == SpdyFramer::SPDY_DONE)
- framer_.Reset();
- }
- }
-
- void InitHeaderStreaming(const SpdyControlFrame* frame) {
- memset(header_buffer_.get(), 0, header_buffer_size_);
- header_buffer_length_ = 0;
- header_stream_id_ = SpdyFramer::GetControlFrameStreamId(frame);
- header_control_type_ = frame->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]);
- }
-
- static size_t control_frame_buffer_max_size() {
- return SpdyFramer::kControlFrameBufferMaxSize;
- }
-
- 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 goaway_count_;
- int credential_count_;
- int settings_frame_count_;
- int setting_count_;
- int data_bytes_;
- int fin_frame_count_; // The count of RST_STREAM type frames received.
- 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 header_blocks_count_;
- 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_;
-
- // Header block streaming state:
- scoped_array<char> header_buffer_;
- size_t header_buffer_length_;
- size_t header_buffer_size_;
- SpdyStreamId header_stream_id_;
- SpdyControlType header_control_type_;
- bool header_buffer_valid_;
- SpdyHeaderBlock headers_;
-
- scoped_array<char> credential_buffer_;
- size_t credential_buffer_length_;
- size_t credential_buffer_size_;
- SpdyCredential credential_;
-};
-
-} // namespace test_spdy2
-
-} // namespace spdy
-
-using spdy::SpdyControlFlags;
-using spdy::SpdyControlFrame;
-using spdy::SpdyDataFrame;
-using spdy::SpdyFrame;
-using spdy::SpdyFrameBuilder;
-using spdy::SpdyFramer;
-using spdy::SpdyHeaderBlock;
-using spdy::SpdySynStreamControlFrame;
-using spdy::kControlFlagMask;
-using spdy::kLengthMask;
-using spdy::CONTROL_FLAG_NONE;
-using spdy::DATA_FLAG_COMPRESSED;
-using spdy::DATA_FLAG_FIN;
-using spdy::SYN_STREAM;
-using spdy::test_spdy2::CompareCharArraysWithHexError;
-using spdy::test_spdy2::SpdyFramerTestUtil;
-using spdy::test_spdy2::TestSpdyVisitor;
-
-namespace spdy {
-
-TEST(SpdyFrameBuilderSpdy2Test, WriteLimits) {
- SpdyFrameBuilder builder(kLengthMask + 4);
- // length field should fail.
- EXPECT_FALSE(builder.WriteBytes(reinterpret_cast<const void*>(0x1),
- kLengthMask + 1));
- EXPECT_EQ(0, builder.length());
-
- // Writing a block of the maximum allowed size should succeed.
- const std::string kLargeData(kLengthMask, 'A');
- builder.WriteUInt32(kLengthMask);
- EXPECT_EQ(4, builder.length());
- EXPECT_TRUE(builder.WriteBytes(kLargeData.data(), kLengthMask));
- EXPECT_EQ(4 + kLengthMask, static_cast<unsigned>(builder.length()));
-}
-
-class SpdyFramerSpdy2Test : public PlatformTest {
- public:
- virtual void TearDown() {}
-
- protected:
- void CompareFrame(const std::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());
- int actual_len = actual_frame.length() + SpdyFrame::kHeaderSize;
- CompareCharArraysWithHexError(
- description, actual, actual_len, expected, expected_len);
- }
-
- // 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() << "." << std::endl;
- 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 << "'."
- << std::endl;
- 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
- << "'." << std::endl;
- return false;
- }
- }
- return true;
- }
-};
-
-
-// Test that we can encode and decode a SpdyHeaderBlock in serialized form.
-TEST_F(SpdyFramerSpdy2Test, HeaderBlockInBuffer) {
- SpdyHeaderBlock headers;
- headers["alpha"] = "beta";
- headers["gamma"] = "charlie";
- SpdyFramer framer(kVer);
-
- // Encode the header block into a SynStream frame.
- scoped_ptr<SpdySynStreamControlFrame> frame(
- framer.CreateSynStream(1, 0, 1, CONTROL_FLAG_NONE, false, &headers));
- EXPECT_TRUE(frame.get() != NULL);
- std::string serialized_headers(frame->header_block(),
- frame->header_block_len());
- SpdyHeaderBlock new_headers;
- EXPECT_TRUE(framer.ParseHeaderBlockInBuffer(serialized_headers.c_str(),
- serialized_headers.size(),
- &new_headers));
-
- EXPECT_EQ(headers.size(), new_headers.size());
- EXPECT_EQ(headers["alpha"], new_headers["alpha"]);
- EXPECT_EQ(headers["gamma"], new_headers["gamma"]);
-}
-
-// Test that if there's not a full frame, we fail to parse it.
-TEST_F(SpdyFramerSpdy2Test, UndersizedHeaderBlockInBuffer) {
- SpdyHeaderBlock headers;
- headers["alpha"] = "beta";
- headers["gamma"] = "charlie";
- SpdyFramer framer(kVer);
-
- // Encode the header block into a SynStream frame.
- scoped_ptr<SpdySynStreamControlFrame> frame(
- framer.CreateSynStream(1, 0, 1, CONTROL_FLAG_NONE, false, &headers));
- EXPECT_TRUE(frame.get() != NULL);
-
- std::string serialized_headers(frame->header_block(),
- frame->header_block_len());
- SpdyHeaderBlock new_headers;
- EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.c_str(),
- serialized_headers.size() - 2,
- &new_headers));
-}
-
-TEST_F(SpdyFramerSpdy2Test, OutOfOrderHeaders) {
- // Frame builder with plentiful buffer size.
- SpdyFrameBuilder frame(1024);
-
- frame.WriteUInt16(kControlFlagMask | 1);
- frame.WriteUInt16(SYN_STREAM);
- frame.WriteUInt32(0); // Placeholder for the length.
- frame.WriteUInt32(3); // stream_id
- frame.WriteUInt32(0); // Associated stream id
- frame.WriteUInt16(0); // Priority.
-
- if (SPDY_VERSION_FOR_TESTS < 3) {
- frame.WriteUInt16(2); // Number of headers.
- frame.WriteString("gamma");
- frame.WriteString("gamma");
- frame.WriteString("alpha");
- frame.WriteString("alpha");
- } else {
- frame.WriteUInt32(2); // Number of headers.
- frame.WriteStringPiece32("gamma");
- frame.WriteStringPiece32("gamma");
- frame.WriteStringPiece32("alpha");
- frame.WriteStringPiece32("alpha");
- }
- // write the length
- frame.WriteUInt32ToOffset(4, frame.length() - SpdyFrame::kHeaderSize);
-
- SpdyHeaderBlock new_headers;
- scoped_ptr<SpdyFrame> control_frame(frame.take());
- SpdySynStreamControlFrame syn_frame(control_frame->data(), false);
- std::string serialized_headers(syn_frame.header_block(),
- syn_frame.header_block_len());
- SpdyFramer framer(kVer);
- framer.set_enable_compression(false);
- EXPECT_TRUE(framer.ParseHeaderBlockInBuffer(serialized_headers.c_str(),
- serialized_headers.size(),
- &new_headers));
-}
-
-TEST_F(SpdyFramerSpdy2Test, CreateCredential) {
- SpdyFramer framer(kVer);
-
- {
- const char kDescription[] = "CREDENTIAL frame";
- const unsigned char kFrameData[] = {
- 0x80, kVer, 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',
- };
- SpdyCredential credential;
- credential.slot = 3;
- credential.proof = "proof";
- credential.certs.push_back("a cert");
- credential.certs.push_back("another cert");
- credential.certs.push_back("final cert");
- scoped_ptr<SpdyFrame> frame(framer.CreateCredentialFrame(credential));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
- }
-}
-
-TEST_F(SpdyFramerSpdy2Test, ParseCredentialFrameData) {
- SpdyFramer framer(kVer);
-
- {
- unsigned char kFrameData[] = {
- 0x80, kVer, 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',
- };
- SpdyCredentialControlFrame frame(reinterpret_cast<char*>(kFrameData),
- false);
- SpdyCredential credential;
- EXPECT_TRUE(SpdyFramer::ParseCredentialData(frame.payload(), frame.length(),
- &credential));
- EXPECT_EQ(3u, credential.slot);
- EXPECT_EQ("proof", credential.proof);
- EXPECT_EQ("a cert", credential.certs.front());
- credential.certs.erase(credential.certs.begin());
- EXPECT_EQ("another cert", credential.certs.front());
- credential.certs.erase(credential.certs.begin());
- EXPECT_EQ("final cert", credential.certs.front());
- credential.certs.erase(credential.certs.begin());
- EXPECT_TRUE(credential.certs.empty());
- }
-}
-
-TEST_F(SpdyFramerSpdy2Test, DuplicateHeader) {
- // Frame builder with plentiful buffer size.
- SpdyFrameBuilder frame(1024);
-
- frame.WriteUInt16(kControlFlagMask | 1);
- frame.WriteUInt16(SYN_STREAM);
- frame.WriteUInt32(0); // Placeholder for the length.
- frame.WriteUInt32(3); // stream_id
- frame.WriteUInt32(0); // associated stream id
- frame.WriteUInt16(0); // Priority.
-
- if (SPDY_VERSION_FOR_TESTS < 3) {
- 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.WriteUInt32ToOffset(4, frame.length() - SpdyFrame::kHeaderSize);
-
- SpdyHeaderBlock new_headers;
- scoped_ptr<SpdyFrame> control_frame(frame.take());
- SpdySynStreamControlFrame syn_frame(control_frame->data(), false);
- std::string serialized_headers(syn_frame.header_block(),
- syn_frame.header_block_len());
- SpdyFramer framer(kVer);
- framer.set_enable_compression(false);
- // This should fail because duplicate headers are verboten by the spec.
- EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.c_str(),
- serialized_headers.size(),
- &new_headers));
-}
-
-TEST_F(SpdyFramerSpdy2Test, MultiValueHeader) {
- // Frame builder with plentiful buffer size.
- SpdyFrameBuilder frame(1024);
-
- frame.WriteUInt16(kControlFlagMask | 1);
- frame.WriteUInt16(SYN_STREAM);
- frame.WriteUInt32(0); // Placeholder for the length.
- frame.WriteUInt32(3); // stream_id
- frame.WriteUInt32(0); // associated stream id
- frame.WriteUInt16(0); // Priority.
-
- std::string value("value1\0value2");
- if (SPDY_VERSION_FOR_TESTS < 3) {
- frame.WriteUInt16(1); // Number of headers.
- frame.WriteString("name");
- frame.WriteString(value);
- } else {
- frame.WriteUInt32(1); // Number of headers.
- frame.WriteStringPiece32("name");
- frame.WriteStringPiece32(value);
- }
- // write the length
- frame.WriteUInt32ToOffset(4, frame.length() - SpdyFrame::kHeaderSize);
-
- SpdyHeaderBlock new_headers;
- scoped_ptr<SpdyFrame> control_frame(frame.take());
- SpdySynStreamControlFrame syn_frame(control_frame->data(), false);
- std::string serialized_headers(syn_frame.header_block(),
- syn_frame.header_block_len());
- SpdyFramer framer(kVer);
- framer.set_enable_compression(false);
- EXPECT_TRUE(framer.ParseHeaderBlockInBuffer(serialized_headers.c_str(),
- serialized_headers.size(),
- &new_headers));
- EXPECT_TRUE(new_headers.find("name") != new_headers.end());
- EXPECT_EQ(value, new_headers.find("name")->second);
-}
-
-TEST_F(SpdyFramerSpdy2Test, BasicCompression) {
- SpdyHeaderBlock headers;
- headers["server"] = "SpdyServer 1.0";
- headers["date"] = "Mon 12 Jan 2009 12:12:12 PST";
- headers["status"] = "200";
- headers["version"] = "HTTP/1.1";
- headers["content-type"] = "text/html";
- headers["content-length"] = "12";
-
- SpdyFramer framer(kVer);
- framer.set_enable_compression(true);
- scoped_ptr<SpdySynStreamControlFrame>
- frame1(framer.CreateSynStream(1, 0, 1, CONTROL_FLAG_NONE, true,
- &headers));
- scoped_ptr<SpdySynStreamControlFrame>
- frame2(framer.CreateSynStream(1, 0, 1, CONTROL_FLAG_NONE, true,
- &headers));
-
- // Expect the second frame to be more compact than the first.
- EXPECT_LE(frame2->length(), frame1->length());
-
- // Decompress the first frame
- scoped_ptr<SpdyFrame> frame3(SpdyFramerTestUtil::DecompressFrame(
- &framer, *frame1.get()));
-
- // Decompress the second frame
- scoped_ptr<SpdyFrame> frame4(SpdyFramerTestUtil::DecompressFrame(
- &framer, *frame2.get()));
-
- // Expect frames 3 & 4 to be the same.
- EXPECT_EQ(0,
- memcmp(frame3->data(), frame4->data(),
- SpdyFrame::kHeaderSize + frame3->length()));
-
-
- // Expect frames 3 to be the same as a uncompressed frame created
- // from scratch.
- scoped_ptr<SpdySynStreamControlFrame>
- uncompressed_frame(framer.CreateSynStream(1, 0, 1, CONTROL_FLAG_NONE,
- false, &headers));
- EXPECT_EQ(frame3->length(), uncompressed_frame->length());
- EXPECT_EQ(0,
- memcmp(frame3->data(), uncompressed_frame->data(),
- SpdyFrame::kHeaderSize + uncompressed_frame->length()));
-}
-
-TEST_F(SpdyFramerSpdy2Test, Basic) {
- const unsigned char kV2Input[] = {
- 0x80, kVer, 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, kVer, 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, kVer, 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, kVer, 0x00, 0x03, // RST_STREAM on Stream #1
- 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00,
-
- 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
- 0x00, 0x00, 0x00, 0x00,
-
- 0x80, kVer, 0x00, 0x03, // RST_STREAM on Stream #3
- 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x00,
- };
-
- const unsigned char kV3Input[] = {
- 0x80, kVer, 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, kVer, 0x00, 0x08, // HEADERS on Stream #1
- 0x00, 0x00, 0x00, 0x22,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 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, kVer, 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, kVer, 0x00, 0x03, // RST_STREAM on Stream #1
- 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00,
-
- 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
- 0x00, 0x00, 0x00, 0x00,
-
- 0x80, kVer, 0x00, 0x03, // RST_STREAM on Stream #3
- 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x00,
- };
-
- TestSpdyVisitor visitor;
- if (SPDY_VERSION_FOR_TESTS < 3) {
- visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
- } else {
- visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
- }
-
- EXPECT_EQ(0, visitor.error_count_);
- EXPECT_EQ(2, visitor.syn_frame_count_);
- EXPECT_EQ(0, visitor.syn_reply_frame_count_);
- EXPECT_EQ(1, visitor.headers_frame_count_);
- EXPECT_EQ(24, visitor.data_bytes_);
- EXPECT_EQ(2, visitor.fin_frame_count_);
- EXPECT_EQ(0, visitor.fin_flag_count_);
- EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
- EXPECT_EQ(4, visitor.data_frame_count_);
-}
-
-// Test that the FIN flag on a data frame signifies EOF.
-TEST_F(SpdyFramerSpdy2Test, FinOnDataFrame) {
- const unsigned char kV2Input[] = {
- 0x80, kVer, 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, kVer, 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, kVer, 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, kVer, 0x00, 0x02, // SYN REPLY Stream #1
- 0x00, 0x00, 0x00, 0x16,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 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,
- };
-
- TestSpdyVisitor visitor;
- if (SPDY_VERSION_FOR_TESTS < 3) {
- visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
- } else {
- visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
- }
-
- EXPECT_EQ(0, visitor.error_count_);
- 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_F(SpdyFramerSpdy2Test, FinOnSynReplyFrame) {
- const unsigned char kV2Input[] = {
- 0x80, kVer, 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, kVer, 0x00, 0x02, // SYN REPLY Stream #1
- 0x01, 0x00, 0x00, 0x14,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x02, 'a', 'a',
- 0x00, 0x02, 'b', 'b',
- };
- const unsigned char kV3Input[] = {
- 0x80, kVer, 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, kVer, 0x00, 0x02, // SYN REPLY Stream #1
- 0x01, 0x00, 0x00, 0x1a,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x01, 0x00, 0x00,
- 0x00, 0x02, 'a', 'a',
- 0x00, 0x00, 0x00, 0x02,
- 'b', 'b',
- };
-
- TestSpdyVisitor visitor;
- if (SPDY_VERSION_FOR_TESTS < 3) {
- visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
- } else {
- visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
- }
-
- EXPECT_EQ(0, visitor.error_count_);
- 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_F(SpdyFramerSpdy2Test, HeaderCompression) {
- SpdyFramer send_framer(kVer);
- SpdyFramer recv_framer(kVer);
-
- 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;
- SpdyControlFlags flags(CONTROL_FLAG_NONE);
- scoped_ptr<SpdySynStreamControlFrame> syn_frame_1(
- send_framer.CreateSynStream(1, 0, 0, flags, true, &block));
- EXPECT_TRUE(syn_frame_1.get() != NULL);
-
- // SYN_STREAM #2
- block[kHeader3] = kValue3;
- scoped_ptr<SpdySynStreamControlFrame> syn_frame_2(
- send_framer.CreateSynStream(3, 0, 0, flags, true, &block));
- EXPECT_TRUE(syn_frame_2.get() != NULL);
-
- // Now start decompressing
- scoped_ptr<SpdyFrame> decompressed;
- scoped_ptr<SpdySynStreamControlFrame> syn_frame;
- scoped_ptr<std::string> serialized_headers;
- SpdyHeaderBlock decompressed_headers;
-
- // Decompress SYN_STREAM #1
- decompressed.reset(SpdyFramerTestUtil::DecompressFrame(
- &recv_framer, *syn_frame_1.get()));
- EXPECT_TRUE(decompressed.get() != NULL);
- EXPECT_TRUE(decompressed->is_control_frame());
- EXPECT_EQ(SYN_STREAM,
- reinterpret_cast<SpdyControlFrame*>(decompressed.get())->type());
- syn_frame.reset(new SpdySynStreamControlFrame(decompressed->data(), false));
- serialized_headers.reset(new std::string(syn_frame->header_block(),
- syn_frame->header_block_len()));
- EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers->c_str(),
- 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.get()));
- EXPECT_TRUE(decompressed.get() != NULL);
- EXPECT_TRUE(decompressed->is_control_frame());
- EXPECT_EQ(SYN_STREAM,
- reinterpret_cast<SpdyControlFrame*>(decompressed.get())->type());
- syn_frame.reset(new SpdySynStreamControlFrame(decompressed->data(), false));
- serialized_headers.reset(new std::string(syn_frame->header_block(),
- syn_frame->header_block_len()));
- decompressed_headers.clear();
- EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers->c_str(),
- 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]);
-
- // We didn't have data streams, so we shouldn't have (de)compressors.
- EXPECT_EQ(0, send_framer.num_stream_compressors());
- EXPECT_EQ(0, send_framer.num_stream_decompressors());
- EXPECT_EQ(0, recv_framer.num_stream_compressors());
- EXPECT_EQ(0, recv_framer.num_stream_decompressors());
-}
-
-// Verify we don't leak when we leave streams unclosed
-TEST_F(SpdyFramerSpdy2Test, UnclosedStreamDataCompressors) {
- SpdyFramer send_framer(kVer);
-
- send_framer.set_enable_compression(true);
-
- const char kHeader1[] = "header1";
- const char kHeader2[] = "header2";
- const char kValue1[] = "value1";
- const char kValue2[] = "value2";
-
- SpdyHeaderBlock block;
- block[kHeader1] = kValue1;
- block[kHeader2] = kValue2;
- SpdyControlFlags flags(CONTROL_FLAG_NONE);
- scoped_ptr<SpdyFrame> syn_frame(
- send_framer.CreateSynStream(1, 0, 0, flags, true, &block));
- EXPECT_TRUE(syn_frame.get() != NULL);
-
- const char bytes[] = "this is a test test test test test!";
- scoped_ptr<SpdyFrame> send_frame(
- send_framer.CreateDataFrame(
- 1, bytes, arraysize(bytes),
- static_cast<SpdyDataFlags>(DATA_FLAG_FIN)));
- EXPECT_TRUE(send_frame.get() != NULL);
-
- // Run the inputs through the framer.
- TestSpdyVisitor visitor;
- visitor.use_compression_ = true;
- const unsigned char* data;
- data = reinterpret_cast<const unsigned char*>(syn_frame->data());
- visitor.SimulateInFramer(data, syn_frame->length() + SpdyFrame::kHeaderSize);
- data = reinterpret_cast<const unsigned char*>(send_frame->data());
- visitor.SimulateInFramer(data, send_frame->length() + SpdyFrame::kHeaderSize);
-
- EXPECT_EQ(0, visitor.error_count_);
- EXPECT_EQ(1, visitor.syn_frame_count_);
- EXPECT_EQ(0, visitor.syn_reply_frame_count_);
- EXPECT_EQ(0, 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_);
-
- // We closed the streams, so all compressors should be down.
- EXPECT_EQ(0, visitor.framer_.num_stream_compressors());
- EXPECT_EQ(0, visitor.framer_.num_stream_decompressors());
- EXPECT_EQ(0, send_framer.num_stream_compressors());
- EXPECT_EQ(0, send_framer.num_stream_decompressors());
-}
-
-// Verify we can decompress the stream even if handed over to the
-// framer 1 byte at a time.
-TEST_F(SpdyFramerSpdy2Test, UnclosedStreamDataCompressorsOneByteAtATime) {
- SpdyFramer send_framer(kVer);
-
- send_framer.set_enable_compression(true);
-
- const char kHeader1[] = "header1";
- const char kHeader2[] = "header2";
- const char kValue1[] = "value1";
- const char kValue2[] = "value2";
-
- SpdyHeaderBlock block;
- block[kHeader1] = kValue1;
- block[kHeader2] = kValue2;
- SpdyControlFlags flags(CONTROL_FLAG_NONE);
- scoped_ptr<SpdyFrame> syn_frame(
- send_framer.CreateSynStream(1, 0, 0, flags, true, &block));
- EXPECT_TRUE(syn_frame.get() != NULL);
-
- const char bytes[] = "this is a test test test test test!";
- scoped_ptr<SpdyFrame> send_frame(
- send_framer.CreateDataFrame(
- 1, bytes, arraysize(bytes),
- static_cast<SpdyDataFlags>(DATA_FLAG_FIN)));
- EXPECT_TRUE(send_frame.get() != NULL);
-
- // Run the inputs through the framer.
- TestSpdyVisitor visitor;
- visitor.use_compression_ = true;
- const unsigned char* data;
- data = reinterpret_cast<const unsigned char*>(syn_frame->data());
- for (size_t idx = 0;
- idx < syn_frame->length() + SpdyFrame::kHeaderSize;
- ++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->length() + SpdyFrame::kHeaderSize;
- ++idx) {
- visitor.SimulateInFramer(data + idx, 1);
- ASSERT_EQ(0, visitor.error_count_);
- }
-
- EXPECT_EQ(0, visitor.error_count_);
- EXPECT_EQ(1, visitor.syn_frame_count_);
- EXPECT_EQ(0, visitor.syn_reply_frame_count_);
- EXPECT_EQ(0, 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_);
-
- // We closed the streams, so all compressors should be down.
- EXPECT_EQ(0, visitor.framer_.num_stream_compressors());
- EXPECT_EQ(0, visitor.framer_.num_stream_decompressors());
- EXPECT_EQ(0, send_framer.num_stream_compressors());
- EXPECT_EQ(0, send_framer.num_stream_decompressors());
-}
-
-TEST_F(SpdyFramerSpdy2Test, WindowUpdateFrame) {
- SpdyFramer framer(kVer);
- scoped_ptr<SpdyWindowUpdateControlFrame> window_update_frame(
- framer.CreateWindowUpdate(1, 0x12345678));
-
- const unsigned char expected_data_frame[] = {
- 0x80, kVer, 0x00, 0x09,
- 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x01,
- 0x12, 0x34, 0x56, 0x78
- };
-
- EXPECT_EQ(16u, window_update_frame->size());
- EXPECT_EQ(0,
- memcmp(window_update_frame->data(), expected_data_frame, 16));
-}
-
-TEST_F(SpdyFramerSpdy2Test, CreateDataFrame) {
- SpdyFramer framer(kVer);
-
- {
- const char kDescription[] = "'hello' data frame, no FIN";
- const unsigned char kFrameData[] = {
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x05,
- 'h', 'e', 'l', 'l',
- 'o'
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
- 1, "hello", 5, DATA_FLAG_NONE));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
- }
-
- {
- const char kDescription[] = "Data frame with negative data byte, no FIN";
- const unsigned char kFrameData[] = {
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x01,
- 0xff
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
- 1, "\xff", 1, DATA_FLAG_NONE));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
- }
-
- {
- const char kDescription[] = "'hello' data frame, with FIN";
- const unsigned char kFrameData[] = {
- 0x00, 0x00, 0x00, 0x01,
- 0x01, 0x00, 0x00, 0x05,
- 'h', 'e', 'l', 'l',
- 'o'
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
- 1, "hello", 5, DATA_FLAG_FIN));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
- }
-
- {
- const char kDescription[] = "Empty data frame";
- const unsigned char kFrameData[] = {
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00,
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
- 1, "", 0, DATA_FLAG_NONE));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
- }
-
- {
- const char kDescription[] = "Data frame with max stream ID";
- const unsigned char kFrameData[] = {
- 0x7f, 0xff, 0xff, 0xff,
- 0x01, 0x00, 0x00, 0x05,
- 'h', 'e', 'l', 'l',
- 'o'
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
- 0x7fffffff, "hello", 5, DATA_FLAG_FIN));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
- }
-
- {
- const char kDescription[] = "Large data frame";
- const int kDataSize = 4 * 1024 * 1024; // 4 MB
- const std::string kData(kDataSize, 'A');
- const unsigned char kFrameHeader[] = {
- 0x00, 0x00, 0x00, 0x01,
- 0x01, 0x40, 0x00, 0x00,
- };
-
- const int kFrameSize = arraysize(kFrameHeader) + kDataSize;
- scoped_array<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);
-
- scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
- 1, kData.data(), kData.size(), DATA_FLAG_FIN));
- CompareFrame(kDescription, *frame, expected_frame_data.get(), kFrameSize);
- }
-}
-
-TEST_F(SpdyFramerSpdy2Test, CreateSynStreamUncompressed) {
- SpdyFramer framer(kVer);
- framer.set_enable_compression(false);
-
- {
- const char kDescription[] = "SYN_STREAM frame, lowest pri, no FIN";
-
- SpdyHeaderBlock headers;
- headers["bar"] = "foo";
- headers["foo"] = "bar";
-
- const unsigned char kPri =
- (SPDY_VERSION_FOR_TESTS != 2) ? 0xE0 : 0xC0;
- const unsigned char kV2FrameData[] = {
- 0x80, kVer, 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, kVer, 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'
- };
- scoped_ptr<SpdySynStreamControlFrame> frame(framer.CreateSynStream(
- 1, 0, framer.GetLowestPriority(), CONTROL_FLAG_NONE, false, &headers));
- CompareFrame(kDescription,
- *frame,
- (SPDY_VERSION_FOR_TESTS < 3) ? kV2FrameData : kV3FrameData,
- (SPDY_VERSION_FOR_TESTS < 3) ? arraysize(kV2FrameData)
- : arraysize(kV3FrameData));
- EXPECT_EQ(1u, SpdyFramer::GetControlFrameStreamId(frame.get()));
- }
-
- {
- const char kDescription[] =
- "SYN_STREAM frame with a 0-length header name, highest pri, FIN, "
- "max stream ID";
-
- SpdyHeaderBlock headers;
- headers[""] = "foo";
- headers["foo"] = "bar";
-
- const unsigned char kV2FrameData[] = {
- 0x80, kVer, 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, kVer, 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'
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateSynStream(
- 0x7fffffff, 0x7fffffff, framer.GetHighestPriority(), CONTROL_FLAG_FIN,
- false, &headers));
- CompareFrame(kDescription,
- *frame,
- (SPDY_VERSION_FOR_TESTS < 3) ? kV2FrameData : kV3FrameData,
- (SPDY_VERSION_FOR_TESTS < 3) ? arraysize(kV2FrameData)
- : arraysize(kV3FrameData));
- }
-
- {
- const char kDescription[] =
- "SYN_STREAM frame with a 0-length header val, high pri, FIN, "
- "max stream ID";
-
- SpdyHeaderBlock headers;
- headers["bar"] = "foo";
- headers["foo"] = "";
-
- const unsigned char kPri =
- (SPDY_VERSION_FOR_TESTS != 2) ? 0x20 : 0x40;
- const unsigned char kV2FrameData[] = {
- 0x80, kVer, 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, kVer, 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
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateSynStream(
- 0x7fffffff, 0x7fffffff, 1, CONTROL_FLAG_FIN, false, &headers));
- CompareFrame(kDescription,
- *frame,
- (SPDY_VERSION_FOR_TESTS < 3) ? kV2FrameData : kV3FrameData,
- (SPDY_VERSION_FOR_TESTS < 3) ? arraysize(kV2FrameData)
- : arraysize(kV3FrameData));
- }
-}
-
-TEST_F(SpdyFramerSpdy2Test, CreateSynStreamCompressed) {
- SpdyFramer framer(kVer);
- framer.set_enable_compression(true);
-
- {
- const char kDescription[] =
- "SYN_STREAM frame, low pri, no FIN";
-
- SpdyHeaderBlock headers;
- headers["bar"] = "foo";
- headers["foo"] = "bar";
-
- const SpdyPriority priority =
- (SPDY_VERSION_FOR_TESTS != 2) ? 4 : 2;
- const unsigned char kV2FrameData[] = {
- 0x80, kVer, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x25,
- 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, 0x4e, 0xcb, 0xcf,
- 0x87, 0x12, 0x40, 0x2e,
- 0x00, 0x00, 0x00, 0xff,
- 0xff
- };
- const unsigned char kV3FrameData[] = {
- 0x80, kVer, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x27,
- 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, 0xE6, 0xB4,
- 0xFC, 0x7C, 0x24, 0x0A,
- 0x28, 0x08, 0x00, 0x00,
- 0x00, 0xFF, 0xFF
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateSynStream(
- 1, 0, priority, CONTROL_FLAG_NONE, true, &headers));
- CompareFrame(kDescription,
- *frame,
- (SPDY_VERSION_FOR_TESTS < 3) ? kV2FrameData : kV3FrameData,
- (SPDY_VERSION_FOR_TESTS < 3) ? arraysize(kV2FrameData)
- : arraysize(kV3FrameData));
- }
-}
-
-TEST_F(SpdyFramerSpdy2Test, CreateSynReplyUncompressed) {
- SpdyFramer framer(kVer);
- framer.set_enable_compression(false);
-
- {
- const char kDescription[] = "SYN_REPLY frame, no FIN";
-
- SpdyHeaderBlock headers;
- headers["bar"] = "foo";
- headers["foo"] = "bar";
-
- const unsigned char kV2FrameData[] = {
- 0x80, kVer, 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, kVer, 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'
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateSynReply(
- 1, CONTROL_FLAG_NONE, false, &headers));
- CompareFrame(kDescription,
- *frame,
- (SPDY_VERSION_FOR_TESTS < 3) ? kV2FrameData : kV3FrameData,
- (SPDY_VERSION_FOR_TESTS < 3) ? arraysize(kV2FrameData)
- : arraysize(kV3FrameData));
- }
-
- {
- const char kDescription[] =
- "SYN_REPLY frame with a 0-length header name, FIN, max stream ID";
-
- SpdyHeaderBlock headers;
- headers[""] = "foo";
- headers["foo"] = "bar";
-
- const unsigned char kV2FrameData[] = {
- 0x80, kVer, 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, kVer, 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'
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateSynReply(
- 0x7fffffff, CONTROL_FLAG_FIN, false, &headers));
- CompareFrame(kDescription,
- *frame,
- (SPDY_VERSION_FOR_TESTS < 3) ? kV2FrameData : kV3FrameData,
- (SPDY_VERSION_FOR_TESTS < 3) ? arraysize(kV2FrameData)
- : arraysize(kV3FrameData));
- }
-
- {
- const char kDescription[] =
- "SYN_REPLY frame with a 0-length header val, FIN, max stream ID";
-
- SpdyHeaderBlock headers;
- headers["bar"] = "foo";
- headers["foo"] = "";
-
- const unsigned char kV2FrameData[] = {
- 0x80, kVer, 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, kVer, 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
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateSynReply(
- 0x7fffffff, CONTROL_FLAG_FIN, false, &headers));
- CompareFrame(kDescription,
- *frame,
- (SPDY_VERSION_FOR_TESTS < 3) ? kV2FrameData : kV3FrameData,
- (SPDY_VERSION_FOR_TESTS < 3) ? arraysize(kV2FrameData)
- : arraysize(kV3FrameData));
- }
-}
-
-TEST_F(SpdyFramerSpdy2Test, CreateSynReplyCompressed) {
- SpdyFramer framer(kVer);
- framer.set_enable_compression(true);
-
- {
- const char kDescription[] = "SYN_REPLY frame, no FIN";
-
- SpdyHeaderBlock headers;
- headers["bar"] = "foo";
- headers["foo"] = "bar";
-
- const unsigned char kV2FrameData[] = {
- 0x80, kVer, 0x00, 0x02,
- 0x00, 0x00, 0x00, 0x21,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x38, 0xea,
- 0xdf, 0xa2, 0x51, 0xb2,
- 0x62, 0x60, 0x62, 0x60,
- 0x4e, 0x4a, 0x2c, 0x62,
- 0x60, 0x4e, 0xcb, 0xcf,
- 0x87, 0x12, 0x40, 0x2e,
- 0x00, 0x00, 0x00, 0xff,
- 0xff
- };
- const unsigned char kV3FrameData[] = {
- 0x80, kVer, 0x00, 0x02,
- 0x00, 0x00, 0x00, 0x21,
- 0x00, 0x00, 0x00, 0x01,
- 0x38, 0xea, 0xe3, 0xc6,
- 0xa7, 0xc2, 0x02, 0xe5,
- 0x0e, 0x50, 0xc2, 0x4b,
- 0x4a, 0x04, 0xe5, 0x0b,
- 0xe6, 0xb4, 0xfc, 0x7c,
- 0x24, 0x0a, 0x28, 0x08,
- 0x00, 0x00, 0x00, 0xff,
- 0xff
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateSynReply(
- 1, CONTROL_FLAG_NONE, true, &headers));
- CompareFrame(kDescription,
- *frame,
- (SPDY_VERSION_FOR_TESTS < 3) ? kV2FrameData : kV3FrameData,
- (SPDY_VERSION_FOR_TESTS < 3) ? arraysize(kV2FrameData)
- : arraysize(kV3FrameData));
- }
-}
-
-TEST_F(SpdyFramerSpdy2Test, CreateRstStream) {
- SpdyFramer framer(kVer);
-
- {
- const char kDescription[] = "RST_STREAM frame";
- const unsigned char kFrameData[] = {
- 0x80, kVer, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x01,
- };
- scoped_ptr<SpdyRstStreamControlFrame> frame(
- framer.CreateRstStream(1, PROTOCOL_ERROR));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
- EXPECT_EQ(1u, SpdyFramer::GetControlFrameStreamId(frame.get()));
- }
-
- {
- const char kDescription[] = "RST_STREAM frame with max stream ID";
- const unsigned char kFrameData[] = {
- 0x80, kVer, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x08,
- 0x7f, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x01,
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateRstStream(0x7FFFFFFF,
- PROTOCOL_ERROR));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
- }
-
- {
- const char kDescription[] = "RST_STREAM frame with max status code";
- const unsigned char kFrameData[] = {
- 0x80, kVer, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x08,
- 0x7f, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x06,
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateRstStream(0x7FFFFFFF,
- INTERNAL_ERROR));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
- }
-}
-
-TEST_F(SpdyFramerSpdy2Test, CreateSettings) {
- SpdyFramer framer(kVer);
-
- {
- const char kDescription[] = "Network byte order SETTINGS frame";
-
- uint32 kValue = 0x0a0b0c0d;
- uint8 kFlags = 0x04;
- uint32 kId = 0x030201;
- SettingsFlagsAndId idAndFlags(kFlags, kId);
-
- SpdySettings settings;
- settings.push_back(SpdySetting(idAndFlags, kValue));
-
- EXPECT_EQ(kValue, settings.back().second);
- EXPECT_EQ(kFlags, settings.back().first.flags());
- EXPECT_EQ(kId, settings.back().first.id());
-
- const unsigned char kFrameDatav2[] = {
- 0x80, kVer, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x0c,
- 0x00, 0x00, 0x00, 0x01,
- 0x01, 0x02, 0x03, 0x04,
- 0x0a, 0x0b, 0x0c, 0x0d,
- };
-
- const unsigned char kFrameDatav3[] = {
- 0x80, kVer, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x0c,
- 0x00, 0x00, 0x00, 0x01,
- 0x04, 0x03, 0x02, 0x01,
- 0x0a, 0x0b, 0x0c, 0x0d,
- };
-
- scoped_ptr<SpdySettingsControlFrame> frame(framer.CreateSettings(settings));
- CompareFrame(kDescription,
- *frame,
- (SPDY_VERSION_FOR_TESTS < 3) ? kFrameDatav2 : kFrameDatav3,
- arraysize(kFrameDatav3)); // Size is unchanged among versions.
- EXPECT_EQ(SpdyFramer::kInvalidStream,
- SpdyFramer::GetControlFrameStreamId(frame.get()));
-
- // Make sure that ParseSettings also works as advertised.
- SpdySettings parsed_settings;
- EXPECT_TRUE(framer.ParseSettings(frame.get(), &parsed_settings));
- EXPECT_EQ(settings.size(), parsed_settings.size());
- EXPECT_EQ(kFlags, parsed_settings.back().first.flags());
- EXPECT_EQ(kId, parsed_settings.back().first.id());
- }
-
- {
- const char kDescription[] = "Basic SETTINGS frame";
-
- SpdySettings settings;
- settings.push_back(
- SpdySettingFromWireFormat(0x00000000, 0x00000000)); // 1st Setting
- settings.push_back(
- SpdySettingFromWireFormat(0xffffffff, 0x00000001)); // 2nd Setting
- settings.push_back(
- SpdySettingFromWireFormat(0xff000001, 0x00000002)); // 3rd Setting
-
- // Duplicates allowed
- settings.push_back(
- SpdySettingFromWireFormat(0x01000002, 0x00000003)); // 4th Setting
- settings.push_back(
- SpdySettingFromWireFormat(0x01000002, 0x00000003)); // 5th Setting
-
- settings.push_back(
- SpdySettingFromWireFormat(0x01000003, 0x000000ff)); // 6th Setting
- settings.push_back(
- SpdySettingFromWireFormat(0x01000004, 0xff000001)); // 7th Setting
- settings.push_back(
- SpdySettingFromWireFormat(0x01000004, 0xffffffff)); // 8th Setting
-
- const unsigned char kFrameData[] = {
- 0x80, kVer, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x44,
- 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x00, // 1st Setting
- 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, // 2nd Setting
- 0x00, 0x00, 0x00, 0x01,
- 0x01, 0x00, 0x00, 0xff, // 3rd Setting
- 0x00, 0x00, 0x00, 0x02,
- 0x02, 0x00, 0x00, 0x01, // 4th Setting
- 0x00, 0x00, 0x00, 0x03,
- 0x02, 0x00, 0x00, 0x01, // 5th Setting
- 0x00, 0x00, 0x00, 0x03,
- 0x03, 0x00, 0x00, 0x01, // 6th Setting
- 0x00, 0x00, 0x00, 0xff,
- 0x04, 0x00, 0x00, 0x01, // 7th Setting
- 0xff, 0x00, 0x00, 0x01,
- 0x04, 0x00, 0x00, 0x01, // 8th Setting
- 0xff, 0xff, 0xff, 0xff,
- };
- scoped_ptr<SpdySettingsControlFrame> frame(framer.CreateSettings(settings));
- CompareFrame(kDescription,
- *frame,
- kFrameData,
- arraysize(kFrameData));
- EXPECT_EQ(SpdyFramer::kInvalidStream,
- SpdyFramer::GetControlFrameStreamId(frame.get()));
- }
-
- {
- const char kDescription[] = "Empty SETTINGS frame";
-
- SpdySettings settings;
-
- const unsigned char kFrameData[] = {
- 0x80, kVer, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x00,
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateSettings(settings));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
- }
-}
-
-TEST_F(SpdyFramerSpdy2Test, CreatePingFrame) {
- SpdyFramer framer(kVer);
-
- {
- const char kDescription[] = "PING frame";
- const unsigned char kFrameData[] = {
- 0x80, kVer, 0x00, 0x06,
- 0x00, 0x00, 0x00, 0x04,
- 0x12, 0x34, 0x56, 0x78,
- };
- scoped_ptr<SpdyPingControlFrame> frame(framer.CreatePingFrame(0x12345678u));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
- EXPECT_EQ(SpdyFramer::kInvalidStream,
- SpdyFramer::GetControlFrameStreamId(frame.get()));
- }
-}
-
-TEST_F(SpdyFramerSpdy2Test, CreateGoAway) {
- SpdyFramer framer(kVer);
-
- {
- const char kDescription[] = "GOAWAY frame";
- const unsigned char kFrameData[] = {
- 0x80, kVer, 0x00, 0x07,
- 0x00, 0x00, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x00,
- };
- scoped_ptr<SpdyGoAwayControlFrame> frame(framer.CreateGoAway(0));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
- EXPECT_EQ(SpdyFramer::kInvalidStream,
- SpdyFramer::GetControlFrameStreamId(frame.get()));
- }
-
- {
- const char kDescription[] = "GOAWAY frame with max stream ID";
- const unsigned char kFrameData[] = {
- 0x80, kVer, 0x00, 0x07,
- 0x00, 0x00, 0x00, 0x04,
- 0x7f, 0xff, 0xff, 0xff,
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateGoAway(0x7FFFFFFF));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
- }
-}
-
-TEST_F(SpdyFramerSpdy2Test, CreateHeadersUncompressed) {
- SpdyFramer framer(kVer);
- framer.set_enable_compression(false);
-
- {
- const char kDescription[] = "HEADERS frame, no FIN";
-
- SpdyHeaderBlock headers;
- headers["bar"] = "foo";
- headers["foo"] = "bar";
-
- const unsigned char kV2FrameData[] = {
- 0x80, kVer, 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, kVer, 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'
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateHeaders(
- 1, CONTROL_FLAG_NONE, false, &headers));
- CompareFrame(kDescription,
- *frame,
- (SPDY_VERSION_FOR_TESTS < 3) ? kV2FrameData : kV3FrameData,
- (SPDY_VERSION_FOR_TESTS < 3) ? arraysize(kV2FrameData)
- : arraysize(kV3FrameData));
- }
-
- {
- const char kDescription[] =
- "HEADERS frame with a 0-length header name, FIN, max stream ID";
-
- SpdyHeaderBlock headers;
- headers[""] = "foo";
- headers["foo"] = "bar";
-
- const unsigned char kV2FrameData[] = {
- 0x80, kVer, 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, kVer, 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'
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateHeaders(
- 0x7fffffff, CONTROL_FLAG_FIN, false, &headers));
- CompareFrame(kDescription,
- *frame,
- (SPDY_VERSION_FOR_TESTS < 3) ? kV2FrameData : kV3FrameData,
- (SPDY_VERSION_FOR_TESTS < 3) ? arraysize(kV2FrameData)
- : arraysize(kV3FrameData));
- }
-
- {
- const char kDescription[] =
- "HEADERS frame with a 0-length header val, FIN, max stream ID";
-
- SpdyHeaderBlock headers;
- headers["bar"] = "foo";
- headers["foo"] = "";
-
- const unsigned char kV2FrameData[] = {
- 0x80, kVer, 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, kVer, 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
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateHeaders(
- 0x7fffffff, CONTROL_FLAG_FIN, false, &headers));
- CompareFrame(kDescription,
- *frame,
- (SPDY_VERSION_FOR_TESTS < 3) ? kV2FrameData : kV3FrameData,
- (SPDY_VERSION_FOR_TESTS < 3) ? arraysize(kV2FrameData)
- : arraysize(kV3FrameData));
- }
-}
-
-TEST_F(SpdyFramerSpdy2Test, CreateHeadersCompressed) {
- SpdyFramer framer(kVer);
- framer.set_enable_compression(true);
-
- {
- const char kDescription[] = "HEADERS frame, no FIN";
-
- SpdyHeaderBlock headers;
- headers["bar"] = "foo";
- headers["foo"] = "bar";
-
- const unsigned char kV2FrameData[] = {
- 0x80, kVer, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x21,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x38, 0xea,
- 0xdf, 0xa2, 0x51, 0xb2,
- 0x62, 0x60, 0x62, 0x60,
- 0x4e, 0x4a, 0x2c, 0x62,
- 0x60, 0x4e, 0xcb, 0xcf,
- 0x87, 0x12, 0x40, 0x2e,
- 0x00, 0x00, 0x00, 0xff,
- 0xff
- };
- const unsigned char kV3FrameData[] = {
- 0x80, kVer, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x21,
- 0x00, 0x00, 0x00, 0x01,
- 0x38, 0xea, 0xe3, 0xc6,
- 0xa7, 0xc2, 0x02, 0xe5,
- 0x0e, 0x50, 0xc2, 0x4b,
- 0x4a, 0x04, 0xe5, 0x0b,
- 0xe6, 0xb4, 0xfc, 0x7c,
- 0x24, 0x0a, 0x28, 0x08,
- 0x00, 0x00, 0x00, 0xff,
- 0xff
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateHeaders(
- 1, CONTROL_FLAG_NONE, true, &headers));
- CompareFrame(kDescription,
- *frame,
- (SPDY_VERSION_FOR_TESTS < 3) ? kV2FrameData : kV3FrameData,
- (SPDY_VERSION_FOR_TESTS < 3) ? arraysize(kV2FrameData)
- : arraysize(kV3FrameData));
- }
-}
-
-TEST_F(SpdyFramerSpdy2Test, CreateWindowUpdate) {
- SpdyFramer framer(kVer);
-
- {
- const char kDescription[] = "WINDOW_UPDATE frame";
- const unsigned char kFrameData[] = {
- 0x80, kVer, 0x00, 0x09,
- 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x01,
- };
- scoped_ptr<SpdyWindowUpdateControlFrame> frame(
- framer.CreateWindowUpdate(1, 1));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
- EXPECT_EQ(1u, SpdyFramer::GetControlFrameStreamId(frame.get()));
- }
-
- {
- const char kDescription[] = "WINDOW_UPDATE frame with max stream ID";
- const unsigned char kFrameData[] = {
- 0x80, kVer, 0x00, 0x09,
- 0x00, 0x00, 0x00, 0x08,
- 0x7f, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x01,
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateWindowUpdate(0x7FFFFFFF, 1));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
- }
-
- {
- const char kDescription[] = "WINDOW_UPDATE frame with max window delta";
- const unsigned char kFrameData[] = {
- 0x80, kVer, 0x00, 0x09,
- 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x01,
- 0x7f, 0xff, 0xff, 0xff,
- };
- scoped_ptr<SpdyFrame> frame(framer.CreateWindowUpdate(1, 0x7FFFFFFF));
- CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
- }
-}
-
-TEST_F(SpdyFramerSpdy2Test, DuplicateFrame) {
- SpdyFramer framer(kVer);
-
- {
- const char kDescription[] = "PING frame";
- const unsigned char kFrameData[] = {
- 0x80, kVer, 0x00, 0x06,
- 0x00, 0x00, 0x00, 0x04,
- 0x12, 0x34, 0x56, 0x78,
- };
- scoped_ptr<SpdyFrame> frame1(framer.CreatePingFrame(0x12345678u));
- CompareFrame(kDescription, *frame1, kFrameData, arraysize(kFrameData));
-
- scoped_ptr<SpdyFrame> frame2(framer.DuplicateFrame(*frame1));
- CompareFrame(kDescription, *frame2, kFrameData, arraysize(kFrameData));
- }
-}
-
-// This test case reproduces conditions that caused ExpandControlFrameBuffer to
-// fail to expand the buffer control frame buffer when it should have, allowing
-// the framer to overrun the buffer, and smash other heap contents. This test
-// relies on the debug version of the heap manager, which checks for buffer
-// overrun errors during delete processing. Regression test for b/2974814.
-TEST_F(SpdyFramerSpdy2Test, ExpandBuffer_HeapSmash) {
- // Sweep through the area of problematic values, to make sure we always cover
- // the danger zone, even if it moves around at bit due to SPDY changes.
- for (uint16 val2_len = SpdyFramer::kControlFrameBufferInitialSize - 50;
- val2_len < SpdyFramer::kControlFrameBufferInitialSize;
- val2_len++) {
- std::string val2 = std::string(val2_len, 'a');
- SpdyHeaderBlock headers;
- headers["bar"] = "foo";
- headers["foo"] = "baz";
- headers["grue"] = val2.c_str();
- SpdyFramer framer(kVer);
- scoped_ptr<SpdySynStreamControlFrame> template_frame(
- framer.CreateSynStream(1, // stream_id
- 0, // associated_stream_id
- 1, // priority
- CONTROL_FLAG_NONE,
- false, // compress
- &headers));
- EXPECT_TRUE(template_frame.get() != NULL);
- TestSpdyVisitor visitor;
- visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(template_frame.get()->data()),
- template_frame.get()->length() + SpdyControlFrame::kHeaderSize);
- EXPECT_EQ(1, visitor.syn_frame_count_);
- }
-}
-
-TEST_F(SpdyFramerSpdy2Test, ControlFrameSizesAreValidated) {
- // Create a GoAway frame that has a few extra bytes at the end.
- // We create enough overhead to require the framer to expand its frame buffer.
- size_t overhead = SpdyFramer::kUncompressedControlFrameBufferInitialSize;
- SpdyFramer framer(kVer);
- scoped_ptr<SpdyGoAwayControlFrame> goaway(framer.CreateGoAway(1));
- goaway->set_length(goaway->length() + overhead);
- std::string pad('A', overhead);
- TestSpdyVisitor visitor;
-
- // First attempt without validation on.
- visitor.framer_.set_validate_control_frame_sizes(false);
- visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(goaway->data()),
- goaway->length() - overhead + SpdyControlFrame::kHeaderSize);
- visitor.SimulateInFramer(
- reinterpret_cast<const unsigned char*>(pad.c_str()),
- overhead);
- EXPECT_EQ(0, visitor.error_count_); // Not an error.
- EXPECT_EQ(1, visitor.goaway_count_); // The goaway was parsed.
-
- // Attempt with validation on.
- visitor.framer_.set_validate_control_frame_sizes(true);
- visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(goaway->data()),
- goaway->length() - overhead + SpdyControlFrame::kHeaderSize);
- visitor.SimulateInFramer(
- reinterpret_cast<const unsigned char*>(pad.c_str()),
- overhead);
- EXPECT_EQ(1, visitor.error_count_); // This generated an error.
- EXPECT_EQ(1, visitor.goaway_count_); // Unchanged from before.
-}
-
-TEST_F(SpdyFramerSpdy2Test, ReadZeroLenSettingsFrame) {
- SpdyFramer framer(kVer);
- SpdySettings settings;
- scoped_ptr<SpdyFrame> control_frame(framer.CreateSettings(settings));
- control_frame->set_length(0);
- TestSpdyVisitor visitor;
- visitor.use_compression_ = false;
- visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame->data()),
- control_frame.get()->length() + SpdyControlFrame::kHeaderSize);
- // Should generate an error, since zero-len settings frames are unsupported.
- EXPECT_EQ(1, visitor.error_count_);
-}
-
-// Tests handling of SETTINGS frames with invalid length.
-TEST_F(SpdyFramerSpdy2Test, ReadBogusLenSettingsFrame) {
- SpdyFramer framer(kVer);
- SpdySettings settings;
- // Add a setting to pad the frame so that we don't get a buffer overflow when
- // calling SimulateInFramer() below.
- settings.push_back(SpdySetting(SettingsFlagsAndId(0, 1), 0x00000002));
- scoped_ptr<SpdyFrame> control_frame(framer.CreateSettings(settings));
- control_frame->set_length(5);
- TestSpdyVisitor visitor;
- visitor.use_compression_ = false;
- visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame->data()),
- control_frame.get()->length() + SpdyControlFrame::kHeaderSize);
- // Should generate an error, since zero-len settings frames are unsupported.
- EXPECT_EQ(1, visitor.error_count_);
-}
-
-// Tests handling of SETTINGS frames larger than the frame buffer size.
-TEST_F(SpdyFramerSpdy2Test, ReadLargeSettingsFrame) {
- SpdyFramer framer(kVer);
- SpdySettings settings;
- settings.push_back(SpdySetting(SettingsFlagsAndId(0, 1), 0x00000002));
- settings.push_back(SpdySetting(SettingsFlagsAndId(0, 2), 0x00000003));
- settings.push_back(SpdySetting(SettingsFlagsAndId(0, 3), 0x00000004));
- scoped_ptr<SpdyFrame> control_frame(framer.CreateSettings(settings));
- EXPECT_LT(SpdyFramer::kUncompressedControlFrameBufferInitialSize,
- control_frame->length() + SpdyControlFrame::kHeaderSize);
- TestSpdyVisitor visitor;
- visitor.use_compression_ = false;
-
- // Read all at once.
- visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame->data()),
- control_frame->length() + SpdyControlFrame::kHeaderSize);
- EXPECT_EQ(0, visitor.error_count_);
- EXPECT_EQ(settings.size(), static_cast<unsigned>(visitor.setting_count_));
- EXPECT_EQ(1, visitor.settings_frame_count_);
-
- // Read data in small chunks.
- size_t framed_data = 0;
- size_t unframed_data = control_frame->length() +
- SpdyControlFrame::kHeaderSize;
- 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(settings.size() * 2, static_cast<unsigned>(visitor.setting_count_));
- EXPECT_EQ(2, visitor.settings_frame_count_);
-}
-
-// Tests handling of SETTINGS frame with duplicate entries.
-TEST_F(SpdyFramerSpdy2Test, ReadDuplicateSettings) {
- SpdyFramer framer(kVer);
- SpdySettings settings;
- settings.push_back(SpdySetting(SettingsFlagsAndId(0, 1), 0x00000002));
- settings.push_back(SpdySetting(SettingsFlagsAndId(0, 1), 0x00000003));
- // This last setting should not be processed due to error above.
- settings.push_back(SpdySetting(SettingsFlagsAndId(0, 3), 0x00000003));
- scoped_ptr<SpdyFrame> control_frame(framer.CreateSettings(settings));
- TestSpdyVisitor visitor;
- visitor.use_compression_ = false;
-
- visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame->data()),
- control_frame->length() + SpdyControlFrame::kHeaderSize);
- EXPECT_EQ(1, visitor.error_count_);
- EXPECT_EQ(1, visitor.setting_count_);
- EXPECT_EQ(1, visitor.settings_frame_count_);
-}
-
-// Tests handling of SETTINGS frame with entries out of order.
-TEST_F(SpdyFramerSpdy2Test, ReadOutOfOrderSettings) {
- SpdyFramer framer(kVer);
- SpdySettings settings;
- settings.push_back(SpdySetting(SettingsFlagsAndId(0, 2), 0x00000002));
- settings.push_back(SpdySetting(SettingsFlagsAndId(0, 1), 0x00000003));
- // This last setting should not be processed due to error above.
- settings.push_back(SpdySetting(SettingsFlagsAndId(0, 3), 0x00000003));
- scoped_ptr<SpdyFrame> control_frame(framer.CreateSettings(settings));
- TestSpdyVisitor visitor;
- visitor.use_compression_ = false;
-
- visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame->data()),
- control_frame->length() + SpdyControlFrame::kHeaderSize);
- EXPECT_EQ(1, visitor.error_count_);
- EXPECT_EQ(1, visitor.setting_count_);
- EXPECT_EQ(1, visitor.settings_frame_count_);
-}
-
-TEST_F(SpdyFramerSpdy2Test, ReadCredentialFrame) {
- SpdyCredential credential;
- credential.slot = 3;
- credential.proof = "proof";
- credential.certs.push_back("a cert");
- credential.certs.push_back("another cert");
- credential.certs.push_back("final cert");
- SpdyFramer framer(kVer);
- scoped_ptr<SpdyFrame> control_frame(
- framer.CreateCredentialFrame(credential));
- EXPECT_TRUE(control_frame.get() != NULL);
- TestSpdyVisitor visitor;
- visitor.use_compression_ = false;
- visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame.get()->data()),
- control_frame.get()->length() + SpdyControlFrame::kHeaderSize);
- EXPECT_EQ(0, visitor.error_count_);
- EXPECT_EQ(1, visitor.credential_count_);
- EXPECT_EQ(control_frame->length(), visitor.credential_buffer_length_);
- EXPECT_EQ(credential.slot, visitor.credential_.slot);
- EXPECT_EQ(credential.proof, visitor.credential_.proof);
- EXPECT_EQ(credential.certs.size(), visitor.credential_.certs.size());
- for (size_t i = 0; i < credential.certs.size(); i++) {
- EXPECT_EQ(credential.certs[i], visitor.credential_.certs[i]);
- }
-}
-
-TEST_F(SpdyFramerSpdy2Test, ReadCredentialFrameWithCorruptProof) {
- SpdyCredential credential;
- credential.slot = 3;
- credential.proof = "proof";
- credential.certs.push_back("a cert");
- credential.certs.push_back("another cert");
- credential.certs.push_back("final cert");
- SpdyFramer framer(kVer);
- scoped_ptr<SpdyFrame> control_frame(
- framer.CreateCredentialFrame(credential));
- EXPECT_TRUE(control_frame.get() != NULL);
- TestSpdyVisitor visitor;
- visitor.use_compression_ = false;
- unsigned char* data =
- reinterpret_cast<unsigned char*>(control_frame.get()->data());
- size_t offset = SpdyControlFrame::kHeaderSize + 4;
- data[offset] = 0xFF; // Proof length is past the end of the frame
- visitor.SimulateInFramer(
- data, control_frame.get()->length() + SpdyControlFrame::kHeaderSize);
- EXPECT_EQ(1, visitor.error_count_);
-}
-
-TEST_F(SpdyFramerSpdy2Test, ReadCredentialFrameWithCorruptCertificate) {
- SpdyCredential credential;
- credential.slot = 3;
- credential.proof = "proof";
- credential.certs.push_back("a cert");
- credential.certs.push_back("another cert");
- credential.certs.push_back("final cert");
- SpdyFramer framer(kVer);
- scoped_ptr<SpdyFrame> control_frame(
- framer.CreateCredentialFrame(credential));
- EXPECT_TRUE(control_frame.get() != NULL);
- TestSpdyVisitor visitor;
- visitor.use_compression_ = false;
- unsigned char* data =
- reinterpret_cast<unsigned char*>(control_frame.get()->data());
- size_t offset = SpdyControlFrame::kHeaderSize + credential.proof.length();
- data[offset] = 0xFF; // Certificate length is past the end of the frame
- visitor.SimulateInFramer(
- data, control_frame.get()->length() + SpdyControlFrame::kHeaderSize);
- EXPECT_EQ(1, visitor.error_count_);
-}
-
-TEST_F(SpdyFramerSpdy2Test, ReadGarbage) {
- SpdyFramer framer(kVer);
- unsigned char garbage_frame[256];
- memset(garbage_frame, ~0, sizeof(garbage_frame));
- TestSpdyVisitor visitor;
- visitor.use_compression_ = false;
- visitor.SimulateInFramer(garbage_frame, sizeof(garbage_frame));
- EXPECT_EQ(1, visitor.error_count_);
-}
-
-TEST_F(SpdyFramerSpdy2Test, ReadGarbageWithValidVersion) {
- SpdyFramer framer(kVer);
- char garbage_frame[256];
- memset(garbage_frame, ~0, sizeof(garbage_frame));
- SpdyControlFrame control_frame(&garbage_frame[0], false);
- control_frame.set_version(SPDY_VERSION_FOR_TESTS);
- TestSpdyVisitor visitor;
- visitor.use_compression_ = false;
- visitor.SimulateInFramer(
- reinterpret_cast<unsigned char*>(control_frame.data()),
- sizeof(garbage_frame));
- EXPECT_EQ(1, visitor.error_count_);
-}
-
-TEST_F(SpdyFramerSpdy2Test, StateToStringTest) {
- EXPECT_STREQ("ERROR",
- SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR));
- EXPECT_STREQ("DONE",
- SpdyFramer::StateToString(SpdyFramer::SPDY_DONE));
- 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_CREDENTIAL_FRAME_PAYLOAD",
- SpdyFramer::StateToString(
- SpdyFramer::SPDY_CREDENTIAL_FRAME_PAYLOAD));
- EXPECT_STREQ("SPDY_SETTINGS_FRAME_PAYLOAD",
- SpdyFramer::StateToString(
- SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD));
- EXPECT_STREQ("UNKNOWN_STATE",
- SpdyFramer::StateToString(
- SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD + 1));
-}
-
-TEST_F(SpdyFramerSpdy2Test, 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("UNKNOWN_ERROR",
- SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR));
-}
-
-TEST_F(SpdyFramerSpdy2Test, StatusCodeToStringTest) {
- EXPECT_STREQ("INVALID",
- SpdyFramer::StatusCodeToString(INVALID));
- EXPECT_STREQ("PROTOCOL_ERROR",
- SpdyFramer::StatusCodeToString(PROTOCOL_ERROR));
- EXPECT_STREQ("INVALID_STREAM",
- SpdyFramer::StatusCodeToString(INVALID_STREAM));
- EXPECT_STREQ("REFUSED_STREAM",
- SpdyFramer::StatusCodeToString(REFUSED_STREAM));
- EXPECT_STREQ("UNSUPPORTED_VERSION",
- SpdyFramer::StatusCodeToString(UNSUPPORTED_VERSION));
- EXPECT_STREQ("CANCEL",
- SpdyFramer::StatusCodeToString(CANCEL));
- EXPECT_STREQ("INTERNAL_ERROR",
- SpdyFramer::StatusCodeToString(INTERNAL_ERROR));
- EXPECT_STREQ("FLOW_CONTROL_ERROR",
- SpdyFramer::StatusCodeToString(FLOW_CONTROL_ERROR));
- EXPECT_STREQ("UNKNOWN_STATUS",
- SpdyFramer::StatusCodeToString(NUM_STATUS_CODES));
-}
-
-TEST_F(SpdyFramerSpdy2Test, ControlTypeToStringTest) {
- EXPECT_STREQ("SYN_STREAM",
- SpdyFramer::ControlTypeToString(SYN_STREAM));
- EXPECT_STREQ("SYN_REPLY",
- SpdyFramer::ControlTypeToString(SYN_REPLY));
- EXPECT_STREQ("RST_STREAM",
- SpdyFramer::ControlTypeToString(RST_STREAM));
- EXPECT_STREQ("SETTINGS",
- SpdyFramer::ControlTypeToString(SETTINGS));
- EXPECT_STREQ("NOOP",
- SpdyFramer::ControlTypeToString(NOOP));
- EXPECT_STREQ("PING",
- SpdyFramer::ControlTypeToString(PING));
- EXPECT_STREQ("GOAWAY",
- SpdyFramer::ControlTypeToString(GOAWAY));
- EXPECT_STREQ("HEADERS",
- SpdyFramer::ControlTypeToString(HEADERS));
- EXPECT_STREQ("WINDOW_UPDATE",
- SpdyFramer::ControlTypeToString(WINDOW_UPDATE));
- EXPECT_STREQ("CREDENTIAL",
- SpdyFramer::ControlTypeToString(CREDENTIAL));
- EXPECT_STREQ("UNKNOWN_CONTROL_TYPE",
- SpdyFramer::ControlTypeToString(NUM_CONTROL_FRAME_TYPES));
-}
-
-TEST_F(SpdyFramerSpdy2Test, GetMinimumControlFrameSizeTest) {
- EXPECT_EQ(SpdySynStreamControlFrame::size(),
- SpdyFramer::GetMinimumControlFrameSize(SYN_STREAM));
- EXPECT_EQ(SpdySynReplyControlFrame::size(),
- SpdyFramer::GetMinimumControlFrameSize(SYN_REPLY));
- EXPECT_EQ(SpdyRstStreamControlFrame::size(),
- SpdyFramer::GetMinimumControlFrameSize(RST_STREAM));
- EXPECT_EQ(SpdySettingsControlFrame::size(),
- SpdyFramer::GetMinimumControlFrameSize(SETTINGS));
- EXPECT_EQ(SpdyFrame::kHeaderSize,
- SpdyFramer::GetMinimumControlFrameSize(NOOP));
- EXPECT_EQ(SpdyPingControlFrame::size(),
- SpdyFramer::GetMinimumControlFrameSize(PING));
- EXPECT_EQ(SpdyGoAwayControlFrame::size(),
- SpdyFramer::GetMinimumControlFrameSize(GOAWAY));
- EXPECT_EQ(SpdyHeadersControlFrame::size(),
- SpdyFramer::GetMinimumControlFrameSize(HEADERS));
- EXPECT_EQ(SpdyWindowUpdateControlFrame::size(),
- SpdyFramer::GetMinimumControlFrameSize(WINDOW_UPDATE));
- EXPECT_EQ(SpdyCredentialControlFrame::size(),
- SpdyFramer::GetMinimumControlFrameSize(CREDENTIAL));
- EXPECT_EQ(static_cast<size_t>(0x7FFFFFFF),
- SpdyFramer::GetMinimumControlFrameSize(NUM_CONTROL_FRAME_TYPES));
-}
-
-TEST_F(SpdyFramerSpdy2Test, CatchProbableHttpResponse) {
- SpdyFramerTestUtil::DecompressionVisitor visitor;
- visitor.set_allow_data_frames(true);
- {
- SpdyFramer framer(kVer);
- framer.set_visitor(&visitor);
- framer.ProcessInput("HTTP/1.1", 8);
- EXPECT_TRUE(framer.probable_http_response());
- }
- {
- SpdyFramer framer(kVer);
- framer.set_visitor(&visitor);
- framer.ProcessInput("HTTP/1.0", 8);
- EXPECT_TRUE(framer.probable_http_response());
- }
-}
-
-TEST_F(SpdyFramerSpdy2Test, SettingsFlagsAndId) {
- const uint32 kId = 0x020304;
- const uint32 kFlags = 0x01;
- const uint32 kWireFormat =
- htonl((SPDY_VERSION_FOR_TESTS < 3) ? 0x04030201 : 0x01020304);
-
- SettingsFlagsAndId id_and_flags =
- SettingsFlagsAndId::FromWireFormat(SPDY_VERSION_FOR_TESTS, kWireFormat);
- EXPECT_EQ(kId, id_and_flags.id());
- EXPECT_EQ(kFlags, id_and_flags.flags());
- EXPECT_EQ(kWireFormat, id_and_flags.GetWireFormat(SPDY_VERSION_FOR_TESTS));
-}
-
-} // namespace

Powered by Google App Engine
This is Rietveld 408576698