| Index: net/spdy/spdy_framer_spdy2_test.cc
|
| ===================================================================
|
| --- net/spdy/spdy_framer_spdy2_test.cc (working copy)
|
| +++ net/spdy/spdy_framer_spdy2_test.cc (working copy)
|
| @@ -11,13 +11,152 @@
|
| #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 {
|
| +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 char kHexChars[] = "0123456789abcdef";
|
| static const int kColumns = 4;
|
|
|
| const int kSizeLimit = 1024;
|
| @@ -58,8 +197,8 @@
|
| const int actual_len,
|
| const unsigned char* expected,
|
| const int expected_len) {
|
| - const int min_len = actual_len > expected_len ? expected_len : actual_len;
|
| - const int max_len = actual_len > expected_len ? actual_len : 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) {
|
| @@ -89,13 +228,16 @@
|
| static const size_t kDefaultCredentialBufferSize = 16 * 1024;
|
|
|
| TestSpdyVisitor()
|
| - : use_compression_(false),
|
| + : 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),
|
| @@ -166,6 +308,9 @@
|
| case CREDENTIAL:
|
| credential_count_++;
|
| break;
|
| + case SETTINGS:
|
| + settings_frame_count_++;
|
| + break;
|
| default:
|
| DLOG(FATAL); // Error!
|
| }
|
| @@ -173,6 +318,10 @@
|
| ++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) {
|
| @@ -182,7 +331,7 @@
|
| ++zero_length_control_frame_header_data_count_;
|
| // Indicates end-of-header-block.
|
| CHECK(header_buffer_valid_);
|
| - bool parsed_headers = SpdyFramer::ParseHeaderBlockInBuffer(
|
| + bool parsed_headers = framer_.ParseHeaderBlockInBuffer(
|
| header_buffer_.get(), header_buffer_length_, &headers_);
|
| DCHECK(parsed_headers);
|
| return true;
|
| @@ -197,7 +346,8 @@
|
| return true;
|
| }
|
|
|
| - bool OnCredentialFrameData(const char* credential_data, size_t len) {
|
| + bool OnCredentialFrameData(const char* credential_data,
|
| + size_t len) {
|
| if (len == 0) {
|
| if (!framer_.ParseCredentialData(credential_buffer_.get(),
|
| credential_buffer_length_,
|
| @@ -272,6 +422,8 @@
|
| 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.
|
| @@ -297,7 +449,7 @@
|
| SpdyCredential credential_;
|
| };
|
|
|
| -} // namespace test
|
| +} // namespace test_spdy2
|
|
|
| } // namespace spdy
|
|
|
| @@ -315,12 +467,13 @@
|
| using spdy::DATA_FLAG_COMPRESSED;
|
| using spdy::DATA_FLAG_FIN;
|
| using spdy::SYN_STREAM;
|
| -using spdy::test::CompareCharArraysWithHexError;
|
| -using spdy::test::TestSpdyVisitor;
|
| +using spdy::test_spdy2::CompareCharArraysWithHexError;
|
| +using spdy::test_spdy2::SpdyFramerTestUtil;
|
| +using spdy::test_spdy2::TestSpdyVisitor;
|
|
|
| namespace spdy {
|
|
|
| -TEST(SpdyFrameBuilderTest, WriteLimits) {
|
| +TEST(SpdyFrameBuilderSpdy2Test, WriteLimits) {
|
| SpdyFrameBuilder builder(kLengthMask + 4);
|
| // length field should fail.
|
| EXPECT_FALSE(builder.WriteBytes(reinterpret_cast<const void*>(0x1),
|
| @@ -335,7 +488,7 @@
|
| EXPECT_EQ(4 + kLengthMask, static_cast<unsigned>(builder.length()));
|
| }
|
|
|
| -class SpdyFramerTest : public PlatformTest {
|
| +class SpdyFramerSpdy2Test : public PlatformTest {
|
| public:
|
| virtual void TearDown() {}
|
|
|
| @@ -382,11 +535,11 @@
|
|
|
|
|
| // Test that we can encode and decode a SpdyHeaderBlock in serialized form.
|
| -TEST_F(SpdyFramerTest, HeaderBlockInBuffer) {
|
| +TEST_F(SpdyFramerSpdy2Test, HeaderBlockInBuffer) {
|
| SpdyHeaderBlock headers;
|
| headers["alpha"] = "beta";
|
| headers["gamma"] = "charlie";
|
| - SpdyFramer framer;
|
| + SpdyFramer framer(kVer);
|
|
|
| // Encode the header block into a SynStream frame.
|
| scoped_ptr<SpdySynStreamControlFrame> frame(
|
| @@ -405,11 +558,11 @@
|
| }
|
|
|
| // Test that if there's not a full frame, we fail to parse it.
|
| -TEST_F(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
|
| +TEST_F(SpdyFramerSpdy2Test, UndersizedHeaderBlockInBuffer) {
|
| SpdyHeaderBlock headers;
|
| headers["alpha"] = "beta";
|
| headers["gamma"] = "charlie";
|
| - SpdyFramer framer;
|
| + SpdyFramer framer(kVer);
|
|
|
| // Encode the header block into a SynStream frame.
|
| scoped_ptr<SpdySynStreamControlFrame> frame(
|
| @@ -424,7 +577,7 @@
|
| &new_headers));
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, OutOfOrderHeaders) {
|
| +TEST_F(SpdyFramerSpdy2Test, OutOfOrderHeaders) {
|
| // Frame builder with plentiful buffer size.
|
| SpdyFrameBuilder frame(1024);
|
|
|
| @@ -435,12 +588,19 @@
|
| frame.WriteUInt32(0); // Associated stream id
|
| frame.WriteUInt16(0); // Priority.
|
|
|
| - frame.WriteUInt16(2); // Number of headers.
|
| - SpdyHeaderBlock::iterator it;
|
| - frame.WriteString("gamma");
|
| - frame.WriteString("gamma");
|
| - frame.WriteString("alpha");
|
| - frame.WriteString("alpha");
|
| + 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);
|
|
|
| @@ -449,14 +609,85 @@
|
| SpdySynStreamControlFrame syn_frame(control_frame->data(), false);
|
| std::string serialized_headers(syn_frame.header_block(),
|
| syn_frame.header_block_len());
|
| - SpdyFramer framer;
|
| + SpdyFramer framer(kVer);
|
| framer.set_enable_compression(false);
|
| EXPECT_TRUE(framer.ParseHeaderBlockInBuffer(serialized_headers.c_str(),
|
| serialized_headers.size(),
|
| &new_headers));
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, DuplicateHeader) {
|
| +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);
|
|
|
| @@ -467,12 +698,19 @@
|
| frame.WriteUInt32(0); // associated stream id
|
| frame.WriteUInt16(0); // Priority.
|
|
|
| - frame.WriteUInt16(2); // Number of headers.
|
| - SpdyHeaderBlock::iterator it;
|
| - frame.WriteString("name");
|
| - frame.WriteString("value1");
|
| - frame.WriteString("name");
|
| - frame.WriteString("value2");
|
| + 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);
|
|
|
| @@ -481,7 +719,7 @@
|
| SpdySynStreamControlFrame syn_frame(control_frame->data(), false);
|
| std::string serialized_headers(syn_frame.header_block(),
|
| syn_frame.header_block_len());
|
| - SpdyFramer framer;
|
| + 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(),
|
| @@ -489,7 +727,7 @@
|
| &new_headers));
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, MultiValueHeader) {
|
| +TEST_F(SpdyFramerSpdy2Test, MultiValueHeader) {
|
| // Frame builder with plentiful buffer size.
|
| SpdyFrameBuilder frame(1024);
|
|
|
| @@ -500,11 +738,16 @@
|
| frame.WriteUInt32(0); // associated stream id
|
| frame.WriteUInt16(0); // Priority.
|
|
|
| - frame.WriteUInt16(1); // Number of headers.
|
| - SpdyHeaderBlock::iterator it;
|
| - frame.WriteString("name");
|
| std::string value("value1\0value2");
|
| - frame.WriteString(value);
|
| + 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);
|
|
|
| @@ -513,7 +756,7 @@
|
| SpdySynStreamControlFrame syn_frame(control_frame->data(), false);
|
| std::string serialized_headers(syn_frame.header_block(),
|
| syn_frame.header_block_len());
|
| - SpdyFramer framer;
|
| + SpdyFramer framer(kVer);
|
| framer.set_enable_compression(false);
|
| EXPECT_TRUE(framer.ParseHeaderBlockInBuffer(serialized_headers.c_str(),
|
| serialized_headers.size(),
|
| @@ -522,7 +765,7 @@
|
| EXPECT_EQ(value, new_headers.find("name")->second);
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, BasicCompression) {
|
| +TEST_F(SpdyFramerSpdy2Test, BasicCompression) {
|
| SpdyHeaderBlock headers;
|
| headers["server"] = "SpdyServer 1.0";
|
| headers["date"] = "Mon 12 Jan 2009 12:12:12 PST";
|
| @@ -531,7 +774,7 @@
|
| headers["content-type"] = "text/html";
|
| headers["content-length"] = "12";
|
|
|
| - SpdyFramer framer;
|
| + SpdyFramer framer(kVer);
|
| framer.set_enable_compression(true);
|
| scoped_ptr<SpdySynStreamControlFrame>
|
| frame1(framer.CreateSynStream(1, 0, 1, CONTROL_FLAG_NONE, true,
|
| @@ -544,10 +787,12 @@
|
| EXPECT_LE(frame2->length(), frame1->length());
|
|
|
| // Decompress the first frame
|
| - scoped_ptr<SpdyFrame> frame3(framer.DecompressFrame(*frame1.get()));
|
| + scoped_ptr<SpdyFrame> frame3(SpdyFramerTestUtil::DecompressFrame(
|
| + &framer, *frame1.get()));
|
|
|
| // Decompress the second frame
|
| - scoped_ptr<SpdyFrame> frame4(framer.DecompressFrame(*frame2.get()));
|
| + scoped_ptr<SpdyFrame> frame4(SpdyFramerTestUtil::DecompressFrame(
|
| + &framer, *frame2.get()));
|
|
|
| // Expect frames 3 & 4 to be the same.
|
| EXPECT_EQ(0,
|
| @@ -566,30 +811,9 @@
|
| SpdyFrame::kHeaderSize + uncompressed_frame->length()));
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, DecompressUncompressedFrame) {
|
| - 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;
|
| - framer.set_enable_compression(true);
|
| - scoped_ptr<SpdySynStreamControlFrame>
|
| - frame1(framer.CreateSynStream(1, 0, 1, CONTROL_FLAG_NONE, false,
|
| - &headers));
|
| -
|
| - // Decompress the frame
|
| - scoped_ptr<SpdyFrame> frame2(framer.DecompressFrame(*frame1.get()));
|
| -
|
| - EXPECT_EQ(NULL, frame2.get());
|
| -}
|
| -
|
| -TEST_F(SpdyFramerTest, Basic) {
|
| - const unsigned char input[] = {
|
| - 0x80, 0x02, 0x00, 0x01, // SYN Stream #1
|
| +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,
|
| @@ -597,7 +821,7 @@
|
| 0x00, 0x02, 'h', 'h',
|
| 0x00, 0x02, 'v', 'v',
|
|
|
| - 0x80, 0x02, 0x00, 0x08, // HEADERS on Stream #1
|
| + 0x80, kVer, 0x00, 0x08, // HEADERS on Stream #1
|
| 0x00, 0x00, 0x00, 0x18,
|
| 0x00, 0x00, 0x00, 0x01,
|
| 0x00, 0x00, 0x00, 0x02,
|
| @@ -608,11 +832,11 @@
|
|
|
| 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
|
| 0x00, 0x00, 0x00, 0x0c,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| + 0xde, 0xad, 0xbe, 0xef,
|
| + 0xde, 0xad, 0xbe, 0xef,
|
| + 0xde, 0xad, 0xbe, 0xef,
|
|
|
| - 0x80, 0x02, 0x00, 0x01, // SYN Stream #3
|
| + 0x80, kVer, 0x00, 0x01, // SYN Stream #3
|
| 0x00, 0x00, 0x00, 0x0c,
|
| 0x00, 0x00, 0x00, 0x03,
|
| 0x00, 0x00, 0x00, 0x00,
|
| @@ -620,14 +844,14 @@
|
|
|
| 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
|
| 0x00, 0x00, 0x00, 0x08,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| + 0xde, 0xad, 0xbe, 0xef,
|
| + 0xde, 0xad, 0xbe, 0xef,
|
|
|
| 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
|
| 0x00, 0x00, 0x00, 0x04,
|
| - 0xde, 0xad, 0xbe, 0xef,
|
| + 0xde, 0xad, 0xbe, 0xef,
|
|
|
| - 0x80, 0x02, 0x00, 0x03, // RST_STREAM on Stream #1
|
| + 0x80, kVer, 0x00, 0x03, // RST_STREAM on Stream #1
|
| 0x00, 0x00, 0x00, 0x08,
|
| 0x00, 0x00, 0x00, 0x01,
|
| 0x00, 0x00, 0x00, 0x00,
|
| @@ -635,14 +859,77 @@
|
| 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
|
| 0x00, 0x00, 0x00, 0x00,
|
|
|
| - 0x80, 0x02, 0x00, 0x03, // RST_STREAM on Stream #3
|
| + 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;
|
| - visitor.SimulateInFramer(input, sizeof(input));
|
| + 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_);
|
| @@ -656,9 +943,9 @@
|
| }
|
|
|
| // Test that the FIN flag on a data frame signifies EOF.
|
| -TEST_F(SpdyFramerTest, FinOnDataFrame) {
|
| - const unsigned char input[] = {
|
| - 0x80, 0x02, 0x00, 0x01, // SYN Stream #1
|
| +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,
|
| @@ -666,7 +953,7 @@
|
| 0x00, 0x02, 'h', 'h',
|
| 0x00, 0x02, 'v', 'v',
|
|
|
| - 0x80, 0x02, 0x00, 0x02, // SYN REPLY Stream #1
|
| + 0x80, kVer, 0x00, 0x02, // SYN REPLY Stream #1
|
| 0x00, 0x00, 0x00, 0x10,
|
| 0x00, 0x00, 0x00, 0x01,
|
| 0x00, 0x00, 0x00, 0x01,
|
| @@ -683,9 +970,43 @@
|
| 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;
|
| - visitor.SimulateInFramer(input, sizeof(input));
|
| + 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_);
|
| @@ -699,9 +1020,9 @@
|
| }
|
|
|
| // Test that the FIN flag on a SYN reply frame signifies EOF.
|
| -TEST_F(SpdyFramerTest, FinOnSynReplyFrame) {
|
| - const unsigned char input[] = {
|
| - 0x80, 0x02, 0x00, 0x01, // SYN Stream #1
|
| +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,
|
| @@ -709,7 +1030,7 @@
|
| 0x00, 0x02, 'h', 'h',
|
| 0x00, 0x02, 'v', 'v',
|
|
|
| - 0x80, 0x02, 0x00, 0x02, // SYN REPLY Stream #1
|
| + 0x80, kVer, 0x00, 0x02, // SYN REPLY Stream #1
|
| 0x01, 0x00, 0x00, 0x14,
|
| 0x00, 0x00, 0x00, 0x01,
|
| 0x00, 0x00, 0x00, 0x00,
|
| @@ -717,9 +1038,34 @@
|
| 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;
|
| - visitor.SimulateInFramer(input, sizeof(input));
|
| + 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_);
|
| @@ -732,9 +1078,9 @@
|
| EXPECT_EQ(0, visitor.data_frame_count_);
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, HeaderCompression) {
|
| - SpdyFramer send_framer;
|
| - SpdyFramer recv_framer;
|
| +TEST_F(SpdyFramerSpdy2Test, HeaderCompression) {
|
| + SpdyFramer send_framer(kVer);
|
| + SpdyFramer recv_framer(kVer);
|
|
|
| send_framer.set_enable_compression(true);
|
| recv_framer.set_enable_compression(true);
|
| @@ -751,33 +1097,30 @@
|
| block[kHeader1] = kValue1;
|
| block[kHeader2] = kValue2;
|
| SpdyControlFlags flags(CONTROL_FLAG_NONE);
|
| - scoped_ptr<spdy::SpdyFrame> syn_frame_1(
|
| + 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<spdy::SpdyFrame> syn_frame_2(
|
| + 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<SpdyFrame> decompressed_syn_frame;
|
| - SpdySynStreamControlFrame* syn_frame;
|
| + scoped_ptr<SpdySynStreamControlFrame> syn_frame;
|
| scoped_ptr<std::string> serialized_headers;
|
| SpdyHeaderBlock decompressed_headers;
|
|
|
| // Decompress SYN_STREAM #1
|
| - decompressed.reset(recv_framer.DecompressFrame(*syn_frame_1.get()));
|
| + 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());
|
| - decompressed_syn_frame.reset(
|
| - new SpdySynStreamControlFrame(decompressed->data(), false));
|
| - syn_frame = reinterpret_cast<SpdySynStreamControlFrame*>(
|
| - decompressed_syn_frame.get());
|
| + 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(),
|
| @@ -788,15 +1131,13 @@
|
| EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
|
|
|
| // Decompress SYN_STREAM #2
|
| - decompressed.reset(recv_framer.DecompressFrame(*syn_frame_2.get()));
|
| + 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());
|
| - decompressed_syn_frame.reset(
|
| - new SpdySynStreamControlFrame(decompressed->data(), false));
|
| - syn_frame = reinterpret_cast<SpdySynStreamControlFrame*>(
|
| - decompressed_syn_frame.get());
|
| + 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();
|
| @@ -816,8 +1157,8 @@
|
| }
|
|
|
| // Verify we don't leak when we leave streams unclosed
|
| -TEST_F(SpdyFramerTest, UnclosedStreamDataCompressors) {
|
| - SpdyFramer send_framer;
|
| +TEST_F(SpdyFramerSpdy2Test, UnclosedStreamDataCompressors) {
|
| + SpdyFramer send_framer(kVer);
|
|
|
| send_framer.set_enable_compression(true);
|
|
|
| @@ -830,7 +1171,7 @@
|
| block[kHeader1] = kValue1;
|
| block[kHeader2] = kValue2;
|
| SpdyControlFlags flags(CONTROL_FLAG_NONE);
|
| - scoped_ptr<spdy::SpdyFrame> syn_frame(
|
| + scoped_ptr<SpdyFrame> syn_frame(
|
| send_framer.CreateSynStream(1, 0, 0, flags, true, &block));
|
| EXPECT_TRUE(syn_frame.get() != NULL);
|
|
|
| @@ -838,7 +1179,7 @@
|
| scoped_ptr<SpdyFrame> send_frame(
|
| send_framer.CreateDataFrame(
|
| 1, bytes, arraysize(bytes),
|
| - DATA_FLAG_FIN));
|
| + static_cast<SpdyDataFlags>(DATA_FLAG_FIN)));
|
| EXPECT_TRUE(send_frame.get() != NULL);
|
|
|
| // Run the inputs through the framer.
|
| @@ -867,12 +1208,76 @@
|
| EXPECT_EQ(0, send_framer.num_stream_decompressors());
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, WindowUpdateFrame) {
|
| +// 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(
|
| - SpdyFramer::CreateWindowUpdate(1, 0x12345678));
|
| + framer.CreateWindowUpdate(1, 0x12345678));
|
|
|
| const unsigned char expected_data_frame[] = {
|
| - 0x80, 0x02, 0x00, 0x09,
|
| + 0x80, kVer, 0x00, 0x09,
|
| 0x00, 0x00, 0x00, 0x08,
|
| 0x00, 0x00, 0x00, 0x01,
|
| 0x12, 0x34, 0x56, 0x78
|
| @@ -883,8 +1288,8 @@
|
| memcmp(window_update_frame->data(), expected_data_frame, 16));
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, CreateDataFrame) {
|
| - SpdyFramer framer;
|
| +TEST_F(SpdyFramerSpdy2Test, CreateDataFrame) {
|
| + SpdyFramer framer(kVer);
|
|
|
| {
|
| const char kDescription[] = "'hello' data frame, no FIN";
|
| @@ -969,8 +1374,8 @@
|
| }
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, CreateSynStreamUncompressed) {
|
| - SpdyFramer framer;
|
| +TEST_F(SpdyFramerSpdy2Test, CreateSynStreamUncompressed) {
|
| + SpdyFramer framer(kVer);
|
| framer.set_enable_compression(false);
|
|
|
| {
|
| @@ -980,24 +1385,43 @@
|
| headers["bar"] = "foo";
|
| headers["foo"] = "bar";
|
|
|
| - const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x01,
|
| + 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,
|
| - 0xC0, 0x00, 0x00, 0x02,
|
| + kPri, 0x00, 0x00, 0x02,
|
| 0x00, 0x03, 'b', 'a',
|
| 'r', 0x00, 0x03, 'f',
|
| 'o', 'o', 0x00, 0x03,
|
| 'f', 'o', 'o', 0x00,
|
| 0x03, 'b', 'a', 'r'
|
| };
|
| - scoped_ptr<SpdyFrame> frame(framer.CreateSynStream(
|
| - 1, 0, SPDY_PRIORITY_LOWEST, CONTROL_FLAG_NONE,
|
| - false, &headers));
|
| - CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| - EXPECT_EQ(1u, SpdyFramer::GetControlFrameStreamId(
|
| - reinterpret_cast<const SpdyControlFrame*>(frame.get())));
|
| + 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()));
|
| }
|
|
|
| {
|
| @@ -1009,8 +1433,8 @@
|
| headers[""] = "foo";
|
| headers["foo"] = "bar";
|
|
|
| - const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x01,
|
| + const unsigned char kV2FrameData[] = {
|
| + 0x80, kVer, 0x00, 0x01,
|
| 0x01, 0x00, 0x00, 0x1D,
|
| 0x7f, 0xff, 0xff, 0xff,
|
| 0x7f, 0xff, 0xff, 0xff,
|
| @@ -1021,58 +1445,97 @@
|
| 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, SPDY_PRIORITY_HIGHEST, CONTROL_FLAG_FIN,
|
| + 0x7fffffff, 0x7fffffff, framer.GetHighestPriority(), CONTROL_FLAG_FIN,
|
| false, &headers));
|
| - CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| + 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, highest pri, FIN, "
|
| + "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 kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x01,
|
| + 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,
|
| - 0x00, 0x00, 0x00, 0x02,
|
| + 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, SPDY_PRIORITY_HIGHEST, CONTROL_FLAG_FIN,
|
| - false, &headers));
|
| - CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| + 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(SpdyFramerTest, CreateSynStreamCompressed) {
|
| - SpdyFramer framer;
|
| +TEST_F(SpdyFramerSpdy2Test, CreateSynStreamCompressed) {
|
| + SpdyFramer framer(kVer);
|
| framer.set_enable_compression(true);
|
|
|
| {
|
| const char kDescription[] =
|
| - "SYN_STREAM frame, lowest pri, no FIN";
|
| + "SYN_STREAM frame, low pri, no FIN";
|
|
|
| SpdyHeaderBlock headers;
|
| headers["bar"] = "foo";
|
| headers["foo"] = "bar";
|
|
|
| - const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x01,
|
| + 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,
|
| - 0xC0, 0x00, 0x38, 0xea,
|
| + 0x80, 0x00, 0x38, 0xea,
|
| 0xdf, 0xa2, 0x51, 0xb2,
|
| 0x62, 0x60, 0x62, 0x60,
|
| 0x4e, 0x4a, 0x2c, 0x62,
|
| @@ -1081,15 +1544,32 @@
|
| 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, SPDY_PRIORITY_LOWEST, CONTROL_FLAG_NONE,
|
| - true, &headers));
|
| - CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| + 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(SpdyFramerTest, CreateSynReplyUncompressed) {
|
| - SpdyFramer framer;
|
| +TEST_F(SpdyFramerSpdy2Test, CreateSynReplyUncompressed) {
|
| + SpdyFramer framer(kVer);
|
| framer.set_enable_compression(false);
|
|
|
| {
|
| @@ -1099,8 +1579,8 @@
|
| headers["bar"] = "foo";
|
| headers["foo"] = "bar";
|
|
|
| - const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x02,
|
| + const unsigned char kV2FrameData[] = {
|
| + 0x80, kVer, 0x00, 0x02,
|
| 0x00, 0x00, 0x00, 0x1C,
|
| 0x00, 0x00, 0x00, 0x01,
|
| 0x00, 0x00, 0x00, 0x02,
|
| @@ -1110,9 +1590,26 @@
|
| '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, kFrameData, arraysize(kFrameData));
|
| + CompareFrame(kDescription,
|
| + *frame,
|
| + (SPDY_VERSION_FOR_TESTS < 3) ? kV2FrameData : kV3FrameData,
|
| + (SPDY_VERSION_FOR_TESTS < 3) ? arraysize(kV2FrameData)
|
| + : arraysize(kV3FrameData));
|
| }
|
|
|
| {
|
| @@ -1123,8 +1620,8 @@
|
| headers[""] = "foo";
|
| headers["foo"] = "bar";
|
|
|
| - const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x02,
|
| + const unsigned char kV2FrameData[] = {
|
| + 0x80, kVer, 0x00, 0x02,
|
| 0x01, 0x00, 0x00, 0x19,
|
| 0x7f, 0xff, 0xff, 0xff,
|
| 0x00, 0x00, 0x00, 0x02,
|
| @@ -1134,9 +1631,26 @@
|
| 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, kFrameData, arraysize(kFrameData));
|
| + CompareFrame(kDescription,
|
| + *frame,
|
| + (SPDY_VERSION_FOR_TESTS < 3) ? kV2FrameData : kV3FrameData,
|
| + (SPDY_VERSION_FOR_TESTS < 3) ? arraysize(kV2FrameData)
|
| + : arraysize(kV3FrameData));
|
| }
|
|
|
| {
|
| @@ -1147,8 +1661,8 @@
|
| headers["bar"] = "foo";
|
| headers["foo"] = "";
|
|
|
| - const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x02,
|
| + const unsigned char kV2FrameData[] = {
|
| + 0x80, kVer, 0x00, 0x02,
|
| 0x01, 0x00, 0x00, 0x19,
|
| 0x7f, 0xff, 0xff, 0xff,
|
| 0x00, 0x00, 0x00, 0x02,
|
| @@ -1158,14 +1672,31 @@
|
| '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, kFrameData, arraysize(kFrameData));
|
| + CompareFrame(kDescription,
|
| + *frame,
|
| + (SPDY_VERSION_FOR_TESTS < 3) ? kV2FrameData : kV3FrameData,
|
| + (SPDY_VERSION_FOR_TESTS < 3) ? arraysize(kV2FrameData)
|
| + : arraysize(kV3FrameData));
|
| }
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, CreateSynReplyCompressed) {
|
| - SpdyFramer framer;
|
| +TEST_F(SpdyFramerSpdy2Test, CreateSynReplyCompressed) {
|
| + SpdyFramer framer(kVer);
|
| framer.set_enable_compression(true);
|
|
|
| {
|
| @@ -1175,8 +1706,8 @@
|
| headers["bar"] = "foo";
|
| headers["foo"] = "bar";
|
|
|
| - const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x02,
|
| + const unsigned char kV2FrameData[] = {
|
| + 0x80, kVer, 0x00, 0x02,
|
| 0x00, 0x00, 0x00, 0x21,
|
| 0x00, 0x00, 0x00, 0x01,
|
| 0x00, 0x00, 0x38, 0xea,
|
| @@ -1188,33 +1719,50 @@
|
| 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, kFrameData, arraysize(kFrameData));
|
| + CompareFrame(kDescription,
|
| + *frame,
|
| + (SPDY_VERSION_FOR_TESTS < 3) ? kV2FrameData : kV3FrameData,
|
| + (SPDY_VERSION_FOR_TESTS < 3) ? arraysize(kV2FrameData)
|
| + : arraysize(kV3FrameData));
|
| }
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, CreateRstStream) {
|
| - SpdyFramer framer;
|
| +TEST_F(SpdyFramerSpdy2Test, CreateRstStream) {
|
| + SpdyFramer framer(kVer);
|
|
|
| {
|
| const char kDescription[] = "RST_STREAM frame";
|
| const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x03,
|
| + 0x80, kVer, 0x00, 0x03,
|
| 0x00, 0x00, 0x00, 0x08,
|
| 0x00, 0x00, 0x00, 0x01,
|
| 0x00, 0x00, 0x00, 0x01,
|
| };
|
| - scoped_ptr<SpdyFrame> frame(framer.CreateRstStream(1, PROTOCOL_ERROR));
|
| + scoped_ptr<SpdyRstStreamControlFrame> frame(
|
| + framer.CreateRstStream(1, PROTOCOL_ERROR));
|
| CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| - EXPECT_EQ(1u, SpdyFramer::GetControlFrameStreamId(
|
| - reinterpret_cast<const SpdyControlFrame*>(frame.get())));
|
| + EXPECT_EQ(1u, SpdyFramer::GetControlFrameStreamId(frame.get()));
|
| }
|
|
|
| {
|
| const char kDescription[] = "RST_STREAM frame with max stream ID";
|
| const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x03,
|
| + 0x80, kVer, 0x00, 0x03,
|
| 0x00, 0x00, 0x00, 0x08,
|
| 0x7f, 0xff, 0xff, 0xff,
|
| 0x00, 0x00, 0x00, 0x01,
|
| @@ -1227,7 +1775,7 @@
|
| {
|
| const char kDescription[] = "RST_STREAM frame with max status code";
|
| const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x03,
|
| + 0x80, kVer, 0x00, 0x03,
|
| 0x00, 0x00, 0x00, 0x08,
|
| 0x7f, 0xff, 0xff, 0xff,
|
| 0x00, 0x00, 0x00, 0x06,
|
| @@ -1238,51 +1786,108 @@
|
| }
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, CreateSettings) {
|
| - SpdyFramer framer;
|
| +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(SpdySetting(0x00000000, 0x00000000));
|
| - settings.push_back(SpdySetting(0xffffffff, 0x00000001));
|
| - settings.push_back(SpdySetting(0xff000001, 0x00000002));
|
| + 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(SpdySetting(0x01000002, 0x00000003));
|
| - settings.push_back(SpdySetting(0x01000002, 0x00000003));
|
| + settings.push_back(
|
| + SpdySettingFromWireFormat(0x01000002, 0x00000003)); // 4th Setting
|
| + settings.push_back(
|
| + SpdySettingFromWireFormat(0x01000002, 0x00000003)); // 5th Setting
|
|
|
| - settings.push_back(SpdySetting(0x01000003, 0x000000ff));
|
| - settings.push_back(SpdySetting(0x01000004, 0xff000001));
|
| - settings.push_back(SpdySetting(0x01000004, 0xffffffff));
|
| + 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, 0x02, 0x00, 0x04,
|
| + 0x80, kVer, 0x00, 0x04,
|
| 0x00, 0x00, 0x00, 0x44,
|
| 0x00, 0x00, 0x00, 0x08,
|
| + 0x00, 0x00, 0x00, 0x00, // 1st Setting
|
| 0x00, 0x00, 0x00, 0x00,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - 0xff, 0xff, 0xff, 0xff,
|
| + 0xff, 0xff, 0xff, 0xff, // 2nd Setting
|
| 0x00, 0x00, 0x00, 0x01,
|
| - 0xff, 0x00, 0x00, 0x01,
|
| + 0x01, 0x00, 0x00, 0xff, // 3rd Setting
|
| 0x00, 0x00, 0x00, 0x02,
|
| - 0x01, 0x00, 0x00, 0x02,
|
| + 0x02, 0x00, 0x00, 0x01, // 4th Setting
|
| 0x00, 0x00, 0x00, 0x03,
|
| - 0x01, 0x00, 0x00, 0x02,
|
| + 0x02, 0x00, 0x00, 0x01, // 5th Setting
|
| 0x00, 0x00, 0x00, 0x03,
|
| - 0x01, 0x00, 0x00, 0x03,
|
| + 0x03, 0x00, 0x00, 0x01, // 6th Setting
|
| 0x00, 0x00, 0x00, 0xff,
|
| - 0x01, 0x00, 0x00, 0x04,
|
| + 0x04, 0x00, 0x00, 0x01, // 7th Setting
|
| 0xff, 0x00, 0x00, 0x01,
|
| - 0x01, 0x00, 0x00, 0x04,
|
| + 0x04, 0x00, 0x00, 0x01, // 8th Setting
|
| 0xff, 0xff, 0xff, 0xff,
|
| };
|
| - scoped_ptr<SpdyFrame> frame(framer.CreateSettings(settings));
|
| - CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| + scoped_ptr<SpdySettingsControlFrame> frame(framer.CreateSettings(settings));
|
| + CompareFrame(kDescription,
|
| + *frame,
|
| + kFrameData,
|
| + arraysize(kFrameData));
|
| EXPECT_EQ(SpdyFramer::kInvalidStream,
|
| - SpdyFramer::GetControlFrameStreamId(
|
| - reinterpret_cast<const SpdyControlFrame*>(frame.get())));
|
| + SpdyFramer::GetControlFrameStreamId(frame.get()));
|
| }
|
|
|
| {
|
| @@ -1291,7 +1896,7 @@
|
| SpdySettings settings;
|
|
|
| const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x04,
|
| + 0x80, kVer, 0x00, 0x04,
|
| 0x00, 0x00, 0x00, 0x04,
|
| 0x00, 0x00, 0x00, 0x00,
|
| };
|
| @@ -1300,62 +1905,43 @@
|
| }
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, CreateNopFrame) {
|
| - SpdyFramer framer;
|
| +TEST_F(SpdyFramerSpdy2Test, CreatePingFrame) {
|
| + SpdyFramer framer(kVer);
|
|
|
| {
|
| - const char kDescription[] = "NOOP frame";
|
| - const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x05,
|
| - 0x00, 0x00, 0x00, 0x00,
|
| - };
|
| - scoped_ptr<SpdyFrame> frame(framer.CreateNopFrame());
|
| - CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| - EXPECT_EQ(SpdyFramer::kInvalidStream,
|
| - SpdyFramer::GetControlFrameStreamId(
|
| - reinterpret_cast<const SpdyControlFrame*>(frame.get())));
|
| - }
|
| -}
|
| -
|
| -TEST_F(SpdyFramerTest, CreatePingFrame) {
|
| - SpdyFramer framer;
|
| -
|
| - {
|
| const char kDescription[] = "PING frame";
|
| const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x06,
|
| + 0x80, kVer, 0x00, 0x06,
|
| 0x00, 0x00, 0x00, 0x04,
|
| 0x12, 0x34, 0x56, 0x78,
|
| };
|
| - scoped_ptr<SpdyFrame> frame(framer.CreatePingFrame(0x12345678u));
|
| + scoped_ptr<SpdyPingControlFrame> frame(framer.CreatePingFrame(0x12345678u));
|
| CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| EXPECT_EQ(SpdyFramer::kInvalidStream,
|
| - SpdyFramer::GetControlFrameStreamId(
|
| - reinterpret_cast<const SpdyControlFrame*>(frame.get())));
|
| + SpdyFramer::GetControlFrameStreamId(frame.get()));
|
| }
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, CreateGoAway) {
|
| - SpdyFramer framer;
|
| +TEST_F(SpdyFramerSpdy2Test, CreateGoAway) {
|
| + SpdyFramer framer(kVer);
|
|
|
| {
|
| const char kDescription[] = "GOAWAY frame";
|
| const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x07,
|
| + 0x80, kVer, 0x00, 0x07,
|
| 0x00, 0x00, 0x00, 0x04,
|
| 0x00, 0x00, 0x00, 0x00,
|
| };
|
| - scoped_ptr<SpdyFrame> frame(framer.CreateGoAway(0));
|
| + scoped_ptr<SpdyGoAwayControlFrame> frame(framer.CreateGoAway(0));
|
| CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| EXPECT_EQ(SpdyFramer::kInvalidStream,
|
| - SpdyFramer::GetControlFrameStreamId(
|
| - reinterpret_cast<const SpdyControlFrame*>(frame.get())));
|
| + SpdyFramer::GetControlFrameStreamId(frame.get()));
|
| }
|
|
|
| {
|
| const char kDescription[] = "GOAWAY frame with max stream ID";
|
| const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x07,
|
| + 0x80, kVer, 0x00, 0x07,
|
| 0x00, 0x00, 0x00, 0x04,
|
| 0x7f, 0xff, 0xff, 0xff,
|
| };
|
| @@ -1364,8 +1950,8 @@
|
| }
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, CreateHeadersUncompressed) {
|
| - SpdyFramer framer;
|
| +TEST_F(SpdyFramerSpdy2Test, CreateHeadersUncompressed) {
|
| + SpdyFramer framer(kVer);
|
| framer.set_enable_compression(false);
|
|
|
| {
|
| @@ -1375,8 +1961,8 @@
|
| headers["bar"] = "foo";
|
| headers["foo"] = "bar";
|
|
|
| - const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x08,
|
| + const unsigned char kV2FrameData[] = {
|
| + 0x80, kVer, 0x00, 0x08,
|
| 0x00, 0x00, 0x00, 0x1C,
|
| 0x00, 0x00, 0x00, 0x01,
|
| 0x00, 0x00, 0x00, 0x02,
|
| @@ -1386,9 +1972,26 @@
|
| '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, kFrameData, arraysize(kFrameData));
|
| + CompareFrame(kDescription,
|
| + *frame,
|
| + (SPDY_VERSION_FOR_TESTS < 3) ? kV2FrameData : kV3FrameData,
|
| + (SPDY_VERSION_FOR_TESTS < 3) ? arraysize(kV2FrameData)
|
| + : arraysize(kV3FrameData));
|
| }
|
|
|
| {
|
| @@ -1399,8 +2002,8 @@
|
| headers[""] = "foo";
|
| headers["foo"] = "bar";
|
|
|
| - const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x08,
|
| + const unsigned char kV2FrameData[] = {
|
| + 0x80, kVer, 0x00, 0x08,
|
| 0x01, 0x00, 0x00, 0x19,
|
| 0x7f, 0xff, 0xff, 0xff,
|
| 0x00, 0x00, 0x00, 0x02,
|
| @@ -1410,9 +2013,26 @@
|
| 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, kFrameData, arraysize(kFrameData));
|
| + CompareFrame(kDescription,
|
| + *frame,
|
| + (SPDY_VERSION_FOR_TESTS < 3) ? kV2FrameData : kV3FrameData,
|
| + (SPDY_VERSION_FOR_TESTS < 3) ? arraysize(kV2FrameData)
|
| + : arraysize(kV3FrameData));
|
| }
|
|
|
| {
|
| @@ -1423,8 +2043,8 @@
|
| headers["bar"] = "foo";
|
| headers["foo"] = "";
|
|
|
| - const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x08,
|
| + const unsigned char kV2FrameData[] = {
|
| + 0x80, kVer, 0x00, 0x08,
|
| 0x01, 0x00, 0x00, 0x19,
|
| 0x7f, 0xff, 0xff, 0xff,
|
| 0x00, 0x00, 0x00, 0x02,
|
| @@ -1434,14 +2054,31 @@
|
| '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, kFrameData, arraysize(kFrameData));
|
| + CompareFrame(kDescription,
|
| + *frame,
|
| + (SPDY_VERSION_FOR_TESTS < 3) ? kV2FrameData : kV3FrameData,
|
| + (SPDY_VERSION_FOR_TESTS < 3) ? arraysize(kV2FrameData)
|
| + : arraysize(kV3FrameData));
|
| }
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, CreateHeadersCompressed) {
|
| - SpdyFramer framer;
|
| +TEST_F(SpdyFramerSpdy2Test, CreateHeadersCompressed) {
|
| + SpdyFramer framer(kVer);
|
| framer.set_enable_compression(true);
|
|
|
| {
|
| @@ -1451,8 +2088,8 @@
|
| headers["bar"] = "foo";
|
| headers["foo"] = "bar";
|
|
|
| - const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x08,
|
| + const unsigned char kV2FrameData[] = {
|
| + 0x80, kVer, 0x00, 0x08,
|
| 0x00, 0x00, 0x00, 0x21,
|
| 0x00, 0x00, 0x00, 0x01,
|
| 0x00, 0x00, 0x38, 0xea,
|
| @@ -1464,33 +2101,50 @@
|
| 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, kFrameData, arraysize(kFrameData));
|
| + CompareFrame(kDescription,
|
| + *frame,
|
| + (SPDY_VERSION_FOR_TESTS < 3) ? kV2FrameData : kV3FrameData,
|
| + (SPDY_VERSION_FOR_TESTS < 3) ? arraysize(kV2FrameData)
|
| + : arraysize(kV3FrameData));
|
| }
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, CreateWindowUpdate) {
|
| - SpdyFramer framer;
|
| +TEST_F(SpdyFramerSpdy2Test, CreateWindowUpdate) {
|
| + SpdyFramer framer(kVer);
|
|
|
| {
|
| const char kDescription[] = "WINDOW_UPDATE frame";
|
| const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x09,
|
| + 0x80, kVer, 0x00, 0x09,
|
| 0x00, 0x00, 0x00, 0x08,
|
| 0x00, 0x00, 0x00, 0x01,
|
| 0x00, 0x00, 0x00, 0x01,
|
| };
|
| - scoped_ptr<SpdyFrame> frame(framer.CreateWindowUpdate(1, 1));
|
| + scoped_ptr<SpdyWindowUpdateControlFrame> frame(
|
| + framer.CreateWindowUpdate(1, 1));
|
| CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
|
| - EXPECT_EQ(1u, SpdyFramer::GetControlFrameStreamId(
|
| - reinterpret_cast<const SpdyControlFrame*>(frame.get())));
|
| + EXPECT_EQ(1u, SpdyFramer::GetControlFrameStreamId(frame.get()));
|
| }
|
|
|
| {
|
| const char kDescription[] = "WINDOW_UPDATE frame with max stream ID";
|
| const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x09,
|
| + 0x80, kVer, 0x00, 0x09,
|
| 0x00, 0x00, 0x00, 0x08,
|
| 0x7f, 0xff, 0xff, 0xff,
|
| 0x00, 0x00, 0x00, 0x01,
|
| @@ -1502,7 +2156,7 @@
|
| {
|
| const char kDescription[] = "WINDOW_UPDATE frame with max window delta";
|
| const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x09,
|
| + 0x80, kVer, 0x00, 0x09,
|
| 0x00, 0x00, 0x00, 0x08,
|
| 0x00, 0x00, 0x00, 0x01,
|
| 0x7f, 0xff, 0xff, 0xff,
|
| @@ -1512,85 +2166,13 @@
|
| }
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, CreateCredential) {
|
| - SpdyFramer framer;
|
| +TEST_F(SpdyFramerSpdy2Test, DuplicateFrame) {
|
| + SpdyFramer framer(kVer);
|
|
|
| {
|
| - const char kDescription[] = "CREDENTIAL frame";
|
| - const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 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(SpdyFramerTest, ParseCredentialFrame) {
|
| - SpdyFramer framer;
|
| -
|
| - {
|
| - unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 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(SpdyFramerTest, DuplicateFrame) {
|
| - SpdyFramer framer;
|
| -
|
| - {
|
| const char kDescription[] = "PING frame";
|
| const unsigned char kFrameData[] = {
|
| - 0x80, 0x02, 0x00, 0x06,
|
| + 0x80, kVer, 0x00, 0x06,
|
| 0x00, 0x00, 0x00, 0x04,
|
| 0x12, 0x34, 0x56, 0x78,
|
| };
|
| @@ -1607,7 +2189,7 @@
|
| // 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(SpdyFramerTest, ExpandBuffer_HeapSmash) {
|
| +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;
|
| @@ -1618,7 +2200,7 @@
|
| headers["bar"] = "foo";
|
| headers["foo"] = "baz";
|
| headers["grue"] = val2.c_str();
|
| - SpdyFramer framer;
|
| + SpdyFramer framer(kVer);
|
| scoped_ptr<SpdySynStreamControlFrame> template_frame(
|
| framer.CreateSynStream(1, // stream_id
|
| 0, // associated_stream_id
|
| @@ -1635,14 +2217,158 @@
|
| }
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, ReadCredentialFrame) {
|
| +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;
|
| + SpdyFramer framer(kVer);
|
| scoped_ptr<SpdyFrame> control_frame(
|
| framer.CreateCredentialFrame(credential));
|
| EXPECT_TRUE(control_frame.get() != NULL);
|
| @@ -1662,14 +2388,14 @@
|
| }
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, ReadCredentialFrameWithCorruptProof) {
|
| +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;
|
| + SpdyFramer framer(kVer);
|
| scoped_ptr<SpdyFrame> control_frame(
|
| framer.CreateCredentialFrame(credential));
|
| EXPECT_TRUE(control_frame.get() != NULL);
|
| @@ -1684,14 +2410,14 @@
|
| EXPECT_EQ(1, visitor.error_count_);
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, ReadCredentialFrameWithCorruptCertificate) {
|
| +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;
|
| + SpdyFramer framer(kVer);
|
| scoped_ptr<SpdyFrame> control_frame(
|
| framer.CreateCredentialFrame(credential));
|
| EXPECT_TRUE(control_frame.get() != NULL);
|
| @@ -1706,8 +2432,8 @@
|
| EXPECT_EQ(1, visitor.error_count_);
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, ReadGarbage) {
|
| - SpdyFramer framer;
|
| +TEST_F(SpdyFramerSpdy2Test, ReadGarbage) {
|
| + SpdyFramer framer(kVer);
|
| unsigned char garbage_frame[256];
|
| memset(garbage_frame, ~0, sizeof(garbage_frame));
|
| TestSpdyVisitor visitor;
|
| @@ -1716,12 +2442,12 @@
|
| EXPECT_EQ(1, visitor.error_count_);
|
| }
|
|
|
| -TEST_F(SpdyFramerTest, ReadGarbageWithValidVersion) {
|
| - SpdyFramer framer;
|
| +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(kSpdyProtocolVersion);
|
| + control_frame.set_version(SPDY_VERSION_FOR_TESTS);
|
| TestSpdyVisitor visitor;
|
| visitor.use_compression_ = false;
|
| visitor.SimulateInFramer(
|
| @@ -1730,7 +2456,7 @@
|
| EXPECT_EQ(1, visitor.error_count_);
|
| }
|
|
|
| -TEST(SpdyFramer, StateToStringTest) {
|
| +TEST_F(SpdyFramerSpdy2Test, StateToStringTest) {
|
| EXPECT_STREQ("ERROR",
|
| SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR));
|
| EXPECT_STREQ("DONE",
|
| @@ -1760,12 +2486,15 @@
|
| 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_CREDENTIAL_FRAME_PAYLOAD + 1));
|
| + SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD + 1));
|
| }
|
|
|
| -TEST(SpdyFramer, ErrorCodeToStringTest) {
|
| +TEST_F(SpdyFramerSpdy2Test, ErrorCodeToStringTest) {
|
| EXPECT_STREQ("NO_ERROR",
|
| SpdyFramer::ErrorCodeToString(SpdyFramer::SPDY_NO_ERROR));
|
| EXPECT_STREQ("INVALID_CONTROL_FRAME",
|
| @@ -1790,7 +2519,7 @@
|
| SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR));
|
| }
|
|
|
| -TEST(SpdyFramer, StatusCodeToStringTest) {
|
| +TEST_F(SpdyFramerSpdy2Test, StatusCodeToStringTest) {
|
| EXPECT_STREQ("INVALID",
|
| SpdyFramer::StatusCodeToString(INVALID));
|
| EXPECT_STREQ("PROTOCOL_ERROR",
|
| @@ -1811,7 +2540,7 @@
|
| SpdyFramer::StatusCodeToString(NUM_STATUS_CODES));
|
| }
|
|
|
| -TEST(SpdyFramer, ControlTypeToStringTest) {
|
| +TEST_F(SpdyFramerSpdy2Test, ControlTypeToStringTest) {
|
| EXPECT_STREQ("SYN_STREAM",
|
| SpdyFramer::ControlTypeToString(SYN_STREAM));
|
| EXPECT_STREQ("SYN_REPLY",
|
| @@ -1830,13 +2559,13 @@
|
| SpdyFramer::ControlTypeToString(HEADERS));
|
| EXPECT_STREQ("WINDOW_UPDATE",
|
| SpdyFramer::ControlTypeToString(WINDOW_UPDATE));
|
| - EXPECT_STREQ("SETTINGS",
|
| - SpdyFramer::ControlTypeToString(SETTINGS));
|
| + EXPECT_STREQ("CREDENTIAL",
|
| + SpdyFramer::ControlTypeToString(CREDENTIAL));
|
| EXPECT_STREQ("UNKNOWN_CONTROL_TYPE",
|
| SpdyFramer::ControlTypeToString(NUM_CONTROL_FRAME_TYPES));
|
| }
|
|
|
| -TEST(SpdyFramer, GetMinimumControlFrameSizeTest) {
|
| +TEST_F(SpdyFramerSpdy2Test, GetMinimumControlFrameSizeTest) {
|
| EXPECT_EQ(SpdySynStreamControlFrame::size(),
|
| SpdyFramer::GetMinimumControlFrameSize(SYN_STREAM));
|
| EXPECT_EQ(SpdySynReplyControlFrame::size(),
|
| @@ -1845,7 +2574,7 @@
|
| SpdyFramer::GetMinimumControlFrameSize(RST_STREAM));
|
| EXPECT_EQ(SpdySettingsControlFrame::size(),
|
| SpdyFramer::GetMinimumControlFrameSize(SETTINGS));
|
| - EXPECT_EQ(SpdyNoOpControlFrame::size(),
|
| + EXPECT_EQ(SpdyFrame::kHeaderSize,
|
| SpdyFramer::GetMinimumControlFrameSize(NOOP));
|
| EXPECT_EQ(SpdyPingControlFrame::size(),
|
| SpdyFramer::GetMinimumControlFrameSize(PING));
|
| @@ -1861,11 +2590,34 @@
|
| SpdyFramer::GetMinimumControlFrameSize(NUM_CONTROL_FRAME_TYPES));
|
| }
|
|
|
| -std::string RandomString(int length) {
|
| - std::string rv;
|
| - for (int index = 0; index < length; index++)
|
| - rv += static_cast<char>('a' + (rand() % 26));
|
| - return rv;
|
| +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
|
|
|