| 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 | |
| 5 #include "net/spdy/header_coalescer.h" | |
| 6 | |
| 7 #include <vector> | |
| 8 | |
| 9 #include "net/spdy/platform/api/spdy_string.h" | |
| 10 #include "net/spdy/platform/api/spdy_string_utils.h" | |
| 11 #include "testing/gmock/include/gmock/gmock.h" | |
| 12 #include "testing/gtest/include/gtest/gtest.h" | |
| 13 | |
| 14 using ::testing::ElementsAre; | |
| 15 using ::testing::Pair; | |
| 16 | |
| 17 namespace net { | |
| 18 namespace test { | |
| 19 | |
| 20 class HeaderCoalescerTest : public ::testing::Test { | |
| 21 public: | |
| 22 protected: | |
| 23 HeaderCoalescer header_coalescer_; | |
| 24 }; | |
| 25 | |
| 26 TEST_F(HeaderCoalescerTest, CorrectHeaders) { | |
| 27 header_coalescer_.OnHeader(":foo", "bar"); | |
| 28 header_coalescer_.OnHeader("baz", "qux"); | |
| 29 EXPECT_FALSE(header_coalescer_.error_seen()); | |
| 30 | |
| 31 SpdyHeaderBlock header_block = header_coalescer_.release_headers(); | |
| 32 EXPECT_THAT(header_block, | |
| 33 ElementsAre(Pair(":foo", "bar"), Pair("baz", "qux"))); | |
| 34 } | |
| 35 | |
| 36 TEST_F(HeaderCoalescerTest, EmptyHeaderKey) { | |
| 37 EXPECT_FALSE(header_coalescer_.error_seen()); | |
| 38 header_coalescer_.OnHeader("", "foo"); | |
| 39 EXPECT_TRUE(header_coalescer_.error_seen()); | |
| 40 } | |
| 41 | |
| 42 TEST_F(HeaderCoalescerTest, HeaderBlockTooLarge) { | |
| 43 // 3 byte key, 256 * 1024 - 40 byte value, 32 byte overhead: | |
| 44 // less than 256 * 1024 bytes in total. | |
| 45 SpdyString data(256 * 1024 - 40, 'a'); | |
| 46 header_coalescer_.OnHeader("foo", data); | |
| 47 EXPECT_FALSE(header_coalescer_.error_seen()); | |
| 48 | |
| 49 // Another 3 + 3 + 32 bytes: too large. | |
| 50 header_coalescer_.OnHeader("bar", "baz"); | |
| 51 EXPECT_TRUE(header_coalescer_.error_seen()); | |
| 52 } | |
| 53 | |
| 54 TEST_F(HeaderCoalescerTest, PseudoHeadersMustNotFollowRegularHeaders) { | |
| 55 header_coalescer_.OnHeader("foo", "bar"); | |
| 56 EXPECT_FALSE(header_coalescer_.error_seen()); | |
| 57 header_coalescer_.OnHeader(":baz", "qux"); | |
| 58 EXPECT_TRUE(header_coalescer_.error_seen()); | |
| 59 } | |
| 60 | |
| 61 TEST_F(HeaderCoalescerTest, Append) { | |
| 62 header_coalescer_.OnHeader("foo", "bar"); | |
| 63 header_coalescer_.OnHeader("cookie", "baz"); | |
| 64 header_coalescer_.OnHeader("foo", "quux"); | |
| 65 header_coalescer_.OnHeader("cookie", "qux"); | |
| 66 EXPECT_FALSE(header_coalescer_.error_seen()); | |
| 67 | |
| 68 SpdyHeaderBlock header_block = header_coalescer_.release_headers(); | |
| 69 EXPECT_THAT(header_block, | |
| 70 ElementsAre(Pair("foo", SpdyStringPiece("bar\0quux", 8)), | |
| 71 Pair("cookie", "baz; qux"))); | |
| 72 } | |
| 73 | |
| 74 TEST_F(HeaderCoalescerTest, CRLFInHeaderValue) { | |
| 75 EXPECT_FALSE(header_coalescer_.error_seen()); | |
| 76 header_coalescer_.OnHeader("foo", "bar\r\nbaz"); | |
| 77 EXPECT_TRUE(header_coalescer_.error_seen()); | |
| 78 } | |
| 79 | |
| 80 TEST_F(HeaderCoalescerTest, HeaderNameNotValid) { | |
| 81 SpdyStringPiece header_name("\x01\x7F\x80\xff"); | |
| 82 header_coalescer_.OnHeader(header_name, "foo"); | |
| 83 EXPECT_TRUE(header_coalescer_.error_seen()); | |
| 84 } | |
| 85 | |
| 86 // RFC 7230 Section 3.2. Valid header name is defined as: | |
| 87 // field-name = token | |
| 88 // token = 1*tchar | |
| 89 // tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / | |
| 90 // "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA | |
| 91 TEST_F(HeaderCoalescerTest, HeaderNameValid) { | |
| 92 SpdyStringPiece header_name( | |
| 93 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&'*+-." | |
| 94 "^_`|~"); | |
| 95 header_coalescer_.OnHeader(header_name, "foo"); | |
| 96 EXPECT_FALSE(header_coalescer_.error_seen()); | |
| 97 SpdyHeaderBlock header_block = header_coalescer_.release_headers(); | |
| 98 EXPECT_THAT(header_block, ElementsAre(Pair(header_name, "foo"))); | |
| 99 } | |
| 100 | |
| 101 // RFC 7230 Section 3.2. Valid header value is defined as: | |
| 102 // field-value = *( field-content / obs-fold ) | |
| 103 // field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] | |
| 104 // field-vchar = VCHAR / obs-text | |
| 105 // | |
| 106 // obs-fold = CRLF 1*( SP / HTAB ) | |
| 107 // ; obsolete line folding | |
| 108 // ; see Section 3.2.4 | |
| 109 TEST_F(HeaderCoalescerTest, HeaderValueValid) { | |
| 110 // Add two headers, one with an HTAB and one with a SP. | |
| 111 std::vector<char> header_values[2]; | |
| 112 char prefixes[] = {'\t', ' '}; | |
| 113 for (int i = 0; i < 2; ++i) { | |
| 114 header_values[i] = std::vector<char>(); | |
| 115 header_values[i].push_back(prefixes[i]); | |
| 116 // obs-text. From 0x80 to 0xff. | |
| 117 for (int j = 0x80; j <= 0xff; ++j) { | |
| 118 header_values[i].push_back(j); | |
| 119 } | |
| 120 // vchar | |
| 121 for (int j = 0x21; j <= 0x7E; ++j) { | |
| 122 header_values[i].push_back(j); | |
| 123 } | |
| 124 header_coalescer_.OnHeader( | |
| 125 SpdyStringPrintf("%s_%d", "foo", i), | |
| 126 SpdyStringPiece(header_values[i].data(), header_values[i].size())); | |
| 127 EXPECT_FALSE(header_coalescer_.error_seen()); | |
| 128 } | |
| 129 SpdyHeaderBlock header_block = header_coalescer_.release_headers(); | |
| 130 EXPECT_THAT( | |
| 131 header_block, | |
| 132 ElementsAre(Pair("foo_0", SpdyStringPiece(header_values[0].data(), | |
| 133 header_values[0].size())), | |
| 134 Pair("foo_1", SpdyStringPiece(header_values[1].data(), | |
| 135 header_values[1].size())))); | |
| 136 } | |
| 137 | |
| 138 } // namespace test | |
| 139 | |
| 140 } // namespace net | |
| OLD | NEW |