| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 #include "net/quic/spdy_utils.h" | |
| 5 | |
| 6 #include "base/macros.h" | |
| 7 #include "base/strings/string_number_conversions.h" | |
| 8 #include "base/strings/string_piece.h" | |
| 9 #include "net/test/gtest_util.h" | |
| 10 | |
| 11 using base::StringPiece; | |
| 12 using std::string; | |
| 13 using testing::UnorderedElementsAre; | |
| 14 using testing::Pair; | |
| 15 | |
| 16 namespace net { | |
| 17 namespace test { | |
| 18 | |
| 19 TEST(SpdyUtilsTest, SerializeAndParseHeaders) { | |
| 20 // Creates a SpdyHeaderBlock with some key->value pairs, serializes it, then | |
| 21 // parses the serialized output and verifies that the end result is the same | |
| 22 // as the headers that the test started with. | |
| 23 | |
| 24 SpdyHeaderBlock input_headers; | |
| 25 input_headers[":pseudo1"] = "pseudo value1"; | |
| 26 input_headers[":pseudo2"] = "pseudo value2"; | |
| 27 input_headers["key1"] = "value1"; | |
| 28 const int64_t kContentLength = 1234; | |
| 29 input_headers["content-length"] = base::Int64ToString(kContentLength); | |
| 30 input_headers["key2"] = "value2"; | |
| 31 | |
| 32 // Serialize the header block. | |
| 33 string serialized_headers = | |
| 34 SpdyUtils::SerializeUncompressedHeaders(input_headers); | |
| 35 | |
| 36 // Take the serialized header block, and parse back into SpdyHeaderBlock. | |
| 37 SpdyHeaderBlock output_headers; | |
| 38 int64_t content_length = -1; | |
| 39 ASSERT_TRUE(SpdyUtils::ParseHeaders(serialized_headers.data(), | |
| 40 serialized_headers.size(), | |
| 41 &content_length, &output_headers)); | |
| 42 | |
| 43 // Should be back to the original headers. | |
| 44 EXPECT_EQ(content_length, kContentLength); | |
| 45 EXPECT_EQ(output_headers, input_headers); | |
| 46 } | |
| 47 | |
| 48 TEST(SpdyUtilsTest, SerializeAndParseHeadersLargeContentLength) { | |
| 49 // Creates a SpdyHeaderBlock with some key->value pairs, serializes it, then | |
| 50 // parses the serialized output and verifies that the end result is the same | |
| 51 // as the headers that the test started with. | |
| 52 | |
| 53 SpdyHeaderBlock input_headers; | |
| 54 input_headers[":pseudo1"] = "pseudo value1"; | |
| 55 input_headers[":pseudo2"] = "pseudo value2"; | |
| 56 input_headers["key1"] = "value1"; | |
| 57 const int64_t kContentLength = 12345678900; | |
| 58 input_headers["content-length"] = base::Int64ToString(kContentLength); | |
| 59 input_headers["key2"] = "value2"; | |
| 60 | |
| 61 // Serialize the header block. | |
| 62 string serialized_headers = | |
| 63 SpdyUtils::SerializeUncompressedHeaders(input_headers); | |
| 64 | |
| 65 // Take the serialized header block, and parse back into SpdyHeaderBlock. | |
| 66 SpdyHeaderBlock output_headers; | |
| 67 int64_t content_length = -1; | |
| 68 ASSERT_TRUE(SpdyUtils::ParseHeaders(serialized_headers.data(), | |
| 69 serialized_headers.size(), | |
| 70 &content_length, &output_headers)); | |
| 71 | |
| 72 // Should be back to the original headers. | |
| 73 EXPECT_EQ(content_length, kContentLength); | |
| 74 EXPECT_EQ(output_headers, input_headers); | |
| 75 } | |
| 76 | |
| 77 TEST(SpdyUtilsTest, SerializeAndParseValidTrailers) { | |
| 78 // Creates a SpdyHeaderBlock with some valid Trailers key->value pairs, | |
| 79 // serializes it, then parses the serialized output and verifies that the end | |
| 80 // result is the same as the trailers that the test started with. | |
| 81 SpdyHeaderBlock input_trailers; | |
| 82 const size_t kFinalOffset = 5678; | |
| 83 input_trailers[kFinalOffsetHeaderKey] = base::IntToString(kFinalOffset); | |
| 84 input_trailers["key1"] = "value1"; | |
| 85 input_trailers["key2"] = "value2"; | |
| 86 | |
| 87 // Serialize the trailers. | |
| 88 string serialized_trailers = | |
| 89 SpdyUtils::SerializeUncompressedHeaders(input_trailers); | |
| 90 | |
| 91 // Take the serialized trailers, and parse back into a SpdyHeaderBlock. | |
| 92 SpdyHeaderBlock output_trailers; | |
| 93 size_t final_byte_offset = 0; | |
| 94 EXPECT_TRUE(SpdyUtils::ParseTrailers(serialized_trailers.data(), | |
| 95 serialized_trailers.size(), | |
| 96 &final_byte_offset, &output_trailers)); | |
| 97 | |
| 98 // Should be back to the original trailers, without the final offset header. | |
| 99 EXPECT_EQ(final_byte_offset, kFinalOffset); | |
| 100 input_trailers.erase(kFinalOffsetHeaderKey); | |
| 101 EXPECT_EQ(output_trailers, input_trailers); | |
| 102 } | |
| 103 | |
| 104 TEST(SpdyUtilsTest, SerializeAndParseTrailersWithoutFinalOffset) { | |
| 105 // Verifies that parsing fails if Trailers are missing a final offset header. | |
| 106 | |
| 107 SpdyHeaderBlock input_trailers; | |
| 108 input_trailers["key1"] = "value1"; | |
| 109 input_trailers["key2"] = "value2"; | |
| 110 | |
| 111 // Serialize the trailers. | |
| 112 string serialized_trailers = | |
| 113 SpdyUtils::SerializeUncompressedHeaders(input_trailers); | |
| 114 | |
| 115 // Parsing the serialized trailers fails because of the missing final offset. | |
| 116 SpdyHeaderBlock output_trailers; | |
| 117 size_t final_byte_offset = 0; | |
| 118 EXPECT_FALSE(SpdyUtils::ParseTrailers(serialized_trailers.data(), | |
| 119 serialized_trailers.size(), | |
| 120 &final_byte_offset, &output_trailers)); | |
| 121 EXPECT_EQ(final_byte_offset, 0u); | |
| 122 } | |
| 123 | |
| 124 TEST(SpdyUtilsTest, SerializeAndParseTrailersWithPseudoHeaders) { | |
| 125 // Verifies that parsing fails if Trailers include pseudo-headers. | |
| 126 | |
| 127 SpdyHeaderBlock input_trailers; | |
| 128 input_trailers[kFinalOffsetHeaderKey] = "12345"; | |
| 129 input_trailers[":disallowed-pseudo-header"] = "pseudo value"; | |
| 130 input_trailers["key1"] = "value1"; | |
| 131 input_trailers["key2"] = "value2"; | |
| 132 | |
| 133 // Serialize the trailers. | |
| 134 string serialized_trailers = | |
| 135 SpdyUtils::SerializeUncompressedHeaders(input_trailers); | |
| 136 | |
| 137 // Parsing the serialized trailers fails because of the extra pseudo header. | |
| 138 SpdyHeaderBlock output_trailers; | |
| 139 size_t final_byte_offset = 0; | |
| 140 EXPECT_FALSE(SpdyUtils::ParseTrailers(serialized_trailers.data(), | |
| 141 serialized_trailers.size(), | |
| 142 &final_byte_offset, &output_trailers)); | |
| 143 } | |
| 144 static std::unique_ptr<QuicHeaderList> FromList( | |
| 145 const QuicHeaderList::ListType& src) { | |
| 146 std::unique_ptr<QuicHeaderList> headers(new QuicHeaderList); | |
| 147 headers->OnHeaderBlockStart(); | |
| 148 for (const auto& p : src) { | |
| 149 headers->OnHeader(p.first, p.second); | |
| 150 } | |
| 151 headers->OnHeaderBlockEnd(0); | |
| 152 return headers; | |
| 153 } | |
| 154 | |
| 155 TEST(SpdyUtilsTest, CopyAndValidateHeaders) { | |
| 156 auto headers = FromList({// All cookie crumbs are joined. | |
| 157 {"cookie", " part 1"}, | |
| 158 {"cookie", "part 2 "}, | |
| 159 {"cookie", "part3"}, | |
| 160 | |
| 161 // Already-delimited headers are passed through. | |
| 162 {"passed-through", string("foo\0baz", 7)}, | |
| 163 | |
| 164 // Other headers are joined on \0. | |
| 165 {"joined", "value 1"}, | |
| 166 {"joined", "value 2"}, | |
| 167 | |
| 168 // Empty headers remain empty. | |
| 169 {"empty", ""}, | |
| 170 | |
| 171 // Joined empty headers work as expected. | |
| 172 {"empty-joined", ""}, | |
| 173 {"empty-joined", "foo"}, | |
| 174 {"empty-joined", ""}, | |
| 175 {"empty-joined", ""}, | |
| 176 | |
| 177 // Non-continguous cookie crumb. | |
| 178 {"cookie", " fin!"}}); | |
| 179 | |
| 180 int64_t content_length = -1; | |
| 181 SpdyHeaderBlock block; | |
| 182 ASSERT_TRUE( | |
| 183 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block)); | |
| 184 EXPECT_THAT(block, UnorderedElementsAre( | |
| 185 Pair("cookie", " part 1; part 2 ; part3; fin!"), | |
| 186 Pair("passed-through", StringPiece("foo\0baz", 7)), | |
| 187 Pair("joined", StringPiece("value 1\0value 2", 15)), | |
| 188 Pair("empty", ""), | |
| 189 Pair("empty-joined", StringPiece("\0foo\0\0", 6)))); | |
| 190 EXPECT_EQ(-1, content_length); | |
| 191 } | |
| 192 | |
| 193 TEST(SpdyUtilsTest, CopyAndValidateHeadersEmptyName) { | |
| 194 auto headers = FromList({{"foo", "foovalue"}, {"", "barvalue"}, {"baz", ""}}); | |
| 195 int64_t content_length = -1; | |
| 196 SpdyHeaderBlock block; | |
| 197 ASSERT_FALSE( | |
| 198 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block)); | |
| 199 } | |
| 200 | |
| 201 TEST(SpdyUtilsTest, CopyAndValidateHeadersMultipleContentLengths) { | |
| 202 auto headers = FromList({{"content-length", "9"}, | |
| 203 {"foo", "foovalue"}, | |
| 204 {"content-length", "9"}, | |
| 205 {"bar", "barvalue"}, | |
| 206 {"baz", ""}}); | |
| 207 int64_t content_length = -1; | |
| 208 SpdyHeaderBlock block; | |
| 209 ASSERT_TRUE( | |
| 210 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block)); | |
| 211 EXPECT_THAT(block, UnorderedElementsAre( | |
| 212 Pair("foo", "foovalue"), Pair("bar", "barvalue"), | |
| 213 Pair("content-length", StringPiece("9" | |
| 214 "\0" | |
| 215 "9", | |
| 216 3)), | |
| 217 Pair("baz", ""))); | |
| 218 EXPECT_EQ(9, content_length); | |
| 219 } | |
| 220 | |
| 221 TEST(SpdyUtilsTest, CopyAndValidateHeadersInconsistentContentLengths) { | |
| 222 auto headers = FromList({{"content-length", "9"}, | |
| 223 {"foo", "foovalue"}, | |
| 224 {"content-length", "8"}, | |
| 225 {"bar", "barvalue"}, | |
| 226 {"baz", ""}}); | |
| 227 int64_t content_length = -1; | |
| 228 SpdyHeaderBlock block; | |
| 229 ASSERT_FALSE( | |
| 230 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block)); | |
| 231 } | |
| 232 | |
| 233 TEST(SpdyUtilsTest, CopyAndValidateHeadersLargeContentLength) { | |
| 234 auto headers = FromList({{"content-length", "9000000000"}, | |
| 235 {"foo", "foovalue"}, | |
| 236 {"bar", "barvalue"}, | |
| 237 {"baz", ""}}); | |
| 238 int64_t content_length = -1; | |
| 239 SpdyHeaderBlock block; | |
| 240 ASSERT_TRUE( | |
| 241 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block)); | |
| 242 EXPECT_THAT(block, UnorderedElementsAre( | |
| 243 Pair("foo", "foovalue"), Pair("bar", "barvalue"), | |
| 244 Pair("content-length", StringPiece("9000000000")), | |
| 245 Pair("baz", ""))); | |
| 246 EXPECT_EQ(9000000000, content_length); | |
| 247 } | |
| 248 | |
| 249 TEST(SpdyUtilsTest, CopyAndValidateHeadersMultipleValues) { | |
| 250 auto headers = FromList({{"foo", "foovalue"}, | |
| 251 {"bar", "barvalue"}, | |
| 252 {"baz", ""}, | |
| 253 {"foo", "boo"}, | |
| 254 {"baz", "buzz"}}); | |
| 255 int64_t content_length = -1; | |
| 256 SpdyHeaderBlock block; | |
| 257 ASSERT_TRUE( | |
| 258 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block)); | |
| 259 EXPECT_THAT( | |
| 260 block, UnorderedElementsAre(Pair("foo", StringPiece("foovalue\0boo", 12)), | |
| 261 Pair("bar", "barvalue"), | |
| 262 Pair("baz", StringPiece("\0buzz", 5)))); | |
| 263 EXPECT_EQ(-1, content_length); | |
| 264 } | |
| 265 | |
| 266 TEST(SpdyUtilsTest, CopyAndValidateHeadersMoreThanTwoValues) { | |
| 267 auto headers = FromList({{"set-cookie", "value1"}, | |
| 268 {"set-cookie", "value2"}, | |
| 269 {"set-cookie", "value3"}}); | |
| 270 int64_t content_length = -1; | |
| 271 SpdyHeaderBlock block; | |
| 272 ASSERT_TRUE( | |
| 273 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block)); | |
| 274 EXPECT_THAT(block, | |
| 275 UnorderedElementsAre(Pair( | |
| 276 "set-cookie", StringPiece("value1\0value2\0value3", 20)))); | |
| 277 EXPECT_EQ(-1, content_length); | |
| 278 } | |
| 279 | |
| 280 TEST(SpdyUtilsTest, CopyAndValidateHeadersCookie) { | |
| 281 auto headers = FromList({{"foo", "foovalue"}, | |
| 282 {"bar", "barvalue"}, | |
| 283 {"cookie", "value1"}, | |
| 284 {"baz", ""}}); | |
| 285 int64_t content_length = -1; | |
| 286 SpdyHeaderBlock block; | |
| 287 ASSERT_TRUE( | |
| 288 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block)); | |
| 289 EXPECT_THAT(block, UnorderedElementsAre( | |
| 290 Pair("foo", "foovalue"), Pair("bar", "barvalue"), | |
| 291 Pair("cookie", "value1"), Pair("baz", ""))); | |
| 292 EXPECT_EQ(-1, content_length); | |
| 293 } | |
| 294 | |
| 295 TEST(SpdyUtilsTest, CopyAndValidateHeadersMultipleCookies) { | |
| 296 auto headers = FromList({{"foo", "foovalue"}, | |
| 297 {"bar", "barvalue"}, | |
| 298 {"cookie", "value1"}, | |
| 299 {"baz", ""}, | |
| 300 {"cookie", "value2"}}); | |
| 301 int64_t content_length = -1; | |
| 302 SpdyHeaderBlock block; | |
| 303 ASSERT_TRUE( | |
| 304 SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block)); | |
| 305 EXPECT_THAT(block, UnorderedElementsAre( | |
| 306 Pair("foo", "foovalue"), Pair("bar", "barvalue"), | |
| 307 Pair("cookie", "value1; value2"), Pair("baz", ""))); | |
| 308 EXPECT_EQ(-1, content_length); | |
| 309 } | |
| 310 | |
| 311 TEST(SpdyUtilsTest, GetUrlFromHeaderBlock) { | |
| 312 SpdyHeaderBlock headers; | |
| 313 EXPECT_EQ(SpdyUtils::GetUrlFromHeaderBlock(headers), ""); | |
| 314 headers[":scheme"] = "https"; | |
| 315 EXPECT_EQ(SpdyUtils::GetUrlFromHeaderBlock(headers), ""); | |
| 316 headers[":authority"] = "www.google.com"; | |
| 317 EXPECT_EQ(SpdyUtils::GetUrlFromHeaderBlock(headers), ""); | |
| 318 headers[":path"] = "/index.html"; | |
| 319 EXPECT_EQ(SpdyUtils::GetUrlFromHeaderBlock(headers), | |
| 320 "https://www.google.com/index.html"); | |
| 321 headers["key1"] = "value1"; | |
| 322 headers["key2"] = "value2"; | |
| 323 EXPECT_EQ(SpdyUtils::GetUrlFromHeaderBlock(headers), | |
| 324 "https://www.google.com/index.html"); | |
| 325 } | |
| 326 | |
| 327 TEST(SpdyUtilsTest, GetHostNameFromHeaderBlock) { | |
| 328 SpdyHeaderBlock headers; | |
| 329 EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), ""); | |
| 330 headers[":scheme"] = "https"; | |
| 331 EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), ""); | |
| 332 headers[":authority"] = "www.google.com"; | |
| 333 EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), ""); | |
| 334 headers[":path"] = "/index.html"; | |
| 335 EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), "www.google.com"); | |
| 336 headers["key1"] = "value1"; | |
| 337 headers["key2"] = "value2"; | |
| 338 EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), "www.google.com"); | |
| 339 headers[":authority"] = "www.google.com:6666"; | |
| 340 EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), "www.google.com"); | |
| 341 headers[":authority"] = "192.168.1.1"; | |
| 342 EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), "192.168.1.1"); | |
| 343 headers[":authority"] = "192.168.1.1:6666"; | |
| 344 EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), "192.168.1.1"); | |
| 345 } | |
| 346 | |
| 347 TEST(SpdyUtilsTest, UrlIsValid) { | |
| 348 SpdyHeaderBlock headers; | |
| 349 EXPECT_FALSE(SpdyUtils::UrlIsValid(headers)); | |
| 350 headers[":scheme"] = "https"; | |
| 351 EXPECT_FALSE(SpdyUtils::UrlIsValid(headers)); | |
| 352 headers[":authority"] = "www.google.com"; | |
| 353 EXPECT_FALSE(SpdyUtils::UrlIsValid(headers)); | |
| 354 headers[":path"] = "/index.html"; | |
| 355 EXPECT_TRUE(SpdyUtils::UrlIsValid(headers)); | |
| 356 } | |
| 357 | |
| 358 } // namespace test | |
| 359 } // namespace net | |
| OLD | NEW |