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