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