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 2832973003: Split net/spdy into core and chromium subdirectories. (Closed)
Patch Set: Fix some more build rules. Created 3 years, 8 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
« no previous file with comments | « net/spdy/spdy_framer_decoder_adapter.cc ('k') | net/spdy/spdy_header_block.h » ('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 "net/spdy/spdy_framer.h"
6
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include <algorithm>
11 #include <cstdint>
12 #include <limits>
13 #include <memory>
14 #include <tuple>
15 #include <utility>
16 #include <vector>
17
18 #include "base/compiler_specific.h"
19 #include "base/logging.h"
20 #include "base/macros.h"
21 #include "base/memory/ptr_util.h"
22 #include "base/strings/string_number_conversions.h"
23 #include "net/quic/platform/api/quic_flags.h"
24 #include "net/spdy/array_output_buffer.h"
25 #include "net/spdy/hpack/hpack_constants.h"
26 #include "net/spdy/mock_spdy_framer_visitor.h"
27 #include "net/spdy/spdy_flags.h"
28 #include "net/spdy/spdy_frame_builder.h"
29 #include "net/spdy/spdy_frame_reader.h"
30 #include "net/spdy/spdy_protocol.h"
31 #include "net/spdy/spdy_test_utils.h"
32 #include "testing/gmock/include/gmock/gmock.h"
33 #include "testing/gtest/include/gtest/gtest.h"
34 #include "testing/platform_test.h"
35
36 using testing::_;
37
38 namespace net {
39
40 namespace test {
41
42 namespace {
43
44 const int64_t kSize = 64 * 1024;
45 char output_buffer[kSize] = "";
46
47 // frame_list_char is used to hold frames to be compared with output_buffer.
48 const int64_t buffer_size = 64 * 1024;
49 char frame_list_char[buffer_size] = "";
50 }
51
52 class MockDebugVisitor : public SpdyFramerDebugVisitorInterface {
53 public:
54 MOCK_METHOD4(OnSendCompressedFrame,
55 void(SpdyStreamId stream_id,
56 SpdyFrameType type,
57 size_t payload_len,
58 size_t frame_len));
59
60 MOCK_METHOD3(OnReceiveCompressedFrame,
61 void(SpdyStreamId stream_id,
62 SpdyFrameType type,
63 size_t frame_len));
64 };
65
66 class SpdyFramerTestUtil {
67 public:
68 // Decompress a single frame using the decompression context held by
69 // the SpdyFramer. The implemention is meant for use only in tests
70 // and will CHECK fail if the input is anything other than a single,
71 // well-formed compressed frame.
72 //
73 // Returns a new decompressed SpdySerializedFrame.
74 template <class SpdyFrameType>
75 static SpdySerializedFrame DecompressFrame(SpdyFramer* framer,
76 const SpdyFrameType& frame) {
77 DecompressionVisitor visitor;
78 framer->set_visitor(&visitor);
79 CHECK_EQ(frame.size(), framer->ProcessInput(frame.data(), frame.size()));
80 CHECK_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer->state());
81 framer->set_visitor(nullptr);
82 SpdyFramer serializer(SpdyFramer::DISABLE_COMPRESSION);
83 return serializer.SerializeFrame(visitor.GetFrame());
84 }
85
86 class DecompressionVisitor : public SpdyFramerVisitorInterface {
87 public:
88 DecompressionVisitor() : finished_(false) {}
89
90 const SpdyFrameIR& GetFrame() const {
91 CHECK(finished_);
92 return *frame_;
93 }
94
95 SpdyHeadersHandlerInterface* OnHeaderFrameStart(
96 SpdyStreamId stream_id) override {
97 if (headers_handler_ == nullptr) {
98 headers_handler_ = base::MakeUnique<TestHeadersHandler>();
99 }
100 return headers_handler_.get();
101 }
102
103 void OnHeaderFrameEnd(SpdyStreamId stream_id, bool end_headers) override {
104 CHECK(!finished_);
105 frame_->set_header_block(headers_handler_->decoded_block().Clone());
106 finished_ = true;
107 if (end_headers) {
108 headers_handler_.reset();
109 }
110 }
111
112 void OnHeaders(SpdyStreamId stream_id,
113 bool has_priority,
114 int weight,
115 SpdyStreamId parent_stream_id,
116 bool exclusive,
117 bool fin,
118 bool end) override {
119 auto headers = base::MakeUnique<SpdyHeadersIR>(stream_id);
120 headers->set_has_priority(has_priority);
121 headers->set_weight(weight);
122 headers->set_parent_stream_id(parent_stream_id);
123 headers->set_exclusive(exclusive);
124 headers->set_fin(fin);
125 frame_ = std::move(headers);
126 }
127
128 void OnPushPromise(SpdyStreamId stream_id,
129 SpdyStreamId promised_stream_id,
130 bool end) override {
131 frame_ =
132 base::MakeUnique<SpdyPushPromiseIR>(stream_id, promised_stream_id);
133 }
134
135 // TODO(birenroy): Add support for CONTINUATION.
136 void OnContinuation(SpdyStreamId stream_id, bool end) override {
137 LOG(FATAL);
138 }
139
140 // All other methods just LOG(FATAL).
141 void OnError(SpdyFramer* framer) override { LOG(FATAL); }
142 void OnDataFrameHeader(SpdyStreamId stream_id,
143 size_t length,
144 bool fin) override {
145 LOG(FATAL) << "Unexpected data frame header";
146 }
147 void OnStreamFrameData(SpdyStreamId stream_id,
148 const char* data,
149 size_t len) override {
150 LOG(FATAL);
151 }
152
153 void OnStreamEnd(SpdyStreamId stream_id) override { LOG(FATAL); }
154
155 void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
156 LOG(FATAL);
157 }
158
159 void OnRstStream(SpdyStreamId stream_id,
160 SpdyErrorCode error_code) override {
161 LOG(FATAL);
162 }
163 void OnSetting(SpdySettingsIds id, uint32_t value) override { LOG(FATAL); }
164 void OnPing(SpdyPingId unique_id, bool is_ack) override { LOG(FATAL); }
165 void OnSettingsEnd() override { LOG(FATAL); }
166 void OnGoAway(SpdyStreamId last_accepted_stream_id,
167 SpdyErrorCode error_code) override {
168 LOG(FATAL);
169 }
170
171 void OnWindowUpdate(SpdyStreamId stream_id,
172 int delta_window_size) override {
173 LOG(FATAL);
174 }
175
176 void OnPriority(SpdyStreamId stream_id,
177 SpdyStreamId parent_stream_id,
178 int weight,
179 bool exclusive) override {
180 // Do nothing.
181 }
182
183 bool OnUnknownFrame(SpdyStreamId stream_id, uint8_t frame_type) override {
184 LOG(FATAL);
185 return false;
186 }
187
188 private:
189 std::unique_ptr<TestHeadersHandler> headers_handler_;
190 std::unique_ptr<SpdyFrameWithHeaderBlockIR> frame_;
191 bool finished_;
192
193 DISALLOW_COPY_AND_ASSIGN(DecompressionVisitor);
194 };
195
196 private:
197 DISALLOW_COPY_AND_ASSIGN(SpdyFramerTestUtil);
198 };
199
200 MATCHER_P(IsFrameUnionOf, frame_list, "") {
201 size_t size_verified = 0;
202 for (const auto& frame : *frame_list) {
203 if (arg.size() < size_verified + frame.size()) {
204 LOG(FATAL) << "Incremental header serialization should not lead to a "
205 << "higher total frame length than non-incremental method.";
206 return false;
207 }
208 if (memcmp(arg.data() + size_verified, frame.data(), frame.size())) {
209 CompareCharArraysWithHexError(
210 "Header serialization methods should be equivalent: ",
211 reinterpret_cast<unsigned char*>(arg.data() + size_verified),
212 frame.size(), reinterpret_cast<unsigned char*>(frame.data()),
213 frame.size());
214 return false;
215 }
216 size_verified += frame.size();
217 }
218 return size_verified == arg.size();
219 }
220
221 class SpdyFramerPeer {
222 public:
223 static size_t ControlFrameBufferSize() {
224 return SpdyFramer::kControlFrameBufferSize;
225 }
226 static size_t GetNumberRequiredContinuationFrames(SpdyFramer* framer,
227 size_t size) {
228 return framer->GetNumberRequiredContinuationFrames(size);
229 }
230 static void SetError(SpdyFramer* framer, SpdyFramer::SpdyFramerError error) {
231 framer->set_error(error);
232 }
233
234 // TODO(dahollings): Remove these methods when deprecating non-incremental
235 // header serialization path.
236 static std::unique_ptr<SpdyHeadersIR> CloneSpdyHeadersIR(
237 const SpdyHeadersIR& headers) {
238 auto newHeaders = base::MakeUnique<SpdyHeadersIR>(
239 headers.stream_id(), headers.header_block().Clone());
240 newHeaders->set_fin(headers.fin());
241 newHeaders->set_has_priority(headers.has_priority());
242 newHeaders->set_weight(headers.weight());
243 newHeaders->set_parent_stream_id(headers.parent_stream_id());
244 newHeaders->set_exclusive(headers.exclusive());
245 if (headers.padded()) {
246 newHeaders->set_padding_len(headers.padding_payload_len() + 1);
247 }
248 newHeaders->set_end_headers(headers.end_headers());
249 return newHeaders;
250 }
251
252 static SpdySerializedFrame SerializeHeaders(SpdyFramer* framer,
253 const SpdyHeadersIR& headers) {
254 SpdySerializedFrame serialized_headers_old_version(
255 framer->SerializeHeaders(headers));
256 framer->hpack_encoder_.reset(nullptr);
257 auto* saved_debug_visitor = framer->debug_visitor_;
258 framer->debug_visitor_ = nullptr;
259
260 std::vector<SpdySerializedFrame> frame_list;
261 ArrayOutputBuffer frame_list_buffer(frame_list_char, buffer_size);
262 SpdyFramer::SpdyHeaderFrameIterator it(framer, CloneSpdyHeadersIR(headers));
263 while (it.HasNextFrame()) {
264 size_t size_before = frame_list_buffer.Size();
265 it.NextFrame(&frame_list_buffer);
266 frame_list.emplace_back(
267 SpdySerializedFrame(frame_list_buffer.Begin() + size_before,
268 frame_list_buffer.Size() - size_before, false));
269 }
270 framer->debug_visitor_ = saved_debug_visitor;
271
272 EXPECT_THAT(serialized_headers_old_version, IsFrameUnionOf(&frame_list));
273 return serialized_headers_old_version;
274 }
275
276 static SpdySerializedFrame SerializeHeaders(SpdyFramer* framer,
277 const SpdyHeadersIR& headers,
278 ArrayOutputBuffer* output) {
279 if (output == nullptr) {
280 return SerializeHeaders(framer, headers);
281 }
282 output->Reset();
283 EXPECT_TRUE(framer->SerializeHeaders(headers, output));
284 SpdySerializedFrame serialized_headers_old_version(output->Begin(),
285 output->Size(), false);
286 framer->hpack_encoder_.reset(nullptr);
287 auto* saved_debug_visitor = framer->debug_visitor_;
288 framer->debug_visitor_ = nullptr;
289
290 std::vector<SpdySerializedFrame> frame_list;
291 ArrayOutputBuffer frame_list_buffer(frame_list_char, buffer_size);
292 SpdyFramer::SpdyHeaderFrameIterator it(framer, CloneSpdyHeadersIR(headers));
293 while (it.HasNextFrame()) {
294 size_t size_before = frame_list_buffer.Size();
295 it.NextFrame(&frame_list_buffer);
296 frame_list.emplace_back(
297 SpdySerializedFrame(frame_list_buffer.Begin() + size_before,
298 frame_list_buffer.Size() - size_before, false));
299 }
300 framer->debug_visitor_ = saved_debug_visitor;
301
302 EXPECT_THAT(serialized_headers_old_version, IsFrameUnionOf(&frame_list));
303 return serialized_headers_old_version;
304 }
305
306 static std::unique_ptr<SpdyPushPromiseIR> CloneSpdyPushPromiseIR(
307 const SpdyPushPromiseIR& push_promise) {
308 auto new_push_promise = base::MakeUnique<SpdyPushPromiseIR>(
309 push_promise.stream_id(), push_promise.promised_stream_id(),
310 push_promise.header_block().Clone());
311 new_push_promise->set_fin(push_promise.fin());
312 if (push_promise.padded()) {
313 new_push_promise->set_padding_len(push_promise.padding_payload_len() + 1);
314 }
315 new_push_promise->set_end_headers(push_promise.end_headers());
316 return new_push_promise;
317 }
318
319 static SpdySerializedFrame SerializePushPromise(
320 SpdyFramer* framer,
321 const SpdyPushPromiseIR& push_promise) {
322 SpdySerializedFrame serialized_headers_old_version =
323 framer->SerializePushPromise(push_promise);
324 framer->hpack_encoder_.reset(nullptr);
325 auto* saved_debug_visitor = framer->debug_visitor_;
326 framer->debug_visitor_ = nullptr;
327
328 std::vector<SpdySerializedFrame> frame_list;
329 ArrayOutputBuffer frame_list_buffer(frame_list_char, buffer_size);
330 frame_list_buffer.Reset();
331 SpdyFramer::SpdyPushPromiseFrameIterator it(
332 framer, CloneSpdyPushPromiseIR(push_promise));
333 while (it.HasNextFrame()) {
334 size_t size_before = frame_list_buffer.Size();
335 it.NextFrame(&frame_list_buffer);
336 frame_list.emplace_back(
337 SpdySerializedFrame(frame_list_buffer.Begin() + size_before,
338 frame_list_buffer.Size() - size_before, false));
339 }
340 framer->debug_visitor_ = saved_debug_visitor;
341
342 EXPECT_THAT(serialized_headers_old_version, IsFrameUnionOf(&frame_list));
343 return serialized_headers_old_version;
344 }
345
346 static SpdySerializedFrame SerializePushPromise(
347 SpdyFramer* framer,
348 const SpdyPushPromiseIR& push_promise,
349 ArrayOutputBuffer* output) {
350 if (output == nullptr) {
351 return SerializePushPromise(framer, push_promise);
352 }
353 output->Reset();
354 EXPECT_TRUE(framer->SerializePushPromise(push_promise, output));
355 SpdySerializedFrame serialized_headers_old_version(output->Begin(),
356 output->Size(), false);
357 framer->hpack_encoder_.reset(nullptr);
358 auto* saved_debug_visitor = framer->debug_visitor_;
359 framer->debug_visitor_ = nullptr;
360
361 std::vector<SpdySerializedFrame> frame_list;
362 ArrayOutputBuffer frame_list_buffer(frame_list_char, buffer_size);
363 frame_list_buffer.Reset();
364 SpdyFramer::SpdyPushPromiseFrameIterator it(
365 framer, CloneSpdyPushPromiseIR(push_promise));
366 while (it.HasNextFrame()) {
367 size_t size_before = frame_list_buffer.Size();
368 it.NextFrame(&frame_list_buffer);
369 frame_list.emplace_back(
370 SpdySerializedFrame(frame_list_buffer.Begin() + size_before,
371 frame_list_buffer.Size() - size_before, false));
372 }
373 framer->debug_visitor_ = saved_debug_visitor;
374
375 EXPECT_THAT(serialized_headers_old_version, IsFrameUnionOf(&frame_list));
376 return serialized_headers_old_version;
377 }
378 };
379
380 class TestSpdyVisitor : public SpdyFramerVisitorInterface,
381 public SpdyFramerDebugVisitorInterface {
382 public:
383 // This is larger than our max frame size because header blocks that
384 // are too long can spill over into CONTINUATION frames.
385 static const size_t kDefaultHeaderBufferSize = 16 * 1024 * 1024;
386
387 explicit TestSpdyVisitor(SpdyFramer::CompressionOption option)
388 : framer_(option),
389 error_count_(0),
390 headers_frame_count_(0),
391 push_promise_frame_count_(0),
392 goaway_count_(0),
393 setting_count_(0),
394 settings_ack_sent_(0),
395 settings_ack_received_(0),
396 continuation_count_(0),
397 altsvc_count_(0),
398 priority_count_(0),
399 test_altsvc_ir_(0),
400 on_unknown_frame_result_(false),
401 last_window_update_stream_(0),
402 last_window_update_delta_(0),
403 last_push_promise_stream_(0),
404 last_push_promise_promised_stream_(0),
405 data_bytes_(0),
406 fin_frame_count_(0),
407 fin_flag_count_(0),
408 end_of_stream_count_(0),
409 control_frame_header_data_count_(0),
410 zero_length_control_frame_header_data_count_(0),
411 data_frame_count_(0),
412 last_payload_len_(0),
413 last_frame_len_(0),
414 header_buffer_(kDefaultHeaderBufferSize),
415 header_buffer_length_(0),
416 header_stream_id_(static_cast<SpdyStreamId>(-1)),
417 header_control_type_(SpdyFrameType::DATA),
418 header_buffer_valid_(false) {}
419
420 void OnError(SpdyFramer* f) override {
421 VLOG(1) << "SpdyFramer Error: "
422 << SpdyFramer::SpdyFramerErrorToString(f->spdy_framer_error());
423 ++error_count_;
424 }
425
426 void OnDataFrameHeader(SpdyStreamId stream_id,
427 size_t length,
428 bool fin) override {
429 VLOG(1) << "OnDataFrameHeader(" << stream_id << ", " << length << ", "
430 << fin << ")";
431 ++data_frame_count_;
432 header_stream_id_ = stream_id;
433 }
434
435 void OnStreamFrameData(SpdyStreamId stream_id,
436 const char* data,
437 size_t len) override {
438 VLOG(1) << "OnStreamFrameData(" << stream_id << ", data, " << len << ", "
439 << ") data:\n"
440 << base::HexEncode(data, len);
441 EXPECT_EQ(header_stream_id_, stream_id);
442 data_bytes_ += len;
443 }
444
445 void OnStreamEnd(SpdyStreamId stream_id) override {
446 VLOG(1) << "OnStreamEnd(" << stream_id << ")";
447 EXPECT_EQ(header_stream_id_, stream_id);
448 ++end_of_stream_count_;
449 }
450
451 void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
452 VLOG(1) << "OnStreamPadding(" << stream_id << ", " << len << ")\n";
453 EXPECT_EQ(header_stream_id_, stream_id);
454 data_bytes_ += len;
455 }
456
457 SpdyHeadersHandlerInterface* OnHeaderFrameStart(
458 SpdyStreamId stream_id) override {
459 if (headers_handler_ == nullptr) {
460 headers_handler_ = base::MakeUnique<TestHeadersHandler>();
461 }
462 return headers_handler_.get();
463 }
464
465 void OnHeaderFrameEnd(SpdyStreamId stream_id, bool end_headers) override {
466 CHECK(headers_handler_ != nullptr);
467 headers_ = headers_handler_->decoded_block().Clone();
468 header_bytes_received_ = headers_handler_->header_bytes_parsed();
469 if (end_headers) {
470 headers_handler_.reset();
471 }
472 }
473
474 void OnRstStream(SpdyStreamId stream_id, SpdyErrorCode error_code) override {
475 VLOG(1) << "OnRstStream(" << stream_id << ", " << error_code << ")";
476 ++fin_frame_count_;
477 }
478
479 void OnSetting(SpdySettingsIds id, uint32_t value) override {
480 VLOG(1) << "OnSetting(" << id << ", " << std::hex << ", " << value << ")";
481 ++setting_count_;
482 }
483
484 void OnSettingsAck() override {
485 VLOG(1) << "OnSettingsAck";
486 ++settings_ack_received_;
487 }
488
489 void OnSettingsEnd() override {
490 VLOG(1) << "OnSettingsEnd";
491 ++settings_ack_sent_;
492 }
493
494 void OnPing(SpdyPingId unique_id, bool is_ack) override {
495 LOG(DFATAL) << "OnPing(" << unique_id << ", " << (is_ack ? 1 : 0) << ")";
496 }
497
498 void OnGoAway(SpdyStreamId last_accepted_stream_id,
499 SpdyErrorCode error_code) override {
500 VLOG(1) << "OnGoAway(" << last_accepted_stream_id << ", " << error_code
501 << ")";
502 ++goaway_count_;
503 }
504
505 void OnHeaders(SpdyStreamId stream_id,
506 bool has_priority,
507 int weight,
508 SpdyStreamId parent_stream_id,
509 bool exclusive,
510 bool fin,
511 bool end) override {
512 VLOG(1) << "OnHeaders(" << stream_id << ", " << has_priority << ", "
513 << weight << ", " << parent_stream_id << ", " << exclusive << ", "
514 << fin << ", " << end << ")";
515 ++headers_frame_count_;
516 InitHeaderStreaming(SpdyFrameType::HEADERS, stream_id);
517 if (fin) {
518 ++fin_flag_count_;
519 }
520 header_has_priority_ = has_priority;
521 header_parent_stream_id_ = parent_stream_id;
522 header_exclusive_ = exclusive;
523 }
524
525 void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) override {
526 VLOG(1) << "OnWindowUpdate(" << stream_id << ", " << delta_window_size
527 << ")";
528 last_window_update_stream_ = stream_id;
529 last_window_update_delta_ = delta_window_size;
530 }
531
532 void OnPushPromise(SpdyStreamId stream_id,
533 SpdyStreamId promised_stream_id,
534 bool end) override {
535 VLOG(1) << "OnPushPromise(" << stream_id << ", " << promised_stream_id
536 << ", " << end << ")";
537 ++push_promise_frame_count_;
538 InitHeaderStreaming(SpdyFrameType::PUSH_PROMISE, stream_id);
539 last_push_promise_stream_ = stream_id;
540 last_push_promise_promised_stream_ = promised_stream_id;
541 }
542
543 void OnContinuation(SpdyStreamId stream_id, bool end) override {
544 VLOG(1) << "OnContinuation(" << stream_id << ", " << end << ")";
545 ++continuation_count_;
546 }
547
548 void OnAltSvc(SpdyStreamId stream_id,
549 SpdyStringPiece origin,
550 const SpdyAltSvcWireFormat::AlternativeServiceVector&
551 altsvc_vector) override {
552 VLOG(1) << "OnAltSvc(" << stream_id << ", \"" << origin
553 << "\", altsvc_vector)";
554 test_altsvc_ir_.set_stream_id(stream_id);
555 if (origin.length() > 0) {
556 test_altsvc_ir_.set_origin(SpdyString(origin));
557 }
558 for (const auto& altsvc : altsvc_vector) {
559 test_altsvc_ir_.add_altsvc(altsvc);
560 }
561 ++altsvc_count_;
562 }
563
564 void OnPriority(SpdyStreamId stream_id,
565 SpdyStreamId parent_stream_id,
566 int weight,
567 bool exclusive) override {
568 VLOG(1) << "OnPriority(" << stream_id << ", " << parent_stream_id << ", "
569 << weight << ", " << (exclusive ? 1 : 0) << ")";
570 ++priority_count_;
571 }
572
573 bool OnUnknownFrame(SpdyStreamId stream_id, uint8_t frame_type) override {
574 VLOG(1) << "OnUnknownFrame(" << stream_id << ", " << frame_type << ")";
575 return on_unknown_frame_result_;
576 }
577
578 void OnSendCompressedFrame(SpdyStreamId stream_id,
579 SpdyFrameType type,
580 size_t payload_len,
581 size_t frame_len) override {
582 VLOG(1) << "OnSendCompressedFrame(" << stream_id << ", " << type << ", "
583 << payload_len << ", " << frame_len << ")";
584 last_payload_len_ = payload_len;
585 last_frame_len_ = frame_len;
586 }
587
588 void OnReceiveCompressedFrame(SpdyStreamId stream_id,
589 SpdyFrameType type,
590 size_t frame_len) override {
591 VLOG(1) << "OnReceiveCompressedFrame(" << stream_id << ", " << type << ", "
592 << frame_len << ")";
593 last_frame_len_ = frame_len;
594 }
595
596 // Convenience function which runs a framer simulation with particular input.
597 void SimulateInFramer(const unsigned char* input, size_t size) {
598 framer_.set_visitor(this);
599 size_t input_remaining = size;
600 const char* input_ptr = reinterpret_cast<const char*>(input);
601 while (input_remaining > 0 &&
602 framer_.spdy_framer_error() == SpdyFramer::SPDY_NO_ERROR) {
603 // To make the tests more interesting, we feed random (and small) chunks
604 // into the framer. This simulates getting strange-sized reads from
605 // the socket.
606 const size_t kMaxReadSize = 32;
607 size_t bytes_read =
608 (rand() % std::min(input_remaining, kMaxReadSize)) + 1;
609 size_t bytes_processed = framer_.ProcessInput(input_ptr, bytes_read);
610 input_remaining -= bytes_processed;
611 input_ptr += bytes_processed;
612 }
613 }
614
615 void InitHeaderStreaming(SpdyFrameType header_control_type,
616 SpdyStreamId stream_id) {
617 if (!IsDefinedFrameType(SerializeFrameType(header_control_type))) {
618 DLOG(FATAL) << "Attempted to init header streaming with "
619 << "invalid control frame type: " << header_control_type;
620 }
621 std::fill(header_buffer_.begin(), header_buffer_.end(), 0);
622 header_buffer_length_ = 0;
623 header_stream_id_ = stream_id;
624 header_control_type_ = header_control_type;
625 header_buffer_valid_ = true;
626 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream);
627 }
628
629 void set_extension_visitor(ExtensionVisitorInterface* extension) {
630 framer_.set_extension_visitor(extension);
631 }
632
633 // Override the default buffer size (16K). Call before using the framer!
634 void set_header_buffer_size(size_t header_buffer_size) {
635 header_buffer_.resize(header_buffer_size);
636 }
637
638 // Largest control frame that the SPDY implementation sends, including the
639 // size of the header.
640 static size_t sent_control_frame_max_size() {
641 return SpdyFramer::kMaxControlFrameSize;
642 }
643
644 // Largest control frame that the SPDY implementation is willing to receive,
645 // excluding the size of the header.
646 static size_t received_control_frame_max_size() {
647 return kSpdyInitialFrameSizeLimit;
648 }
649
650 static size_t header_data_chunk_max_size() {
651 return SpdyFramer::kHeaderDataChunkMaxSize;
652 }
653
654 SpdyFramer framer_;
655
656 // Counters from the visitor callbacks.
657 int error_count_;
658 int headers_frame_count_;
659 int push_promise_frame_count_;
660 int goaway_count_;
661 int setting_count_;
662 int settings_ack_sent_;
663 int settings_ack_received_;
664 int continuation_count_;
665 int altsvc_count_;
666 int priority_count_;
667 SpdyAltSvcIR test_altsvc_ir_;
668 bool on_unknown_frame_result_;
669 SpdyStreamId last_window_update_stream_;
670 int last_window_update_delta_;
671 SpdyStreamId last_push_promise_stream_;
672 SpdyStreamId last_push_promise_promised_stream_;
673 int data_bytes_;
674 int fin_frame_count_; // The count of RST_STREAM type frames received.
675 int fin_flag_count_; // The count of frames with the FIN flag set.
676 int end_of_stream_count_; // The count of zero-length data frames.
677 int control_frame_header_data_count_; // The count of chunks received.
678 // The count of zero-length control frame header data chunks received.
679 int zero_length_control_frame_header_data_count_;
680 int data_frame_count_;
681 size_t last_payload_len_;
682 size_t last_frame_len_;
683
684 // Header block streaming state:
685 std::vector<char> header_buffer_;
686 size_t header_buffer_length_;
687 size_t header_bytes_received_;
688 SpdyStreamId header_stream_id_;
689 SpdyFrameType header_control_type_;
690 bool header_buffer_valid_;
691 std::unique_ptr<TestHeadersHandler> headers_handler_;
692 SpdyHeaderBlock headers_;
693 bool header_has_priority_;
694 SpdyStreamId header_parent_stream_id_;
695 bool header_exclusive_;
696 };
697
698 class TestExtension : public ExtensionVisitorInterface {
699 public:
700 void OnSetting(uint16_t id, uint32_t value) override {
701 settings_received_.push_back({id, value});
702 }
703
704 // Called when non-standard frames are received.
705 bool OnFrameHeader(SpdyStreamId stream_id,
706 size_t length,
707 uint8_t type,
708 uint8_t flags) override {
709 stream_id_ = stream_id;
710 length_ = length;
711 type_ = type;
712 flags_ = flags;
713 return true;
714 }
715
716 // The payload for a single frame may be delivered as multiple calls to
717 // OnFramePayload.
718 void OnFramePayload(const char* data, size_t len) override {
719 payload_.append(data, len);
720 }
721
722 std::vector<std::pair<uint16_t, uint32_t>> settings_received_;
723 SpdyStreamId stream_id_ = 0;
724 size_t length_ = 0;
725 uint8_t type_ = 0;
726 uint8_t flags_ = 0;
727 SpdyString payload_;
728 };
729
730 // Retrieves serialized headers from a HEADERS frame.
731 SpdyStringPiece GetSerializedHeaders(const SpdySerializedFrame& frame,
732 const SpdyFramer& framer) {
733 SpdyFrameReader reader(frame.data(), frame.size());
734 reader.Seek(3); // Seek past the frame length.
735
736 uint8_t serialized_type;
737 reader.ReadUInt8(&serialized_type);
738
739 SpdyFrameType type = ParseFrameType(serialized_type);
740 DCHECK_EQ(SpdyFrameType::HEADERS, type);
741 uint8_t flags;
742 reader.ReadUInt8(&flags);
743
744 return SpdyStringPiece(frame.data() + framer.GetHeadersMinimumSize(),
745 frame.size() - framer.GetHeadersMinimumSize());
746 }
747
748 enum DecoderChoice { DECODER_SELF, DECODER_NESTED, DECODER_HTTP2 };
749 enum HpackChoice { HPACK_DECODER_1, HPACK_DECODER_3 };
750 enum Output { USE, NOT_USE };
751
752 class SpdyFramerTest : public ::testing::TestWithParam<
753 std::tuple<DecoderChoice, HpackChoice, Output>> {
754 public:
755 SpdyFramerTest() : output_(output_buffer, kSize) {}
756
757 protected:
758 void SetUp() override {
759 auto param = GetParam();
760 switch (std::get<0>(param)) {
761 case DECODER_SELF:
762 FLAGS_use_nested_spdy_framer_decoder = false;
763 FLAGS_chromium_http2_flag_spdy_use_http2_frame_decoder_adapter = false;
764 break;
765 case DECODER_NESTED:
766 FLAGS_use_nested_spdy_framer_decoder = true;
767 FLAGS_chromium_http2_flag_spdy_use_http2_frame_decoder_adapter = false;
768 break;
769 case DECODER_HTTP2:
770 FLAGS_use_nested_spdy_framer_decoder = false;
771 FLAGS_chromium_http2_flag_spdy_use_http2_frame_decoder_adapter = true;
772 break;
773 }
774 switch (std::get<1>(param)) {
775 case HPACK_DECODER_1:
776 FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3 = false;
777 break;
778 case HPACK_DECODER_3:
779 FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3 = true;
780 break;
781 }
782 switch (std::get<2>(param)) {
783 case USE:
784 use_output_ = true;
785 break;
786 case NOT_USE:
787 // TODO(yasong): remove this case after
788 // FLAGS_chromium_http2_flag_remove_rewritelength deprecates.
789 use_output_ = false;
790 break;
791 }
792 }
793
794 void CompareFrame(const SpdyString& description,
795 const SpdySerializedFrame& actual_frame,
796 const unsigned char* expected,
797 const int expected_len) {
798 const unsigned char* actual =
799 reinterpret_cast<const unsigned char*>(actual_frame.data());
800 CompareCharArraysWithHexError(description, actual, actual_frame.size(),
801 expected, expected_len);
802 }
803
804 void CompareFrames(const SpdyString& description,
805 const SpdySerializedFrame& expected_frame,
806 const SpdySerializedFrame& actual_frame) {
807 CompareCharArraysWithHexError(
808 description,
809 reinterpret_cast<const unsigned char*>(expected_frame.data()),
810 expected_frame.size(),
811 reinterpret_cast<const unsigned char*>(actual_frame.data()),
812 actual_frame.size());
813 }
814
815 bool use_output_ = false;
816 ArrayOutputBuffer output_;
817 };
818
819 INSTANTIATE_TEST_CASE_P(SpdyFramerTests,
820 SpdyFramerTest,
821 ::testing::Combine(::testing::Values(DECODER_SELF,
822 DECODER_NESTED,
823 DECODER_HTTP2),
824 ::testing::Values(HPACK_DECODER_1,
825 HPACK_DECODER_3),
826 ::testing::Values(USE, NOT_USE)));
827
828 // Test that we can encode and decode a SpdyHeaderBlock in serialized form.
829 TEST_P(SpdyFramerTest, HeaderBlockInBuffer) {
830 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
831
832 // Encode the header block into a Headers frame.
833 SpdyHeadersIR headers(1);
834 headers.SetHeader("alpha", "beta");
835 headers.SetHeader("gamma", "charlie");
836 headers.SetHeader("cookie", "key1=value1; key2=value2");
837 SpdySerializedFrame frame(
838 SpdyFramerPeer::SerializeHeaders(&framer, headers, &output_));
839
840 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
841 visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
842 frame.size());
843
844 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
845 EXPECT_EQ(headers.header_block(), visitor.headers_);
846 }
847
848 // Test that if there's not a full frame, we fail to parse it.
849 TEST_P(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
850 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
851
852 // Encode the header block into a Headers frame.
853 SpdyHeadersIR headers(1);
854 headers.SetHeader("alpha", "beta");
855 headers.SetHeader("gamma", "charlie");
856 SpdySerializedFrame frame(
857 SpdyFramerPeer::SerializeHeaders(&framer, headers, &output_));
858
859 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
860 visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
861 frame.size() - 2);
862
863 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
864 EXPECT_EQ(0u, visitor.headers_.size());
865 }
866
867 // Test that we treat incoming upper-case or mixed-case header values as
868 // malformed.
869 TEST_P(SpdyFramerTest, RejectUpperCaseHeaderBlockValue) {
870 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
871
872 SpdyFrameBuilder frame(1024);
873 frame.BeginNewFrame(framer, SpdyFrameType::HEADERS, 0, 1);
874 frame.WriteUInt32(1);
875 frame.WriteStringPiece32("Name1");
876 frame.WriteStringPiece32("value1");
877 frame.OverwriteLength(framer, frame.length() - framer.GetFrameHeaderSize());
878
879 SpdyFrameBuilder frame2(1024);
880 frame2.BeginNewFrame(framer, SpdyFrameType::HEADERS, 0, 1);
881 frame2.WriteUInt32(2);
882 frame2.WriteStringPiece32("name1");
883 frame2.WriteStringPiece32("value1");
884 frame2.WriteStringPiece32("nAmE2");
885 frame2.WriteStringPiece32("value2");
886 frame.OverwriteLength(framer, frame2.length() - framer.GetFrameHeaderSize());
887
888 SpdySerializedFrame control_frame(frame.take());
889 SpdyStringPiece serialized_headers =
890 GetSerializedHeaders(control_frame, framer);
891 SpdySerializedFrame control_frame2(frame2.take());
892 SpdyStringPiece serialized_headers2 =
893 GetSerializedHeaders(control_frame2, framer);
894
895 SpdyHeaderBlock new_headers;
896 EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(
897 serialized_headers.data(), serialized_headers.size(), &new_headers));
898 EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(
899 serialized_headers2.data(), serialized_headers2.size(), &new_headers));
900 }
901
902 // Test that we can encode and decode stream dependency values in a header
903 // frame.
904 TEST_P(SpdyFramerTest, HeaderStreamDependencyValues) {
905 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
906
907 const SpdyStreamId parent_stream_id_test_array[] = {0, 3};
908 for (SpdyStreamId parent_stream_id : parent_stream_id_test_array) {
909 const bool exclusive_test_array[] = {true, false};
910 for (bool exclusive : exclusive_test_array) {
911 SpdyHeadersIR headers(1);
912 headers.set_has_priority(true);
913 headers.set_parent_stream_id(parent_stream_id);
914 headers.set_exclusive(exclusive);
915 SpdySerializedFrame frame(
916 SpdyFramerPeer::SerializeHeaders(&framer, headers, &output_));
917
918 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
919 visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
920 frame.size());
921
922 EXPECT_TRUE(visitor.header_has_priority_);
923 EXPECT_EQ(parent_stream_id, visitor.header_parent_stream_id_);
924 EXPECT_EQ(exclusive, visitor.header_exclusive_);
925 }
926 }
927 }
928
929 // Test that if we receive a frame with payload length field at the
930 // advertised max size, we do not set an error in ProcessInput.
931 TEST_P(SpdyFramerTest, AcceptMaxFrameSizeSetting) {
932 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
933 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
934 framer.set_visitor(&visitor);
935
936 // DATA frame with maximum allowed payload length.
937 unsigned char kH2FrameData[] = {
938 0x00, 0x40, 0x00, // Length: 2^14
939 0x00, // Type: HEADERS
940 0x00, // Flags: None
941 0x00, 0x00, 0x00, 0x01, // Stream: 1
942 0x00, 0x00, 0x00, 0x00, // Junk payload
943 };
944
945 SpdySerializedFrame frame(reinterpret_cast<char*>(kH2FrameData),
946 sizeof(kH2FrameData), false);
947
948 EXPECT_CALL(visitor, OnDataFrameHeader(1, 1 << 14, false));
949 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 4));
950 framer.ProcessInput(frame.data(), frame.size());
951 EXPECT_FALSE(framer.HasError());
952 }
953
954 // Test that if we receive a frame with payload length larger than the
955 // advertised max size, we set an error of SPDY_INVALID_CONTROL_FRAME_SIZE.
956 TEST_P(SpdyFramerTest, ExceedMaxFrameSizeSetting) {
957 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
958 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
959 framer.set_visitor(&visitor);
960
961 // DATA frame with too large payload length.
962 unsigned char kH2FrameData[] = {
963 0x00, 0x40, 0x01, // Length: 2^14 + 1
964 0x00, // Type: HEADERS
965 0x00, // Flags: None
966 0x00, 0x00, 0x00, 0x01, // Stream: 1
967 0x00, 0x00, 0x00, 0x00, // Junk payload
968 };
969
970 SpdySerializedFrame frame(reinterpret_cast<char*>(kH2FrameData),
971 sizeof(kH2FrameData), false);
972
973 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
974 framer.ProcessInput(frame.data(), frame.size());
975 EXPECT_TRUE(framer.HasError());
976 EXPECT_EQ(SpdyFramer::SPDY_OVERSIZED_PAYLOAD, framer.spdy_framer_error())
977 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
978 }
979
980 // Test that if we receive a DATA frame with padding length larger than the
981 // payload length, we set an error of SPDY_INVALID_PADDING
982 TEST_P(SpdyFramerTest, OversizedDataPaddingError) {
983 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
984 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
985 framer.set_visitor(&visitor);
986
987 // DATA frame with invalid padding length.
988 // |kH2FrameData| has to be |unsigned char|, because Chromium on Windows uses
989 // MSVC, where |char| is signed by default, which would not compile because of
990 // the element exceeding 127.
991 unsigned char kH2FrameData[] = {
992 0x00, 0x00, 0x05, // Length: 5
993 0x00, // Type: DATA
994 0x09, // Flags: END_STREAM|PADDED
995 0x00, 0x00, 0x00, 0x01, // Stream: 1
996 0xff, // PadLen: 255 trailing bytes (Too Long)
997 0x00, 0x00, 0x00, 0x00, // Padding
998 };
999
1000 SpdySerializedFrame frame(reinterpret_cast<char*>(kH2FrameData),
1001 sizeof(kH2FrameData), false);
1002
1003 {
1004 testing::InSequence seq;
1005 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, 1));
1006 EXPECT_CALL(visitor, OnStreamPadding(1, 1));
1007 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
1008 }
1009 EXPECT_GT(frame.size(), framer.ProcessInput(frame.data(), frame.size()));
1010 EXPECT_TRUE(framer.HasError());
1011 EXPECT_EQ(SpdyFramer::SPDY_INVALID_PADDING, framer.spdy_framer_error())
1012 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
1013 }
1014
1015 // Test that if we receive a DATA frame with padding length not larger than the
1016 // payload length, we do not set an error of SPDY_INVALID_PADDING
1017 TEST_P(SpdyFramerTest, CorrectlySizedDataPaddingNoError) {
1018 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
1019 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
1020 framer.set_visitor(&visitor);
1021
1022 // DATA frame with valid Padding length
1023 char kH2FrameData[] = {
1024 0x00, 0x00, 0x05, // Length: 5
1025 0x00, // Type: DATA
1026 0x08, // Flags: PADDED
1027 0x00, 0x00, 0x00, 0x01, // Stream: 1
1028 0x04, // PadLen: 4 trailing bytes
1029 0x00, 0x00, 0x00, 0x00, // Padding
1030 };
1031
1032 SpdySerializedFrame frame(kH2FrameData, sizeof(kH2FrameData), false);
1033
1034 {
1035 testing::InSequence seq;
1036 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, false));
1037 EXPECT_CALL(visitor, OnStreamPadding(1, 1));
1038 EXPECT_CALL(visitor, OnError(testing::Eq(&framer))).Times(0);
1039 // Note that OnStreamFrameData(1, _, 1)) is never called
1040 // since there is no data, only padding
1041 EXPECT_CALL(visitor, OnStreamPadding(1, 4));
1042 }
1043
1044 EXPECT_EQ(frame.size(), framer.ProcessInput(frame.data(), frame.size()));
1045 EXPECT_FALSE(framer.HasError());
1046 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.spdy_framer_error())
1047 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
1048 }
1049
1050 // Test that if we receive a HEADERS frame with padding length larger than the
1051 // payload length, we set an error of SPDY_INVALID_PADDING
1052 TEST_P(SpdyFramerTest, OversizedHeadersPaddingError) {
1053 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
1054 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
1055 framer.set_visitor(&visitor);
1056
1057 // HEADERS frame with invalid padding length.
1058 // |kH2FrameData| has to be |unsigned char|, because Chromium on Windows uses
1059 // MSVC, where |char| is signed by default, which would not compile because of
1060 // the element exceeding 127.
1061 unsigned char kH2FrameData[] = {
1062 0x00, 0x00, 0x05, // Length: 5
1063 0x01, // Type: HEADERS
1064 0x08, // Flags: PADDED
1065 0x00, 0x00, 0x00, 0x01, // Stream: 1
1066 0xff, // PadLen: 255 trailing bytes (Too Long)
1067 0x00, 0x00, 0x00, 0x00, // Padding
1068 };
1069
1070 SpdySerializedFrame frame(reinterpret_cast<char*>(kH2FrameData),
1071 sizeof(kH2FrameData), false);
1072
1073 EXPECT_CALL(visitor, OnHeaders(1, false, 0, 0, false, false, false));
1074 EXPECT_CALL(visitor, OnHeaderFrameStart(1)).Times(1);
1075 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
1076 EXPECT_EQ(frame.size(), framer.ProcessInput(frame.data(), frame.size()));
1077 EXPECT_TRUE(framer.HasError());
1078 EXPECT_EQ(SpdyFramer::SPDY_INVALID_PADDING, framer.spdy_framer_error())
1079 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
1080 }
1081
1082 // Test that if we receive a HEADERS frame with padding length not larger
1083 // than the payload length, we do not set an error of SPDY_INVALID_PADDING
1084 TEST_P(SpdyFramerTest, CorrectlySizedHeadersPaddingNoError) {
1085 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
1086 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
1087 framer.set_visitor(&visitor);
1088
1089 // HEADERS frame with invalid Padding length
1090 char kH2FrameData[] = {
1091 0x00, 0x00, 0x05, // Length: 5
1092 0x01, // Type: HEADERS
1093 0x08, // Flags: PADDED
1094 0x00, 0x00, 0x00, 0x01, // Stream: 1
1095 0x04, // PadLen: 4 trailing bytes
1096 0x00, 0x00, 0x00, 0x00, // Padding
1097 };
1098
1099 SpdySerializedFrame frame(kH2FrameData, sizeof(kH2FrameData), false);
1100
1101 EXPECT_CALL(visitor, OnHeaders(1, false, 0, 0, false, false, false));
1102 EXPECT_CALL(visitor, OnHeaderFrameStart(1)).Times(1);
1103 EXPECT_EQ(frame.size(), framer.ProcessInput(frame.data(), frame.size()));
1104 EXPECT_FALSE(framer.HasError());
1105 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.spdy_framer_error())
1106 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
1107 }
1108
1109 // Test that if we receive a DATA with stream ID zero, we signal an error
1110 // (but don't crash).
1111 TEST_P(SpdyFramerTest, DataWithStreamIdZero) {
1112 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
1113 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
1114 framer.set_visitor(&visitor);
1115
1116 const char bytes[] = "hello";
1117 SpdyDataIR data_ir(0, bytes);
1118 SpdySerializedFrame frame(framer.SerializeData(data_ir));
1119
1120 // We shouldn't have to read the whole frame before we signal an error.
1121 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
1122 EXPECT_GT(frame.size(), framer.ProcessInput(frame.data(), frame.size()));
1123 EXPECT_TRUE(framer.HasError());
1124 EXPECT_EQ(SpdyFramer::SPDY_INVALID_STREAM_ID, framer.spdy_framer_error())
1125 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
1126 }
1127
1128 // Test that if we receive a HEADERS with stream ID zero, we signal an error
1129 // (but don't crash).
1130 TEST_P(SpdyFramerTest, HeadersWithStreamIdZero) {
1131 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
1132 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
1133 framer.set_visitor(&visitor);
1134
1135 SpdyHeadersIR headers(0);
1136 headers.SetHeader("alpha", "beta");
1137 SpdySerializedFrame frame(
1138 SpdyFramerPeer::SerializeHeaders(&framer, headers, &output_));
1139
1140 // We shouldn't have to read the whole frame before we signal an error.
1141 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
1142 EXPECT_GT(frame.size(), framer.ProcessInput(frame.data(), frame.size()));
1143 EXPECT_TRUE(framer.HasError());
1144 EXPECT_EQ(SpdyFramer::SPDY_INVALID_STREAM_ID, framer.spdy_framer_error())
1145 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
1146 }
1147
1148 // Test that if we receive a PRIORITY with stream ID zero, we signal an error
1149 // (but don't crash).
1150 TEST_P(SpdyFramerTest, PriorityWithStreamIdZero) {
1151 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
1152 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
1153 framer.set_visitor(&visitor);
1154
1155 SpdyPriorityIR priority_ir(0, 1, 16, true);
1156 SpdySerializedFrame frame(framer.SerializeFrame(priority_ir));
1157 if (use_output_) {
1158 ASSERT_TRUE(framer.SerializeFrame(priority_ir, &output_));
1159 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
1160 }
1161
1162 // We shouldn't have to read the whole frame before we signal an error.
1163 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
1164 EXPECT_GT(frame.size(), framer.ProcessInput(frame.data(), frame.size()));
1165 EXPECT_TRUE(framer.HasError());
1166 EXPECT_EQ(SpdyFramer::SPDY_INVALID_STREAM_ID, framer.spdy_framer_error())
1167 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
1168 }
1169
1170 // Test that if we receive a RST_STREAM with stream ID zero, we signal an error
1171 // (but don't crash).
1172 TEST_P(SpdyFramerTest, RstStreamWithStreamIdZero) {
1173 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
1174 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
1175 framer.set_visitor(&visitor);
1176
1177 SpdyRstStreamIR rst_stream_ir(0, ERROR_CODE_PROTOCOL_ERROR);
1178 SpdySerializedFrame frame(framer.SerializeRstStream(rst_stream_ir));
1179 if (use_output_) {
1180 ASSERT_TRUE(framer.SerializeRstStream(rst_stream_ir, &output_));
1181 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
1182 }
1183
1184 // We shouldn't have to read the whole frame before we signal an error.
1185 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
1186 EXPECT_GT(frame.size(), framer.ProcessInput(frame.data(), frame.size()));
1187 EXPECT_TRUE(framer.HasError());
1188 EXPECT_EQ(SpdyFramer::SPDY_INVALID_STREAM_ID, framer.spdy_framer_error())
1189 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
1190 }
1191
1192 // Test that if we receive a SETTINGS with stream ID other than zero,
1193 // we signal an error (but don't crash).
1194 TEST_P(SpdyFramerTest, SettingsWithStreamIdNotZero) {
1195 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
1196 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
1197 framer.set_visitor(&visitor);
1198
1199 // Settings frame with invalid StreamID of 0x01
1200 char kH2FrameData[] = {
1201 0x00, 0x00, 0x06, // Length: 6
1202 0x04, // Type: SETTINGS
1203 0x00, // Flags: none
1204 0x00, 0x00, 0x00, 0x01, // Stream: 1
1205 0x00, 0x04, // Param: INITIAL_WINDOW_SIZE
1206 0x0a, 0x0b, 0x0c, 0x0d, // Value: 168496141
1207 };
1208
1209 SpdySerializedFrame frame(kH2FrameData, sizeof(kH2FrameData), false);
1210
1211 // We shouldn't have to read the whole frame before we signal an error.
1212 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
1213 EXPECT_GT(frame.size(), framer.ProcessInput(frame.data(), frame.size()));
1214 EXPECT_TRUE(framer.HasError());
1215 EXPECT_EQ(SpdyFramer::SPDY_INVALID_STREAM_ID, framer.spdy_framer_error())
1216 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
1217 }
1218
1219 // Test that if we receive a GOAWAY with stream ID other than zero,
1220 // we signal an error (but don't crash).
1221 TEST_P(SpdyFramerTest, GoawayWithStreamIdNotZero) {
1222 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
1223 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
1224 framer.set_visitor(&visitor);
1225
1226 // GOAWAY frame with invalid StreamID of 0x01
1227 char kH2FrameData[] = {
1228 0x00, 0x00, 0x0a, // Length: 10
1229 0x07, // Type: GOAWAY
1230 0x00, // Flags: none
1231 0x00, 0x00, 0x00, 0x01, // Stream: 1
1232 0x00, 0x00, 0x00, 0x00, // Last: 0
1233 0x00, 0x00, 0x00, 0x00, // Error: NO_ERROR
1234 0x47, 0x41, // Description
1235 };
1236
1237 SpdySerializedFrame frame(kH2FrameData, sizeof(kH2FrameData), false);
1238
1239 // We shouldn't have to read the whole frame before we signal an error.
1240 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
1241 EXPECT_GT(frame.size(), framer.ProcessInput(frame.data(), frame.size()));
1242 EXPECT_TRUE(framer.HasError());
1243 EXPECT_EQ(SpdyFramer::SPDY_INVALID_STREAM_ID, framer.spdy_framer_error())
1244 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
1245 }
1246
1247 // Test that if we receive a CONTINUATION with stream ID zero, we signal an
1248 // SPDY_INVALID_STREAM_ID.
1249 TEST_P(SpdyFramerTest, ContinuationWithStreamIdZero) {
1250 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
1251 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
1252 framer.set_visitor(&visitor);
1253
1254 SpdyContinuationIR continuation(0);
1255 auto some_nonsense_encoding =
1256 base::MakeUnique<SpdyString>("some nonsense encoding");
1257 continuation.take_encoding(std::move(some_nonsense_encoding));
1258 continuation.set_end_headers(true);
1259 SpdySerializedFrame frame(framer.SerializeContinuation(continuation));
1260 if (use_output_) {
1261 ASSERT_TRUE(framer.SerializeContinuation(continuation, &output_));
1262 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
1263 }
1264
1265 // We shouldn't have to read the whole frame before we signal an error.
1266 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
1267 EXPECT_GT(frame.size(), framer.ProcessInput(frame.data(), frame.size()));
1268 EXPECT_TRUE(framer.HasError());
1269 EXPECT_EQ(SpdyFramer::SPDY_INVALID_STREAM_ID, framer.spdy_framer_error())
1270 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
1271 }
1272
1273 // Test that if we receive a PUSH_PROMISE with stream ID zero, we signal an
1274 // SPDY_INVALID_STREAM_ID.
1275 TEST_P(SpdyFramerTest, PushPromiseWithStreamIdZero) {
1276 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
1277 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
1278 framer.set_visitor(&visitor);
1279
1280 SpdyPushPromiseIR push_promise(0, 4);
1281 push_promise.SetHeader("alpha", "beta");
1282 SpdySerializedFrame frame(SpdyFramerPeer::SerializePushPromise(
1283 &framer, push_promise, use_output_ ? &output_ : nullptr));
1284
1285 // We shouldn't have to read the whole frame before we signal an error.
1286 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
1287 EXPECT_GT(frame.size(), framer.ProcessInput(frame.data(), frame.size()));
1288 EXPECT_TRUE(framer.HasError());
1289 EXPECT_EQ(SpdyFramer::SPDY_INVALID_STREAM_ID, framer.spdy_framer_error())
1290 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
1291 }
1292
1293 // Test that if we receive a PUSH_PROMISE with promised stream ID zero, we
1294 // signal SPDY_INVALID_STREAM_ID.
1295 TEST_P(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) {
1296 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
1297 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
1298 framer.set_visitor(&visitor);
1299
1300 SpdyPushPromiseIR push_promise(3, 0);
1301 push_promise.SetHeader("alpha", "beta");
1302 SpdySerializedFrame frame(SpdyFramerPeer::SerializePushPromise(
1303 &framer, push_promise, use_output_ ? &output_ : nullptr));
1304
1305 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
1306 framer.ProcessInput(frame.data(), frame.size());
1307 EXPECT_TRUE(framer.HasError());
1308 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.spdy_framer_error())
1309 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
1310 }
1311
1312 TEST_P(SpdyFramerTest, DuplicateHeader) {
1313 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
1314 // Frame builder with plentiful buffer size.
1315 SpdyFrameBuilder frame(1024);
1316 frame.BeginNewFrame(framer, SpdyFrameType::HEADERS, 0, 3);
1317
1318 frame.WriteUInt32(2); // Number of headers.
1319 frame.WriteStringPiece32("name");
1320 frame.WriteStringPiece32("value1");
1321 frame.WriteStringPiece32("name");
1322 frame.WriteStringPiece32("value2");
1323 // write the length
1324 frame.OverwriteLength(framer, frame.length() - framer.GetFrameHeaderSize());
1325
1326 SpdyHeaderBlock new_headers;
1327 SpdySerializedFrame control_frame(frame.take());
1328 SpdyStringPiece serialized_headers =
1329 GetSerializedHeaders(control_frame, framer);
1330 // This should fail because duplicate headers are verboten by the spec.
1331 EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(
1332 serialized_headers.data(), serialized_headers.size(), &new_headers));
1333 }
1334
1335 TEST_P(SpdyFramerTest, MultiValueHeader) {
1336 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
1337 // Frame builder with plentiful buffer size.
1338 SpdyFrameBuilder frame(1024);
1339 frame.BeginNewFrame(framer, SpdyFrameType::HEADERS,
1340 HEADERS_FLAG_PRIORITY | HEADERS_FLAG_END_HEADERS, 3);
1341 frame.WriteUInt32(0); // Priority exclusivity and dependent stream.
1342 frame.WriteUInt8(255); // Priority weight.
1343
1344 SpdyString value("value1\0value2", 13);
1345 // TODO(jgraettinger): If this pattern appears again, move to test class.
1346 SpdyHeaderBlock header_set;
1347 header_set["name"] = value;
1348 SpdyString buffer;
1349 HpackEncoder encoder(ObtainHpackHuffmanTable());
1350 encoder.DisableCompression();
1351 encoder.EncodeHeaderSet(header_set, &buffer);
1352 frame.WriteBytes(&buffer[0], buffer.size());
1353 // write the length
1354 frame.OverwriteLength(framer, frame.length() - framer.GetFrameHeaderSize());
1355
1356 SpdySerializedFrame control_frame(frame.take());
1357
1358 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
1359 visitor.SimulateInFramer(
1360 reinterpret_cast<unsigned char*>(control_frame.data()),
1361 control_frame.size());
1362
1363 EXPECT_THAT(visitor.headers_, testing::ElementsAre(testing::Pair(
1364 "name", SpdyStringPiece(value))));
1365 }
1366
1367 TEST_P(SpdyFramerTest, CompressEmptyHeaders) {
1368 // See crbug.com/172383
1369 SpdyHeadersIR headers(1);
1370 headers.SetHeader("server", "SpdyServer 1.0");
1371 headers.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
1372 headers.SetHeader("status", "200");
1373 headers.SetHeader("version", "HTTP/1.1");
1374 headers.SetHeader("content-type", "text/html");
1375 headers.SetHeader("content-length", "12");
1376 headers.SetHeader("x-empty-header", "");
1377
1378 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
1379 SpdySerializedFrame frame1(
1380 SpdyFramerPeer::SerializeHeaders(&framer, headers, &output_));
1381 }
1382
1383 TEST_P(SpdyFramerTest, Basic) {
1384 // Send HEADERS frames with PRIORITY and END_HEADERS set.
1385 // frame-format off
1386 const unsigned char kH2Input[] = {
1387 0x00, 0x00, 0x05, // Length: 5
1388 0x01, // Type: HEADERS
1389 0x24, // Flags: END_HEADERS|PRIORITY
1390 0x00, 0x00, 0x00, 0x01, // Stream: 1
1391 0x00, 0x00, 0x00, 0x00, // Parent: 0
1392 0x82, // Weight: 131
1393
1394 0x00, 0x00, 0x01, // Length: 1
1395 0x01, // Type: HEADERS
1396 0x04, // Flags: END_HEADERS
1397 0x00, 0x00, 0x00, 0x01, // Stream: 1
1398 0x8c, // :status: 200
1399
1400 0x00, 0x00, 0x0c, // Length: 12
1401 0x00, // Type: DATA
1402 0x00, // Flags: none
1403 0x00, 0x00, 0x00, 0x01, // Stream: 1
1404 0xde, 0xad, 0xbe, 0xef, // Payload
1405 0xde, 0xad, 0xbe, 0xef, //
1406 0xde, 0xad, 0xbe, 0xef, //
1407
1408 0x00, 0x00, 0x05, // Length: 5
1409 0x01, // Type: HEADERS
1410 0x24, // Flags: END_HEADERS|PRIORITY
1411 0x00, 0x00, 0x00, 0x03, // Stream: 3
1412 0x00, 0x00, 0x00, 0x00, // Parent: 0
1413 0x82, // Weight: 131
1414
1415 0x00, 0x00, 0x08, // Length: 8
1416 0x00, // Type: DATA
1417 0x00, // Flags: none
1418 0x00, 0x00, 0x00, 0x03, // Stream: 3
1419 0xde, 0xad, 0xbe, 0xef, // Payload
1420 0xde, 0xad, 0xbe, 0xef, //
1421
1422 0x00, 0x00, 0x04, // Length: 4
1423 0x00, // Type: DATA
1424 0x00, // Flags: none
1425 0x00, 0x00, 0x00, 0x01, // Stream: 1
1426 0xde, 0xad, 0xbe, 0xef, // Payload
1427
1428 0x00, 0x00, 0x04, // Length: 4
1429 0x03, // Type: RST_STREAM
1430 0x00, // Flags: none
1431 0x00, 0x00, 0x00, 0x01, // Stream: 1
1432 0x00, 0x00, 0x00, 0x08, // Error: CANCEL
1433
1434 0x00, 0x00, 0x00, // Length: 0
1435 0x00, // Type: DATA
1436 0x00, // Flags: none
1437 0x00, 0x00, 0x00, 0x03, // Stream: 3
1438
1439 0x00, 0x00, 0x04, // Length: 4
1440 0x03, // Type: RST_STREAM
1441 0x00, // Flags: none
1442 0x00, 0x00, 0x00, 0x03, // Stream: 3
1443 0x00, 0x00, 0x00, 0x08, // Error: CANCEL
1444 };
1445 // frame-format on
1446
1447 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
1448 visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
1449
1450 EXPECT_EQ(24, visitor.data_bytes_);
1451 EXPECT_EQ(0, visitor.error_count_);
1452 EXPECT_EQ(2, visitor.fin_frame_count_);
1453
1454 EXPECT_EQ(3, visitor.headers_frame_count_);
1455
1456 EXPECT_EQ(0, visitor.fin_flag_count_);
1457 EXPECT_EQ(0, visitor.end_of_stream_count_);
1458 EXPECT_EQ(4, visitor.data_frame_count_);
1459 }
1460
1461 // Test that the FIN flag on a data frame signifies EOF.
1462 TEST_P(SpdyFramerTest, FinOnDataFrame) {
1463 // Send HEADERS frames with END_HEADERS set.
1464 // frame-format off
1465 const unsigned char kH2Input[] = {
1466 0x00, 0x00, 0x05, // Length: 5
1467 0x01, // Type: HEADERS
1468 0x24, // Flags: END_HEADERS|PRIORITY
1469 0x00, 0x00, 0x00, 0x01, // Stream: 1
1470 0x00, 0x00, 0x00, 0x00, // Parent: 0
1471 0x82, // Weight: 131
1472
1473 0x00, 0x00, 0x01, // Length: 1
1474 0x01, // Type: HEADERS
1475 0x04, // Flags: END_HEADERS
1476 0x00, 0x00, 0x00, 0x01, // Stream: 1
1477 0x8c, // :status: 200
1478
1479 0x00, 0x00, 0x0c, // Length: 12
1480 0x00, // Type: DATA
1481 0x00, // Flags: none
1482 0x00, 0x00, 0x00, 0x01, // Stream: 1
1483 0xde, 0xad, 0xbe, 0xef, // Payload
1484 0xde, 0xad, 0xbe, 0xef, //
1485 0xde, 0xad, 0xbe, 0xef, //
1486
1487 0x00, 0x00, 0x04, // Length: 4
1488 0x00, // Type: DATA
1489 0x01, // Flags: END_STREAM
1490 0x00, 0x00, 0x00, 0x01, // Stream: 1
1491 0xde, 0xad, 0xbe, 0xef, // Payload
1492 };
1493 // frame-format on
1494
1495 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
1496 visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
1497
1498 EXPECT_EQ(0, visitor.error_count_);
1499 EXPECT_EQ(2, visitor.headers_frame_count_);
1500 EXPECT_EQ(16, visitor.data_bytes_);
1501 EXPECT_EQ(0, visitor.fin_frame_count_);
1502 EXPECT_EQ(0, visitor.fin_flag_count_);
1503 EXPECT_EQ(1, visitor.end_of_stream_count_);
1504 EXPECT_EQ(2, visitor.data_frame_count_);
1505 }
1506
1507 TEST_P(SpdyFramerTest, FinOnHeadersFrame) {
1508 // Send HEADERS frames with END_HEADERS set.
1509 // frame-format off
1510 const unsigned char kH2Input[] = {
1511 0x00, 0x00, 0x05, // Length: 5
1512 0x01, // Type: HEADERS
1513 0x24, // Flags: END_HEADERS|PRIORITY
1514 0x00, 0x00, 0x00, 0x01, // Stream: 1
1515 0x00, 0x00, 0x00, 0x00, // Parent: 0
1516 0x82, // Weight: 131
1517
1518 0x00, 0x00, 0x01, // Length: 1
1519 0x01, // Type: HEADERS
1520 0x05, // Flags: END_STREAM|END_HEADERS
1521 0x00, 0x00, 0x00, 0x01, // Stream: 1
1522 0x8c, // :status: 200
1523 };
1524 // frame-format on
1525
1526 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
1527 visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
1528
1529 EXPECT_EQ(0, visitor.error_count_);
1530 EXPECT_EQ(2, visitor.headers_frame_count_);
1531 EXPECT_EQ(0, visitor.data_bytes_);
1532 EXPECT_EQ(0, visitor.fin_frame_count_);
1533 EXPECT_EQ(1, visitor.fin_flag_count_);
1534 EXPECT_EQ(1, visitor.end_of_stream_count_);
1535 EXPECT_EQ(0, visitor.data_frame_count_);
1536 }
1537
1538 // Verify we can decompress the stream even if handed over to the
1539 // framer 1 byte at a time.
1540 TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
1541 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
1542
1543 const char kHeader1[] = "header1";
1544 const char kHeader2[] = "header2";
1545 const char kValue1[] = "value1";
1546 const char kValue2[] = "value2";
1547
1548 SpdyHeadersIR headers(1);
1549 headers.SetHeader(kHeader1, kValue1);
1550 headers.SetHeader(kHeader2, kValue2);
1551 SpdySerializedFrame headers_frame(SpdyFramerPeer::SerializeHeaders(
1552 &framer, headers, use_output_ ? &output_ : nullptr));
1553
1554 const char bytes[] = "this is a test test test test test!";
1555 SpdyDataIR data_ir(1, SpdyStringPiece(bytes, arraysize(bytes)));
1556 data_ir.set_fin(true);
1557 SpdySerializedFrame send_frame(framer.SerializeData(data_ir));
1558
1559 // Run the inputs through the framer.
1560 TestSpdyVisitor visitor(SpdyFramer::ENABLE_COMPRESSION);
1561 const unsigned char* data;
1562 data = reinterpret_cast<const unsigned char*>(headers_frame.data());
1563 for (size_t idx = 0; idx < headers_frame.size(); ++idx) {
1564 visitor.SimulateInFramer(data + idx, 1);
1565 ASSERT_EQ(0, visitor.error_count_);
1566 }
1567 data = reinterpret_cast<const unsigned char*>(send_frame.data());
1568 for (size_t idx = 0; idx < send_frame.size(); ++idx) {
1569 visitor.SimulateInFramer(data + idx, 1);
1570 ASSERT_EQ(0, visitor.error_count_);
1571 }
1572
1573 EXPECT_EQ(0, visitor.error_count_);
1574 EXPECT_EQ(1, visitor.headers_frame_count_);
1575 EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_));
1576 EXPECT_EQ(0, visitor.fin_frame_count_);
1577 EXPECT_EQ(0, visitor.fin_flag_count_);
1578 EXPECT_EQ(1, visitor.end_of_stream_count_);
1579 EXPECT_EQ(1, visitor.data_frame_count_);
1580 }
1581
1582 TEST_P(SpdyFramerTest, WindowUpdateFrame) {
1583 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
1584 SpdyWindowUpdateIR window_update(1, 0x12345678);
1585 SpdySerializedFrame frame(framer.SerializeWindowUpdate(window_update));
1586 if (use_output_) {
1587 ASSERT_TRUE(framer.SerializeWindowUpdate(window_update, &output_));
1588 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
1589 }
1590
1591 const char kDescription[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678";
1592 const unsigned char kH2FrameData[] = {
1593 0x00, 0x00, 0x04, // Length: 4
1594 0x08, // Type: WINDOW_UPDATE
1595 0x00, // Flags: none
1596 0x00, 0x00, 0x00, 0x01, // Stream: 1
1597 0x12, 0x34, 0x56, 0x78, // Increment: 305419896
1598 };
1599
1600 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
1601 }
1602
1603 TEST_P(SpdyFramerTest, CreateDataFrame) {
1604 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
1605
1606 {
1607 const char kDescription[] = "'hello' data frame, no FIN";
1608 // frame-format off
1609 const unsigned char kH2FrameData[] = {
1610 0x00, 0x00, 0x05, // Length: 5
1611 0x00, // Type: DATA
1612 0x00, // Flags: none
1613 0x00, 0x00, 0x00, 0x01, // Stream: 1
1614 'h', 'e', 'l', 'l', // Payload
1615 'o', //
1616 };
1617 // frame-format on
1618 const char bytes[] = "hello";
1619
1620 SpdyDataIR data_ir(1, bytes);
1621 SpdySerializedFrame frame(framer.SerializeData(data_ir));
1622 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
1623
1624 SpdyDataIR data_header_ir(1);
1625 data_header_ir.SetDataShallow(bytes);
1626 frame =
1627 framer.SerializeDataFrameHeaderWithPaddingLengthField(data_header_ir);
1628 CompareCharArraysWithHexError(
1629 kDescription, reinterpret_cast<const unsigned char*>(frame.data()),
1630 framer.GetDataFrameMinimumSize(), kH2FrameData,
1631 framer.GetDataFrameMinimumSize());
1632 }
1633
1634 {
1635 const char kDescription[] = "'hello' data frame with more padding, no FIN";
1636 const unsigned char kH2FrameData[] = {
1637 0x00, 0x00, 0xfd, // Length: 253
1638 0x00, // Type: DATA
1639 0x08, // Flags: PADDED
1640 0x00, 0x00, 0x00, 0x01, // Stream: 1
1641 0xf7, // PadLen: 247 trailing bytes
1642 'h', 'e', 'l', 'l', // Payload
1643 'o', //
1644 // Padding of 247 0x00(s).
1645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1664 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1665 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1666 };
1667 // frame-format on
1668 // clang-format on
1669 const char bytes[] = "hello";
1670
1671 SpdyDataIR data_ir(1, bytes);
1672 // 247 zeros and the pad length field make the overall padding to be 248
1673 // bytes.
1674 data_ir.set_padding_len(248);
1675 SpdySerializedFrame frame(framer.SerializeData(data_ir));
1676 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
1677
1678 frame = framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir);
1679 CompareCharArraysWithHexError(
1680 kDescription, reinterpret_cast<const unsigned char*>(frame.data()),
1681 framer.GetDataFrameMinimumSize(), kH2FrameData,
1682 framer.GetDataFrameMinimumSize());
1683 }
1684
1685 {
1686 const char kDescription[] = "'hello' data frame with few padding, no FIN";
1687 // frame-format off
1688 const unsigned char kH2FrameData[] = {
1689 0x00, 0x00, 0x0d, // Length: 13
1690 0x00, // Type: DATA
1691 0x08, // Flags: PADDED
1692 0x00, 0x00, 0x00, 0x01, // Stream: 1
1693 0x07, // PadLen: 7 trailing bytes
1694 'h', 'e', 'l', 'l', // Payload
1695 'o', //
1696 0x00, 0x00, 0x00, 0x00, // Padding
1697 0x00, 0x00, 0x00, // Padding
1698 };
1699 // frame-format on
1700 const char bytes[] = "hello";
1701
1702 SpdyDataIR data_ir(1, bytes);
1703 // 7 zeros and the pad length field make the overall padding to be 8 bytes.
1704 data_ir.set_padding_len(8);
1705 SpdySerializedFrame frame(framer.SerializeData(data_ir));
1706 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
1707 }
1708
1709 {
1710 const char kDescription[] =
1711 "'hello' data frame with 1 byte padding, no FIN";
1712 // frame-format off
1713 const unsigned char kH2FrameData[] = {
1714 0x00, 0x00, 0x06, // Length: 6
1715 0x00, // Type: DATA
1716 0x08, // Flags: PADDED
1717 0x00, 0x00, 0x00, 0x01, // Stream: 1
1718 0x00, // PadLen: 0 trailing bytes
1719 'h', 'e', 'l', 'l', // Payload
1720 'o', //
1721 };
1722 // frame-format on
1723 const char bytes[] = "hello";
1724
1725 SpdyDataIR data_ir(1, bytes);
1726 // The pad length field itself is used for the 1-byte padding and no padding
1727 // payload is needed.
1728 data_ir.set_padding_len(1);
1729 SpdySerializedFrame frame(framer.SerializeData(data_ir));
1730 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
1731
1732 frame = framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir);
1733 CompareCharArraysWithHexError(
1734 kDescription, reinterpret_cast<const unsigned char*>(frame.data()),
1735 framer.GetDataFrameMinimumSize(), kH2FrameData,
1736 framer.GetDataFrameMinimumSize());
1737 }
1738
1739 {
1740 const char kDescription[] = "Data frame with negative data byte, no FIN";
1741 const unsigned char kH2FrameData[] = {
1742 0x00, 0x00, 0x01, // Length: 1
1743 0x00, // Type: DATA
1744 0x00, // Flags: none
1745 0x00, 0x00, 0x00, 0x01, // Stream: 1
1746 0xff, // Payload
1747 };
1748 SpdyDataIR data_ir(1, "\xff");
1749 SpdySerializedFrame frame(framer.SerializeData(data_ir));
1750 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
1751 }
1752
1753 {
1754 const char kDescription[] = "'hello' data frame, with FIN";
1755 const unsigned char kH2FrameData[] = {
1756 0x00, 0x00, 0x05, // Length: 5
1757 0x00, // Type: DATA
1758 0x01, // Flags: END_STREAM
1759 0x00, 0x00, 0x00, 0x01, // Stream: 1
1760 0x68, 0x65, 0x6c, 0x6c, // Payload
1761 0x6f, //
1762 };
1763 SpdyDataIR data_ir(1, "hello");
1764 data_ir.set_fin(true);
1765 SpdySerializedFrame frame(framer.SerializeData(data_ir));
1766 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
1767 }
1768
1769 {
1770 const char kDescription[] = "Empty data frame";
1771 const unsigned char kH2FrameData[] = {
1772 0x00, 0x00, 0x00, // Length: 0
1773 0x00, // Type: DATA
1774 0x00, // Flags: none
1775 0x00, 0x00, 0x00, 0x01, // Stream: 1
1776 };
1777 SpdyDataIR data_ir(1, "");
1778 SpdySerializedFrame frame(framer.SerializeData(data_ir));
1779 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
1780
1781 frame = framer.SerializeDataFrameHeaderWithPaddingLengthField(data_ir);
1782 CompareCharArraysWithHexError(
1783 kDescription, reinterpret_cast<const unsigned char*>(frame.data()),
1784 framer.GetDataFrameMinimumSize(), kH2FrameData,
1785 framer.GetDataFrameMinimumSize());
1786 }
1787
1788 {
1789 const char kDescription[] = "Data frame with max stream ID";
1790 const unsigned char kH2FrameData[] = {
1791 0x00, 0x00, 0x05, // Length: 5
1792 0x00, // Type: DATA
1793 0x01, // Flags: END_STREAM
1794 0x7f, 0xff, 0xff, 0xff, // Stream: 0x7fffffff
1795 0x68, 0x65, 0x6c, 0x6c, // Payload
1796 0x6f, //
1797 };
1798 SpdyDataIR data_ir(0x7fffffff, "hello");
1799 data_ir.set_fin(true);
1800 SpdySerializedFrame frame(framer.SerializeData(data_ir));
1801 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
1802 }
1803 }
1804
1805 TEST_P(SpdyFramerTest, CreateRstStream) {
1806 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
1807
1808 {
1809 const char kDescription[] = "RST_STREAM frame";
1810 const unsigned char kH2FrameData[] = {
1811 0x00, 0x00, 0x04, // Length: 4
1812 0x03, // Type: RST_STREAM
1813 0x00, // Flags: none
1814 0x00, 0x00, 0x00, 0x01, // Stream: 1
1815 0x00, 0x00, 0x00, 0x01, // Error: PROTOCOL_ERROR
1816 };
1817 SpdyRstStreamIR rst_stream(1, ERROR_CODE_PROTOCOL_ERROR);
1818 SpdySerializedFrame frame(framer.SerializeRstStream(rst_stream));
1819 if (use_output_) {
1820 ASSERT_TRUE(framer.SerializeRstStream(rst_stream, &output_));
1821 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
1822 }
1823 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
1824 }
1825
1826 {
1827 const char kDescription[] = "RST_STREAM frame with max stream ID";
1828 const unsigned char kH2FrameData[] = {
1829 0x00, 0x00, 0x04, // Length: 4
1830 0x03, // Type: RST_STREAM
1831 0x00, // Flags: none
1832 0x7f, 0xff, 0xff, 0xff, // Stream: 0x7fffffff
1833 0x00, 0x00, 0x00, 0x01, // Error: PROTOCOL_ERROR
1834 };
1835 SpdyRstStreamIR rst_stream(0x7FFFFFFF, ERROR_CODE_PROTOCOL_ERROR);
1836 SpdySerializedFrame frame(framer.SerializeRstStream(rst_stream));
1837 if (use_output_) {
1838 output_.Reset();
1839 ASSERT_TRUE(framer.SerializeRstStream(rst_stream, &output_));
1840 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
1841 }
1842 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
1843 }
1844
1845 {
1846 const char kDescription[] = "RST_STREAM frame with max status code";
1847 const unsigned char kH2FrameData[] = {
1848 0x00, 0x00, 0x04, // Length: 4
1849 0x03, // Type: RST_STREAM
1850 0x00, // Flags: none
1851 0x7f, 0xff, 0xff, 0xff, // Stream: 0x7fffffff
1852 0x00, 0x00, 0x00, 0x02, // Error: INTERNAL_ERROR
1853 };
1854 SpdyRstStreamIR rst_stream(0x7FFFFFFF, ERROR_CODE_INTERNAL_ERROR);
1855 SpdySerializedFrame frame(framer.SerializeRstStream(rst_stream));
1856 if (use_output_) {
1857 output_.Reset();
1858 ASSERT_TRUE(framer.SerializeRstStream(rst_stream, &output_));
1859 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
1860 }
1861 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
1862 }
1863 }
1864
1865 TEST_P(SpdyFramerTest, CreateSettings) {
1866 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
1867
1868 {
1869 const char kDescription[] = "Network byte order SETTINGS frame";
1870
1871 const unsigned char kH2FrameData[] = {
1872 0x00, 0x00, 0x06, // Length: 6
1873 0x04, // Type: SETTINGS
1874 0x00, // Flags: none
1875 0x00, 0x00, 0x00, 0x00, // Stream: 0
1876 0x00, 0x04, // Param: INITIAL_WINDOW_SIZE
1877 0x0a, 0x0b, 0x0c, 0x0d, // Value: 168496141
1878 };
1879
1880 uint32_t kValue = 0x0a0b0c0d;
1881 SpdySettingsIR settings_ir;
1882
1883 SpdySettingsIds kId = SETTINGS_INITIAL_WINDOW_SIZE;
1884 settings_ir.AddSetting(kId, kValue);
1885
1886 SpdySerializedFrame frame(framer.SerializeSettings(settings_ir));
1887 if (use_output_) {
1888 ASSERT_TRUE(framer.SerializeSettings(settings_ir, &output_));
1889 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
1890 }
1891 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
1892 }
1893
1894 {
1895 const char kDescription[] = "Basic SETTINGS frame";
1896 // These end up seemingly out of order because of the way that our internal
1897 // ordering for settings_ir works. HTTP2 has no requirement on ordering on
1898 // the wire.
1899 const unsigned char kH2FrameData[] = {
1900 0x00, 0x00, 0x18, // Length: 24
1901 0x04, // Type: SETTINGS
1902 0x00, // Flags: none
1903 0x00, 0x00, 0x00, 0x00, // Stream: 0
1904 0x00, 0x01, // Param: HEADER_TABLE_SIZE
1905 0x00, 0x00, 0x00, 0x05, // Value: 5
1906 0x00, 0x02, // Param: ENABLE_PUSH
1907 0x00, 0x00, 0x00, 0x06, // Value: 6
1908 0x00, 0x03, // Param: MAX_CONCURRENT_STREAMS
1909 0x00, 0x00, 0x00, 0x07, // Value: 7
1910 0x00, 0x04, // Param: INITIAL_WINDOW_SIZE
1911 0x00, 0x00, 0x00, 0x08, // Value: 8
1912 };
1913
1914 SpdySettingsIR settings_ir;
1915 settings_ir.AddSetting(SETTINGS_HEADER_TABLE_SIZE, 5);
1916 settings_ir.AddSetting(SETTINGS_ENABLE_PUSH, 6);
1917 settings_ir.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, 7);
1918 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 8);
1919 SpdySerializedFrame frame(framer.SerializeSettings(settings_ir));
1920 if (use_output_) {
1921 output_.Reset();
1922 ASSERT_TRUE(framer.SerializeSettings(settings_ir, &output_));
1923 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
1924 }
1925
1926 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
1927 }
1928
1929 {
1930 const char kDescription[] = "Empty SETTINGS frame";
1931
1932 const unsigned char kH2FrameData[] = {
1933 0x00, 0x00, 0x00, // Length: 0
1934 0x04, // Type: SETTINGS
1935 0x00, // Flags: none
1936 0x00, 0x00, 0x00, 0x00, // Stream: 0
1937 };
1938 SpdySettingsIR settings_ir;
1939 SpdySerializedFrame frame(framer.SerializeSettings(settings_ir));
1940 if (use_output_) {
1941 output_.Reset();
1942 ASSERT_TRUE(framer.SerializeSettings(settings_ir, &output_));
1943 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
1944 }
1945
1946 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
1947 }
1948 }
1949
1950 TEST_P(SpdyFramerTest, CreatePingFrame) {
1951 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
1952
1953 {
1954 const char kDescription[] = "PING frame";
1955 const unsigned char kH2FrameData[] = {
1956 0x00, 0x00, 0x08, // Length: 8
1957 0x06, // Type: PING
1958 0x00, // Flags: none
1959 0x00, 0x00, 0x00, 0x00, // Stream: 0
1960 0x12, 0x34, 0x56, 0x78, // Opaque
1961 0x9a, 0xbc, 0xde, 0xff, // Data
1962 };
1963 const unsigned char kH2FrameDataWithAck[] = {
1964 0x00, 0x00, 0x08, // Length: 8
1965 0x06, // Type: PING
1966 0x01, // Flags: ACK
1967 0x00, 0x00, 0x00, 0x00, // Stream: 0
1968 0x12, 0x34, 0x56, 0x78, // Opaque
1969 0x9a, 0xbc, 0xde, 0xff, // Data
1970 };
1971 SpdySerializedFrame frame;
1972 const SpdyPingId kPingId = 0x123456789abcdeffULL;
1973 SpdyPingIR ping_ir(kPingId);
1974 // Tests SpdyPingIR when the ping is not an ack.
1975 ASSERT_FALSE(ping_ir.is_ack());
1976 frame = framer.SerializePing(ping_ir);
1977 if (use_output_) {
1978 ASSERT_TRUE(framer.SerializePing(ping_ir, &output_));
1979 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
1980 }
1981 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
1982
1983 // Tests SpdyPingIR when the ping is an ack.
1984 ping_ir.set_is_ack(true);
1985 frame = framer.SerializePing(ping_ir);
1986 if (use_output_) {
1987 output_.Reset();
1988 ASSERT_TRUE(framer.SerializePing(ping_ir, &output_));
1989 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
1990 }
1991 CompareFrame(kDescription, frame, kH2FrameDataWithAck,
1992 arraysize(kH2FrameDataWithAck));
1993 }
1994 }
1995
1996 TEST_P(SpdyFramerTest, CreateGoAway) {
1997 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
1998
1999 {
2000 const char kDescription[] = "GOAWAY frame";
2001 const unsigned char kH2FrameData[] = {
2002 0x00, 0x00, 0x0a, // Length: 10
2003 0x07, // Type: GOAWAY
2004 0x00, // Flags: none
2005 0x00, 0x00, 0x00, 0x00, // Stream: 0
2006 0x00, 0x00, 0x00, 0x00, // Last: 0
2007 0x00, 0x00, 0x00, 0x00, // Error: NO_ERROR
2008 0x47, 0x41, // Description
2009 };
2010 SpdyGoAwayIR goaway_ir(0, ERROR_CODE_NO_ERROR, "GA");
2011 SpdySerializedFrame frame(framer.SerializeGoAway(goaway_ir));
2012 if (use_output_) {
2013 ASSERT_TRUE(framer.SerializeGoAway(goaway_ir, &output_));
2014 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
2015 }
2016 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
2017 }
2018
2019 {
2020 const char kDescription[] = "GOAWAY frame with max stream ID, status";
2021 const unsigned char kH2FrameData[] = {
2022 0x00, 0x00, 0x0a, // Length: 10
2023 0x07, // Type: GOAWAY
2024 0x00, // Flags: none
2025 0x00, 0x00, 0x00, 0x00, // Stream: 0
2026 0x7f, 0xff, 0xff, 0xff, // Last: 0x7fffffff
2027 0x00, 0x00, 0x00, 0x02, // Error: INTERNAL_ERROR
2028 0x47, 0x41, // Description
2029 };
2030 SpdyGoAwayIR goaway_ir(0x7FFFFFFF, ERROR_CODE_INTERNAL_ERROR, "GA");
2031 SpdySerializedFrame frame(framer.SerializeGoAway(goaway_ir));
2032 if (use_output_) {
2033 output_.Reset();
2034 ASSERT_TRUE(framer.SerializeGoAway(goaway_ir, &output_));
2035 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
2036 }
2037 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
2038 }
2039 }
2040
2041 TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
2042 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
2043
2044 {
2045 const char kDescription[] = "HEADERS frame, no FIN";
2046 // frame-format off
2047 const unsigned char kH2FrameData[] = {
2048 0x00, 0x00, 0x12, // Length: 18
2049 0x01, // Type: HEADERS
2050 0x04, // Flags: END_HEADERS
2051 0x00, 0x00, 0x00, 0x01, // Stream: 1
2052
2053 0x00, // Unindexed Entry
2054 0x03, // Name Len: 3
2055 0x62, 0x61, 0x72, // bar
2056 0x03, // Value Len: 3
2057 0x66, 0x6f, 0x6f, // foo
2058
2059 0x00, // Unindexed Entry
2060 0x03, // Name Len: 3
2061 0x66, 0x6f, 0x6f, // foo
2062 0x03, // Value Len: 3
2063 0x62, 0x61, 0x72, // bar
2064 };
2065 // frame-format on
2066
2067 SpdyHeadersIR headers(1);
2068 headers.SetHeader("bar", "foo");
2069 headers.SetHeader("foo", "bar");
2070 SpdySerializedFrame frame(SpdyFramerPeer::SerializeHeaders(
2071 &framer, headers, use_output_ ? &output_ : nullptr));
2072 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
2073 }
2074
2075 {
2076 const char kDescription[] =
2077 "HEADERS frame with a 0-length header name, FIN, max stream ID";
2078 // frame-format off
2079 const unsigned char kH2FrameData[] = {
2080 0x00, 0x00, 0x0f, // Length: 15
2081 0x01, // Type: HEADERS
2082 0x05, // Flags: END_STREAM|END_HEADERS
2083 0x7f, 0xff, 0xff, 0xff, // Stream: 2147483647
2084
2085 0x00, // Unindexed Entry
2086 0x00, // Name Len: 0
2087 0x03, // Value Len: 3
2088 0x66, 0x6f, 0x6f, // foo
2089
2090 0x00, // Unindexed Entry
2091 0x03, // Name Len: 3
2092 0x66, 0x6f, 0x6f, // foo
2093 0x03, // Value Len: 3
2094 0x62, 0x61, 0x72, // bar
2095 };
2096 // frame-format on
2097 SpdyHeadersIR headers(0x7fffffff);
2098 headers.set_fin(true);
2099 headers.SetHeader("", "foo");
2100 headers.SetHeader("foo", "bar");
2101 SpdySerializedFrame frame(SpdyFramerPeer::SerializeHeaders(
2102 &framer, headers, use_output_ ? &output_ : nullptr));
2103 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
2104 }
2105
2106 {
2107 const char kDescription[] =
2108 "HEADERS frame with a 0-length header val, FIN, max stream ID";
2109 // frame-format off
2110 const unsigned char kH2FrameData[] = {
2111 0x00, 0x00, 0x0f, // Length: 15
2112 0x01, // Type: HEADERS
2113 0x05, // Flags: END_STREAM|END_HEADERS
2114 0x7f, 0xff, 0xff, 0xff, // Stream: 2147483647
2115
2116 0x00, // Unindexed Entry
2117 0x03, // Name Len: 3
2118 0x62, 0x61, 0x72, // bar
2119 0x03, // Value Len: 3
2120 0x66, 0x6f, 0x6f, // foo
2121
2122 0x00, // Unindexed Entry
2123 0x03, // Name Len: 3
2124 0x66, 0x6f, 0x6f, // foo
2125 0x00, // Value Len: 0
2126 };
2127 // frame-format on
2128 SpdyHeadersIR headers_ir(0x7fffffff);
2129 headers_ir.set_fin(true);
2130 headers_ir.SetHeader("bar", "foo");
2131 headers_ir.SetHeader("foo", "");
2132 SpdySerializedFrame frame(SpdyFramerPeer::SerializeHeaders(
2133 &framer, headers_ir, use_output_ ? &output_ : nullptr));
2134 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
2135 }
2136
2137 {
2138 const char kDescription[] =
2139 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri";
2140
2141 // frame-format off
2142 const unsigned char kH2FrameData[] = {
2143 0x00, 0x00, 0x14, // Length: 20
2144 0x01, // Type: HEADERS
2145 0x25, // Flags: END_STREAM|END_HEADERS|PRIORITY
2146 0x7f, 0xff, 0xff, 0xff, // Stream: 2147483647
2147 0x00, 0x00, 0x00, 0x00, // Parent: 0
2148 0xdb, // Weight: 220
2149
2150 0x00, // Unindexed Entry
2151 0x03, // Name Len: 3
2152 0x62, 0x61, 0x72, // bar
2153 0x03, // Value Len: 3
2154 0x66, 0x6f, 0x6f, // foo
2155
2156 0x00, // Unindexed Entry
2157 0x03, // Name Len: 3
2158 0x66, 0x6f, 0x6f, // foo
2159 0x00, // Value Len: 0
2160 };
2161 // frame-format on
2162 SpdyHeadersIR headers_ir(0x7fffffff);
2163 headers_ir.set_fin(true);
2164 headers_ir.set_has_priority(true);
2165 headers_ir.set_weight(220);
2166 headers_ir.SetHeader("bar", "foo");
2167 headers_ir.SetHeader("foo", "");
2168 SpdySerializedFrame frame(SpdyFramerPeer::SerializeHeaders(
2169 &framer, headers_ir, use_output_ ? &output_ : nullptr));
2170 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
2171 }
2172
2173 {
2174 const char kDescription[] =
2175 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri, "
2176 "exclusive=true, parent_stream=0";
2177
2178 // frame-format off
2179 const unsigned char kV4FrameData[] = {
2180 0x00, 0x00, 0x14, // Length: 20
2181 0x01, // Type: HEADERS
2182 0x25, // Flags: END_STREAM|END_HEADERS|PRIORITY
2183 0x7f, 0xff, 0xff, 0xff, // Stream: 2147483647
2184 0x80, 0x00, 0x00, 0x00, // Parent: 0 (Exclusive)
2185 0xdb, // Weight: 220
2186
2187 0x00, // Unindexed Entry
2188 0x03, // Name Len: 3
2189 0x62, 0x61, 0x72, // bar
2190 0x03, // Value Len: 3
2191 0x66, 0x6f, 0x6f, // foo
2192
2193 0x00, // Unindexed Entry
2194 0x03, // Name Len: 3
2195 0x66, 0x6f, 0x6f, // foo
2196 0x00, // Value Len: 0
2197 };
2198 // frame-format on
2199 SpdyHeadersIR headers_ir(0x7fffffff);
2200 headers_ir.set_fin(true);
2201 headers_ir.set_has_priority(true);
2202 headers_ir.set_weight(220);
2203 headers_ir.set_exclusive(true);
2204 headers_ir.set_parent_stream_id(0);
2205 headers_ir.SetHeader("bar", "foo");
2206 headers_ir.SetHeader("foo", "");
2207 SpdySerializedFrame frame(SpdyFramerPeer::SerializeHeaders(
2208 &framer, headers_ir, use_output_ ? &output_ : nullptr));
2209 CompareFrame(kDescription, frame, kV4FrameData, arraysize(kV4FrameData));
2210 }
2211
2212 {
2213 const char kDescription[] =
2214 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri, "
2215 "exclusive=false, parent_stream=max stream ID";
2216
2217 // frame-format off
2218 const unsigned char kV4FrameData[] = {
2219 0x00, 0x00, 0x14, // Length: 20
2220 0x01, // Type: HEADERS
2221 0x25, // Flags: END_STREAM|END_HEADERS|PRIORITY
2222 0x7f, 0xff, 0xff, 0xff, // Stream: 2147483647
2223 0x7f, 0xff, 0xff, 0xff, // Parent: 2147483647
2224 0xdb, // Weight: 220
2225
2226 0x00, // Unindexed Entry
2227 0x03, // Name Len: 3
2228 0x62, 0x61, 0x72, // bar
2229 0x03, // Value Len: 3
2230 0x66, 0x6f, 0x6f, // foo
2231
2232 0x00, // Unindexed Entry
2233 0x03, // Name Len: 3
2234 0x66, 0x6f, 0x6f, // foo
2235 0x00, // Value Len: 0
2236 };
2237 // frame-format on
2238 SpdyHeadersIR headers_ir(0x7fffffff);
2239 headers_ir.set_fin(true);
2240 headers_ir.set_has_priority(true);
2241 headers_ir.set_weight(220);
2242 headers_ir.set_exclusive(false);
2243 headers_ir.set_parent_stream_id(0x7fffffff);
2244 headers_ir.SetHeader("bar", "foo");
2245 headers_ir.SetHeader("foo", "");
2246 SpdySerializedFrame frame(SpdyFramerPeer::SerializeHeaders(
2247 &framer, headers_ir, use_output_ ? &output_ : nullptr));
2248 CompareFrame(kDescription, frame, kV4FrameData, arraysize(kV4FrameData));
2249 }
2250
2251 {
2252 const char kDescription[] =
2253 "HEADERS frame with a 0-length header name, FIN, max stream ID, padded";
2254
2255 // frame-format off
2256 const unsigned char kH2FrameData[] = {
2257 0x00, 0x00, 0x15, // Length: 21
2258 0x01, // Type: HEADERS
2259 0x0d, // Flags: END_STREAM|END_HEADERS|PADDED
2260 0x7f, 0xff, 0xff, 0xff, // Stream: 2147483647
2261 0x05, // PadLen: 5 trailing bytes
2262
2263 0x00, // Unindexed Entry
2264 0x00, // Name Len: 0
2265 0x03, // Value Len: 3
2266 0x66, 0x6f, 0x6f, // foo
2267
2268 0x00, // Unindexed Entry
2269 0x03, // Name Len: 3
2270 0x66, 0x6f, 0x6f, // foo
2271 0x03, // Value Len: 3
2272 0x62, 0x61, 0x72, // bar
2273
2274 0x00, 0x00, 0x00, 0x00, // Padding
2275 0x00, // Padding
2276 };
2277 // frame-format on
2278 SpdyHeadersIR headers_ir(0x7fffffff);
2279 headers_ir.set_fin(true);
2280 headers_ir.SetHeader("", "foo");
2281 headers_ir.SetHeader("foo", "bar");
2282 headers_ir.set_padding_len(6);
2283 SpdySerializedFrame frame(SpdyFramerPeer::SerializeHeaders(
2284 &framer, headers_ir, use_output_ ? &output_ : nullptr));
2285 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
2286 }
2287 }
2288
2289 TEST_P(SpdyFramerTest, CreateWindowUpdate) {
2290 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
2291
2292 {
2293 const char kDescription[] = "WINDOW_UPDATE frame";
2294 const unsigned char kH2FrameData[] = {
2295 0x00, 0x00, 0x04, // Length: 4
2296 0x08, // Type: WINDOW_UPDATE
2297 0x00, // Flags: none
2298 0x00, 0x00, 0x00, 0x01, // Stream: 1
2299 0x00, 0x00, 0x00, 0x01, // Increment: 1
2300 };
2301 SpdySerializedFrame frame(
2302 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 1)));
2303 if (use_output_) {
2304 output_.Reset();
2305 ASSERT_TRUE(
2306 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 1), &output_));
2307 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
2308 }
2309 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
2310 }
2311
2312 {
2313 const char kDescription[] = "WINDOW_UPDATE frame with max stream ID";
2314 const unsigned char kH2FrameData[] = {
2315 0x00, 0x00, 0x04, // Length: 4
2316 0x08, // Type: WINDOW_UPDATE
2317 0x00, // Flags: none
2318 0x7f, 0xff, 0xff, 0xff, // Stream: 0x7fffffff
2319 0x00, 0x00, 0x00, 0x01, // Increment: 1
2320 };
2321 SpdySerializedFrame frame(
2322 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(0x7FFFFFFF, 1)));
2323 if (use_output_) {
2324 output_.Reset();
2325 ASSERT_TRUE(framer.SerializeWindowUpdate(
2326 SpdyWindowUpdateIR(0x7FFFFFFF, 1), &output_));
2327 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
2328 }
2329 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
2330 }
2331
2332 {
2333 const char kDescription[] = "WINDOW_UPDATE frame with max window delta";
2334 const unsigned char kH2FrameData[] = {
2335 0x00, 0x00, 0x04, // Length: 4
2336 0x08, // Type: WINDOW_UPDATE
2337 0x00, // Flags: none
2338 0x00, 0x00, 0x00, 0x01, // Stream: 1
2339 0x7f, 0xff, 0xff, 0xff, // Increment: 0x7fffffff
2340 };
2341 SpdySerializedFrame frame(
2342 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 0x7FFFFFFF)));
2343 if (use_output_) {
2344 output_.Reset();
2345 ASSERT_TRUE(framer.SerializeWindowUpdate(
2346 SpdyWindowUpdateIR(1, 0x7FFFFFFF), &output_));
2347 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
2348 }
2349 CompareFrame(kDescription, frame, kH2FrameData, arraysize(kH2FrameData));
2350 }
2351 }
2352
2353 TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
2354 {
2355 // Test framing PUSH_PROMISE without padding.
2356 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
2357 const char kDescription[] = "PUSH_PROMISE frame without padding";
2358
2359 // frame-format off
2360 const unsigned char kFrameData[] = {
2361 0x00, 0x00, 0x16, // Length: 22
2362 0x05, // Type: PUSH_PROMISE
2363 0x04, // Flags: END_HEADERS
2364 0x00, 0x00, 0x00, 0x29, // Stream: 41
2365 0x00, 0x00, 0x00, 0x3a, // Promise: 58
2366
2367 0x00, // Unindexed Entry
2368 0x03, // Name Len: 3
2369 0x62, 0x61, 0x72, // bar
2370 0x03, // Value Len: 3
2371 0x66, 0x6f, 0x6f, // foo
2372
2373 0x00, // Unindexed Entry
2374 0x03, // Name Len: 3
2375 0x66, 0x6f, 0x6f, // foo
2376 0x03, // Value Len: 3
2377 0x62, 0x61, 0x72, // bar
2378 };
2379 // frame-format on
2380
2381 SpdyPushPromiseIR push_promise(41, 58);
2382 push_promise.SetHeader("bar", "foo");
2383 push_promise.SetHeader("foo", "bar");
2384 SpdySerializedFrame frame(SpdyFramerPeer::SerializePushPromise(
2385 &framer, push_promise, use_output_ ? &output_ : nullptr));
2386 CompareFrame(kDescription, frame, kFrameData, arraysize(kFrameData));
2387 }
2388
2389 {
2390 // Test framing PUSH_PROMISE with one byte of padding.
2391 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
2392 const char kDescription[] = "PUSH_PROMISE frame with one byte of padding";
2393
2394 // frame-format off
2395 const unsigned char kFrameData[] = {
2396 0x00, 0x00, 0x17, // Length: 23
2397 0x05, // Type: PUSH_PROMISE
2398 0x0c, // Flags: END_HEADERS|PADDED
2399 0x00, 0x00, 0x00, 0x29, // Stream: 41
2400 0x00, // PadLen: 0 trailing bytes
2401 0x00, 0x00, 0x00, 0x3a, // Promise: 58
2402
2403 0x00, // Unindexed Entry
2404 0x03, // Name Len: 3
2405 0x62, 0x61, 0x72, // bar
2406 0x03, // Value Len: 3
2407 0x66, 0x6f, 0x6f, // foo
2408
2409 0x00, // Unindexed Entry
2410 0x03, // Name Len: 3
2411 0x66, 0x6f, 0x6f, // foo
2412 0x03, // Value Len: 3
2413 0x62, 0x61, 0x72, // bar
2414 };
2415 // frame-format on
2416
2417 SpdyPushPromiseIR push_promise(41, 58);
2418 push_promise.set_padding_len(1);
2419 push_promise.SetHeader("bar", "foo");
2420 push_promise.SetHeader("foo", "bar");
2421 output_.Reset();
2422 SpdySerializedFrame frame(SpdyFramerPeer::SerializePushPromise(
2423 &framer, push_promise, use_output_ ? &output_ : nullptr));
2424
2425 CompareFrame(kDescription, frame, kFrameData, arraysize(kFrameData));
2426 }
2427
2428 {
2429 // Test framing PUSH_PROMISE with 177 bytes of padding.
2430 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
2431 const char kDescription[] = "PUSH_PROMISE frame with 177 bytes of padding";
2432
2433 // frame-format off
2434 // clang-format off
2435 const unsigned char kFrameData[] = {
2436 0x00, 0x00, 0xc7, // Length: 199
2437 0x05, // Type: PUSH_PROMISE
2438 0x0c, // Flags: END_HEADERS|PADDED
2439 0x00, 0x00, 0x00, 0x2a, // Stream: 42
2440 0xb0, // PadLen: 176 trailing bytes
2441 0x00, 0x00, 0x00, 0x39, // Promise: 57
2442
2443 0x00, // Unindexed Entry
2444 0x03, // Name Len: 3
2445 0x62, 0x61, 0x72, // bar
2446 0x03, // Value Len: 3
2447 0x66, 0x6f, 0x6f, // foo
2448
2449 0x00, // Unindexed Entry
2450 0x03, // Name Len: 3
2451 0x66, 0x6f, 0x6f, // foo
2452 0x03, // Value Len: 3
2453 0x62, 0x61, 0x72, // bar
2454
2455 // Padding of 176 0x00(s).
2456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2457 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2458 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2460 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2461 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2462 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2463 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2465 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2466 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2467 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2468 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2469 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2470 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2471 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2472 };
2473 // clang-format on
2474 // frame-format on
2475
2476 SpdyPushPromiseIR push_promise(42, 57);
2477 push_promise.set_padding_len(177);
2478 push_promise.SetHeader("bar", "foo");
2479 push_promise.SetHeader("foo", "bar");
2480 output_.Reset();
2481 SpdySerializedFrame frame(SpdyFramerPeer::SerializePushPromise(
2482 &framer, push_promise, use_output_ ? &output_ : nullptr));
2483
2484 CompareFrame(kDescription, frame, kFrameData, arraysize(kFrameData));
2485 }
2486 }
2487
2488 // Regression test for https://crbug.com/464748.
2489 TEST_P(SpdyFramerTest, GetNumberRequiredContinuationFrames) {
2490 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
2491 EXPECT_EQ(1u, SpdyFramerPeer::GetNumberRequiredContinuationFrames(
2492 &framer, 16383 + 16374));
2493 EXPECT_EQ(2u, SpdyFramerPeer::GetNumberRequiredContinuationFrames(
2494 &framer, 16383 + 16374 + 1));
2495 EXPECT_EQ(2u, SpdyFramerPeer::GetNumberRequiredContinuationFrames(
2496 &framer, 16383 + 2 * 16374));
2497 EXPECT_EQ(3u, SpdyFramerPeer::GetNumberRequiredContinuationFrames(
2498 &framer, 16383 + 2 * 16374 + 1));
2499 }
2500
2501 TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
2502 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
2503 const char kDescription[] = "CONTINUATION frame";
2504
2505 // frame-format off
2506 const unsigned char kFrameData[] = {
2507 0x00, 0x00, 0x12, // Length: 18
2508 0x09, // Type: CONTINUATION
2509 0x04, // Flags: END_HEADERS
2510 0x00, 0x00, 0x00, 0x2a, // Stream: 42
2511
2512 0x00, // Unindexed Entry
2513 0x03, // Name Len: 3
2514 0x62, 0x61, 0x72, // bar
2515 0x03, // Value Len: 3
2516 0x66, 0x6f, 0x6f, // foo
2517
2518 0x00, // Unindexed Entry
2519 0x03, // Name Len: 3
2520 0x66, 0x6f, 0x6f, // foo
2521 0x03, // Value Len: 3
2522 0x62, 0x61, 0x72, // bar
2523 };
2524 // frame-format on
2525
2526 SpdyHeaderBlock header_block;
2527 header_block["bar"] = "foo";
2528 header_block["foo"] = "bar";
2529 auto buffer = base::MakeUnique<SpdyString>();
2530 HpackEncoder encoder(ObtainHpackHuffmanTable());
2531 encoder.DisableCompression();
2532 encoder.EncodeHeaderSet(header_block, buffer.get());
2533
2534 SpdyContinuationIR continuation(42);
2535 continuation.take_encoding(std::move(buffer));
2536 continuation.set_end_headers(true);
2537
2538 SpdySerializedFrame frame(framer.SerializeContinuation(continuation));
2539 if (use_output_) {
2540 ASSERT_TRUE(framer.SerializeContinuation(continuation, &output_));
2541 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
2542 }
2543 CompareFrame(kDescription, frame, kFrameData, arraysize(kFrameData));
2544 }
2545
2546 // Test that if we send an unexpected CONTINUATION
2547 // we signal an error (but don't crash).
2548 TEST_P(SpdyFramerTest, SendUnexpectedContinuation) {
2549 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
2550 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
2551 framer.set_visitor(&visitor);
2552
2553 // frame-format off
2554 char kH2FrameData[] = {
2555 0x00, 0x00, 0x12, // Length: 18
2556 0x09, // Type: CONTINUATION
2557 0x04, // Flags: END_HEADERS
2558 0x00, 0x00, 0x00, 0x2a, // Stream: 42
2559
2560 0x00, // Unindexed Entry
2561 0x03, // Name Len: 3
2562 0x62, 0x61, 0x72, // bar
2563 0x03, // Value Len: 3
2564 0x66, 0x6f, 0x6f, // foo
2565
2566 0x00, // Unindexed Entry
2567 0x03, // Name Len: 3
2568 0x66, 0x6f, 0x6f, // foo
2569 0x03, // Value Len: 3
2570 0x62, 0x61, 0x72, // bar
2571 };
2572 // frame-format on
2573
2574 SpdySerializedFrame frame(kH2FrameData, sizeof(kH2FrameData), false);
2575
2576 // We shouldn't have to read the whole frame before we signal an error.
2577 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
2578 EXPECT_GT(frame.size(), framer.ProcessInput(frame.data(), frame.size()));
2579 EXPECT_TRUE(framer.HasError());
2580 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME, framer.spdy_framer_error())
2581 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
2582 }
2583
2584 TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
2585 {
2586 // Test framing in a case such that a PUSH_PROMISE frame, with one byte of
2587 // padding, cannot hold all the data payload, which is overflowed to the
2588 // consecutive CONTINUATION frame.
2589 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
2590 const char kDescription[] =
2591 "PUSH_PROMISE and CONTINUATION frames with one byte of padding";
2592
2593 // frame-format off
2594 const unsigned char kPartialPushPromiseFrameData[] = {
2595 0x00, 0x3f, 0xf6, // Length: 16374
2596 0x05, // Type: PUSH_PROMISE
2597 0x08, // Flags: PADDED
2598 0x00, 0x00, 0x00, 0x2a, // Stream: 42
2599 0x00, // PadLen: 0 trailing bytes
2600 0x00, 0x00, 0x00, 0x39, // Promise: 57
2601
2602 0x00, // Unindexed Entry
2603 0x03, // Name Len: 3
2604 0x78, 0x78, 0x78, // xxx
2605 0x7f, 0x80, 0x7f, // Value Len: 16361
2606 0x78, 0x78, 0x78, 0x78, // xxxx
2607 0x78, 0x78, 0x78, 0x78, // xxxx
2608 0x78, 0x78, 0x78, 0x78, // xxxx
2609 0x78, 0x78, 0x78, 0x78, // xxxx
2610 0x78, 0x78, 0x78, 0x78, // xxxx
2611 0x78, 0x78, 0x78, 0x78, // xxxx
2612 0x78, 0x78, 0x78, 0x78, // xxxx
2613 0x78, 0x78, 0x78, 0x78, // xxxx
2614 0x78, 0x78, 0x78, 0x78, // xxxx
2615 0x78, 0x78, 0x78, 0x78, // xxxx
2616 0x78, 0x78, 0x78, 0x78, // xxxx
2617 0x78, 0x78, 0x78, 0x78, // xxxx
2618 0x78, 0x78, 0x78, 0x78, // xxxx
2619 0x78, 0x78, 0x78, 0x78, // xxxx
2620 0x78, 0x78, 0x78, 0x78, // xxxx
2621 0x78, 0x78, 0x78, 0x78, // xxxx
2622 0x78, 0x78, 0x78, 0x78, // xxxx
2623 0x78, 0x78, 0x78, 0x78, // xxxx
2624 0x78, 0x78, 0x78, 0x78, // xxxx
2625 0x78, 0x78, 0x78, 0x78, // xxxx
2626 0x78, 0x78, 0x78, 0x78, // xxxx
2627 };
2628 const unsigned char kContinuationFrameData[] = {
2629 0x00, 0x00, 0x16, // Length: 22
2630 0x09, // Type: CONTINUATION
2631 0x04, // Flags: END_HEADERS
2632 0x00, 0x00, 0x00, 0x2a, // Stream: 42
2633 0x78, 0x78, 0x78, 0x78, // xxxx
2634 0x78, 0x78, 0x78, 0x78, // xxxx
2635 0x78, 0x78, 0x78, 0x78, // xxxx
2636 0x78, 0x78, 0x78, 0x78, // xxxx
2637 0x78, 0x78, 0x78, 0x78, // xxxx
2638 0x78, // x
2639 };
2640 // frame-format on
2641
2642 SpdyPushPromiseIR push_promise(42, 57);
2643 push_promise.set_padding_len(1);
2644 SpdyString big_value(TestSpdyVisitor::sent_control_frame_max_size(), 'x');
2645 push_promise.SetHeader("xxx", big_value);
2646 SpdySerializedFrame frame(SpdyFramerPeer::SerializePushPromise(
2647 &framer, push_promise, use_output_ ? &output_ : nullptr));
2648
2649 // The entire frame should look like below:
2650 // Name Length in Byte
2651 // ------------------------------------------- Begin of PUSH_PROMISE frame
2652 // PUSH_PROMISE header 9
2653 // Pad length field 1
2654 // Promised stream 4
2655 // Length field of key 2
2656 // Content of key 3
2657 // Length field of value 3
2658 // Part of big_value 16361
2659 // ------------------------------------------- Begin of CONTINUATION frame
2660 // CONTINUATION header 9
2661 // Remaining of big_value 22
2662 // ------------------------------------------- End
2663
2664 // Length of everything listed above except big_value.
2665 int len_non_data_payload = 31;
2666 EXPECT_EQ(
2667 TestSpdyVisitor::sent_control_frame_max_size() + len_non_data_payload,
2668 frame.size());
2669
2670 // Partially compare the PUSH_PROMISE frame against the template.
2671 const unsigned char* frame_data =
2672 reinterpret_cast<const unsigned char*>(frame.data());
2673 CompareCharArraysWithHexError(
2674 kDescription, frame_data, arraysize(kPartialPushPromiseFrameData),
2675 kPartialPushPromiseFrameData, arraysize(kPartialPushPromiseFrameData));
2676
2677 // Compare the CONTINUATION frame against the template.
2678 frame_data += TestSpdyVisitor::sent_control_frame_max_size();
2679 CompareCharArraysWithHexError(
2680 kDescription, frame_data, arraysize(kContinuationFrameData),
2681 kContinuationFrameData, arraysize(kContinuationFrameData));
2682 }
2683 }
2684
2685 TEST_P(SpdyFramerTest, CreateAltSvc) {
2686 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
2687
2688 const char kDescription[] = "ALTSVC frame";
2689 const unsigned char kType = SerializeFrameType(SpdyFrameType::ALTSVC);
2690 const unsigned char kFrameData[] = {
2691 0x00, 0x00, 0x49, kType, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x06, 'o',
2692 'r', 'i', 'g', 'i', 'n', 'p', 'i', 'd', '1', '=', '"', 'h',
2693 'o', 's', 't', ':', '4', '4', '3', '"', ';', ' ', 'm', 'a',
2694 '=', '5', ',', 'p', '%', '2', '2', '%', '3', 'D', 'i', '%',
2695 '3', 'A', 'd', '=', '"', 'h', '_', '\\', '\\', 'o', '\\', '"',
2696 's', 't', ':', '1', '2', '3', '"', ';', ' ', 'm', 'a', '=',
2697 '4', '2', ';', ' ', 'v', '=', '"', '2', '4', '"'};
2698 SpdyAltSvcIR altsvc_ir(3);
2699 altsvc_ir.set_origin("origin");
2700 altsvc_ir.add_altsvc(SpdyAltSvcWireFormat::AlternativeService(
2701 "pid1", "host", 443, 5, SpdyAltSvcWireFormat::VersionVector()));
2702 altsvc_ir.add_altsvc(SpdyAltSvcWireFormat::AlternativeService(
2703 "p\"=i:d", "h_\\o\"st", 123, 42,
2704 SpdyAltSvcWireFormat::VersionVector{24}));
2705 SpdySerializedFrame frame(framer.SerializeFrame(altsvc_ir));
2706 if (use_output_) {
2707 ASSERT_TRUE(framer.SerializeFrame(altsvc_ir, &output_));
2708 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
2709 }
2710 CompareFrame(kDescription, frame, kFrameData, arraysize(kFrameData));
2711 }
2712
2713 TEST_P(SpdyFramerTest, CreatePriority) {
2714 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
2715
2716 const char kDescription[] = "PRIORITY frame";
2717 const unsigned char kFrameData[] = {
2718 0x00, 0x00, 0x05, // Length: 5
2719 0x02, // Type: PRIORITY
2720 0x00, // Flags: none
2721 0x00, 0x00, 0x00, 0x02, // Stream: 2
2722 0x80, 0x00, 0x00, 0x01, // Parent: 1 (Exclusive)
2723 0x10, // Weight: 17
2724 };
2725 SpdyPriorityIR priority_ir(2, 1, 17, true);
2726 SpdySerializedFrame frame(framer.SerializeFrame(priority_ir));
2727 if (use_output_) {
2728 ASSERT_TRUE(framer.SerializeFrame(priority_ir, &output_));
2729 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
2730 }
2731 CompareFrame(kDescription, frame, kFrameData, arraysize(kFrameData));
2732 SpdyPriorityIR priority2(2);
2733 priority2.set_parent_stream_id(1);
2734 priority2.set_weight(17);
2735 priority2.set_exclusive(true);
2736 if (use_output_) {
2737 output_.Reset();
2738 ASSERT_TRUE(framer.SerializeFrame(priority2, &output_));
2739 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
2740 } else {
2741 frame = framer.SerializeFrame(priority2);
2742 }
2743 CompareFrame(kDescription, frame, kFrameData, arraysize(kFrameData));
2744 }
2745
2746 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) {
2747 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
2748 SpdyHeadersIR headers_ir(1);
2749 headers_ir.SetHeader("alpha", "beta");
2750 headers_ir.SetHeader("gamma", "delta");
2751 SpdySerializedFrame control_frame(SpdyFramerPeer::SerializeHeaders(
2752 &framer, headers_ir, use_output_ ? &output_ : nullptr));
2753 TestSpdyVisitor visitor(SpdyFramer::ENABLE_COMPRESSION);
2754 visitor.SimulateInFramer(
2755 reinterpret_cast<unsigned char*>(control_frame.data()),
2756 control_frame.size());
2757 EXPECT_EQ(1, visitor.headers_frame_count_);
2758 EXPECT_EQ(0, visitor.control_frame_header_data_count_);
2759 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
2760 EXPECT_EQ(0, visitor.end_of_stream_count_);
2761 EXPECT_EQ(headers_ir.header_block(), visitor.headers_);
2762 }
2763
2764 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) {
2765 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
2766 SpdyHeadersIR headers_ir(1);
2767 headers_ir.set_fin(true);
2768 headers_ir.SetHeader("alpha", "beta");
2769 headers_ir.SetHeader("gamma", "delta");
2770 SpdySerializedFrame control_frame(SpdyFramerPeer::SerializeHeaders(
2771 &framer, headers_ir, use_output_ ? &output_ : nullptr));
2772 TestSpdyVisitor visitor(SpdyFramer::ENABLE_COMPRESSION);
2773 visitor.SimulateInFramer(
2774 reinterpret_cast<unsigned char*>(control_frame.data()),
2775 control_frame.size());
2776 EXPECT_EQ(1, visitor.headers_frame_count_);
2777 EXPECT_EQ(0, visitor.control_frame_header_data_count_);
2778 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
2779 EXPECT_EQ(1, visitor.end_of_stream_count_);
2780 EXPECT_EQ(headers_ir.header_block(), visitor.headers_);
2781 }
2782
2783 TEST_P(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) {
2784 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
2785 SpdyHeadersIR headers(1);
2786 headers.set_padding_len(256);
2787
2788 // Exact payload length will change with HPACK, but this should be long
2789 // enough to cause an overflow.
2790 const size_t kBigValueSize = TestSpdyVisitor::sent_control_frame_max_size();
2791 SpdyString big_value(kBigValueSize, 'x');
2792 headers.SetHeader("aa", big_value);
2793 SpdySerializedFrame control_frame(SpdyFramerPeer::SerializeHeaders(
2794 &framer, headers, use_output_ ? &output_ : nullptr));
2795 EXPECT_GT(control_frame.size(),
2796 TestSpdyVisitor::sent_control_frame_max_size());
2797
2798 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
2799 visitor.SimulateInFramer(
2800 reinterpret_cast<unsigned char*>(control_frame.data()),
2801 control_frame.size());
2802 EXPECT_TRUE(visitor.header_buffer_valid_);
2803 EXPECT_EQ(0, visitor.error_count_);
2804 EXPECT_EQ(1, visitor.headers_frame_count_);
2805 EXPECT_EQ(1, visitor.continuation_count_);
2806 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
2807 }
2808
2809 TEST_P(SpdyFramerTest, MultipleContinuationFramesWithIterator) {
2810 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
2811 auto headers = base::MakeUnique<SpdyHeadersIR>(1);
2812 headers->set_padding_len(256);
2813
2814 // Exact payload length will change with HPACK, but this should be long
2815 // enough to cause an overflow.
2816 const size_t kBigValueSize = TestSpdyVisitor::sent_control_frame_max_size();
2817 SpdyString big_valuex(kBigValueSize, 'x');
2818 headers->SetHeader("aa", big_valuex);
2819 SpdyString big_valuez(kBigValueSize, 'z');
2820 headers->SetHeader("bb", big_valuez);
2821
2822 SpdyFramer::SpdyHeaderFrameIterator frame_it(&framer, std::move(headers));
2823
2824 EXPECT_TRUE(frame_it.HasNextFrame());
2825 EXPECT_TRUE(frame_it.NextFrame(&output_));
2826 SpdySerializedFrame headers_frame(output_.Begin(), output_.Size(), false);
2827 EXPECT_EQ(headers_frame.size(),
2828 TestSpdyVisitor::sent_control_frame_max_size());
2829
2830 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
2831 visitor.SimulateInFramer(
2832 reinterpret_cast<unsigned char*>(headers_frame.data()),
2833 headers_frame.size());
2834 EXPECT_TRUE(visitor.header_buffer_valid_);
2835 EXPECT_EQ(0, visitor.error_count_);
2836 EXPECT_EQ(1, visitor.headers_frame_count_);
2837 EXPECT_EQ(0, visitor.continuation_count_);
2838 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
2839
2840 output_.Reset();
2841 EXPECT_TRUE(frame_it.HasNextFrame());
2842 EXPECT_TRUE(frame_it.NextFrame(&output_));
2843 SpdySerializedFrame first_cont_frame(output_.Begin(), output_.Size(), false);
2844 EXPECT_EQ(first_cont_frame.size(),
2845 TestSpdyVisitor::sent_control_frame_max_size());
2846
2847 visitor.SimulateInFramer(
2848 reinterpret_cast<unsigned char*>(first_cont_frame.data()),
2849 first_cont_frame.size());
2850 EXPECT_TRUE(visitor.header_buffer_valid_);
2851 EXPECT_EQ(0, visitor.error_count_);
2852 EXPECT_EQ(1, visitor.headers_frame_count_);
2853 EXPECT_EQ(1, visitor.continuation_count_);
2854 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
2855
2856 output_.Reset();
2857 EXPECT_TRUE(frame_it.HasNextFrame());
2858 EXPECT_TRUE(frame_it.NextFrame(&output_));
2859 SpdySerializedFrame second_cont_frame(output_.Begin(), output_.Size(), false);
2860 EXPECT_LT(second_cont_frame.size(),
2861 TestSpdyVisitor::sent_control_frame_max_size());
2862
2863 visitor.SimulateInFramer(
2864 reinterpret_cast<unsigned char*>(second_cont_frame.data()),
2865 second_cont_frame.size());
2866 EXPECT_TRUE(visitor.header_buffer_valid_);
2867 EXPECT_EQ(0, visitor.error_count_);
2868 EXPECT_EQ(1, visitor.headers_frame_count_);
2869 EXPECT_EQ(2, visitor.continuation_count_);
2870 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
2871
2872 EXPECT_FALSE(frame_it.HasNextFrame());
2873 }
2874
2875 TEST_P(SpdyFramerTest, PushPromiseFramesWithIterator) {
2876 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
2877 auto push_promise = base::MakeUnique<SpdyPushPromiseIR>(1, 2);
2878 push_promise->set_padding_len(256);
2879
2880 // Exact payload length will change with HPACK, but this should be long
2881 // enough to cause an overflow.
2882 const size_t kBigValueSize = TestSpdyVisitor::sent_control_frame_max_size();
2883 SpdyString big_valuex(kBigValueSize, 'x');
2884 push_promise->SetHeader("aa", big_valuex);
2885 SpdyString big_valuez(kBigValueSize, 'z');
2886 push_promise->SetHeader("bb", big_valuez);
2887
2888 SpdyFramer::SpdyPushPromiseFrameIterator frame_it(&framer,
2889 std::move(push_promise));
2890
2891 EXPECT_TRUE(frame_it.HasNextFrame());
2892 EXPECT_TRUE(frame_it.NextFrame(&output_));
2893 SpdySerializedFrame push_promise_frame(output_.Begin(), output_.Size(),
2894 false);
2895 EXPECT_EQ(push_promise_frame.size(),
2896 TestSpdyVisitor::sent_control_frame_max_size());
2897
2898 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
2899 visitor.SimulateInFramer(
2900 reinterpret_cast<unsigned char*>(push_promise_frame.data()),
2901 push_promise_frame.size());
2902 EXPECT_TRUE(visitor.header_buffer_valid_);
2903 EXPECT_EQ(0, visitor.error_count_);
2904 EXPECT_EQ(1, visitor.push_promise_frame_count_);
2905 EXPECT_EQ(0, visitor.continuation_count_);
2906 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
2907
2908 EXPECT_TRUE(frame_it.HasNextFrame());
2909 output_.Reset();
2910 EXPECT_TRUE(frame_it.NextFrame(&output_));
2911 SpdySerializedFrame first_cont_frame(output_.Begin(), output_.Size(), false);
2912
2913 EXPECT_EQ(first_cont_frame.size(),
2914 TestSpdyVisitor::sent_control_frame_max_size());
2915 visitor.SimulateInFramer(
2916 reinterpret_cast<unsigned char*>(first_cont_frame.data()),
2917 first_cont_frame.size());
2918 EXPECT_TRUE(visitor.header_buffer_valid_);
2919 EXPECT_EQ(0, visitor.error_count_);
2920 EXPECT_EQ(1, visitor.push_promise_frame_count_);
2921 EXPECT_EQ(1, visitor.continuation_count_);
2922 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
2923
2924 EXPECT_TRUE(frame_it.HasNextFrame());
2925 output_.Reset();
2926 EXPECT_TRUE(frame_it.NextFrame(&output_));
2927 SpdySerializedFrame second_cont_frame(output_.Begin(), output_.Size(), false);
2928 EXPECT_LT(second_cont_frame.size(),
2929 TestSpdyVisitor::sent_control_frame_max_size());
2930
2931 visitor.SimulateInFramer(
2932 reinterpret_cast<unsigned char*>(second_cont_frame.data()),
2933 second_cont_frame.size());
2934 EXPECT_TRUE(visitor.header_buffer_valid_);
2935 EXPECT_EQ(0, visitor.error_count_);
2936 EXPECT_EQ(1, visitor.push_promise_frame_count_);
2937 EXPECT_EQ(2, visitor.continuation_count_);
2938 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
2939
2940 EXPECT_FALSE(frame_it.HasNextFrame());
2941 }
2942
2943 TEST_P(SpdyFramerTest, TooLargePushPromiseFrameUsesContinuation) {
2944 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
2945 SpdyPushPromiseIR push_promise(1, 2);
2946 push_promise.set_padding_len(256);
2947
2948 // Exact payload length will change with HPACK, but this should be long
2949 // enough to cause an overflow.
2950 const size_t kBigValueSize = TestSpdyVisitor::sent_control_frame_max_size();
2951 SpdyString big_value(kBigValueSize, 'x');
2952 push_promise.SetHeader("aa", big_value);
2953 SpdySerializedFrame control_frame(SpdyFramerPeer::SerializePushPromise(
2954 &framer, push_promise, use_output_ ? &output_ : nullptr));
2955 EXPECT_GT(control_frame.size(),
2956 TestSpdyVisitor::sent_control_frame_max_size());
2957
2958 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
2959 visitor.SimulateInFramer(
2960 reinterpret_cast<unsigned char*>(control_frame.data()),
2961 control_frame.size());
2962 EXPECT_TRUE(visitor.header_buffer_valid_);
2963 EXPECT_EQ(0, visitor.error_count_);
2964 EXPECT_EQ(1, visitor.push_promise_frame_count_);
2965 EXPECT_EQ(1, visitor.continuation_count_);
2966 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
2967 }
2968
2969 // Check that the framer stops delivering header data chunks once the visitor
2970 // declares it doesn't want any more. This is important to guard against
2971 // "zip bomb" types of attacks.
2972 TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) {
2973 const size_t kHeaderBufferChunks = 4;
2974 const size_t kHeaderBufferSize =
2975 TestSpdyVisitor::header_data_chunk_max_size() * kHeaderBufferChunks;
2976 const size_t kBigValueSize = kHeaderBufferSize * 2;
2977 SpdyString big_value(kBigValueSize, 'x');
2978 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
2979 SpdyHeadersIR headers(1);
2980 headers.set_fin(true);
2981 headers.SetHeader("aa", big_value);
2982 SpdySerializedFrame control_frame(SpdyFramerPeer::SerializeHeaders(
2983 &framer, headers, use_output_ ? &output_ : nullptr));
2984 TestSpdyVisitor visitor(SpdyFramer::ENABLE_COMPRESSION);
2985 visitor.set_header_buffer_size(kHeaderBufferSize);
2986 visitor.SimulateInFramer(
2987 reinterpret_cast<unsigned char*>(control_frame.data()),
2988 control_frame.size());
2989 // It's up to the visitor to ignore extraneous header data; the framer
2990 // won't throw an error.
2991 EXPECT_GT(visitor.header_bytes_received_, visitor.header_buffer_.size());
2992 EXPECT_EQ(1, visitor.end_of_stream_count_);
2993 }
2994
2995 TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) {
2996 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
2997 // Create a GoAway frame that has a few extra bytes at the end.
2998 // We create enough overhead to overflow the framer's control frame buffer.
2999 ASSERT_LE(SpdyFramerPeer::ControlFrameBufferSize(), 250u);
3000 const size_t length = SpdyFramerPeer::ControlFrameBufferSize() + 1;
3001
3002 // HTTP/2 GOAWAY frames are only bound by a minimal length, since they may
3003 // carry opaque data. Verify that minimal length is tested.
3004 ASSERT_GT(framer.GetGoAwayMinimumSize(), kFrameHeaderSize);
3005 const size_t less_than_min_length =
3006 framer.GetGoAwayMinimumSize() - kFrameHeaderSize - 1;
3007 ASSERT_LE(less_than_min_length, std::numeric_limits<unsigned char>::max());
3008 const unsigned char kH2Len = static_cast<unsigned char>(less_than_min_length);
3009 const unsigned char kH2FrameData[] = {
3010 0x00, 0x00, kH2Len, // Length: min length - 1
3011 0x07, // Type: GOAWAY
3012 0x00, // Flags: none
3013 0x00, 0x00, 0x00, 0x00, // Stream: 0
3014 0x00, 0x00, 0x00, 0x00, // Last: 0
3015 0x00, 0x00, 0x00, // Truncated Status Field
3016 };
3017 const size_t pad_length = length + kFrameHeaderSize - sizeof(kH2FrameData);
3018 SpdyString pad(pad_length, 'A');
3019 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3020
3021 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
3022 visitor.SimulateInFramer(reinterpret_cast<const unsigned char*>(pad.c_str()),
3023 pad.length());
3024
3025 EXPECT_EQ(1, visitor.error_count_); // This generated an error.
3026 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
3027 visitor.framer_.spdy_framer_error())
3028 << SpdyFramer::SpdyFramerErrorToString(
3029 visitor.framer_.spdy_framer_error());
3030 EXPECT_EQ(0, visitor.goaway_count_); // Frame not parsed.
3031 }
3032
3033 TEST_P(SpdyFramerTest, ReadZeroLenSettingsFrame) {
3034 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3035 SpdySettingsIR settings_ir;
3036 SpdySerializedFrame control_frame(framer.SerializeSettings(settings_ir));
3037 if (use_output_) {
3038 ASSERT_TRUE(framer.SerializeSettings(settings_ir, &output_));
3039 control_frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
3040 }
3041 SetFrameLength(&control_frame, 0);
3042 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3043 visitor.SimulateInFramer(
3044 reinterpret_cast<unsigned char*>(control_frame.data()),
3045 framer.GetFrameHeaderSize());
3046 // Zero-len settings frames are permitted as of HTTP/2.
3047 EXPECT_EQ(0, visitor.error_count_);
3048 }
3049
3050 // Tests handling of SETTINGS frames with invalid length.
3051 TEST_P(SpdyFramerTest, ReadBogusLenSettingsFrame) {
3052 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3053 SpdySettingsIR settings_ir;
3054
3055 // Add settings to more than fill the frame so that we don't get a buffer
3056 // overflow when calling SimulateInFramer() below. These settings must be
3057 // distinct parameters because SpdySettingsIR has a map for settings, and will
3058 // collapse multiple copies of the same parameter.
3059 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0x00000002);
3060 settings_ir.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, 0x00000002);
3061 SpdySerializedFrame control_frame(framer.SerializeSettings(settings_ir));
3062 if (use_output_) {
3063 ASSERT_TRUE(framer.SerializeSettings(settings_ir, &output_));
3064 control_frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
3065 }
3066 const size_t kNewLength = 8;
3067 SetFrameLength(&control_frame, kNewLength);
3068 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3069 visitor.SimulateInFramer(
3070 reinterpret_cast<unsigned char*>(control_frame.data()),
3071 framer.GetFrameHeaderSize() + kNewLength);
3072 // Should generate an error, since its not possible to have a
3073 // settings frame of length kNewLength.
3074 EXPECT_EQ(1, visitor.error_count_);
3075 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_SIZE,
3076 visitor.framer_.spdy_framer_error())
3077 << SpdyFramer::SpdyFramerErrorToString(
3078 visitor.framer_.spdy_framer_error());
3079 }
3080
3081 // Tests handling of SETTINGS frames larger than the frame buffer size.
3082 TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) {
3083 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3084 SpdySettingsIR settings_ir;
3085 settings_ir.AddSetting(SETTINGS_HEADER_TABLE_SIZE, 5);
3086 settings_ir.AddSetting(SETTINGS_ENABLE_PUSH, 6);
3087 settings_ir.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, 7);
3088
3089 SpdySerializedFrame control_frame(framer.SerializeSettings(settings_ir));
3090 if (use_output_) {
3091 ASSERT_TRUE(framer.SerializeSettings(settings_ir, &output_));
3092 control_frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
3093 }
3094
3095 EXPECT_LT(SpdyFramerPeer::ControlFrameBufferSize(), control_frame.size());
3096 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3097
3098 // Read all at once.
3099 visitor.SimulateInFramer(
3100 reinterpret_cast<unsigned char*>(control_frame.data()),
3101 control_frame.size());
3102 EXPECT_EQ(0, visitor.error_count_);
3103 EXPECT_EQ(3, visitor.setting_count_);
3104 EXPECT_EQ(1, visitor.settings_ack_sent_);
3105
3106 // Read data in small chunks.
3107 size_t framed_data = 0;
3108 size_t unframed_data = control_frame.size();
3109 size_t kReadChunkSize = 5; // Read five bytes at a time.
3110 while (unframed_data > 0) {
3111 size_t to_read = std::min(kReadChunkSize, unframed_data);
3112 visitor.SimulateInFramer(
3113 reinterpret_cast<unsigned char*>(control_frame.data() + framed_data),
3114 to_read);
3115 unframed_data -= to_read;
3116 framed_data += to_read;
3117 }
3118 EXPECT_EQ(0, visitor.error_count_);
3119 EXPECT_EQ(3 * 2, visitor.setting_count_);
3120 EXPECT_EQ(2, visitor.settings_ack_sent_);
3121 }
3122
3123 // Tests handling of SETTINGS frame with duplicate entries.
3124 TEST_P(SpdyFramerTest, ReadDuplicateSettings) {
3125 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3126
3127 const unsigned char kH2FrameData[] = {
3128 0x00, 0x00, 0x12, // Length: 18
3129 0x04, // Type: SETTINGS
3130 0x00, // Flags: none
3131 0x00, 0x00, 0x00, 0x00, // Stream: 0
3132 0x00, 0x01, // Param: HEADER_TABLE_SIZE
3133 0x00, 0x00, 0x00, 0x02, // Value: 2
3134 0x00, 0x01, // Param: HEADER_TABLE_SIZE
3135 0x00, 0x00, 0x00, 0x03, // Value: 3
3136 0x00, 0x03, // Param: MAX_CONCURRENT_STREAMS
3137 0x00, 0x00, 0x00, 0x03, // Value: 3
3138 };
3139
3140 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3141 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
3142
3143 // In HTTP/2, duplicate settings are allowed;
3144 // each setting replaces the previous value for that setting.
3145 EXPECT_EQ(3, visitor.setting_count_);
3146 EXPECT_EQ(0, visitor.error_count_);
3147 EXPECT_EQ(1, visitor.settings_ack_sent_);
3148 }
3149
3150 // Tests handling of SETTINGS frame with a setting we don't recognize.
3151 TEST_P(SpdyFramerTest, ReadUnknownSettingsId) {
3152 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3153 const unsigned char kH2FrameData[] = {
3154 0x00, 0x00, 0x06, // Length: 6
3155 0x04, // Type: SETTINGS
3156 0x00, // Flags: none
3157 0x00, 0x00, 0x00, 0x00, // Stream: 0
3158 0x00, 0x10, // Param: 16
3159 0x00, 0x00, 0x00, 0x02, // Value: 2
3160 };
3161
3162 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3163 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
3164
3165 // In HTTP/2, we ignore unknown settings because of extensions.
3166 EXPECT_EQ(0, visitor.setting_count_);
3167 EXPECT_EQ(0, visitor.error_count_);
3168 }
3169
3170 TEST_P(SpdyFramerTest, ReadUnknownSettingsWithExtension) {
3171 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3172 const unsigned char kH2FrameData[] = {
3173 0x00, 0x00, 0x0c, // Length: 12
3174 0x04, // Type: SETTINGS
3175 0x00, // Flags: none
3176 0x00, 0x00, 0x00, 0x00, // Stream: 0
3177 0x00, 0x10, // Param: 16
3178 0x00, 0x00, 0x00, 0x02, // Value: 2
3179 0x00, 0x5f, // Param: 95
3180 0x00, 0x01, 0x00, 0x02, // Value: 65538
3181 };
3182
3183 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3184 TestExtension extension;
3185 visitor.set_extension_visitor(&extension);
3186 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
3187
3188 // In HTTP/2, we ignore unknown settings because of extensions.
3189 EXPECT_EQ(0, visitor.setting_count_);
3190 EXPECT_EQ(0, visitor.error_count_);
3191
3192 EXPECT_THAT(
3193 extension.settings_received_,
3194 testing::ElementsAre(testing::Pair(16, 2), testing::Pair(95, 65538)));
3195 }
3196
3197 // Tests handling of SETTINGS frame with entries out of order.
3198 TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) {
3199 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3200 const unsigned char kH2FrameData[] = {
3201 0x00, 0x00, 0x12, // Length: 18
3202 0x04, // Type: SETTINGS
3203 0x00, // Flags: none
3204 0x00, 0x00, 0x00, 0x00, // Stream: 0
3205 0x00, 0x02, // Param: ENABLE_PUSH
3206 0x00, 0x00, 0x00, 0x02, // Value: 2
3207 0x00, 0x01, // Param: HEADER_TABLE_SIZE
3208 0x00, 0x00, 0x00, 0x03, // Value: 3
3209 0x00, 0x03, // Param: MAX_CONCURRENT_STREAMS
3210 0x00, 0x00, 0x00, 0x03, // Value: 3
3211 };
3212
3213 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3214 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
3215
3216 // In HTTP/2, settings are allowed in any order.
3217 EXPECT_EQ(3, visitor.setting_count_);
3218 EXPECT_EQ(0, visitor.error_count_);
3219 }
3220
3221 TEST_P(SpdyFramerTest, ProcessSettingsAckFrame) {
3222 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3223
3224 const unsigned char kFrameData[] = {
3225 0x00, 0x00, 0x00, // Length: 0
3226 0x04, // Type: SETTINGS
3227 0x01, // Flags: ACK
3228 0x00, 0x00, 0x00, 0x00, // Stream: 0
3229 };
3230
3231 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3232 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
3233
3234 EXPECT_EQ(0, visitor.error_count_);
3235 EXPECT_EQ(0, visitor.setting_count_);
3236 EXPECT_EQ(1, visitor.settings_ack_received_);
3237 }
3238
3239 TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) {
3240 const int kPaddingLen = 119;
3241 const char data_payload[] = "hello";
3242
3243 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
3244 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3245 framer.set_visitor(&visitor);
3246
3247 SpdyDataIR data_ir(1, data_payload);
3248 data_ir.set_padding_len(kPaddingLen);
3249 SpdySerializedFrame frame(framer.SerializeData(data_ir));
3250
3251 int bytes_consumed = 0;
3252
3253 // Send the frame header.
3254 EXPECT_CALL(visitor,
3255 OnDataFrameHeader(1, kPaddingLen + strlen(data_payload), false));
3256 CHECK_EQ(framer.GetDataFrameMinimumSize(),
3257 framer.ProcessInput(frame.data(), framer.GetDataFrameMinimumSize()));
3258 CHECK_EQ(framer.state(), SpdyFramer::SPDY_READ_DATA_FRAME_PADDING_LENGTH);
3259 CHECK_EQ(framer.spdy_framer_error(), SpdyFramer::SPDY_NO_ERROR);
3260 bytes_consumed += framer.GetDataFrameMinimumSize();
3261
3262 // Send the padding length field.
3263 EXPECT_CALL(visitor, OnStreamPadding(1, 1));
3264 CHECK_EQ(1u, framer.ProcessInput(frame.data() + bytes_consumed, 1));
3265 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
3266 CHECK_EQ(framer.spdy_framer_error(), SpdyFramer::SPDY_NO_ERROR);
3267 bytes_consumed += 1;
3268
3269 // Send the first two bytes of the data payload, i.e., "he".
3270 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 2));
3271 CHECK_EQ(2u, framer.ProcessInput(frame.data() + bytes_consumed, 2));
3272 CHECK_EQ(framer.state(), SpdyFramer::SPDY_FORWARD_STREAM_FRAME);
3273 CHECK_EQ(framer.spdy_framer_error(), SpdyFramer::SPDY_NO_ERROR);
3274 bytes_consumed += 2;
3275
3276 // Send the rest three bytes of the data payload, i.e., "llo".
3277 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 3));
3278 CHECK_EQ(3u, framer.ProcessInput(frame.data() + bytes_consumed, 3));
3279 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
3280 CHECK_EQ(framer.spdy_framer_error(), SpdyFramer::SPDY_NO_ERROR);
3281 bytes_consumed += 3;
3282
3283 // Send the first 100 bytes of the padding payload.
3284 EXPECT_CALL(visitor, OnStreamPadding(1, 100));
3285 CHECK_EQ(100u, framer.ProcessInput(frame.data() + bytes_consumed, 100));
3286 CHECK_EQ(framer.state(), SpdyFramer::SPDY_CONSUME_PADDING);
3287 CHECK_EQ(framer.spdy_framer_error(), SpdyFramer::SPDY_NO_ERROR);
3288 bytes_consumed += 100;
3289
3290 // Send rest of the padding payload.
3291 EXPECT_CALL(visitor, OnStreamPadding(1, 18));
3292 CHECK_EQ(18u, framer.ProcessInput(frame.data() + bytes_consumed, 18));
3293 CHECK_EQ(framer.state(), SpdyFramer::SPDY_READY_FOR_FRAME);
3294 CHECK_EQ(framer.spdy_framer_error(), SpdyFramer::SPDY_NO_ERROR);
3295 }
3296
3297 TEST_P(SpdyFramerTest, ReadWindowUpdate) {
3298 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3299 SpdySerializedFrame control_frame(
3300 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2)));
3301 if (use_output_) {
3302 ASSERT_TRUE(
3303 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2), &output_));
3304 control_frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
3305 }
3306 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3307 visitor.SimulateInFramer(
3308 reinterpret_cast<unsigned char*>(control_frame.data()),
3309 control_frame.size());
3310 EXPECT_EQ(1u, visitor.last_window_update_stream_);
3311 EXPECT_EQ(2, visitor.last_window_update_delta_);
3312 }
3313
3314 TEST_P(SpdyFramerTest, ReadCompressedPushPromise) {
3315 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3316 SpdyPushPromiseIR push_promise(42, 57);
3317 push_promise.SetHeader("foo", "bar");
3318 push_promise.SetHeader("bar", "foofoo");
3319 SpdySerializedFrame frame(SpdyFramerPeer::SerializePushPromise(
3320 &framer, push_promise, use_output_ ? &output_ : nullptr));
3321 TestSpdyVisitor visitor(SpdyFramer::ENABLE_COMPRESSION);
3322 visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
3323 frame.size());
3324 EXPECT_EQ(42u, visitor.last_push_promise_stream_);
3325 EXPECT_EQ(57u, visitor.last_push_promise_promised_stream_);
3326 EXPECT_EQ(push_promise.header_block(), visitor.headers_);
3327 }
3328
3329 TEST_P(SpdyFramerTest, ReadHeadersWithContinuation) {
3330 // frame-format off
3331 const unsigned char kInput[] = {
3332 0x00, 0x00, 0x14, // Length: 20
3333 0x01, // Type: HEADERS
3334 0x08, // Flags: PADDED
3335 0x00, 0x00, 0x00, 0x01, // Stream: 1
3336 0x03, // PadLen: 3 trailing bytes
3337 0x00, // Unindexed Entry
3338 0x06, // Name Len: 6
3339 'c', 'o', 'o', 'k', 'i', 'e', // Name
3340 0x07, // Value Len: 7
3341 'f', 'o', 'o', '=', 'b', 'a', 'r', // Value
3342 0x00, 0x00, 0x00, // Padding
3343
3344 0x00, 0x00, 0x14, // Length: 20
3345 0x09, // Type: CONTINUATION
3346 0x00, // Flags: none
3347 0x00, 0x00, 0x00, 0x01, // Stream: 1
3348 0x00, // Unindexed Entry
3349 0x06, // Name Len: 6
3350 'c', 'o', 'o', 'k', 'i', 'e', // Name
3351 0x08, // Value Len: 7
3352 'b', 'a', 'z', '=', 'b', 'i', 'n', 'g', // Value
3353 0x00, // Unindexed Entry
3354 0x06, // Name Len: 6
3355 'c', // Name (split)
3356
3357 0x00, 0x00, 0x12, // Length: 18
3358 0x09, // Type: CONTINUATION
3359 0x04, // Flags: END_HEADERS
3360 0x00, 0x00, 0x00, 0x01, // Stream: 1
3361 'o', 'o', 'k', 'i', 'e', // Name (continued)
3362 0x00, // Value Len: 0
3363 0x00, // Unindexed Entry
3364 0x04, // Name Len: 4
3365 'n', 'a', 'm', 'e', // Name
3366 0x05, // Value Len: 5
3367 'v', 'a', 'l', 'u', 'e', // Value
3368 };
3369 // frame-format on
3370
3371 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3372 visitor.SimulateInFramer(kInput, sizeof(kInput));
3373
3374 EXPECT_EQ(0, visitor.error_count_);
3375 EXPECT_EQ(1, visitor.headers_frame_count_);
3376 EXPECT_EQ(2, visitor.continuation_count_);
3377 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
3378 EXPECT_EQ(0, visitor.end_of_stream_count_);
3379
3380 EXPECT_THAT(
3381 visitor.headers_,
3382 testing::ElementsAre(testing::Pair("cookie", "foo=bar; baz=bing; "),
3383 testing::Pair("name", "value")));
3384 }
3385
3386 TEST_P(SpdyFramerTest, ReadHeadersWithContinuationAndFin) {
3387 // frame-format off
3388 const unsigned char kInput[] = {
3389 0x00, 0x00, 0x10, // Length: 20
3390 0x01, // Type: HEADERS
3391 0x01, // Flags: END_STREAM
3392 0x00, 0x00, 0x00, 0x01, // Stream: 1
3393 0x00, // Unindexed Entry
3394 0x06, // Name Len: 6
3395 'c', 'o', 'o', 'k', 'i', 'e', // Name
3396 0x07, // Value Len: 7
3397 'f', 'o', 'o', '=', 'b', 'a', 'r', // Value
3398
3399 0x00, 0x00, 0x14, // Length: 20
3400 0x09, // Type: CONTINUATION
3401 0x00, // Flags: none
3402 0x00, 0x00, 0x00, 0x01, // Stream: 1
3403 0x00, // Unindexed Entry
3404 0x06, // Name Len: 6
3405 'c', 'o', 'o', 'k', 'i', 'e', // Name
3406 0x08, // Value Len: 7
3407 'b', 'a', 'z', '=', 'b', 'i', 'n', 'g', // Value
3408 0x00, // Unindexed Entry
3409 0x06, // Name Len: 6
3410 'c', // Name (split)
3411
3412 0x00, 0x00, 0x12, // Length: 18
3413 0x09, // Type: CONTINUATION
3414 0x04, // Flags: END_HEADERS
3415 0x00, 0x00, 0x00, 0x01, // Stream: 1
3416 'o', 'o', 'k', 'i', 'e', // Name (continued)
3417 0x00, // Value Len: 0
3418 0x00, // Unindexed Entry
3419 0x04, // Name Len: 4
3420 'n', 'a', 'm', 'e', // Name
3421 0x05, // Value Len: 5
3422 'v', 'a', 'l', 'u', 'e', // Value
3423 };
3424 // frame-format on
3425
3426 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3427 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3428 visitor.SimulateInFramer(kInput, sizeof(kInput));
3429
3430 EXPECT_EQ(0, visitor.error_count_);
3431 EXPECT_EQ(1, visitor.headers_frame_count_);
3432 EXPECT_EQ(2, visitor.continuation_count_);
3433 EXPECT_EQ(1, visitor.fin_flag_count_);
3434 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
3435 EXPECT_EQ(1, visitor.end_of_stream_count_);
3436
3437 EXPECT_THAT(
3438 visitor.headers_,
3439 testing::ElementsAre(testing::Pair("cookie", "foo=bar; baz=bing; "),
3440 testing::Pair("name", "value")));
3441 }
3442
3443 TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) {
3444 // frame-format off
3445 const unsigned char kInput[] = {
3446 0x00, 0x00, 0x17, 0x05, // PUSH_PROMISE
3447 0x08, 0x00, 0x00, 0x00, // PADDED
3448 0x01, 0x02, 0x00, 0x00, // Stream 1, Pad length field
3449 0x00, 0x2A, 0x00, 0x06, // Promised stream 42
3450 'c', 'o', 'o', 'k',
3451 'i', 'e', 0x07, 'f',
3452 'o', 'o', '=', 'b',
3453 'a', 'r', 0x00, 0x00,
3454
3455 0x00, 0x00, 0x14, 0x09, // CONTINUATION
3456 0x00, 0x00, 0x00, 0x00,
3457 0x01, 0x00, 0x06, 'c', // Stream 1
3458 'o', 'o', 'k', 'i',
3459 'e', 0x08, 'b', 'a',
3460 'z', '=', 'b', 'i',
3461 'n', 'g', 0x00, 0x06,
3462 'c',
3463
3464 0x00, 0x00, 0x12, 0x09, // CONTINUATION
3465 0x04, 0x00, 0x00, 0x00, // END_HEADERS
3466 0x01, 'o', 'o', 'k', // Stream 1
3467 'i', 'e', 0x00, 0x00,
3468 0x04, 'n', 'a', 'm',
3469 'e', 0x05, 'v', 'a',
3470 'l', 'u', 'e',
3471 };
3472 // frame-format on
3473
3474 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3475 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3476 visitor.SimulateInFramer(kInput, sizeof(kInput));
3477
3478 EXPECT_EQ(0, visitor.error_count_);
3479 EXPECT_EQ(1u, visitor.last_push_promise_stream_);
3480 EXPECT_EQ(42u, visitor.last_push_promise_promised_stream_);
3481 EXPECT_EQ(2, visitor.continuation_count_);
3482 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
3483 EXPECT_EQ(0, visitor.end_of_stream_count_);
3484
3485 EXPECT_THAT(
3486 visitor.headers_,
3487 testing::ElementsAre(testing::Pair("cookie", "foo=bar; baz=bing; "),
3488 testing::Pair("name", "value")));
3489 }
3490
3491 // Receiving an unknown frame when a continuation is expected should
3492 // result in a SPDY_UNEXPECTED_FRAME error
3493 TEST_P(SpdyFramerTest, ReceiveUnknownMidContinuation) {
3494 const unsigned char kInput[] = {
3495 0x00, 0x00, 0x10, // Length: 16
3496 0x01, // Type: HEADERS
3497 0x00, // Flags: none
3498 0x00, 0x00, 0x00, 0x01, // Stream: 1
3499 0x00, 0x06, 0x63, 0x6f, // HPACK
3500 0x6f, 0x6b, 0x69, 0x65, //
3501 0x07, 0x66, 0x6f, 0x6f, //
3502 0x3d, 0x62, 0x61, 0x72, //
3503
3504 0x00, 0x00, 0x14, // Length: 20
3505 0xa9, // Type: UnknownFrameType(169)
3506 0x00, // Flags: none
3507 0x00, 0x00, 0x00, 0x01, // Stream: 1
3508 0x00, 0x06, 0x63, 0x6f, // Payload
3509 0x6f, 0x6b, 0x69, 0x65, //
3510 0x08, 0x62, 0x61, 0x7a, //
3511 0x3d, 0x62, 0x69, 0x6e, //
3512 0x67, 0x00, 0x06, 0x63, //
3513 };
3514
3515 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3516 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3517 // Assume the unknown frame is allowed
3518 visitor.on_unknown_frame_result_ = true;
3519 framer.set_visitor(&visitor);
3520 visitor.SimulateInFramer(kInput, sizeof(kInput));
3521
3522 EXPECT_EQ(1, visitor.error_count_);
3523 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
3524 visitor.framer_.spdy_framer_error())
3525 << SpdyFramer::SpdyFramerErrorToString(
3526 visitor.framer_.spdy_framer_error());
3527 EXPECT_EQ(1, visitor.headers_frame_count_);
3528 EXPECT_EQ(0, visitor.continuation_count_);
3529 EXPECT_EQ(0u, visitor.header_buffer_length_);
3530 }
3531
3532 // Receiving an unknown frame when a continuation is expected should
3533 // result in a SPDY_UNEXPECTED_FRAME error
3534 TEST_P(SpdyFramerTest, ReceiveUnknownMidContinuationWithExtension) {
3535 const unsigned char kInput[] = {
3536 0x00, 0x00, 0x10, // Length: 16
3537 0x01, // Type: HEADERS
3538 0x00, // Flags: none
3539 0x00, 0x00, 0x00, 0x01, // Stream: 1
3540 0x00, 0x06, 0x63, 0x6f, // HPACK
3541 0x6f, 0x6b, 0x69, 0x65, //
3542 0x07, 0x66, 0x6f, 0x6f, //
3543 0x3d, 0x62, 0x61, 0x72, //
3544
3545 0x00, 0x00, 0x14, // Length: 20
3546 0xa9, // Type: UnknownFrameType(169)
3547 0x00, // Flags: none
3548 0x00, 0x00, 0x00, 0x01, // Stream: 1
3549 0x00, 0x06, 0x63, 0x6f, // Payload
3550 0x6f, 0x6b, 0x69, 0x65, //
3551 0x08, 0x62, 0x61, 0x7a, //
3552 0x3d, 0x62, 0x69, 0x6e, //
3553 0x67, 0x00, 0x06, 0x63, //
3554 };
3555
3556 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3557 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3558 TestExtension extension;
3559 visitor.set_extension_visitor(&extension);
3560 framer.set_visitor(&visitor);
3561 visitor.SimulateInFramer(kInput, sizeof(kInput));
3562
3563 EXPECT_EQ(1, visitor.error_count_);
3564 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
3565 visitor.framer_.spdy_framer_error())
3566 << SpdyFramer::SpdyFramerErrorToString(
3567 visitor.framer_.spdy_framer_error());
3568 EXPECT_EQ(1, visitor.headers_frame_count_);
3569 EXPECT_EQ(0, visitor.continuation_count_);
3570 EXPECT_EQ(0u, visitor.header_buffer_length_);
3571 }
3572
3573 TEST_P(SpdyFramerTest, ReceiveContinuationOnWrongStream) {
3574 const unsigned char kInput[] = {
3575 0x00, 0x00, 0x10, // Length: 16
3576 0x01, // Type: HEADERS
3577 0x00, // Flags: none
3578 0x00, 0x00, 0x00, 0x01, // Stream: 1
3579 0x00, 0x06, 0x63, 0x6f, // HPACK
3580 0x6f, 0x6b, 0x69, 0x65, //
3581 0x07, 0x66, 0x6f, 0x6f, //
3582 0x3d, 0x62, 0x61, 0x72, //
3583
3584 0x00, 0x00, 0x14, // Length: 20
3585 0x09, // Type: CONTINUATION
3586 0x00, // Flags: none
3587 0x00, 0x00, 0x00, 0x02, // Stream: 2
3588 0x00, 0x06, 0x63, 0x6f, // HPACK
3589 0x6f, 0x6b, 0x69, 0x65, //
3590 0x08, 0x62, 0x61, 0x7a, //
3591 0x3d, 0x62, 0x69, 0x6e, //
3592 0x67, 0x00, 0x06, 0x63, //
3593 };
3594
3595 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3596 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3597 framer.set_visitor(&visitor);
3598 visitor.SimulateInFramer(kInput, sizeof(kInput));
3599
3600 EXPECT_EQ(1, visitor.error_count_);
3601 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
3602 visitor.framer_.spdy_framer_error())
3603 << SpdyFramer::SpdyFramerErrorToString(
3604 visitor.framer_.spdy_framer_error());
3605 EXPECT_EQ(1, visitor.headers_frame_count_);
3606 EXPECT_EQ(0, visitor.continuation_count_);
3607 EXPECT_EQ(0u, visitor.header_buffer_length_);
3608 }
3609
3610 TEST_P(SpdyFramerTest, ReadContinuationOutOfOrder) {
3611 const unsigned char kInput[] = {
3612 0x00, 0x00, 0x18, // Length: 24
3613 0x09, // Type: CONTINUATION
3614 0x00, // Flags: none
3615 0x00, 0x00, 0x00, 0x01, // Stream: 1
3616 0x00, 0x06, 0x63, 0x6f, // HPACK
3617 0x6f, 0x6b, 0x69, 0x65, //
3618 0x07, 0x66, 0x6f, 0x6f, //
3619 0x3d, 0x62, 0x61, 0x72, //
3620 };
3621
3622 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3623 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3624 framer.set_visitor(&visitor);
3625 visitor.SimulateInFramer(kInput, sizeof(kInput));
3626
3627 EXPECT_EQ(1, visitor.error_count_);
3628 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
3629 visitor.framer_.spdy_framer_error())
3630 << SpdyFramer::SpdyFramerErrorToString(
3631 visitor.framer_.spdy_framer_error());
3632 EXPECT_EQ(0, visitor.continuation_count_);
3633 EXPECT_EQ(0u, visitor.header_buffer_length_);
3634 }
3635
3636 TEST_P(SpdyFramerTest, ExpectContinuationReceiveData) {
3637 const unsigned char kInput[] = {
3638 0x00, 0x00, 0x10, // Length: 16
3639 0x01, // Type: HEADERS
3640 0x00, // Flags: none
3641 0x00, 0x00, 0x00, 0x01, // Stream: 1
3642 0x00, 0x06, 0x63, 0x6f, // HPACK
3643 0x6f, 0x6b, 0x69, 0x65, //
3644 0x07, 0x66, 0x6f, 0x6f, //
3645 0x3d, 0x62, 0x61, 0x72, //
3646
3647 0x00, 0x00, 0x00, // Length: 0
3648 0x00, // Type: DATA
3649 0x01, // Flags: END_STREAM
3650 0x00, 0x00, 0x00, 0x04, // Stream: 4
3651
3652 0xde, 0xad, 0xbe, 0xef, // Truncated Frame Header
3653 };
3654
3655 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3656 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3657 framer.set_visitor(&visitor);
3658 visitor.SimulateInFramer(kInput, sizeof(kInput));
3659
3660 EXPECT_EQ(1, visitor.error_count_);
3661 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
3662 visitor.framer_.spdy_framer_error())
3663 << SpdyFramer::SpdyFramerErrorToString(
3664 visitor.framer_.spdy_framer_error());
3665 EXPECT_EQ(1, visitor.headers_frame_count_);
3666 EXPECT_EQ(0, visitor.continuation_count_);
3667 EXPECT_EQ(0u, visitor.header_buffer_length_);
3668 EXPECT_EQ(0, visitor.data_frame_count_);
3669 }
3670
3671 TEST_P(SpdyFramerTest, ExpectContinuationReceiveControlFrame) {
3672 const unsigned char kInput[] = {
3673 0x00, 0x00, 0x10, // Length: 16
3674 0x01, // Type: HEADERS
3675 0x00, // Flags: none
3676 0x00, 0x00, 0x00, 0x01, // Stream: 1
3677 0x00, 0x06, 0x63, 0x6f, // HPACK
3678 0x6f, 0x6b, 0x69, 0x65, //
3679 0x07, 0x66, 0x6f, 0x6f, //
3680 0x3d, 0x62, 0x61, 0x72, //
3681
3682 0x00, 0x00, 0x10, // Length: 16
3683 0x01, // Type: HEADERS
3684 0x00, // Flags: none
3685 0x00, 0x00, 0x00, 0x01, // Stream: 1
3686 0x00, 0x06, 0x63, 0x6f, // HPACK
3687 0x6f, 0x6b, 0x69, 0x65, //
3688 0x07, 0x66, 0x6f, 0x6f, //
3689 0x3d, 0x62, 0x61, 0x72, //
3690 };
3691
3692 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3693 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3694 framer.set_visitor(&visitor);
3695 visitor.SimulateInFramer(kInput, sizeof(kInput));
3696
3697 EXPECT_EQ(1, visitor.error_count_);
3698 EXPECT_EQ(SpdyFramer::SPDY_UNEXPECTED_FRAME,
3699 visitor.framer_.spdy_framer_error())
3700 << SpdyFramer::SpdyFramerErrorToString(
3701 visitor.framer_.spdy_framer_error());
3702 EXPECT_EQ(1, visitor.headers_frame_count_);
3703 EXPECT_EQ(0, visitor.continuation_count_);
3704 EXPECT_EQ(0u, visitor.header_buffer_length_);
3705 EXPECT_EQ(0, visitor.data_frame_count_);
3706 }
3707
3708 TEST_P(SpdyFramerTest, ReadGarbage) {
3709 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3710 unsigned char garbage_frame[256];
3711 memset(garbage_frame, ~0, sizeof(garbage_frame));
3712 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3713 visitor.SimulateInFramer(garbage_frame, sizeof(garbage_frame));
3714 EXPECT_EQ(1, visitor.error_count_);
3715 }
3716
3717 TEST_P(SpdyFramerTest, ReadUnknownExtensionFrame) {
3718 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3719
3720 // The unrecognized frame type should still have a valid length.
3721 const unsigned char unknown_frame[] = {
3722 0x00, 0x00, 0x08, // Length: 8
3723 0xff, // Type: UnknownFrameType(255)
3724 0xff, // Flags: 0xff
3725 0xff, 0xff, 0xff, 0xff, // Stream: 0x7fffffff (R-bit set)
3726 0xff, 0xff, 0xff, 0xff, // Payload
3727 0xff, 0xff, 0xff, 0xff, //
3728 };
3729 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3730
3731 // Simulate the case where the stream id validation checks out.
3732 visitor.on_unknown_frame_result_ = true;
3733 visitor.SimulateInFramer(unknown_frame, arraysize(unknown_frame));
3734 EXPECT_EQ(0, visitor.error_count_);
3735
3736 // Follow it up with a valid control frame to make sure we handle
3737 // subsequent frames correctly.
3738 SpdySettingsIR settings_ir;
3739 settings_ir.AddSetting(SETTINGS_HEADER_TABLE_SIZE, 10);
3740 SpdySerializedFrame control_frame(framer.SerializeSettings(settings_ir));
3741 if (use_output_) {
3742 ASSERT_TRUE(framer.SerializeSettings(settings_ir, &output_));
3743 control_frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
3744 }
3745 visitor.SimulateInFramer(
3746 reinterpret_cast<unsigned char*>(control_frame.data()),
3747 control_frame.size());
3748 EXPECT_EQ(0, visitor.error_count_);
3749 EXPECT_EQ(1u, static_cast<unsigned>(visitor.setting_count_));
3750 EXPECT_EQ(1u, static_cast<unsigned>(visitor.settings_ack_sent_));
3751 }
3752
3753 TEST_P(SpdyFramerTest, ReadUnknownExtensionFrameWithExtension) {
3754 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3755
3756 // The unrecognized frame type should still have a valid length.
3757 const unsigned char unknown_frame[] = {
3758 0x00, 0x00, 0x14, // Length: 20
3759 0xff, // Type: UnknownFrameType(255)
3760 0xff, // Flags: 0xff
3761 0xff, 0xff, 0xff, 0xff, // Stream: 0x7fffffff (R-bit set)
3762 0xff, 0xff, 0xff, 0xff, // Payload
3763 0xff, 0xff, 0xff, 0xff, //
3764 0xff, 0xff, 0xff, 0xff, //
3765 0xff, 0xff, 0xff, 0xff, //
3766 0xff, 0xff, 0xff, 0xff, //
3767 };
3768 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3769 TestExtension extension;
3770 visitor.set_extension_visitor(&extension);
3771 visitor.SimulateInFramer(unknown_frame, arraysize(unknown_frame));
3772 EXPECT_EQ(0, visitor.error_count_);
3773 EXPECT_EQ(0x7fffffffu, extension.stream_id_);
3774 EXPECT_EQ(20u, extension.length_);
3775 EXPECT_EQ(255, extension.type_);
3776 EXPECT_EQ(0xff, extension.flags_);
3777 EXPECT_EQ(SpdyString(20, '\xff'), extension.payload_);
3778
3779 // Follow it up with a valid control frame to make sure we handle
3780 // subsequent frames correctly.
3781 SpdySettingsIR settings_ir;
3782 settings_ir.AddSetting(SETTINGS_HEADER_TABLE_SIZE, 10);
3783 SpdySerializedFrame control_frame(framer.SerializeSettings(settings_ir));
3784 visitor.SimulateInFramer(
3785 reinterpret_cast<unsigned char*>(control_frame.data()),
3786 control_frame.size());
3787 EXPECT_EQ(0, visitor.error_count_);
3788 EXPECT_EQ(1u, static_cast<unsigned>(visitor.setting_count_));
3789 EXPECT_EQ(1u, static_cast<unsigned>(visitor.settings_ack_sent_));
3790 }
3791
3792 TEST_P(SpdyFramerTest, ReadGarbageWithValidLength) {
3793 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3794 const unsigned char kFrameData[] = {
3795 0x00, 0x00, 0x08, // Length: 8
3796 0xff, // Type: UnknownFrameType(255)
3797 0xff, // Flags: 0xff
3798 0xff, 0xff, 0xff, 0xff, // Stream: 0x7fffffff (R-bit set)
3799 0xff, 0xff, 0xff, 0xff, // Payload
3800 0xff, 0xff, 0xff, 0xff, //
3801 };
3802 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3803 visitor.SimulateInFramer(kFrameData, arraysize(kFrameData));
3804 EXPECT_EQ(1, visitor.error_count_);
3805 }
3806
3807 TEST_P(SpdyFramerTest, ReadGarbageHPACKEncoding) {
3808 const unsigned char kInput[] = {
3809 0x00, 0x12, 0x01, // Length: 4609
3810 0x04, // Type: SETTINGS
3811 0x00, // Flags: none
3812 0x00, 0x00, 0x01, 0xef, // Stream: 495
3813 0xef, 0xff, // Param: 61439
3814 0xff, 0xff, 0xff, 0xff, // Value: 4294967295
3815 0xff, 0xff, // Param: 0xffff
3816 0xff, 0xff, 0xff, 0xff, // Value: 4294967295
3817 0xff, 0xff, 0xff, 0xff, // Settings (Truncated)
3818 0xff, //
3819 };
3820
3821 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3822 visitor.SimulateInFramer(kInput, arraysize(kInput));
3823 EXPECT_EQ(1, visitor.error_count_);
3824 }
3825
3826 TEST_P(SpdyFramerTest, SizesTest) {
3827 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3828 EXPECT_EQ(9u, framer.GetDataFrameMinimumSize());
3829 EXPECT_EQ(9u, framer.GetFrameHeaderSize());
3830 EXPECT_EQ(13u, framer.GetRstStreamSize());
3831 EXPECT_EQ(9u, framer.GetSettingsMinimumSize());
3832 EXPECT_EQ(17u, framer.GetPingSize());
3833 EXPECT_EQ(17u, framer.GetGoAwayMinimumSize());
3834 EXPECT_EQ(9u, framer.GetHeadersMinimumSize());
3835 EXPECT_EQ(13u, framer.GetWindowUpdateSize());
3836 EXPECT_EQ(13u, framer.GetPushPromiseMinimumSize());
3837 EXPECT_EQ(11u, framer.GetAltSvcMinimumSize());
3838 EXPECT_EQ(9u, framer.GetFrameMinimumSize());
3839 EXPECT_EQ(16393u, framer.GetFrameMaximumSize());
3840 EXPECT_EQ(16384u, framer.GetDataFrameMaximumPayload());
3841 }
3842
3843 TEST_P(SpdyFramerTest, StateToStringTest) {
3844 EXPECT_STREQ("ERROR", SpdyFramer::StateToString(SpdyFramer::SPDY_ERROR));
3845 EXPECT_STREQ("FRAME_COMPLETE",
3846 SpdyFramer::StateToString(SpdyFramer::SPDY_FRAME_COMPLETE));
3847 EXPECT_STREQ("READY_FOR_FRAME",
3848 SpdyFramer::StateToString(SpdyFramer::SPDY_READY_FOR_FRAME));
3849 EXPECT_STREQ(
3850 "READING_COMMON_HEADER",
3851 SpdyFramer::StateToString(SpdyFramer::SPDY_READING_COMMON_HEADER));
3852 EXPECT_STREQ(
3853 "CONTROL_FRAME_PAYLOAD",
3854 SpdyFramer::StateToString(SpdyFramer::SPDY_CONTROL_FRAME_PAYLOAD));
3855 EXPECT_STREQ(
3856 "IGNORE_REMAINING_PAYLOAD",
3857 SpdyFramer::StateToString(SpdyFramer::SPDY_IGNORE_REMAINING_PAYLOAD));
3858 EXPECT_STREQ(
3859 "FORWARD_STREAM_FRAME",
3860 SpdyFramer::StateToString(SpdyFramer::SPDY_FORWARD_STREAM_FRAME));
3861 EXPECT_STREQ("SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK",
3862 SpdyFramer::StateToString(
3863 SpdyFramer::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK));
3864 EXPECT_STREQ(
3865 "SPDY_CONTROL_FRAME_HEADER_BLOCK",
3866 SpdyFramer::StateToString(SpdyFramer::SPDY_CONTROL_FRAME_HEADER_BLOCK));
3867 EXPECT_STREQ(
3868 "SPDY_SETTINGS_FRAME_PAYLOAD",
3869 SpdyFramer::StateToString(SpdyFramer::SPDY_SETTINGS_FRAME_PAYLOAD));
3870 EXPECT_STREQ(
3871 "SPDY_ALTSVC_FRAME_PAYLOAD",
3872 SpdyFramer::StateToString(SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD));
3873 EXPECT_STREQ("UNKNOWN_STATE", SpdyFramer::StateToString(
3874 SpdyFramer::SPDY_ALTSVC_FRAME_PAYLOAD + 1));
3875 }
3876
3877 TEST_P(SpdyFramerTest, SpdyFramerErrorToStringTest) {
3878 EXPECT_STREQ("NO_ERROR",
3879 SpdyFramer::SpdyFramerErrorToString(SpdyFramer::SPDY_NO_ERROR));
3880 EXPECT_STREQ("INVALID_STREAM_ID", SpdyFramer::SpdyFramerErrorToString(
3881 SpdyFramer::SPDY_INVALID_STREAM_ID));
3882 EXPECT_STREQ("INVALID_CONTROL_FRAME",
3883 SpdyFramer::SpdyFramerErrorToString(
3884 SpdyFramer::SPDY_INVALID_CONTROL_FRAME));
3885 EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
3886 SpdyFramer::SpdyFramerErrorToString(
3887 SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
3888 EXPECT_STREQ("ZLIB_INIT_FAILURE", SpdyFramer::SpdyFramerErrorToString(
3889 SpdyFramer::SPDY_ZLIB_INIT_FAILURE));
3890 EXPECT_STREQ("UNSUPPORTED_VERSION",
3891 SpdyFramer::SpdyFramerErrorToString(
3892 SpdyFramer::SPDY_UNSUPPORTED_VERSION));
3893 EXPECT_STREQ("DECOMPRESS_FAILURE", SpdyFramer::SpdyFramerErrorToString(
3894 SpdyFramer::SPDY_DECOMPRESS_FAILURE));
3895 EXPECT_STREQ("COMPRESS_FAILURE", SpdyFramer::SpdyFramerErrorToString(
3896 SpdyFramer::SPDY_COMPRESS_FAILURE));
3897 EXPECT_STREQ("GOAWAY_FRAME_CORRUPT",
3898 SpdyFramer::SpdyFramerErrorToString(
3899 SpdyFramer::SPDY_GOAWAY_FRAME_CORRUPT));
3900 EXPECT_STREQ("RST_STREAM_FRAME_CORRUPT",
3901 SpdyFramer::SpdyFramerErrorToString(
3902 SpdyFramer::SPDY_RST_STREAM_FRAME_CORRUPT));
3903 EXPECT_STREQ("INVALID_PADDING", SpdyFramer::SpdyFramerErrorToString(
3904 SpdyFramer::SPDY_INVALID_PADDING));
3905 EXPECT_STREQ("INVALID_DATA_FRAME_FLAGS",
3906 SpdyFramer::SpdyFramerErrorToString(
3907 SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS));
3908 EXPECT_STREQ("INVALID_CONTROL_FRAME_FLAGS",
3909 SpdyFramer::SpdyFramerErrorToString(
3910 SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS));
3911 EXPECT_STREQ("UNEXPECTED_FRAME", SpdyFramer::SpdyFramerErrorToString(
3912 SpdyFramer::SPDY_UNEXPECTED_FRAME));
3913 EXPECT_STREQ("INTERNAL_FRAMER_ERROR",
3914 SpdyFramer::SpdyFramerErrorToString(
3915 SpdyFramer::SPDY_INTERNAL_FRAMER_ERROR));
3916 EXPECT_STREQ("INVALID_CONTROL_FRAME_SIZE",
3917 SpdyFramer::SpdyFramerErrorToString(
3918 SpdyFramer::SPDY_INVALID_CONTROL_FRAME_SIZE));
3919 EXPECT_STREQ("OVERSIZED_PAYLOAD", SpdyFramer::SpdyFramerErrorToString(
3920 SpdyFramer::SPDY_OVERSIZED_PAYLOAD));
3921 EXPECT_STREQ("UNKNOWN_ERROR",
3922 SpdyFramer::SpdyFramerErrorToString(SpdyFramer::LAST_ERROR));
3923 EXPECT_STREQ("UNKNOWN_ERROR", SpdyFramer::SpdyFramerErrorToString(
3924 static_cast<SpdyFramer::SpdyFramerError>(
3925 SpdyFramer::LAST_ERROR + 1)));
3926 }
3927
3928 TEST_P(SpdyFramerTest, DataFrameFlagsV4) {
3929 uint8_t valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_PADDED;
3930
3931 uint8_t flags = 0;
3932 do {
3933 SCOPED_TRACE(testing::Message() << "Flags " << flags << std::hex
3934 << static_cast<int>(flags));
3935
3936 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
3937 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3938 framer.set_visitor(&visitor);
3939
3940 SpdyDataIR data_ir(1, "hello");
3941 SpdySerializedFrame frame(framer.SerializeData(data_ir));
3942 SetFrameFlags(&frame, flags);
3943
3944 if (flags & ~valid_data_flags) {
3945 EXPECT_CALL(visitor, OnError(_));
3946 } else {
3947 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
3948 if (flags & DATA_FLAG_PADDED) {
3949 // The first byte of payload is parsed as padding length, but 'h'
3950 // (0x68) is too large a padding length for a 5 byte payload.
3951 EXPECT_CALL(visitor, OnStreamPadding(_, 1));
3952 // Expect Error since the frame ends prematurely.
3953 EXPECT_CALL(visitor, OnError(_));
3954 } else {
3955 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5));
3956 if (flags & DATA_FLAG_FIN) {
3957 EXPECT_CALL(visitor, OnStreamEnd(_));
3958 }
3959 }
3960 }
3961
3962 framer.ProcessInput(frame.data(), frame.size());
3963 if (flags & ~valid_data_flags) {
3964 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
3965 EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS,
3966 framer.spdy_framer_error())
3967 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
3968 } else if (flags & DATA_FLAG_PADDED) {
3969 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
3970 EXPECT_EQ(SpdyFramer::SPDY_INVALID_PADDING, framer.spdy_framer_error())
3971 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
3972 } else {
3973 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
3974 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.spdy_framer_error())
3975 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
3976 }
3977 } while (++flags != 0);
3978 }
3979
3980 TEST_P(SpdyFramerTest, RstStreamFrameFlags) {
3981 uint8_t flags = 0;
3982 do {
3983 SCOPED_TRACE(testing::Message() << "Flags " << flags << std::hex
3984 << static_cast<int>(flags));
3985
3986 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
3987 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
3988 framer.set_visitor(&visitor);
3989
3990 SpdyRstStreamIR rst_stream(13, ERROR_CODE_CANCEL);
3991 SpdySerializedFrame frame(framer.SerializeRstStream(rst_stream));
3992 if (use_output_) {
3993 output_.Reset();
3994 ASSERT_TRUE(framer.SerializeRstStream(rst_stream, &output_));
3995 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
3996 }
3997 SetFrameFlags(&frame, flags);
3998
3999 EXPECT_CALL(visitor, OnRstStream(13, ERROR_CODE_CANCEL));
4000
4001 framer.ProcessInput(frame.data(), frame.size());
4002
4003 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
4004 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.spdy_framer_error())
4005 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
4006 } while (++flags != 0);
4007 }
4008
4009 TEST_P(SpdyFramerTest, SettingsFrameFlags) {
4010 uint8_t flags = 0;
4011 do {
4012 SCOPED_TRACE(testing::Message() << "Flags " << flags << std::hex
4013 << static_cast<int>(flags));
4014
4015 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4016 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4017 framer.set_visitor(&visitor);
4018
4019 SpdySettingsIR settings_ir;
4020 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 16);
4021 SpdySerializedFrame frame(framer.SerializeSettings(settings_ir));
4022 if (use_output_) {
4023 output_.Reset();
4024 ASSERT_TRUE(framer.SerializeSettings(settings_ir, &output_));
4025 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
4026 }
4027 SetFrameFlags(&frame, flags);
4028
4029 if (flags & SETTINGS_FLAG_ACK) {
4030 EXPECT_CALL(visitor, OnError(_));
4031 } else {
4032 EXPECT_CALL(visitor, OnSettings(flags & SETTINGS_FLAG_ACK));
4033 EXPECT_CALL(visitor, OnSetting(SETTINGS_INITIAL_WINDOW_SIZE, 16));
4034 EXPECT_CALL(visitor, OnSettingsEnd());
4035 }
4036
4037 framer.ProcessInput(frame.data(), frame.size());
4038 if (flags & SETTINGS_FLAG_ACK) {
4039 // The frame is invalid because ACK frames should have no payload.
4040 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4041 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_SIZE,
4042 framer.spdy_framer_error())
4043 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
4044 } else {
4045 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
4046 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.spdy_framer_error())
4047 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
4048 }
4049 } while (++flags != 0);
4050 }
4051
4052 TEST_P(SpdyFramerTest, GoawayFrameFlags) {
4053 uint8_t flags = 0;
4054 do {
4055 SCOPED_TRACE(testing::Message() << "Flags " << flags << std::hex
4056 << static_cast<int>(flags));
4057
4058 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4059 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4060 framer.set_visitor(&visitor);
4061
4062 SpdyGoAwayIR goaway_ir(97, ERROR_CODE_NO_ERROR, "test");
4063 SpdySerializedFrame frame(framer.SerializeGoAway(goaway_ir));
4064 if (use_output_) {
4065 output_.Reset();
4066 ASSERT_TRUE(framer.SerializeGoAway(goaway_ir, &output_));
4067 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
4068 }
4069 SetFrameFlags(&frame, flags);
4070
4071 EXPECT_CALL(visitor, OnGoAway(97, ERROR_CODE_NO_ERROR));
4072
4073 framer.ProcessInput(frame.data(), frame.size());
4074 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
4075 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.spdy_framer_error())
4076 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
4077 } while (++flags != 0);
4078 }
4079
4080 TEST_P(SpdyFramerTest, HeadersFrameFlags) {
4081 uint8_t flags = 0;
4082 do {
4083 SCOPED_TRACE(testing::Message() << "Flags " << flags << std::hex
4084 << static_cast<int>(flags));
4085
4086 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4087 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4088 framer.set_visitor(&visitor);
4089
4090 SpdyHeadersIR headers_ir(57);
4091 if (flags & HEADERS_FLAG_PRIORITY) {
4092 headers_ir.set_weight(3);
4093 headers_ir.set_has_priority(true);
4094 headers_ir.set_parent_stream_id(5);
4095 headers_ir.set_exclusive(true);
4096 }
4097 headers_ir.SetHeader("foo", "bar");
4098 SpdySerializedFrame frame(SpdyFramerPeer::SerializeHeaders(
4099 &framer, headers_ir, use_output_ ? &output_ : nullptr));
4100 uint8_t set_flags = flags & ~HEADERS_FLAG_PADDED;
4101 SetFrameFlags(&frame, set_flags);
4102
4103 // Expected callback values
4104 SpdyStreamId stream_id = 57;
4105 bool has_priority = false;
4106 SpdyPriority priority = 0;
4107 SpdyStreamId parent_stream_id = 0;
4108 bool exclusive = false;
4109 bool fin = flags & CONTROL_FLAG_FIN;
4110 bool end = flags & HEADERS_FLAG_END_HEADERS;
4111 if (flags & HEADERS_FLAG_PRIORITY) {
4112 has_priority = true;
4113 priority = 3;
4114 parent_stream_id = 5;
4115 exclusive = true;
4116 }
4117 EXPECT_CALL(visitor, OnHeaders(stream_id, has_priority, priority,
4118 parent_stream_id, exclusive, fin, end));
4119 EXPECT_CALL(visitor, OnHeaderFrameStart(57)).Times(1);
4120 if (end) {
4121 EXPECT_CALL(visitor, OnHeaderFrameEnd(57, _)).Times(1);
4122 }
4123 if (flags & DATA_FLAG_FIN && end) {
4124 EXPECT_CALL(visitor, OnStreamEnd(_));
4125 } else {
4126 // Do not close the stream if we are expecting a CONTINUATION frame.
4127 EXPECT_CALL(visitor, OnStreamEnd(_)).Times(0);
4128 }
4129
4130 framer.ProcessInput(frame.data(), frame.size());
4131 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
4132 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.spdy_framer_error())
4133 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
4134 } while (++flags != 0);
4135 }
4136
4137 TEST_P(SpdyFramerTest, PingFrameFlags) {
4138 uint8_t flags = 0;
4139 do {
4140 SCOPED_TRACE(testing::Message() << "Flags " << flags << std::hex
4141 << static_cast<int>(flags));
4142
4143 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4144 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4145 framer.set_visitor(&visitor);
4146
4147 SpdySerializedFrame frame(framer.SerializePing(SpdyPingIR(42)));
4148 SetFrameFlags(&frame, flags);
4149
4150 EXPECT_CALL(visitor, OnPing(42, flags & PING_FLAG_ACK));
4151
4152 framer.ProcessInput(frame.data(), frame.size());
4153 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
4154 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.spdy_framer_error())
4155 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
4156 } while (++flags != 0);
4157 }
4158
4159 TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) {
4160 uint8_t flags = 0;
4161 do {
4162 SCOPED_TRACE(testing::Message() << "Flags " << flags << std::hex
4163 << static_cast<int>(flags));
4164
4165 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4166 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4167 framer.set_visitor(&visitor);
4168
4169 SpdySerializedFrame frame(
4170 framer.SerializeWindowUpdate(SpdyWindowUpdateIR(4, 1024)));
4171 SetFrameFlags(&frame, flags);
4172
4173 EXPECT_CALL(visitor, OnWindowUpdate(4, 1024));
4174
4175 framer.ProcessInput(frame.data(), frame.size());
4176 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
4177 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.spdy_framer_error())
4178 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
4179 } while (++flags != 0);
4180 }
4181
4182 TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
4183 const SpdyStreamId client_id = 123; // Must be odd.
4184 const SpdyStreamId promised_id = 22; // Must be even.
4185 uint8_t flags = 0;
4186 do {
4187 SCOPED_TRACE(testing::Message() << "Flags " << flags << std::hex
4188 << static_cast<int>(flags));
4189
4190 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4191 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
4192 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4193 framer.set_visitor(&visitor);
4194 framer.set_debug_visitor(&debug_visitor);
4195
4196 EXPECT_CALL(
4197 debug_visitor,
4198 OnSendCompressedFrame(client_id, SpdyFrameType::PUSH_PROMISE, _, _));
4199
4200 SpdyPushPromiseIR push_promise(client_id, promised_id);
4201 push_promise.SetHeader("foo", "bar");
4202 SpdySerializedFrame frame(SpdyFramerPeer::SerializePushPromise(
4203 &framer, push_promise, use_output_ ? &output_ : nullptr));
4204 // TODO(jgraettinger): Add padding to SpdyPushPromiseIR,
4205 // and implement framing.
4206 SetFrameFlags(&frame, flags & ~HEADERS_FLAG_PADDED);
4207
4208 bool end = flags & PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
4209 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(
4210 client_id, SpdyFrameType::PUSH_PROMISE, _));
4211 EXPECT_CALL(visitor, OnPushPromise(client_id, promised_id, end));
4212 EXPECT_CALL(visitor, OnHeaderFrameStart(client_id)).Times(1);
4213 if (end) {
4214 EXPECT_CALL(visitor, OnHeaderFrameEnd(client_id, _)).Times(1);
4215 }
4216
4217 framer.ProcessInput(frame.data(), frame.size());
4218 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
4219 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.spdy_framer_error())
4220 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
4221 } while (++flags != 0);
4222 }
4223
4224 TEST_P(SpdyFramerTest, ContinuationFrameFlags) {
4225 uint8_t flags = 0;
4226 do {
4227 if (use_output_) {
4228 output_.Reset();
4229 }
4230 SCOPED_TRACE(testing::Message() << "Flags " << flags << std::hex
4231 << static_cast<int>(flags));
4232
4233 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4234 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
4235 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4236 framer.set_visitor(&visitor);
4237 framer.set_debug_visitor(&debug_visitor);
4238
4239 EXPECT_CALL(debug_visitor,
4240 OnSendCompressedFrame(42, SpdyFrameType::HEADERS, _, _));
4241 EXPECT_CALL(debug_visitor,
4242 OnReceiveCompressedFrame(42, SpdyFrameType::HEADERS, _));
4243 EXPECT_CALL(visitor, OnHeaders(42, false, 0, 0, false, false, false));
4244 EXPECT_CALL(visitor, OnHeaderFrameStart(42)).Times(1);
4245
4246 SpdyHeadersIR headers_ir(42);
4247 headers_ir.SetHeader("foo", "bar");
4248 SpdySerializedFrame frame0;
4249 if (use_output_) {
4250 EXPECT_TRUE(framer.SerializeHeaders(headers_ir, &output_));
4251 frame0 = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
4252 } else {
4253 frame0 = framer.SerializeHeaders(headers_ir);
4254 }
4255 SetFrameFlags(&frame0, 0);
4256
4257 SpdyContinuationIR continuation(42);
4258 SpdySerializedFrame frame1;
4259 if (use_output_) {
4260 char* begin = output_.Begin() + output_.Size();
4261 ASSERT_TRUE(framer.SerializeContinuation(continuation, &output_));
4262 frame1 =
4263 SpdySerializedFrame(begin, output_.Size() - frame0.size(), false);
4264 } else {
4265 frame1 = framer.SerializeContinuation(continuation);
4266 }
4267 SetFrameFlags(&frame1, flags);
4268
4269 EXPECT_CALL(debug_visitor,
4270 OnReceiveCompressedFrame(42, SpdyFrameType::CONTINUATION, _));
4271 EXPECT_CALL(visitor, OnContinuation(42, flags & HEADERS_FLAG_END_HEADERS));
4272 bool end = flags & HEADERS_FLAG_END_HEADERS;
4273 if (end) {
4274 EXPECT_CALL(visitor, OnHeaderFrameEnd(42, _)).Times(1);
4275 }
4276
4277 framer.ProcessInput(frame0.data(), frame0.size());
4278 framer.ProcessInput(frame1.data(), frame1.size());
4279 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
4280 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.spdy_framer_error())
4281 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
4282 } while (++flags != 0);
4283 }
4284
4285 // TODO(mlavan): Add TEST_F(SpdyFramerTest, AltSvcFrameFlags)
4286
4287 // Test handling of a RST_STREAM with out-of-bounds status codes.
4288 TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
4289 const unsigned char kH2RstStreamInvalid[] = {
4290 0x00, 0x00, 0x04, // Length: 4
4291 0x03, // Type: RST_STREAM
4292 0x00, // Flags: none
4293 0x00, 0x00, 0x00, 0x01, // Stream: 1
4294 0x00, 0x00, 0x00, 0x00, // Error: NO_ERROR
4295 };
4296 const unsigned char kH2RstStreamNumStatusCodes[] = {
4297 0x00, 0x00, 0x04, // Length: 4
4298 0x03, // Type: RST_STREAM
4299 0x00, // Flags: none
4300 0x00, 0x00, 0x00, 0x01, // Stream: 1
4301 0x00, 0x00, 0x00, 0xff, // Error: 255
4302 };
4303
4304 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4305 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4306 framer.set_visitor(&visitor);
4307
4308 EXPECT_CALL(visitor, OnRstStream(1, ERROR_CODE_NO_ERROR));
4309 framer.ProcessInput(reinterpret_cast<const char*>(kH2RstStreamInvalid),
4310 arraysize(kH2RstStreamInvalid));
4311 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
4312 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.spdy_framer_error())
4313 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
4314
4315 framer.Reset();
4316
4317 EXPECT_CALL(visitor, OnRstStream(1, ERROR_CODE_INTERNAL_ERROR));
4318 framer.ProcessInput(reinterpret_cast<const char*>(kH2RstStreamNumStatusCodes),
4319 arraysize(kH2RstStreamNumStatusCodes));
4320 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
4321 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.spdy_framer_error())
4322 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
4323 }
4324
4325 // Test handling of GOAWAY frames with out-of-bounds status code.
4326 TEST_P(SpdyFramerTest, GoAwayStatusBounds) {
4327 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4328 const unsigned char kH2FrameData[] = {
4329 0x00, 0x00, 0x0a, // Length: 10
4330 0x07, // Type: GOAWAY
4331 0x00, // Flags: none
4332 0x00, 0x00, 0x00, 0x00, // Stream: 0
4333 0x00, 0x00, 0x00, 0x01, // Last: 1
4334 0xff, 0xff, 0xff, 0xff, // Error: 0xffffffff
4335 0x47, 0x41, // Description
4336 };
4337 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4338 framer.set_visitor(&visitor);
4339
4340 EXPECT_CALL(visitor, OnGoAway(1, ERROR_CODE_INTERNAL_ERROR));
4341 framer.ProcessInput(reinterpret_cast<const char*>(kH2FrameData),
4342 arraysize(kH2FrameData));
4343 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
4344 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.spdy_framer_error())
4345 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
4346 }
4347
4348 // Tests handling of a GOAWAY frame with out-of-bounds stream ID.
4349 TEST_P(SpdyFramerTest, GoAwayStreamIdBounds) {
4350 const unsigned char kH2FrameData[] = {
4351 0x00, 0x00, 0x08, // Length: 8
4352 0x07, // Type: GOAWAY
4353 0x00, // Flags: none
4354 0x00, 0x00, 0x00, 0x00, // Stream: 0
4355 0xff, 0xff, 0xff, 0xff, // Last: 0x7fffffff (R-bit set)
4356 0x00, 0x00, 0x00, 0x00, // Error: NO_ERROR
4357 };
4358
4359 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4360 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4361 framer.set_visitor(&visitor);
4362
4363 EXPECT_CALL(visitor, OnGoAway(0x7fffffff, ERROR_CODE_NO_ERROR));
4364 framer.ProcessInput(reinterpret_cast<const char*>(kH2FrameData),
4365 arraysize(kH2FrameData));
4366 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
4367 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.spdy_framer_error())
4368 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
4369 }
4370
4371 TEST_P(SpdyFramerTest, OnAltSvcWithOrigin) {
4372 const SpdyStreamId kStreamId = 0; // Stream id must be zero if origin given.
4373
4374 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4375 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4376 framer.set_visitor(&visitor);
4377
4378 SpdyAltSvcWireFormat::AlternativeService altsvc1(
4379 "pid1", "host", 443, 5, SpdyAltSvcWireFormat::VersionVector());
4380 SpdyAltSvcWireFormat::AlternativeService altsvc2(
4381 "p\"=i:d", "h_\\o\"st", 123, 42, SpdyAltSvcWireFormat::VersionVector{24});
4382 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
4383 altsvc_vector.push_back(altsvc1);
4384 altsvc_vector.push_back(altsvc2);
4385 EXPECT_CALL(visitor,
4386 OnAltSvc(kStreamId, SpdyStringPiece("o_r|g!n"), altsvc_vector));
4387
4388 SpdyAltSvcIR altsvc_ir(kStreamId);
4389 altsvc_ir.set_origin("o_r|g!n");
4390 altsvc_ir.add_altsvc(altsvc1);
4391 altsvc_ir.add_altsvc(altsvc2);
4392 SpdySerializedFrame frame(framer.SerializeFrame(altsvc_ir));
4393 if (use_output_) {
4394 output_.Reset();
4395 ASSERT_TRUE(framer.SerializeFrame(altsvc_ir, &output_));
4396 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
4397 }
4398 framer.ProcessInput(frame.data(), frame.size());
4399
4400 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
4401 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.spdy_framer_error())
4402 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
4403 }
4404
4405 TEST_P(SpdyFramerTest, OnAltSvcNoOrigin) {
4406 const SpdyStreamId kStreamId = 1;
4407
4408 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4409 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4410 framer.set_visitor(&visitor);
4411
4412 SpdyAltSvcWireFormat::AlternativeService altsvc1(
4413 "pid1", "host", 443, 5, SpdyAltSvcWireFormat::VersionVector());
4414 SpdyAltSvcWireFormat::AlternativeService altsvc2(
4415 "p\"=i:d", "h_\\o\"st", 123, 42, SpdyAltSvcWireFormat::VersionVector{24});
4416 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
4417 altsvc_vector.push_back(altsvc1);
4418 altsvc_vector.push_back(altsvc2);
4419 EXPECT_CALL(visitor, OnAltSvc(kStreamId, SpdyStringPiece(""), altsvc_vector));
4420
4421 SpdyAltSvcIR altsvc_ir(kStreamId);
4422 altsvc_ir.add_altsvc(altsvc1);
4423 altsvc_ir.add_altsvc(altsvc2);
4424 SpdySerializedFrame frame(framer.SerializeFrame(altsvc_ir));
4425 framer.ProcessInput(frame.data(), frame.size());
4426
4427 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
4428 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.spdy_framer_error())
4429 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
4430 }
4431
4432 TEST_P(SpdyFramerTest, OnAltSvcEmptyProtocolId) {
4433 const SpdyStreamId kStreamId = 0; // Stream id must be zero if origin given.
4434
4435 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4436 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4437 framer.set_visitor(&visitor);
4438
4439 EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
4440
4441 SpdyAltSvcIR altsvc_ir(kStreamId);
4442 altsvc_ir.set_origin("o1");
4443 altsvc_ir.add_altsvc(SpdyAltSvcWireFormat::AlternativeService(
4444 "pid1", "host", 443, 5, SpdyAltSvcWireFormat::VersionVector()));
4445 altsvc_ir.add_altsvc(SpdyAltSvcWireFormat::AlternativeService(
4446 "", "h1", 443, 10, SpdyAltSvcWireFormat::VersionVector()));
4447 SpdySerializedFrame frame(framer.SerializeFrame(altsvc_ir));
4448 if (use_output_) {
4449 output_.Reset();
4450 ASSERT_TRUE(framer.SerializeFrame(altsvc_ir, &output_));
4451 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
4452 }
4453 framer.ProcessInput(frame.data(), frame.size());
4454
4455 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4456 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.spdy_framer_error())
4457 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
4458 }
4459
4460 TEST_P(SpdyFramerTest, OnAltSvcBadLengths) {
4461 const unsigned char kType = SerializeFrameType(SpdyFrameType::ALTSVC);
4462 const unsigned char kFrameDataOriginLenLargerThanFrame[] = {
4463 0x00, 0x00, 0x05, kType, 0x00, 0x00, 0x00,
4464 0x00, 0x03, 0x42, 0x42, 'f', 'o', 'o',
4465 };
4466
4467 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
4468 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4469 framer.set_visitor(&visitor);
4470 visitor.SimulateInFramer(kFrameDataOriginLenLargerThanFrame,
4471 sizeof(kFrameDataOriginLenLargerThanFrame));
4472
4473 EXPECT_EQ(1, visitor.error_count_);
4474 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME,
4475 visitor.framer_.spdy_framer_error());
4476 }
4477
4478 // Tests handling of ALTSVC frames delivered in small chunks.
4479 TEST_P(SpdyFramerTest, ReadChunkedAltSvcFrame) {
4480 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4481 SpdyAltSvcIR altsvc_ir(1);
4482 SpdyAltSvcWireFormat::AlternativeService altsvc1(
4483 "pid1", "host", 443, 5, SpdyAltSvcWireFormat::VersionVector());
4484 SpdyAltSvcWireFormat::AlternativeService altsvc2(
4485 "p\"=i:d", "h_\\o\"st", 123, 42, SpdyAltSvcWireFormat::VersionVector{24});
4486 altsvc_ir.add_altsvc(altsvc1);
4487 altsvc_ir.add_altsvc(altsvc2);
4488
4489 SpdySerializedFrame control_frame(framer.SerializeAltSvc(altsvc_ir));
4490 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
4491
4492 // Read data in small chunks.
4493 size_t framed_data = 0;
4494 size_t unframed_data = control_frame.size();
4495 size_t kReadChunkSize = 5; // Read five bytes at a time.
4496 while (unframed_data > 0) {
4497 size_t to_read = std::min(kReadChunkSize, unframed_data);
4498 visitor.SimulateInFramer(
4499 reinterpret_cast<unsigned char*>(control_frame.data() + framed_data),
4500 to_read);
4501 unframed_data -= to_read;
4502 framed_data += to_read;
4503 }
4504 EXPECT_EQ(0, visitor.error_count_);
4505 EXPECT_EQ(1, visitor.altsvc_count_);
4506 ASSERT_EQ(2u, visitor.test_altsvc_ir_.altsvc_vector().size());
4507 EXPECT_TRUE(visitor.test_altsvc_ir_.altsvc_vector()[0] == altsvc1);
4508 EXPECT_TRUE(visitor.test_altsvc_ir_.altsvc_vector()[1] == altsvc2);
4509 }
4510
4511 // While RFC7838 Section 4 says that an ALTSVC frame on stream 0 with empty
4512 // origin MUST be ignored, it is not implemented at the framer level: instead,
4513 // such frames are passed on to the consumer.
4514 TEST_P(SpdyFramerTest, ReadAltSvcFrame) {
4515 constexpr struct {
4516 uint32_t stream_id;
4517 const char* origin;
4518 } test_cases[] = {{0, ""},
4519 {1, ""},
4520 {0, "https://www.example.com"},
4521 {1, "https://www.example.com"}};
4522 for (const auto& test_case : test_cases) {
4523 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4524 SpdyAltSvcIR altsvc_ir(test_case.stream_id);
4525 SpdyAltSvcWireFormat::AlternativeService altsvc(
4526 "pid1", "host", 443, 5, SpdyAltSvcWireFormat::VersionVector());
4527 altsvc_ir.add_altsvc(altsvc);
4528 altsvc_ir.set_origin(test_case.origin);
4529 SpdySerializedFrame frame(framer.SerializeAltSvc(altsvc_ir));
4530
4531 TestSpdyVisitor visitor(SpdyFramer::ENABLE_COMPRESSION);
4532 framer.set_visitor(&visitor);
4533 framer.ProcessInput(frame.data(), frame.size());
4534
4535 EXPECT_EQ(0, visitor.error_count_);
4536 EXPECT_EQ(1, visitor.altsvc_count_);
4537 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
4538 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.spdy_framer_error())
4539 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
4540 }
4541 }
4542
4543 // An ALTSVC frame with invalid Alt-Svc-Field-Value results in an error.
4544 TEST_P(SpdyFramerTest, ErrorOnAltSvcFrameWithInvalidValue) {
4545 // Alt-Svc-Field-Value must be "clear" or must contain an "=" character
4546 // per RFC7838 Section 3.
4547 const char kFrameData[] = {
4548 0x00, 0x00, 0x16, // Length: 22
4549 0x0a, // Type: ALTSVC
4550 0x00, // Flags: none
4551 0x00, 0x00, 0x00, 0x01, // Stream: 1
4552 0x00, 0x00, // Origin-Len: 0
4553 0x74, 0x68, 0x69, 0x73, // thisisnotavalidvalue
4554 0x69, 0x73, 0x6e, 0x6f, 0x74, 0x61, 0x76, 0x61,
4555 0x6c, 0x69, 0x64, 0x76, 0x61, 0x6c, 0x75, 0x65,
4556 };
4557
4558 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4559 TestSpdyVisitor visitor(SpdyFramer::ENABLE_COMPRESSION);
4560 framer.set_visitor(&visitor);
4561 framer.ProcessInput(kFrameData, sizeof(kFrameData));
4562
4563 EXPECT_EQ(1, visitor.error_count_);
4564 EXPECT_EQ(0, visitor.altsvc_count_);
4565 EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state());
4566 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.spdy_framer_error())
4567 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
4568 }
4569
4570 // Tests handling of PRIORITY frames.
4571 TEST_P(SpdyFramerTest, ReadPriority) {
4572 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4573 SpdyPriorityIR priority(3, 1, 256, false);
4574 SpdySerializedFrame frame(framer.SerializePriority(priority));
4575 if (use_output_) {
4576 output_.Reset();
4577 ASSERT_TRUE(framer.SerializePriority(priority, &output_));
4578 frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
4579 }
4580 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4581 framer.set_visitor(&visitor);
4582 EXPECT_CALL(visitor, OnPriority(3, 1, 256, false));
4583 framer.ProcessInput(frame.data(), frame.size());
4584
4585 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
4586 EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.spdy_framer_error())
4587 << SpdyFramer::SpdyFramerErrorToString(framer.spdy_framer_error());
4588 // TODO(mlavan): once we actually maintain a priority tree,
4589 // check that state is adjusted correctly.
4590 }
4591
4592 // Tests handling of PRIORITY frame with incorrect size.
4593 TEST_P(SpdyFramerTest, ReadIncorrectlySizedPriority) {
4594 // PRIORITY frame of size 4, which isn't correct.
4595 const unsigned char kFrameData[] = {
4596 0x00, 0x00, 0x04, // Length: 4
4597 0x02, // Type: PRIORITY
4598 0x00, // Flags: none
4599 0x00, 0x00, 0x00, 0x03, // Stream: 3
4600 0x00, 0x00, 0x00, 0x01, // Priority (Truncated)
4601 };
4602
4603 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
4604 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
4605
4606 EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
4607 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_SIZE,
4608 visitor.framer_.spdy_framer_error())
4609 << SpdyFramer::SpdyFramerErrorToString(
4610 visitor.framer_.spdy_framer_error());
4611 }
4612
4613 // Tests handling of PING frame with incorrect size.
4614 TEST_P(SpdyFramerTest, ReadIncorrectlySizedPing) {
4615 // PING frame of size 4, which isn't correct.
4616 const unsigned char kFrameData[] = {
4617 0x00, 0x00, 0x04, // Length: 4
4618 0x06, // Type: PING
4619 0x00, // Flags: none
4620 0x00, 0x00, 0x00, 0x00, // Stream: 0
4621 0x00, 0x00, 0x00, 0x01, // Ping (Truncated)
4622 };
4623
4624 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
4625 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
4626
4627 EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
4628 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_SIZE,
4629 visitor.framer_.spdy_framer_error())
4630 << SpdyFramer::SpdyFramerErrorToString(
4631 visitor.framer_.spdy_framer_error());
4632 }
4633
4634 // Tests handling of WINDOW_UPDATE frame with incorrect size.
4635 TEST_P(SpdyFramerTest, ReadIncorrectlySizedWindowUpdate) {
4636 // WINDOW_UPDATE frame of size 3, which isn't correct.
4637 const unsigned char kFrameData[] = {
4638 0x00, 0x00, 0x03, // Length: 3
4639 0x08, // Type: WINDOW_UPDATE
4640 0x00, // Flags: none
4641 0x00, 0x00, 0x00, 0x03, // Stream: 3
4642 0x00, 0x00, 0x01, // WindowUpdate (Truncated)
4643 };
4644
4645 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
4646 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
4647
4648 EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
4649 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_SIZE,
4650 visitor.framer_.spdy_framer_error())
4651 << SpdyFramer::SpdyFramerErrorToString(
4652 visitor.framer_.spdy_framer_error());
4653 }
4654
4655 // Tests handling of RST_STREAM frame with incorrect size.
4656 TEST_P(SpdyFramerTest, ReadIncorrectlySizedRstStream) {
4657 // RST_STREAM frame of size 3, which isn't correct.
4658 const unsigned char kFrameData[] = {
4659 0x00, 0x00, 0x03, // Length: 3
4660 0x03, // Type: RST_STREAM
4661 0x00, // Flags: none
4662 0x00, 0x00, 0x00, 0x03, // Stream: 3
4663 0x00, 0x00, 0x01, // RstStream (Truncated)
4664 };
4665
4666 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
4667 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
4668
4669 EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
4670 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_SIZE,
4671 visitor.framer_.spdy_framer_error())
4672 << SpdyFramer::SpdyFramerErrorToString(
4673 visitor.framer_.spdy_framer_error());
4674 }
4675
4676 // Regression test for https://crbug.com/548674:
4677 // RST_STREAM with payload must not be accepted.
4678 TEST_P(SpdyFramerTest, ReadInvalidRstStreamWithPayload) {
4679 const unsigned char kFrameData[] = {
4680 0x00, 0x00, 0x07, // Length: 7
4681 0x03, // Type: RST_STREAM
4682 0x00, // Flags: none
4683 0x00, 0x00, 0x00, 0x01, // Stream: 1
4684 0x00, 0x00, 0x00, 0x00, // Error: NO_ERROR
4685 'f', 'o', 'o' // Payload: "foo"
4686 };
4687
4688 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
4689 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
4690
4691 EXPECT_EQ(SpdyFramer::SPDY_ERROR, visitor.framer_.state());
4692 EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_SIZE,
4693 visitor.framer_.spdy_framer_error())
4694 << SpdyFramer::SpdyFramerErrorToString(
4695 visitor.framer_.spdy_framer_error());
4696 }
4697
4698 // Test that SpdyFramer processes, by default, all passed input in one call
4699 // to ProcessInput (i.e. will not be calling set_process_single_input_frame()).
4700 TEST_P(SpdyFramerTest, ProcessAllInput) {
4701 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4702 auto visitor =
4703 base::MakeUnique<TestSpdyVisitor>(SpdyFramer::DISABLE_COMPRESSION);
4704 framer.set_visitor(visitor.get());
4705
4706 // Create two input frames.
4707 SpdyHeadersIR headers(1);
4708 headers.SetHeader("alpha", "beta");
4709 headers.SetHeader("gamma", "charlie");
4710 headers.SetHeader("cookie", "key1=value1; key2=value2");
4711 SpdySerializedFrame headers_frame(SpdyFramerPeer::SerializeHeaders(
4712 &framer, headers, use_output_ ? &output_ : nullptr));
4713
4714 const char four_score[] = "Four score and seven years ago";
4715 SpdyDataIR four_score_ir(1, four_score);
4716 SpdySerializedFrame four_score_frame(framer.SerializeData(four_score_ir));
4717
4718 // Put them in a single buffer (new variables here to make it easy to
4719 // change the order and type of frames).
4720 SpdySerializedFrame frame1 = std::move(headers_frame);
4721 SpdySerializedFrame frame2 = std::move(four_score_frame);
4722
4723 const size_t frame1_size = frame1.size();
4724 const size_t frame2_size = frame2.size();
4725
4726 VLOG(1) << "frame1_size = " << frame1_size;
4727 VLOG(1) << "frame2_size = " << frame2_size;
4728
4729 SpdyString input_buffer;
4730 input_buffer.append(frame1.data(), frame1_size);
4731 input_buffer.append(frame2.data(), frame2_size);
4732
4733 const char* buf = input_buffer.data();
4734 const size_t buf_size = input_buffer.size();
4735
4736 VLOG(1) << "buf_size = " << buf_size;
4737
4738 size_t processed = framer.ProcessInput(buf, buf_size);
4739 EXPECT_EQ(buf_size, processed);
4740 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
4741 EXPECT_EQ(1, visitor->headers_frame_count_);
4742 EXPECT_EQ(1, visitor->data_frame_count_);
4743 EXPECT_EQ(strlen(four_score), static_cast<unsigned>(visitor->data_bytes_));
4744 }
4745
4746 // Test that SpdyFramer stops after processing a full frame if
4747 // process_single_input_frame is set. Input to ProcessInput has two frames, but
4748 // only processes the first when we give it the first frame split at any point,
4749 // or give it more than one frame in the input buffer.
4750 TEST_P(SpdyFramerTest, ProcessAtMostOneFrame) {
4751 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4752 framer.set_process_single_input_frame(true);
4753
4754 // Create two input frames.
4755 const char four_score[] = "Four score and ...";
4756 SpdyDataIR four_score_ir(1, four_score);
4757 SpdySerializedFrame four_score_frame(framer.SerializeData(four_score_ir));
4758
4759 SpdyHeadersIR headers(2);
4760 headers.SetHeader("alpha", "beta");
4761 headers.SetHeader("gamma", "charlie");
4762 headers.SetHeader("cookie", "key1=value1; key2=value2");
4763 SpdySerializedFrame headers_frame(SpdyFramerPeer::SerializeHeaders(
4764 &framer, headers, use_output_ ? &output_ : nullptr));
4765
4766 // Put them in a single buffer (new variables here to make it easy to
4767 // change the order and type of frames).
4768 SpdySerializedFrame frame1 = std::move(four_score_frame);
4769 SpdySerializedFrame frame2 = std::move(headers_frame);
4770
4771 const size_t frame1_size = frame1.size();
4772 const size_t frame2_size = frame2.size();
4773
4774 VLOG(1) << "frame1_size = " << frame1_size;
4775 VLOG(1) << "frame2_size = " << frame2_size;
4776
4777 SpdyString input_buffer;
4778 input_buffer.append(frame1.data(), frame1_size);
4779 input_buffer.append(frame2.data(), frame2_size);
4780
4781 const char* buf = input_buffer.data();
4782 const size_t buf_size = input_buffer.size();
4783
4784 VLOG(1) << "buf_size = " << buf_size;
4785
4786 for (size_t first_size = 0; first_size <= buf_size; ++first_size) {
4787 VLOG(1) << "first_size = " << first_size;
4788 auto visitor =
4789 base::MakeUnique<TestSpdyVisitor>(SpdyFramer::DISABLE_COMPRESSION);
4790 framer.set_visitor(visitor.get());
4791
4792 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
4793
4794 size_t processed_first = framer.ProcessInput(buf, first_size);
4795 if (first_size < frame1_size) {
4796 EXPECT_EQ(first_size, processed_first);
4797
4798 if (first_size == 0) {
4799 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
4800 } else {
4801 EXPECT_NE(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
4802 }
4803
4804 const char* rest = buf + processed_first;
4805 const size_t remaining = buf_size - processed_first;
4806 VLOG(1) << "remaining = " << remaining;
4807
4808 size_t processed_second = framer.ProcessInput(rest, remaining);
4809
4810 // Redundant tests just to make it easier to think about.
4811 EXPECT_EQ(frame1_size - processed_first, processed_second);
4812 size_t processed_total = processed_first + processed_second;
4813 EXPECT_EQ(frame1_size, processed_total);
4814 } else {
4815 EXPECT_EQ(frame1_size, processed_first);
4816 }
4817
4818 EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state());
4819
4820 // At this point should have processed the entirety of the first frame,
4821 // and none of the second frame.
4822
4823 EXPECT_EQ(1, visitor->data_frame_count_);
4824 EXPECT_EQ(strlen(four_score), static_cast<unsigned>(visitor->data_bytes_));
4825 EXPECT_EQ(0, visitor->headers_frame_count_);
4826 }
4827 }
4828
4829 } // namespace test
4830
4831 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/spdy_framer_decoder_adapter.cc ('k') | net/spdy/spdy_header_block.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698