chromeos: bluetooth: add BluetoothInputClient
[chromium-blink-merge.git] / net / spdy / spdy_framer_test.cc
blob8518bbbd282ad3ec9576c94f6e93cd385033d38b
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.
5 #include <algorithm>
6 #include <iostream>
8 #include "base/memory/scoped_ptr.h"
9 #include "net/spdy/spdy_framer.h"
10 #include "net/spdy/spdy_protocol.h"
11 #include "net/spdy/spdy_frame_builder.h"
12 #include "testing/platform_test.h"
14 namespace spdy {
16 namespace test {
18 std::string HexDumpWithMarks(const unsigned char* data, int length,
19 const bool* marks, int mark_length) {
20 static const char kHexChars[] = "0123456789ABCDEF";
21 static const int kColumns = 4;
23 const int kSizeLimit = 1024;
24 if (length > kSizeLimit || mark_length > kSizeLimit) {
25 LOG(ERROR) << "Only dumping first " << kSizeLimit << " bytes.";
26 length = std::min(length, kSizeLimit);
27 mark_length = std::min(mark_length, kSizeLimit);
30 std::string hex;
31 for (const unsigned char* row = data; length > 0;
32 row += kColumns, length -= kColumns) {
33 for (const unsigned char *p = row; p < row + 4; ++p) {
34 if (p < row + length) {
35 const bool mark =
36 (marks && (p - data) < mark_length && marks[p - data]);
37 hex += mark ? '*' : ' ';
38 hex += kHexChars[(*p & 0xf0) >> 4];
39 hex += kHexChars[*p & 0x0f];
40 hex += mark ? '*' : ' ';
41 } else {
42 hex += " ";
45 hex = hex + " ";
47 for (const unsigned char *p = row; p < row + 4 && p < row + length; ++p)
48 hex += (*p >= 0x20 && *p <= 0x7f) ? (*p) : '.';
50 hex = hex + '\n';
52 return hex;
55 void CompareCharArraysWithHexError(
56 const std::string& description,
57 const unsigned char* actual,
58 const int actual_len,
59 const unsigned char* expected,
60 const int expected_len) {
61 const int min_len = actual_len > expected_len ? expected_len : actual_len;
62 const int max_len = actual_len > expected_len ? actual_len : expected_len;
63 scoped_array<bool> marks(new bool[max_len]);
64 bool identical = (actual_len == expected_len);
65 for (int i = 0; i < min_len; ++i) {
66 if (actual[i] != expected[i]) {
67 marks[i] = true;
68 identical = false;
69 } else {
70 marks[i] = false;
73 for (int i = min_len; i < max_len; ++i) {
74 marks[i] = true;
76 if (identical) return;
77 ADD_FAILURE()
78 << "Description:\n"
79 << description
80 << "\n\nExpected:\n"
81 << HexDumpWithMarks(expected, expected_len, marks.get(), max_len)
82 << "\nActual:\n"
83 << HexDumpWithMarks(actual, actual_len, marks.get(), max_len);
86 class TestSpdyVisitor : public SpdyFramerVisitorInterface {
87 public:
88 static const size_t kDefaultHeaderBufferSize = 64 * 1024;
89 static const size_t kDefaultCredentialBufferSize = 16 * 1024;
91 TestSpdyVisitor()
92 : use_compression_(false),
93 error_count_(0),
94 syn_frame_count_(0),
95 syn_reply_frame_count_(0),
96 headers_frame_count_(0),
97 goaway_count_(0),
98 credential_count_(0),
99 data_bytes_(0),
100 fin_frame_count_(0),
101 fin_flag_count_(0),
102 zero_length_data_frame_count_(0),
103 header_blocks_count_(0),
104 control_frame_header_data_count_(0),
105 zero_length_control_frame_header_data_count_(0),
106 data_frame_count_(0),
107 header_buffer_(new char[kDefaultHeaderBufferSize]),
108 header_buffer_length_(0),
109 header_buffer_size_(kDefaultHeaderBufferSize),
110 header_stream_id_(-1),
111 header_control_type_(NUM_CONTROL_FRAME_TYPES),
112 header_buffer_valid_(false),
113 credential_buffer_(new char[kDefaultCredentialBufferSize]),
114 credential_buffer_length_(0),
115 credential_buffer_size_(kDefaultCredentialBufferSize) {
118 void OnError(SpdyFramer* f) {
119 LOG(INFO) << "SpdyFramer Error: "
120 << SpdyFramer::ErrorCodeToString(f->error_code());
121 error_count_++;
124 void OnDataFrameHeader(const SpdyDataFrame* frame) {
125 data_frame_count_++;
126 header_stream_id_ = frame->stream_id();
129 void OnStreamFrameData(SpdyStreamId stream_id,
130 const char* data,
131 size_t len) {
132 EXPECT_EQ(header_stream_id_, stream_id);
133 if (len == 0)
134 ++zero_length_data_frame_count_;
136 data_bytes_ += len;
137 std::cerr << "OnStreamFrameData(" << stream_id << ", \"";
138 if (len > 0) {
139 for (size_t i = 0 ; i < len; ++i) {
140 std::cerr << std::hex << (0xFF & (unsigned int)data[i]) << std::dec;
143 std::cerr << "\", " << len << ")\n";
146 void OnControl(const SpdyControlFrame* frame) {
147 switch (frame->type()) {
148 case SYN_STREAM:
149 syn_frame_count_++;
150 InitHeaderStreaming(frame);
151 break;
152 case SYN_REPLY:
153 syn_reply_frame_count_++;
154 InitHeaderStreaming(frame);
155 break;
156 case RST_STREAM:
157 fin_frame_count_++;
158 break;
159 case HEADERS:
160 headers_frame_count_++;
161 InitHeaderStreaming(frame);
162 break;
163 case GOAWAY:
164 goaway_count_++;
165 break;
166 case CREDENTIAL:
167 credential_count_++;
168 break;
169 default:
170 DLOG(FATAL); // Error!
172 if (frame->flags() & CONTROL_FLAG_FIN)
173 ++fin_flag_count_;
176 bool OnControlFrameHeaderData(SpdyStreamId stream_id,
177 const char* header_data,
178 size_t len) {
179 ++control_frame_header_data_count_;
180 CHECK_EQ(header_stream_id_, stream_id);
181 if (len == 0) {
182 ++zero_length_control_frame_header_data_count_;
183 // Indicates end-of-header-block.
184 CHECK(header_buffer_valid_);
185 bool parsed_headers = SpdyFramer::ParseHeaderBlockInBuffer(
186 header_buffer_.get(), header_buffer_length_, &headers_);
187 DCHECK(parsed_headers);
188 return true;
190 const size_t available = header_buffer_size_ - header_buffer_length_;
191 if (len > available) {
192 header_buffer_valid_ = false;
193 return false;
195 memcpy(header_buffer_.get() + header_buffer_length_, header_data, len);
196 header_buffer_length_ += len;
197 return true;
200 bool OnCredentialFrameData(const char* credential_data, size_t len) {
201 if (len == 0) {
202 if (!framer_.ParseCredentialData(credential_buffer_.get(),
203 credential_buffer_length_,
204 &credential_)) {
205 ++error_count_;
207 return true;
209 const size_t available =
210 credential_buffer_size_ - credential_buffer_length_;
211 if (len > available) {
212 return false;
214 memcpy(credential_buffer_.get() + credential_buffer_length_,
215 credential_data, len);
216 credential_buffer_length_ += len;
217 return true;
220 // Convenience function which runs a framer simulation with particular input.
221 void SimulateInFramer(const unsigned char* input, size_t size) {
222 framer_.set_enable_compression(use_compression_);
223 framer_.set_visitor(this);
224 size_t input_remaining = size;
225 const char* input_ptr = reinterpret_cast<const char*>(input);
226 while (input_remaining > 0 &&
227 framer_.error_code() == SpdyFramer::SPDY_NO_ERROR) {
228 // To make the tests more interesting, we feed random (amd small) chunks
229 // into the framer. This simulates getting strange-sized reads from
230 // the socket.
231 const size_t kMaxReadSize = 32;
232 size_t bytes_read =
233 (rand() % std::min(input_remaining, kMaxReadSize)) + 1;
234 size_t bytes_processed = framer_.ProcessInput(input_ptr, bytes_read);
235 input_remaining -= bytes_processed;
236 input_ptr += bytes_processed;
237 if (framer_.state() == SpdyFramer::SPDY_DONE)
238 framer_.Reset();
242 void InitHeaderStreaming(const SpdyControlFrame* frame) {
243 memset(header_buffer_.get(), 0, header_buffer_size_);
244 header_buffer_length_ = 0;
245 header_stream_id_ = SpdyFramer::GetControlFrameStreamId(frame);
246 header_control_type_ = frame->type();
247 header_buffer_valid_ = true;
248 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream);
251 // Override the default buffer size (16K). Call before using the framer!
252 void set_header_buffer_size(size_t header_buffer_size) {
253 header_buffer_size_ = header_buffer_size;
254 header_buffer_.reset(new char[header_buffer_size]);
257 static size_t control_frame_buffer_max_size() {
258 return SpdyFramer::kControlFrameBufferMaxSize;
261 static size_t header_data_chunk_max_size() {
262 return SpdyFramer::kHeaderDataChunkMaxSize;
265 SpdyFramer framer_;
266 bool use_compression_;
268 // Counters from the visitor callbacks.
269 int error_count_;
270 int syn_frame_count_;
271 int syn_reply_frame_count_;
272 int headers_frame_count_;
273 int goaway_count_;
274 int credential_count_;
275 int data_bytes_;
276 int fin_frame_count_; // The count of RST_STREAM type frames received.
277 int fin_flag_count_; // The count of frames with the FIN flag set.
278 int zero_length_data_frame_count_; // The count of zero-length data frames.
279 int header_blocks_count_;
280 int control_frame_header_data_count_; // The count of chunks received.
281 // The count of zero-length control frame header data chunks received.
282 int zero_length_control_frame_header_data_count_;
283 int data_frame_count_;
285 // Header block streaming state:
286 scoped_array<char> header_buffer_;
287 size_t header_buffer_length_;
288 size_t header_buffer_size_;
289 SpdyStreamId header_stream_id_;
290 SpdyControlType header_control_type_;
291 bool header_buffer_valid_;
292 SpdyHeaderBlock headers_;
294 scoped_array<char> credential_buffer_;
295 size_t credential_buffer_length_;
296 size_t credential_buffer_size_;
297 SpdyCredential credential_;
300 } // namespace test
302 } // namespace spdy
304 using spdy::SpdyControlFlags;
305 using spdy::SpdyControlFrame;
306 using spdy::SpdyDataFrame;
307 using spdy::SpdyFrame;
308 using spdy::SpdyFrameBuilder;
309 using spdy::SpdyFramer;
310 using spdy::SpdyHeaderBlock;
311 using spdy::SpdySynStreamControlFrame;
312 using spdy::kControlFlagMask;
313 using spdy::kLengthMask;
314 using spdy::CONTROL_FLAG_NONE;
315 using spdy::DATA_FLAG_COMPRESSED;
316 using spdy::DATA_FLAG_FIN;
317 using spdy::SYN_STREAM;
318 using spdy::test::CompareCharArraysWithHexError;
319 using spdy::test::TestSpdyVisitor;
321 namespace spdy {
323 TEST(SpdyFrameBuilderTest, WriteLimits) {
324 SpdyFrameBuilder builder(kLengthMask + 4);
325 // length field should fail.
326 EXPECT_FALSE(builder.WriteBytes(reinterpret_cast<const void*>(0x1),
327 kLengthMask + 1));
328 EXPECT_EQ(0, builder.length());
330 // Writing a block of the maximum allowed size should succeed.
331 const std::string kLargeData(kLengthMask, 'A');
332 builder.WriteUInt32(kLengthMask);
333 EXPECT_EQ(4, builder.length());
334 EXPECT_TRUE(builder.WriteBytes(kLargeData.data(), kLengthMask));
335 EXPECT_EQ(4 + kLengthMask, static_cast<unsigned>(builder.length()));
338 class SpdyFramerTest : public PlatformTest {
339 public:
340 virtual void TearDown() {}
342 protected:
343 void CompareFrame(const std::string& description,
344 const SpdyFrame& actual_frame,
345 const unsigned char* expected,
346 const int expected_len) {
347 const unsigned char* actual =
348 reinterpret_cast<const unsigned char*>(actual_frame.data());
349 int actual_len = actual_frame.length() + SpdyFrame::kHeaderSize;
350 CompareCharArraysWithHexError(
351 description, actual, actual_len, expected, expected_len);
354 // Returns true if the two header blocks have equivalent content.
355 bool CompareHeaderBlocks(const SpdyHeaderBlock* expected,
356 const SpdyHeaderBlock* actual) {
357 if (expected->size() != actual->size()) {
358 LOG(ERROR) << "Expected " << expected->size() << " headers; actually got "
359 << actual->size() << "." << std::endl;
360 return false;
362 for (SpdyHeaderBlock::const_iterator it = expected->begin();
363 it != expected->end();
364 ++it) {
365 SpdyHeaderBlock::const_iterator it2 = actual->find(it->first);
366 if (it2 == actual->end()) {
367 LOG(ERROR) << "Expected header name '" << it->first << "'."
368 << std::endl;
369 return false;
371 if (it->second.compare(it2->second) != 0) {
372 LOG(ERROR) << "Expected header named '" << it->first
373 << "' to have a value of '" << it->second
374 << "'. The actual value received was '" << it2->second
375 << "'." << std::endl;
376 return false;
379 return true;
384 // Test that we can encode and decode a SpdyHeaderBlock in serialized form.
385 TEST_F(SpdyFramerTest, HeaderBlockInBuffer) {
386 SpdyHeaderBlock headers;
387 headers["alpha"] = "beta";
388 headers["gamma"] = "charlie";
389 SpdyFramer framer;
391 // Encode the header block into a SynStream frame.
392 scoped_ptr<SpdySynStreamControlFrame> frame(
393 framer.CreateSynStream(1, 0, 1, CONTROL_FLAG_NONE, false, &headers));
394 EXPECT_TRUE(frame.get() != NULL);
395 std::string serialized_headers(frame->header_block(),
396 frame->header_block_len());
397 SpdyHeaderBlock new_headers;
398 EXPECT_TRUE(framer.ParseHeaderBlockInBuffer(serialized_headers.c_str(),
399 serialized_headers.size(),
400 &new_headers));
402 EXPECT_EQ(headers.size(), new_headers.size());
403 EXPECT_EQ(headers["alpha"], new_headers["alpha"]);
404 EXPECT_EQ(headers["gamma"], new_headers["gamma"]);
407 // Test that if there's not a full frame, we fail to parse it.
408 TEST_F(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
409 SpdyHeaderBlock headers;
410 headers["alpha"] = "beta";
411 headers["gamma"] = "charlie";
412 SpdyFramer framer;
414 // Encode the header block into a SynStream frame.
415 scoped_ptr<SpdySynStreamControlFrame> frame(
416 framer.CreateSynStream(1, 0, 1, CONTROL_FLAG_NONE, false, &headers));
417 EXPECT_TRUE(frame.get() != NULL);
419 std::string serialized_headers(frame->header_block(),
420 frame->header_block_len());
421 SpdyHeaderBlock new_headers;
422 EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.c_str(),
423 serialized_headers.size() - 2,
424 &new_headers));
427 TEST_F(SpdyFramerTest, OutOfOrderHeaders) {
428 // Frame builder with plentiful buffer size.
429 SpdyFrameBuilder frame(1024);
431 frame.WriteUInt16(kControlFlagMask | 1);
432 frame.WriteUInt16(SYN_STREAM);
433 frame.WriteUInt32(0); // Placeholder for the length.
434 frame.WriteUInt32(3); // stream_id
435 frame.WriteUInt32(0); // Associated stream id
436 frame.WriteUInt16(0); // Priority.
438 frame.WriteUInt16(2); // Number of headers.
439 SpdyHeaderBlock::iterator it;
440 frame.WriteString("gamma");
441 frame.WriteString("gamma");
442 frame.WriteString("alpha");
443 frame.WriteString("alpha");
444 // write the length
445 frame.WriteUInt32ToOffset(4, frame.length() - SpdyFrame::kHeaderSize);
447 SpdyHeaderBlock new_headers;
448 scoped_ptr<SpdyFrame> control_frame(frame.take());
449 SpdySynStreamControlFrame syn_frame(control_frame->data(), false);
450 std::string serialized_headers(syn_frame.header_block(),
451 syn_frame.header_block_len());
452 SpdyFramer framer;
453 framer.set_enable_compression(false);
454 EXPECT_TRUE(framer.ParseHeaderBlockInBuffer(serialized_headers.c_str(),
455 serialized_headers.size(),
456 &new_headers));
459 TEST_F(SpdyFramerTest, DuplicateHeader) {
460 // Frame builder with plentiful buffer size.
461 SpdyFrameBuilder frame(1024);
463 frame.WriteUInt16(kControlFlagMask | 1);
464 frame.WriteUInt16(SYN_STREAM);
465 frame.WriteUInt32(0); // Placeholder for the length.
466 frame.WriteUInt32(3); // stream_id
467 frame.WriteUInt32(0); // associated stream id
468 frame.WriteUInt16(0); // Priority.
470 frame.WriteUInt16(2); // Number of headers.
471 SpdyHeaderBlock::iterator it;
472 frame.WriteString("name");
473 frame.WriteString("value1");
474 frame.WriteString("name");
475 frame.WriteString("value2");
476 // write the length
477 frame.WriteUInt32ToOffset(4, frame.length() - SpdyFrame::kHeaderSize);
479 SpdyHeaderBlock new_headers;
480 scoped_ptr<SpdyFrame> control_frame(frame.take());
481 SpdySynStreamControlFrame syn_frame(control_frame->data(), false);
482 std::string serialized_headers(syn_frame.header_block(),
483 syn_frame.header_block_len());
484 SpdyFramer framer;
485 framer.set_enable_compression(false);
486 // This should fail because duplicate headers are verboten by the spec.
487 EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.c_str(),
488 serialized_headers.size(),
489 &new_headers));
492 TEST_F(SpdyFramerTest, MultiValueHeader) {
493 // Frame builder with plentiful buffer size.
494 SpdyFrameBuilder frame(1024);
496 frame.WriteUInt16(kControlFlagMask | 1);
497 frame.WriteUInt16(SYN_STREAM);
498 frame.WriteUInt32(0); // Placeholder for the length.
499 frame.WriteUInt32(3); // stream_id
500 frame.WriteUInt32(0); // associated stream id
501 frame.WriteUInt16(0); // Priority.
503 frame.WriteUInt16(1); // Number of headers.
504 SpdyHeaderBlock::iterator it;
505 frame.WriteString("name");
506 std::string value("value1\0value2");
507 frame.WriteString(value);
508 // write the length
509 frame.WriteUInt32ToOffset(4, frame.length() - SpdyFrame::kHeaderSize);
511 SpdyHeaderBlock new_headers;
512 scoped_ptr<SpdyFrame> control_frame(frame.take());
513 SpdySynStreamControlFrame syn_frame(control_frame->data(), false);
514 std::string serialized_headers(syn_frame.header_block(),
515 syn_frame.header_block_len());
516 SpdyFramer framer;
517 framer.set_enable_compression(false);
518 EXPECT_TRUE(framer.ParseHeaderBlockInBuffer(serialized_headers.c_str(),
519 serialized_headers.size(),
520 &new_headers));
521 EXPECT_TRUE(new_headers.find("name") != new_headers.end());
522 EXPECT_EQ(value, new_headers.find("name")->second);
525 TEST_F(SpdyFramerTest, BasicCompression) {
526 SpdyHeaderBlock headers;
527 headers["server"] = "SpdyServer 1.0";
528 headers["date"] = "Mon 12 Jan 2009 12:12:12 PST";
529 headers["status"] = "200";
530 headers["version"] = "HTTP/1.1";
531 headers["content-type"] = "text/html";
532 headers["content-length"] = "12";
534 SpdyFramer framer;
535 framer.set_enable_compression(true);
536 scoped_ptr<SpdySynStreamControlFrame>
537 frame1(framer.CreateSynStream(1, 0, 1, CONTROL_FLAG_NONE, true,
538 &headers));
539 scoped_ptr<SpdySynStreamControlFrame>
540 frame2(framer.CreateSynStream(1, 0, 1, CONTROL_FLAG_NONE, true,
541 &headers));
543 // Expect the second frame to be more compact than the first.
544 EXPECT_LE(frame2->length(), frame1->length());
546 // Decompress the first frame
547 scoped_ptr<SpdyFrame> frame3(framer.DecompressFrame(*frame1.get()));
549 // Decompress the second frame
550 scoped_ptr<SpdyFrame> frame4(framer.DecompressFrame(*frame2.get()));
552 // Expect frames 3 & 4 to be the same.
553 EXPECT_EQ(0,
554 memcmp(frame3->data(), frame4->data(),
555 SpdyFrame::kHeaderSize + frame3->length()));
558 // Expect frames 3 to be the same as a uncompressed frame created
559 // from scratch.
560 scoped_ptr<SpdySynStreamControlFrame>
561 uncompressed_frame(framer.CreateSynStream(1, 0, 1, CONTROL_FLAG_NONE,
562 false, &headers));
563 EXPECT_EQ(frame3->length(), uncompressed_frame->length());
564 EXPECT_EQ(0,
565 memcmp(frame3->data(), uncompressed_frame->data(),
566 SpdyFrame::kHeaderSize + uncompressed_frame->length()));
569 TEST_F(SpdyFramerTest, DecompressUncompressedFrame) {
570 SpdyHeaderBlock headers;
571 headers["server"] = "SpdyServer 1.0";
572 headers["date"] = "Mon 12 Jan 2009 12:12:12 PST";
573 headers["status"] = "200";
574 headers["version"] = "HTTP/1.1";
575 headers["content-type"] = "text/html";
576 headers["content-length"] = "12";
578 SpdyFramer framer;
579 framer.set_enable_compression(true);
580 scoped_ptr<SpdySynStreamControlFrame>
581 frame1(framer.CreateSynStream(1, 0, 1, CONTROL_FLAG_NONE, false,
582 &headers));
584 // Decompress the frame
585 scoped_ptr<SpdyFrame> frame2(framer.DecompressFrame(*frame1.get()));
587 EXPECT_EQ(NULL, frame2.get());
590 TEST_F(SpdyFramerTest, Basic) {
591 const unsigned char input[] = {
592 0x80, 0x02, 0x00, 0x01, // SYN Stream #1
593 0x00, 0x00, 0x00, 0x14,
594 0x00, 0x00, 0x00, 0x01,
595 0x00, 0x00, 0x00, 0x00,
596 0x00, 0x00, 0x00, 0x01,
597 0x00, 0x02, 'h', 'h',
598 0x00, 0x02, 'v', 'v',
600 0x80, 0x02, 0x00, 0x08, // HEADERS on Stream #1
601 0x00, 0x00, 0x00, 0x18,
602 0x00, 0x00, 0x00, 0x01,
603 0x00, 0x00, 0x00, 0x02,
604 0x00, 0x02, 'h', '2',
605 0x00, 0x02, 'v', '2',
606 0x00, 0x02, 'h', '3',
607 0x00, 0x02, 'v', '3',
609 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
610 0x00, 0x00, 0x00, 0x0c,
611 0xde, 0xad, 0xbe, 0xef,
612 0xde, 0xad, 0xbe, 0xef,
613 0xde, 0xad, 0xbe, 0xef,
615 0x80, 0x02, 0x00, 0x01, // SYN Stream #3
616 0x00, 0x00, 0x00, 0x0c,
617 0x00, 0x00, 0x00, 0x03,
618 0x00, 0x00, 0x00, 0x00,
619 0x00, 0x00, 0x00, 0x00,
621 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
622 0x00, 0x00, 0x00, 0x08,
623 0xde, 0xad, 0xbe, 0xef,
624 0xde, 0xad, 0xbe, 0xef,
626 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
627 0x00, 0x00, 0x00, 0x04,
628 0xde, 0xad, 0xbe, 0xef,
630 0x80, 0x02, 0x00, 0x03, // RST_STREAM on Stream #1
631 0x00, 0x00, 0x00, 0x08,
632 0x00, 0x00, 0x00, 0x01,
633 0x00, 0x00, 0x00, 0x00,
635 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
636 0x00, 0x00, 0x00, 0x00,
638 0x80, 0x02, 0x00, 0x03, // RST_STREAM on Stream #3
639 0x00, 0x00, 0x00, 0x08,
640 0x00, 0x00, 0x00, 0x03,
641 0x00, 0x00, 0x00, 0x00,
644 TestSpdyVisitor visitor;
645 visitor.SimulateInFramer(input, sizeof(input));
647 EXPECT_EQ(0, visitor.error_count_);
648 EXPECT_EQ(2, visitor.syn_frame_count_);
649 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
650 EXPECT_EQ(1, visitor.headers_frame_count_);
651 EXPECT_EQ(24, visitor.data_bytes_);
652 EXPECT_EQ(2, visitor.fin_frame_count_);
653 EXPECT_EQ(0, visitor.fin_flag_count_);
654 EXPECT_EQ(0, visitor.zero_length_data_frame_count_);
655 EXPECT_EQ(4, visitor.data_frame_count_);
658 // Test that the FIN flag on a data frame signifies EOF.
659 TEST_F(SpdyFramerTest, FinOnDataFrame) {
660 const unsigned char input[] = {
661 0x80, 0x02, 0x00, 0x01, // SYN Stream #1
662 0x00, 0x00, 0x00, 0x14,
663 0x00, 0x00, 0x00, 0x01,
664 0x00, 0x00, 0x00, 0x00,
665 0x00, 0x00, 0x00, 0x01,
666 0x00, 0x02, 'h', 'h',
667 0x00, 0x02, 'v', 'v',
669 0x80, 0x02, 0x00, 0x02, // SYN REPLY Stream #1
670 0x00, 0x00, 0x00, 0x10,
671 0x00, 0x00, 0x00, 0x01,
672 0x00, 0x00, 0x00, 0x01,
673 0x00, 0x02, 'a', 'a',
674 0x00, 0x02, 'b', 'b',
676 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
677 0x00, 0x00, 0x00, 0x0c,
678 0xde, 0xad, 0xbe, 0xef,
679 0xde, 0xad, 0xbe, 0xef,
680 0xde, 0xad, 0xbe, 0xef,
682 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
683 0x01, 0x00, 0x00, 0x04,
684 0xde, 0xad, 0xbe, 0xef,
687 TestSpdyVisitor visitor;
688 visitor.SimulateInFramer(input, sizeof(input));
690 EXPECT_EQ(0, visitor.error_count_);
691 EXPECT_EQ(1, visitor.syn_frame_count_);
692 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
693 EXPECT_EQ(0, visitor.headers_frame_count_);
694 EXPECT_EQ(16, visitor.data_bytes_);
695 EXPECT_EQ(0, visitor.fin_frame_count_);
696 EXPECT_EQ(0, visitor.fin_flag_count_);
697 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
698 EXPECT_EQ(2, visitor.data_frame_count_);
701 // Test that the FIN flag on a SYN reply frame signifies EOF.
702 TEST_F(SpdyFramerTest, FinOnSynReplyFrame) {
703 const unsigned char input[] = {
704 0x80, 0x02, 0x00, 0x01, // SYN Stream #1
705 0x00, 0x00, 0x00, 0x14,
706 0x00, 0x00, 0x00, 0x01,
707 0x00, 0x00, 0x00, 0x00,
708 0x00, 0x00, 0x00, 0x01,
709 0x00, 0x02, 'h', 'h',
710 0x00, 0x02, 'v', 'v',
712 0x80, 0x02, 0x00, 0x02, // SYN REPLY Stream #1
713 0x01, 0x00, 0x00, 0x14,
714 0x00, 0x00, 0x00, 0x01,
715 0x00, 0x00, 0x00, 0x00,
716 0x00, 0x00, 0x00, 0x01,
717 0x00, 0x02, 'a', 'a',
718 0x00, 0x02, 'b', 'b',
721 TestSpdyVisitor visitor;
722 visitor.SimulateInFramer(input, sizeof(input));
724 EXPECT_EQ(0, visitor.error_count_);
725 EXPECT_EQ(1, visitor.syn_frame_count_);
726 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
727 EXPECT_EQ(0, visitor.headers_frame_count_);
728 EXPECT_EQ(0, visitor.data_bytes_);
729 EXPECT_EQ(0, visitor.fin_frame_count_);
730 EXPECT_EQ(1, visitor.fin_flag_count_);
731 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
732 EXPECT_EQ(0, visitor.data_frame_count_);
735 TEST_F(SpdyFramerTest, HeaderCompression) {
736 SpdyFramer send_framer;
737 SpdyFramer recv_framer;
739 send_framer.set_enable_compression(true);
740 recv_framer.set_enable_compression(true);
742 const char kHeader1[] = "header1";
743 const char kHeader2[] = "header2";
744 const char kHeader3[] = "header3";
745 const char kValue1[] = "value1";
746 const char kValue2[] = "value2";
747 const char kValue3[] = "value3";
749 // SYN_STREAM #1
750 SpdyHeaderBlock block;
751 block[kHeader1] = kValue1;
752 block[kHeader2] = kValue2;
753 SpdyControlFlags flags(CONTROL_FLAG_NONE);
754 scoped_ptr<spdy::SpdyFrame> syn_frame_1(
755 send_framer.CreateSynStream(1, 0, 0, flags, true, &block));
756 EXPECT_TRUE(syn_frame_1.get() != NULL);
758 // SYN_STREAM #2
759 block[kHeader3] = kValue3;
760 scoped_ptr<spdy::SpdyFrame> syn_frame_2(
761 send_framer.CreateSynStream(3, 0, 0, flags, true, &block));
762 EXPECT_TRUE(syn_frame_2.get() != NULL);
764 // Now start decompressing
765 scoped_ptr<SpdyFrame> decompressed;
766 scoped_ptr<SpdyFrame> decompressed_syn_frame;
767 SpdySynStreamControlFrame* syn_frame;
768 scoped_ptr<std::string> serialized_headers;
769 SpdyHeaderBlock decompressed_headers;
771 // Decompress SYN_STREAM #1
772 decompressed.reset(recv_framer.DecompressFrame(*syn_frame_1.get()));
773 EXPECT_TRUE(decompressed.get() != NULL);
774 EXPECT_TRUE(decompressed->is_control_frame());
775 EXPECT_EQ(SYN_STREAM,
776 reinterpret_cast<SpdyControlFrame*>(decompressed.get())->type());
777 decompressed_syn_frame.reset(
778 new SpdySynStreamControlFrame(decompressed->data(), false));
779 syn_frame = reinterpret_cast<SpdySynStreamControlFrame*>(
780 decompressed_syn_frame.get());
781 serialized_headers.reset(new std::string(syn_frame->header_block(),
782 syn_frame->header_block_len()));
783 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers->c_str(),
784 serialized_headers->size(),
785 &decompressed_headers));
786 EXPECT_EQ(2u, decompressed_headers.size());
787 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
788 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
790 // Decompress SYN_STREAM #2
791 decompressed.reset(recv_framer.DecompressFrame(*syn_frame_2.get()));
792 EXPECT_TRUE(decompressed.get() != NULL);
793 EXPECT_TRUE(decompressed->is_control_frame());
794 EXPECT_EQ(SYN_STREAM,
795 reinterpret_cast<SpdyControlFrame*>(decompressed.get())->type());
796 decompressed_syn_frame.reset(
797 new SpdySynStreamControlFrame(decompressed->data(), false));
798 syn_frame = reinterpret_cast<SpdySynStreamControlFrame*>(
799 decompressed_syn_frame.get());
800 serialized_headers.reset(new std::string(syn_frame->header_block(),
801 syn_frame->header_block_len()));
802 decompressed_headers.clear();
803 EXPECT_TRUE(recv_framer.ParseHeaderBlockInBuffer(serialized_headers->c_str(),
804 serialized_headers->size(),
805 &decompressed_headers));
806 EXPECT_EQ(3u, decompressed_headers.size());
807 EXPECT_EQ(kValue1, decompressed_headers[kHeader1]);
808 EXPECT_EQ(kValue2, decompressed_headers[kHeader2]);
809 EXPECT_EQ(kValue3, decompressed_headers[kHeader3]);
811 // We didn't have data streams, so we shouldn't have (de)compressors.
812 EXPECT_EQ(0, send_framer.num_stream_compressors());
813 EXPECT_EQ(0, send_framer.num_stream_decompressors());
814 EXPECT_EQ(0, recv_framer.num_stream_compressors());
815 EXPECT_EQ(0, recv_framer.num_stream_decompressors());
818 // Verify we don't leak when we leave streams unclosed
819 TEST_F(SpdyFramerTest, UnclosedStreamDataCompressors) {
820 SpdyFramer send_framer;
822 send_framer.set_enable_compression(true);
824 const char kHeader1[] = "header1";
825 const char kHeader2[] = "header2";
826 const char kValue1[] = "value1";
827 const char kValue2[] = "value2";
829 SpdyHeaderBlock block;
830 block[kHeader1] = kValue1;
831 block[kHeader2] = kValue2;
832 SpdyControlFlags flags(CONTROL_FLAG_NONE);
833 scoped_ptr<spdy::SpdyFrame> syn_frame(
834 send_framer.CreateSynStream(1, 0, 0, flags, true, &block));
835 EXPECT_TRUE(syn_frame.get() != NULL);
837 const char bytes[] = "this is a test test test test test!";
838 scoped_ptr<SpdyFrame> send_frame(
839 send_framer.CreateDataFrame(
840 1, bytes, arraysize(bytes),
841 DATA_FLAG_FIN));
842 EXPECT_TRUE(send_frame.get() != NULL);
844 // Run the inputs through the framer.
845 TestSpdyVisitor visitor;
846 visitor.use_compression_ = true;
847 const unsigned char* data;
848 data = reinterpret_cast<const unsigned char*>(syn_frame->data());
849 visitor.SimulateInFramer(data, syn_frame->length() + SpdyFrame::kHeaderSize);
850 data = reinterpret_cast<const unsigned char*>(send_frame->data());
851 visitor.SimulateInFramer(data, send_frame->length() + SpdyFrame::kHeaderSize);
853 EXPECT_EQ(0, visitor.error_count_);
854 EXPECT_EQ(1, visitor.syn_frame_count_);
855 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
856 EXPECT_EQ(0, visitor.headers_frame_count_);
857 EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_));
858 EXPECT_EQ(0, visitor.fin_frame_count_);
859 EXPECT_EQ(0, visitor.fin_flag_count_);
860 EXPECT_EQ(1, visitor.zero_length_data_frame_count_);
861 EXPECT_EQ(1, visitor.data_frame_count_);
863 // We closed the streams, so all compressors should be down.
864 EXPECT_EQ(0, visitor.framer_.num_stream_compressors());
865 EXPECT_EQ(0, visitor.framer_.num_stream_decompressors());
866 EXPECT_EQ(0, send_framer.num_stream_compressors());
867 EXPECT_EQ(0, send_framer.num_stream_decompressors());
870 TEST_F(SpdyFramerTest, WindowUpdateFrame) {
871 scoped_ptr<SpdyWindowUpdateControlFrame> window_update_frame(
872 SpdyFramer::CreateWindowUpdate(1, 0x12345678));
874 const unsigned char expected_data_frame[] = {
875 0x80, 0x02, 0x00, 0x09,
876 0x00, 0x00, 0x00, 0x08,
877 0x00, 0x00, 0x00, 0x01,
878 0x12, 0x34, 0x56, 0x78
881 EXPECT_EQ(16u, window_update_frame->size());
882 EXPECT_EQ(0,
883 memcmp(window_update_frame->data(), expected_data_frame, 16));
886 TEST_F(SpdyFramerTest, CreateDataFrame) {
887 SpdyFramer framer;
890 const char kDescription[] = "'hello' data frame, no FIN";
891 const unsigned char kFrameData[] = {
892 0x00, 0x00, 0x00, 0x01,
893 0x00, 0x00, 0x00, 0x05,
894 'h', 'e', 'l', 'l',
897 scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
898 1, "hello", 5, DATA_FLAG_NONE));
899 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
903 const char kDescription[] = "Data frame with negative data byte, no FIN";
904 const unsigned char kFrameData[] = {
905 0x00, 0x00, 0x00, 0x01,
906 0x00, 0x00, 0x00, 0x01,
907 0xff
909 scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
910 1, "\xff", 1, DATA_FLAG_NONE));
911 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
915 const char kDescription[] = "'hello' data frame, with FIN";
916 const unsigned char kFrameData[] = {
917 0x00, 0x00, 0x00, 0x01,
918 0x01, 0x00, 0x00, 0x05,
919 'h', 'e', 'l', 'l',
922 scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
923 1, "hello", 5, DATA_FLAG_FIN));
924 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
928 const char kDescription[] = "Empty data frame";
929 const unsigned char kFrameData[] = {
930 0x00, 0x00, 0x00, 0x01,
931 0x00, 0x00, 0x00, 0x00,
933 scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
934 1, "", 0, DATA_FLAG_NONE));
935 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
939 const char kDescription[] = "Data frame with max stream ID";
940 const unsigned char kFrameData[] = {
941 0x7f, 0xff, 0xff, 0xff,
942 0x01, 0x00, 0x00, 0x05,
943 'h', 'e', 'l', 'l',
946 scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
947 0x7fffffff, "hello", 5, DATA_FLAG_FIN));
948 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
952 const char kDescription[] = "Large data frame";
953 const int kDataSize = 4 * 1024 * 1024; // 4 MB
954 const std::string kData(kDataSize, 'A');
955 const unsigned char kFrameHeader[] = {
956 0x00, 0x00, 0x00, 0x01,
957 0x01, 0x40, 0x00, 0x00,
960 const int kFrameSize = arraysize(kFrameHeader) + kDataSize;
961 scoped_array<unsigned char> expected_frame_data(
962 new unsigned char[kFrameSize]);
963 memcpy(expected_frame_data.get(), kFrameHeader, arraysize(kFrameHeader));
964 memset(expected_frame_data.get() + arraysize(kFrameHeader), 'A', kDataSize);
966 scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
967 1, kData.data(), kData.size(), DATA_FLAG_FIN));
968 CompareFrame(kDescription, *frame, expected_frame_data.get(), kFrameSize);
972 TEST_F(SpdyFramerTest, CreateSynStreamUncompressed) {
973 SpdyFramer framer;
974 framer.set_enable_compression(false);
977 const char kDescription[] = "SYN_STREAM frame, lowest pri, no FIN";
979 SpdyHeaderBlock headers;
980 headers["bar"] = "foo";
981 headers["foo"] = "bar";
983 const unsigned char kFrameData[] = {
984 0x80, 0x02, 0x00, 0x01,
985 0x00, 0x00, 0x00, 0x20,
986 0x00, 0x00, 0x00, 0x01,
987 0x00, 0x00, 0x00, 0x00,
988 0xC0, 0x00, 0x00, 0x02,
989 0x00, 0x03, 'b', 'a',
990 'r', 0x00, 0x03, 'f',
991 'o', 'o', 0x00, 0x03,
992 'f', 'o', 'o', 0x00,
993 0x03, 'b', 'a', 'r'
995 scoped_ptr<SpdyFrame> frame(framer.CreateSynStream(
996 1, 0, SPDY_PRIORITY_LOWEST, CONTROL_FLAG_NONE,
997 false, &headers));
998 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
999 EXPECT_EQ(1u, SpdyFramer::GetControlFrameStreamId(
1000 reinterpret_cast<const SpdyControlFrame*>(frame.get())));
1004 const char kDescription[] =
1005 "SYN_STREAM frame with a 0-length header name, highest pri, FIN, "
1006 "max stream ID";
1008 SpdyHeaderBlock headers;
1009 headers[""] = "foo";
1010 headers["foo"] = "bar";
1012 const unsigned char kFrameData[] = {
1013 0x80, 0x02, 0x00, 0x01,
1014 0x01, 0x00, 0x00, 0x1D,
1015 0x7f, 0xff, 0xff, 0xff,
1016 0x7f, 0xff, 0xff, 0xff,
1017 0x00, 0x00, 0x00, 0x02,
1018 0x00, 0x00, 0x00, 0x03,
1019 'f', 'o', 'o', 0x00,
1020 0x03, 'f', 'o', 'o',
1021 0x00, 0x03, 'b', 'a',
1024 scoped_ptr<SpdyFrame> frame(framer.CreateSynStream(
1025 0x7fffffff, 0x7fffffff, SPDY_PRIORITY_HIGHEST, CONTROL_FLAG_FIN,
1026 false, &headers));
1027 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1031 const char kDescription[] =
1032 "SYN_STREAM frame with a 0-length header val, highest pri, FIN, "
1033 "max stream ID";
1035 SpdyHeaderBlock headers;
1036 headers["bar"] = "foo";
1037 headers["foo"] = "";
1039 const unsigned char kFrameData[] = {
1040 0x80, 0x02, 0x00, 0x01,
1041 0x01, 0x00, 0x00, 0x1D,
1042 0x7f, 0xff, 0xff, 0xff,
1043 0x7f, 0xff, 0xff, 0xff,
1044 0x00, 0x00, 0x00, 0x02,
1045 0x00, 0x03, 'b', 'a',
1046 'r', 0x00, 0x03, 'f',
1047 'o', 'o', 0x00, 0x03,
1048 'f', 'o', 'o', 0x00,
1049 0x00
1051 scoped_ptr<SpdyFrame> frame(framer.CreateSynStream(
1052 0x7fffffff, 0x7fffffff, SPDY_PRIORITY_HIGHEST, CONTROL_FLAG_FIN,
1053 false, &headers));
1054 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1058 TEST_F(SpdyFramerTest, CreateSynStreamCompressed) {
1059 SpdyFramer framer;
1060 framer.set_enable_compression(true);
1063 const char kDescription[] =
1064 "SYN_STREAM frame, lowest pri, no FIN";
1066 SpdyHeaderBlock headers;
1067 headers["bar"] = "foo";
1068 headers["foo"] = "bar";
1070 const unsigned char kFrameData[] = {
1071 0x80, 0x02, 0x00, 0x01,
1072 0x00, 0x00, 0x00, 0x25,
1073 0x00, 0x00, 0x00, 0x01,
1074 0x00, 0x00, 0x00, 0x00,
1075 0xC0, 0x00, 0x38, 0xea,
1076 0xdf, 0xa2, 0x51, 0xb2,
1077 0x62, 0x60, 0x62, 0x60,
1078 0x4e, 0x4a, 0x2c, 0x62,
1079 0x60, 0x4e, 0xcb, 0xcf,
1080 0x87, 0x12, 0x40, 0x2e,
1081 0x00, 0x00, 0x00, 0xff,
1082 0xff
1084 scoped_ptr<SpdyFrame> frame(framer.CreateSynStream(
1085 1, 0, SPDY_PRIORITY_LOWEST, CONTROL_FLAG_NONE,
1086 true, &headers));
1087 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1091 TEST_F(SpdyFramerTest, CreateSynReplyUncompressed) {
1092 SpdyFramer framer;
1093 framer.set_enable_compression(false);
1096 const char kDescription[] = "SYN_REPLY frame, no FIN";
1098 SpdyHeaderBlock headers;
1099 headers["bar"] = "foo";
1100 headers["foo"] = "bar";
1102 const unsigned char kFrameData[] = {
1103 0x80, 0x02, 0x00, 0x02,
1104 0x00, 0x00, 0x00, 0x1C,
1105 0x00, 0x00, 0x00, 0x01,
1106 0x00, 0x00, 0x00, 0x02,
1107 0x00, 0x03, 'b', 'a',
1108 'r', 0x00, 0x03, 'f',
1109 'o', 'o', 0x00, 0x03,
1110 'f', 'o', 'o', 0x00,
1111 0x03, 'b', 'a', 'r'
1113 scoped_ptr<SpdyFrame> frame(framer.CreateSynReply(
1114 1, CONTROL_FLAG_NONE, false, &headers));
1115 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1119 const char kDescription[] =
1120 "SYN_REPLY frame with a 0-length header name, FIN, max stream ID";
1122 SpdyHeaderBlock headers;
1123 headers[""] = "foo";
1124 headers["foo"] = "bar";
1126 const unsigned char kFrameData[] = {
1127 0x80, 0x02, 0x00, 0x02,
1128 0x01, 0x00, 0x00, 0x19,
1129 0x7f, 0xff, 0xff, 0xff,
1130 0x00, 0x00, 0x00, 0x02,
1131 0x00, 0x00, 0x00, 0x03,
1132 'f', 'o', 'o', 0x00,
1133 0x03, 'f', 'o', 'o',
1134 0x00, 0x03, 'b', 'a',
1137 scoped_ptr<SpdyFrame> frame(framer.CreateSynReply(
1138 0x7fffffff, CONTROL_FLAG_FIN, false, &headers));
1139 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1143 const char kDescription[] =
1144 "SYN_REPLY frame with a 0-length header val, FIN, max stream ID";
1146 SpdyHeaderBlock headers;
1147 headers["bar"] = "foo";
1148 headers["foo"] = "";
1150 const unsigned char kFrameData[] = {
1151 0x80, 0x02, 0x00, 0x02,
1152 0x01, 0x00, 0x00, 0x19,
1153 0x7f, 0xff, 0xff, 0xff,
1154 0x00, 0x00, 0x00, 0x02,
1155 0x00, 0x03, 'b', 'a',
1156 'r', 0x00, 0x03, 'f',
1157 'o', 'o', 0x00, 0x03,
1158 'f', 'o', 'o', 0x00,
1159 0x00
1161 scoped_ptr<SpdyFrame> frame(framer.CreateSynReply(
1162 0x7fffffff, CONTROL_FLAG_FIN, false, &headers));
1163 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1167 TEST_F(SpdyFramerTest, CreateSynReplyCompressed) {
1168 SpdyFramer framer;
1169 framer.set_enable_compression(true);
1172 const char kDescription[] = "SYN_REPLY frame, no FIN";
1174 SpdyHeaderBlock headers;
1175 headers["bar"] = "foo";
1176 headers["foo"] = "bar";
1178 const unsigned char kFrameData[] = {
1179 0x80, 0x02, 0x00, 0x02,
1180 0x00, 0x00, 0x00, 0x21,
1181 0x00, 0x00, 0x00, 0x01,
1182 0x00, 0x00, 0x38, 0xea,
1183 0xdf, 0xa2, 0x51, 0xb2,
1184 0x62, 0x60, 0x62, 0x60,
1185 0x4e, 0x4a, 0x2c, 0x62,
1186 0x60, 0x4e, 0xcb, 0xcf,
1187 0x87, 0x12, 0x40, 0x2e,
1188 0x00, 0x00, 0x00, 0xff,
1189 0xff
1191 scoped_ptr<SpdyFrame> frame(framer.CreateSynReply(
1192 1, CONTROL_FLAG_NONE, true, &headers));
1193 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1197 TEST_F(SpdyFramerTest, CreateRstStream) {
1198 SpdyFramer framer;
1201 const char kDescription[] = "RST_STREAM frame";
1202 const unsigned char kFrameData[] = {
1203 0x80, 0x02, 0x00, 0x03,
1204 0x00, 0x00, 0x00, 0x08,
1205 0x00, 0x00, 0x00, 0x01,
1206 0x00, 0x00, 0x00, 0x01,
1208 scoped_ptr<SpdyFrame> frame(framer.CreateRstStream(1, PROTOCOL_ERROR));
1209 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1210 EXPECT_EQ(1u, SpdyFramer::GetControlFrameStreamId(
1211 reinterpret_cast<const SpdyControlFrame*>(frame.get())));
1215 const char kDescription[] = "RST_STREAM frame with max stream ID";
1216 const unsigned char kFrameData[] = {
1217 0x80, 0x02, 0x00, 0x03,
1218 0x00, 0x00, 0x00, 0x08,
1219 0x7f, 0xff, 0xff, 0xff,
1220 0x00, 0x00, 0x00, 0x01,
1222 scoped_ptr<SpdyFrame> frame(framer.CreateRstStream(0x7FFFFFFF,
1223 PROTOCOL_ERROR));
1224 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1228 const char kDescription[] = "RST_STREAM frame with max status code";
1229 const unsigned char kFrameData[] = {
1230 0x80, 0x02, 0x00, 0x03,
1231 0x00, 0x00, 0x00, 0x08,
1232 0x7f, 0xff, 0xff, 0xff,
1233 0x00, 0x00, 0x00, 0x06,
1235 scoped_ptr<SpdyFrame> frame(framer.CreateRstStream(0x7FFFFFFF,
1236 INTERNAL_ERROR));
1237 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1241 TEST_F(SpdyFramerTest, CreateSettings) {
1242 SpdyFramer framer;
1245 const char kDescription[] = "Basic SETTINGS frame";
1247 SpdySettings settings;
1248 settings.push_back(SpdySetting(0x00000000, 0x00000000));
1249 settings.push_back(SpdySetting(0xffffffff, 0x00000001));
1250 settings.push_back(SpdySetting(0xff000001, 0x00000002));
1252 // Duplicates allowed
1253 settings.push_back(SpdySetting(0x01000002, 0x00000003));
1254 settings.push_back(SpdySetting(0x01000002, 0x00000003));
1256 settings.push_back(SpdySetting(0x01000003, 0x000000ff));
1257 settings.push_back(SpdySetting(0x01000004, 0xff000001));
1258 settings.push_back(SpdySetting(0x01000004, 0xffffffff));
1260 const unsigned char kFrameData[] = {
1261 0x80, 0x02, 0x00, 0x04,
1262 0x00, 0x00, 0x00, 0x44,
1263 0x00, 0x00, 0x00, 0x08,
1264 0x00, 0x00, 0x00, 0x00,
1265 0x00, 0x00, 0x00, 0x00,
1266 0xff, 0xff, 0xff, 0xff,
1267 0x00, 0x00, 0x00, 0x01,
1268 0xff, 0x00, 0x00, 0x01,
1269 0x00, 0x00, 0x00, 0x02,
1270 0x01, 0x00, 0x00, 0x02,
1271 0x00, 0x00, 0x00, 0x03,
1272 0x01, 0x00, 0x00, 0x02,
1273 0x00, 0x00, 0x00, 0x03,
1274 0x01, 0x00, 0x00, 0x03,
1275 0x00, 0x00, 0x00, 0xff,
1276 0x01, 0x00, 0x00, 0x04,
1277 0xff, 0x00, 0x00, 0x01,
1278 0x01, 0x00, 0x00, 0x04,
1279 0xff, 0xff, 0xff, 0xff,
1281 scoped_ptr<SpdyFrame> frame(framer.CreateSettings(settings));
1282 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1283 EXPECT_EQ(SpdyFramer::kInvalidStream,
1284 SpdyFramer::GetControlFrameStreamId(
1285 reinterpret_cast<const SpdyControlFrame*>(frame.get())));
1289 const char kDescription[] = "Empty SETTINGS frame";
1291 SpdySettings settings;
1293 const unsigned char kFrameData[] = {
1294 0x80, 0x02, 0x00, 0x04,
1295 0x00, 0x00, 0x00, 0x04,
1296 0x00, 0x00, 0x00, 0x00,
1298 scoped_ptr<SpdyFrame> frame(framer.CreateSettings(settings));
1299 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1303 TEST_F(SpdyFramerTest, CreateNopFrame) {
1304 SpdyFramer framer;
1307 const char kDescription[] = "NOOP frame";
1308 const unsigned char kFrameData[] = {
1309 0x80, 0x02, 0x00, 0x05,
1310 0x00, 0x00, 0x00, 0x00,
1312 scoped_ptr<SpdyFrame> frame(framer.CreateNopFrame());
1313 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1314 EXPECT_EQ(SpdyFramer::kInvalidStream,
1315 SpdyFramer::GetControlFrameStreamId(
1316 reinterpret_cast<const SpdyControlFrame*>(frame.get())));
1320 TEST_F(SpdyFramerTest, CreatePingFrame) {
1321 SpdyFramer framer;
1324 const char kDescription[] = "PING frame";
1325 const unsigned char kFrameData[] = {
1326 0x80, 0x02, 0x00, 0x06,
1327 0x00, 0x00, 0x00, 0x04,
1328 0x12, 0x34, 0x56, 0x78,
1330 scoped_ptr<SpdyFrame> frame(framer.CreatePingFrame(0x12345678u));
1331 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1332 EXPECT_EQ(SpdyFramer::kInvalidStream,
1333 SpdyFramer::GetControlFrameStreamId(
1334 reinterpret_cast<const SpdyControlFrame*>(frame.get())));
1338 TEST_F(SpdyFramerTest, CreateGoAway) {
1339 SpdyFramer framer;
1342 const char kDescription[] = "GOAWAY frame";
1343 const unsigned char kFrameData[] = {
1344 0x80, 0x02, 0x00, 0x07,
1345 0x00, 0x00, 0x00, 0x04,
1346 0x00, 0x00, 0x00, 0x00,
1348 scoped_ptr<SpdyFrame> frame(framer.CreateGoAway(0));
1349 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1350 EXPECT_EQ(SpdyFramer::kInvalidStream,
1351 SpdyFramer::GetControlFrameStreamId(
1352 reinterpret_cast<const SpdyControlFrame*>(frame.get())));
1356 const char kDescription[] = "GOAWAY frame with max stream ID";
1357 const unsigned char kFrameData[] = {
1358 0x80, 0x02, 0x00, 0x07,
1359 0x00, 0x00, 0x00, 0x04,
1360 0x7f, 0xff, 0xff, 0xff,
1362 scoped_ptr<SpdyFrame> frame(framer.CreateGoAway(0x7FFFFFFF));
1363 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1367 TEST_F(SpdyFramerTest, CreateHeadersUncompressed) {
1368 SpdyFramer framer;
1369 framer.set_enable_compression(false);
1372 const char kDescription[] = "HEADERS frame, no FIN";
1374 SpdyHeaderBlock headers;
1375 headers["bar"] = "foo";
1376 headers["foo"] = "bar";
1378 const unsigned char kFrameData[] = {
1379 0x80, 0x02, 0x00, 0x08,
1380 0x00, 0x00, 0x00, 0x1C,
1381 0x00, 0x00, 0x00, 0x01,
1382 0x00, 0x00, 0x00, 0x02,
1383 0x00, 0x03, 'b', 'a',
1384 'r', 0x00, 0x03, 'f',
1385 'o', 'o', 0x00, 0x03,
1386 'f', 'o', 'o', 0x00,
1387 0x03, 'b', 'a', 'r'
1389 scoped_ptr<SpdyFrame> frame(framer.CreateHeaders(
1390 1, CONTROL_FLAG_NONE, false, &headers));
1391 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1395 const char kDescription[] =
1396 "HEADERS frame with a 0-length header name, FIN, max stream ID";
1398 SpdyHeaderBlock headers;
1399 headers[""] = "foo";
1400 headers["foo"] = "bar";
1402 const unsigned char kFrameData[] = {
1403 0x80, 0x02, 0x00, 0x08,
1404 0x01, 0x00, 0x00, 0x19,
1405 0x7f, 0xff, 0xff, 0xff,
1406 0x00, 0x00, 0x00, 0x02,
1407 0x00, 0x00, 0x00, 0x03,
1408 'f', 'o', 'o', 0x00,
1409 0x03, 'f', 'o', 'o',
1410 0x00, 0x03, 'b', 'a',
1413 scoped_ptr<SpdyFrame> frame(framer.CreateHeaders(
1414 0x7fffffff, CONTROL_FLAG_FIN, false, &headers));
1415 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1419 const char kDescription[] =
1420 "HEADERS frame with a 0-length header val, FIN, max stream ID";
1422 SpdyHeaderBlock headers;
1423 headers["bar"] = "foo";
1424 headers["foo"] = "";
1426 const unsigned char kFrameData[] = {
1427 0x80, 0x02, 0x00, 0x08,
1428 0x01, 0x00, 0x00, 0x19,
1429 0x7f, 0xff, 0xff, 0xff,
1430 0x00, 0x00, 0x00, 0x02,
1431 0x00, 0x03, 'b', 'a',
1432 'r', 0x00, 0x03, 'f',
1433 'o', 'o', 0x00, 0x03,
1434 'f', 'o', 'o', 0x00,
1435 0x00
1437 scoped_ptr<SpdyFrame> frame(framer.CreateHeaders(
1438 0x7fffffff, CONTROL_FLAG_FIN, false, &headers));
1439 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1443 TEST_F(SpdyFramerTest, CreateHeadersCompressed) {
1444 SpdyFramer framer;
1445 framer.set_enable_compression(true);
1448 const char kDescription[] = "HEADERS frame, no FIN";
1450 SpdyHeaderBlock headers;
1451 headers["bar"] = "foo";
1452 headers["foo"] = "bar";
1454 const unsigned char kFrameData[] = {
1455 0x80, 0x02, 0x00, 0x08,
1456 0x00, 0x00, 0x00, 0x21,
1457 0x00, 0x00, 0x00, 0x01,
1458 0x00, 0x00, 0x38, 0xea,
1459 0xdf, 0xa2, 0x51, 0xb2,
1460 0x62, 0x60, 0x62, 0x60,
1461 0x4e, 0x4a, 0x2c, 0x62,
1462 0x60, 0x4e, 0xcb, 0xcf,
1463 0x87, 0x12, 0x40, 0x2e,
1464 0x00, 0x00, 0x00, 0xff,
1465 0xff
1467 scoped_ptr<SpdyFrame> frame(framer.CreateHeaders(
1468 1, CONTROL_FLAG_NONE, true, &headers));
1469 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1473 TEST_F(SpdyFramerTest, CreateWindowUpdate) {
1474 SpdyFramer framer;
1477 const char kDescription[] = "WINDOW_UPDATE frame";
1478 const unsigned char kFrameData[] = {
1479 0x80, 0x02, 0x00, 0x09,
1480 0x00, 0x00, 0x00, 0x08,
1481 0x00, 0x00, 0x00, 0x01,
1482 0x00, 0x00, 0x00, 0x01,
1484 scoped_ptr<SpdyFrame> frame(framer.CreateWindowUpdate(1, 1));
1485 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1486 EXPECT_EQ(1u, SpdyFramer::GetControlFrameStreamId(
1487 reinterpret_cast<const SpdyControlFrame*>(frame.get())));
1491 const char kDescription[] = "WINDOW_UPDATE frame with max stream ID";
1492 const unsigned char kFrameData[] = {
1493 0x80, 0x02, 0x00, 0x09,
1494 0x00, 0x00, 0x00, 0x08,
1495 0x7f, 0xff, 0xff, 0xff,
1496 0x00, 0x00, 0x00, 0x01,
1498 scoped_ptr<SpdyFrame> frame(framer.CreateWindowUpdate(0x7FFFFFFF, 1));
1499 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1503 const char kDescription[] = "WINDOW_UPDATE frame with max window delta";
1504 const unsigned char kFrameData[] = {
1505 0x80, 0x02, 0x00, 0x09,
1506 0x00, 0x00, 0x00, 0x08,
1507 0x00, 0x00, 0x00, 0x01,
1508 0x7f, 0xff, 0xff, 0xff,
1510 scoped_ptr<SpdyFrame> frame(framer.CreateWindowUpdate(1, 0x7FFFFFFF));
1511 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1515 TEST_F(SpdyFramerTest, CreateCredential) {
1516 SpdyFramer framer;
1519 const char kDescription[] = "CREDENTIAL frame";
1520 const unsigned char kFrameData[] = {
1521 0x80, 0x02, 0x00, 0x0A,
1522 0x00, 0x00, 0x00, 0x3F,
1523 0x00, 0x03, 0x00, 0x0A,
1524 'g', 'o', 'o', 'g',
1525 'l', 'e', '.', 'c',
1526 'o', 'm', 0x00, 0x00,
1527 0x00, 0x05, 'p', 'r',
1528 'o', 'o', 'f', 0x00,
1529 0x00, 0x00, 0x06, 'a',
1530 ' ', 'c', 'e', 'r',
1531 't', 0x00, 0x00, 0x00,
1532 0x0C, 'a', 'n', 'o',
1533 't', 'h', 'e', 'r',
1534 ' ', 'c', 'e', 'r',
1535 't', 0x00, 0x00, 0x00,
1536 0x0A, 'f', 'i', 'n',
1537 'a', 'l', ' ', 'c',
1538 'e', 'r', 't',
1540 SpdyCredential credential;
1541 credential.slot = 3;
1542 credential.origin = "google.com";
1543 credential.proof = "proof";
1544 credential.certs.push_back("a cert");
1545 credential.certs.push_back("another cert");
1546 credential.certs.push_back("final cert");
1547 scoped_ptr<SpdyFrame> frame(framer.CreateCredentialFrame(credential));
1548 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1552 TEST_F(SpdyFramerTest, ParseCredentialFrame) {
1553 SpdyFramer framer;
1556 unsigned char kFrameData[] = {
1557 0x80, 0x02, 0x00, 0x0A,
1558 0x00, 0x00, 0x00, 0x3F,
1559 0x00, 0x03, 0x00, 0x0A,
1560 'g', 'o', 'o', 'g',
1561 'l', 'e', '.', 'c',
1562 'o', 'm', 0x00, 0x00,
1563 0x00, 0x05, 'p', 'r',
1564 'o', 'o', 'f', 0x00,
1565 0x00, 0x00, 0x06, 'a',
1566 ' ', 'c', 'e', 'r',
1567 't', 0x00, 0x00, 0x00,
1568 0x0C, 'a', 'n', 'o',
1569 't', 'h', 'e', 'r',
1570 ' ', 'c', 'e', 'r',
1571 't', 0x00, 0x00, 0x00,
1572 0x0A, 'f', 'i', 'n',
1573 'a', 'l', ' ', 'c',
1574 'e', 'r', 't',
1576 SpdyCredentialControlFrame frame(reinterpret_cast<char*>(kFrameData),
1577 false);
1578 SpdyCredential credential;
1579 EXPECT_TRUE(SpdyFramer::ParseCredentialData(frame.payload(),
1580 frame.length(),
1581 &credential));
1582 EXPECT_EQ(3u, credential.slot);
1583 EXPECT_EQ("google.com", credential.origin);
1584 EXPECT_EQ("proof", credential.proof);
1585 EXPECT_EQ("a cert", credential.certs.front());
1586 credential.certs.erase(credential.certs.begin());
1587 EXPECT_EQ("another cert", credential.certs.front());
1588 credential.certs.erase(credential.certs.begin());
1589 EXPECT_EQ("final cert", credential.certs.front());
1590 credential.certs.erase(credential.certs.begin());
1591 EXPECT_TRUE(credential.certs.empty());
1595 TEST_F(SpdyFramerTest, DuplicateFrame) {
1596 SpdyFramer framer;
1599 const char kDescription[] = "PING frame";
1600 const unsigned char kFrameData[] = {
1601 0x80, 0x02, 0x00, 0x06,
1602 0x00, 0x00, 0x00, 0x04,
1603 0x12, 0x34, 0x56, 0x78,
1605 scoped_ptr<SpdyFrame> frame1(framer.CreatePingFrame(0x12345678u));
1606 CompareFrame(kDescription, *frame1, kFrameData, arraysize(kFrameData));
1608 scoped_ptr<SpdyFrame> frame2(framer.DuplicateFrame(*frame1));
1609 CompareFrame(kDescription, *frame2, kFrameData, arraysize(kFrameData));
1613 // This test case reproduces conditions that caused ExpandControlFrameBuffer to
1614 // fail to expand the buffer control frame buffer when it should have, allowing
1615 // the framer to overrun the buffer, and smash other heap contents. This test
1616 // relies on the debug version of the heap manager, which checks for buffer
1617 // overrun errors during delete processing. Regression test for b/2974814.
1618 TEST_F(SpdyFramerTest, ExpandBuffer_HeapSmash) {
1619 // Sweep through the area of problematic values, to make sure we always cover
1620 // the danger zone, even if it moves around at bit due to SPDY changes.
1621 for (uint16 val2_len = SpdyFramer::kControlFrameBufferInitialSize - 50;
1622 val2_len < SpdyFramer::kControlFrameBufferInitialSize;
1623 val2_len++) {
1624 std::string val2 = std::string(val2_len, 'a');
1625 SpdyHeaderBlock headers;
1626 headers["bar"] = "foo";
1627 headers["foo"] = "baz";
1628 headers["grue"] = val2.c_str();
1629 SpdyFramer framer;
1630 scoped_ptr<SpdySynStreamControlFrame> template_frame(
1631 framer.CreateSynStream(1, // stream_id
1632 0, // associated_stream_id
1633 1, // priority
1634 CONTROL_FLAG_NONE,
1635 false, // compress
1636 &headers));
1637 EXPECT_TRUE(template_frame.get() != NULL);
1638 TestSpdyVisitor visitor;
1639 visitor.SimulateInFramer(
1640 reinterpret_cast<unsigned char*>(template_frame.get()->data()),
1641 template_frame.get()->length() + SpdyControlFrame::kHeaderSize);
1642 EXPECT_EQ(1, visitor.syn_frame_count_);
1646 TEST_F(SpdyFramerTest, ReadCredentialFrame) {
1647 SpdyCredential credential;
1648 credential.slot = 3;
1649 credential.origin = "google.com";
1650 credential.proof = "proof";
1651 credential.certs.push_back("a cert");
1652 credential.certs.push_back("another cert");
1653 credential.certs.push_back("final cert");
1654 SpdyFramer framer;
1655 scoped_ptr<SpdyFrame> control_frame(
1656 framer.CreateCredentialFrame(credential));
1657 EXPECT_TRUE(control_frame.get() != NULL);
1658 TestSpdyVisitor visitor;
1659 visitor.use_compression_ = false;
1660 visitor.SimulateInFramer(
1661 reinterpret_cast<unsigned char*>(control_frame.get()->data()),
1662 control_frame.get()->length() + SpdyControlFrame::kHeaderSize);
1663 EXPECT_EQ(0, visitor.error_count_);
1664 EXPECT_EQ(1, visitor.credential_count_);
1665 EXPECT_EQ(control_frame->length(), visitor.credential_buffer_length_);
1666 EXPECT_EQ(credential.slot, visitor.credential_.slot);
1667 EXPECT_EQ(credential.origin, visitor.credential_.origin);
1668 EXPECT_EQ(credential.proof, visitor.credential_.proof);
1669 EXPECT_EQ(credential.certs.size(), visitor.credential_.certs.size());
1670 for (size_t i = 0; i < credential.certs.size(); i++) {
1671 EXPECT_EQ(credential.certs[i], visitor.credential_.certs[i]);
1675 TEST_F(SpdyFramerTest, ReadCredentialFrameWithCorruptOrigin) {
1676 SpdyCredential credential;
1677 credential.slot = 3;
1678 credential.origin = "google.com";
1679 credential.proof = "proof";
1680 credential.certs.push_back("a cert");
1681 credential.certs.push_back("another cert");
1682 credential.certs.push_back("final cert");
1683 SpdyFramer framer;
1684 scoped_ptr<SpdyFrame> control_frame(
1685 framer.CreateCredentialFrame(credential));
1686 EXPECT_TRUE(control_frame.get() != NULL);
1687 TestSpdyVisitor visitor;
1688 visitor.use_compression_ = false;
1689 unsigned char* data =
1690 reinterpret_cast<unsigned char*>(control_frame.get()->data());
1691 // Origin length is past the end of the frame
1692 data[SpdyControlFrame::kHeaderSize + 2] = 0xFF;
1693 visitor.SimulateInFramer(
1694 data, control_frame.get()->length() + SpdyControlFrame::kHeaderSize);
1695 EXPECT_EQ(1, visitor.error_count_);
1698 TEST_F(SpdyFramerTest, ReadCredentialFrameWithCorruptProof) {
1699 SpdyCredential credential;
1700 credential.slot = 3;
1701 credential.origin = "google.com";
1702 credential.proof = "proof";
1703 credential.certs.push_back("a cert");
1704 credential.certs.push_back("another cert");
1705 credential.certs.push_back("final cert");
1706 SpdyFramer framer;
1707 scoped_ptr<SpdyFrame> control_frame(
1708 framer.CreateCredentialFrame(credential));
1709 EXPECT_TRUE(control_frame.get() != NULL);
1710 TestSpdyVisitor visitor;
1711 visitor.use_compression_ = false;
1712 unsigned char* data =
1713 reinterpret_cast<unsigned char*>(control_frame.get()->data());
1714 size_t offset = SpdyControlFrame::kHeaderSize + 4 +
1715 credential.origin.length();
1716 data[offset] = 0xFF; // Proof length is past the end of the frame
1717 visitor.SimulateInFramer(
1718 data, control_frame.get()->length() + SpdyControlFrame::kHeaderSize);
1719 EXPECT_EQ(1, visitor.error_count_);
1722 TEST_F(SpdyFramerTest, ReadCredentialFrameWithCorruptCertificate) {
1723 SpdyCredential credential;
1724 credential.slot = 3;
1725 credential.origin = "google.com";
1726 credential.proof = "proof";
1727 credential.certs.push_back("a cert");
1728 credential.certs.push_back("another cert");
1729 credential.certs.push_back("final cert");
1730 SpdyFramer framer;
1731 scoped_ptr<SpdyFrame> control_frame(
1732 framer.CreateCredentialFrame(credential));
1733 EXPECT_TRUE(control_frame.get() != NULL);
1734 TestSpdyVisitor visitor;
1735 visitor.use_compression_ = false;
1736 unsigned char* data =
1737 reinterpret_cast<unsigned char*>(control_frame.get()->data());
1738 size_t offset = SpdyControlFrame::kHeaderSize + 4 +
1739 credential.origin.length() + 4 + credential.proof.length();
1740 data[offset] = 0xFF; // Certificate length is past the end of the frame
1741 visitor.SimulateInFramer(
1742 data, control_frame.get()->length() + SpdyControlFrame::kHeaderSize);
1743 EXPECT_EQ(1, visitor.error_count_);
1746 TEST_F(SpdyFramerTest, ReadGarbage) {
1747 SpdyFramer framer;
1748 unsigned char garbage_frame[256];
1749 memset(garbage_frame, ~0, sizeof(garbage_frame));
1750 TestSpdyVisitor visitor;
1751 visitor.use_compression_ = false;
1752 visitor.SimulateInFramer(garbage_frame, sizeof(garbage_frame));
1753 EXPECT_EQ(1, visitor.error_count_);
1756 TEST_F(SpdyFramerTest, ReadGarbageWithValidVersion) {
1757 SpdyFramer framer;
1758 char garbage_frame[256];
1759 memset(garbage_frame, ~0, sizeof(garbage_frame));
1760 SpdyControlFrame control_frame(&garbage_frame[0], false);
1761 control_frame.set_version(kSpdyProtocolVersion);
1762 TestSpdyVisitor visitor;
1763 visitor.use_compression_ = false;
1764 visitor.SimulateInFramer(
1765 reinterpret_cast<unsigned char*>(control_frame.data()),
1766 sizeof(garbage_frame));
1767 EXPECT_EQ(1, visitor.error_count_);
1770 TEST(SpdyFramer, StateToStringTest) {
1771 EXPECT_STREQ("ERROR",
1772 SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR));
1773 EXPECT_STREQ("DONE",
1774 SpdyFramer::StateToString(SpdyFramer::SPDY_DONE));
1775 EXPECT_STREQ("AUTO_RESET",
1776 SpdyFramer::StateToString(SpdyFramer::SPDY_AUTO_RESET));
1777 EXPECT_STREQ("RESET",
1778 SpdyFramer::StateToString(SpdyFramer::SPDY_RESET));
1779 EXPECT_STREQ("READING_COMMON_HEADER",
1780 SpdyFramer::StateToString(
1781 SpdyFramer::SPDY_READING_COMMON_HEADER));
1782 EXPECT_STREQ("CONTROL_FRAME_PAYLOAD",
1783 SpdyFramer::StateToString(
1784 SpdyFramer::SPDY_CONTROL_FRAME_PAYLOAD));
1785 EXPECT_STREQ("IGNORE_REMAINING_PAYLOAD",
1786 SpdyFramer::StateToString(
1787 SpdyFramer::SPDY_IGNORE_REMAINING_PAYLOAD));
1788 EXPECT_STREQ("FORWARD_STREAM_FRAME",
1789 SpdyFramer::StateToString(
1790 SpdyFramer::SPDY_FORWARD_STREAM_FRAME));
1791 EXPECT_STREQ("SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK",
1792 SpdyFramer::StateToString(
1793 SpdyFramer::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK));
1794 EXPECT_STREQ("SPDY_CONTROL_FRAME_HEADER_BLOCK",
1795 SpdyFramer::StateToString(
1796 SpdyFramer::SPDY_CONTROL_FRAME_HEADER_BLOCK));
1797 EXPECT_STREQ("SPDY_CREDENTIAL_FRAME_PAYLOAD",
1798 SpdyFramer::StateToString(
1799 SpdyFramer::SPDY_CREDENTIAL_FRAME_PAYLOAD));
1800 EXPECT_STREQ("UNKNOWN_STATE",
1801 SpdyFramer::StateToString(
1802 SpdyFramer::SPDY_CREDENTIAL_FRAME_PAYLOAD + 1));
1805 TEST(SpdyFramer, ErrorCodeToStringTest) {
1806 EXPECT_STREQ("NO_ERROR",
1807 SpdyFramer::ErrorCodeToString(SpdyFramer::SPDY_NO_ERROR));
1808 EXPECT_STREQ("INVALID_CONTROL_FRAME",
1809 SpdyFramer::ErrorCodeToString(
1810 SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
1811 EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
1812 SpdyFramer::ErrorCodeToString(
1813 SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
1814 EXPECT_STREQ("ZLIB_INIT_FAILURE",
1815 SpdyFramer::ErrorCodeToString(
1816 SpdyFramer::SPDY_ZLIB_INIT_FAILURE));
1817 EXPECT_STREQ("UNSUPPORTED_VERSION",
1818 SpdyFramer::ErrorCodeToString(
1819 SpdyFramer::SPDY_UNSUPPORTED_VERSION));
1820 EXPECT_STREQ("DECOMPRESS_FAILURE",
1821 SpdyFramer::ErrorCodeToString(
1822 SpdyFramer::SPDY_DECOMPRESS_FAILURE));
1823 EXPECT_STREQ("COMPRESS_FAILURE",
1824 SpdyFramer::ErrorCodeToString(
1825 SpdyFramer::SPDY_COMPRESS_FAILURE));
1826 EXPECT_STREQ("UNKNOWN_ERROR",
1827 SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR));
1830 TEST(SpdyFramer, StatusCodeToStringTest) {
1831 EXPECT_STREQ("INVALID",
1832 SpdyFramer::StatusCodeToString(INVALID));
1833 EXPECT_STREQ("PROTOCOL_ERROR",
1834 SpdyFramer::StatusCodeToString(PROTOCOL_ERROR));
1835 EXPECT_STREQ("INVALID_STREAM",
1836 SpdyFramer::StatusCodeToString(INVALID_STREAM));
1837 EXPECT_STREQ("REFUSED_STREAM",
1838 SpdyFramer::StatusCodeToString(REFUSED_STREAM));
1839 EXPECT_STREQ("UNSUPPORTED_VERSION",
1840 SpdyFramer::StatusCodeToString(UNSUPPORTED_VERSION));
1841 EXPECT_STREQ("CANCEL",
1842 SpdyFramer::StatusCodeToString(CANCEL));
1843 EXPECT_STREQ("INTERNAL_ERROR",
1844 SpdyFramer::StatusCodeToString(INTERNAL_ERROR));
1845 EXPECT_STREQ("FLOW_CONTROL_ERROR",
1846 SpdyFramer::StatusCodeToString(FLOW_CONTROL_ERROR));
1847 EXPECT_STREQ("UNKNOWN_STATUS",
1848 SpdyFramer::StatusCodeToString(NUM_STATUS_CODES));
1851 TEST(SpdyFramer, ControlTypeToStringTest) {
1852 EXPECT_STREQ("SYN_STREAM",
1853 SpdyFramer::ControlTypeToString(SYN_STREAM));
1854 EXPECT_STREQ("SYN_REPLY",
1855 SpdyFramer::ControlTypeToString(SYN_REPLY));
1856 EXPECT_STREQ("RST_STREAM",
1857 SpdyFramer::ControlTypeToString(RST_STREAM));
1858 EXPECT_STREQ("SETTINGS",
1859 SpdyFramer::ControlTypeToString(SETTINGS));
1860 EXPECT_STREQ("NOOP",
1861 SpdyFramer::ControlTypeToString(NOOP));
1862 EXPECT_STREQ("PING",
1863 SpdyFramer::ControlTypeToString(PING));
1864 EXPECT_STREQ("GOAWAY",
1865 SpdyFramer::ControlTypeToString(GOAWAY));
1866 EXPECT_STREQ("HEADERS",
1867 SpdyFramer::ControlTypeToString(HEADERS));
1868 EXPECT_STREQ("WINDOW_UPDATE",
1869 SpdyFramer::ControlTypeToString(WINDOW_UPDATE));
1870 EXPECT_STREQ("SETTINGS",
1871 SpdyFramer::ControlTypeToString(SETTINGS));
1872 EXPECT_STREQ("UNKNOWN_CONTROL_TYPE",
1873 SpdyFramer::ControlTypeToString(NUM_CONTROL_FRAME_TYPES));
1876 TEST(SpdyFramer, GetMinimumControlFrameSizeTest) {
1877 EXPECT_EQ(SpdySynStreamControlFrame::size(),
1878 SpdyFramer::GetMinimumControlFrameSize(SYN_STREAM));
1879 EXPECT_EQ(SpdySynReplyControlFrame::size(),
1880 SpdyFramer::GetMinimumControlFrameSize(SYN_REPLY));
1881 EXPECT_EQ(SpdyRstStreamControlFrame::size(),
1882 SpdyFramer::GetMinimumControlFrameSize(RST_STREAM));
1883 EXPECT_EQ(SpdySettingsControlFrame::size(),
1884 SpdyFramer::GetMinimumControlFrameSize(SETTINGS));
1885 EXPECT_EQ(SpdyNoOpControlFrame::size(),
1886 SpdyFramer::GetMinimumControlFrameSize(NOOP));
1887 EXPECT_EQ(SpdyPingControlFrame::size(),
1888 SpdyFramer::GetMinimumControlFrameSize(PING));
1889 EXPECT_EQ(SpdyGoAwayControlFrame::size(),
1890 SpdyFramer::GetMinimumControlFrameSize(GOAWAY));
1891 EXPECT_EQ(SpdyHeadersControlFrame::size(),
1892 SpdyFramer::GetMinimumControlFrameSize(HEADERS));
1893 EXPECT_EQ(SpdyWindowUpdateControlFrame::size(),
1894 SpdyFramer::GetMinimumControlFrameSize(WINDOW_UPDATE));
1895 EXPECT_EQ(SpdyCredentialControlFrame::size(),
1896 SpdyFramer::GetMinimumControlFrameSize(CREDENTIAL));
1897 EXPECT_EQ(static_cast<size_t>(0x7FFFFFFF),
1898 SpdyFramer::GetMinimumControlFrameSize(NUM_CONTROL_FRAME_TYPES));
1901 std::string RandomString(int length) {
1902 std::string rv;
1903 for (int index = 0; index < length; index++)
1904 rv += static_cast<char>('a' + (rand() % 26));
1905 return rv;
1908 } // namespace