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