| 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, void(SpdyStreamId stream_id, |
| 28 uint32_t num_of_headers)); | 28 uint32_t num_of_headers)); |
| 29 MOCK_METHOD1(OnHeaderBlockEnd, void(SpdyStreamId stream_id)); | 29 MOCK_METHOD2(OnHeaderBlockEnd, void(SpdyStreamId stream_id, size_t bytes)); |
| 30 MOCK_METHOD3(OnHeader, void(SpdyStreamId stream_id, | 30 MOCK_METHOD3(OnHeader, void(SpdyStreamId stream_id, |
| 31 StringPiece, | 31 StringPiece, |
| 32 StringPiece)); | 32 StringPiece)); |
| 33 }; | 33 }; |
| 34 | 34 |
| 35 class SpdyHeadersBlockParserTest : | 35 class SpdyHeadersBlockParserTest : |
| 36 public ::testing::TestWithParam<SpdyMajorVersion> { | 36 public ::testing::TestWithParam<SpdyMajorVersion> { |
| 37 public: | 37 public: |
| 38 virtual ~SpdyHeadersBlockParserTest() {} | 38 virtual ~SpdyHeadersBlockParserTest() {} |
| 39 | 39 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 | 113 |
| 114 // All tests are run with 3 different SPDY versions: SPDY/2, SPDY/3, SPDY/4. | 114 // All tests are run with 3 different SPDY versions: SPDY/2, SPDY/3, SPDY/4. |
| 115 INSTANTIATE_TEST_CASE_P(SpdyHeadersBlockParserTests, | 115 INSTANTIATE_TEST_CASE_P(SpdyHeadersBlockParserTests, |
| 116 SpdyHeadersBlockParserTest, | 116 SpdyHeadersBlockParserTest, |
| 117 ::testing::Values(SPDY2, SPDY3, SPDY4)); | 117 ::testing::Values(SPDY2, SPDY3, SPDY4)); |
| 118 | 118 |
| 119 TEST_P(SpdyHeadersBlockParserTest, BasicTest) { | 119 TEST_P(SpdyHeadersBlockParserTest, BasicTest) { |
| 120 // Sanity test, verify that we parse out correctly a block with | 120 // 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 | 121 // a single key-value pair and that we notify when we start and finish |
| 122 // handling a headers block. | 122 // handling a headers block. |
| 123 string headers(CreateHeaders(1, false)); |
| 124 |
| 123 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); | 125 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); |
| 124 | 126 |
| 125 std::string expect_key = base_key + IntToString(0); | 127 std::string expect_key = base_key + IntToString(0); |
| 126 std::string expect_value = base_value + IntToString(0); | 128 std::string expect_value = base_value + IntToString(0); |
| 127 EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key), | 129 EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key), |
| 128 StringPiece(expect_value))).Times(1); | 130 StringPiece(expect_value))).Times(1); |
| 129 EXPECT_CALL(handler_, OnHeaderBlockEnd(1)).Times(1); | 131 EXPECT_CALL(handler_, OnHeaderBlockEnd(1, headers.length())).Times(1); |
| 130 | 132 |
| 131 string headers(CreateHeaders(1, false)); | |
| 132 EXPECT_TRUE(parser_-> | 133 EXPECT_TRUE(parser_-> |
| 133 HandleControlFrameHeadersData(1, headers.c_str(), headers.length())); | 134 HandleControlFrameHeadersData(1, headers.c_str(), headers.length())); |
| 134 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); | 135 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); |
| 135 } | 136 } |
| 136 | 137 |
| 137 TEST_P(SpdyHeadersBlockParserTest, NullsSupportedTest) { | 138 TEST_P(SpdyHeadersBlockParserTest, NullsSupportedTest) { |
| 138 // Sanity test, verify that we parse out correctly a block with | 139 // 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. | 140 // a single key-value pair when the key and value contain null charecters. |
| 141 string headers(CreateHeaders(1, true)); |
| 142 |
| 140 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); | 143 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); |
| 141 | 144 |
| 142 std::string expect_key = base_key + string("\0", 1) + IntToString(0); | 145 std::string expect_key = base_key + string("\0", 1) + IntToString(0); |
| 143 std::string expect_value = base_value + string("\0", 1) + IntToString(0); | 146 std::string expect_value = base_value + string("\0", 1) + IntToString(0); |
| 144 EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key), | 147 EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key), |
| 145 StringPiece(expect_value))).Times(1); | 148 StringPiece(expect_value))).Times(1); |
| 146 EXPECT_CALL(handler_, OnHeaderBlockEnd(1)).Times(1); | 149 EXPECT_CALL(handler_, OnHeaderBlockEnd(1, headers.length())).Times(1); |
| 147 | 150 |
| 148 string headers(CreateHeaders(1, true)); | |
| 149 EXPECT_TRUE(parser_-> | 151 EXPECT_TRUE(parser_-> |
| 150 HandleControlFrameHeadersData(1, headers.c_str(), headers.length())); | 152 HandleControlFrameHeadersData(1, headers.c_str(), headers.length())); |
| 151 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); | 153 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); |
| 152 } | 154 } |
| 153 | 155 |
| 154 TEST_P(SpdyHeadersBlockParserTest, MultipleBlocksAndHeadersWithPartialData) { | 156 TEST_P(SpdyHeadersBlockParserTest, MultipleBlocksAndHeadersWithPartialData) { |
| 155 testing::InSequence s; | 157 testing::InSequence s; |
| 156 | 158 |
| 159 // CreateHeaders is deterministic; we can call it once for the whole test. |
| 160 string headers(CreateHeaders(kNumHeadersInBlock, false)); |
| 161 |
| 157 // The mock doesn't retain storage of arguments, so keep them in scope. | 162 // The mock doesn't retain storage of arguments, so keep them in scope. |
| 158 std::vector<string> retained_arguments; | 163 std::vector<string> retained_arguments; |
| 159 for (int i = 0; i < kNumHeadersInBlock; i++) { | 164 for (int i = 0; i < kNumHeadersInBlock; i++) { |
| 160 retained_arguments.push_back(base_key + IntToString(i)); | 165 retained_arguments.push_back(base_key + IntToString(i)); |
| 161 retained_arguments.push_back(base_value + IntToString(i)); | 166 retained_arguments.push_back(base_value + IntToString(i)); |
| 162 } | 167 } |
| 163 // For each block we expect to parse out the headers in order. | 168 // For each block we expect to parse out the headers in order. |
| 164 for (int i = 0; i < kNumHeaderBlocks; i++) { | 169 for (int i = 0; i < kNumHeaderBlocks; i++) { |
| 165 EXPECT_CALL(handler_, OnHeaderBlock(i, kNumHeadersInBlock)).Times(1); | 170 EXPECT_CALL(handler_, OnHeaderBlock(i, kNumHeadersInBlock)).Times(1); |
| 166 for (int j = 0; j < kNumHeadersInBlock; j++) { | 171 for (int j = 0; j < kNumHeadersInBlock; j++) { |
| 167 EXPECT_CALL(handler_, OnHeader( | 172 EXPECT_CALL(handler_, OnHeader( |
| 168 i, | 173 i, |
| 169 StringPiece(retained_arguments[2 * j]), | 174 StringPiece(retained_arguments[2 * j]), |
| 170 StringPiece(retained_arguments[2 * j + 1]))).Times(1); | 175 StringPiece(retained_arguments[2 * j + 1]))).Times(1); |
| 171 } | 176 } |
| 172 EXPECT_CALL(handler_, OnHeaderBlockEnd(i)).Times(1); | 177 EXPECT_CALL(handler_, OnHeaderBlockEnd(i, headers.length())).Times(1); |
| 173 } | 178 } |
| 174 // Parse the header blocks, feeding the parser one byte at a time. | 179 // Parse the header blocks, feeding the parser one byte at a time. |
| 175 for (int i = 0; i < kNumHeaderBlocks; i++) { | 180 for (int i = 0; i < kNumHeaderBlocks; i++) { |
| 176 string headers(CreateHeaders(kNumHeadersInBlock, false)); | |
| 177 for (string::iterator it = headers.begin(); it != headers.end(); ++it) { | 181 for (string::iterator it = headers.begin(); it != headers.end(); ++it) { |
| 178 if ((it + 1) == headers.end()) { | 182 if ((it + 1) == headers.end()) { |
| 179 // Last byte completes the block. | 183 // Last byte completes the block. |
| 180 EXPECT_TRUE(parser_->HandleControlFrameHeadersData(i, &(*it), 1)); | 184 EXPECT_TRUE(parser_->HandleControlFrameHeadersData(i, &(*it), 1)); |
| 181 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); | 185 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); |
| 182 } else { | 186 } else { |
| 183 EXPECT_FALSE(parser_->HandleControlFrameHeadersData(i, &(*it), 1)); | 187 EXPECT_FALSE(parser_->HandleControlFrameHeadersData(i, &(*it), 1)); |
| 184 EXPECT_EQ(SpdyHeadersBlockParser::NEED_MORE_DATA, parser_->get_error()); | 188 EXPECT_EQ(SpdyHeadersBlockParser::NEED_MORE_DATA, parser_->get_error()); |
| 185 } | 189 } |
| 186 } | 190 } |
| 187 } | 191 } |
| 188 } | 192 } |
| 189 | 193 |
| 190 TEST_P(SpdyHeadersBlockParserTest, HandlesEmptyCallsTest) { | 194 TEST_P(SpdyHeadersBlockParserTest, HandlesEmptyCallsTest) { |
| 191 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); | 195 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); |
| 192 | 196 |
| 197 string headers(CreateHeaders(1, false)); |
| 198 |
| 193 string expect_key = base_key + IntToString(0); | 199 string expect_key = base_key + IntToString(0); |
| 194 string expect_value = base_value + IntToString(0); | 200 string expect_value = base_value + IntToString(0); |
| 195 EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key), | 201 EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key), |
| 196 StringPiece(expect_value))).Times(1); | 202 StringPiece(expect_value))).Times(1); |
| 197 EXPECT_CALL(handler_, OnHeaderBlockEnd(1)).Times(1); | 203 EXPECT_CALL(handler_, OnHeaderBlockEnd(1, headers.length())).Times(1); |
| 198 | 204 |
| 199 // Send a header in pieces with intermediate empty calls. | 205 // Send a header in pieces with intermediate empty calls. |
| 200 string headers(CreateHeaders(1, false)); | |
| 201 for (string::iterator it = headers.begin(); it != headers.end(); ++it) { | 206 for (string::iterator it = headers.begin(); it != headers.end(); ++it) { |
| 202 if ((it + 1) == headers.end()) { | 207 if ((it + 1) == headers.end()) { |
| 203 // Last byte completes the block. | 208 // Last byte completes the block. |
| 204 EXPECT_TRUE(parser_->HandleControlFrameHeadersData(1, &(*it), 1)); | 209 EXPECT_TRUE(parser_->HandleControlFrameHeadersData(1, &(*it), 1)); |
| 205 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); | 210 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); |
| 206 } else { | 211 } else { |
| 207 EXPECT_FALSE(parser_->HandleControlFrameHeadersData(1, &(*it), 1)); | 212 EXPECT_FALSE(parser_->HandleControlFrameHeadersData(1, &(*it), 1)); |
| 208 EXPECT_EQ(SpdyHeadersBlockParser::NEED_MORE_DATA, parser_->get_error()); | 213 EXPECT_EQ(SpdyHeadersBlockParser::NEED_MORE_DATA, parser_->get_error()); |
| 209 EXPECT_FALSE(parser_->HandleControlFrameHeadersData(1, NULL, 0)); | 214 EXPECT_FALSE(parser_->HandleControlFrameHeadersData(1, NULL, 0)); |
| 210 } | 215 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 229 string headers = EncodeLength(1) + EncodeLength( | 234 string headers = EncodeLength(1) + EncodeLength( |
| 230 SpdyHeadersBlockParser::kMaximumFieldLength + 1); | 235 SpdyHeadersBlockParser::kMaximumFieldLength + 1); |
| 231 EXPECT_FALSE(parser_-> | 236 EXPECT_FALSE(parser_-> |
| 232 HandleControlFrameHeadersData(1, headers.c_str(), headers.length())); | 237 HandleControlFrameHeadersData(1, headers.c_str(), headers.length())); |
| 233 EXPECT_EQ(SpdyHeadersBlockParser::HEADER_FIELD_TOO_LARGE, | 238 EXPECT_EQ(SpdyHeadersBlockParser::HEADER_FIELD_TOO_LARGE, |
| 234 parser_->get_error()); | 239 parser_->get_error()); |
| 235 } | 240 } |
| 236 } | 241 } |
| 237 | 242 |
| 238 TEST_P(SpdyHeadersBlockParserTest, ExtraDataTest) { | 243 TEST_P(SpdyHeadersBlockParserTest, ExtraDataTest) { |
| 244 string headers = CreateHeaders(1, false) + "foobar"; |
| 245 |
| 239 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); | 246 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); |
| 240 EXPECT_CALL(handler_, OnHeaderBlockEnd(1)).Times(1); | 247 EXPECT_CALL(handler_, OnHeaderBlockEnd(1, headers.length())).Times(1); |
| 241 | 248 |
| 242 string expect_key = base_key + IntToString(0); | 249 string expect_key = base_key + IntToString(0); |
| 243 string expect_value = base_value + IntToString(0); | 250 string expect_value = base_value + IntToString(0); |
| 244 EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key), | 251 EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key), |
| 245 StringPiece(expect_value))).Times(1); | 252 StringPiece(expect_value))).Times(1); |
| 246 | 253 |
| 247 string headers = CreateHeaders(1, false) + "foobar"; | |
| 248 EXPECT_FALSE(parser_-> | 254 EXPECT_FALSE(parser_-> |
| 249 HandleControlFrameHeadersData(1, headers.c_str(), headers.length())); | 255 HandleControlFrameHeadersData(1, headers.c_str(), headers.length())); |
| 250 EXPECT_EQ(SpdyHeadersBlockParser::TOO_MUCH_DATA, parser_->get_error()); | 256 EXPECT_EQ(SpdyHeadersBlockParser::TOO_MUCH_DATA, parser_->get_error()); |
| 251 } | 257 } |
| 252 | 258 |
| 253 } // namespace net | 259 } // namespace net |
| OLD | NEW |