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 |