Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Side by Side Diff: net/spdy/spdy_framer_test.cc

Issue 9618002: SPDY - integration of spdy/3 code. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/spdy/spdy_framer_spdy3_test.cc ('k') | net/spdy/spdy_http_stream_spdy2_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
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"
13
14 namespace spdy {
15
16 namespace test {
17
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;
22
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);
28 }
29
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 += " ";
43 }
44 }
45 hex = hex + " ";
46
47 for (const unsigned char *p = row; p < row + 4 && p < row + length; ++p)
48 hex += (*p >= 0x20 && *p <= 0x7f) ? (*p) : '.';
49
50 hex = hex + '\n';
51 }
52 return hex;
53 }
54
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;
71 }
72 }
73 for (int i = min_len; i < max_len; ++i) {
74 marks[i] = true;
75 }
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);
84 }
85
86 class TestSpdyVisitor : public SpdyFramerVisitorInterface {
87 public:
88 static const size_t kDefaultHeaderBufferSize = 64 * 1024;
89 static const size_t kDefaultCredentialBufferSize = 16 * 1024;
90
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) {
116 }
117
118 void OnError(SpdyFramer* f) {
119 LOG(INFO) << "SpdyFramer Error: "
120 << SpdyFramer::ErrorCodeToString(f->error_code());
121 error_count_++;
122 }
123
124 void OnDataFrameHeader(const SpdyDataFrame* frame) {
125 data_frame_count_++;
126 header_stream_id_ = frame->stream_id();
127 }
128
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_;
135
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;
141 }
142 }
143 std::cerr << "\", " << len << ")\n";
144 }
145
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!
171 }
172 if (frame->flags() & CONTROL_FLAG_FIN)
173 ++fin_flag_count_;
174 }
175
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;
189 }
190 const size_t available = header_buffer_size_ - header_buffer_length_;
191 if (len > available) {
192 header_buffer_valid_ = false;
193 return false;
194 }
195 memcpy(header_buffer_.get() + header_buffer_length_, header_data, len);
196 header_buffer_length_ += len;
197 return true;
198 }
199
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_;
206 }
207 return true;
208 }
209 const size_t available =
210 credential_buffer_size_ - credential_buffer_length_;
211 if (len > available) {
212 return false;
213 }
214 memcpy(credential_buffer_.get() + credential_buffer_length_,
215 credential_data, len);
216 credential_buffer_length_ += len;
217 return true;
218 }
219
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();
239 }
240 }
241
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);
249 }
250
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]);
255 }
256
257 static size_t control_frame_buffer_max_size() {
258 return SpdyFramer::kControlFrameBufferMaxSize;
259 }
260
261 static size_t header_data_chunk_max_size() {
262 return SpdyFramer::kHeaderDataChunkMaxSize;
263 }
264
265 SpdyFramer framer_;
266 bool use_compression_;
267
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_;
284
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_;
293
294 scoped_array<char> credential_buffer_;
295 size_t credential_buffer_length_;
296 size_t credential_buffer_size_;
297 SpdyCredential credential_;
298 };
299
300 } // namespace test
301
302 } // namespace spdy
303
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;
320
321 namespace spdy {
322
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());
329
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()));
336 }
337
338 class SpdyFramerTest : public PlatformTest {
339 public:
340 virtual void TearDown() {}
341
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);
352 }
353
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;
361 }
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;
370 }
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;
377 }
378 }
379 return true;
380 }
381 };
382
383
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;
390
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));
401
402 EXPECT_EQ(headers.size(), new_headers.size());
403 EXPECT_EQ(headers["alpha"], new_headers["alpha"]);
404 EXPECT_EQ(headers["gamma"], new_headers["gamma"]);
405 }
406
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;
413
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);
418
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));
425 }
426
427 TEST_F(SpdyFramerTest, OutOfOrderHeaders) {
428 // Frame builder with plentiful buffer size.
429 SpdyFrameBuilder frame(1024);
430
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.
437
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);
446
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));
457 }
458
459 TEST_F(SpdyFramerTest, DuplicateHeader) {
460 // Frame builder with plentiful buffer size.
461 SpdyFrameBuilder frame(1024);
462
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.
469
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);
478
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));
490 }
491
492 TEST_F(SpdyFramerTest, MultiValueHeader) {
493 // Frame builder with plentiful buffer size.
494 SpdyFrameBuilder frame(1024);
495
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.
502
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);
510
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);
523 }
524
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";
533
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));
542
543 // Expect the second frame to be more compact than the first.
544 EXPECT_LE(frame2->length(), frame1->length());
545
546 // Decompress the first frame
547 scoped_ptr<SpdyFrame> frame3(framer.DecompressFrame(*frame1.get()));
548
549 // Decompress the second frame
550 scoped_ptr<SpdyFrame> frame4(framer.DecompressFrame(*frame2.get()));
551
552 // Expect frames 3 & 4 to be the same.
553 EXPECT_EQ(0,
554 memcmp(frame3->data(), frame4->data(),
555 SpdyFrame::kHeaderSize + frame3->length()));
556
557
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()));
567 }
568
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";
577
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));
583
584 // Decompress the frame
585 scoped_ptr<SpdyFrame> frame2(framer.DecompressFrame(*frame1.get()));
586
587 EXPECT_EQ(NULL, frame2.get());
588 }
589
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',
599
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',
608
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,
614
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,
620
621 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
622 0x00, 0x00, 0x00, 0x08,
623 0xde, 0xad, 0xbe, 0xef,
624 0xde, 0xad, 0xbe, 0xef,
625
626 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1
627 0x00, 0x00, 0x00, 0x04,
628 0xde, 0xad, 0xbe, 0xef,
629
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,
634
635 0x00, 0x00, 0x00, 0x03, // DATA on Stream #3
636 0x00, 0x00, 0x00, 0x00,
637
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,
642 };
643
644 TestSpdyVisitor visitor;
645 visitor.SimulateInFramer(input, sizeof(input));
646
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_);
656 }
657
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',
668
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',
675
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,
681
682 0x00, 0x00, 0x00, 0x01, // DATA on Stream #1, with EOF
683 0x01, 0x00, 0x00, 0x04,
684 0xde, 0xad, 0xbe, 0xef,
685 };
686
687 TestSpdyVisitor visitor;
688 visitor.SimulateInFramer(input, sizeof(input));
689
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_);
699 }
700
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',
711
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',
719 };
720
721 TestSpdyVisitor visitor;
722 visitor.SimulateInFramer(input, sizeof(input));
723
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_);
733 }
734
735 TEST_F(SpdyFramerTest, HeaderCompression) {
736 SpdyFramer send_framer;
737 SpdyFramer recv_framer;
738
739 send_framer.set_enable_compression(true);
740 recv_framer.set_enable_compression(true);
741
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";
748
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);
757
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);
763
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;
770
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]);
789
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]);
810
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());
816 }
817
818 // Verify we don't leak when we leave streams unclosed
819 TEST_F(SpdyFramerTest, UnclosedStreamDataCompressors) {
820 SpdyFramer send_framer;
821
822 send_framer.set_enable_compression(true);
823
824 const char kHeader1[] = "header1";
825 const char kHeader2[] = "header2";
826 const char kValue1[] = "value1";
827 const char kValue2[] = "value2";
828
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);
836
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);
843
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);
852
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_);
862
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());
868 }
869
870 TEST_F(SpdyFramerTest, WindowUpdateFrame) {
871 scoped_ptr<SpdyWindowUpdateControlFrame> window_update_frame(
872 SpdyFramer::CreateWindowUpdate(1, 0x12345678));
873
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
879 };
880
881 EXPECT_EQ(16u, window_update_frame->size());
882 EXPECT_EQ(0,
883 memcmp(window_update_frame->data(), expected_data_frame, 16));
884 }
885
886 TEST_F(SpdyFramerTest, CreateDataFrame) {
887 SpdyFramer framer;
888
889 {
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',
895 'o'
896 };
897 scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
898 1, "hello", 5, DATA_FLAG_NONE));
899 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
900 }
901
902 {
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
908 };
909 scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
910 1, "\xff", 1, DATA_FLAG_NONE));
911 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
912 }
913
914 {
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',
920 'o'
921 };
922 scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
923 1, "hello", 5, DATA_FLAG_FIN));
924 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
925 }
926
927 {
928 const char kDescription[] = "Empty data frame";
929 const unsigned char kFrameData[] = {
930 0x00, 0x00, 0x00, 0x01,
931 0x00, 0x00, 0x00, 0x00,
932 };
933 scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
934 1, "", 0, DATA_FLAG_NONE));
935 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
936 }
937
938 {
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',
944 'o'
945 };
946 scoped_ptr<SpdyFrame> frame(framer.CreateDataFrame(
947 0x7fffffff, "hello", 5, DATA_FLAG_FIN));
948 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
949 }
950
951 {
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,
958 };
959
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);
965
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);
969 }
970 }
971
972 TEST_F(SpdyFramerTest, CreateSynStreamUncompressed) {
973 SpdyFramer framer;
974 framer.set_enable_compression(false);
975
976 {
977 const char kDescription[] = "SYN_STREAM frame, lowest pri, no FIN";
978
979 SpdyHeaderBlock headers;
980 headers["bar"] = "foo";
981 headers["foo"] = "bar";
982
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'
994 };
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())));
1001 }
1002
1003 {
1004 const char kDescription[] =
1005 "SYN_STREAM frame with a 0-length header name, highest pri, FIN, "
1006 "max stream ID";
1007
1008 SpdyHeaderBlock headers;
1009 headers[""] = "foo";
1010 headers["foo"] = "bar";
1011
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',
1022 'r'
1023 };
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));
1028 }
1029
1030 {
1031 const char kDescription[] =
1032 "SYN_STREAM frame with a 0-length header val, highest pri, FIN, "
1033 "max stream ID";
1034
1035 SpdyHeaderBlock headers;
1036 headers["bar"] = "foo";
1037 headers["foo"] = "";
1038
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
1050 };
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));
1055 }
1056 }
1057
1058 TEST_F(SpdyFramerTest, CreateSynStreamCompressed) {
1059 SpdyFramer framer;
1060 framer.set_enable_compression(true);
1061
1062 {
1063 const char kDescription[] =
1064 "SYN_STREAM frame, lowest pri, no FIN";
1065
1066 SpdyHeaderBlock headers;
1067 headers["bar"] = "foo";
1068 headers["foo"] = "bar";
1069
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
1083 };
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));
1088 }
1089 }
1090
1091 TEST_F(SpdyFramerTest, CreateSynReplyUncompressed) {
1092 SpdyFramer framer;
1093 framer.set_enable_compression(false);
1094
1095 {
1096 const char kDescription[] = "SYN_REPLY frame, no FIN";
1097
1098 SpdyHeaderBlock headers;
1099 headers["bar"] = "foo";
1100 headers["foo"] = "bar";
1101
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'
1112 };
1113 scoped_ptr<SpdyFrame> frame(framer.CreateSynReply(
1114 1, CONTROL_FLAG_NONE, false, &headers));
1115 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1116 }
1117
1118 {
1119 const char kDescription[] =
1120 "SYN_REPLY frame with a 0-length header name, FIN, max stream ID";
1121
1122 SpdyHeaderBlock headers;
1123 headers[""] = "foo";
1124 headers["foo"] = "bar";
1125
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',
1135 'r'
1136 };
1137 scoped_ptr<SpdyFrame> frame(framer.CreateSynReply(
1138 0x7fffffff, CONTROL_FLAG_FIN, false, &headers));
1139 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1140 }
1141
1142 {
1143 const char kDescription[] =
1144 "SYN_REPLY frame with a 0-length header val, FIN, max stream ID";
1145
1146 SpdyHeaderBlock headers;
1147 headers["bar"] = "foo";
1148 headers["foo"] = "";
1149
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
1160 };
1161 scoped_ptr<SpdyFrame> frame(framer.CreateSynReply(
1162 0x7fffffff, CONTROL_FLAG_FIN, false, &headers));
1163 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1164 }
1165 }
1166
1167 TEST_F(SpdyFramerTest, CreateSynReplyCompressed) {
1168 SpdyFramer framer;
1169 framer.set_enable_compression(true);
1170
1171 {
1172 const char kDescription[] = "SYN_REPLY frame, no FIN";
1173
1174 SpdyHeaderBlock headers;
1175 headers["bar"] = "foo";
1176 headers["foo"] = "bar";
1177
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
1190 };
1191 scoped_ptr<SpdyFrame> frame(framer.CreateSynReply(
1192 1, CONTROL_FLAG_NONE, true, &headers));
1193 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1194 }
1195 }
1196
1197 TEST_F(SpdyFramerTest, CreateRstStream) {
1198 SpdyFramer framer;
1199
1200 {
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,
1207 };
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())));
1212 }
1213
1214 {
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,
1221 };
1222 scoped_ptr<SpdyFrame> frame(framer.CreateRstStream(0x7FFFFFFF,
1223 PROTOCOL_ERROR));
1224 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1225 }
1226
1227 {
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,
1234 };
1235 scoped_ptr<SpdyFrame> frame(framer.CreateRstStream(0x7FFFFFFF,
1236 INTERNAL_ERROR));
1237 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1238 }
1239 }
1240
1241 TEST_F(SpdyFramerTest, CreateSettings) {
1242 SpdyFramer framer;
1243
1244 {
1245 const char kDescription[] = "Basic SETTINGS frame";
1246
1247 SpdySettings settings;
1248 settings.push_back(SpdySetting(0x00000000, 0x00000000));
1249 settings.push_back(SpdySetting(0xffffffff, 0x00000001));
1250 settings.push_back(SpdySetting(0xff000001, 0x00000002));
1251
1252 // Duplicates allowed
1253 settings.push_back(SpdySetting(0x01000002, 0x00000003));
1254 settings.push_back(SpdySetting(0x01000002, 0x00000003));
1255
1256 settings.push_back(SpdySetting(0x01000003, 0x000000ff));
1257 settings.push_back(SpdySetting(0x01000004, 0xff000001));
1258 settings.push_back(SpdySetting(0x01000004, 0xffffffff));
1259
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,
1280 };
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())));
1286 }
1287
1288 {
1289 const char kDescription[] = "Empty SETTINGS frame";
1290
1291 SpdySettings settings;
1292
1293 const unsigned char kFrameData[] = {
1294 0x80, 0x02, 0x00, 0x04,
1295 0x00, 0x00, 0x00, 0x04,
1296 0x00, 0x00, 0x00, 0x00,
1297 };
1298 scoped_ptr<SpdyFrame> frame(framer.CreateSettings(settings));
1299 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1300 }
1301 }
1302
1303 TEST_F(SpdyFramerTest, CreateNopFrame) {
1304 SpdyFramer framer;
1305
1306 {
1307 const char kDescription[] = "NOOP frame";
1308 const unsigned char kFrameData[] = {
1309 0x80, 0x02, 0x00, 0x05,
1310 0x00, 0x00, 0x00, 0x00,
1311 };
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())));
1317 }
1318 }
1319
1320 TEST_F(SpdyFramerTest, CreatePingFrame) {
1321 SpdyFramer framer;
1322
1323 {
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,
1329 };
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())));
1335 }
1336 }
1337
1338 TEST_F(SpdyFramerTest, CreateGoAway) {
1339 SpdyFramer framer;
1340
1341 {
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,
1347 };
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())));
1353 }
1354
1355 {
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,
1361 };
1362 scoped_ptr<SpdyFrame> frame(framer.CreateGoAway(0x7FFFFFFF));
1363 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1364 }
1365 }
1366
1367 TEST_F(SpdyFramerTest, CreateHeadersUncompressed) {
1368 SpdyFramer framer;
1369 framer.set_enable_compression(false);
1370
1371 {
1372 const char kDescription[] = "HEADERS frame, no FIN";
1373
1374 SpdyHeaderBlock headers;
1375 headers["bar"] = "foo";
1376 headers["foo"] = "bar";
1377
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'
1388 };
1389 scoped_ptr<SpdyFrame> frame(framer.CreateHeaders(
1390 1, CONTROL_FLAG_NONE, false, &headers));
1391 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1392 }
1393
1394 {
1395 const char kDescription[] =
1396 "HEADERS frame with a 0-length header name, FIN, max stream ID";
1397
1398 SpdyHeaderBlock headers;
1399 headers[""] = "foo";
1400 headers["foo"] = "bar";
1401
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',
1411 'r'
1412 };
1413 scoped_ptr<SpdyFrame> frame(framer.CreateHeaders(
1414 0x7fffffff, CONTROL_FLAG_FIN, false, &headers));
1415 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1416 }
1417
1418 {
1419 const char kDescription[] =
1420 "HEADERS frame with a 0-length header val, FIN, max stream ID";
1421
1422 SpdyHeaderBlock headers;
1423 headers["bar"] = "foo";
1424 headers["foo"] = "";
1425
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
1436 };
1437 scoped_ptr<SpdyFrame> frame(framer.CreateHeaders(
1438 0x7fffffff, CONTROL_FLAG_FIN, false, &headers));
1439 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1440 }
1441 }
1442
1443 TEST_F(SpdyFramerTest, CreateHeadersCompressed) {
1444 SpdyFramer framer;
1445 framer.set_enable_compression(true);
1446
1447 {
1448 const char kDescription[] = "HEADERS frame, no FIN";
1449
1450 SpdyHeaderBlock headers;
1451 headers["bar"] = "foo";
1452 headers["foo"] = "bar";
1453
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
1466 };
1467 scoped_ptr<SpdyFrame> frame(framer.CreateHeaders(
1468 1, CONTROL_FLAG_NONE, true, &headers));
1469 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1470 }
1471 }
1472
1473 TEST_F(SpdyFramerTest, CreateWindowUpdate) {
1474 SpdyFramer framer;
1475
1476 {
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,
1483 };
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())));
1488 }
1489
1490 {
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,
1497 };
1498 scoped_ptr<SpdyFrame> frame(framer.CreateWindowUpdate(0x7FFFFFFF, 1));
1499 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1500 }
1501
1502 {
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,
1509 };
1510 scoped_ptr<SpdyFrame> frame(framer.CreateWindowUpdate(1, 0x7FFFFFFF));
1511 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1512 }
1513 }
1514
1515 TEST_F(SpdyFramerTest, CreateCredential) {
1516 SpdyFramer framer;
1517
1518 {
1519 const char kDescription[] = "CREDENTIAL frame";
1520 const unsigned char kFrameData[] = {
1521 0x80, 0x02, 0x00, 0x0A,
1522 0x00, 0x00, 0x00, 0x33,
1523 0x00, 0x03, 0x00, 0x00,
1524 0x00, 0x05, 'p', 'r',
1525 'o', 'o', 'f', 0x00,
1526 0x00, 0x00, 0x06, 'a',
1527 ' ', 'c', 'e', 'r',
1528 't', 0x00, 0x00, 0x00,
1529 0x0C, 'a', 'n', 'o',
1530 't', 'h', 'e', 'r',
1531 ' ', 'c', 'e', 'r',
1532 't', 0x00, 0x00, 0x00,
1533 0x0A, 'f', 'i', 'n',
1534 'a', 'l', ' ', 'c',
1535 'e', 'r', 't',
1536 };
1537 SpdyCredential credential;
1538 credential.slot = 3;
1539 credential.proof = "proof";
1540 credential.certs.push_back("a cert");
1541 credential.certs.push_back("another cert");
1542 credential.certs.push_back("final cert");
1543 scoped_ptr<SpdyFrame> frame(framer.CreateCredentialFrame(credential));
1544 CompareFrame(kDescription, *frame, kFrameData, arraysize(kFrameData));
1545 }
1546 }
1547
1548 TEST_F(SpdyFramerTest, ParseCredentialFrame) {
1549 SpdyFramer framer;
1550
1551 {
1552 unsigned char kFrameData[] = {
1553 0x80, 0x02, 0x00, 0x0A,
1554 0x00, 0x00, 0x00, 0x33,
1555 0x00, 0x03, 0x00, 0x00,
1556 0x00, 0x05, 'p', 'r',
1557 'o', 'o', 'f', 0x00,
1558 0x00, 0x00, 0x06, 'a',
1559 ' ', 'c', 'e', 'r',
1560 't', 0x00, 0x00, 0x00,
1561 0x0C, 'a', 'n', 'o',
1562 't', 'h', 'e', 'r',
1563 ' ', 'c', 'e', 'r',
1564 't', 0x00, 0x00, 0x00,
1565 0x0A, 'f', 'i', 'n',
1566 'a', 'l', ' ', 'c',
1567 'e', 'r', 't',
1568 };
1569 SpdyCredentialControlFrame frame(reinterpret_cast<char*>(kFrameData),
1570 false);
1571 SpdyCredential credential;
1572 EXPECT_TRUE(SpdyFramer::ParseCredentialData(frame.payload(),
1573 frame.length(),
1574 &credential));
1575 EXPECT_EQ(3u, credential.slot);
1576 EXPECT_EQ("proof", credential.proof);
1577 EXPECT_EQ("a cert", credential.certs.front());
1578 credential.certs.erase(credential.certs.begin());
1579 EXPECT_EQ("another cert", credential.certs.front());
1580 credential.certs.erase(credential.certs.begin());
1581 EXPECT_EQ("final cert", credential.certs.front());
1582 credential.certs.erase(credential.certs.begin());
1583 EXPECT_TRUE(credential.certs.empty());
1584 }
1585 }
1586
1587 TEST_F(SpdyFramerTest, DuplicateFrame) {
1588 SpdyFramer framer;
1589
1590 {
1591 const char kDescription[] = "PING frame";
1592 const unsigned char kFrameData[] = {
1593 0x80, 0x02, 0x00, 0x06,
1594 0x00, 0x00, 0x00, 0x04,
1595 0x12, 0x34, 0x56, 0x78,
1596 };
1597 scoped_ptr<SpdyFrame> frame1(framer.CreatePingFrame(0x12345678u));
1598 CompareFrame(kDescription, *frame1, kFrameData, arraysize(kFrameData));
1599
1600 scoped_ptr<SpdyFrame> frame2(framer.DuplicateFrame(*frame1));
1601 CompareFrame(kDescription, *frame2, kFrameData, arraysize(kFrameData));
1602 }
1603 }
1604
1605 // This test case reproduces conditions that caused ExpandControlFrameBuffer to
1606 // fail to expand the buffer control frame buffer when it should have, allowing
1607 // the framer to overrun the buffer, and smash other heap contents. This test
1608 // relies on the debug version of the heap manager, which checks for buffer
1609 // overrun errors during delete processing. Regression test for b/2974814.
1610 TEST_F(SpdyFramerTest, ExpandBuffer_HeapSmash) {
1611 // Sweep through the area of problematic values, to make sure we always cover
1612 // the danger zone, even if it moves around at bit due to SPDY changes.
1613 for (uint16 val2_len = SpdyFramer::kControlFrameBufferInitialSize - 50;
1614 val2_len < SpdyFramer::kControlFrameBufferInitialSize;
1615 val2_len++) {
1616 std::string val2 = std::string(val2_len, 'a');
1617 SpdyHeaderBlock headers;
1618 headers["bar"] = "foo";
1619 headers["foo"] = "baz";
1620 headers["grue"] = val2.c_str();
1621 SpdyFramer framer;
1622 scoped_ptr<SpdySynStreamControlFrame> template_frame(
1623 framer.CreateSynStream(1, // stream_id
1624 0, // associated_stream_id
1625 1, // priority
1626 CONTROL_FLAG_NONE,
1627 false, // compress
1628 &headers));
1629 EXPECT_TRUE(template_frame.get() != NULL);
1630 TestSpdyVisitor visitor;
1631 visitor.SimulateInFramer(
1632 reinterpret_cast<unsigned char*>(template_frame.get()->data()),
1633 template_frame.get()->length() + SpdyControlFrame::kHeaderSize);
1634 EXPECT_EQ(1, visitor.syn_frame_count_);
1635 }
1636 }
1637
1638 TEST_F(SpdyFramerTest, ReadCredentialFrame) {
1639 SpdyCredential credential;
1640 credential.slot = 3;
1641 credential.proof = "proof";
1642 credential.certs.push_back("a cert");
1643 credential.certs.push_back("another cert");
1644 credential.certs.push_back("final cert");
1645 SpdyFramer framer;
1646 scoped_ptr<SpdyFrame> control_frame(
1647 framer.CreateCredentialFrame(credential));
1648 EXPECT_TRUE(control_frame.get() != NULL);
1649 TestSpdyVisitor visitor;
1650 visitor.use_compression_ = false;
1651 visitor.SimulateInFramer(
1652 reinterpret_cast<unsigned char*>(control_frame.get()->data()),
1653 control_frame.get()->length() + SpdyControlFrame::kHeaderSize);
1654 EXPECT_EQ(0, visitor.error_count_);
1655 EXPECT_EQ(1, visitor.credential_count_);
1656 EXPECT_EQ(control_frame->length(), visitor.credential_buffer_length_);
1657 EXPECT_EQ(credential.slot, visitor.credential_.slot);
1658 EXPECT_EQ(credential.proof, visitor.credential_.proof);
1659 EXPECT_EQ(credential.certs.size(), visitor.credential_.certs.size());
1660 for (size_t i = 0; i < credential.certs.size(); i++) {
1661 EXPECT_EQ(credential.certs[i], visitor.credential_.certs[i]);
1662 }
1663 }
1664
1665 TEST_F(SpdyFramerTest, ReadCredentialFrameWithCorruptProof) {
1666 SpdyCredential credential;
1667 credential.slot = 3;
1668 credential.proof = "proof";
1669 credential.certs.push_back("a cert");
1670 credential.certs.push_back("another cert");
1671 credential.certs.push_back("final cert");
1672 SpdyFramer framer;
1673 scoped_ptr<SpdyFrame> control_frame(
1674 framer.CreateCredentialFrame(credential));
1675 EXPECT_TRUE(control_frame.get() != NULL);
1676 TestSpdyVisitor visitor;
1677 visitor.use_compression_ = false;
1678 unsigned char* data =
1679 reinterpret_cast<unsigned char*>(control_frame.get()->data());
1680 size_t offset = SpdyControlFrame::kHeaderSize + 4;
1681 data[offset] = 0xFF; // Proof length is past the end of the frame
1682 visitor.SimulateInFramer(
1683 data, control_frame.get()->length() + SpdyControlFrame::kHeaderSize);
1684 EXPECT_EQ(1, visitor.error_count_);
1685 }
1686
1687 TEST_F(SpdyFramerTest, ReadCredentialFrameWithCorruptCertificate) {
1688 SpdyCredential credential;
1689 credential.slot = 3;
1690 credential.proof = "proof";
1691 credential.certs.push_back("a cert");
1692 credential.certs.push_back("another cert");
1693 credential.certs.push_back("final cert");
1694 SpdyFramer framer;
1695 scoped_ptr<SpdyFrame> control_frame(
1696 framer.CreateCredentialFrame(credential));
1697 EXPECT_TRUE(control_frame.get() != NULL);
1698 TestSpdyVisitor visitor;
1699 visitor.use_compression_ = false;
1700 unsigned char* data =
1701 reinterpret_cast<unsigned char*>(control_frame.get()->data());
1702 size_t offset = SpdyControlFrame::kHeaderSize + credential.proof.length();
1703 data[offset] = 0xFF; // Certificate length is past the end of the frame
1704 visitor.SimulateInFramer(
1705 data, control_frame.get()->length() + SpdyControlFrame::kHeaderSize);
1706 EXPECT_EQ(1, visitor.error_count_);
1707 }
1708
1709 TEST_F(SpdyFramerTest, ReadGarbage) {
1710 SpdyFramer framer;
1711 unsigned char garbage_frame[256];
1712 memset(garbage_frame, ~0, sizeof(garbage_frame));
1713 TestSpdyVisitor visitor;
1714 visitor.use_compression_ = false;
1715 visitor.SimulateInFramer(garbage_frame, sizeof(garbage_frame));
1716 EXPECT_EQ(1, visitor.error_count_);
1717 }
1718
1719 TEST_F(SpdyFramerTest, ReadGarbageWithValidVersion) {
1720 SpdyFramer framer;
1721 char garbage_frame[256];
1722 memset(garbage_frame, ~0, sizeof(garbage_frame));
1723 SpdyControlFrame control_frame(&garbage_frame[0], false);
1724 control_frame.set_version(kSpdyProtocolVersion);
1725 TestSpdyVisitor visitor;
1726 visitor.use_compression_ = false;
1727 visitor.SimulateInFramer(
1728 reinterpret_cast<unsigned char*>(control_frame.data()),
1729 sizeof(garbage_frame));
1730 EXPECT_EQ(1, visitor.error_count_);
1731 }
1732
1733 TEST(SpdyFramer, StateToStringTest) {
1734 EXPECT_STREQ("ERROR",
1735 SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR));
1736 EXPECT_STREQ("DONE",
1737 SpdyFramer::StateToString(SpdyFramer::SPDY_DONE));
1738 EXPECT_STREQ("AUTO_RESET",
1739 SpdyFramer::StateToString(SpdyFramer::SPDY_AUTO_RESET));
1740 EXPECT_STREQ("RESET",
1741 SpdyFramer::StateToString(SpdyFramer::SPDY_RESET));
1742 EXPECT_STREQ("READING_COMMON_HEADER",
1743 SpdyFramer::StateToString(
1744 SpdyFramer::SPDY_READING_COMMON_HEADER));
1745 EXPECT_STREQ("CONTROL_FRAME_PAYLOAD",
1746 SpdyFramer::StateToString(
1747 SpdyFramer::SPDY_CONTROL_FRAME_PAYLOAD));
1748 EXPECT_STREQ("IGNORE_REMAINING_PAYLOAD",
1749 SpdyFramer::StateToString(
1750 SpdyFramer::SPDY_IGNORE_REMAINING_PAYLOAD));
1751 EXPECT_STREQ("FORWARD_STREAM_FRAME",
1752 SpdyFramer::StateToString(
1753 SpdyFramer::SPDY_FORWARD_STREAM_FRAME));
1754 EXPECT_STREQ("SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK",
1755 SpdyFramer::StateToString(
1756 SpdyFramer::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK));
1757 EXPECT_STREQ("SPDY_CONTROL_FRAME_HEADER_BLOCK",
1758 SpdyFramer::StateToString(
1759 SpdyFramer::SPDY_CONTROL_FRAME_HEADER_BLOCK));
1760 EXPECT_STREQ("SPDY_CREDENTIAL_FRAME_PAYLOAD",
1761 SpdyFramer::StateToString(
1762 SpdyFramer::SPDY_CREDENTIAL_FRAME_PAYLOAD));
1763 EXPECT_STREQ("UNKNOWN_STATE",
1764 SpdyFramer::StateToString(
1765 SpdyFramer::SPDY_CREDENTIAL_FRAME_PAYLOAD + 1));
1766 }
1767
1768 TEST(SpdyFramer, ErrorCodeToStringTest) {
1769 EXPECT_STREQ("NO_ERROR",
1770 SpdyFramer::ErrorCodeToString(SpdyFramer::SPDY_NO_ERROR));
1771 EXPECT_STREQ("INVALID_CONTROL_FRAME",
1772 SpdyFramer::ErrorCodeToString(
1773 SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
1774 EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
1775 SpdyFramer::ErrorCodeToString(
1776 SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
1777 EXPECT_STREQ("ZLIB_INIT_FAILURE",
1778 SpdyFramer::ErrorCodeToString(
1779 SpdyFramer::SPDY_ZLIB_INIT_FAILURE));
1780 EXPECT_STREQ("UNSUPPORTED_VERSION",
1781 SpdyFramer::ErrorCodeToString(
1782 SpdyFramer::SPDY_UNSUPPORTED_VERSION));
1783 EXPECT_STREQ("DECOMPRESS_FAILURE",
1784 SpdyFramer::ErrorCodeToString(
1785 SpdyFramer::SPDY_DECOMPRESS_FAILURE));
1786 EXPECT_STREQ("COMPRESS_FAILURE",
1787 SpdyFramer::ErrorCodeToString(
1788 SpdyFramer::SPDY_COMPRESS_FAILURE));
1789 EXPECT_STREQ("UNKNOWN_ERROR",
1790 SpdyFramer::ErrorCodeToString(SpdyFramer::LAST_ERROR));
1791 }
1792
1793 TEST(SpdyFramer, StatusCodeToStringTest) {
1794 EXPECT_STREQ("INVALID",
1795 SpdyFramer::StatusCodeToString(INVALID));
1796 EXPECT_STREQ("PROTOCOL_ERROR",
1797 SpdyFramer::StatusCodeToString(PROTOCOL_ERROR));
1798 EXPECT_STREQ("INVALID_STREAM",
1799 SpdyFramer::StatusCodeToString(INVALID_STREAM));
1800 EXPECT_STREQ("REFUSED_STREAM",
1801 SpdyFramer::StatusCodeToString(REFUSED_STREAM));
1802 EXPECT_STREQ("UNSUPPORTED_VERSION",
1803 SpdyFramer::StatusCodeToString(UNSUPPORTED_VERSION));
1804 EXPECT_STREQ("CANCEL",
1805 SpdyFramer::StatusCodeToString(CANCEL));
1806 EXPECT_STREQ("INTERNAL_ERROR",
1807 SpdyFramer::StatusCodeToString(INTERNAL_ERROR));
1808 EXPECT_STREQ("FLOW_CONTROL_ERROR",
1809 SpdyFramer::StatusCodeToString(FLOW_CONTROL_ERROR));
1810 EXPECT_STREQ("UNKNOWN_STATUS",
1811 SpdyFramer::StatusCodeToString(NUM_STATUS_CODES));
1812 }
1813
1814 TEST(SpdyFramer, ControlTypeToStringTest) {
1815 EXPECT_STREQ("SYN_STREAM",
1816 SpdyFramer::ControlTypeToString(SYN_STREAM));
1817 EXPECT_STREQ("SYN_REPLY",
1818 SpdyFramer::ControlTypeToString(SYN_REPLY));
1819 EXPECT_STREQ("RST_STREAM",
1820 SpdyFramer::ControlTypeToString(RST_STREAM));
1821 EXPECT_STREQ("SETTINGS",
1822 SpdyFramer::ControlTypeToString(SETTINGS));
1823 EXPECT_STREQ("NOOP",
1824 SpdyFramer::ControlTypeToString(NOOP));
1825 EXPECT_STREQ("PING",
1826 SpdyFramer::ControlTypeToString(PING));
1827 EXPECT_STREQ("GOAWAY",
1828 SpdyFramer::ControlTypeToString(GOAWAY));
1829 EXPECT_STREQ("HEADERS",
1830 SpdyFramer::ControlTypeToString(HEADERS));
1831 EXPECT_STREQ("WINDOW_UPDATE",
1832 SpdyFramer::ControlTypeToString(WINDOW_UPDATE));
1833 EXPECT_STREQ("SETTINGS",
1834 SpdyFramer::ControlTypeToString(SETTINGS));
1835 EXPECT_STREQ("UNKNOWN_CONTROL_TYPE",
1836 SpdyFramer::ControlTypeToString(NUM_CONTROL_FRAME_TYPES));
1837 }
1838
1839 TEST(SpdyFramer, GetMinimumControlFrameSizeTest) {
1840 EXPECT_EQ(SpdySynStreamControlFrame::size(),
1841 SpdyFramer::GetMinimumControlFrameSize(SYN_STREAM));
1842 EXPECT_EQ(SpdySynReplyControlFrame::size(),
1843 SpdyFramer::GetMinimumControlFrameSize(SYN_REPLY));
1844 EXPECT_EQ(SpdyRstStreamControlFrame::size(),
1845 SpdyFramer::GetMinimumControlFrameSize(RST_STREAM));
1846 EXPECT_EQ(SpdySettingsControlFrame::size(),
1847 SpdyFramer::GetMinimumControlFrameSize(SETTINGS));
1848 EXPECT_EQ(SpdyNoOpControlFrame::size(),
1849 SpdyFramer::GetMinimumControlFrameSize(NOOP));
1850 EXPECT_EQ(SpdyPingControlFrame::size(),
1851 SpdyFramer::GetMinimumControlFrameSize(PING));
1852 EXPECT_EQ(SpdyGoAwayControlFrame::size(),
1853 SpdyFramer::GetMinimumControlFrameSize(GOAWAY));
1854 EXPECT_EQ(SpdyHeadersControlFrame::size(),
1855 SpdyFramer::GetMinimumControlFrameSize(HEADERS));
1856 EXPECT_EQ(SpdyWindowUpdateControlFrame::size(),
1857 SpdyFramer::GetMinimumControlFrameSize(WINDOW_UPDATE));
1858 EXPECT_EQ(SpdyCredentialControlFrame::size(),
1859 SpdyFramer::GetMinimumControlFrameSize(CREDENTIAL));
1860 EXPECT_EQ(static_cast<size_t>(0x7FFFFFFF),
1861 SpdyFramer::GetMinimumControlFrameSize(NUM_CONTROL_FRAME_TYPES));
1862 }
1863
1864 std::string RandomString(int length) {
1865 std::string rv;
1866 for (int index = 0; index < length; index++)
1867 rv += static_cast<char>('a' + (rand() % 26));
1868 return rv;
1869 }
1870
1871 } // namespace
OLDNEW
« no previous file with comments | « net/spdy/spdy_framer_spdy3_test.cc ('k') | net/spdy/spdy_http_stream_spdy2_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698