15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/spdy/spdy_headers_block_parser.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <string>
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/sys_byteorder.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace net {
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::IntToString;
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::StringPiece;
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using std::string;
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using testing::ElementsAre;
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using testing::ElementsAreArray;
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A mock the handler class to check that we parse out the correct headers
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// and call the callback methods when we should.
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class MockSpdyHeadersHandler : public SpdyHeadersHandlerInterface {
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MOCK_METHOD2(OnHeaderBlock, void(SpdyStreamId stream_id,
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   uint32_t num_of_headers));
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MOCK_METHOD2(OnHeaderBlockEnd, void(SpdyStreamId stream_id, size_t bytes));
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MOCK_METHOD3(OnHeader, void(SpdyStreamId stream_id,
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              StringPiece,
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              StringPiece));
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class SpdyHeadersBlockParserTest :
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    public ::testing::TestWithParam<SpdyMajorVersion> {
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~SpdyHeadersBlockParserTest() {}
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) protected:
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void SetUp() {
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Create a parser using the mock handler.
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    spdy_version_ = GetParam();
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    parser_.reset(new SpdyHeadersBlockParser(spdy_version_, &handler_));
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    length_field_size_ =
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        SpdyHeadersBlockParser::LengthFieldSizeForVersion(spdy_version_);
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Create a header block with a specified number of headers.
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  string CreateHeaders(uint32_t num_headers, bool insert_nulls) {
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    string headers;
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // First, write the number of headers in the header block.
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    headers += EncodeLength(num_headers);
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Second, write the key-value pairs.
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (uint32_t i = 0; i < num_headers; i++) {
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Build the key.
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      string key;
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (insert_nulls) {
61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        key = string(kBaseKey) + string("\0", 1) + IntToString(i);
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        key = string(kBaseKey) + IntToString(i);
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Encode the key as SPDY header.
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      headers += EncodeLength(key.length());
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      headers += key;
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Build the value.
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      string value;
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (insert_nulls) {
72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        value = string(kBaseValue) + string("\0", 1) + IntToString(i);
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        value = string(kBaseValue) + IntToString(i);
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Encode the value as SPDY header.
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      headers += EncodeLength(value.length());
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      headers += value;
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return headers;
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  string EncodeLength(uint32_t len) {
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    char buffer[4];
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (length_field_size_ == sizeof(uint32_t)) {
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      uint32_t net_order_len = htonl(len);
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      memcpy(buffer, &net_order_len, length_field_size_);
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    } else if (length_field_size_ == sizeof(uint16_t)) {
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      uint16_t net_order_len = htons(len);
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      memcpy(buffer, &net_order_len, length_field_size_);
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    } else {
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      CHECK(false) << "Invalid length field size";
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return string(buffer, length_field_size_);
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  size_t length_field_size_;
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SpdyMajorVersion spdy_version_;
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MockSpdyHeadersHandler handler_;
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<SpdyHeadersBlockParser> parser_;
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  static const char *const kBaseKey;
104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  static const char *const kBaseValue;
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Number of headers and header blocks used in the tests.
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static const int kNumHeadersInBlock = 10;
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static const int kNumHeaderBlocks = 10;
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
111116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst char *const SpdyHeadersBlockParserTest::kBaseKey = "test_key";
112116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst char *const SpdyHeadersBlockParserTest::kBaseValue = "test_value";
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// All tests are run with 3 different SPDY versions: SPDY/2, SPDY/3, SPDY/4.
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)INSTANTIATE_TEST_CASE_P(SpdyHeadersBlockParserTests,
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        SpdyHeadersBlockParserTest,
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        ::testing::Values(SPDY2, SPDY3, SPDY4));
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_P(SpdyHeadersBlockParserTest, BasicTest) {
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Sanity test, verify that we parse out correctly a block with
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // a single key-value pair and that we notify when we start and finish
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // handling a headers block.
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  string headers(CreateHeaders(1, false));
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1);
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string expect_key = kBaseKey + IntToString(0);
128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string expect_value = kBaseValue + IntToString(0);
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key),
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 StringPiece(expect_value))).Times(1);
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_CALL(handler_, OnHeaderBlockEnd(1, headers.length())).Times(1);
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(parser_->
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      HandleControlFrameHeadersData(1, headers.c_str(), headers.length()));
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error());
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_P(SpdyHeadersBlockParserTest, NullsSupportedTest) {
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Sanity test, verify that we parse out correctly a block with
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // a single key-value pair when the key and value contain null charecters.
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  string headers(CreateHeaders(1, true));
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1);
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string expect_key = kBaseKey + string("\0", 1) + IntToString(0);
146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string expect_value = kBaseValue + string("\0", 1) + IntToString(0);
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key),
148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 StringPiece(expect_value))).Times(1);
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_CALL(handler_, OnHeaderBlockEnd(1, headers.length())).Times(1);
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(parser_->
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      HandleControlFrameHeadersData(1, headers.c_str(), headers.length()));
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error());
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_P(SpdyHeadersBlockParserTest, MultipleBlocksAndHeadersWithPartialData) {
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  testing::InSequence s;
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // CreateHeaders is deterministic; we can call it once for the whole test.
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  string headers(CreateHeaders(kNumHeadersInBlock, false));
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The mock doesn't retain storage of arguments, so keep them in scope.
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<string> retained_arguments;
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (int i = 0; i < kNumHeadersInBlock; i++) {
165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    retained_arguments.push_back(kBaseKey + IntToString(i));
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    retained_arguments.push_back(kBaseValue + IntToString(i));
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // For each block we expect to parse out the headers in order.
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (int i = 0; i < kNumHeaderBlocks; i++) {
170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    EXPECT_CALL(handler_, OnHeaderBlock(i, kNumHeadersInBlock)).Times(1);
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (int j = 0; j < kNumHeadersInBlock; j++) {
172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      EXPECT_CALL(handler_, OnHeader(
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          i,
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          StringPiece(retained_arguments[2 * j]),
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          StringPiece(retained_arguments[2 * j + 1]))).Times(1);
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    EXPECT_CALL(handler_, OnHeaderBlockEnd(i, headers.length())).Times(1);
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Parse the header blocks, feeding the parser one byte at a time.
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (int i = 0; i < kNumHeaderBlocks; i++) {
181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    for (string::iterator it = headers.begin(); it != headers.end(); ++it) {
182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if ((it + 1) == headers.end()) {
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        // Last byte completes the block.
184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        EXPECT_TRUE(parser_->HandleControlFrameHeadersData(i, &(*it), 1));
185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error());
186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      } else {
187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        EXPECT_FALSE(parser_->HandleControlFrameHeadersData(i, &(*it), 1));
188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        EXPECT_EQ(SpdyHeadersBlockParser::NEED_MORE_DATA, parser_->get_error());
189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      }
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_P(SpdyHeadersBlockParserTest, HandlesEmptyCallsTest) {
195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1);
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  string headers(CreateHeaders(1, false));
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  string expect_key = kBaseKey + IntToString(0);
200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  string expect_value = kBaseValue + IntToString(0);
201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key),
202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 StringPiece(expect_value))).Times(1);
203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_CALL(handler_, OnHeaderBlockEnd(1, headers.length())).Times(1);
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Send a header in pieces with intermediate empty calls.
206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (string::iterator it = headers.begin(); it != headers.end(); ++it) {
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if ((it + 1) == headers.end()) {
208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // Last byte completes the block.
209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      EXPECT_TRUE(parser_->HandleControlFrameHeadersData(1, &(*it), 1));
210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error());
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    } else {
212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      EXPECT_FALSE(parser_->HandleControlFrameHeadersData(1, &(*it), 1));
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      EXPECT_EQ(SpdyHeadersBlockParser::NEED_MORE_DATA, parser_->get_error());
214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      EXPECT_FALSE(parser_->HandleControlFrameHeadersData(1, NULL, 0));
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_P(SpdyHeadersBlockParserTest, LargeBlocksDiscardedTest) {
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Header block with too many headers.
221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  {
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    string headers = EncodeLength(
223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        parser_->MaxNumberOfHeadersForVersion(spdy_version_) + 1);
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    EXPECT_FALSE(parser_->
225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        HandleControlFrameHeadersData(1, headers.c_str(), headers.length()));
226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    EXPECT_EQ(SpdyHeadersBlockParser::HEADER_BLOCK_TOO_LARGE,
227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              parser_->get_error());
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  parser_->Reset();
230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Header block with one header, which has a too-long key.
231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  {
232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1);
233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    string headers = EncodeLength(1) + EncodeLength(
235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        SpdyHeadersBlockParser::kMaximumFieldLength + 1);
236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    EXPECT_FALSE(parser_->
237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        HandleControlFrameHeadersData(1, headers.c_str(), headers.length()));
238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    EXPECT_EQ(SpdyHeadersBlockParser::HEADER_FIELD_TOO_LARGE,
239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              parser_->get_error());
240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_P(SpdyHeadersBlockParserTest, ExtraDataTest) {
244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  string headers = CreateHeaders(1, false) + "foobar";
245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1);
247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_CALL(handler_, OnHeaderBlockEnd(1, headers.length())).Times(1);
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
249116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  string expect_key = kBaseKey + IntToString(0);
250116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  string expect_value = kBaseValue + IntToString(0);
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key),
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 StringPiece(expect_value))).Times(1);
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_FALSE(parser_->
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      HandleControlFrameHeadersData(1, headers.c_str(), headers.length()));
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(SpdyHeadersBlockParser::TOO_MUCH_DATA, parser_->get_error());
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace net
260