| 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" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 string headers; | 51 string headers; |
| 52 | 52 |
| 53 // First, write the number of headers in the header block. | 53 // First, write the number of headers in the header block. |
| 54 headers += EncodeLength(num_headers); | 54 headers += EncodeLength(num_headers); |
| 55 | 55 |
| 56 // Second, write the key-value pairs. | 56 // Second, write the key-value pairs. |
| 57 for (uint32_t i = 0; i < num_headers; i++) { | 57 for (uint32_t i = 0; i < num_headers; i++) { |
| 58 // Build the key. | 58 // Build the key. |
| 59 string key; | 59 string key; |
| 60 if (insert_nulls) { | 60 if (insert_nulls) { |
| 61 key = string(base_key) + string("\0", 1) + IntToString(i); | 61 key = string(kBaseKey) + string("\0", 1) + IntToString(i); |
| 62 } else { | 62 } else { |
| 63 key = string(base_key) + IntToString(i); | 63 key = string(kBaseKey) + IntToString(i); |
| 64 } | 64 } |
| 65 // Encode the key as SPDY header. | 65 // Encode the key as SPDY header. |
| 66 headers += EncodeLength(key.length()); | 66 headers += EncodeLength(key.length()); |
| 67 headers += key; | 67 headers += key; |
| 68 | 68 |
| 69 // Build the value. | 69 // Build the value. |
| 70 string value; | 70 string value; |
| 71 if (insert_nulls) { | 71 if (insert_nulls) { |
| 72 value = string(base_value) + string("\0", 1) + IntToString(i); | 72 value = string(kBaseValue) + string("\0", 1) + IntToString(i); |
| 73 } else { | 73 } else { |
| 74 value = string(base_value) + IntToString(i); | 74 value = string(kBaseValue) + IntToString(i); |
| 75 } | 75 } |
| 76 // Encode the value as SPDY header. | 76 // Encode the value as SPDY header. |
| 77 headers += EncodeLength(value.length()); | 77 headers += EncodeLength(value.length()); |
| 78 headers += value; | 78 headers += value; |
| 79 } | 79 } |
| 80 return headers; | 80 return headers; |
| 81 } | 81 } |
| 82 | 82 |
| 83 string EncodeLength(uint32_t len) { | 83 string EncodeLength(uint32_t len) { |
| 84 char buffer[4]; | 84 char buffer[4]; |
| 85 if (length_field_size_ == sizeof(uint32_t)) { | 85 if (length_field_size_ == sizeof(uint32_t)) { |
| 86 uint32_t net_order_len = htonl(len); | 86 uint32_t net_order_len = htonl(len); |
| 87 memcpy(buffer, &net_order_len, length_field_size_); | 87 memcpy(buffer, &net_order_len, length_field_size_); |
| 88 } else if (length_field_size_ == sizeof(uint16_t)) { | 88 } else if (length_field_size_ == sizeof(uint16_t)) { |
| 89 uint16_t net_order_len = htons(len); | 89 uint16_t net_order_len = htons(len); |
| 90 memcpy(buffer, &net_order_len, length_field_size_); | 90 memcpy(buffer, &net_order_len, length_field_size_); |
| 91 } else { | 91 } else { |
| 92 CHECK(false) << "Invalid length field size"; | 92 CHECK(false) << "Invalid length field size"; |
| 93 } | 93 } |
| 94 return string(buffer, length_field_size_); | 94 return string(buffer, length_field_size_); |
| 95 } | 95 } |
| 96 | 96 |
| 97 size_t length_field_size_; | 97 size_t length_field_size_; |
| 98 SpdyMajorVersion spdy_version_; | 98 SpdyMajorVersion spdy_version_; |
| 99 | 99 |
| 100 MockSpdyHeadersHandler handler_; | 100 MockSpdyHeadersHandler handler_; |
| 101 scoped_ptr<SpdyHeadersBlockParser> parser_; | 101 scoped_ptr<SpdyHeadersBlockParser> parser_; |
| 102 | 102 |
| 103 static const char* base_key; | 103 static const char *const kBaseKey; |
| 104 static const char* base_value; | 104 static const char *const kBaseValue; |
| 105 | 105 |
| 106 // Number of headers and header blocks used in the tests. | 106 // Number of headers and header blocks used in the tests. |
| 107 static const int kNumHeadersInBlock = 10; | 107 static const int kNumHeadersInBlock = 10; |
| 108 static const int kNumHeaderBlocks = 10; | 108 static const int kNumHeaderBlocks = 10; |
| 109 }; | 109 }; |
| 110 | 110 |
| 111 const char* SpdyHeadersBlockParserTest::base_key = "test_key"; | 111 const char *const SpdyHeadersBlockParserTest::kBaseKey = "test_key"; |
| 112 const char* SpdyHeadersBlockParserTest::base_value = "test_value"; | 112 const char *const SpdyHeadersBlockParserTest::kBaseValue = "test_value"; |
| 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)); | 123 string headers(CreateHeaders(1, false)); |
| 124 | 124 |
| 125 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); | 125 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); |
| 126 | 126 |
| 127 std::string expect_key = base_key + IntToString(0); | 127 std::string expect_key = kBaseKey + IntToString(0); |
| 128 std::string expect_value = base_value + IntToString(0); | 128 std::string expect_value = kBaseValue + IntToString(0); |
| 129 EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key), | 129 EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key), |
| 130 StringPiece(expect_value))).Times(1); | 130 StringPiece(expect_value))).Times(1); |
| 131 EXPECT_CALL(handler_, OnHeaderBlockEnd(1, headers.length())).Times(1); | 131 EXPECT_CALL(handler_, OnHeaderBlockEnd(1, headers.length())).Times(1); |
| 132 | 132 |
| 133 EXPECT_TRUE(parser_-> | 133 EXPECT_TRUE(parser_-> |
| 134 HandleControlFrameHeadersData(1, headers.c_str(), headers.length())); | 134 HandleControlFrameHeadersData(1, headers.c_str(), headers.length())); |
| 135 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); | 135 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); |
| 136 } | 136 } |
| 137 | 137 |
| 138 TEST_P(SpdyHeadersBlockParserTest, NullsSupportedTest) { | 138 TEST_P(SpdyHeadersBlockParserTest, NullsSupportedTest) { |
| 139 // Sanity test, verify that we parse out correctly a block with | 139 // Sanity test, verify that we parse out correctly a block with |
| 140 // 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)); | 141 string headers(CreateHeaders(1, true)); |
| 142 | 142 |
| 143 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); | 143 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); |
| 144 | 144 |
| 145 std::string expect_key = base_key + string("\0", 1) + IntToString(0); | 145 std::string expect_key = kBaseKey + string("\0", 1) + IntToString(0); |
| 146 std::string expect_value = base_value + string("\0", 1) + IntToString(0); | 146 std::string expect_value = kBaseValue + string("\0", 1) + IntToString(0); |
| 147 EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key), | 147 EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key), |
| 148 StringPiece(expect_value))).Times(1); | 148 StringPiece(expect_value))).Times(1); |
| 149 EXPECT_CALL(handler_, OnHeaderBlockEnd(1, headers.length())).Times(1); | 149 EXPECT_CALL(handler_, OnHeaderBlockEnd(1, headers.length())).Times(1); |
| 150 | 150 |
| 151 EXPECT_TRUE(parser_-> | 151 EXPECT_TRUE(parser_-> |
| 152 HandleControlFrameHeadersData(1, headers.c_str(), headers.length())); | 152 HandleControlFrameHeadersData(1, headers.c_str(), headers.length())); |
| 153 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); | 153 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); |
| 154 } | 154 } |
| 155 | 155 |
| 156 TEST_P(SpdyHeadersBlockParserTest, MultipleBlocksAndHeadersWithPartialData) { | 156 TEST_P(SpdyHeadersBlockParserTest, MultipleBlocksAndHeadersWithPartialData) { |
| 157 testing::InSequence s; | 157 testing::InSequence s; |
| 158 | 158 |
| 159 // CreateHeaders is deterministic; we can call it once for the whole test. | 159 // CreateHeaders is deterministic; we can call it once for the whole test. |
| 160 string headers(CreateHeaders(kNumHeadersInBlock, false)); | 160 string headers(CreateHeaders(kNumHeadersInBlock, false)); |
| 161 | 161 |
| 162 // 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. |
| 163 std::vector<string> retained_arguments; | 163 std::vector<string> retained_arguments; |
| 164 for (int i = 0; i < kNumHeadersInBlock; i++) { | 164 for (int i = 0; i < kNumHeadersInBlock; i++) { |
| 165 retained_arguments.push_back(base_key + IntToString(i)); | 165 retained_arguments.push_back(kBaseKey + IntToString(i)); |
| 166 retained_arguments.push_back(base_value + IntToString(i)); | 166 retained_arguments.push_back(kBaseValue + IntToString(i)); |
| 167 } | 167 } |
| 168 // 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. |
| 169 for (int i = 0; i < kNumHeaderBlocks; i++) { | 169 for (int i = 0; i < kNumHeaderBlocks; i++) { |
| 170 EXPECT_CALL(handler_, OnHeaderBlock(i, kNumHeadersInBlock)).Times(1); | 170 EXPECT_CALL(handler_, OnHeaderBlock(i, kNumHeadersInBlock)).Times(1); |
| 171 for (int j = 0; j < kNumHeadersInBlock; j++) { | 171 for (int j = 0; j < kNumHeadersInBlock; j++) { |
| 172 EXPECT_CALL(handler_, OnHeader( | 172 EXPECT_CALL(handler_, OnHeader( |
| 173 i, | 173 i, |
| 174 StringPiece(retained_arguments[2 * j]), | 174 StringPiece(retained_arguments[2 * j]), |
| 175 StringPiece(retained_arguments[2 * j + 1]))).Times(1); | 175 StringPiece(retained_arguments[2 * j + 1]))).Times(1); |
| 176 } | 176 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 189 } | 189 } |
| 190 } | 190 } |
| 191 } | 191 } |
| 192 } | 192 } |
| 193 | 193 |
| 194 TEST_P(SpdyHeadersBlockParserTest, HandlesEmptyCallsTest) { | 194 TEST_P(SpdyHeadersBlockParserTest, HandlesEmptyCallsTest) { |
| 195 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); | 195 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); |
| 196 | 196 |
| 197 string headers(CreateHeaders(1, false)); | 197 string headers(CreateHeaders(1, false)); |
| 198 | 198 |
| 199 string expect_key = base_key + IntToString(0); | 199 string expect_key = kBaseKey + IntToString(0); |
| 200 string expect_value = base_value + IntToString(0); | 200 string expect_value = kBaseValue + IntToString(0); |
| 201 EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key), | 201 EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key), |
| 202 StringPiece(expect_value))).Times(1); | 202 StringPiece(expect_value))).Times(1); |
| 203 EXPECT_CALL(handler_, OnHeaderBlockEnd(1, headers.length())).Times(1); | 203 EXPECT_CALL(handler_, OnHeaderBlockEnd(1, headers.length())).Times(1); |
| 204 | 204 |
| 205 // Send a header in pieces with intermediate empty calls. | 205 // Send a header in pieces with intermediate empty calls. |
| 206 for (string::iterator it = headers.begin(); it != headers.end(); ++it) { | 206 for (string::iterator it = headers.begin(); it != headers.end(); ++it) { |
| 207 if ((it + 1) == headers.end()) { | 207 if ((it + 1) == headers.end()) { |
| 208 // Last byte completes the block. | 208 // Last byte completes the block. |
| 209 EXPECT_TRUE(parser_->HandleControlFrameHeadersData(1, &(*it), 1)); | 209 EXPECT_TRUE(parser_->HandleControlFrameHeadersData(1, &(*it), 1)); |
| 210 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); | 210 EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 239 parser_->get_error()); | 239 parser_->get_error()); |
| 240 } | 240 } |
| 241 } | 241 } |
| 242 | 242 |
| 243 TEST_P(SpdyHeadersBlockParserTest, ExtraDataTest) { | 243 TEST_P(SpdyHeadersBlockParserTest, ExtraDataTest) { |
| 244 string headers = CreateHeaders(1, false) + "foobar"; | 244 string headers = CreateHeaders(1, false) + "foobar"; |
| 245 | 245 |
| 246 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); | 246 EXPECT_CALL(handler_, OnHeaderBlock(1, 1)).Times(1); |
| 247 EXPECT_CALL(handler_, OnHeaderBlockEnd(1, headers.length())).Times(1); | 247 EXPECT_CALL(handler_, OnHeaderBlockEnd(1, headers.length())).Times(1); |
| 248 | 248 |
| 249 string expect_key = base_key + IntToString(0); | 249 string expect_key = kBaseKey + IntToString(0); |
| 250 string expect_value = base_value + IntToString(0); | 250 string expect_value = kBaseValue + IntToString(0); |
| 251 EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key), | 251 EXPECT_CALL(handler_, OnHeader(1, StringPiece(expect_key), |
| 252 StringPiece(expect_value))).Times(1); | 252 StringPiece(expect_value))).Times(1); |
| 253 | 253 |
| 254 EXPECT_FALSE(parser_-> | 254 EXPECT_FALSE(parser_-> |
| 255 HandleControlFrameHeadersData(1, headers.c_str(), headers.length())); | 255 HandleControlFrameHeadersData(1, headers.c_str(), headers.length())); |
| 256 EXPECT_EQ(SpdyHeadersBlockParser::TOO_MUCH_DATA, parser_->get_error()); | 256 EXPECT_EQ(SpdyHeadersBlockParser::TOO_MUCH_DATA, parser_->get_error()); |
| 257 } | 257 } |
| 258 | 258 |
| 259 } // namespace net | 259 } // namespace net |
| OLD | NEW |