| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/spdy/spdy_headers_block_parser.h" | 5 #include "net/spdy/spdy_headers_block_parser.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| 11 #include "base/sys_byteorder.h" | 11 #include "base/sys_byteorder.h" |
| 12 #include "testing/gmock/include/gmock/gmock.h" | 12 #include "testing/gmock/include/gmock/gmock.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" | 13 #include "testing/gtest/include/gtest/gtest.h" |
| 14 | 14 |
| 15 namespace net { | 15 namespace net { |
| 16 | 16 |
| 17 using base::IntToString; | 17 using base::IntToString; |
| 18 using base::StringPiece; | 18 using base::StringPiece; |
| 19 using std::string; | 19 using std::string; |
| 20 using testing::ElementsAre; | 20 using testing::ElementsAre; |
| 21 using testing::ElementsAreArray; | 21 using testing::ElementsAreArray; |
| 22 | 22 |
| 23 // A mock the handler class to check that we parse out the correct headers | 23 // A mock the handler class to check that we parse out the correct headers |
| 24 // and call the callback methods when we should. | 24 // and call the callback methods when we should. |
| 25 class MockSpdyHeadersHandler : public SpdyHeadersHandlerInterface { | 25 class MockSpdyHeadersHandler : public SpdyHeadersHandlerInterface { |
| 26 public: | 26 public: |
| 27 MOCK_METHOD2(OnHeaderBlock, void(SpdyStreamId stream_id, | 27 MOCK_METHOD2(OnHeaderBlock, |
| 28 uint32_t num_of_headers)); | 28 void(SpdyStreamId stream_id, uint32_t num_of_headers)); |
| 29 MOCK_METHOD1(OnHeaderBlockEnd, void(SpdyStreamId stream_id)); | 29 MOCK_METHOD1(OnHeaderBlockEnd, void(SpdyStreamId stream_id)); |
| 30 MOCK_METHOD3(OnHeader, void(SpdyStreamId stream_id, | 30 MOCK_METHOD3(OnHeader, |
| 31 StringPiece, | 31 void(SpdyStreamId stream_id, StringPiece, StringPiece)); |
| 32 StringPiece)); | |
| 33 }; | 32 }; |
| 34 | 33 |
| 35 class SpdyHeadersBlockParserTest : | 34 class SpdyHeadersBlockParserTest |
| 36 public ::testing::TestWithParam<SpdyMajorVersion> { | 35 : public ::testing::TestWithParam<SpdyMajorVersion> { |
| 37 public: | 36 public: |
| 38 virtual ~SpdyHeadersBlockParserTest() {} | 37 virtual ~SpdyHeadersBlockParserTest() {} |
| 39 | 38 |
| 40 protected: | 39 protected: |
| 41 virtual void SetUp() { | 40 virtual void SetUp() { |
| 42 // Create a parser using the mock handler. | 41 // Create a parser using the mock handler. |
| 43 spdy_version_ = GetParam(); | 42 spdy_version_ = GetParam(); |
| 44 parser_.reset(new SpdyHeadersBlockParser(spdy_version_, &handler_)); | 43 parser_.reset(new SpdyHeadersBlockParser(spdy_version_, &handler_)); |
| 45 length_field_size_ = | 44 length_field_size_ = |
| 46 SpdyHeadersBlockParser::LengthFieldSizeForVersion(spdy_version_); | 45 SpdyHeadersBlockParser::LengthFieldSizeForVersion(spdy_version_); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 ::testing::Values(SPDY2, SPDY3, SPDY4)); | 116 ::testing::Values(SPDY2, SPDY3, SPDY4)); |
| 118 | 117 |
| 119 TEST_P(SpdyHeadersBlockParserTest, BasicTest) { | 118 TEST_P(SpdyHeadersBlockParserTest, BasicTest) { |
| 120 // Sanity test, verify that we parse out correctly a block with | 119 // Sanity test, verify that we parse out correctly a block with |
| 121 // a single key-value pair and that we notify when we start and finish | 120 // a single key-value pair and that we notify when we start and finish |
| 122 // handling a headers block. | 121 // handling a headers block. |
| 123 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); | 122 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); |
| 124 | 123 |
| 125 std::string expect_key = base_key + IntToString(0); | 124 std::string expect_key = base_key + IntToString(0); |
| 126 std::string expect_value = base_value + IntToString(0); | 125 std::string expect_value = base_value + IntToString(0); |
| 127 EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key), | 126 EXPECT_CALL(handler_, |
| 128 StringPiece(expect_value))).Times(1); | 127 OnHeader(1, StringPiece(expect_key), StringPiece(expect_value))) |
| 128 .Times(1); |
| 129 EXPECT_CALL(handler_, OnHeaderBlockEnd(1)).Times(1); | 129 EXPECT_CALL(handler_, OnHeaderBlockEnd(1)).Times(1); |
| 130 | 130 |
| 131 string headers(CreateHeaders(1, false)); | 131 string headers(CreateHeaders(1, false)); |
| 132 EXPECT_TRUE(parser_-> | 132 EXPECT_TRUE(parser_->HandleControlFrameHeadersData( |
| 133 HandleControlFrameHeadersData(1, headers.c_str(), headers.length())); | 133 1, headers.c_str(), headers.length())); |
| 134 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); | 134 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); |
| 135 } | 135 } |
| 136 | 136 |
| 137 TEST_P(SpdyHeadersBlockParserTest, NullsSupportedTest) { | 137 TEST_P(SpdyHeadersBlockParserTest, NullsSupportedTest) { |
| 138 // Sanity test, verify that we parse out correctly a block with | 138 // Sanity test, verify that we parse out correctly a block with |
| 139 // a single key-value pair when the key and value contain null charecters. | 139 // a single key-value pair when the key and value contain null charecters. |
| 140 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); | 140 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); |
| 141 | 141 |
| 142 std::string expect_key = base_key + string("\0", 1) + IntToString(0); | 142 std::string expect_key = base_key + string("\0", 1) + IntToString(0); |
| 143 std::string expect_value = base_value + string("\0", 1) + IntToString(0); | 143 std::string expect_value = base_value + string("\0", 1) + IntToString(0); |
| 144 EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key), | 144 EXPECT_CALL(handler_, |
| 145 StringPiece(expect_value))).Times(1); | 145 OnHeader(1, StringPiece(expect_key), StringPiece(expect_value))) |
| 146 .Times(1); |
| 146 EXPECT_CALL(handler_, OnHeaderBlockEnd(1)).Times(1); | 147 EXPECT_CALL(handler_, OnHeaderBlockEnd(1)).Times(1); |
| 147 | 148 |
| 148 string headers(CreateHeaders(1, true)); | 149 string headers(CreateHeaders(1, true)); |
| 149 EXPECT_TRUE(parser_-> | 150 EXPECT_TRUE(parser_->HandleControlFrameHeadersData( |
| 150 HandleControlFrameHeadersData(1, headers.c_str(), headers.length())); | 151 1, headers.c_str(), headers.length())); |
| 151 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); | 152 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); |
| 152 } | 153 } |
| 153 | 154 |
| 154 TEST_P(SpdyHeadersBlockParserTest, MultipleBlocksAndHeadersWithPartialData) { | 155 TEST_P(SpdyHeadersBlockParserTest, MultipleBlocksAndHeadersWithPartialData) { |
| 155 testing::InSequence s; | 156 testing::InSequence s; |
| 156 | 157 |
| 157 // The mock doesn't retain storage of arguments, so keep them in scope. | 158 // The mock doesn't retain storage of arguments, so keep them in scope. |
| 158 std::vector<string> retained_arguments; | 159 std::vector<string> retained_arguments; |
| 159 for (int i = 0; i < kNumHeadersInBlock; i++) { | 160 for (int i = 0; i < kNumHeadersInBlock; i++) { |
| 160 retained_arguments.push_back(base_key + IntToString(i)); | 161 retained_arguments.push_back(base_key + IntToString(i)); |
| 161 retained_arguments.push_back(base_value + IntToString(i)); | 162 retained_arguments.push_back(base_value + IntToString(i)); |
| 162 } | 163 } |
| 163 // For each block we expect to parse out the headers in order. | 164 // For each block we expect to parse out the headers in order. |
| 164 for (int i = 0; i < kNumHeaderBlocks; i++) { | 165 for (int i = 0; i < kNumHeaderBlocks; i++) { |
| 165 EXPECT_CALL(handler_, OnHeaderBlock(i, kNumHeadersInBlock)).Times(1); | 166 EXPECT_CALL(handler_, OnHeaderBlock(i, kNumHeadersInBlock)).Times(1); |
| 166 for (int j = 0; j < kNumHeadersInBlock; j++) { | 167 for (int j = 0; j < kNumHeadersInBlock; j++) { |
| 167 EXPECT_CALL(handler_, OnHeader( | 168 EXPECT_CALL(handler_, |
| 168 i, | 169 OnHeader(i, |
| 169 StringPiece(retained_arguments[2 * j]), | 170 StringPiece(retained_arguments[2 * j]), |
| 170 StringPiece(retained_arguments[2 * j + 1]))).Times(1); | 171 StringPiece(retained_arguments[2 * j + 1]))) |
| 172 .Times(1); |
| 171 } | 173 } |
| 172 EXPECT_CALL(handler_, OnHeaderBlockEnd(i)).Times(1); | 174 EXPECT_CALL(handler_, OnHeaderBlockEnd(i)).Times(1); |
| 173 } | 175 } |
| 174 // Parse the header blocks, feeding the parser one byte at a time. | 176 // Parse the header blocks, feeding the parser one byte at a time. |
| 175 for (int i = 0; i < kNumHeaderBlocks; i++) { | 177 for (int i = 0; i < kNumHeaderBlocks; i++) { |
| 176 string headers(CreateHeaders(kNumHeadersInBlock, false)); | 178 string headers(CreateHeaders(kNumHeadersInBlock, false)); |
| 177 for (string::iterator it = headers.begin(); it != headers.end(); ++it) { | 179 for (string::iterator it = headers.begin(); it != headers.end(); ++it) { |
| 178 if ((it + 1) == headers.end()) { | 180 if ((it + 1) == headers.end()) { |
| 179 // Last byte completes the block. | 181 // Last byte completes the block. |
| 180 EXPECT_TRUE(parser_->HandleControlFrameHeadersData(i, &(*it), 1)); | 182 EXPECT_TRUE(parser_->HandleControlFrameHeadersData(i, &(*it), 1)); |
| 181 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); | 183 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); |
| 182 } else { | 184 } else { |
| 183 EXPECT_FALSE(parser_->HandleControlFrameHeadersData(i, &(*it), 1)); | 185 EXPECT_FALSE(parser_->HandleControlFrameHeadersData(i, &(*it), 1)); |
| 184 EXPECT_EQ(SpdyHeadersBlockParser::NEED_MORE_DATA, parser_->get_error()); | 186 EXPECT_EQ(SpdyHeadersBlockParser::NEED_MORE_DATA, parser_->get_error()); |
| 185 } | 187 } |
| 186 } | 188 } |
| 187 } | 189 } |
| 188 } | 190 } |
| 189 | 191 |
| 190 TEST_P(SpdyHeadersBlockParserTest, HandlesEmptyCallsTest) { | 192 TEST_P(SpdyHeadersBlockParserTest, HandlesEmptyCallsTest) { |
| 191 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); | 193 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); |
| 192 | 194 |
| 193 string expect_key = base_key + IntToString(0); | 195 string expect_key = base_key + IntToString(0); |
| 194 string expect_value = base_value + IntToString(0); | 196 string expect_value = base_value + IntToString(0); |
| 195 EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key), | 197 EXPECT_CALL(handler_, |
| 196 StringPiece(expect_value))).Times(1); | 198 OnHeader(1, StringPiece(expect_key), StringPiece(expect_value))) |
| 199 .Times(1); |
| 197 EXPECT_CALL(handler_, OnHeaderBlockEnd(1)).Times(1); | 200 EXPECT_CALL(handler_, OnHeaderBlockEnd(1)).Times(1); |
| 198 | 201 |
| 199 // Send a header in pieces with intermediate empty calls. | 202 // Send a header in pieces with intermediate empty calls. |
| 200 string headers(CreateHeaders(1, false)); | 203 string headers(CreateHeaders(1, false)); |
| 201 for (string::iterator it = headers.begin(); it != headers.end(); ++it) { | 204 for (string::iterator it = headers.begin(); it != headers.end(); ++it) { |
| 202 if ((it + 1) == headers.end()) { | 205 if ((it + 1) == headers.end()) { |
| 203 // Last byte completes the block. | 206 // Last byte completes the block. |
| 204 EXPECT_TRUE(parser_->HandleControlFrameHeadersData(1, &(*it), 1)); | 207 EXPECT_TRUE(parser_->HandleControlFrameHeadersData(1, &(*it), 1)); |
| 205 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); | 208 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); |
| 206 } else { | 209 } else { |
| 207 EXPECT_FALSE(parser_->HandleControlFrameHeadersData(1, &(*it), 1)); | 210 EXPECT_FALSE(parser_->HandleControlFrameHeadersData(1, &(*it), 1)); |
| 208 EXPECT_EQ(SpdyHeadersBlockParser::NEED_MORE_DATA, parser_->get_error()); | 211 EXPECT_EQ(SpdyHeadersBlockParser::NEED_MORE_DATA, parser_->get_error()); |
| 209 EXPECT_FALSE(parser_->HandleControlFrameHeadersData(1, NULL, 0)); | 212 EXPECT_FALSE(parser_->HandleControlFrameHeadersData(1, NULL, 0)); |
| 210 } | 213 } |
| 211 } | 214 } |
| 212 } | 215 } |
| 213 | 216 |
| 214 TEST_P(SpdyHeadersBlockParserTest, LargeBlocksDiscardedTest) { | 217 TEST_P(SpdyHeadersBlockParserTest, LargeBlocksDiscardedTest) { |
| 215 // Header block with too many headers. | 218 // Header block with too many headers. |
| 216 { | 219 { |
| 217 string headers = EncodeLength( | 220 string headers = |
| 218 parser_->MaxNumberOfHeadersForVersion(spdy_version_) + 1); | 221 EncodeLength(parser_->MaxNumberOfHeadersForVersion(spdy_version_) + 1); |
| 219 EXPECT_FALSE(parser_-> | 222 EXPECT_FALSE(parser_->HandleControlFrameHeadersData( |
| 220 HandleControlFrameHeadersData(1, headers.c_str(), headers.length())); | 223 1, headers.c_str(), headers.length())); |
| 221 EXPECT_EQ(SpdyHeadersBlockParser::HEADER_BLOCK_TOO_LARGE, | 224 EXPECT_EQ(SpdyHeadersBlockParser::HEADER_BLOCK_TOO_LARGE, |
| 222 parser_->get_error()); | 225 parser_->get_error()); |
| 223 } | 226 } |
| 224 parser_->Reset(); | 227 parser_->Reset(); |
| 225 // Header block with one header, which has a too-long key. | 228 // Header block with one header, which has a too-long key. |
| 226 { | 229 { |
| 227 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); | 230 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); |
| 228 | 231 |
| 229 string headers = EncodeLength(1) + EncodeLength( | 232 string headers = |
| 230 SpdyHeadersBlockParser::kMaximumFieldLength + 1); | 233 EncodeLength(1) + |
| 231 EXPECT_FALSE(parser_-> | 234 EncodeLength(SpdyHeadersBlockParser::kMaximumFieldLength + 1); |
| 232 HandleControlFrameHeadersData(1, headers.c_str(), headers.length())); | 235 EXPECT_FALSE(parser_->HandleControlFrameHeadersData( |
| 236 1, headers.c_str(), headers.length())); |
| 233 EXPECT_EQ(SpdyHeadersBlockParser::HEADER_FIELD_TOO_LARGE, | 237 EXPECT_EQ(SpdyHeadersBlockParser::HEADER_FIELD_TOO_LARGE, |
| 234 parser_->get_error()); | 238 parser_->get_error()); |
| 235 } | 239 } |
| 236 } | 240 } |
| 237 | 241 |
| 238 TEST_P(SpdyHeadersBlockParserTest, ExtraDataTest) { | 242 TEST_P(SpdyHeadersBlockParserTest, ExtraDataTest) { |
| 239 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); | 243 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); |
| 240 EXPECT_CALL(handler_, OnHeaderBlockEnd(1)).Times(1); | 244 EXPECT_CALL(handler_, OnHeaderBlockEnd(1)).Times(1); |
| 241 | 245 |
| 242 string expect_key = base_key + IntToString(0); | 246 string expect_key = base_key + IntToString(0); |
| 243 string expect_value = base_value + IntToString(0); | 247 string expect_value = base_value + IntToString(0); |
| 244 EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key), | 248 EXPECT_CALL(handler_, |
| 245 StringPiece(expect_value))).Times(1); | 249 OnHeader(1, StringPiece(expect_key), StringPiece(expect_value))) |
| 250 .Times(1); |
| 246 | 251 |
| 247 string headers = CreateHeaders(1, false) + "foobar"; | 252 string headers = CreateHeaders(1, false) + "foobar"; |
| 248 EXPECT_FALSE(parser_-> | 253 EXPECT_FALSE(parser_->HandleControlFrameHeadersData( |
| 249 HandleControlFrameHeadersData(1, headers.c_str(), headers.length())); | 254 1, headers.c_str(), headers.length())); |
| 250 EXPECT_EQ(SpdyHeadersBlockParser::TOO_MUCH_DATA, parser_->get_error()); | 255 EXPECT_EQ(SpdyHeadersBlockParser::TOO_MUCH_DATA, parser_->get_error()); |
| 251 } | 256 } |
| 252 | 257 |
| 253 } // namespace net | 258 } // namespace net |
| OLD | NEW |