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