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