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