Home | History | Annotate | Download | only in spdy
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <algorithm>
      6 #include <iostream>
      7 #include <limits>
      8 
      9 #include "base/compiler_specific.h"
     10 #include "base/memory/scoped_ptr.h"
     11 #include "net/spdy/spdy_frame_builder.h"
     12 #include "net/spdy/spdy_framer.h"
     13 #include "net/spdy/spdy_protocol.h"
     14 #include "net/spdy/spdy_test_utils.h"
     15 #include "testing/gmock/include/gmock/gmock.h"
     16 #include "testing/platform_test.h"
     17 
     18 using std::string;
     19 using std::max;
     20 using std::min;
     21 using std::numeric_limits;
     22 using testing::_;
     23 
     24 namespace net {
     25 
     26 namespace test {
     27 
     28 static const size_t kMaxDecompressedSize = 1024;
     29 
     30 // TODO(akalin): Make sure expectations on mocks are set before mock
     31 // functions are called, as interleaving expectations and calls is
     32 // undefined.
     33 class MockVisitor : public SpdyFramerVisitorInterface {
     34  public:
     35   MOCK_METHOD1(OnError, void(SpdyFramer* framer));
     36   MOCK_METHOD3(OnDataFrameHeader, void(SpdyStreamId stream_id,
     37                                        size_t length,
     38                                        bool fin));
     39   MOCK_METHOD4(OnStreamFrameData, void(SpdyStreamId stream_id,
     40                                        const char* data,
     41                                        size_t len,
     42                                        bool fin));
     43   MOCK_METHOD3(OnControlFrameHeaderData, bool(SpdyStreamId stream_id,
     44                                               const char* header_data,
     45                                               size_t len));
     46   MOCK_METHOD6(OnSynStream, void(SpdyStreamId stream_id,
     47                                  SpdyStreamId associated_stream_id,
     48                                  SpdyPriority priority,
     49                                  uint8 slot,
     50                                  bool fin,
     51                                  bool unidirectional));
     52   MOCK_METHOD2(OnSynReply, void(SpdyStreamId stream_id, bool fin));
     53   MOCK_METHOD2(OnRstStream, void(SpdyStreamId stream_id,
     54                                  SpdyRstStreamStatus status));
     55   MOCK_METHOD1(OnSettings, void(bool clear_persisted));
     56   MOCK_METHOD3(OnSetting, void(SpdySettingsIds id, uint8 flags, uint32 value));
     57   MOCK_METHOD1(OnPing, void(uint32 unique_id));
     58   MOCK_METHOD2(OnGoAway, void(SpdyStreamId last_accepted_stream_id,
     59                               SpdyGoAwayStatus status));
     60   MOCK_METHOD2(OnHeaders, void(SpdyStreamId stream_id, bool fin));
     61   MOCK_METHOD2(OnWindowUpdate, void(SpdyStreamId stream_id,
     62                                     uint32 delta_window_size));
     63   MOCK_METHOD2(OnCredentialFrameData, bool(const char* credential_data,
     64                                            size_t len));
     65   MOCK_METHOD1(OnBlocked, void(SpdyStreamId stream_id));
     66   MOCK_METHOD2(OnPushPromise, void(SpdyStreamId stream_id,
     67                                    SpdyStreamId promised_stream_id));
     68 };
     69 
     70 class MockDebugVisitor : public SpdyFramerDebugVisitorInterface {
     71  public:
     72   MOCK_METHOD4(OnSendCompressedFrame, void(SpdyStreamId stream_id,
     73                                            SpdyFrameType type,
     74                                            size_t payload_len,
     75                                            size_t frame_len));
     76 
     77   MOCK_METHOD3(OnReceiveCompressedFrame, void(SpdyStreamId stream_id,
     78                                               SpdyFrameType type,
     79                                               size_t frame_len));
     80 };
     81 
     82 class SpdyFramerTestUtil {
     83  public:
     84   // Decompress a single frame using the decompression context held by
     85   // the SpdyFramer.  The implemention is meant for use only in tests
     86   // and will CHECK fail if the input is anything other than a single,
     87   // well-formed compressed frame.
     88   //
     89   // Returns a new decompressed SpdyFrame.
     90   template<class SpdyFrameType> static SpdyFrame* DecompressFrame(
     91       SpdyFramer* framer, const SpdyFrameType& frame) {
     92     DecompressionVisitor visitor(framer->protocol_version());
     93     framer->set_visitor(&visitor);
     94     CHECK_EQ(frame.size(), framer->ProcessInput(frame.data(), frame.size()));
     95     CHECK_EQ(SpdyFramer::SPDY_RESET, framer->state());
     96     framer->set_visitor(NULL);
     97 
     98     char* buffer = visitor.ReleaseBuffer();
     99     CHECK(buffer != NULL);
    100     SpdyFrame* decompressed_frame = new SpdyFrame(buffer, visitor.size(), true);
    101     if (framer->protocol_version() == 4) {
    102       SetFrameLength(decompressed_frame,
    103                      visitor.size(),
    104                      framer->protocol_version());
    105     } else {
    106       SetFrameLength(decompressed_frame,
    107                      visitor.size() - framer->GetControlFrameHeaderSize(),
    108                      framer->protocol_version());
    109     }
    110     return decompressed_frame;
    111   }
    112 
    113   class DecompressionVisitor : public SpdyFramerVisitorInterface {
    114    public:
    115     explicit DecompressionVisitor(SpdyMajorVersion version)
    116         : version_(version), size_(0), finished_(false) {}
    117 
    118     void ResetBuffer() {
    119       CHECK(buffer_.get() == NULL);
    120       CHECK_EQ(0u, size_);
    121       CHECK(!finished_);
    122       buffer_.reset(new char[kMaxDecompressedSize]);
    123     }
    124 
    125     virtual void OnError(SpdyFramer* framer) OVERRIDE { LOG(FATAL); }
    126     virtual void OnDataFrameHeader(SpdyStreamId stream_id,
    127                                    size_t length,
    128                                    bool fin) OVERRIDE {
    129       LOG(FATAL) << "Unexpected data frame header";
    130     }
    131     virtual void OnStreamFrameData(SpdyStreamId stream_id,
    132                                    const char* data,
    133                                    size_t len,
    134                                    bool fin) OVERRIDE {
    135       LOG(FATAL);
    136     }
    137 
    138     virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id,
    139                                           const char* header_data,
    140                                           size_t len) OVERRIDE {
    141       CHECK(buffer_.get() != NULL);
    142       CHECK_GE(kMaxDecompressedSize, size_ + len);
    143       CHECK(!finished_);
    144       if (len != 0) {
    145         memcpy(buffer_.get() + size_, header_data, len);
    146         size_ += len;
    147       } else {
    148         // Done.
    149         finished_ = true;
    150       }
    151       return true;
    152     }
    153 
    154     virtual void OnSynStream(SpdyStreamId stream_id,
    155                              SpdyStreamId associated_stream_id,
    156                              SpdyPriority priority,
    157                              uint8 slot,
    158                              bool fin,
    159                              bool unidirectional) OVERRIDE {
    160       SpdyFramer framer(version_);
    161       framer.set_enable_compression(false);
    162       const SpdyHeaderBlock null_headers;
    163       int flags = CONTROL_FLAG_NONE;
    164       if (fin) {
    165         flags &= CONTROL_FLAG_FIN;
    166       }
    167       if (unidirectional) {
    168         flags &= CONTROL_FLAG_UNIDIRECTIONAL;
    169       }
    170       scoped_ptr<SpdyFrame> frame(
    171           framer.CreateSynStream(stream_id,
    172                                  associated_stream_id,
    173                                  priority,
    174                                  slot,
    175                                  static_cast<SpdyControlFlags>(flags),
    176                                  false,
    177                                  &null_headers));
    178       ResetBuffer();
    179       memcpy(buffer_.get(), frame->data(), framer.GetSynStreamMinimumSize());
    180       size_ += framer.GetSynStreamMinimumSize();
    181     }
    182 
    183     virtual void OnSynReply(SpdyStreamId stream_id, bool fin) OVERRIDE {
    184       SpdyFramer framer(version_);
    185       framer.set_enable_compression(false);
    186       const SpdyHeaderBlock null_headers;
    187       int flags = CONTROL_FLAG_NONE;
    188       if (fin) {
    189         flags &= CONTROL_FLAG_FIN;
    190       }
    191       scoped_ptr<SpdyFrame> frame(
    192           framer.CreateHeaders(stream_id,
    193                                static_cast<SpdyControlFlags>(flags),
    194                                false,
    195                                &null_headers));
    196       ResetBuffer();
    197       memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
    198       size_ += framer.GetSynStreamMinimumSize();
    199     }
    200 
    201     virtual void OnRstStream(SpdyStreamId stream_id,
    202                              SpdyRstStreamStatus status) OVERRIDE {
    203       LOG(FATAL);
    204     }
    205     virtual void OnSetting(SpdySettingsIds id,
    206                            uint8 flags,
    207                            uint32 value) OVERRIDE {
    208       LOG(FATAL);
    209     }
    210     virtual void OnPing(uint32 unique_id) OVERRIDE {
    211       LOG(FATAL);
    212     }
    213     virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
    214                           SpdyGoAwayStatus status) OVERRIDE {
    215       LOG(FATAL);
    216     }
    217 
    218     virtual void OnHeaders(SpdyStreamId stream_id, bool fin) OVERRIDE {
    219       SpdyFramer framer(version_);
    220       framer.set_enable_compression(false);
    221       const SpdyHeaderBlock null_headers;
    222       int flags = CONTROL_FLAG_NONE;
    223       if (fin) {
    224         flags &= CONTROL_FLAG_FIN;
    225       }
    226       scoped_ptr<SpdyFrame> frame(
    227           framer.CreateHeaders(stream_id,
    228                                static_cast<SpdyControlFlags>(flags),
    229                                false,
    230                                &null_headers));
    231       ResetBuffer();
    232       memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
    233       size_ += framer.GetHeadersMinimumSize();
    234     }
    235 
    236     virtual void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) {
    237       LOG(FATAL);
    238     }
    239     virtual bool OnCredentialFrameData(const char* /*credential_data*/,
    240                                        size_t /*len*/) OVERRIDE {
    241       LOG(FATAL) << "Unexpected CREDENTIAL Frame";
    242       return false;
    243     }
    244 
    245     virtual void OnPushPromise(SpdyStreamId stream_id,
    246                                SpdyStreamId promised_stream_id) OVERRIDE {
    247       SpdyFramer framer(version_);
    248       framer.set_enable_compression(false);
    249       const SpdyHeaderBlock null_headers;
    250       scoped_ptr<SpdyFrame> frame(
    251           framer.CreatePushPromise(stream_id, promised_stream_id,
    252                                    &null_headers));
    253       ResetBuffer();
    254       memcpy(buffer_.get(), frame->data(), framer.GetPushPromiseMinimumSize());
    255       size_ += framer.GetPushPromiseMinimumSize();
    256     }
    257 
    258     char* ReleaseBuffer() {
    259       CHECK(finished_);
    260       return buffer_.release();
    261     }
    262 
    263     virtual void OnWindowUpdate(SpdyStreamId stream_id,
    264                                 uint32 delta_window_size) OVERRIDE {
    265       LOG(FATAL);
    266     }
    267 
    268     size_t size() const {
    269       CHECK(finished_);
    270       return size_;
    271     }
    272 
    273    private:
    274     SpdyMajorVersion version_;
    275     scoped_ptr<char[]> buffer_;
    276     size_t size_;
    277     bool finished_;
    278 
    279     DISALLOW_COPY_AND_ASSIGN(DecompressionVisitor);
    280   };
    281 
    282  private:
    283   DISALLOW_COPY_AND_ASSIGN(SpdyFramerTestUtil);
    284 };
    285 
    286 class TestSpdyVisitor : public SpdyFramerVisitorInterface,
    287                         public SpdyFramerDebugVisitorInterface {
    288  public:
    289   static const size_t kDefaultHeaderBufferSize = 16 * 1024 * 1024;
    290   static const size_t kDefaultCredentialBufferSize = 16 * 1024;
    291 
    292   explicit TestSpdyVisitor(SpdyMajorVersion version)
    293     : framer_(version),
    294       use_compression_(false),
    295       error_count_(0),
    296       syn_frame_count_(0),
    297       syn_reply_frame_count_(0),
    298       headers_frame_count_(0),
    299       goaway_count_(0),
    300       setting_count_(0),
    301       last_window_update_stream_(0),
    302       last_window_update_delta_(0),
    303       last_push_promise_stream_(0),
    304       last_push_promise_promised_stream_(0),
    305       data_bytes_(0),
    306       fin_frame_count_(0),
    307       fin_flag_count_(0),
    308       zero_length_data_frame_count_(0),
    309       control_frame_header_data_count_(0),
    310       zero_length_control_frame_header_data_count_(0),
    311       data_frame_count_(0),
    312       last_payload_len_(0),
    313       last_frame_len_(0),
    314       header_buffer_(new char[kDefaultHeaderBufferSize]),
    315       header_buffer_length_(0),
    316       header_buffer_size_(kDefaultHeaderBufferSize),
    317       header_stream_id_(-1),
    318       header_control_type_(DATA),
    319       header_buffer_valid_(false),
    320       credential_buffer_(new char[kDefaultCredentialBufferSize]),
    321       credential_buffer_length_(0),
    322       credential_buffer_size_(kDefaultCredentialBufferSize) {
    323   }
    324 
    325   virtual void OnError(SpdyFramer* f) OVERRIDE {
    326     LOG(INFO) << "SpdyFramer Error: "
    327               << SpdyFramer::ErrorCodeToString(f->error_code());
    328     error_count_++;
    329   }
    330 
    331   virtual void OnDataFrameHeader(SpdyStreamId stream_id,
    332                                  size_t length,
    333                                  bool fin) OVERRIDE {
    334     data_frame_count_++;
    335     header_stream_id_ = stream_id;
    336   }
    337 
    338   virtual void OnStreamFrameData(SpdyStreamId stream_id,
    339                                  const char* data,
    340                                  size_t len,
    341                                  bool fin) OVERRIDE {
    342     EXPECT_EQ(header_stream_id_, stream_id);
    343     if (len == 0)
    344       ++zero_length_data_frame_count_;
    345 
    346     data_bytes_ += len;
    347     std::cerr << "OnStreamFrameData(" << stream_id << ", \"";
    348     if (len > 0) {
    349       for (size_t i = 0 ; i < len; ++i) {
    350         std::cerr << std::hex << (0xFF & (unsigned int)data[i]) << std::dec;
    351       }
    352     }
    353     std::cerr << "\", " << len << ")\n";
    354   }
    355 
    356   virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id,
    357                                         const char* header_data,
    358                                         size_t len) OVERRIDE {
    359     ++control_frame_header_data_count_;
    360     CHECK_EQ(header_stream_id_, stream_id);
    361     if (len == 0) {
    362       ++zero_length_control_frame_header_data_count_;
    363       // Indicates end-of-header-block.
    364       CHECK(header_buffer_valid_);
    365       size_t parsed_length = framer_.ParseHeaderBlockInBuffer(
    366           header_buffer_.get(), header_buffer_length_, &headers_);
    367       DCHECK_EQ(header_buffer_length_, parsed_length);
    368       return true;
    369     }
    370     const size_t available = header_buffer_size_ - header_buffer_length_;
    371     if (len > available) {
    372       header_buffer_valid_ = false;
    373       return false;
    374     }
    375     memcpy(header_buffer_.get() + header_buffer_length_, header_data, len);
    376     header_buffer_length_ += len;
    377     return true;
    378   }
    379 
    380   virtual void OnSynStream(SpdyStreamId stream_id,
    381                            SpdyStreamId associated_stream_id,
    382                            SpdyPriority priority,
    383                            uint8 credential_slot,
    384                            bool fin,
    385                            bool unidirectional) OVERRIDE {
    386     syn_frame_count_++;
    387     InitHeaderStreaming(SYN_STREAM, stream_id);
    388     if (fin) {
    389       fin_flag_count_++;
    390     }
    391   }
    392 
    393   virtual void OnSynReply(SpdyStreamId stream_id, bool fin) OVERRIDE {
    394     syn_reply_frame_count_++;
    395     InitHeaderStreaming(SYN_REPLY, stream_id);
    396     if (fin) {
    397       fin_flag_count_++;
    398     }
    399   }
    400 
    401   virtual void OnRstStream(SpdyStreamId stream_id,
    402                            SpdyRstStreamStatus status) OVERRIDE {
    403     fin_frame_count_++;
    404   }
    405 
    406   virtual void OnSetting(SpdySettingsIds id,
    407                          uint8 flags,
    408                          uint32 value) OVERRIDE {
    409     setting_count_++;
    410   }
    411 
    412   virtual void OnPing(uint32 unique_id) OVERRIDE {
    413     DLOG(FATAL);
    414   }
    415 
    416   virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
    417                         SpdyGoAwayStatus status) OVERRIDE {
    418     goaway_count_++;
    419   }
    420 
    421   virtual void OnHeaders(SpdyStreamId stream_id, bool fin) OVERRIDE {
    422     headers_frame_count_++;
    423     InitHeaderStreaming(HEADERS, stream_id);
    424     if (fin) {
    425       fin_flag_count_++;
    426     }
    427   }
    428 
    429   virtual void OnWindowUpdate(SpdyStreamId stream_id,
    430                               uint32 delta_window_size) OVERRIDE {
    431     last_window_update_stream_ = stream_id;
    432     last_window_update_delta_ = delta_window_size;
    433   }
    434 
    435   virtual bool OnCredentialFrameData(const char* credential_data,
    436                                      size_t len) OVERRIDE {
    437     if (len == 0) {
    438       if (!framer_.ParseCredentialData(credential_buffer_.get(),
    439                                        credential_buffer_length_,
    440                                        &credential_)) {
    441         LOG(INFO) << "Error parsing credential data.";
    442         ++error_count_;
    443       }
    444       return true;
    445     }
    446     const size_t available =
    447         credential_buffer_size_ - credential_buffer_length_;
    448     if (len > available) {
    449       return false;
    450     }
    451     memcpy(credential_buffer_.get() + credential_buffer_length_,
    452            credential_data, len);
    453     credential_buffer_length_ += len;
    454     return true;
    455   }
    456 
    457   virtual void OnPushPromise(SpdyStreamId stream_id,
    458                              SpdyStreamId promised_stream_id) OVERRIDE {
    459     InitHeaderStreaming(PUSH_PROMISE, stream_id);
    460     last_push_promise_stream_ = stream_id;
    461     last_push_promise_promised_stream_ = promised_stream_id;
    462   }
    463 
    464   virtual void OnSendCompressedFrame(SpdyStreamId stream_id,
    465                                      SpdyFrameType type,
    466                                      size_t payload_len,
    467                                      size_t frame_len) OVERRIDE {
    468     last_payload_len_ = payload_len;
    469     last_frame_len_ = frame_len;
    470   }
    471 
    472   virtual void OnReceiveCompressedFrame(SpdyStreamId stream_id,
    473                                         SpdyFrameType type,
    474                                         size_t frame_len) OVERRIDE {
    475     last_frame_len_ = frame_len;
    476   }
    477 
    478   // Convenience function which runs a framer simulation with particular input.
    479   void SimulateInFramer(const unsigned char* input, size_t size) {
    480     framer_.set_enable_compression(use_compression_);
    481     framer_.set_visitor(this);
    482     size_t input_remaining = size;
    483     const char* input_ptr = reinterpret_cast<const char*>(input);
    484     while (input_remaining > 0 &&
    485            framer_.error_code() == SpdyFramer::SPDY_NO_ERROR) {
    486       // To make the tests more interesting, we feed random (amd small) chunks
    487       // into the framer.  This simulates getting strange-sized reads from
    488       // the socket.
    489       const size_t kMaxReadSize = 32;
    490       size_t bytes_read =
    491           (rand() % min(input_remaining, kMaxReadSize)) + 1;
    492       size_t bytes_processed = framer_.ProcessInput(input_ptr, bytes_read);
    493       input_remaining -= bytes_processed;
    494       input_ptr += bytes_processed;
    495     }
    496   }
    497 
    498   void InitHeaderStreaming(SpdyFrameType header_control_type,
    499                            SpdyStreamId stream_id) {
    500     DCHECK_GE(header_control_type, FIRST_CONTROL_TYPE);
    501     DCHECK_LE(header_control_type, LAST_CONTROL_TYPE);
    502     memset(header_buffer_.get(), 0, header_buffer_size_);
    503     header_buffer_length_ = 0;
    504     header_stream_id_ = stream_id;
    505     header_control_type_ = header_control_type;
    506     header_buffer_valid_ = true;
    507     DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream);
    508   }
    509 
    510   // Override the default buffer size (16K). Call before using the framer!
    511   void set_header_buffer_size(size_t header_buffer_size) {
    512     header_buffer_size_ = header_buffer_size;
    513     header_buffer_.reset(new char[header_buffer_size]);
    514   }
    515 
    516   static size_t header_data_chunk_max_size() {
    517     return SpdyFramer::kHeaderDataChunkMaxSize;
    518   }
    519 
    520   SpdyFramer framer_;
    521   bool use_compression_;
    522 
    523   // Counters from the visitor callbacks.
    524   int error_count_;
    525   int syn_frame_count_;
    526   int syn_reply_frame_count_;
    527   int headers_frame_count_;
    528   int goaway_count_;
    529   int setting_count_;
    530   SpdyStreamId last_window_update_stream_;
    531   uint32 last_window_update_delta_;
    532   SpdyStreamId last_push_promise_stream_;
    533   SpdyStreamId last_push_promise_promised_stream_;
    534   int data_bytes_;
    535   int fin_frame_count_;  // The count of RST_STREAM type frames received.
    536   int fin_flag_count_;  // The count of frames with the FIN flag set.
    537   int zero_length_data_frame_count_;  // The count of zero-length data frames.
    538   int control_frame_header_data_count_;  // The count of chunks received.
    539   // The count of zero-length control frame header data chunks received.
    540   int zero_length_control_frame_header_data_count_;
    541   int data_frame_count_;
    542   size_t last_payload_len_;
    543   size_t last_frame_len_;
    544 
    545   // Header block streaming state:
    546   scoped_ptr<char[]> header_buffer_;
    547   size_t header_buffer_length_;
    548   size_t header_buffer_size_;
    549   SpdyStreamId header_stream_id_;
    550   SpdyFrameType header_control_type_;
    551   bool header_buffer_valid_;
    552   SpdyHeaderBlock headers_;
    553 
    554   scoped_ptr<char[]> credential_buffer_;
    555   size_t credential_buffer_length_;
    556   size_t credential_buffer_size_;
    557   SpdyCredential credential_;
    558 };
    559 
    560 // Retrieves serialized headers from SYN_STREAM frame.
    561 // Does not check that the given frame is a SYN_STREAM.
    562 base::StringPiece GetSerializedHeaders(const SpdyFrame* frame,
    563                                        const SpdyFramer& framer) {
    564   return base::StringPiece(frame->data() + framer.GetSynStreamMinimumSize(),
    565                            frame->size() - framer.GetSynStreamMinimumSize());
    566 }
    567 
    568 }  // namespace test
    569 
    570 }  // namespace net
    571 
    572 using net::test::SetFrameLength;
    573 using net::test::SetFrameFlags;
    574 using net::test::CompareCharArraysWithHexError;
    575 using net::test::SpdyFramerTestUtil;
    576 using net::test::TestSpdyVisitor;
    577 using net::test::GetSerializedHeaders;
    578 
    579 namespace net {
    580 
    581 class SpdyFramerTest : public ::testing::TestWithParam<SpdyMajorVersion> {
    582  protected:
    583   virtual void SetUp() {
    584     spdy_version_ = GetParam();
    585     spdy_version_ch_ = static_cast<unsigned char>(spdy_version_);
    586   }
    587 
    588   void CompareFrame(const string& description,
    589                     const SpdyFrame& actual_frame,
    590                     const unsigned char* expected,
    591                     const int expected_len) {
    592     const unsigned char* actual =
    593         reinterpret_cast<const unsigned char*>(actual_frame.data());
    594     CompareCharArraysWithHexError(
    595         description, actual, actual_frame.size(), expected, expected_len);
    596   }
    597 
    598   void CompareFrames(const string& description,
    599                      const SpdyFrame& expected_frame,
    600                      const SpdyFrame& actual_frame) {
    601     CompareCharArraysWithHexError(
    602         description,
    603         reinterpret_cast<const unsigned char*>(expected_frame.data()),
    604         expected_frame.size(),
    605         reinterpret_cast<const unsigned char*>(actual_frame.data()),
    606         actual_frame.size());
    607   }
    608 
    609   // Returns true if the two header blocks have equivalent content.
    610   bool CompareHeaderBlocks(const SpdyHeaderBlock* expected,
    611                            const SpdyHeaderBlock* actual) {
    612     if (expected->size() != actual->size()) {
    613       LOG(ERROR) << "Expected " << expected->size() << " headers; actually got "
    614                  << actual->size() << ".";
    615       return false;
    616     }
    617     for (SpdyHeaderBlock::const_iterator it = expected->begin();
    618          it != expected->end();
    619          ++it) {
    620       SpdyHeaderBlock::const_iterator it2 = actual->find(it->first);
    621       if (it2 == actual->end()) {
    622         LOG(ERROR) << "Expected header name '" << it->first << "'.";
    623         return false;
    624       }
    625       if (it->second.compare(it2->second) != 0) {
    626         LOG(ERROR) << "Expected header named '" << it->first
    627                    << "' to have a value of '" << it->second
    628                    << "'. The actual value received was '" << it2->second
    629                    << "'.";
    630         return false;
    631       }
    632     }
    633     return true;
    634   }
    635 
    636   void AddSpdySettingFromWireFormat(SettingsMap* settings,
    637                                     uint32 key,
    638                                     uint32 value) {
    639     SettingsFlagsAndId flags_and_id =
    640         SettingsFlagsAndId::FromWireFormat(spdy_version_, key);
    641     SpdySettingsIds id = static_cast<SpdySettingsIds>(flags_and_id.id());
    642     SpdySettingsFlags flags =
    643         static_cast<SpdySettingsFlags>(flags_and_id.flags());
    644     CHECK(settings->find(id) == settings->end());
    645     settings->insert(std::make_pair(id, SettingsFlagsAndValue(flags, value)));
    646   }
    647 
    648   bool IsSpdy2() { return spdy_version_ == SPDY2; }
    649   bool IsSpdy3() { return spdy_version_ == SPDY3; }
    650   bool IsSpdy4() { return spdy_version_ == SPDY4; }
    651 
    652   // Version of SPDY protocol to be used.
    653   SpdyMajorVersion spdy_version_;
    654   unsigned char spdy_version_ch_;
    655 };
    656 
    657 // All tests are run with 3 different SPDY versions: SPDY/2, SPDY/3, SPDY/4.
    658 INSTANTIATE_TEST_CASE_P(SpdyFramerTests,
    659                         SpdyFramerTest,
    660                         ::testing::Values(SPDY2, SPDY3, SPDY4));
    661 
    662 // Test that we can encode and decode a SpdyHeaderBlock in serialized form.
    663 TEST_P(SpdyFramerTest, HeaderBlockInBuffer) {
    664   SpdyHeaderBlock headers;
    665   headers["alpha"] = "beta";
    666   headers["gamma"] = "charlie";
    667   SpdyFramer framer(spdy_version_);
    668   framer.set_enable_compression(false);
    669 
    670   // Encode the header block into a SynStream frame.
    671   scoped_ptr<SpdyFrame> frame(
    672       framer.CreateSynStream(1,  // stream id
    673                              0,  // associated stream id
    674                              1,  // priority
    675                              0,  // credential slot
    676                              CONTROL_FLAG_NONE,
    677                              false,  // compress
    678                              &headers));
    679   EXPECT_TRUE(frame.get() != NULL);
    680   base::StringPiece serialized_headers =
    681       GetSerializedHeaders(frame.get(), framer);
    682   SpdyHeaderBlock new_headers;
    683   EXPECT_TRUE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
    684                                               serialized_headers.size(),
    685                                               &new_headers));
    686 
    687   EXPECT_EQ(headers.size(), new_headers.size());
    688   EXPECT_EQ(headers["alpha"], new_headers["alpha"]);
    689   EXPECT_EQ(headers["gamma"], new_headers["gamma"]);
    690 }
    691 
    692 // Test that if there's not a full frame, we fail to parse it.
    693 TEST_P(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
    694   SpdyHeaderBlock headers;
    695   headers["alpha"] = "beta";
    696   headers["gamma"] = "charlie";
    697   SpdyFramer framer(spdy_version_);
    698   framer.set_enable_compression(false);
    699 
    700   // Encode the header block into a SynStream frame.
    701   scoped_ptr<SpdyFrame> frame(
    702       framer.CreateSynStream(1,  // stream id
    703                              0,  // associated stream id
    704                              1,  // priority
    705                              0,  // credential slot
    706                              CONTROL_FLAG_NONE,
    707                              false,  // compress
    708                              &headers));
    709   EXPECT_TRUE(frame.get() != NULL);
    710 
    711   base::StringPiece serialized_headers =
    712       GetSerializedHeaders(frame.get(), framer);
    713   SpdyHeaderBlock new_headers;
    714   EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
    715                                                serialized_headers.size() - 2,
    716                                                &new_headers));
    717 }
    718 
    719 TEST_P(SpdyFramerTest, OutOfOrderHeaders) {
    720   SpdyFramer framer(spdy_version_);
    721   framer.set_enable_compression(false);
    722 
    723   // Frame builder with plentiful buffer size.
    724   SpdyFrameBuilder frame(1024);
    725   if (spdy_version_ < 4) {
    726     frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
    727     frame.WriteUInt32(3);  // stream_id
    728   } else {
    729     frame.WriteFramePrefix(framer, SYN_STREAM, CONTROL_FLAG_NONE, 3);
    730   }
    731 
    732   frame.WriteUInt32(0);  // Associated stream id
    733   frame.WriteUInt16(0);  // Priority.
    734 
    735   if (IsSpdy2()) {
    736     frame.WriteUInt16(2);  // Number of headers.
    737     frame.WriteString("gamma");
    738     frame.WriteString("gamma");
    739     frame.WriteString("alpha");
    740     frame.WriteString("alpha");
    741   } else {
    742     frame.WriteUInt32(2);  // Number of headers.
    743     frame.WriteStringPiece32("gamma");
    744     frame.WriteStringPiece32("gamma");
    745     frame.WriteStringPiece32("alpha");
    746     frame.WriteStringPiece32("alpha");
    747   }
    748   // write the length
    749   frame.RewriteLength(framer);
    750 
    751   SpdyHeaderBlock new_headers;
    752   scoped_ptr<SpdyFrame> control_frame(frame.take());
    753   base::StringPiece serialized_headers =
    754       GetSerializedHeaders(control_frame.get(), framer);
    755   EXPECT_TRUE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
    756                                               serialized_headers.size(),
    757                                               &new_headers));
    758 }
    759 
    760 // Test that if we receive a SYN_STREAM with stream ID zero, we signal an error
    761 // (but don't crash).
    762 TEST_P(SpdyFramerTest, SynStreamWithStreamIdZero) {
    763   testing::StrictMock<net::test::MockVisitor> visitor;
    764   SpdyFramer framer(spdy_version_);
    765   framer.set_visitor(&visitor);
    766 
    767   SpdyHeaderBlock headers;
    768   headers["alpha"] = "beta";
    769   scoped_ptr<SpdySerializedFrame> frame(
    770       framer.CreateSynStream(0,  // stream id
    771                              0,  // associated stream id
    772                              1,  // priority
    773                              0,  // credential slot
    774                              CONTROL_FLAG_NONE,
    775                              true,  // compress
    776                              &headers));
    777   ASSERT_TRUE(frame.get() != NULL);
    778 
    779   // We shouldn't have to read the whole frame before we signal an error.
    780   EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
    781   EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
    782   EXPECT_TRUE(framer.HasError());
    783   EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
    784       << SpdyFramer::ErrorCodeToString(framer.error_code());
    785 }
    786 
    787 // Test that if we receive a SYN_REPLY with stream ID zero, we signal an error
    788 // (but don't crash).
    789 TEST_P(SpdyFramerTest, SynReplyWithStreamIdZero) {
    790   testing::StrictMock<net::test::MockVisitor> visitor;
    791   SpdyFramer framer(spdy_version_);
    792   framer.set_visitor(&visitor);
    793 
    794   SpdyHeaderBlock headers;
    795   headers["alpha"] = "beta";
    796   scoped_ptr<SpdySerializedFrame> frame(
    797       framer.CreateSynReply(0,  // stream id
    798                             CONTROL_FLAG_NONE,
    799                             true,  // compress
    800                             &headers));
    801   ASSERT_TRUE(frame.get() != NULL);
    802 
    803   // We shouldn't have to read the whole frame before we signal an error.
    804   EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
    805   EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
    806   EXPECT_TRUE(framer.HasError());
    807   EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
    808       << SpdyFramer::ErrorCodeToString(framer.error_code());
    809 }
    810 
    811 // Test that if we receive a HEADERS with stream ID zero, we signal an error
    812 // (but don't crash).
    813 TEST_P(SpdyFramerTest, HeadersWithStreamIdZero) {
    814   testing::StrictMock<net::test::MockVisitor> visitor;
    815   SpdyFramer framer(spdy_version_);
    816   framer.set_visitor(&visitor);
    817 
    818   SpdyHeaderBlock headers;
    819   headers["alpha"] = "beta";
    820   scoped_ptr<SpdySerializedFrame> frame(
    821       framer.CreateHeaders(0,  // stream id
    822                            CONTROL_FLAG_NONE,
    823                            true,  // compress
    824                            &headers));
    825   ASSERT_TRUE(frame.get() != NULL);
    826 
    827   // We shouldn't have to read the whole frame before we signal an error.
    828   EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
    829   EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
    830   EXPECT_TRUE(framer.HasError());
    831   EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
    832       << SpdyFramer::ErrorCodeToString(framer.error_code());
    833 }
    834 
    835 // Test that if we receive a PUSH_PROMISE with stream ID zero, we signal an
    836 // error (but don't crash).
    837 TEST_P(SpdyFramerTest, PushPromiseWithStreamIdZero) {
    838   if (spdy_version_ < SPDY4) {
    839     return;
    840   }
    841 
    842   testing::StrictMock<net::test::MockVisitor> visitor;
    843   SpdyFramer framer(spdy_version_);
    844   framer.set_visitor(&visitor);
    845 
    846   SpdyHeaderBlock headers;
    847   headers["alpha"] = "beta";
    848   scoped_ptr<SpdySerializedFrame> frame(
    849       framer.CreatePushPromise(0,  // stream id
    850                                4,  // promised stream id
    851                                &headers));
    852   ASSERT_TRUE(frame.get() != NULL);
    853 
    854   // We shouldn't have to read the whole frame before we signal an error.
    855   EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
    856   EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
    857   EXPECT_TRUE(framer.HasError());
    858   EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
    859       << SpdyFramer::ErrorCodeToString(framer.error_code());
    860 }
    861 
    862 // Test that if we receive a PUSH_PROMISE with promised stream ID zero, we
    863 // signal an error (but don't crash).
    864 TEST_P(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) {
    865   if (spdy_version_ < SPDY4) {
    866     return;
    867   }
    868 
    869   testing::StrictMock<net::test::MockVisitor> visitor;
    870   SpdyFramer framer(spdy_version_);
    871   framer.set_visitor(&visitor);
    872 
    873   SpdyHeaderBlock headers;
    874   headers["alpha"] = "beta";
    875   scoped_ptr<SpdySerializedFrame> frame(
    876       framer.CreatePushPromise(3,  // stream id
    877                                0,  // promised stream id
    878                                &headers));
    879   ASSERT_TRUE(frame.get() != NULL);
    880 
    881   // We shouldn't have to read the whole frame before we signal an error.
    882   EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
    883   EXPECT_GT(frame->size(), framer.ProcessInput(frame->data(), frame->size()));
    884   EXPECT_TRUE(framer.HasError());
    885   EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
    886       << SpdyFramer::ErrorCodeToString(framer.error_code());
    887 }
    888 
    889 TEST_P(SpdyFramerTest, CreateCredential) {
    890   SpdyFramer framer(spdy_version_);
    891 
    892   {
    893     const char kDescription[] = "CREDENTIAL frame";
    894     const unsigned char kV3FrameData[] = {  // Also applies for V2.
    895       0x80, spdy_version_ch_, 0x00, 0x0A,
    896       0x00, 0x00, 0x00, 0x33,
    897       0x00, 0x03, 0x00, 0x00,
    898       0x00, 0x05, 'p',  'r',
    899       'o',  'o',  'f',  0x00,
    900       0x00, 0x00, 0x06, 'a',
    901       ' ',  'c',  'e',  'r',
    902       't',  0x00, 0x00, 0x00,
    903       0x0C, 'a',  'n',  'o',
    904       't',  'h',  'e',  'r',
    905       ' ',  'c',  'e',  'r',
    906       't',  0x00, 0x00, 0x00,
    907       0x0A, 'f',  'i',  'n',
    908       'a',  'l',  ' ',  'c',
    909       'e',  'r',  't',
    910     };
    911     const unsigned char kV4FrameData[] = {
    912       0x00, 0x3b, 0x0A, 0x00,
    913       0x00, 0x00, 0x00, 0x00,
    914       0x00, 0x03, 0x00, 0x00,
    915       0x00, 0x05, 'p',  'r',
    916       'o',  'o',  'f',  0x00,
    917       0x00, 0x00, 0x06, 'a',
    918       ' ',  'c',  'e',  'r',
    919       't',  0x00, 0x00, 0x00,
    920       0x0C, 'a',  'n',  'o',
    921       't',  'h',  'e',  'r',
    922       ' ',  'c',  'e',  'r',
    923       't',  0x00, 0x00, 0x00,
    924       0x0A, 'f',  'i',  'n',
    925       'a',  'l',  ' ',  'c',
    926       'e',  'r',  't',
    927     };
    928     SpdyCredential credential;
    929     credential.slot = 3;
    930     credential.proof = "proof";
    931     credential.certs.push_back("a cert");
    932     credential.certs.push_back("another cert");
    933     credential.certs.push_back("final cert");
    934     scoped_ptr<SpdyFrame> frame(framer.CreateCredentialFrame(credential));
    935     if (IsSpdy4()) {
    936       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
    937     } else {
    938       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
    939     }
    940   }
    941 }
    942 
    943 TEST_P(SpdyFramerTest, ParseCredentialFrameData) {
    944   SpdyFramer framer(spdy_version_);
    945 
    946   {
    947     const unsigned char kV3FrameData[] = {  // Also applies for V2.
    948       0x80, spdy_version_ch_, 0x00, 0x0A,
    949       0x00, 0x00, 0x00, 0x33,
    950       0x00, 0x03, 0x00, 0x00,
    951       0x00, 0x05, 'p',  'r',
    952       'o',  'o',  'f',  0x00,
    953       0x00, 0x00, 0x06, 'a',
    954       ' ',  'c',  'e',  'r',
    955       't',  0x00, 0x00, 0x00,
    956       0x0C, 'a',  'n',  'o',
    957       't',  'h',  'e',  'r',
    958       ' ',  'c',  'e',  'r',
    959       't',  0x00,  0x00, 0x00,
    960       0x0A, 'f',  'i',  'n',
    961       'a',  'l',  ' ',  'c',
    962       'e',  'r',  't',
    963     };
    964     const unsigned char kV4FrameData[] = {
    965       0x00, 0x37, 0x0A, 0x00,
    966       0x00, 0x00, 0x00, 0x00,
    967       0x00, 0x03, 0x00, 0x00,
    968       0x00, 0x05, 'p',  'r',
    969       'o',  'o',  'f',  0x00,
    970       0x00, 0x00, 0x06, 'a',
    971       ' ',  'c',  'e',  'r',
    972       't',  0x00, 0x00, 0x00,
    973       0x0C, 'a',  'n',  'o',
    974       't',  'h',  'e',  'r',
    975       ' ',  'c',  'e',  'r',
    976       't',  0x00,  0x00, 0x00,
    977       0x0A, 'f',  'i',  'n',
    978       'a',  'l',  ' ',  'c',
    979       'e',  'r',  't',
    980     };
    981 
    982     SpdyCredential credential;
    983     if (IsSpdy4()) {
    984       EXPECT_TRUE(SpdyFramer::ParseCredentialData(
    985           reinterpret_cast<const char*>(kV4FrameData) +
    986               framer.GetControlFrameHeaderSize(),
    987           arraysize(kV4FrameData) - framer.GetControlFrameHeaderSize(),
    988           &credential));
    989     } else {
    990       EXPECT_TRUE(SpdyFramer::ParseCredentialData(
    991           reinterpret_cast<const char*>(kV3FrameData) +
    992               framer.GetControlFrameHeaderSize(),
    993           arraysize(kV3FrameData) - framer.GetControlFrameHeaderSize(),
    994           &credential));
    995     }
    996     EXPECT_EQ(3u, credential.slot);
    997     EXPECT_EQ("proof", credential.proof);
    998     EXPECT_EQ("a cert", credential.certs.front());
    999     credential.certs.erase(credential.certs.begin());
   1000     EXPECT_EQ("another cert", credential.certs.front());
   1001     credential.certs.erase(credential.certs.begin());
   1002     EXPECT_EQ("final cert", credential.certs.front());
   1003     credential.certs.erase(credential.certs.begin());
   1004     EXPECT_TRUE(credential.certs.empty());
   1005   }
   1006 }
   1007 
   1008 TEST_P(SpdyFramerTest, DuplicateHeader) {
   1009   SpdyFramer framer(spdy_version_);
   1010   // Frame builder with plentiful buffer size.
   1011   SpdyFrameBuilder frame(1024);
   1012   if (spdy_version_ < 4) {
   1013     frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
   1014     frame.WriteUInt32(3);  // stream_id
   1015   } else {
   1016     frame.WriteFramePrefix(framer, SYN_STREAM, CONTROL_FLAG_NONE, 3);
   1017   }
   1018 
   1019   frame.WriteUInt32(0);  // associated stream id
   1020   frame.WriteUInt16(0);  // Priority.
   1021 
   1022   if (IsSpdy2()) {
   1023     frame.WriteUInt16(2);  // Number of headers.
   1024     frame.WriteString("name");
   1025     frame.WriteString("value1");
   1026     frame.WriteString("name");
   1027     frame.WriteString("value2");
   1028   } else {
   1029     frame.WriteUInt32(2);  // Number of headers.
   1030     frame.WriteStringPiece32("name");
   1031     frame.WriteStringPiece32("value1");
   1032     frame.WriteStringPiece32("name");
   1033     frame.WriteStringPiece32("value2");
   1034   }
   1035   // write the length
   1036   frame.RewriteLength(framer);
   1037 
   1038   SpdyHeaderBlock new_headers;
   1039   framer.set_enable_compression(false);
   1040   scoped_ptr<SpdyFrame> control_frame(frame.take());
   1041   base::StringPiece serialized_headers =
   1042       GetSerializedHeaders(control_frame.get(), framer);
   1043   // This should fail because duplicate headers are verboten by the spec.
   1044   EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
   1045                                                serialized_headers.size(),
   1046                                                &new_headers));
   1047 }
   1048 
   1049 TEST_P(SpdyFramerTest, MultiValueHeader) {
   1050   SpdyFramer framer(spdy_version_);
   1051   // Frame builder with plentiful buffer size.
   1052   SpdyFrameBuilder frame(1024);
   1053   if (spdy_version_ < 4) {
   1054     frame.WriteControlFrameHeader(framer, SYN_STREAM, CONTROL_FLAG_NONE);
   1055     frame.WriteUInt32(3);  // stream_id
   1056   } else {
   1057     frame.WriteFramePrefix(framer, SYN_STREAM, CONTROL_FLAG_NONE, 3);
   1058   }
   1059 
   1060   frame.WriteUInt32(0);  // associated stream id
   1061   frame.WriteUInt16(0);  // Priority.
   1062 
   1063   string value("value1\0value2");
   1064   if (IsSpdy2()) {
   1065     frame.WriteUInt16(1);  // Number of headers.
   1066     frame.WriteString("name");
   1067     frame.WriteString(value);
   1068   } else {
   1069     frame.WriteUInt32(1);  // Number of headers.
   1070     frame.WriteStringPiece32("name");
   1071     frame.WriteStringPiece32(value);
   1072   }
   1073   // write the length
   1074   frame.RewriteLength(framer);
   1075 
   1076   SpdyHeaderBlock new_headers;
   1077   framer.set_enable_compression(false);
   1078   scoped_ptr<SpdyFrame> control_frame(frame.take());
   1079   base::StringPiece serialized_headers =
   1080       GetSerializedHeaders(control_frame.get(), framer);
   1081   EXPECT_TRUE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
   1082                                               serialized_headers.size(),
   1083                                               &new_headers));
   1084   EXPECT_TRUE(new_headers.find("name") != new_headers.end());
   1085   EXPECT_EQ(value, new_headers.find("name")->second);
   1086 }
   1087 
   1088 TEST_P(SpdyFramerTest, BasicCompression) {
   1089   SpdyHeaderBlock headers;
   1090   headers["server"] = "SpdyServer 1.0";
   1091   headers["date"] = "Mon 12 Jan 2009 12:12:12 PST";
   1092   headers["status"] = "200";
   1093   headers["version"] = "HTTP/1.1";
   1094   headers["content-type"] = "text/html";
   1095   headers["content-length"] = "12";
   1096 
   1097   scoped_ptr<TestSpdyVisitor> visitor(new TestSpdyVisitor(spdy_version_));
   1098   SpdyFramer framer(spdy_version_);
   1099   framer.set_debug_visitor(visitor.get());
   1100   scoped_ptr<SpdyFrame> frame1(
   1101       framer.CreateSynStream(1,  // stream id
   1102                              0,  // associated stream id
   1103                              1,  // priority
   1104                              0,  // credential slot
   1105                              CONTROL_FLAG_NONE,
   1106                              true,  // compress
   1107                              &headers));
   1108   size_t uncompressed_size1 = visitor->last_payload_len_;
   1109   size_t compressed_size1 =
   1110       visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
   1111   if (IsSpdy2()) {
   1112     EXPECT_EQ(139u, uncompressed_size1);
   1113 #if defined(USE_SYSTEM_ZLIB)
   1114     EXPECT_EQ(155u, compressed_size1);
   1115 #else  // !defined(USE_SYSTEM_ZLIB)
   1116     EXPECT_EQ(135u, compressed_size1);
   1117 #endif  // !defined(USE_SYSTEM_ZLIB)
   1118   } else {
   1119     EXPECT_EQ(165u, uncompressed_size1);
   1120 #if defined(USE_SYSTEM_ZLIB)
   1121     EXPECT_EQ(181u, compressed_size1);
   1122 #else  // !defined(USE_SYSTEM_ZLIB)
   1123     EXPECT_EQ(117u, compressed_size1);
   1124 #endif  // !defined(USE_SYSTEM_ZLIB)
   1125   }
   1126   scoped_ptr<SpdyFrame> frame2(
   1127       framer.CreateSynStream(1,  // stream id
   1128                              0,  // associated stream id
   1129                              1,  // priority
   1130                              0,  // credential slot
   1131                              CONTROL_FLAG_NONE,
   1132                              true,  // compress
   1133                              &headers));
   1134   size_t uncompressed_size2 = visitor->last_payload_len_;
   1135   size_t compressed_size2 =
   1136       visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
   1137 
   1138   // Expect the second frame to be more compact than the first.
   1139   EXPECT_LE(frame2->size(), frame1->size());
   1140 
   1141   // Decompress the first frame
   1142   scoped_ptr<SpdyFrame> frame3(SpdyFramerTestUtil::DecompressFrame(
   1143       &framer, *frame1.get()));
   1144 
   1145   // Decompress the second frame
   1146   visitor.reset(new TestSpdyVisitor(spdy_version_));
   1147   framer.set_debug_visitor(visitor.get());
   1148   scoped_ptr<SpdyFrame> frame4(SpdyFramerTestUtil::DecompressFrame(
   1149       &framer, *frame2.get()));
   1150   size_t uncompressed_size4 =
   1151       frame4->size() - framer.GetSynStreamMinimumSize();
   1152   size_t compressed_size4 =
   1153       visitor->last_frame_len_ - framer.GetSynStreamMinimumSize();
   1154   if (IsSpdy2()) {
   1155     EXPECT_EQ(139u, uncompressed_size4);
   1156 #if defined(USE_SYSTEM_ZLIB)
   1157     EXPECT_EQ(149u, compressed_size4);
   1158 #else  // !defined(USE_SYSTEM_ZLIB)
   1159     EXPECT_EQ(101u, compressed_size4);
   1160 #endif  // !defined(USE_SYSTEM_ZLIB)
   1161   } else {
   1162     EXPECT_EQ(165u, uncompressed_size4);
   1163 #if defined(USE_SYSTEM_ZLIB)
   1164     EXPECT_EQ(175u, compressed_size4);
   1165 #else  // !defined(USE_SYSTEM_ZLIB)
   1166     EXPECT_EQ(102u, compressed_size4);
   1167 #endif  // !defined(USE_SYSTEM_ZLIB)
   1168   }
   1169 
   1170   EXPECT_EQ(uncompressed_size1, uncompressed_size2);
   1171   EXPECT_EQ(uncompressed_size1, uncompressed_size4);
   1172   EXPECT_EQ(compressed_size2, compressed_size4);
   1173 
   1174   // Expect frames 3 & 4 to be the same.
   1175   CompareFrames("Uncompressed SYN_STREAM", *frame3, *frame4);
   1176 
   1177   // Expect frames 3 to be the same as a uncompressed frame created
   1178   // from scratch.
   1179   framer.set_enable_compression(false);
   1180   scoped_ptr<SpdyFrame> uncompressed_frame(
   1181       framer.CreateSynStream(1,  // stream id
   1182                              0,  // associated stream id
   1183                              1,  // priority
   1184                              0,  // credential slot
   1185                              CONTROL_FLAG_NONE,
   1186                              false,  // compress
   1187                              &headers));
   1188   CompareFrames("Uncompressed SYN_STREAM", *frame3, *uncompressed_frame);
   1189 }
   1190 
   1191 TEST_P(SpdyFramerTest, CompressEmptyHeaders) {
   1192   // See crbug.com/172383
   1193   SpdyHeaderBlock headers;
   1194   headers["server"] = "SpdyServer 1.0";
   1195   headers["date"] = "Mon 12 Jan 2009 12:12:12 PST";
   1196   headers["status"] = "200";
   1197   headers["version"] = "HTTP/1.1";
   1198   headers["content-type"] = "text/html";
   1199   headers["content-length"] = "12";
   1200   headers["x-empty-header"] = "";
   1201 
   1202   SpdyFramer framer(spdy_version_);
   1203   framer.set_enable_compression(true);
   1204   scoped_ptr<SpdyFrame> frame1(
   1205       framer.CreateSynStream(1,  // stream id
   1206                              0,  // associated stream id
   1207                              1,  // priority
   1208                              0,  // credential slot
   1209                              CONTROL_FLAG_NONE,
   1210                              true,  // compress
   1211                              &headers));
   1212 }
   1213 
   1214 TEST_P(SpdyFramerTest, Basic) {
   1215   const unsigned char kV2Input[] = {
   1216     0x80, spdy_version_ch_, 0x00, 0x01,  // SYN Stream #1
   1217     0x00, 0x00, 0x00, 0x14,
   1218     0x00, 0x00, 0x00, 0x01,
   1219     0x00, 0x00, 0x00, 0x00,
   1220     0x00, 0x00, 0x00, 0x01,
   1221     0x00, 0x02, 'h', 'h',
   1222     0x00, 0x02, 'v', 'v',
   1223 
   1224     0x80, spdy_version_ch_, 0x00, 0x08,  // HEADERS on Stream #1
   1225     0x00, 0x00, 0x00, 0x18,
   1226     0x00, 0x00, 0x00, 0x01,
   1227     0x00, 0x00, 0x00, 0x02,
   1228     0x00, 0x02, 'h', '2',
   1229     0x00, 0x02, 'v', '2',
   1230     0x00, 0x02, 'h', '3',
   1231     0x00, 0x02, 'v', '3',
   1232 
   1233     0x00, 0x00, 0x00, 0x01,           // DATA on Stream #1
   1234     0x00, 0x00, 0x00, 0x0c,
   1235     0xde, 0xad, 0xbe, 0xef,
   1236     0xde, 0xad, 0xbe, 0xef,
   1237     0xde, 0xad, 0xbe, 0xef,
   1238 
   1239     0x80, spdy_version_ch_, 0x00, 0x01,  // SYN Stream #3
   1240     0x00, 0x00, 0x00, 0x0c,
   1241     0x00, 0x00, 0x00, 0x03,
   1242     0x00, 0x00, 0x00, 0x00,
   1243     0x00, 0x00, 0x00, 0x00,
   1244 
   1245     0x00, 0x00, 0x00, 0x03,           // DATA on Stream #3
   1246     0x00, 0x00, 0x00, 0x08,
   1247     0xde, 0xad, 0xbe, 0xef,
   1248     0xde, 0xad, 0xbe, 0xef,
   1249 
   1250     0x00, 0x00, 0x00, 0x01,           // DATA on Stream #1
   1251     0x00, 0x00, 0x00, 0x04,
   1252     0xde, 0xad, 0xbe, 0xef,
   1253 
   1254     0x80, spdy_version_ch_, 0x00, 0x03,  // RST_STREAM on Stream #1
   1255     0x00, 0x00, 0x00, 0x08,
   1256     0x00, 0x00, 0x00, 0x01,
   1257     0x00, 0x00, 0x00, 0x00,
   1258 
   1259     0x00, 0x00, 0x00, 0x03,           // DATA on Stream #3
   1260     0x00, 0x00, 0x00, 0x00,
   1261 
   1262     0x80, spdy_version_ch_, 0x00, 0x03,  // RST_STREAM on Stream #3
   1263     0x00, 0x00, 0x00, 0x08,
   1264     0x00, 0x00, 0x00, 0x03,
   1265     0x00, 0x00, 0x00, 0x00,
   1266   };
   1267 
   1268   const unsigned char kV3Input[] = {
   1269     0x80, spdy_version_ch_, 0x00, 0x01,  // SYN Stream #1
   1270     0x00, 0x00, 0x00, 0x1a,
   1271     0x00, 0x00, 0x00, 0x01,
   1272     0x00, 0x00, 0x00, 0x00,
   1273     0x00, 0x00, 0x00, 0x00,
   1274     0x00, 0x01, 0x00, 0x00,
   1275     0x00, 0x02, 'h', 'h',
   1276     0x00, 0x00, 0x00, 0x02,
   1277     'v', 'v',
   1278 
   1279     0x80, spdy_version_ch_, 0x00, 0x08,  // HEADERS on Stream #1
   1280     0x00, 0x00, 0x00, 0x20,
   1281     0x00, 0x00, 0x00, 0x01,
   1282     0x00, 0x00, 0x00, 0x02,
   1283     0x00, 0x00, 0x00, 0x02,
   1284     'h', '2',
   1285     0x00, 0x00, 0x00, 0x02,
   1286     'v', '2', 0x00, 0x00,
   1287     0x00, 0x02, 'h', '3',
   1288     0x00, 0x00, 0x00, 0x02,
   1289     'v', '3',
   1290 
   1291     0x00, 0x00, 0x00, 0x01,           // DATA on Stream #1
   1292     0x00, 0x00, 0x00, 0x0c,
   1293     0xde, 0xad, 0xbe, 0xef,
   1294     0xde, 0xad, 0xbe, 0xef,
   1295     0xde, 0xad, 0xbe, 0xef,
   1296 
   1297     0x80, spdy_version_ch_, 0x00, 0x01,  // SYN Stream #3
   1298     0x00, 0x00, 0x00, 0x0e,
   1299     0x00, 0x00, 0x00, 0x03,
   1300     0x00, 0x00, 0x00, 0x00,
   1301     0x00, 0x00, 0x00, 0x00,
   1302     0x00, 0x00,
   1303 
   1304     0x00, 0x00, 0x00, 0x03,           // DATA on Stream #3
   1305     0x00, 0x00, 0x00, 0x08,
   1306     0xde, 0xad, 0xbe, 0xef,
   1307     0xde, 0xad, 0xbe, 0xef,
   1308 
   1309     0x00, 0x00, 0x00, 0x01,           // DATA on Stream #1
   1310     0x00, 0x00, 0x00, 0x04,
   1311     0xde, 0xad, 0xbe, 0xef,
   1312 
   1313     0x80, spdy_version_ch_, 0x00, 0x03,  // RST_STREAM on Stream #1
   1314     0x00, 0x00, 0x00, 0x08,
   1315     0x00, 0x00, 0x00, 0x01,
   1316     0x00, 0x00, 0x00, 0x00,
   1317 
   1318     0x00, 0x00, 0x00, 0x03,           // DATA on Stream #3
   1319     0x00, 0x00, 0x00, 0x00,
   1320 
   1321     0x80, spdy_version_ch_, 0x00, 0x03,  // RST_STREAM on Stream #3
   1322     0x00, 0x00, 0x00, 0x08,
   1323     0x00, 0x00, 0x00, 0x03,
   1324     0x00, 0x00, 0x00, 0x00,
   1325   };
   1326 
   1327   const unsigned char kV4Input[] = {
   1328     0x00, 0x1e, 0x01, 0x00,           // SYN_STREAM #1
   1329     0x00, 0x00, 0x00, 0x01,
   1330     0x00, 0x00, 0x00, 0x00,
   1331     0x00, 0x00, 0x00, 0x00,
   1332     0x00, 0x01, 0x00, 0x00,
   1333     0x00, 0x02, 'h', 'h',
   1334     0x00, 0x00, 0x00, 0x02,
   1335     'v', 'v',
   1336 
   1337     0x00, 0x24, 0x08, 0x00,           // HEADERS on Stream #1
   1338     0x00, 0x00, 0x00, 0x01,
   1339     0x00, 0x00, 0x00, 0x02,
   1340     0x00, 0x00, 0x00, 0x02,
   1341     'h',  '2',  0x00, 0x00,
   1342     0x00, 0x02, 'v',  '2',
   1343     0x00, 0x00, 0x00, 0x02,
   1344     'h',  '3',  0x00, 0x00,
   1345     0x00, 0x02, 'v', '3',
   1346 
   1347     0x00, 0x14, 0x00, 0x00,           // DATA on Stream #1
   1348     0x00, 0x00, 0x00, 0x01,
   1349     0xde, 0xad, 0xbe, 0xef,
   1350     0xde, 0xad, 0xbe, 0xef,
   1351     0xde, 0xad, 0xbe, 0xef,
   1352 
   1353     0x00, 0x12, 0x01, 0x00,           // SYN Stream #3
   1354     0x00, 0x00, 0x00, 0x03,
   1355     0x00, 0x00, 0x00, 0x00,
   1356     0x00, 0x00, 0x00, 0x00,
   1357     0x00, 0x00,
   1358 
   1359     0x00, 0x10, 0x00, 0x00,           // DATA on Stream #3
   1360     0x00, 0x00, 0x00, 0x03,
   1361     0xde, 0xad, 0xbe, 0xef,
   1362     0xde, 0xad, 0xbe, 0xef,
   1363 
   1364     0x00, 0x0c, 0x00, 0x00,           // DATA on Stream #1
   1365     0x00, 0x00, 0x00, 0x01,
   1366     0xde, 0xad, 0xbe, 0xef,
   1367 
   1368     0x00, 0x0c, 0x03, 0x00,           // RST_STREAM on Stream #1
   1369     0x00, 0x00, 0x00, 0x01,
   1370     0x00, 0x00, 0x00, 0x00,
   1371 
   1372     0x00, 0x08, 0x00, 0x00,           // DATA on Stream #3
   1373     0x00, 0x00, 0x00, 0x03,
   1374 
   1375     0x00, 0x0c, 0x03, 0x00,           // RST_STREAM on Stream #3
   1376     0x00, 0x00, 0x00, 0x03,
   1377     0x00, 0x00, 0x00, 0x00,
   1378   };
   1379 
   1380   TestSpdyVisitor visitor(spdy_version_);
   1381   if (IsSpdy2()) {
   1382     visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
   1383   } else if (IsSpdy3()) {
   1384     visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
   1385   } else {
   1386     visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
   1387   }
   1388 
   1389   EXPECT_EQ(0, visitor.error_count_);
   1390   EXPECT_EQ(2, visitor.syn_frame_count_);
   1391   EXPECT_EQ(0, visitor.syn_reply_frame_count_);
   1392   EXPECT_EQ(1, visitor.headers_frame_count_);
   1393   EXPECT_EQ(24, visitor.data_bytes_);
   1394   EXPECT_EQ(2, visitor.fin_frame_count_);
   1395   EXPECT_EQ(0, visitor.fin_flag_count_);
   1396   EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
   1397   EXPECT_EQ(4, visitor.data_frame_count_);
   1398 }
   1399 
   1400 // Test that the FIN flag on a data frame signifies EOF.
   1401 TEST_P(SpdyFramerTest, FinOnDataFrame) {
   1402   const unsigned char kV2Input[] = {
   1403     0x80, spdy_version_ch_, 0x00, 0x01,  // SYN Stream #1
   1404     0x00, 0x00, 0x00, 0x14,
   1405     0x00, 0x00, 0x00, 0x01,
   1406     0x00, 0x00, 0x00, 0x00,
   1407     0x00, 0x00, 0x00, 0x01,
   1408     0x00, 0x02, 'h', 'h',
   1409     0x00, 0x02, 'v', 'v',
   1410 
   1411     0x80, spdy_version_ch_, 0x00, 0x02,  // SYN REPLY Stream #1
   1412     0x00, 0x00, 0x00, 0x10,
   1413     0x00, 0x00, 0x00, 0x01,
   1414     0x00, 0x00, 0x00, 0x01,
   1415     0x00, 0x02, 'a', 'a',
   1416     0x00, 0x02, 'b', 'b',
   1417 
   1418     0x00, 0x00, 0x00, 0x01,           // DATA on Stream #1
   1419     0x00, 0x00, 0x00, 0x0c,
   1420     0xde, 0xad, 0xbe, 0xef,
   1421     0xde, 0xad, 0xbe, 0xef,
   1422     0xde, 0xad, 0xbe, 0xef,
   1423 
   1424     0x00, 0x00, 0x00, 0x01,           // DATA on Stream #1, with EOF
   1425     0x01, 0x00, 0x00, 0x04,
   1426     0xde, 0xad, 0xbe, 0xef,
   1427   };
   1428   const unsigned char kV3Input[] = {
   1429     0x80, spdy_version_ch_, 0x00, 0x01,  // SYN Stream #1
   1430     0x00, 0x00, 0x00, 0x1a,
   1431     0x00, 0x00, 0x00, 0x01,
   1432     0x00, 0x00, 0x00, 0x00,
   1433     0x00, 0x00, 0x00, 0x00,
   1434     0x00, 0x01, 0x00, 0x00,
   1435     0x00, 0x02, 'h', 'h',
   1436     0x00, 0x00, 0x00, 0x02,
   1437     'v',  'v',
   1438 
   1439     0x80, spdy_version_ch_, 0x00, 0x02,  // SYN REPLY Stream #1
   1440     0x00, 0x00, 0x00, 0x14,
   1441     0x00, 0x00, 0x00, 0x01,
   1442     0x00, 0x00, 0x00, 0x01,
   1443     0x00, 0x00, 0x00, 0x02,
   1444     'a',  'a',  0x00, 0x00,
   1445     0x00, 0x02, 'b', 'b',
   1446 
   1447     0x00, 0x00, 0x00, 0x01,           // DATA on Stream #1
   1448     0x00, 0x00, 0x00, 0x0c,
   1449     0xde, 0xad, 0xbe, 0xef,
   1450     0xde, 0xad, 0xbe, 0xef,
   1451     0xde, 0xad, 0xbe, 0xef,
   1452 
   1453     0x00, 0x00, 0x00, 0x01,           // DATA on Stream #1, with EOF
   1454     0x01, 0x00, 0x00, 0x04,
   1455     0xde, 0xad, 0xbe, 0xef,
   1456   };
   1457   const unsigned char kV4Input[] = {
   1458     0x00, 0x1e, 0x01, 0x00,           // SYN_STREAM #1
   1459     0x00, 0x00, 0x00, 0x01,
   1460     0x00, 0x00, 0x00, 0x00,
   1461     0x00, 0x00, 0x00, 0x00,
   1462     0x00, 0x01, 0x00, 0x00,
   1463     0x00, 0x02, 'h', 'h',
   1464     0x00, 0x00, 0x00, 0x02,
   1465     'v',  'v',
   1466 
   1467     0x00, 0x18, 0x02, 0x00,           // SYN REPLY Stream #1
   1468     0x00, 0x00, 0x00, 0x01,
   1469     0x00, 0x00, 0x00, 0x01,
   1470     0x00, 0x00, 0x00, 0x02,
   1471     'a',  'a',  0x00, 0x00,
   1472     0x00, 0x02, 'b', 'b',
   1473 
   1474     0x00, 0x14, 0x00, 0x00,           // DATA on Stream #1
   1475     0x00, 0x00, 0x00, 0x01,
   1476     0xde, 0xad, 0xbe, 0xef,
   1477     0xde, 0xad, 0xbe, 0xef,
   1478     0xde, 0xad, 0xbe, 0xef,
   1479 
   1480     0x00, 0x0c, 0x00, 0x01,           // DATA on Stream #1, with FIN
   1481     0x00, 0x00, 0x00, 0x01,
   1482     0xde, 0xad, 0xbe, 0xef,
   1483   };
   1484 
   1485   TestSpdyVisitor visitor(spdy_version_);
   1486   if (IsSpdy2()) {
   1487     visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
   1488   } else if (IsSpdy3()) {
   1489     visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
   1490   } else {
   1491     visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
   1492   }
   1493 
   1494   EXPECT_EQ(0, visitor.error_count_);
   1495   EXPECT_EQ(1, visitor.syn_frame_count_);
   1496   EXPECT_EQ(1, visitor.syn_reply_frame_count_);
   1497   EXPECT_EQ(0, visitor.headers_frame_count_);
   1498   EXPECT_EQ(16, visitor.data_bytes_);
   1499   EXPECT_EQ(0, visitor.fin_frame_count_);
   1500   EXPECT_EQ(0, visitor.fin_flag_count_);
   1501   EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
   1502   EXPECT_EQ(2, visitor.data_frame_count_);
   1503 }
   1504 
   1505 // Test that the FIN flag on a SYN reply frame signifies EOF.
   1506 TEST_P(SpdyFramerTest, FinOnSynReplyFrame) {
   1507   const unsigned char kV2Input[] = {
   1508     0x80, spdy_version_ch_, 0x00, 0x01,  // SYN Stream #1
   1509     0x00, 0x00, 0x00, 0x14,
   1510     0x00, 0x00, 0x00, 0x01,
   1511     0x00, 0x00, 0x00, 0x00,
   1512     0x00, 0x00, 0x00, 0x01,
   1513     0x00, 0x02, 'h', 'h',
   1514     0x00, 0x02, 'v', 'v',
   1515 
   1516     0x80, spdy_version_ch_, 0x00, 0x02,  // SYN REPLY Stream #1
   1517     0x01, 0x00, 0x00, 0x10,
   1518     0x00, 0x00, 0x00, 0x01,
   1519     0x00, 0x00, 0x00, 0x01,
   1520     0x00, 0x02, 'a', 'a',
   1521     0x00, 0x02, 'b', 'b',
   1522   };
   1523   const unsigned char kV3Input[] = {
   1524     0x80, spdy_version_ch_, 0x00, 0x01,  // SYN Stream #1
   1525     0x00, 0x00, 0x00, 0x1a,
   1526     0x00, 0x00, 0x00, 0x01,
   1527     0x00, 0x00, 0x00, 0x00,
   1528     0x00, 0x00, 0x00, 0x00,
   1529     0x00, 0x01, 0x00, 0x00,
   1530     0x00, 0x02, 'h', 'h',
   1531     0x00, 0x00, 0x00, 0x02,
   1532     'v', 'v',
   1533 
   1534     0x80, spdy_version_ch_, 0x00, 0x02,  // SYN REPLY Stream #1
   1535     0x01, 0x00, 0x00, 0x14,
   1536     0x00, 0x00, 0x00, 0x01,
   1537     0x00, 0x00, 0x00, 0x01,
   1538     0x00, 0x00, 0x00, 0x02,
   1539     'a', 'a',   0x00, 0x00,
   1540     0x00, 0x02, 'b', 'b',
   1541   };
   1542   const unsigned char kV4Input[] = {
   1543     0x00, 0x1e, 0x01, 0x00,           // SYN_STREAM #1
   1544     0x00, 0x00, 0x00, 0x01,
   1545     0x00, 0x00, 0x00, 0x00,
   1546     0x00, 0x00, 0x00, 0x00,
   1547     0x00, 0x01, 0x00, 0x00,
   1548     0x00, 0x02, 'h', 'h',
   1549     0x00, 0x00, 0x00, 0x02,
   1550     'v', 'v',
   1551 
   1552     0x00, 0x18, 0x02, 0x01,           // SYN_REPLY #1, with FIN
   1553     0x00, 0x00, 0x00, 0x01,
   1554     0x00, 0x00, 0x00, 0x01,
   1555     0x00, 0x00, 0x00, 0x02,
   1556     'a', 'a',   0x00, 0x00,
   1557     0x00, 0x02, 'b', 'b',
   1558   };
   1559 
   1560   TestSpdyVisitor visitor(spdy_version_);
   1561   if (IsSpdy2()) {
   1562     visitor.SimulateInFramer(kV2Input, sizeof(kV2Input));
   1563   } else if (IsSpdy3()) {
   1564     visitor.SimulateInFramer(kV3Input, sizeof(kV3Input));
   1565   } else {
   1566     visitor.SimulateInFramer(kV4Input, sizeof(kV4Input));
   1567   }
   1568 
   1569   EXPECT_EQ(0, visitor.error_count_);
   1570   EXPECT_EQ(1, visitor.syn_frame_count_);
   1571   EXPECT_EQ(1, visitor.syn_reply_frame_count_);
   1572   EXPECT_EQ(0, visitor.headers_frame_count_);
   1573   EXPECT_EQ(0, visitor.data_bytes_);
   1574   EXPECT_EQ(0, visitor.fin_frame_count_);
   1575   EXPECT_EQ(1, visitor.fin_flag_count_);
   1576   EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
   1577   EXPECT_EQ(0, visitor.data_frame_count_);
   1578 }
   1579 
   1580 TEST_P(SpdyFramerTest, HeaderCompression) {
   1581   SpdyFramer send_framer(spdy_version_);
   1582   SpdyFramer recv_framer(spdy_version_);
   1583 
   1584   send_framer.set_enable_compression(true);
   1585   recv_framer.set_enable_compression(true);
   1586 
   1587   const char kHeader1[] = "header1";
   1588   const char kHeader2[] = "header2";
   1589   const char kHeader3[] = "header3";
   1590   const char kValue1[] = "value1";
   1591   const char kValue2[] = "value2";
   1592   const char kValue3[] = "value3";
   1593 
   1594   // SYN_STREAM #1
   1595   SpdyHeaderBlock block;
   1596   block[kHeader1] = kValue1;
   1597   block[kHeader2] = kValue2;
   1598   SpdyControlFlags flags(CONTROL_FLAG_NONE);
   1599   SpdySynStreamIR syn_ir_1(1);
   1600   syn_ir_1.SetHeader(kHeader1, kValue1);
   1601   syn_ir_1.SetHeader(kHeader2, kValue2);
   1602   scoped_ptr<SpdyFrame> syn_frame_1(send_framer.SerializeFrame(syn_ir_1));
   1603   EXPECT_TRUE(syn_frame_1.get() != NULL);
   1604 
   1605   // SYN_STREAM #2
   1606   block[kHeader3] = kValue3;
   1607   scoped_ptr<SpdyFrame> syn_frame_2(
   1608       send_framer.CreateSynStream(3,  // stream id
   1609                                   0,  // associated stream id
   1610                                   0,  // priority
   1611                                   0,  // credential slot
   1612                                   flags,
   1613                                   true,  // compress
   1614                                   &block));
   1615   EXPECT_TRUE(syn_frame_2.get() != NULL);
   1616 
   1617   // Now start decompressing
   1618   scoped_ptr<SpdyFrame> decompressed;
   1619   scoped_ptr<SpdyFrame> uncompressed;
   1620   base::StringPiece serialized_headers;
   1621   SpdyHeaderBlock decompressed_headers;
   1622 
   1623   // Decompress SYN_STREAM #1
   1624   decompressed.reset(SpdyFramerTestUtil::DecompressFrame(
   1625       &recv_framer, *syn_frame_1.get()));
   1626   EXPECT_TRUE(decompressed.get() != NULL);
   1627   serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
   1628   EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
   1629                                                    serialized_headers.size(),
   1630                                                    &decompressed_headers));
   1631   EXPECT_EQ(2u, decompressed_headers.size());
   1632   EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
   1633   EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
   1634 
   1635   // Decompress SYN_STREAM #2
   1636   decompressed.reset(SpdyFramerTestUtil::DecompressFrame(
   1637       &recv_framer, *syn_frame_2.get()));
   1638   EXPECT_TRUE(decompressed.get() != NULL);
   1639   serialized_headers = GetSerializedHeaders(decompressed.get(), send_framer);
   1640   decompressed_headers.clear();
   1641   EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers.data(),
   1642                                                    serialized_headers.size(),
   1643                                                    &decompressed_headers));
   1644   EXPECT_EQ(3u, decompressed_headers.size());
   1645   EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
   1646   EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
   1647   EXPECT_EQ(kValue3, decompressed_headers[kHeader3]);
   1648 }
   1649 
   1650 // Verify we don't leak when we leave streams unclosed
   1651 TEST_P(SpdyFramerTest, UnclosedStreamDataCompressors) {
   1652   SpdyFramer send_framer(spdy_version_);
   1653 
   1654   send_framer.set_enable_compression(true);
   1655 
   1656   const char kHeader1[] = "header1";
   1657   const char kHeader2[] = "header2";
   1658   const char kValue1[] = "value1";
   1659   const char kValue2[] = "value2";
   1660 
   1661   SpdyHeaderBlock block;
   1662   block[kHeader1] = kValue1;
   1663   block[kHeader2] = kValue2;
   1664   SpdyControlFlags flags(CONTROL_FLAG_NONE);
   1665   scoped_ptr<SpdyFrame> syn_frame(
   1666       send_framer.CreateSynStream(1,  // stream id
   1667                                   0,  // associated stream id
   1668                                   0,  // priority
   1669                                   0,  // credential slot
   1670                                   flags,
   1671                                   true,  // compress
   1672                                   &block));
   1673   EXPECT_TRUE(syn_frame.get() != NULL);
   1674 
   1675   const char bytes[] = "this is a test test test test test!";
   1676   scoped_ptr<SpdyFrame> send_frame(
   1677       send_framer.CreateDataFrame(
   1678           1, bytes, arraysize(bytes),
   1679           static_cast<SpdyDataFlags>(DATA_FLAG_FIN)));
   1680   EXPECT_TRUE(send_frame.get() != NULL);
   1681 
   1682   // Run the inputs through the framer.
   1683   TestSpdyVisitor visitor(spdy_version_);
   1684   visitor.use_compression_ = true;
   1685   const unsigned char* data;
   1686   data = reinterpret_cast<const unsigned char*>(syn_frame->data());
   1687   visitor.SimulateInFramer(data, syn_frame->size());
   1688   data = reinterpret_cast<const unsigned char*>(send_frame->data());
   1689   visitor.SimulateInFramer(data, send_frame->size());
   1690 
   1691   EXPECT_EQ(0, visitor.error_count_);
   1692   EXPECT_EQ(1, visitor.syn_frame_count_);
   1693   EXPECT_EQ(0, visitor.syn_reply_frame_count_);
   1694   EXPECT_EQ(0, visitor.headers_frame_count_);
   1695   EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_));
   1696   EXPECT_EQ(0, visitor.fin_frame_count_);
   1697   EXPECT_EQ(0, visitor.fin_flag_count_);
   1698   EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
   1699   EXPECT_EQ(1, visitor.data_frame_count_);
   1700 }
   1701 
   1702 // Verify we can decompress the stream even if handed over to the
   1703 // framer 1 byte at a time.
   1704 TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
   1705   SpdyFramer send_framer(spdy_version_);
   1706 
   1707   send_framer.set_enable_compression(true);
   1708 
   1709   const char kHeader1[] = "header1";
   1710   const char kHeader2[] = "header2";
   1711   const char kValue1[] = "value1";
   1712   const char kValue2[] = "value2";
   1713 
   1714   SpdyHeaderBlock block;
   1715   block[kHeader1] = kValue1;
   1716   block[kHeader2] = kValue2;
   1717   SpdyControlFlags flags(CONTROL_FLAG_NONE);
   1718   scoped_ptr<SpdyFrame> syn_frame(
   1719       send_framer.CreateSynStream(1,  // stream id
   1720                                   0,  // associated stream id
   1721                                   0,  // priority
   1722                                   0,  // credential slot
   1723                                   flags,
   1724                                   true,  // compress
   1725                                   &block));
   1726   EXPECT_TRUE(syn_frame.get() != NULL);
   1727 
   1728   const char bytes[] = "this is a test test test test test!";
   1729   scoped_ptr<SpdyFrame> send_frame(
   1730       send_framer.CreateDataFrame(
   1731           1, bytes, arraysize(bytes),
   1732           static_cast<SpdyDataFlags>(DATA_FLAG_FIN)));
   1733   EXPECT_TRUE(send_frame.get() != NULL);
   1734 
   1735   // Run the inputs through the framer.
   1736   TestSpdyVisitor visitor(spdy_version_);
   1737   visitor.use_compression_ = true;
   1738   const unsigned char* data;
   1739   data = reinterpret_cast<const unsigned char*>(syn_frame->data());
   1740   for (size_t idx = 0; idx < syn_frame->size(); ++idx) {
   1741     visitor.SimulateInFramer(data + idx, 1);
   1742     ASSERT_EQ(0, visitor.error_count_);
   1743   }
   1744   data = reinterpret_cast<const unsigned char*>(send_frame->data());
   1745   for (size_t idx = 0; idx < send_frame->size(); ++idx) {
   1746     visitor.SimulateInFramer(data + idx, 1);
   1747     ASSERT_EQ(0, visitor.error_count_);
   1748   }
   1749 
   1750   EXPECT_EQ(0, visitor.error_count_);
   1751   EXPECT_EQ(1, visitor.syn_frame_count_);
   1752   EXPECT_EQ(0, visitor.syn_reply_frame_count_);
   1753   EXPECT_EQ(0, visitor.headers_frame_count_);
   1754   EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_));
   1755   EXPECT_EQ(0, visitor.fin_frame_count_);
   1756   EXPECT_EQ(0, visitor.fin_flag_count_);
   1757   EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
   1758   EXPECT_EQ(1, visitor.data_frame_count_);
   1759 }
   1760 
   1761 TEST_P(SpdyFramerTest, WindowUpdateFrame) {
   1762   SpdyFramer framer(spdy_version_);
   1763   scoped_ptr<SpdyFrame> frame(framer.CreateWindowUpdate(1, 0x12345678));
   1764 
   1765   const char kDescription[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678";
   1766   const unsigned char kV3FrameData[] = {  // Also applies for V2.
   1767     0x80, spdy_version_ch_, 0x00, 0x09,
   1768     0x00, 0x00, 0x00, 0x08,
   1769     0x00, 0x00, 0x00, 0x01,
   1770     0x12, 0x34, 0x56, 0x78
   1771   };
   1772   const unsigned char kV4FrameData[] = {
   1773     0x00, 0x0c, 0x09, 0x00,
   1774     0x00, 0x00, 0x00, 0x01,
   1775     0x12, 0x34, 0x56, 0x78
   1776   };
   1777 
   1778   if (IsSpdy4()) {
   1779      CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   1780   } else {
   1781      CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   1782   }
   1783 }
   1784 
   1785 TEST_P(SpdyFramerTest, CreateDataFrame) {
   1786   SpdyFramer framer(spdy_version_);
   1787 
   1788   {
   1789     const char kDescription[] = "'hello' data frame, no FIN";
   1790     const unsigned char kV3FrameData[] = {  // Also applies for V2.
   1791       0x00, 0x00, 0x00, 0x01,
   1792       0x00, 0x00, 0x00, 0x05,
   1793       'h',  'e',  'l',  'l',
   1794       'o'
   1795     };
   1796     const unsigned char kV4FrameData[] = {
   1797       0x00, 0x0d, 0x00, 0x00,
   1798       0x00, 0x00, 0x00, 0x01,
   1799       'h',  'e',  'l',  'l',
   1800       'o'
   1801     };
   1802     const char bytes[] = "hello";
   1803 
   1804     scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
   1805         1, bytes, strlen(bytes), DATA_FLAG_NONE));
   1806     if (IsSpdy4()) {
   1807        CompareFrame(
   1808            kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   1809     } else {
   1810        CompareFrame(
   1811            kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   1812     }
   1813 
   1814     SpdyDataIR data_ir(1);
   1815     data_ir.SetDataShallow(base::StringPiece(bytes, strlen(bytes)));
   1816     frame.reset(framer.SerializeDataFrameHeader(data_ir));
   1817     CompareCharArraysWithHexError(
   1818         kDescription,
   1819         reinterpret_cast<const unsigned char*>(frame->data()),
   1820         framer.GetDataFrameMinimumSize(),
   1821         IsSpdy4() ? kV4FrameData : kV3FrameData,
   1822         framer.GetDataFrameMinimumSize());
   1823   }
   1824 
   1825   {
   1826     const char kDescription[] = "Data frame with negative data byte, no FIN";
   1827     const unsigned char kV3FrameData[] = {  // Also applies for V2.
   1828       0x00, 0x00, 0x00, 0x01,
   1829       0x00, 0x00, 0x00, 0x01,
   1830       0xff
   1831     };
   1832     const unsigned char kV4FrameData[] = {
   1833       0x00, 0x09, 0x00, 0x00,
   1834       0x00, 0x00, 0x00, 0x01,
   1835       0xff
   1836     };
   1837     scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
   1838         1, "\xff", 1, DATA_FLAG_NONE));
   1839     if (IsSpdy4()) {
   1840        CompareFrame(
   1841            kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   1842     } else {
   1843        CompareFrame(
   1844            kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   1845     }
   1846   }
   1847 
   1848   {
   1849     const char kDescription[] = "'hello' data frame, with FIN";
   1850     const unsigned char kV3FrameData[] = {  // Also applies for V2.
   1851       0x00, 0x00, 0x00, 0x01,
   1852       0x01, 0x00, 0x00, 0x05,
   1853       'h', 'e', 'l', 'l',
   1854       'o'
   1855     };
   1856     const unsigned char kV4FrameData[] = {
   1857       0x00, 0x0d, 0x00, 0x01,
   1858       0x00, 0x00, 0x00, 0x01,
   1859       'h',  'e',  'l',  'l',
   1860       'o'
   1861     };
   1862     scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
   1863         1, "hello", 5, DATA_FLAG_FIN));
   1864     if (IsSpdy4()) {
   1865        CompareFrame(
   1866            kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   1867     } else {
   1868        CompareFrame(
   1869            kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   1870     }
   1871   }
   1872 
   1873   {
   1874     const char kDescription[] = "Empty data frame";
   1875     const unsigned char kV3FrameData[] = {  // Also applies for V2.
   1876       0x00, 0x00, 0x00, 0x01,
   1877       0x00, 0x00, 0x00, 0x00,
   1878     };
   1879     const unsigned char kV4FrameData[] = {
   1880       0x00, 0x08, 0x00, 0x00,
   1881       0x00, 0x00, 0x00, 0x01,
   1882     };
   1883     scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
   1884         1, "", 0, DATA_FLAG_NONE));
   1885     if (IsSpdy4()) {
   1886        CompareFrame(
   1887            kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   1888     } else {
   1889        CompareFrame(
   1890            kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   1891     }
   1892   }
   1893 
   1894   {
   1895     const char kDescription[] = "Data frame with max stream ID";
   1896     const unsigned char kV3FrameData[] = {  // Also applies for V2.
   1897       0x7f, 0xff, 0xff, 0xff,
   1898       0x01, 0x00, 0x00, 0x05,
   1899       'h',  'e',  'l',  'l',
   1900       'o'
   1901     };
   1902     const unsigned char kV4FrameData[] = {
   1903       0x00, 0x0d, 0x00, 0x01,
   1904       0x7f, 0xff, 0xff, 0xff,
   1905       'h',  'e',  'l',  'l',
   1906       'o'
   1907     };
   1908     scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
   1909         0x7fffffff, "hello", 5, DATA_FLAG_FIN));
   1910     if (IsSpdy4()) {
   1911        CompareFrame(
   1912            kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   1913     } else {
   1914        CompareFrame(
   1915            kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   1916     }
   1917   }
   1918 
   1919   if (!IsSpdy4()) {
   1920     // This test does not apply to SPDY 4 because the max frame size is smaller
   1921     // than 4MB.
   1922     const char kDescription[] = "Large data frame";
   1923     const int kDataSize = 4 * 1024 * 1024;  // 4 MB
   1924     const string kData(kDataSize, 'A');
   1925     const unsigned char kFrameHeader[] = {
   1926       0x00, 0x00, 0x00, 0x01,
   1927       0x01, 0x40, 0x00, 0x00,
   1928     };
   1929 
   1930     const int kFrameSize = arraysize(kFrameHeader) + kDataSize;
   1931     scoped_ptr<unsigned char[]> expected_frame_data(
   1932         new unsigned char[kFrameSize]);
   1933     memcpy(expected_frame_data.get(), kFrameHeader, arraysize(kFrameHeader));
   1934     memset(expected_frame_data.get() + arraysize(kFrameHeader), 'A', kDataSize);
   1935 
   1936     scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
   1937         1, kData.data(), kData.size(), DATA_FLAG_FIN));
   1938     CompareFrame(kDescription, *frame, expected_frame_data.get(), kFrameSize);
   1939   }
   1940 }
   1941 
   1942 TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
   1943   SpdyFramer framer(spdy_version_);
   1944   framer.set_enable_compression(false);
   1945 
   1946   {
   1947     const char kDescription[] = "SYN_STREAM frame, lowest pri, slot 2, no FIN";
   1948 
   1949     SpdyHeaderBlock headers;
   1950     headers["bar"] = "foo";
   1951     headers["foo"] = "bar";
   1952 
   1953     const unsigned char kPri = IsSpdy2() ? 0xC0 : 0xE0;
   1954     const unsigned char kCre = IsSpdy2() ? 0 : 2;
   1955     const unsigned char kV2FrameData[] = {
   1956       0x80, spdy_version_ch_, 0x00, 0x01,
   1957       0x00, 0x00, 0x00, 0x20,
   1958       0x00, 0x00, 0x00, 0x01,
   1959       0x00, 0x00, 0x00, 0x00,
   1960       kPri, 0x00, 0x00, 0x02,
   1961       0x00, 0x03, 'b',  'a',
   1962       'r',  0x00, 0x03, 'f',
   1963       'o',  'o',  0x00, 0x03,
   1964       'f',  'o',  'o',  0x00,
   1965       0x03, 'b',  'a',  'r'
   1966     };
   1967     const unsigned char kV3FrameData[] = {
   1968       0x80, spdy_version_ch_, 0x00, 0x01,
   1969       0x00, 0x00, 0x00, 0x2a,
   1970       0x00, 0x00, 0x00, 0x01,
   1971       0x00, 0x00, 0x00, 0x00,
   1972       kPri, kCre, 0x00, 0x00,
   1973       0x00, 0x02, 0x00, 0x00,
   1974       0x00, 0x03, 'b',  'a',
   1975       'r',  0x00, 0x00, 0x00,
   1976       0x03, 'f',  'o',  'o',
   1977       0x00, 0x00, 0x00, 0x03,
   1978       'f',  'o',  'o',  0x00,
   1979       0x00, 0x00, 0x03, 'b',
   1980       'a',  'r'
   1981     };
   1982     const unsigned char kV4FrameData[] = {
   1983       0x00, 0x2e, 0x01, 0x00,
   1984       0x00, 0x00, 0x00, 0x01,
   1985       0x00, 0x00, 0x00, 0x00,
   1986       kPri, kCre, 0x00, 0x00,
   1987       0x00, 0x02, 0x00, 0x00,
   1988       0x00, 0x03, 'b',  'a',
   1989       'r',  0x00, 0x00, 0x00,
   1990       0x03, 'f',  'o',  'o',
   1991       0x00, 0x00, 0x00, 0x03,
   1992       'f',  'o',  'o',  0x00,
   1993       0x00, 0x00, 0x03, 'b',
   1994       'a',  'r'
   1995     };
   1996     scoped_ptr<SpdyFrame> frame(
   1997         framer.CreateSynStream(1,  // stream id
   1998                                0,  // associated stream id
   1999                                framer.GetLowestPriority(),
   2000                                kCre,  // credential slot
   2001                                CONTROL_FLAG_NONE,
   2002                                false,  // compress
   2003                                &headers));
   2004     if (IsSpdy2()) {
   2005       CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
   2006     } else if (IsSpdy3()) {
   2007       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   2008     } else {
   2009       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   2010     }
   2011   }
   2012 
   2013   {
   2014     const char kDescription[] =
   2015         "SYN_STREAM frame with a 0-length header name, highest pri, FIN, "
   2016         "max stream ID";
   2017 
   2018     SpdyHeaderBlock headers;
   2019     headers[std::string()] = "foo";
   2020     headers["foo"] = "bar";
   2021 
   2022     const unsigned char kV2FrameData[] = {
   2023       0x80, spdy_version_ch_, 0x00, 0x01,
   2024       0x01, 0x00, 0x00, 0x1D,
   2025       0x7f, 0xff, 0xff, 0xff,
   2026       0x7f, 0xff, 0xff, 0xff,
   2027       0x00, 0x00, 0x00, 0x02,
   2028       0x00, 0x00, 0x00, 0x03,
   2029       'f',  'o',  'o',  0x00,
   2030       0x03, 'f',  'o',  'o',
   2031       0x00, 0x03, 'b',  'a',
   2032       'r'
   2033     };
   2034     const unsigned char kV3FrameData[] = {
   2035       0x80, spdy_version_ch_, 0x00, 0x01,
   2036       0x01, 0x00, 0x00, 0x27,
   2037       0x7f, 0xff, 0xff, 0xff,
   2038       0x7f, 0xff, 0xff, 0xff,
   2039       0x00, 0x00, 0x00, 0x00,
   2040       0x00, 0x02, 0x00, 0x00,
   2041       0x00, 0x00, 0x00, 0x00,
   2042       0x00, 0x03, 'f',  'o',
   2043       'o',  0x00, 0x00, 0x00,
   2044       0x03, 'f',  'o',  'o',
   2045       0x00, 0x00, 0x00, 0x03,
   2046       'b',  'a',  'r'
   2047     };
   2048     const unsigned char kV4FrameData[] = {
   2049       0x00, 0x2b, 0x01, 0x01,
   2050       0x7f, 0xff, 0xff, 0xff,
   2051       0x7f, 0xff, 0xff, 0xff,
   2052       0x00, 0x00, 0x00, 0x00,
   2053       0x00, 0x02, 0x00, 0x00,
   2054       0x00, 0x00, 0x00, 0x00,
   2055       0x00, 0x03, 'f',  'o',
   2056       'o',  0x00, 0x00, 0x00,
   2057       0x03, 'f',  'o',  'o',
   2058       0x00, 0x00, 0x00, 0x03,
   2059       'b',  'a',  'r'
   2060     };
   2061     scoped_ptr<SpdyFrame> frame(
   2062         framer.CreateSynStream(0x7fffffff,  // stream id
   2063                                0x7fffffff,  // associated stream id
   2064                                framer.GetHighestPriority(),
   2065                                0,  // credential slot
   2066                                CONTROL_FLAG_FIN,
   2067                                false,  // compress
   2068                                &headers));
   2069     if (IsSpdy2()) {
   2070       CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
   2071     } else if (IsSpdy3()) {
   2072       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   2073     } else {
   2074       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   2075     }
   2076   }
   2077 
   2078   {
   2079     const char kDescription[] =
   2080         "SYN_STREAM frame with a 0-length header val, high pri, FIN, "
   2081         "max stream ID";
   2082 
   2083     SpdyHeaderBlock headers;
   2084     headers["bar"] = "foo";
   2085     headers["foo"] = "";
   2086 
   2087     const unsigned char kPri = IsSpdy2() ? 0x40 : 0x20;
   2088     const unsigned char kV2FrameData[] = {
   2089       0x80, spdy_version_ch_, 0x00, 0x01,
   2090       0x01, 0x00, 0x00, 0x1D,
   2091       0x7f, 0xff, 0xff, 0xff,
   2092       0x7f, 0xff, 0xff, 0xff,
   2093       kPri, 0x00, 0x00, 0x02,
   2094       0x00, 0x03, 'b',  'a',
   2095       'r',  0x00, 0x03, 'f',
   2096       'o',  'o',  0x00, 0x03,
   2097       'f',  'o',  'o',  0x00,
   2098       0x00
   2099     };
   2100     const unsigned char kV3FrameData[] = {
   2101       0x80, spdy_version_ch_, 0x00, 0x01,
   2102       0x01, 0x00, 0x00, 0x27,
   2103       0x7f, 0xff, 0xff, 0xff,
   2104       0x7f, 0xff, 0xff, 0xff,
   2105       kPri, 0x00, 0x00, 0x00,
   2106       0x00, 0x02, 0x00, 0x00,
   2107       0x00, 0x03, 'b',  'a',
   2108       'r',  0x00, 0x00, 0x00,
   2109       0x03, 'f',  'o',  'o',
   2110       0x00, 0x00, 0x00, 0x03,
   2111       'f',  'o',  'o',  0x00,
   2112       0x00, 0x00, 0x00
   2113     };
   2114     const unsigned char kV4FrameData[] = {
   2115       0x00, 0x2b, 0x01, 0x01,
   2116       0x7f, 0xff, 0xff, 0xff,
   2117       0x7f, 0xff, 0xff, 0xff,
   2118       kPri, 0x00, 0x00, 0x00,
   2119       0x00, 0x02, 0x00, 0x00,
   2120       0x00, 0x03, 'b',  'a',
   2121       'r',  0x00, 0x00, 0x00,
   2122       0x03, 'f',  'o',  'o',
   2123       0x00, 0x00, 0x00, 0x03,
   2124       'f',  'o',  'o',  0x00,
   2125       0x00, 0x00, 0x00
   2126     };
   2127     scoped_ptr<SpdyFrame> frame(
   2128         framer.CreateSynStream(0x7fffffff,  // stream id
   2129                                0x7fffffff,  // associated stream id
   2130                                1,  // priority
   2131                                0,  // credential slot
   2132                                CONTROL_FLAG_FIN,
   2133                                false,  // compress
   2134                                &headers));
   2135     if (IsSpdy2()) {
   2136       CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
   2137     } else if (IsSpdy3()) {
   2138       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   2139     } else {
   2140       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   2141     }
   2142   }
   2143 }
   2144 
   2145 // TODO(phajdan.jr): Clean up after we no longer need
   2146 // to workaround http://crbug.com/139744.
   2147 #if !defined(USE_SYSTEM_ZLIB)
   2148 TEST_P(SpdyFramerTest, CreateSynStreamCompressed) {
   2149   SpdyFramer framer(spdy_version_);
   2150   framer.set_enable_compression(true);
   2151 
   2152   {
   2153     const char kDescription[] =
   2154         "SYN_STREAM frame, low pri, no FIN";
   2155 
   2156     SpdyHeaderBlock headers;
   2157     headers["bar"] = "foo";
   2158     headers["foo"] = "bar";
   2159 
   2160     const SpdyPriority priority = IsSpdy2() ? 2 : 4;
   2161     const unsigned char kV2FrameData[] = {
   2162       0x80, spdy_version_ch_, 0x00, 0x01,
   2163       0x00, 0x00, 0x00, 0x36,
   2164       0x00, 0x00, 0x00, 0x01,
   2165       0x00, 0x00, 0x00, 0x00,
   2166       0x80, 0x00, 0x38, 0xea,
   2167       0xdf, 0xa2, 0x51, 0xb2,
   2168       0x62, 0x60, 0x62, 0x60,
   2169       0x4e, 0x4a, 0x2c, 0x62,
   2170       0x60, 0x06, 0x08, 0xa0,
   2171       0xb4, 0xfc, 0x7c, 0x80,
   2172       0x00, 0x62, 0x60, 0x4e,
   2173       0xcb, 0xcf, 0x67, 0x60,
   2174       0x06, 0x08, 0xa0, 0xa4,
   2175       0xc4, 0x22, 0x80, 0x00,
   2176       0x02, 0x00, 0x00, 0x00,
   2177       0xff, 0xff,
   2178     };
   2179     const unsigned char kV3FrameData[] = {
   2180       0x80, spdy_version_ch_, 0x00, 0x01,
   2181       0x00, 0x00, 0x00, 0x37,
   2182       0x00, 0x00, 0x00, 0x01,
   2183       0x00, 0x00, 0x00, 0x00,
   2184       0x80, 0x00, 0x38, 0xEA,
   2185       0xE3, 0xC6, 0xA7, 0xC2,
   2186       0x02, 0xE5, 0x0E, 0x50,
   2187       0xC2, 0x4B, 0x4A, 0x04,
   2188       0xE5, 0x0B, 0x66, 0x80,
   2189       0x00, 0x4A, 0xCB, 0xCF,
   2190       0x07, 0x08, 0x20, 0x10,
   2191       0x95, 0x96, 0x9F, 0x0F,
   2192       0xA2, 0x00, 0x02, 0x28,
   2193       0x29, 0xB1, 0x08, 0x20,
   2194       0x80, 0x00, 0x00, 0x00,
   2195       0x00, 0xFF, 0xFF,
   2196     };
   2197     const unsigned char kV4FrameData[] = {
   2198       0x00, 0x3b, 0x01, 0x00,
   2199       0x00, 0x00, 0x00, 0x01,
   2200       0x00, 0x00, 0x00, 0x00,
   2201       0x80, 0x00, 0x38, 0xea,
   2202       0xe3, 0xc6, 0xa7, 0xc2,
   2203       0x02, 0xe5, 0x0e, 0x50,
   2204       0xc2, 0x4b, 0x4a, 0x04,
   2205       0xe5, 0x0b, 0x66, 0x80,
   2206       0x00, 0x4a, 0xcb, 0xcf,
   2207       0x07, 0x08, 0x20, 0x10,
   2208       0x95, 0x96, 0x9f, 0x0f,
   2209       0xa2, 0x00, 0x02, 0x28,
   2210       0x29, 0xb1, 0x08, 0x20,
   2211       0x80, 0x00, 0x00, 0x00,
   2212       0x00, 0xff, 0xff,
   2213     };
   2214     scoped_ptr<SpdyFrame> frame(
   2215         framer.CreateSynStream(1,  // stream id
   2216                                0,  // associated stream id
   2217                                priority,
   2218                                0,  // credential slot
   2219                                CONTROL_FLAG_NONE,
   2220                                true,  // compress
   2221                                &headers));
   2222     if (IsSpdy2()) {
   2223       CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
   2224     } else if (IsSpdy3()) {
   2225       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   2226     } else {
   2227       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   2228     }
   2229   }
   2230 }
   2231 #endif  // !defined(USE_SYSTEM_ZLIB)
   2232 
   2233 TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
   2234   SpdyFramer framer(spdy_version_);
   2235   framer.set_enable_compression(false);
   2236 
   2237   {
   2238     const char kDescription[] = "SYN_REPLY frame, no FIN";
   2239 
   2240     SpdyHeaderBlock headers;
   2241     headers["bar"] = "foo";
   2242     headers["foo"] = "bar";
   2243 
   2244     const unsigned char kV2FrameData[] = {
   2245       0x80, spdy_version_ch_, 0x00, 0x02,
   2246       0x00, 0x00, 0x00, 0x1C,
   2247       0x00, 0x00, 0x00, 0x01,
   2248       0x00, 0x00, 0x00, 0x02,
   2249       0x00, 0x03, 'b',  'a',
   2250       'r',  0x00, 0x03, 'f',
   2251       'o',  'o',  0x00, 0x03,
   2252       'f',  'o',  'o',  0x00,
   2253       0x03, 'b',  'a',  'r'
   2254     };
   2255     const unsigned char kV3FrameData[] = {
   2256       0x80, spdy_version_ch_, 0x00, 0x02,
   2257       0x00, 0x00, 0x00, 0x24,
   2258       0x00, 0x00, 0x00, 0x01,
   2259       0x00, 0x00, 0x00, 0x02,
   2260       0x00, 0x00, 0x00, 0x03,
   2261       'b',  'a',  'r',  0x00,
   2262       0x00, 0x00, 0x03, 'f',
   2263       'o',  'o',  0x00, 0x00,
   2264       0x00, 0x03, 'f',  'o',
   2265       'o',  0x00, 0x00, 0x00,
   2266       0x03, 'b',  'a',  'r'
   2267     };
   2268     const unsigned char kV4FrameData[] = {
   2269       0x00, 0x28, 0x02, 0x00,
   2270       0x00, 0x00, 0x00, 0x01,
   2271       0x00, 0x00, 0x00, 0x02,
   2272       0x00, 0x00, 0x00, 0x03,
   2273       'b',  'a',  'r',  0x00,
   2274       0x00, 0x00, 0x03, 'f',
   2275       'o',  'o',  0x00, 0x00,
   2276       0x00, 0x03, 'f',  'o',
   2277       'o',  0x00, 0x00, 0x00,
   2278       0x03, 'b',  'a',  'r'
   2279     };
   2280     scoped_ptr<SpdyFrame> frame(framer.CreateSynReply(
   2281         1, CONTROL_FLAG_NONE, false, &headers));
   2282     if (IsSpdy2()) {
   2283       CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
   2284     } else if (IsSpdy3()) {
   2285       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   2286     } else {
   2287       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   2288     }
   2289   }
   2290 
   2291   {
   2292     const char kDescription[] =
   2293         "SYN_REPLY frame with a 0-length header name, FIN, max stream ID";
   2294 
   2295     SpdyHeaderBlock headers;
   2296     headers[std::string()] = "foo";
   2297     headers["foo"] = "bar";
   2298 
   2299     const unsigned char kV2FrameData[] = {
   2300       0x80, spdy_version_ch_, 0x00, 0x02,
   2301       0x01, 0x00, 0x00, 0x19,
   2302       0x7f, 0xff, 0xff, 0xff,
   2303       0x00, 0x00, 0x00, 0x02,
   2304       0x00, 0x00, 0x00, 0x03,
   2305       'f',  'o',  'o',  0x00,
   2306       0x03, 'f',  'o',  'o',
   2307       0x00, 0x03, 'b',  'a',
   2308       'r'
   2309     };
   2310     const unsigned char kV3FrameData[] = {
   2311       0x80, spdy_version_ch_, 0x00, 0x02,
   2312       0x01, 0x00, 0x00, 0x21,
   2313       0x7f, 0xff, 0xff, 0xff,
   2314       0x00, 0x00, 0x00, 0x02,
   2315       0x00, 0x00, 0x00, 0x00,
   2316       0x00, 0x00, 0x00, 0x03,
   2317       'f',  'o',  'o',  0x00,
   2318       0x00, 0x00, 0x03, 'f',
   2319       'o',  'o',  0x00, 0x00,
   2320       0x00, 0x03, 'b',  'a',
   2321       'r'
   2322     };
   2323     const unsigned char kV4FrameData[] = {
   2324       0x00, 0x25, 0x02, 0x01,
   2325       0x7f, 0xff, 0xff, 0xff,
   2326       0x00, 0x00, 0x00, 0x02,
   2327       0x00, 0x00, 0x00, 0x00,
   2328       0x00, 0x00, 0x00, 0x03,
   2329       'f',  'o',  'o',  0x00,
   2330       0x00, 0x00, 0x03, 'f',
   2331       'o',  'o',  0x00, 0x00,
   2332       0x00, 0x03, 'b',  'a',
   2333       'r'
   2334     };
   2335     scoped_ptr<SpdyFrame> frame(framer.CreateSynReply(
   2336         0x7fffffff, CONTROL_FLAG_FIN, false, &headers));
   2337     if (IsSpdy2()) {
   2338       CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
   2339     } else if (IsSpdy3()) {
   2340       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   2341     } else {
   2342       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   2343     }
   2344   }
   2345 
   2346   {
   2347     const char kDescription[] =
   2348         "SYN_REPLY frame with a 0-length header val, FIN, max stream ID";
   2349 
   2350     SpdyHeaderBlock headers;
   2351     headers["bar"] = "foo";
   2352     headers["foo"] = "";
   2353 
   2354     const unsigned char kV2FrameData[] = {
   2355       0x80, spdy_version_ch_, 0x00, 0x02,
   2356       0x01, 0x00, 0x00, 0x19,
   2357       0x7f, 0xff, 0xff, 0xff,
   2358       0x00, 0x00, 0x00, 0x02,
   2359       0x00, 0x03, 'b',  'a',
   2360       'r',  0x00, 0x03, 'f',
   2361       'o',  'o',  0x00, 0x03,
   2362       'f',  'o',  'o',  0x00,
   2363       0x00
   2364     };
   2365     const unsigned char kV3FrameData[] = {
   2366       0x80, spdy_version_ch_, 0x00, 0x02,
   2367       0x01, 0x00, 0x00, 0x21,
   2368       0x7f, 0xff, 0xff, 0xff,
   2369       0x00, 0x00, 0x00, 0x02,
   2370       0x00, 0x00, 0x00, 0x03,
   2371       'b',  'a',  'r',  0x00,
   2372       0x00, 0x00, 0x03, 'f',
   2373       'o',  'o',  0x00, 0x00,
   2374       0x00, 0x03, 'f',  'o',
   2375       'o',  0x00, 0x00, 0x00,
   2376       0x00
   2377     };
   2378     const unsigned char kV4FrameData[] = {
   2379       0x00, 0x25, 0x02, 0x01,
   2380       0x7f, 0xff, 0xff, 0xff,
   2381       0x00, 0x00, 0x00, 0x02,
   2382       0x00, 0x00, 0x00, 0x03,
   2383       'b',  'a',  'r',  0x00,
   2384       0x00, 0x00, 0x03, 'f',
   2385       'o',  'o',  0x00, 0x00,
   2386       0x00, 0x03, 'f',  'o',
   2387       'o',  0x00, 0x00, 0x00,
   2388       0x00
   2389     };
   2390     scoped_ptr<SpdyFrame> frame(framer.CreateSynReply(
   2391         0x7fffffff, CONTROL_FLAG_FIN, false, &headers));
   2392     if (IsSpdy2()) {
   2393       CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
   2394     } else if (IsSpdy3()) {
   2395       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   2396     } else {
   2397       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   2398     }
   2399   }
   2400 }
   2401 
   2402 // TODO(phajdan.jr): Clean up after we no longer need
   2403 // to workaround http://crbug.com/139744.
   2404 #if !defined(USE_SYSTEM_ZLIB)
   2405 TEST_P(SpdyFramerTest, CreateSynReplyCompressed) {
   2406   SpdyFramer framer(spdy_version_);
   2407   framer.set_enable_compression(true);
   2408 
   2409   {
   2410     const char kDescription[] = "SYN_REPLY frame, no FIN";
   2411 
   2412     SpdyHeaderBlock headers;
   2413     headers["bar"] = "foo";
   2414     headers["foo"] = "bar";
   2415 
   2416     const unsigned char kV2FrameData[] = {
   2417       0x80, spdy_version_ch_, 0x00, 0x02,
   2418       0x00, 0x00, 0x00, 0x32,
   2419       0x00, 0x00, 0x00, 0x01,
   2420       0x00, 0x00, 0x38, 0xea,
   2421       0xdf, 0xa2, 0x51, 0xb2,
   2422       0x62, 0x60, 0x62, 0x60,
   2423       0x4e, 0x4a, 0x2c, 0x62,
   2424       0x60, 0x06, 0x08, 0xa0,
   2425       0xb4, 0xfc, 0x7c, 0x80,
   2426       0x00, 0x62, 0x60, 0x4e,
   2427       0xcb, 0xcf, 0x67, 0x60,
   2428       0x06, 0x08, 0xa0, 0xa4,
   2429       0xc4, 0x22, 0x80, 0x00,
   2430       0x02, 0x00, 0x00, 0x00,
   2431       0xff, 0xff,
   2432     };
   2433     const unsigned char kV3FrameData[] = {
   2434       0x80, spdy_version_ch_, 0x00, 0x02,
   2435       0x00, 0x00, 0x00, 0x31,
   2436       0x00, 0x00, 0x00, 0x01,
   2437       0x38, 0xea, 0xe3, 0xc6,
   2438       0xa7, 0xc2, 0x02, 0xe5,
   2439       0x0e, 0x50, 0xc2, 0x4b,
   2440       0x4a, 0x04, 0xe5, 0x0b,
   2441       0x66, 0x80, 0x00, 0x4a,
   2442       0xcb, 0xcf, 0x07, 0x08,
   2443       0x20, 0x10, 0x95, 0x96,
   2444       0x9f, 0x0f, 0xa2, 0x00,
   2445       0x02, 0x28, 0x29, 0xb1,
   2446       0x08, 0x20, 0x80, 0x00,
   2447       0x00, 0x00, 0x00, 0xff,
   2448       0xff,
   2449     };
   2450     const unsigned char kV4FrameData[] = {
   2451       0x00, 0x35, 0x02, 0x00,
   2452       0x00, 0x00, 0x00, 0x01,
   2453       0x38, 0xea, 0xe3, 0xc6,
   2454       0xa7, 0xc2, 0x02, 0xe5,
   2455       0x0e, 0x50, 0xc2, 0x4b,
   2456       0x4a, 0x04, 0xe5, 0x0b,
   2457       0x66, 0x80, 0x00, 0x4a,
   2458       0xcb, 0xcf, 0x07, 0x08,
   2459       0x20, 0x10, 0x95, 0x96,
   2460       0x9f, 0x0f, 0xa2, 0x00,
   2461       0x02, 0x28, 0x29, 0xb1,
   2462       0x08, 0x20, 0x80, 0x00,
   2463       0x00, 0x00, 0x00, 0xff,
   2464       0xff,
   2465     };
   2466     scoped_ptr<SpdyFrame> frame(framer.CreateSynReply(
   2467         1, CONTROL_FLAG_NONE, true, &headers));
   2468     if (IsSpdy2()) {
   2469       CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
   2470     } else if (IsSpdy3()) {
   2471       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   2472     } else {
   2473       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   2474     }
   2475   }
   2476 }
   2477 #endif  // !defined(USE_SYSTEM_ZLIB)
   2478 
   2479 TEST_P(SpdyFramerTest, CreateRstStream) {
   2480   SpdyFramer framer(spdy_version_);
   2481 
   2482   {
   2483     const char kDescription[] = "RST_STREAM frame";
   2484     const unsigned char kV3FrameData[] = {  // Also applies for V2.
   2485       0x80, spdy_version_ch_, 0x00, 0x03,
   2486       0x00, 0x00, 0x00, 0x08,
   2487       0x00, 0x00, 0x00, 0x01,
   2488       0x00, 0x00, 0x00, 0x01,
   2489     };
   2490     const unsigned char kV4FrameData[] = {
   2491       0x00, 0x0c, 0x03, 0x00,
   2492       0x00, 0x00, 0x00, 0x01,
   2493       0x00, 0x00, 0x00, 0x01,
   2494     };
   2495     scoped_ptr<SpdyFrame> frame(
   2496         framer.CreateRstStream(1, RST_STREAM_PROTOCOL_ERROR));
   2497     if (IsSpdy4()) {
   2498       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   2499     } else {
   2500       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   2501     }
   2502   }
   2503 
   2504   {
   2505     const char kDescription[] = "RST_STREAM frame with max stream ID";
   2506     const unsigned char kV3FrameData[] = {  // Also applies for V2.
   2507       0x80, spdy_version_ch_, 0x00, 0x03,
   2508       0x00, 0x00, 0x00, 0x08,
   2509       0x7f, 0xff, 0xff, 0xff,
   2510       0x00, 0x00, 0x00, 0x01,
   2511     };
   2512     const unsigned char kV4FrameData[] = {
   2513       0x00, 0x0c, 0x03, 0x00,
   2514       0x7f, 0xff, 0xff, 0xff,
   2515       0x00, 0x00, 0x00, 0x01,
   2516     };
   2517     scoped_ptr<SpdyFrame> frame(framer.CreateRstStream(
   2518         0x7FFFFFFF, RST_STREAM_PROTOCOL_ERROR));
   2519     if (IsSpdy4()) {
   2520       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   2521     } else {
   2522       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   2523     }
   2524   }
   2525 
   2526   {
   2527     const char kDescription[] = "RST_STREAM frame with max status code";
   2528     const unsigned char kV3FrameData[] = {  // Also applies for V2.
   2529       0x80, spdy_version_ch_, 0x00, 0x03,
   2530       0x00, 0x00, 0x00, 0x08,
   2531       0x7f, 0xff, 0xff, 0xff,
   2532       0x00, 0x00, 0x00, 0x06,
   2533     };
   2534     const unsigned char kV4FrameData[] = {
   2535       0x00, 0x0c, 0x03, 0x00,
   2536       0x7f, 0xff, 0xff, 0xff,
   2537       0x00, 0x00, 0x00, 0x06,
   2538     };
   2539     scoped_ptr<SpdyFrame> frame(framer.CreateRstStream(
   2540         0x7FFFFFFF, RST_STREAM_INTERNAL_ERROR));
   2541     if (IsSpdy4()) {
   2542       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   2543     } else {
   2544       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   2545     }
   2546   }
   2547 }
   2548 
   2549 TEST_P(SpdyFramerTest, CreateSettings) {
   2550   SpdyFramer framer(spdy_version_);
   2551 
   2552   {
   2553     const char kDescription[] = "Network byte order SETTINGS frame";
   2554 
   2555     uint32 kValue = 0x0a0b0c0d;
   2556     SpdySettingsFlags kFlags = static_cast<SpdySettingsFlags>(0x01);
   2557     SpdySettingsIds kId = static_cast<SpdySettingsIds>(0x020304);
   2558 
   2559     SettingsMap settings;
   2560     settings[kId] = SettingsFlagsAndValue(kFlags, kValue);
   2561 
   2562     EXPECT_EQ(kFlags, settings[kId].first);
   2563     EXPECT_EQ(kValue, settings[kId].second);
   2564 
   2565     const unsigned char kV2FrameData[] = {
   2566       0x80, spdy_version_ch_, 0x00, 0x04,
   2567       0x00, 0x00, 0x00, 0x0c,
   2568       0x00, 0x00, 0x00, 0x01,
   2569       0x04, 0x03, 0x02, 0x01,
   2570       0x0a, 0x0b, 0x0c, 0x0d,
   2571     };
   2572     const unsigned char kV3FrameData[] = {
   2573       0x80, spdy_version_ch_, 0x00, 0x04,
   2574       0x00, 0x00, 0x00, 0x0c,
   2575       0x00, 0x00, 0x00, 0x01,
   2576       0x01, 0x02, 0x03, 0x04,
   2577       0x0a, 0x0b, 0x0c, 0x0d,
   2578     };
   2579     const unsigned char kV4FrameData[] = {
   2580       0x00, 0x14, 0x04, 0x00,
   2581       0x00, 0x00, 0x00, 0x00,
   2582       0x00, 0x00, 0x00, 0x01,
   2583       0x01, 0x02, 0x03, 0x04,
   2584       0x0a, 0x0b, 0x0c, 0x0d,
   2585     };
   2586 
   2587     scoped_ptr<SpdyFrame> frame(framer.CreateSettings(settings));
   2588     if (IsSpdy2()) {
   2589       CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
   2590     } else if (IsSpdy3()) {
   2591       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   2592     } else {
   2593       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   2594     }
   2595   }
   2596 
   2597   {
   2598     const char kDescription[] = "Basic SETTINGS frame";
   2599 
   2600     SettingsMap settings;
   2601     AddSpdySettingFromWireFormat(
   2602         &settings, 0x00000000, 0x00000001);  // 1st Setting
   2603     AddSpdySettingFromWireFormat(
   2604         &settings, 0x01000001, 0x00000002);  // 2nd Setting
   2605     AddSpdySettingFromWireFormat(
   2606         &settings, 0x02000002, 0x00000003);  // 3rd Setting
   2607     AddSpdySettingFromWireFormat(
   2608         &settings, 0x03000003, 0xff000004);  // 4th Setting
   2609 
   2610     const unsigned char kV3FrameData[] = {  // Also applies for V2.
   2611       0x80, spdy_version_ch_, 0x00, 0x04,
   2612       0x00, 0x00, 0x00, 0x24,
   2613       0x00, 0x00, 0x00, 0x04,
   2614       0x00, 0x00, 0x00, 0x00,  // 1st Setting
   2615       0x00, 0x00, 0x00, 0x01,
   2616       0x01, 0x00, 0x00, 0x01,  // 2nd Setting
   2617       0x00, 0x00, 0x00, 0x02,
   2618       0x02, 0x00, 0x00, 0x02,  // 3rd Setting
   2619       0x00, 0x00, 0x00, 0x03,
   2620       0x03, 0x00, 0x00, 0x03,  // 4th Setting
   2621       0xff, 0x00, 0x00, 0x04,
   2622     };
   2623     const unsigned char kV4FrameData[] = {
   2624       0x00, 0x2c, 0x04, 0x00,
   2625       0x00, 0x00, 0x00, 0x00,
   2626       0x00, 0x00, 0x00, 0x04,
   2627       0x00, 0x00, 0x00, 0x00,  // 1st Setting
   2628       0x00, 0x00, 0x00, 0x01,
   2629       0x01, 0x00, 0x00, 0x01,  // 2nd Setting
   2630       0x00, 0x00, 0x00, 0x02,
   2631       0x02, 0x00, 0x00, 0x02,  // 3rd Setting
   2632       0x00, 0x00, 0x00, 0x03,
   2633       0x03, 0x00, 0x00, 0x03,  // 4th Setting
   2634       0xff, 0x00, 0x00, 0x04,
   2635     };
   2636     scoped_ptr<SpdyFrame> frame(framer.CreateSettings(settings));
   2637     if (IsSpdy4()) {
   2638       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   2639     } else {
   2640       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   2641     }
   2642   }
   2643 
   2644   {
   2645     const char kDescription[] = "Empty SETTINGS frame";
   2646 
   2647     SettingsMap settings;
   2648 
   2649     const unsigned char kV3FrameData[] = {  // Also applies for V2.
   2650       0x80, spdy_version_ch_, 0x00, 0x04,
   2651       0x00, 0x00, 0x00, 0x04,
   2652       0x00, 0x00, 0x00, 0x00,
   2653     };
   2654     const unsigned char kV4FrameData[] = {
   2655       0x00, 0x0c, 0x04, 0x00,
   2656       0x00, 0x00, 0x00, 0x00,
   2657       0x00, 0x00, 0x00, 0x00,
   2658     };
   2659     scoped_ptr<SpdyFrame> frame(framer.CreateSettings(settings));
   2660     if (IsSpdy4()) {
   2661       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   2662     } else {
   2663       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   2664     }
   2665   }
   2666 }
   2667 
   2668 TEST_P(SpdyFramerTest, CreatePingFrame) {
   2669   SpdyFramer framer(spdy_version_);
   2670 
   2671   {
   2672     const char kDescription[] = "PING frame";
   2673     const unsigned char kV3FrameData[] = {  // Also applies for V2.
   2674       0x80, spdy_version_ch_, 0x00, 0x06,
   2675       0x00, 0x00, 0x00, 0x04,
   2676       0x12, 0x34, 0x56, 0x78,
   2677     };
   2678     const unsigned char kV4FrameData[] = {
   2679       0x00, 0x0c, 0x06, 0x00,
   2680       0x00, 0x00, 0x00, 0x00,
   2681       0x12, 0x34, 0x56, 0x78,
   2682     };
   2683     scoped_ptr<SpdyFrame> frame(framer.CreatePingFrame(0x12345678u));
   2684     if (IsSpdy4()) {
   2685       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   2686     } else {
   2687       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   2688     }
   2689   }
   2690 }
   2691 
   2692 TEST_P(SpdyFramerTest, CreateGoAway) {
   2693   SpdyFramer framer(spdy_version_);
   2694 
   2695   {
   2696     const char kDescription[] = "GOAWAY frame";
   2697     const unsigned char kV2FrameData[] = {
   2698       0x80, spdy_version_ch_, 0x00, 0x07,
   2699       0x00, 0x00, 0x00, 0x04,
   2700       0x00, 0x00, 0x00, 0x00,
   2701     };
   2702     const unsigned char kV3FrameData[] = {
   2703       0x80, spdy_version_ch_, 0x00, 0x07,
   2704       0x00, 0x00, 0x00, 0x08,
   2705       0x00, 0x00, 0x00, 0x00,
   2706       0x00, 0x00, 0x00, 0x00,
   2707     };
   2708     const unsigned char kV4FrameData[] = {
   2709       0x00, 0x10, 0x07, 0x00,
   2710       0x00, 0x00, 0x00, 0x00,
   2711       0x00, 0x00, 0x00, 0x00,
   2712       0x00, 0x00, 0x00, 0x00,
   2713     };
   2714     scoped_ptr<SpdyFrame> frame(framer.CreateGoAway(0, GOAWAY_OK));
   2715     if (IsSpdy2()) {
   2716       CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
   2717     } else if (IsSpdy3()) {
   2718       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   2719     } else {
   2720       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   2721     }
   2722   }
   2723 
   2724   {
   2725     const char kDescription[] = "GOAWAY frame with max stream ID, status";
   2726     const unsigned char kV2FrameData[] = {
   2727       0x80, spdy_version_ch_, 0x00, 0x07,
   2728       0x00, 0x00, 0x00, 0x04,
   2729       0x7f, 0xff, 0xff, 0xff,
   2730     };
   2731     const unsigned char kV3FrameData[] = {
   2732       0x80, spdy_version_ch_, 0x00, 0x07,
   2733       0x00, 0x00, 0x00, 0x08,
   2734       0x7f, 0xff, 0xff, 0xff,
   2735       0x00, 0x00, 0x00, 0x02,
   2736     };
   2737     const unsigned char kV4FrameData[] = {
   2738       0x00, 0x10, 0x07, 0x00,
   2739       0x00, 0x00, 0x00, 0x00,
   2740       0x7f, 0xff, 0xff, 0xff,
   2741       0x00, 0x00, 0x00, 0x02,
   2742     };
   2743     scoped_ptr<SpdyFrame> frame(framer.CreateGoAway(0x7FFFFFFF,
   2744                                                     GOAWAY_INTERNAL_ERROR));
   2745     if (IsSpdy2()) {
   2746       CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
   2747     } else if (IsSpdy3()) {
   2748       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   2749     } else {
   2750       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   2751     }
   2752   }
   2753 }
   2754 
   2755 TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
   2756   SpdyFramer framer(spdy_version_);
   2757   framer.set_enable_compression(false);
   2758 
   2759   {
   2760     const char kDescription[] = "HEADERS frame, no FIN";
   2761 
   2762     SpdyHeaderBlock headers;
   2763     headers["bar"] = "foo";
   2764     headers["foo"] = "bar";
   2765 
   2766     const unsigned char kV2FrameData[] = {
   2767       0x80, spdy_version_ch_, 0x00, 0x08,
   2768       0x00, 0x00, 0x00, 0x1C,
   2769       0x00, 0x00, 0x00, 0x01,
   2770       0x00, 0x00, 0x00, 0x02,
   2771       0x00, 0x03, 'b',  'a',
   2772       'r',  0x00, 0x03, 'f',
   2773       'o',  'o',  0x00, 0x03,
   2774       'f',  'o',  'o',  0x00,
   2775       0x03, 'b',  'a',  'r'
   2776     };
   2777     const unsigned char kV3FrameData[] = {
   2778       0x80, spdy_version_ch_, 0x00, 0x08,
   2779       0x00, 0x00, 0x00, 0x24,
   2780       0x00, 0x00, 0x00, 0x01,
   2781       0x00, 0x00, 0x00, 0x02,
   2782       0x00, 0x00, 0x00, 0x03,
   2783       'b',  'a',  'r',  0x00,
   2784       0x00, 0x00, 0x03, 'f',
   2785       'o',  'o',  0x00, 0x00,
   2786       0x00, 0x03, 'f',  'o',
   2787       'o',  0x00, 0x00, 0x00,
   2788       0x03, 'b',  'a',  'r'
   2789     };
   2790     const unsigned char kV4FrameData[] = {
   2791       0x00, 0x28, 0x08, 0x00,
   2792       0x00, 0x00, 0x00, 0x01,
   2793       0x00, 0x00, 0x00, 0x02,
   2794       0x00, 0x00, 0x00, 0x03,
   2795       'b',  'a',  'r',  0x00,
   2796       0x00, 0x00, 0x03, 'f',
   2797       'o',  'o',  0x00, 0x00,
   2798       0x00, 0x03, 'f',  'o',
   2799       'o',  0x00, 0x00, 0x00,
   2800       0x03, 'b',  'a',  'r'
   2801     };
   2802     scoped_ptr<SpdyFrame> frame(framer.CreateHeaders(
   2803         1, CONTROL_FLAG_NONE, false, &headers));
   2804     if (IsSpdy2()) {
   2805       CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
   2806     } else if (IsSpdy3()) {
   2807       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   2808     } else {
   2809       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   2810     }
   2811   }
   2812 
   2813   {
   2814     const char kDescription[] =
   2815         "HEADERS frame with a 0-length header name, FIN, max stream ID";
   2816 
   2817     SpdyHeaderBlock headers;
   2818     headers[std::string()] = "foo";
   2819     headers["foo"] = "bar";
   2820 
   2821     const unsigned char kV2FrameData[] = {
   2822       0x80, spdy_version_ch_, 0x00, 0x08,
   2823       0x01, 0x00, 0x00, 0x19,
   2824       0x7f, 0xff, 0xff, 0xff,
   2825       0x00, 0x00, 0x00, 0x02,
   2826       0x00, 0x00, 0x00, 0x03,
   2827       'f',  'o',  'o',  0x00,
   2828       0x03, 'f',  'o',  'o',
   2829       0x00, 0x03, 'b',  'a',
   2830       'r'
   2831     };
   2832     const unsigned char kV3FrameData[] = {
   2833       0x80, spdy_version_ch_, 0x00, 0x08,
   2834       0x01, 0x00, 0x00, 0x21,
   2835       0x7f, 0xff, 0xff, 0xff,
   2836       0x00, 0x00, 0x00, 0x02,
   2837       0x00, 0x00, 0x00, 0x00,
   2838       0x00, 0x00, 0x00, 0x03,
   2839       'f',  'o',  'o',  0x00,
   2840       0x00, 0x00, 0x03, 'f',
   2841       'o',  'o',  0x00, 0x00,
   2842       0x00, 0x03, 'b',  'a',
   2843       'r'
   2844     };
   2845     const unsigned char kV4FrameData[] = {
   2846       0x00, 0x25, 0x08, 0x01,
   2847       0x7f, 0xff, 0xff, 0xff,
   2848       0x00, 0x00, 0x00, 0x02,
   2849       0x00, 0x00, 0x00, 0x00,
   2850       0x00, 0x00, 0x00, 0x03,
   2851       'f',  'o',  'o',  0x00,
   2852       0x00, 0x00, 0x03, 'f',
   2853       'o',  'o',  0x00, 0x00,
   2854       0x00, 0x03, 'b',  'a',
   2855       'r'
   2856     };
   2857     scoped_ptr<SpdyFrame> frame(framer.CreateHeaders(
   2858         0x7fffffff, CONTROL_FLAG_FIN, false, &headers));
   2859     if (IsSpdy2()) {
   2860       CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
   2861     } else if (IsSpdy3()) {
   2862       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   2863     } else {
   2864       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   2865     }
   2866   }
   2867 
   2868   {
   2869     const char kDescription[] =
   2870         "HEADERS frame with a 0-length header val, FIN, max stream ID";
   2871 
   2872     SpdyHeaderBlock headers;
   2873     headers["bar"] = "foo";
   2874     headers["foo"] = "";
   2875 
   2876     const unsigned char kV2FrameData[] = {
   2877       0x80, spdy_version_ch_, 0x00, 0x08,
   2878       0x01, 0x00, 0x00, 0x19,
   2879       0x7f, 0xff, 0xff, 0xff,
   2880       0x00, 0x00, 0x00, 0x02,
   2881       0x00, 0x03, 'b',  'a',
   2882       'r',  0x00, 0x03, 'f',
   2883       'o',  'o',  0x00, 0x03,
   2884       'f',  'o',  'o',  0x00,
   2885       0x00
   2886     };
   2887     const unsigned char kV3FrameData[] = {
   2888       0x80, spdy_version_ch_, 0x00, 0x08,
   2889       0x01, 0x00, 0x00, 0x21,
   2890       0x7f, 0xff, 0xff, 0xff,
   2891       0x00, 0x00, 0x00, 0x02,
   2892       0x00, 0x00, 0x00, 0x03,
   2893       'b',  'a',  'r',  0x00,
   2894       0x00, 0x00, 0x03, 'f',
   2895       'o',  'o',  0x00, 0x00,
   2896       0x00, 0x03, 'f',  'o',
   2897       'o',  0x00, 0x00, 0x00,
   2898       0x00
   2899     };
   2900     const unsigned char kV4FrameData[] = {
   2901       0x00, 0x25, 0x08, 0x01,
   2902       0x7f, 0xff, 0xff, 0xff,
   2903       0x00, 0x00, 0x00, 0x02,
   2904       0x00, 0x00, 0x00, 0x03,
   2905       'b',  'a',  'r',  0x00,
   2906       0x00, 0x00, 0x03, 'f',
   2907       'o',  'o',  0x00, 0x00,
   2908       0x00, 0x03, 'f',  'o',
   2909       'o',  0x00, 0x00, 0x00,
   2910       0x00
   2911     };
   2912     scoped_ptr<SpdyFrame> frame(framer.CreateHeaders(
   2913         0x7fffffff, CONTROL_FLAG_FIN, false, &headers));
   2914     if (IsSpdy2()) {
   2915       CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
   2916     } else if (IsSpdy3()) {
   2917       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   2918     } else {
   2919       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   2920     }
   2921   }
   2922 }
   2923 
   2924 // TODO(phajdan.jr): Clean up after we no longer need
   2925 // to workaround http://crbug.com/139744.
   2926 #if !defined(USE_SYSTEM_ZLIB)
   2927 TEST_P(SpdyFramerTest, CreateHeadersCompressed) {
   2928   SpdyFramer framer(spdy_version_);
   2929   framer.set_enable_compression(true);
   2930 
   2931   {
   2932     const char kDescription[] = "HEADERS frame, no FIN";
   2933 
   2934     SpdyHeaderBlock headers;
   2935     headers["bar"] = "foo";
   2936     headers["foo"] = "bar";
   2937 
   2938     const unsigned char kV2FrameData[] = {
   2939       0x80, spdy_version_ch_, 0x00, 0x08,
   2940       0x00, 0x00, 0x00, 0x32,
   2941       0x00, 0x00, 0x00, 0x01,
   2942       0x00, 0x00, 0x38, 0xea,
   2943       0xdf, 0xa2, 0x51, 0xb2,
   2944       0x62, 0x60, 0x62, 0x60,
   2945       0x4e, 0x4a, 0x2c, 0x62,
   2946       0x60, 0x06, 0x08, 0xa0,
   2947       0xb4, 0xfc, 0x7c, 0x80,
   2948       0x00, 0x62, 0x60, 0x4e,
   2949       0xcb, 0xcf, 0x67, 0x60,
   2950       0x06, 0x08, 0xa0, 0xa4,
   2951       0xc4, 0x22, 0x80, 0x00,
   2952       0x02, 0x00, 0x00, 0x00,
   2953       0xff, 0xff,
   2954     };
   2955     const unsigned char kV3FrameData[] = {
   2956       0x80, spdy_version_ch_, 0x00, 0x08,
   2957       0x00, 0x00, 0x00, 0x31,
   2958       0x00, 0x00, 0x00, 0x01,
   2959       0x38, 0xea, 0xe3, 0xc6,
   2960       0xa7, 0xc2, 0x02, 0xe5,
   2961       0x0e, 0x50, 0xc2, 0x4b,
   2962       0x4a, 0x04, 0xe5, 0x0b,
   2963       0x66, 0x80, 0x00, 0x4a,
   2964       0xcb, 0xcf, 0x07, 0x08,
   2965       0x20, 0x10, 0x95, 0x96,
   2966       0x9f, 0x0f, 0xa2, 0x00,
   2967       0x02, 0x28, 0x29, 0xb1,
   2968       0x08, 0x20, 0x80, 0x00,
   2969       0x00, 0x00, 0x00, 0xff,
   2970       0xff,
   2971     };
   2972     const unsigned char kV4FrameData[] = {
   2973       0x00, 0x35, 0x08, 0x00,
   2974       0x00, 0x00, 0x00, 0x01,
   2975       0x38, 0xea, 0xe3, 0xc6,
   2976       0xa7, 0xc2, 0x02, 0xe5,
   2977       0x0e, 0x50, 0xc2, 0x4b,
   2978       0x4a, 0x04, 0xe5, 0x0b,
   2979       0x66, 0x80, 0x00, 0x4a,
   2980       0xcb, 0xcf, 0x07, 0x08,
   2981       0x20, 0x10, 0x95, 0x96,
   2982       0x9f, 0x0f, 0xa2, 0x00,
   2983       0x02, 0x28, 0x29, 0xb1,
   2984       0x08, 0x20, 0x80, 0x00,
   2985       0x00, 0x00, 0x00, 0xff,
   2986       0xff
   2987     };
   2988     scoped_ptr<SpdyFrame> frame(framer.CreateHeaders(
   2989         1, CONTROL_FLAG_NONE, true, &headers));
   2990     if (IsSpdy2()) {
   2991       CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
   2992     } else if (IsSpdy3()) {
   2993       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   2994     } else {
   2995       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   2996     }
   2997   }
   2998 }
   2999 #endif  // !defined(USE_SYSTEM_ZLIB)
   3000 
   3001 TEST_P(SpdyFramerTest, CreateWindowUpdate) {
   3002   SpdyFramer framer(spdy_version_);
   3003 
   3004   {
   3005     const char kDescription[] = "WINDOW_UPDATE frame";
   3006     const unsigned char kV3FrameData[] = {  // Also applies for V2.
   3007       0x80, spdy_version_ch_, 0x00, 0x09,
   3008       0x00, 0x00, 0x00, 0x08,
   3009       0x00, 0x00, 0x00, 0x01,
   3010       0x00, 0x00, 0x00, 0x01,
   3011     };
   3012     const unsigned char kV4FrameData[] = {
   3013       0x00, 0x0c, 0x09, 0x00,
   3014       0x00, 0x00, 0x00, 0x01,
   3015       0x00, 0x00, 0x00, 0x01,
   3016     };
   3017     scoped_ptr<SpdyFrame> frame(
   3018         framer.CreateWindowUpdate(1, 1));
   3019     if (IsSpdy4()) {
   3020       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   3021     } else {
   3022       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   3023     }
   3024   }
   3025 
   3026   {
   3027     const char kDescription[] = "WINDOW_UPDATE frame with max stream ID";
   3028     const unsigned char kV3FrameData[] = {  // Also applies for V2.
   3029       0x80, spdy_version_ch_, 0x00, 0x09,
   3030       0x00, 0x00, 0x00, 0x08,
   3031       0x7f, 0xff, 0xff, 0xff,
   3032       0x00, 0x00, 0x00, 0x01,
   3033     };
   3034     const unsigned char kV4FrameData[] = {
   3035       0x00, 0x0c, 0x09, 0x00,
   3036       0x7f, 0xff, 0xff, 0xff,
   3037       0x00, 0x00, 0x00, 0x01,
   3038     };
   3039     scoped_ptr<SpdyFrame> frame(framer.CreateWindowUpdate(0x7FFFFFFF, 1));
   3040     if (IsSpdy4()) {
   3041       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   3042     } else {
   3043       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   3044     }
   3045   }
   3046 
   3047   {
   3048     const char kDescription[] = "WINDOW_UPDATE frame with max window delta";
   3049     const unsigned char kV3FrameData[] = {  // Also applies for V2.
   3050       0x80, spdy_version_ch_, 0x00, 0x09,
   3051       0x00, 0x00, 0x00, 0x08,
   3052       0x00, 0x00, 0x00, 0x01,
   3053       0x7f, 0xff, 0xff, 0xff,
   3054     };
   3055     const unsigned char kV4FrameData[] = {
   3056       0x00, 0x0c, 0x09, 0x00,
   3057       0x00, 0x00, 0x00, 0x01,
   3058       0x7f, 0xff, 0xff, 0xff,
   3059     };
   3060     scoped_ptr<SpdyFrame> frame(framer.CreateWindowUpdate(1, 0x7FFFFFFF));
   3061     if (IsSpdy4()) {
   3062       CompareFrame(kDescription, *frame, kV4FrameData, arraysize(kV4FrameData));
   3063     } else {
   3064       CompareFrame(kDescription, *frame, kV3FrameData, arraysize(kV3FrameData));
   3065     }
   3066   }
   3067 }
   3068 
   3069 TEST_P(SpdyFramerTest, SerializeBlocked) {
   3070   if (spdy_version_ < SPDY4) {
   3071     return;
   3072   }
   3073 
   3074   SpdyFramer framer(spdy_version_);
   3075 
   3076   const char kDescription[] = "BLOCKED frame";
   3077   const unsigned char kFrameData[] = {
   3078     0x00, 0x08, 0x0b, 0x00,
   3079     0x00, 0x00, 0x00, 0x00,
   3080   };
   3081   SpdyBlockedIR blocked_ir(0);
   3082   scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
   3083   CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
   3084 
   3085 }
   3086 
   3087 TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
   3088   if (spdy_version_ < SPDY4) {
   3089     return;
   3090   }
   3091 
   3092   SpdyFramer framer(spdy_version_);
   3093   framer.set_enable_compression(false);
   3094 
   3095   const char kDescription[] = "PUSH_PROMISE frame";
   3096   SpdyHeaderBlock headers;
   3097   headers["bar"] = "foo";
   3098   headers["foo"] = "bar";
   3099 
   3100   const unsigned char kFrameData[] = {
   3101     0x00, 0x2C, 0x0C, 0x00,  // length = 44, type = 12, flags = 0
   3102     0x00, 0x00, 0x00, 0x2A,  // stream id = 42
   3103     0x00, 0x00, 0x00, 0x39,  // promised stream id = 57
   3104     0x00, 0x00, 0x00, 0x02,  // start of uncompressed header block
   3105     0x00, 0x00, 0x00, 0x03,
   3106     'b',  'a',  'r',  0x00,
   3107     0x00, 0x00, 0x03, 'f',
   3108     'o',  'o',  0x00, 0x00,
   3109     0x00, 0x03, 'f',  'o',
   3110     'o',  0x00, 0x00, 0x00,
   3111     0x03, 'b',  'a',  'r'    // end of uncompressed header block
   3112   };
   3113 
   3114   scoped_ptr<SpdySerializedFrame> frame(framer.CreatePushPromise(
   3115       42, 57, &headers));
   3116   CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
   3117 }
   3118 
   3119 TEST_P(SpdyFramerTest, CreatePushPromiseCompressed) {
   3120   if (spdy_version_ < SPDY4) {
   3121     return;
   3122   }
   3123 
   3124   SpdyFramer framer(spdy_version_);
   3125   framer.set_enable_compression(true);
   3126 
   3127   const char kDescription[] = "PUSH_PROMISE frame";
   3128   SpdyHeaderBlock headers;
   3129   headers["bar"] = "foo";
   3130   headers["foo"] = "bar";
   3131 
   3132   const unsigned char kFrameData[] = {
   3133     0x00, 0x39, 0x0C, 0x00,  // length = 57, type = 12, flags = 0
   3134     0x00, 0x00, 0x00, 0x2A,  // stream id = 42
   3135     0x00, 0x00, 0x00, 0x39,  // promised stream id = 57
   3136     0x38, 0xea, 0xe3, 0xc6,  // start of compressed header block
   3137     0xa7, 0xc2, 0x02, 0xe5,
   3138     0x0e, 0x50, 0xc2, 0x4b,
   3139     0x4a, 0x04, 0xe5, 0x0b,
   3140     0x66, 0x80, 0x00, 0x4a,
   3141     0xcb, 0xcf, 0x07, 0x08,
   3142     0x20, 0x10, 0x95, 0x96,
   3143     0x9f, 0x0f, 0xa2, 0x00,
   3144     0x02, 0x28, 0x29, 0xb1,
   3145     0x08, 0x20, 0x80, 0x00,
   3146     0x00, 0x00, 0x00, 0xff,
   3147     0xff                     // end of compressed header block
   3148   };
   3149 
   3150   scoped_ptr<SpdySerializedFrame> frame(framer.CreatePushPromise(
   3151       42, 57, &headers));
   3152   CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
   3153 }
   3154 
   3155 TEST_P(SpdyFramerTest, ReadCompressedSynStreamHeaderBlock) {
   3156   SpdyHeaderBlock headers;
   3157   headers["aa"] = "vv";
   3158   headers["bb"] = "ww";
   3159   SpdyFramer framer(spdy_version_);
   3160   scoped_ptr<SpdyFrame> control_frame(
   3161       framer.CreateSynStream(1,                     // stream_id
   3162                              0,                     // associated_stream_id
   3163                              1,                     // priority
   3164                              0,                     // credential_slot
   3165                              CONTROL_FLAG_NONE,
   3166                              true,                  // compress
   3167                              &headers));
   3168   EXPECT_TRUE(control_frame.get() != NULL);
   3169   TestSpdyVisitor visitor(spdy_version_);
   3170   visitor.use_compression_ = true;
   3171   visitor.SimulateInFramer(
   3172       reinterpret_cast<unsigned char*>(control_frame->data()),
   3173       control_frame->size());
   3174   EXPECT_EQ(1, visitor.syn_frame_count_);
   3175   EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
   3176 }
   3177 
   3178 TEST_P(SpdyFramerTest, ReadCompressedSynReplyHeaderBlock) {
   3179   SpdyHeaderBlock headers;
   3180   headers["alpha"] = "beta";
   3181   headers["gamma"] = "delta";
   3182   SpdyFramer framer(spdy_version_);
   3183   scoped_ptr<SpdyFrame> control_frame(
   3184       framer.CreateSynReply(1,                     // stream_id
   3185                             CONTROL_FLAG_NONE,
   3186                             true,                  // compress
   3187                             &headers));
   3188   EXPECT_TRUE(control_frame.get() != NULL);
   3189   TestSpdyVisitor visitor(spdy_version_);
   3190   visitor.use_compression_ = true;
   3191   visitor.SimulateInFramer(
   3192       reinterpret_cast<unsigned char*>(control_frame->data()),
   3193       control_frame->size());
   3194   EXPECT_EQ(1, visitor.syn_reply_frame_count_);
   3195   EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
   3196 }
   3197 
   3198 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) {
   3199   SpdyHeaderBlock headers;
   3200   headers["alpha"] = "beta";
   3201   headers["gamma"] = "delta";
   3202   SpdyFramer framer(spdy_version_);
   3203   scoped_ptr<SpdyFrame> control_frame(
   3204       framer.CreateHeaders(1,                     // stream_id
   3205                            CONTROL_FLAG_NONE,
   3206                            true,                  // compress
   3207                            &headers));
   3208   EXPECT_TRUE(control_frame.get() != NULL);
   3209   TestSpdyVisitor visitor(spdy_version_);
   3210   visitor.use_compression_ = true;
   3211   visitor.SimulateInFramer(
   3212       reinterpret_cast<unsigned char*>(control_frame->data()),
   3213       control_frame->size());
   3214   EXPECT_EQ(1, visitor.headers_frame_count_);
   3215   // control_frame_header_data_count_ depends on the random sequence
   3216   // produced by rand(), so adding, removing or running single tests
   3217   // alters this value.  The best we can do is assert that it happens
   3218   // at least twice.
   3219   EXPECT_LE(2, visitor.control_frame_header_data_count_);
   3220   EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
   3221   EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
   3222   EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
   3223 }
   3224 
   3225 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) {
   3226   SpdyHeaderBlock headers;
   3227   headers["alpha"] = "beta";
   3228   headers["gamma"] = "delta";
   3229   SpdyFramer framer(spdy_version_);
   3230   scoped_ptr<SpdyFrame> control_frame(
   3231       framer.CreateHeaders(1,                     // stream_id
   3232                            CONTROL_FLAG_FIN,
   3233                            true,                  // compress
   3234                            &headers));
   3235   EXPECT_TRUE(control_frame.get() != NULL);
   3236   TestSpdyVisitor visitor(spdy_version_);
   3237   visitor.use_compression_ = true;
   3238   visitor.SimulateInFramer(
   3239       reinterpret_cast<unsigned char*>(control_frame->data()),
   3240       control_frame->size());
   3241   EXPECT_EQ(1, visitor.headers_frame_count_);
   3242   // control_frame_header_data_count_ depends on the random sequence
   3243   // produced by rand(), so adding, removing or running single tests
   3244   // alters this value.  The best we can do is assert that it happens
   3245   // at least twice.
   3246   EXPECT_LE(2, visitor.control_frame_header_data_count_);
   3247   EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
   3248   EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
   3249   EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
   3250 }
   3251 
   3252 TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) {
   3253   // First find the size of the header value in order to just reach the control
   3254   // frame max size.
   3255   SpdyFramer framer(spdy_version_);
   3256   framer.set_enable_compression(false);
   3257   SpdyHeaderBlock headers;
   3258   headers["aa"] = "";
   3259   scoped_ptr<SpdyFrame> control_frame(
   3260       framer.CreateSynStream(1,                     // stream_id
   3261                              0,                     // associated_stream_id
   3262                              1,                     // priority
   3263                              0,                     // credential_slot
   3264                              CONTROL_FLAG_NONE,
   3265                              false,                 // compress
   3266                              &headers));
   3267   const size_t kBigValueSize =
   3268       framer.GetControlFrameBufferMaxSize() - control_frame->size();
   3269 
   3270   // Create a frame at exatly that size.
   3271   string big_value(kBigValueSize, 'x');
   3272   headers["aa"] = big_value.c_str();
   3273   control_frame.reset(
   3274       framer.CreateSynStream(1,                     // stream_id
   3275                              0,                     // associated_stream_id
   3276                              1,                     // priority
   3277                              0,                     // credential_slot
   3278                              CONTROL_FLAG_NONE,
   3279                              false,                 // compress
   3280                              &headers));
   3281   EXPECT_TRUE(control_frame.get() != NULL);
   3282   EXPECT_EQ(framer.GetControlFrameBufferMaxSize(), control_frame->size());
   3283 
   3284   TestSpdyVisitor visitor(spdy_version_);
   3285   visitor.SimulateInFramer(
   3286       reinterpret_cast<unsigned char*>(control_frame->data()),
   3287       control_frame->size());
   3288   EXPECT_TRUE(visitor.header_buffer_valid_);
   3289   EXPECT_EQ(0, visitor.error_count_);
   3290   EXPECT_EQ(1, visitor.syn_frame_count_);
   3291   EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_);
   3292   EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
   3293   EXPECT_LT(kBigValueSize, visitor.header_buffer_length_);
   3294 }
   3295 
   3296 TEST_P(SpdyFramerTest, ControlFrameTooLarge) {
   3297   // First find the size of the header value in order to just reach the control
   3298   // frame max size.
   3299   SpdyFramer framer(spdy_version_);
   3300   framer.set_enable_compression(false);
   3301   SpdyHeaderBlock headers;
   3302   headers["aa"] = "";
   3303   scoped_ptr<SpdyFrame> control_frame(
   3304       framer.CreateSynStream(1,                     // stream_id
   3305                              0,                     // associated_stream_id
   3306                              1,                     // priority
   3307                              0,                     // credential_slot
   3308                              CONTROL_FLAG_NONE,
   3309                              false,                 // compress
   3310                              &headers));
   3311   const size_t kBigValueSize =
   3312       framer.GetControlFrameBufferMaxSize() - control_frame->size() + 1;
   3313 
   3314   // Create a frame at exatly that size.
   3315   string big_value(kBigValueSize, 'x');
   3316   headers["aa"] = big_value.c_str();
   3317   control_frame.reset(
   3318       framer.CreateSynStream(1,                     // stream_id
   3319                              0,                     // associated_stream_id
   3320                              1,                     // priority
   3321                              0,                     // credential_slot
   3322                              CONTROL_FLAG_NONE,
   3323                              false,                 // compress
   3324                              &headers));
   3325   EXPECT_TRUE(control_frame.get() != NULL);
   3326   EXPECT_EQ(framer.GetControlFrameBufferMaxSize() + 1,
   3327             control_frame->size());
   3328 
   3329   TestSpdyVisitor visitor(spdy_version_);
   3330   visitor.SimulateInFramer(
   3331       reinterpret_cast<unsigned char*>(control_frame->data()),
   3332       control_frame->size());
   3333   EXPECT_FALSE(visitor.header_buffer_valid_);
   3334   EXPECT_EQ(1, visitor.error_count_);
   3335   EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
   3336             visitor.framer_.error_code())
   3337       << SpdyFramer::ErrorCodeToString(framer.error_code());
   3338   EXPECT_EQ(0, visitor.syn_frame_count_);
   3339   EXPECT_EQ(0u, visitor.header_buffer_length_);
   3340 }
   3341 
   3342 // Check that the framer stops delivering header data chunks once the visitor
   3343 // declares it doesn't want any more. This is important to guard against
   3344 // "zip bomb" types of attacks.
   3345 TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) {
   3346   SpdyHeaderBlock headers;
   3347   const size_t kHeaderBufferChunks = 4;
   3348   const size_t kHeaderBufferSize =
   3349       TestSpdyVisitor::header_data_chunk_max_size() * kHeaderBufferChunks;
   3350   const size_t kBigValueSize = kHeaderBufferSize * 2;
   3351   string big_value(kBigValueSize, 'x');
   3352   headers["aa"] = big_value.c_str();
   3353   SpdyFramer framer(spdy_version_);
   3354   scoped_ptr<SpdyFrame> control_frame(
   3355       framer.CreateSynStream(1,                     // stream_id
   3356                              0,                     // associated_stream_id
   3357                              1,                     // priority
   3358                              0,                     // credential_slot
   3359                              CONTROL_FLAG_FIN,      // half close
   3360                              true,                  // compress
   3361                              &headers));
   3362   EXPECT_TRUE(control_frame.get() != NULL);
   3363   TestSpdyVisitor visitor(spdy_version_);
   3364   visitor.set_header_buffer_size(kHeaderBufferSize);
   3365   visitor.use_compression_ = true;
   3366   visitor.SimulateInFramer(
   3367       reinterpret_cast<unsigned char*>(control_frame->data()),
   3368       control_frame->size());
   3369   EXPECT_FALSE(visitor.header_buffer_valid_);
   3370   EXPECT_EQ(1, visitor.error_count_);
   3371   EXPECT_EQ(SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
   3372             visitor.framer_.error_code())
   3373       << SpdyFramer::ErrorCodeToString(framer.error_code());
   3374 
   3375   // The framer should have stoped delivering chunks after the visitor
   3376   // signaled "stop" by returning false from OnControlFrameHeaderData().
   3377   //
   3378   // control_frame_header_data_count_ depends on the random sequence
   3379   // produced by rand(), so adding, removing or running single tests
   3380   // alters this value.  The best we can do is assert that it happens
   3381   // at least kHeaderBufferChunks + 1.
   3382   EXPECT_LE(kHeaderBufferChunks + 1,
   3383             static_cast<unsigned>(visitor.control_frame_header_data_count_));
   3384   EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
   3385 
   3386   // The framer should not have sent half-close to the visitor.
   3387   EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
   3388 }
   3389 
   3390 TEST_P(SpdyFramerTest, DecompressCorruptHeaderBlock) {
   3391   SpdyHeaderBlock headers;
   3392   headers["aa"] = "alpha beta gamma delta";
   3393   SpdyFramer framer(spdy_version_);
   3394   framer.set_enable_compression(false);
   3395   // Construct a SYN_STREAM control frame without compressing the header block,
   3396   // and have the framer try to decompress it. This will cause the framer to
   3397   // deal with a decompression error.
   3398   scoped_ptr<SpdyFrame> control_frame(
   3399       framer.CreateSynStream(1,                     // stream_id
   3400                              0,                     // associated_stream_id
   3401                              1,                     // priority
   3402                              0,                     // credential_slot
   3403                              CONTROL_FLAG_NONE,
   3404                              false,                 // compress
   3405                              &headers));
   3406   TestSpdyVisitor visitor(spdy_version_);
   3407   visitor.use_compression_ = true;
   3408   visitor.SimulateInFramer(
   3409       reinterpret_cast<unsigned char*>(control_frame->data()),
   3410       control_frame->size());
   3411   EXPECT_EQ(1, visitor.error_count_);
   3412   EXPECT_EQ(SpdyFramer::SPDY_DECOMPRESS_FAILURE, visitor.framer_.error_code())
   3413       << SpdyFramer::ErrorCodeToString(framer.error_code());
   3414   EXPECT_EQ(0u, visitor.header_buffer_length_);
   3415 }
   3416 
   3417 TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) {
   3418   // Create a GoAway frame that has a few extra bytes at the end.
   3419   // We create enough overhead to overflow the framer's control frame buffer.
   3420   ASSERT_GE(250u, SpdyFramer::kControlFrameBufferSize);
   3421   const unsigned char length =  1 + SpdyFramer::kControlFrameBufferSize;
   3422   const unsigned char kV3FrameData[] = {  // Also applies for V2.
   3423     0x80, spdy_version_ch_, 0x00, 0x07,
   3424     0x00, 0x00, 0x00, length,
   3425     0x00, 0x00, 0x00, 0x00,
   3426     0x00, 0x00, 0x00, 0x00,
   3427   };
   3428   const unsigned char kV4FrameData[] = {
   3429     0x00, static_cast<uint8>(length + 4), 0x07, 0x00,
   3430     0x00, 0x00, 0x00, 0x00,
   3431     0x00, 0x00, 0x00, 0x00,
   3432   };
   3433   SpdyFramer framer(spdy_version_);
   3434   const size_t pad_length =
   3435       length + framer.GetControlFrameHeaderSize() -
   3436       (IsSpdy4() ? sizeof(kV4FrameData) : sizeof(kV3FrameData));
   3437   string pad('A', pad_length);
   3438   TestSpdyVisitor visitor(spdy_version_);
   3439 
   3440   if (IsSpdy4()) {
   3441     visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
   3442   } else {
   3443     visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
   3444   }
   3445   visitor.SimulateInFramer(
   3446       reinterpret_cast<const unsigned char*>(pad.c_str()),
   3447       pad.length());
   3448 
   3449   EXPECT_EQ(1, visitor.error_count_);  // This generated an error.
   3450   EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
   3451             visitor.framer_.error_code())
   3452       << SpdyFramer::ErrorCodeToString(framer.error_code());
   3453   EXPECT_EQ(0, visitor.goaway_count_);  // Frame not parsed.
   3454 }
   3455 
   3456 TEST_P(SpdyFramerTest, ReadZeroLenSettingsFrame) {
   3457   SpdyFramer framer(spdy_version_);
   3458   SettingsMap settings;
   3459   scoped_ptr<SpdyFrame> control_frame(framer.CreateSettings(settings));
   3460   SetFrameLength(control_frame.get(), 0, spdy_version_);
   3461   TestSpdyVisitor visitor(spdy_version_);
   3462   visitor.use_compression_ = false;
   3463   visitor.SimulateInFramer(
   3464       reinterpret_cast<unsigned char*>(control_frame->data()),
   3465       framer.GetControlFrameHeaderSize());
   3466   // Should generate an error, since zero-len settings frames are unsupported.
   3467   EXPECT_EQ(1, visitor.error_count_);
   3468 }
   3469 
   3470 // Tests handling of SETTINGS frames with invalid length.
   3471 TEST_P(SpdyFramerTest, ReadBogusLenSettingsFrame) {
   3472   SpdyFramer framer(spdy_version_);
   3473   SettingsMap settings;
   3474   // Add a setting to pad the frame so that we don't get a buffer overflow when
   3475   // calling SimulateInFramer() below.
   3476   settings[SETTINGS_UPLOAD_BANDWIDTH] =
   3477       SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, 0x00000002);
   3478   scoped_ptr<SpdyFrame> control_frame(framer.CreateSettings(settings));
   3479   const size_t kNewLength = 5;
   3480   SetFrameLength(control_frame.get(), kNewLength, spdy_version_);
   3481   TestSpdyVisitor visitor(spdy_version_);
   3482   visitor.use_compression_ = false;
   3483   visitor.SimulateInFramer(
   3484       reinterpret_cast<unsigned char*>(control_frame->data()),
   3485       framer.GetControlFrameHeaderSize() + kNewLength);
   3486   // Should generate an error, since zero-len settings frames are unsupported.
   3487   EXPECT_EQ(1, visitor.error_count_);
   3488 }
   3489 
   3490 // Tests handling of SETTINGS frames larger than the frame buffer size.
   3491 TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) {
   3492   SpdyFramer framer(spdy_version_);
   3493   SettingsMap settings;
   3494   SpdySettingsFlags flags = SETTINGS_FLAG_PLEASE_PERSIST;
   3495   settings[SETTINGS_UPLOAD_BANDWIDTH] =
   3496       SettingsFlagsAndValue(flags, 0x00000002);
   3497   settings[SETTINGS_DOWNLOAD_BANDWIDTH] =
   3498       SettingsFlagsAndValue(flags, 0x00000003);
   3499   settings[SETTINGS_ROUND_TRIP_TIME] = SettingsFlagsAndValue(flags, 0x00000004);
   3500   scoped_ptr<SpdyFrame> control_frame(framer.CreateSettings(settings));
   3501   EXPECT_LT(SpdyFramer::kControlFrameBufferSize,
   3502             control_frame->size());
   3503   TestSpdyVisitor visitor(spdy_version_);
   3504   visitor.use_compression_ = false;
   3505 
   3506   // Read all at once.
   3507   visitor.SimulateInFramer(
   3508       reinterpret_cast<unsigned char*>(control_frame->data()),
   3509       control_frame->size());
   3510   EXPECT_EQ(0, visitor.error_count_);
   3511   EXPECT_EQ(settings.size(), static_cast<unsigned>(visitor.setting_count_));
   3512 
   3513   // Read data in small chunks.
   3514   size_t framed_data = 0;
   3515   size_t unframed_data = control_frame->size();
   3516   size_t kReadChunkSize = 5;  // Read five bytes at a time.
   3517   while (unframed_data > 0) {
   3518     size_t to_read = min(kReadChunkSize, unframed_data);
   3519     visitor.SimulateInFramer(
   3520         reinterpret_cast<unsigned char*>(control_frame->data() + framed_data),
   3521         to_read);
   3522     unframed_data -= to_read;
   3523     framed_data += to_read;
   3524   }
   3525   EXPECT_EQ(0, visitor.error_count_);
   3526   EXPECT_EQ(settings.size() * 2, static_cast<unsigned>(visitor.setting_count_));
   3527 }
   3528 
   3529 // Tests handling of SETTINGS frame with duplicate entries.
   3530 TEST_P(SpdyFramerTest, ReadDuplicateSettings) {
   3531   SpdyFramer framer(spdy_version_);
   3532 
   3533   const unsigned char kV2FrameData[] = {
   3534     0x80, spdy_version_ch_, 0x00, 0x04,
   3535     0x00, 0x00, 0x00, 0x1C,
   3536     0x00, 0x00, 0x00, 0x03,
   3537     0x01, 0x00, 0x00, 0x00,  // 1st Setting
   3538     0x00, 0x00, 0x00, 0x02,
   3539     0x01, 0x00, 0x00, 0x00,  // 2nd (duplicate) Setting
   3540     0x00, 0x00, 0x00, 0x03,
   3541     0x03, 0x00, 0x00, 0x00,  // 3rd (unprocessed) Setting
   3542     0x00, 0x00, 0x00, 0x03,
   3543   };
   3544   const unsigned char kV3FrameData[] = {
   3545     0x80, spdy_version_ch_, 0x00, 0x04,
   3546     0x00, 0x00, 0x00, 0x1C,
   3547     0x00, 0x00, 0x00, 0x03,
   3548     0x00, 0x00, 0x00, 0x01,  // 1st Setting
   3549     0x00, 0x00, 0x00, 0x02,
   3550     0x00, 0x00, 0x00, 0x01,  // 2nd (duplicate) Setting
   3551     0x00, 0x00, 0x00, 0x03,
   3552     0x00, 0x00, 0x00, 0x03,  // 3rd (unprocessed) Setting
   3553     0x00, 0x00, 0x00, 0x03,
   3554   };
   3555   const unsigned char kV4FrameData[] = {
   3556     0x00, 0x24, 0x04, 0x00,
   3557     0x00, 0x00, 0x00, 0x00,
   3558     0x00, 0x00, 0x00, 0x03,
   3559     0x00, 0x00, 0x00, 0x01,  // 1st Setting
   3560     0x00, 0x00, 0x00, 0x02,
   3561     0x00, 0x00, 0x00, 0x01,  // 2nd (duplicate) Setting
   3562     0x00, 0x00, 0x00, 0x03,
   3563     0x00, 0x00, 0x00, 0x03,  // 3rd (unprocessed) Setting
   3564     0x00, 0x00, 0x00, 0x03,
   3565   };
   3566 
   3567   TestSpdyVisitor visitor(spdy_version_);
   3568   visitor.use_compression_ = false;
   3569   if (IsSpdy2()) {
   3570     visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
   3571   } else if (IsSpdy3()) {
   3572     visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
   3573   } else {
   3574     visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
   3575   }
   3576   EXPECT_EQ(1, visitor.error_count_);
   3577   EXPECT_EQ(1, visitor.setting_count_);
   3578 }
   3579 
   3580 // Tests handling of SETTINGS frame with entries out of order.
   3581 TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) {
   3582   SpdyFramer framer(spdy_version_);
   3583 
   3584   const unsigned char kV2FrameData[] = {
   3585     0x80, spdy_version_ch_, 0x00, 0x04,
   3586     0x00, 0x00, 0x00, 0x1C,
   3587     0x00, 0x00, 0x00, 0x03,
   3588     0x02, 0x00, 0x00, 0x00,  // 1st Setting
   3589     0x00, 0x00, 0x00, 0x02,
   3590     0x01, 0x00, 0x00, 0x00,  // 2nd (out of order) Setting
   3591     0x00, 0x00, 0x00, 0x03,
   3592     0x03, 0x00, 0x00, 0x00,  // 3rd (unprocessed) Setting
   3593     0x00, 0x00, 0x00, 0x03,
   3594   };
   3595   const unsigned char kV3FrameData[] = {
   3596     0x80, spdy_version_ch_, 0x00, 0x04,
   3597     0x00, 0x00, 0x00, 0x1C,
   3598     0x00, 0x00, 0x00, 0x03,
   3599     0x00, 0x00, 0x00, 0x02,  // 1st Setting
   3600     0x00, 0x00, 0x00, 0x02,
   3601     0x00, 0x00, 0x00, 0x01,  // 2nd (out of order) Setting
   3602     0x00, 0x00, 0x00, 0x03,
   3603     0x00, 0x00, 0x01, 0x03,  // 3rd (unprocessed) Setting
   3604     0x00, 0x00, 0x00, 0x03,
   3605   };
   3606   const unsigned char kV4FrameData[] = {
   3607     0x00, 0x24, 0x04, 0x00,
   3608     0x00, 0x00, 0x00, 0x00,
   3609     0x00, 0x00, 0x00, 0x03,
   3610     0x00, 0x00, 0x00, 0x02,  // 1st Setting
   3611     0x00, 0x00, 0x00, 0x02,
   3612     0x00, 0x00, 0x00, 0x01,  // 2nd (out of order) Setting
   3613     0x00, 0x00, 0x00, 0x03,
   3614     0x00, 0x00, 0x01, 0x03,  // 3rd (unprocessed) Setting
   3615     0x00, 0x00, 0x00, 0x03,
   3616   };
   3617 
   3618   TestSpdyVisitor visitor(spdy_version_);
   3619   visitor.use_compression_ = false;
   3620   if (IsSpdy2()) {
   3621     visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData));
   3622   } else if (IsSpdy3()) {
   3623     visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData));
   3624   } else {
   3625     visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData));
   3626   }
   3627   EXPECT_EQ(1, visitor.error_count_);
   3628   EXPECT_EQ(1, visitor.setting_count_);
   3629 }
   3630 
   3631 TEST_P(SpdyFramerTest, ReadWindowUpdate) {
   3632   SpdyFramer framer(spdy_version_);
   3633   scoped_ptr<SpdyFrame> control_frame(
   3634       framer.CreateWindowUpdate(1, 2));
   3635   TestSpdyVisitor visitor(spdy_version_);
   3636   visitor.SimulateInFramer(
   3637       reinterpret_cast<unsigned char*>(control_frame->data()),
   3638       control_frame->size());
   3639   EXPECT_EQ(1u, visitor.last_window_update_stream_);
   3640   EXPECT_EQ(2u, visitor.last_window_update_delta_);
   3641 }
   3642 
   3643 TEST_P(SpdyFramerTest, ReadCredentialFrame) {
   3644   SpdyCredential credential;
   3645   credential.slot = 3;
   3646   credential.proof = "proof";
   3647   credential.certs.push_back("a cert");
   3648   credential.certs.push_back("another cert");
   3649   credential.certs.push_back("final cert");
   3650   SpdyFramer framer(spdy_version_);
   3651   scoped_ptr<SpdyFrame> control_frame(
   3652       framer.CreateCredentialFrame(credential));
   3653   EXPECT_TRUE(control_frame.get() != NULL);
   3654   TestSpdyVisitor visitor(spdy_version_);
   3655   visitor.use_compression_ = false;
   3656   visitor.SimulateInFramer(
   3657       reinterpret_cast<unsigned char*>(control_frame->data()),
   3658       control_frame->size());
   3659   EXPECT_EQ(0, visitor.error_count_);
   3660   EXPECT_EQ(control_frame->size() - framer.GetControlFrameHeaderSize(),
   3661             visitor.credential_buffer_length_);
   3662   EXPECT_EQ(credential.slot, visitor.credential_.slot);
   3663   EXPECT_EQ(credential.proof, visitor.credential_.proof);
   3664   EXPECT_EQ(credential.certs.size(), visitor.credential_.certs.size());
   3665   for (size_t i = 0; i < credential.certs.size(); i++) {
   3666     EXPECT_EQ(credential.certs[i], visitor.credential_.certs[i]);
   3667   }
   3668 }
   3669 
   3670 TEST_P(SpdyFramerTest, ReadCredentialFrameOneByteAtATime) {
   3671   SpdyCredential credential;
   3672   credential.slot = 3;
   3673   credential.proof = "proof";
   3674   credential.certs.push_back("a cert");
   3675   credential.certs.push_back("another cert");
   3676   credential.certs.push_back("final cert");
   3677   SpdyFramer framer(spdy_version_);
   3678   scoped_ptr<SpdyFrame> control_frame(
   3679       framer.CreateCredentialFrame(credential));
   3680   EXPECT_TRUE(control_frame.get() != NULL);
   3681   TestSpdyVisitor visitor(spdy_version_);
   3682   visitor.use_compression_ = false;
   3683   // Read one byte at a time to make sure we handle edge cases
   3684   unsigned char* data =
   3685       reinterpret_cast<unsigned char*>(control_frame->data());
   3686   for (size_t idx = 0; idx < control_frame->size(); ++idx) {
   3687     visitor.SimulateInFramer(data + idx, 1);
   3688     ASSERT_EQ(0, visitor.error_count_);
   3689   }
   3690   EXPECT_EQ(0, visitor.error_count_);
   3691   EXPECT_EQ(control_frame->size() - framer.GetControlFrameHeaderSize(),
   3692             visitor.credential_buffer_length_);
   3693   EXPECT_EQ(credential.slot, visitor.credential_.slot);
   3694   EXPECT_EQ(credential.proof, visitor.credential_.proof);
   3695   EXPECT_EQ(credential.certs.size(), visitor.credential_.certs.size());
   3696   for (size_t i = 0; i < credential.certs.size(); i++) {
   3697     EXPECT_EQ(credential.certs[i], visitor.credential_.certs[i]);
   3698   }
   3699 }
   3700 
   3701 TEST_P(SpdyFramerTest, ReadCredentialFrameWithNoPayload) {
   3702   SpdyCredential credential;
   3703   credential.slot = 3;
   3704   credential.proof = "proof";
   3705   credential.certs.push_back("a cert");
   3706   credential.certs.push_back("another cert");
   3707   credential.certs.push_back("final cert");
   3708   SpdyFramer framer(spdy_version_);
   3709   scoped_ptr<SpdyFrame> control_frame(
   3710       framer.CreateCredentialFrame(credential));
   3711   EXPECT_TRUE(control_frame.get() != NULL);
   3712   TestSpdyVisitor visitor(spdy_version_);
   3713   visitor.use_compression_ = false;
   3714   SetFrameLength(control_frame.get(), 0, spdy_version_);
   3715   unsigned char* data =
   3716       reinterpret_cast<unsigned char*>(control_frame->data());
   3717   visitor.SimulateInFramer(data, framer.GetControlFrameHeaderSize());
   3718   EXPECT_EQ(1, visitor.error_count_);
   3719 }
   3720 
   3721 TEST_P(SpdyFramerTest, ReadCredentialFrameWithCorruptProof) {
   3722   SpdyCredential credential;
   3723   credential.slot = 3;
   3724   credential.proof = "proof";
   3725   credential.certs.push_back("a cert");
   3726   credential.certs.push_back("another cert");
   3727   credential.certs.push_back("final cert");
   3728   SpdyFramer framer(spdy_version_);
   3729   scoped_ptr<SpdyFrame> control_frame(
   3730       framer.CreateCredentialFrame(credential));
   3731   EXPECT_TRUE(control_frame.get() != NULL);
   3732   TestSpdyVisitor visitor(spdy_version_);
   3733   visitor.use_compression_ = false;
   3734   unsigned char* data =
   3735       reinterpret_cast<unsigned char*>(control_frame->data());
   3736   size_t offset = framer.GetControlFrameHeaderSize() + 4;
   3737   data[offset] = 0xFF;  // Proof length is past the end of the frame
   3738   visitor.SimulateInFramer(
   3739       data, control_frame->size());
   3740   EXPECT_EQ(1, visitor.error_count_);
   3741 }
   3742 
   3743 TEST_P(SpdyFramerTest, ReadCredentialFrameWithCorruptCertificate) {
   3744   SpdyCredential credential;
   3745   credential.slot = 3;
   3746   credential.proof = "proof";
   3747   credential.certs.push_back("a cert");
   3748   credential.certs.push_back("another cert");
   3749   credential.certs.push_back("final cert");
   3750   SpdyFramer framer(spdy_version_);
   3751   scoped_ptr<SpdyFrame> control_frame(
   3752       framer.CreateCredentialFrame(credential));
   3753   EXPECT_TRUE(control_frame.get() != NULL);
   3754   TestSpdyVisitor visitor(spdy_version_);
   3755   visitor.use_compression_ = false;
   3756   unsigned char* data =
   3757       reinterpret_cast<unsigned char*>(control_frame->data());
   3758   size_t offset = framer.GetCredentialMinimumSize() + 1;
   3759   data[offset] = 0xFF;  // Proof length is past the end of the frame
   3760   visitor.SimulateInFramer(
   3761       data, control_frame->size());
   3762   EXPECT_EQ(1, visitor.error_count_);
   3763 }
   3764 
   3765 // Regression test for parsing issue found in b/8278897.
   3766 TEST_P(SpdyFramerTest, ReadCredentialFrameFollowedByAnotherFrame) {
   3767   SpdyCredential credential;
   3768   credential.slot = 3;
   3769   credential.proof = "proof";
   3770   credential.certs.push_back("a cert");
   3771   credential.certs.push_back("another cert");
   3772   credential.certs.push_back("final cert");
   3773   SpdyFramer framer(spdy_version_);
   3774   scoped_ptr<SpdyFrame> credential_frame(
   3775       framer.CreateCredentialFrame(credential));
   3776   EXPECT_TRUE(credential_frame.get() != NULL);
   3777   TestSpdyVisitor visitor(spdy_version_);
   3778   visitor.use_compression_ = false;
   3779   string multiple_frame_data(credential_frame->data(),
   3780                              credential_frame->size());
   3781   scoped_ptr<SpdyFrame> goaway_frame(framer.CreateGoAway(0, GOAWAY_OK));
   3782   multiple_frame_data.append(string(goaway_frame->data(),
   3783                                     goaway_frame->size()));
   3784   visitor.SimulateInFramer(
   3785       reinterpret_cast<unsigned const char*>(multiple_frame_data.data()),
   3786       multiple_frame_data.length());
   3787   EXPECT_EQ(0, visitor.error_count_);
   3788   EXPECT_EQ(credential_frame->size() - framer.GetControlFrameHeaderSize(),
   3789             visitor.credential_buffer_length_);
   3790   EXPECT_EQ(credential.slot, visitor.credential_.slot);
   3791   EXPECT_EQ(credential.proof, visitor.credential_.proof);
   3792   EXPECT_EQ(credential.certs.size(), visitor.credential_.certs.size());
   3793   for (size_t i = 0; i < credential.certs.size(); i++) {
   3794     EXPECT_EQ(credential.certs[i], visitor.credential_.certs[i]);
   3795   }
   3796 }
   3797 
   3798 TEST_P(SpdyFramerTest, ReadCompressedPushPromise) {
   3799   if (spdy_version_ < 4) {
   3800     return;
   3801   }
   3802 
   3803   SpdyHeaderBlock headers;
   3804   headers["foo"] = "bar";
   3805   headers["bar"] = "foofoo";
   3806   SpdyFramer framer(spdy_version_);
   3807   scoped_ptr<SpdyFrame> frame(framer.CreatePushPromise(42, 57, &headers));
   3808   EXPECT_TRUE(frame.get() != NULL);
   3809   TestSpdyVisitor visitor(spdy_version_);
   3810   visitor.use_compression_ = true;
   3811   visitor.SimulateInFramer(
   3812       reinterpret_cast<unsigned char*>(frame->data()),
   3813       frame->size());
   3814   EXPECT_EQ(42u, visitor.last_push_promise_stream_);
   3815   EXPECT_EQ(57u, visitor.last_push_promise_promised_stream_);
   3816   EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
   3817 }
   3818 
   3819 TEST_P(SpdyFramerTest, ReadGarbage) {
   3820   SpdyFramer framer(spdy_version_);
   3821   unsigned char garbage_frame[256];
   3822   memset(garbage_frame, ~0, sizeof(garbage_frame));
   3823   TestSpdyVisitor visitor(spdy_version_);
   3824   visitor.use_compression_ = false;
   3825   visitor.SimulateInFramer(garbage_frame, sizeof(garbage_frame));
   3826   EXPECT_EQ(1, visitor.error_count_);
   3827 }
   3828 
   3829 TEST_P(SpdyFramerTest, ReadGarbageWithValidVersion) {
   3830   if (IsSpdy4()) {
   3831     // Not valid for SPDY 4 since there is no version field.
   3832     return;
   3833   }
   3834   SpdyFramer framer(spdy_version_);
   3835   const unsigned char kFrameData[] = {
   3836     0x80, spdy_version_ch_, 0xff, 0xff,
   3837     0xff, 0xff, 0xff, 0xff,
   3838   };
   3839   TestSpdyVisitor visitor(spdy_version_);
   3840   visitor.use_compression_ = false;
   3841   visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
   3842   EXPECT_EQ(1, visitor.error_count_);
   3843 }
   3844 
   3845 TEST_P(SpdyFramerTest, SizesTest) {
   3846   SpdyFramer framer(spdy_version_);
   3847   EXPECT_EQ(8u, framer.GetDataFrameMinimumSize());
   3848   if (IsSpdy4()) {
   3849     EXPECT_EQ(8u, framer.GetSynReplyMinimumSize());
   3850     EXPECT_EQ(12u, framer.GetRstStreamSize());
   3851     EXPECT_EQ(12u, framer.GetSettingsMinimumSize());
   3852     EXPECT_EQ(12u, framer.GetPingSize());
   3853     EXPECT_EQ(16u, framer.GetGoAwaySize());
   3854     EXPECT_EQ(8u, framer.GetHeadersMinimumSize());
   3855     EXPECT_EQ(12u, framer.GetWindowUpdateSize());
   3856     EXPECT_EQ(10u, framer.GetCredentialMinimumSize());
   3857     EXPECT_EQ(8u, framer.GetBlockedSize());
   3858     EXPECT_EQ(12u, framer.GetPushPromiseMinimumSize());
   3859     EXPECT_EQ(8u, framer.GetFrameMinimumSize());
   3860     EXPECT_EQ(65535u, framer.GetFrameMaximumSize());
   3861     EXPECT_EQ(65527u, framer.GetDataFrameMaximumPayload());
   3862   } else {
   3863     EXPECT_EQ(8u, framer.GetControlFrameHeaderSize());
   3864     EXPECT_EQ(18u, framer.GetSynStreamMinimumSize());
   3865     EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetSynReplyMinimumSize());
   3866     EXPECT_EQ(16u, framer.GetRstStreamSize());
   3867     EXPECT_EQ(12u, framer.GetSettingsMinimumSize());
   3868     EXPECT_EQ(12u, framer.GetPingSize());
   3869     EXPECT_EQ(IsSpdy2() ? 12u : 16u, framer.GetGoAwaySize());
   3870     EXPECT_EQ(IsSpdy2() ? 14u : 12u, framer.GetHeadersMinimumSize());
   3871     EXPECT_EQ(16u, framer.GetWindowUpdateSize());
   3872     EXPECT_EQ(10u, framer.GetCredentialMinimumSize());
   3873     EXPECT_EQ(8u, framer.GetFrameMinimumSize());
   3874     EXPECT_EQ(16777215u, framer.GetFrameMaximumSize());
   3875     EXPECT_EQ(16777207u, framer.GetDataFrameMaximumPayload());
   3876   }
   3877 }
   3878 
   3879 TEST_P(SpdyFramerTest, StateToStringTest) {
   3880   EXPECT_STREQ("ERROR",
   3881                SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR));
   3882   EXPECT_STREQ("AUTO_RESET",
   3883                SpdyFramer::StateToString(SpdyFramer::SPDY_AUTO_RESET));
   3884   EXPECT_STREQ("RESET",
   3885                SpdyFramer::StateToString(SpdyFramer::SPDY_RESET));
   3886   EXPECT_STREQ("READING_COMMON_HEADER",
   3887                SpdyFramer::StateToString(
   3888                    SpdyFramer::SPDY_READING_COMMON_HEADER));
   3889   EXPECT_STREQ("CONTROL_FRAME_PAYLOAD",
   3890                SpdyFramer::StateToString(
   3891                    SpdyFramer::SPDY_CONTROL_FRAME_PAYLOAD));
   3892   EXPECT_STREQ("IGNORE_REMAINING_PAYLOAD",
   3893                SpdyFramer::StateToString(
   3894                    SpdyFramer::SPDY_IGNORE_REMAINING_PAYLOAD));
   3895   EXPECT_STREQ("FORWARD_STREAM_FRAME",
   3896                SpdyFramer::StateToString(
   3897                    SpdyFramer::SPDY_FORWARD_STREAM_FRAME));
   3898   EXPECT_STREQ("SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK",
   3899                SpdyFramer::StateToString(
   3900                    SpdyFramer::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK));
   3901   EXPECT_STREQ("SPDY_CONTROL_FRAME_HEADER_BLOCK",
   3902                SpdyFramer::StateToString(
   3903                    SpdyFramer::SPDY_CONTROL_FRAME_HEADER_BLOCK));
   3904   EXPECT_STREQ("SPDY_CREDENTIAL_FRAME_PAYLOAD",
   3905                SpdyFramer::StateToString(
   3906                    SpdyFramer::SPDY_CREDENTIAL_FRAME_PAYLOAD));
   3907   EXPECT_STREQ("SPDY_SETTINGS_FRAME_PAYLOAD",
   3908                SpdyFramer::StateToString(
   3909                    SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD));
   3910   EXPECT_STREQ("UNKNOWN_STATE",
   3911                SpdyFramer::StateToString(
   3912                    SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD + 1));
   3913 }
   3914 
   3915 TEST_P(SpdyFramerTest, ErrorCodeToStringTest) {
   3916   EXPECT_STREQ("NO_ERROR",
   3917                SpdyFramer::ErrorCodeToString(SpdyFramer::SPDY_NO_ERROR));
   3918   EXPECT_STREQ("INVALID_CONTROL_FRAME",
   3919                SpdyFramer::ErrorCodeToString(
   3920                    SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
   3921   EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
   3922                SpdyFramer::ErrorCodeToString(
   3923                    SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
   3924   EXPECT_STREQ("ZLIB_INIT_FAILURE",
   3925                SpdyFramer::ErrorCodeToString(
   3926                    SpdyFramer::SPDY_ZLIB_INIT_FAILURE));
   3927   EXPECT_STREQ("UNSUPPORTED_VERSION",
   3928                SpdyFramer::ErrorCodeToString(
   3929                    SpdyFramer::SPDY_UNSUPPORTED_VERSION));
   3930   EXPECT_STREQ("DECOMPRESS_FAILURE",
   3931                SpdyFramer::ErrorCodeToString(
   3932                    SpdyFramer::SPDY_DECOMPRESS_FAILURE));
   3933   EXPECT_STREQ("COMPRESS_FAILURE",
   3934                SpdyFramer::ErrorCodeToString(
   3935                    SpdyFramer::SPDY_COMPRESS_FAILURE));
   3936   EXPECT_STREQ("SPDY_INVALID_DATA_FRAME_FLAGS",
   3937                SpdyFramer::ErrorCodeToString(
   3938                    SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
   3939   EXPECT_STREQ("SPDY_INVALID_CONTROL_FRAME_FLAGS",
   3940                SpdyFramer::ErrorCodeToString(
   3941                    SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS));
   3942   EXPECT_STREQ("UNKNOWN_ERROR",
   3943                SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR));
   3944 }
   3945 
   3946 TEST_P(SpdyFramerTest, StatusCodeToStringTest) {
   3947   EXPECT_STREQ("INVALID",
   3948                SpdyFramer::StatusCodeToString(RST_STREAM_INVALID));
   3949   EXPECT_STREQ("PROTOCOL_ERROR",
   3950                SpdyFramer::StatusCodeToString(RST_STREAM_PROTOCOL_ERROR));
   3951   EXPECT_STREQ("INVALID_STREAM",
   3952                SpdyFramer::StatusCodeToString(RST_STREAM_INVALID_STREAM));
   3953   EXPECT_STREQ("REFUSED_STREAM",
   3954                SpdyFramer::StatusCodeToString(RST_STREAM_REFUSED_STREAM));
   3955   EXPECT_STREQ("UNSUPPORTED_VERSION",
   3956                SpdyFramer::StatusCodeToString(RST_STREAM_UNSUPPORTED_VERSION));
   3957   EXPECT_STREQ("CANCEL",
   3958                SpdyFramer::StatusCodeToString(RST_STREAM_CANCEL));
   3959   EXPECT_STREQ("INTERNAL_ERROR",
   3960                SpdyFramer::StatusCodeToString(RST_STREAM_INTERNAL_ERROR));
   3961   EXPECT_STREQ("FLOW_CONTROL_ERROR",
   3962                SpdyFramer::StatusCodeToString(RST_STREAM_FLOW_CONTROL_ERROR));
   3963   EXPECT_STREQ("UNKNOWN_STATUS",
   3964                SpdyFramer::StatusCodeToString(RST_STREAM_NUM_STATUS_CODES));
   3965 }
   3966 
   3967 TEST_P(SpdyFramerTest, FrameTypeToStringTest) {
   3968   EXPECT_STREQ("DATA",
   3969                SpdyFramer::FrameTypeToString(DATA));
   3970   EXPECT_STREQ("SYN_STREAM",
   3971                SpdyFramer::FrameTypeToString(SYN_STREAM));
   3972   EXPECT_STREQ("SYN_REPLY",
   3973                SpdyFramer::FrameTypeToString(SYN_REPLY));
   3974   EXPECT_STREQ("RST_STREAM",
   3975                SpdyFramer::FrameTypeToString(RST_STREAM));
   3976   EXPECT_STREQ("SETTINGS",
   3977                SpdyFramer::FrameTypeToString(SETTINGS));
   3978   EXPECT_STREQ("NOOP",
   3979                SpdyFramer::FrameTypeToString(NOOP));
   3980   EXPECT_STREQ("PING",
   3981                SpdyFramer::FrameTypeToString(PING));
   3982   EXPECT_STREQ("GOAWAY",
   3983                SpdyFramer::FrameTypeToString(GOAWAY));
   3984   EXPECT_STREQ("HEADERS",
   3985                SpdyFramer::FrameTypeToString(HEADERS));
   3986   EXPECT_STREQ("WINDOW_UPDATE",
   3987                SpdyFramer::FrameTypeToString(WINDOW_UPDATE));
   3988   EXPECT_STREQ("PUSH_PROMISE",
   3989                SpdyFramer::FrameTypeToString(PUSH_PROMISE));
   3990   EXPECT_STREQ("CREDENTIAL",
   3991                SpdyFramer::FrameTypeToString(CREDENTIAL));
   3992 }
   3993 
   3994 TEST_P(SpdyFramerTest, CatchProbableHttpResponse) {
   3995   if (IsSpdy4()) {
   3996     // TODO(hkhalil): catch probable HTTP response in SPDY 4?
   3997     return;
   3998   }
   3999   {
   4000     testing::StrictMock<test::MockVisitor> visitor;
   4001     SpdyFramer framer(spdy_version_);
   4002     framer.set_visitor(&visitor);
   4003 
   4004     EXPECT_CALL(visitor, OnError(_));
   4005     framer.ProcessInput("HTTP/1.1", 8);
   4006     EXPECT_TRUE(framer.probable_http_response());
   4007     EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
   4008     EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
   4009         << SpdyFramer::ErrorCodeToString(framer.error_code());
   4010   }
   4011   {
   4012     testing::StrictMock<test::MockVisitor> visitor;
   4013     SpdyFramer framer(spdy_version_);
   4014     framer.set_visitor(&visitor);
   4015 
   4016     EXPECT_CALL(visitor, OnError(_));
   4017     framer.ProcessInput("HTTP/1.0", 8);
   4018     EXPECT_TRUE(framer.probable_http_response());
   4019     EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
   4020     EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code())
   4021         << SpdyFramer::ErrorCodeToString(framer.error_code());
   4022   }
   4023 }
   4024 
   4025 TEST_P(SpdyFramerTest, DataFrameFlags) {
   4026   for (int flags = 0; flags < 256; ++flags) {
   4027     SCOPED_TRACE(testing::Message() << "Flags " << flags);
   4028 
   4029     testing::StrictMock<test::MockVisitor> visitor;
   4030     SpdyFramer framer(spdy_version_);
   4031     framer.set_visitor(&visitor);
   4032 
   4033     scoped_ptr<SpdyFrame> frame(
   4034         framer.CreateDataFrame(1, "hello", 5, DATA_FLAG_NONE));
   4035     SetFrameFlags(frame.get(), flags, spdy_version_);
   4036 
   4037     if (flags & ~DATA_FLAG_FIN) {
   4038       EXPECT_CALL(visitor, OnError(_));
   4039     } else {
   4040       EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
   4041       EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false));
   4042       if (flags & DATA_FLAG_FIN) {
   4043         EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
   4044       }
   4045     }
   4046 
   4047     framer.ProcessInput(frame->data(), frame->size());
   4048     if (flags & ~DATA_FLAG_FIN) {
   4049       EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
   4050       EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS,
   4051                 framer.error_code())
   4052           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4053     } else {
   4054       EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
   4055       EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
   4056           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4057     }
   4058   }
   4059 }
   4060 
   4061 TEST_P(SpdyFramerTest, SynStreamFrameFlags) {
   4062   for (int flags = 0; flags < 256; ++flags) {
   4063     SCOPED_TRACE(testing::Message() << "Flags " << flags);
   4064 
   4065     testing::StrictMock<test::MockVisitor> visitor;
   4066     testing::StrictMock<test::MockDebugVisitor> debug_visitor;
   4067     SpdyFramer framer(spdy_version_);
   4068     framer.set_visitor(&visitor);
   4069     framer.set_debug_visitor(&debug_visitor);
   4070 
   4071     EXPECT_CALL(debug_visitor, OnSendCompressedFrame(8, SYN_STREAM, _, _));
   4072 
   4073     SpdyHeaderBlock headers;
   4074     headers["foo"] = "bar";
   4075     scoped_ptr<SpdyFrame> frame(
   4076         framer.CreateSynStream(8, 3, 1, 0, CONTROL_FLAG_NONE, true, &headers));
   4077     SetFrameFlags(frame.get(), flags, spdy_version_);
   4078 
   4079     if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
   4080       EXPECT_CALL(visitor, OnError(_));
   4081     } else {
   4082       EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(8, SYN_STREAM, _));
   4083       EXPECT_CALL(visitor, OnSynStream(8, 3, 1, 0, flags & CONTROL_FLAG_FIN,
   4084                                        flags & CONTROL_FLAG_UNIDIRECTIONAL));
   4085       EXPECT_CALL(visitor, OnControlFrameHeaderData(8, _, _))
   4086           .WillRepeatedly(testing::Return(true));
   4087       if (flags & DATA_FLAG_FIN) {
   4088         EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
   4089       }
   4090     }
   4091 
   4092     framer.ProcessInput(frame->data(), frame->size());
   4093     if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
   4094       EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
   4095       EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
   4096                 framer.error_code())
   4097           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4098     } else {
   4099       EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
   4100       EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
   4101           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4102     }
   4103   }
   4104 }
   4105 
   4106 TEST_P(SpdyFramerTest, SynReplyFrameFlags) {
   4107   for (int flags = 0; flags < 256; ++flags) {
   4108     SCOPED_TRACE(testing::Message() << "Flags " << flags);
   4109 
   4110     testing::StrictMock<test::MockVisitor> visitor;
   4111     SpdyFramer framer(spdy_version_);
   4112     framer.set_visitor(&visitor);
   4113 
   4114     SpdyHeaderBlock headers;
   4115     headers["foo"] = "bar";
   4116     scoped_ptr<SpdyFrame> frame(
   4117         framer.CreateSynReply(37, CONTROL_FLAG_NONE, true, &headers));
   4118     SetFrameFlags(frame.get(), flags, spdy_version_);
   4119 
   4120     if (flags & ~CONTROL_FLAG_FIN) {
   4121       EXPECT_CALL(visitor, OnError(_));
   4122     } else {
   4123       EXPECT_CALL(visitor, OnSynReply(37, flags & CONTROL_FLAG_FIN));
   4124       EXPECT_CALL(visitor, OnControlFrameHeaderData(37, _, _))
   4125           .WillRepeatedly(testing::Return(true));
   4126       if (flags & DATA_FLAG_FIN) {
   4127         EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
   4128       }
   4129     }
   4130 
   4131     framer.ProcessInput(frame->data(), frame->size());
   4132     if (flags & ~CONTROL_FLAG_FIN) {
   4133       EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
   4134       EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
   4135                 framer.error_code())
   4136           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4137     } else {
   4138       EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
   4139       EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
   4140           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4141     }
   4142   }
   4143 }
   4144 
   4145 TEST_P(SpdyFramerTest, RstStreamFrameFlags) {
   4146   for (int flags = 0; flags < 256; ++flags) {
   4147     SCOPED_TRACE(testing::Message() << "Flags " << flags);
   4148 
   4149     testing::StrictMock<test::MockVisitor> visitor;
   4150     SpdyFramer framer(spdy_version_);
   4151     framer.set_visitor(&visitor);
   4152 
   4153     scoped_ptr<SpdyFrame> frame(framer.CreateRstStream(13, RST_STREAM_CANCEL));
   4154     SetFrameFlags(frame.get(), flags, spdy_version_);
   4155 
   4156     if (flags != 0) {
   4157       EXPECT_CALL(visitor, OnError(_));
   4158     } else {
   4159       EXPECT_CALL(visitor, OnRstStream(13, RST_STREAM_CANCEL));
   4160     }
   4161 
   4162     framer.ProcessInput(frame->data(), frame->size());
   4163     if (flags != 0) {
   4164       EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
   4165       EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
   4166                 framer.error_code())
   4167           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4168     } else {
   4169       EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
   4170       EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
   4171           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4172     }
   4173   }
   4174 }
   4175 
   4176 TEST_P(SpdyFramerTest, SettingsFrameFlags) {
   4177   for (int flags = 0; flags < 256; ++flags) {
   4178     SCOPED_TRACE(testing::Message() << "Flags " << flags);
   4179 
   4180     testing::StrictMock<test::MockVisitor> visitor;
   4181     SpdyFramer framer(spdy_version_);
   4182     framer.set_visitor(&visitor);
   4183 
   4184     SettingsMap settings;
   4185     settings[SETTINGS_UPLOAD_BANDWIDTH] =
   4186         std::make_pair(SETTINGS_FLAG_NONE, 54321);
   4187     scoped_ptr<SpdyFrame> frame(framer.CreateSettings(settings));
   4188     SetFrameFlags(frame.get(), flags, spdy_version_);
   4189 
   4190     if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
   4191       EXPECT_CALL(visitor, OnError(_));
   4192     } else {
   4193       EXPECT_CALL(visitor, OnSettings(
   4194           flags & SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS));
   4195       EXPECT_CALL(visitor, OnSetting(SETTINGS_UPLOAD_BANDWIDTH,
   4196                                      SETTINGS_FLAG_NONE, 54321));
   4197     }
   4198 
   4199     framer.ProcessInput(frame->data(), frame->size());
   4200     if (flags & ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
   4201       EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
   4202       EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
   4203                 framer.error_code())
   4204           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4205     } else {
   4206       EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
   4207       EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
   4208           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4209     }
   4210   }
   4211 }
   4212 
   4213 TEST_P(SpdyFramerTest, GoawayFrameFlags) {
   4214   for (int flags = 0; flags < 256; ++flags) {
   4215     SCOPED_TRACE(testing::Message() << "Flags " << flags);
   4216 
   4217     testing::StrictMock<test::MockVisitor> visitor;
   4218     SpdyFramer framer(spdy_version_);
   4219     framer.set_visitor(&visitor);
   4220 
   4221     scoped_ptr<SpdyFrame> frame(framer.CreateGoAway(97, GOAWAY_OK));
   4222     SetFrameFlags(frame.get(), flags, spdy_version_);
   4223 
   4224     if (flags != 0) {
   4225       EXPECT_CALL(visitor, OnError(_));
   4226     } else {
   4227       EXPECT_CALL(visitor, OnGoAway(97, GOAWAY_OK));
   4228     }
   4229 
   4230     framer.ProcessInput(frame->data(), frame->size());
   4231     if (flags != 0) {
   4232       EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
   4233       EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
   4234                 framer.error_code())
   4235           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4236     } else {
   4237       EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
   4238       EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
   4239           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4240     }
   4241   }
   4242 }
   4243 
   4244 TEST_P(SpdyFramerTest, HeadersFrameFlags) {
   4245   for (int flags = 0; flags < 256; ++flags) {
   4246     SCOPED_TRACE(testing::Message() << "Flags " << flags);
   4247 
   4248     testing::StrictMock<test::MockVisitor> visitor;
   4249     SpdyFramer framer(spdy_version_);
   4250     framer.set_visitor(&visitor);
   4251 
   4252     SpdyHeaderBlock headers;
   4253     headers["foo"] = "bar";
   4254     scoped_ptr<SpdyFrame> frame(
   4255         framer.CreateHeaders(57, CONTROL_FLAG_NONE, true, &headers));
   4256     SetFrameFlags(frame.get(), flags, spdy_version_);
   4257 
   4258     if (flags & ~CONTROL_FLAG_FIN) {
   4259       EXPECT_CALL(visitor, OnError(_));
   4260     } else {
   4261       EXPECT_CALL(visitor, OnHeaders(57, flags & CONTROL_FLAG_FIN));
   4262       EXPECT_CALL(visitor, OnControlFrameHeaderData(57, _, _))
   4263           .WillRepeatedly(testing::Return(true));
   4264       if (flags & DATA_FLAG_FIN) {
   4265         EXPECT_CALL(visitor, OnStreamFrameData(_, _, 0, true));
   4266       }
   4267     }
   4268 
   4269     framer.ProcessInput(frame->data(), frame->size());
   4270     if (flags & ~CONTROL_FLAG_FIN) {
   4271       EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
   4272       EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
   4273                 framer.error_code())
   4274           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4275     } else {
   4276       EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
   4277       EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
   4278           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4279     }
   4280   }
   4281 }
   4282 
   4283 TEST_P(SpdyFramerTest, PingFrameFlags) {
   4284   for (int flags = 0; flags < 256; ++flags) {
   4285     SCOPED_TRACE(testing::Message() << "Flags " << flags);
   4286 
   4287     testing::StrictMock<test::MockVisitor> visitor;
   4288     SpdyFramer framer(spdy_version_);
   4289     framer.set_visitor(&visitor);
   4290 
   4291     scoped_ptr<SpdyFrame> frame(framer.CreatePingFrame(42));
   4292     SetFrameFlags(frame.get(), flags, spdy_version_);
   4293 
   4294     if (flags != 0) {
   4295       EXPECT_CALL(visitor, OnError(_));
   4296     } else {
   4297       EXPECT_CALL(visitor, OnPing(42));
   4298     }
   4299 
   4300     framer.ProcessInput(frame->data(), frame->size());
   4301     if (flags != 0) {
   4302       EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
   4303       EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
   4304                 framer.error_code())
   4305           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4306     } else {
   4307       EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
   4308       EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
   4309           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4310     }
   4311   }
   4312 }
   4313 
   4314 TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) {
   4315   for (int flags = 0; flags < 256; ++flags) {
   4316     SCOPED_TRACE(testing::Message() << "Flags " << flags);
   4317 
   4318     testing::StrictMock<test::MockVisitor> visitor;
   4319     SpdyFramer framer(spdy_version_);
   4320     framer.set_visitor(&visitor);
   4321 
   4322     scoped_ptr<SpdyFrame> frame(framer.CreateWindowUpdate(4, 1024));
   4323     SetFrameFlags(frame.get(), flags, spdy_version_);
   4324 
   4325     if (flags != 0) {
   4326       EXPECT_CALL(visitor, OnError(_));
   4327     } else {
   4328       EXPECT_CALL(visitor, OnWindowUpdate(4, 1024));
   4329     }
   4330 
   4331     framer.ProcessInput(frame->data(), frame->size());
   4332     if (flags != 0) {
   4333       EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
   4334       EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
   4335                 framer.error_code())
   4336           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4337     } else {
   4338       EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
   4339       EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
   4340           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4341     }
   4342   }
   4343 }
   4344 
   4345 TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
   4346   if (spdy_version_ < SPDY4) {
   4347     return;
   4348   }
   4349 
   4350   for (int flags = 0; flags < 256; ++flags) {
   4351     SCOPED_TRACE(testing::Message() << "Flags " << flags);
   4352 
   4353     testing::StrictMock<net::test::MockVisitor> visitor;
   4354     testing::StrictMock<net::test::MockDebugVisitor> debug_visitor;
   4355     SpdyFramer framer(spdy_version_);
   4356     framer.set_visitor(&visitor);
   4357     framer.set_debug_visitor(&debug_visitor);
   4358 
   4359     EXPECT_CALL(debug_visitor, OnSendCompressedFrame(42, PUSH_PROMISE, _, _));
   4360 
   4361     SpdyHeaderBlock headers;
   4362     headers["foo"] = "bar";
   4363     scoped_ptr<SpdyFrame> frame(framer.CreatePushPromise(42, 57, &headers));
   4364     SetFrameFlags(frame.get(), flags, spdy_version_);
   4365 
   4366     if (flags != 0) {
   4367       EXPECT_CALL(visitor, OnError(_));
   4368     } else {
   4369       EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(42, PUSH_PROMISE, _));
   4370       EXPECT_CALL(visitor, OnPushPromise(42, 57));
   4371       EXPECT_CALL(visitor, OnControlFrameHeaderData(42, _, _))
   4372           .WillRepeatedly(testing::Return(true));
   4373     }
   4374 
   4375     framer.ProcessInput(frame->data(), frame->size());
   4376     if (flags != 0) {
   4377       EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
   4378       EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
   4379                 framer.error_code())
   4380           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4381     } else {
   4382       EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
   4383       EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
   4384           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4385     }
   4386   }
   4387 }
   4388 
   4389 TEST_P(SpdyFramerTest, CredentialFrameFlags) {
   4390   for (int flags = 0; flags < 256; ++flags) {
   4391     SCOPED_TRACE(testing::Message() << "Flags " << flags);
   4392 
   4393     testing::StrictMock<test::MockVisitor> visitor;
   4394     SpdyFramer framer(spdy_version_);
   4395     framer.set_visitor(&visitor);
   4396 
   4397     SpdyCredential credential;
   4398     scoped_ptr<SpdyFrame> frame(framer.CreateCredentialFrame(credential));
   4399     SetFrameFlags(frame.get(), flags, spdy_version_);
   4400 
   4401     if (flags != 0) {
   4402       EXPECT_CALL(visitor, OnError(_));
   4403     } else {
   4404       EXPECT_CALL(visitor, OnCredentialFrameData(_, _))
   4405           .WillRepeatedly(testing::Return(true));
   4406     }
   4407 
   4408     framer.ProcessInput(frame->data(), frame->size());
   4409     if (flags != 0) {
   4410       EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
   4411       EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS,
   4412                 framer.error_code())
   4413           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4414     } else {
   4415       EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
   4416       EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
   4417           << SpdyFramer::ErrorCodeToString(framer.error_code());
   4418     }
   4419   }
   4420 }
   4421 
   4422 TEST_P(SpdyFramerTest, EmptySynStream) {
   4423   SpdyHeaderBlock headers;
   4424 
   4425   testing::StrictMock<test::MockVisitor> visitor;
   4426   testing::StrictMock<test::MockDebugVisitor> debug_visitor;
   4427   SpdyFramer framer(spdy_version_);
   4428   framer.set_visitor(&visitor);
   4429   framer.set_debug_visitor(&debug_visitor);
   4430 
   4431   EXPECT_CALL(debug_visitor, OnSendCompressedFrame(1, SYN_STREAM, _, _));
   4432 
   4433   scoped_ptr<SpdyFrame>
   4434       frame(framer.CreateSynStream(1, 0, 1, 0, CONTROL_FLAG_NONE, true,
   4435                                    &headers));
   4436   // Adjust size to remove the name/value block.
   4437   if (IsSpdy4()) {
   4438     SetFrameLength(
   4439         frame.get(),
   4440         framer.GetSynStreamMinimumSize(),
   4441         spdy_version_);
   4442   } else {
   4443     SetFrameLength(
   4444         frame.get(),
   4445         framer.GetSynStreamMinimumSize() - framer.GetControlFrameHeaderSize(),
   4446         spdy_version_);
   4447   }
   4448 
   4449   EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(1, SYN_STREAM, _));
   4450   EXPECT_CALL(visitor, OnSynStream(1, 0, 1, 0, false, false));
   4451   EXPECT_CALL(visitor, OnControlFrameHeaderData(1, NULL, 0));
   4452 
   4453   framer.ProcessInput(frame->data(), framer.GetSynStreamMinimumSize());
   4454   EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
   4455   EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
   4456       << SpdyFramer::ErrorCodeToString(framer.error_code());
   4457 }
   4458 
   4459 TEST_P(SpdyFramerTest, SettingsFlagsAndId) {
   4460   const uint32 kId = 0x020304;
   4461   const uint32 kFlags = 0x01;
   4462   const uint32 kWireFormat = htonl(IsSpdy2() ? 0x04030201 : 0x01020304);
   4463 
   4464   SettingsFlagsAndId id_and_flags =
   4465       SettingsFlagsAndId::FromWireFormat(spdy_version_, kWireFormat);
   4466   EXPECT_EQ(kId, id_and_flags.id());
   4467   EXPECT_EQ(kFlags, id_and_flags.flags());
   4468   EXPECT_EQ(kWireFormat, id_and_flags.GetWireFormat(spdy_version_));
   4469 }
   4470 
   4471 // Test handling of a RST_STREAM with out-of-bounds status codes.
   4472 TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
   4473   DCHECK_GE(0xff, RST_STREAM_NUM_STATUS_CODES);
   4474 
   4475   const unsigned char kV3RstStreamInvalid[] = {
   4476     0x80, spdy_version_ch_, 0x00, 0x03,
   4477     0x00, 0x00, 0x00, 0x08,
   4478     0x00, 0x00, 0x00, 0x01,
   4479     0x00, 0x00, 0x00, RST_STREAM_INVALID
   4480   };
   4481   const unsigned char kV4RstStreamInvalid[] = {
   4482     0x00, 0x0c, 0x03, 0x00,
   4483     0x00, 0x00, 0x00, 0x01,
   4484     0x00, 0x00, 0x00, RST_STREAM_INVALID
   4485   };
   4486 
   4487   const unsigned char kV3RstStreamNumStatusCodes[] = {
   4488     0x80, spdy_version_ch_, 0x00, 0x03,
   4489     0x00, 0x00, 0x00, 0x08,
   4490     0x00, 0x00, 0x00, 0x01,
   4491     0x00, 0x00, 0x00, RST_STREAM_NUM_STATUS_CODES
   4492   };
   4493   const unsigned char kV4RstStreamNumStatusCodes[] = {
   4494     0x00, 0x0c, 0x03, 0x00,
   4495     0x00, 0x00, 0x00, 0x01,
   4496     0x00, 0x00, 0x00, RST_STREAM_NUM_STATUS_CODES
   4497   };
   4498 
   4499   testing::StrictMock<test::MockVisitor> visitor;
   4500   SpdyFramer framer(spdy_version_);
   4501   framer.set_visitor(&visitor);
   4502 
   4503   EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
   4504   if (IsSpdy4()) {
   4505     framer.ProcessInput(reinterpret_cast<const char*>(kV4RstStreamInvalid),
   4506                         arraysize(kV4RstStreamInvalid));
   4507   } else {
   4508     framer.ProcessInput(reinterpret_cast<const char*>(kV3RstStreamInvalid),
   4509                         arraysize(kV3RstStreamInvalid));
   4510   }
   4511   EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
   4512   EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
   4513       << SpdyFramer::ErrorCodeToString(framer.error_code());
   4514 
   4515   EXPECT_CALL(visitor, OnRstStream(1, RST_STREAM_INVALID));
   4516   if (IsSpdy4()) {
   4517     framer.ProcessInput(
   4518         reinterpret_cast<const char*>(kV4RstStreamNumStatusCodes),
   4519         arraysize(kV4RstStreamNumStatusCodes));
   4520   } else {
   4521     framer.ProcessInput(
   4522         reinterpret_cast<const char*>(kV3RstStreamNumStatusCodes),
   4523         arraysize(kV3RstStreamNumStatusCodes));
   4524   }
   4525   EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
   4526   EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
   4527       << SpdyFramer::ErrorCodeToString(framer.error_code());
   4528 }
   4529 
   4530 // Tests handling of a GOAWAY frame with out-of-bounds stream ID.
   4531 TEST_P(SpdyFramerTest, GoAwayStreamIdBounds) {
   4532   const unsigned char kV2FrameData[] = {
   4533     0x80, spdy_version_ch_, 0x00, 0x07,
   4534     0x00, 0x00, 0x00, 0x04,
   4535     0xff, 0xff, 0xff, 0xff,
   4536   };
   4537   const unsigned char kV3FrameData[] = {
   4538     0x80, spdy_version_ch_, 0x00, 0x07,
   4539     0x00, 0x00, 0x00, 0x08,
   4540     0xff, 0xff, 0xff, 0xff,
   4541     0x00, 0x00, 0x00, 0x00,
   4542   };
   4543   const unsigned char kV4FrameData[] = {
   4544     0x00, 0x10, 0x07, 0x00,
   4545     0x00, 0x00, 0x00, 0x00,
   4546     0xff, 0xff, 0xff, 0xff,
   4547     0x00, 0x00, 0x00, 0x00,
   4548   };
   4549 
   4550   testing::StrictMock<test::MockVisitor> visitor;
   4551   SpdyFramer framer(spdy_version_);
   4552   framer.set_visitor(&visitor);
   4553 
   4554   EXPECT_CALL(visitor, OnGoAway(0x7fffffff, GOAWAY_OK));
   4555   if (IsSpdy2()) {
   4556     framer.ProcessInput(reinterpret_cast<const char*>(kV2FrameData),
   4557                         arraysize(kV2FrameData));
   4558   } else if (IsSpdy3()) {
   4559     framer.ProcessInput(reinterpret_cast<const char*>(kV3FrameData),
   4560                         arraysize(kV3FrameData));
   4561   } else {
   4562     framer.ProcessInput(reinterpret_cast<const char*>(kV4FrameData),
   4563                         arraysize(kV4FrameData));
   4564   }
   4565   EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
   4566   EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
   4567       << SpdyFramer::ErrorCodeToString(framer.error_code());
   4568 }
   4569 
   4570 TEST_P(SpdyFramerTest, OnBlocked) {
   4571   if (spdy_version_ < SPDY4) {
   4572     return;
   4573   }
   4574 
   4575   const SpdyStreamId kStreamId = 0;
   4576 
   4577   testing::StrictMock<test::MockVisitor> visitor;
   4578   SpdyFramer framer(spdy_version_);
   4579   framer.set_visitor(&visitor);
   4580 
   4581   EXPECT_CALL(visitor, OnBlocked(kStreamId));
   4582 
   4583   SpdyBlockedIR blocked_ir(0);
   4584   scoped_ptr<SpdySerializedFrame> frame(framer.SerializeFrame(blocked_ir));
   4585   framer.ProcessInput(frame->data(), framer.GetBlockedSize());
   4586 
   4587   EXPECT_EQ(SpdyFramer::SPDY_RESET, framer.state());
   4588   EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code())
   4589       << SpdyFramer::ErrorCodeToString(framer.error_code());
   4590 }
   4591 
   4592 }  // namespace net
   4593