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