header_coalescer_test.cc 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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/spdy/header_coalescer.h"
  5. #include <string>
  6. #include <vector>
  7. #include "net/log/net_log.h"
  8. #include "net/log/test_net_log.h"
  9. #include "net/log/test_net_log_util.h"
  10. #include "net/spdy/spdy_test_util_common.h"
  11. #include "testing/gmock/include/gmock/gmock.h"
  12. #include "testing/gtest/include/gtest/gtest.h"
  13. using ::testing::ElementsAre;
  14. using ::testing::Pair;
  15. namespace net::test {
  16. class HeaderCoalescerTest : public ::testing::Test {
  17. public:
  18. HeaderCoalescerTest()
  19. : header_coalescer_(kMaxHeaderListSizeForTest, net_log_with_source_) {}
  20. void ExpectEntry(base::StringPiece expected_header_name,
  21. base::StringPiece expected_header_value,
  22. base::StringPiece expected_error_message) {
  23. auto entry_list = net_log_observer_.GetEntries();
  24. ASSERT_EQ(1u, entry_list.size());
  25. EXPECT_EQ(entry_list[0].type,
  26. NetLogEventType::HTTP2_SESSION_RECV_INVALID_HEADER);
  27. EXPECT_EQ(entry_list[0].source.id, net_log_with_source_.source().id);
  28. std::string value;
  29. EXPECT_EQ(expected_header_name,
  30. GetStringValueFromParams(entry_list[0], "header_name"));
  31. EXPECT_EQ(expected_header_value,
  32. GetStringValueFromParams(entry_list[0], "header_value"));
  33. EXPECT_EQ(expected_error_message,
  34. GetStringValueFromParams(entry_list[0], "error"));
  35. }
  36. protected:
  37. NetLogWithSource net_log_with_source_{
  38. NetLogWithSource::Make(NetLog::Get(), NetLogSourceType::NONE)};
  39. RecordingNetLogObserver net_log_observer_;
  40. HeaderCoalescer header_coalescer_;
  41. };
  42. TEST_F(HeaderCoalescerTest, CorrectHeaders) {
  43. header_coalescer_.OnHeader(":foo", "bar");
  44. header_coalescer_.OnHeader("baz", "qux");
  45. EXPECT_FALSE(header_coalescer_.error_seen());
  46. spdy::Http2HeaderBlock header_block = header_coalescer_.release_headers();
  47. EXPECT_THAT(header_block,
  48. ElementsAre(Pair(":foo", "bar"), Pair("baz", "qux")));
  49. }
  50. TEST_F(HeaderCoalescerTest, EmptyHeaderKey) {
  51. header_coalescer_.OnHeader("", "foo");
  52. EXPECT_TRUE(header_coalescer_.error_seen());
  53. ExpectEntry("", "foo", "Header name must not be empty.");
  54. }
  55. TEST_F(HeaderCoalescerTest, HeaderBlockTooLarge) {
  56. // key + value + overhead = 3 + kMaxHeaderListSizeForTest - 40 + 32
  57. // = kMaxHeaderListSizeForTest - 5
  58. std::string data(kMaxHeaderListSizeForTest - 40, 'a');
  59. header_coalescer_.OnHeader("foo", data);
  60. EXPECT_FALSE(header_coalescer_.error_seen());
  61. // Another 3 + 4 + 32 bytes: too large.
  62. header_coalescer_.OnHeader("bar", "abcd");
  63. EXPECT_TRUE(header_coalescer_.error_seen());
  64. ExpectEntry("bar", "abcd", "Header list too large.");
  65. }
  66. TEST_F(HeaderCoalescerTest, PseudoHeadersMustNotFollowRegularHeaders) {
  67. header_coalescer_.OnHeader("foo", "bar");
  68. EXPECT_FALSE(header_coalescer_.error_seen());
  69. header_coalescer_.OnHeader(":baz", "qux");
  70. EXPECT_TRUE(header_coalescer_.error_seen());
  71. ExpectEntry(":baz", "qux", "Pseudo header must not follow regular headers.");
  72. }
  73. TEST_F(HeaderCoalescerTest, Append) {
  74. header_coalescer_.OnHeader("foo", "bar");
  75. header_coalescer_.OnHeader("cookie", "baz");
  76. header_coalescer_.OnHeader("foo", "quux");
  77. header_coalescer_.OnHeader("cookie", "qux");
  78. EXPECT_FALSE(header_coalescer_.error_seen());
  79. spdy::Http2HeaderBlock header_block = header_coalescer_.release_headers();
  80. EXPECT_THAT(header_block,
  81. ElementsAre(Pair("foo", absl::string_view("bar\0quux", 8)),
  82. Pair("cookie", "baz; qux")));
  83. }
  84. TEST_F(HeaderCoalescerTest, HeaderNameNotValid) {
  85. absl::string_view header_name("\x1\x7F\x80\xFF");
  86. header_coalescer_.OnHeader(header_name, "foo");
  87. EXPECT_TRUE(header_coalescer_.error_seen());
  88. ExpectEntry("%ESCAPED:\xE2\x80\x8B \x1\x7F%80%FF", "foo",
  89. "Invalid character in header name.");
  90. }
  91. // RFC 7540 Section 8.1.2.6. Uppercase in header name is invalid.
  92. TEST_F(HeaderCoalescerTest, HeaderNameHasUppercase) {
  93. absl::string_view header_name("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
  94. header_coalescer_.OnHeader(header_name, "foo");
  95. EXPECT_TRUE(header_coalescer_.error_seen());
  96. ExpectEntry("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "foo",
  97. "Upper case characters in header name.");
  98. }
  99. // RFC 7230 Section 3.2. Valid header name is defined as:
  100. // field-name = token
  101. // token = 1*tchar
  102. // tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
  103. // "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
  104. TEST_F(HeaderCoalescerTest, HeaderNameValid) {
  105. // Due to RFC 7540 Section 8.1.2.6. Uppercase characters are not included.
  106. absl::string_view header_name(
  107. "abcdefghijklmnopqrstuvwxyz0123456789!#$%&'*+-."
  108. "^_`|~");
  109. header_coalescer_.OnHeader(header_name, "foo");
  110. EXPECT_FALSE(header_coalescer_.error_seen());
  111. spdy::Http2HeaderBlock header_block = header_coalescer_.release_headers();
  112. EXPECT_THAT(header_block, ElementsAre(Pair(header_name, "foo")));
  113. }
  114. // According to RFC 7540 Section 10.3 and RFC 7230 Section 3.2, allowed
  115. // characters in header values are '\t', ' ', 0x21 to 0x7E, and 0x80 to 0xFF.
  116. TEST_F(HeaderCoalescerTest, HeaderValueValid) {
  117. header_coalescer_.OnHeader("foo", " bar \x21 \x7e baz\tqux\x80\xff ");
  118. EXPECT_FALSE(header_coalescer_.error_seen());
  119. }
  120. TEST_F(HeaderCoalescerTest, HeaderValueContainsLF) {
  121. header_coalescer_.OnHeader("foo", "bar\nbaz");
  122. EXPECT_TRUE(header_coalescer_.error_seen());
  123. ExpectEntry("foo", "bar\nbaz", "Invalid character 0x0A in header value.");
  124. }
  125. TEST_F(HeaderCoalescerTest, HeaderValueContainsCR) {
  126. header_coalescer_.OnHeader("foo", "bar\rbaz");
  127. EXPECT_TRUE(header_coalescer_.error_seen());
  128. ExpectEntry("foo", "bar\rbaz", "Invalid character 0x0D in header value.");
  129. }
  130. TEST_F(HeaderCoalescerTest, HeaderValueContains0x7f) {
  131. header_coalescer_.OnHeader("foo", "bar\x7f baz");
  132. EXPECT_TRUE(header_coalescer_.error_seen());
  133. ExpectEntry("foo", "bar\x7F baz", "Invalid character 0x7F in header value.");
  134. }
  135. } // namespace net::test