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
3 // found in the LICENSE file.
5 #include "net/spdy/spdy_headers_block_parser.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/sys_byteorder.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
16 using base::IntToString;
17 using base::StringPiece;
19 using testing::ElementsAre;
20 using testing::ElementsAreArray;
22 class MockKeyValueHandler : public KeyValueHandler {
24 // A mock the handler method to make sure we parse out (and call it with)
25 // the correct parameters.
26 MOCK_METHOD2(OnKeyValuePair, void(const StringPiece&, const StringPiece&));
29 class SpdyHeadersBlockParserTest : public testing::Test {
31 virtual ~SpdyHeadersBlockParserTest() {}
34 virtual void SetUp() {
35 // Create a parser using the mock handler.
36 parser_.reset(new SpdyHeadersBlockParser(&handler_));
39 MockKeyValueHandler handler_;
40 scoped_ptr<SpdyHeadersBlockParser> parser_;
42 // Create a header block with a specified number of headers.
43 static string CreateHeaders(uint32_t num_headers, bool insert_nulls) {
45 char length_field[sizeof(uint32_t)];
47 // First, write the number of headers in the header block.
48 StoreInt(num_headers, length_field);
49 headers += string(length_field, sizeof(length_field));
51 // Second, write the key-value pairs.
52 for (uint32_t i = 0; i < num_headers; i++) {
56 key = string(base_key) + string("\0", 1) + IntToString(i);
58 key = string(base_key) + IntToString(i);
60 // Encode the key as SPDY header.
61 StoreInt(key.length(), length_field);
62 headers += string(length_field, sizeof(length_field));
68 value = string(base_value) + string("\0", 1) + IntToString(i);
70 value = string(base_value) + IntToString(i);
72 // Encode the value as SPDY header.
73 StoreInt(value.length(), length_field);
74 headers += string(length_field, sizeof(length_field));
81 static const char* base_key;
82 static const char* base_value;
84 // Number of headers and header blocks used in the tests.
85 static const int kNumHeadersInBlock = 10;
86 static const int kNumHeaderBlocks = 10;
89 static void StoreInt(uint32_t num, char* buf) {
90 uint32_t net_order_len = base::HostToNet32(num);
91 memcpy(buf, &net_order_len, sizeof(num));
95 const char* SpdyHeadersBlockParserTest::base_key = "test_key";
96 const char* SpdyHeadersBlockParserTest::base_value = "test_value";
98 TEST_F(SpdyHeadersBlockParserTest, Basic) {
99 // Sanity test, verify that we parse out correctly a block with
100 // a single key-value pair.
101 std::string expect_key = base_key + IntToString(0);
102 std::string expect_value = base_value + IntToString(0);
103 EXPECT_CALL(handler_, OnKeyValuePair(StringPiece(expect_key),
104 StringPiece(expect_value))).Times(1);
105 string headers(CreateHeaders(1, false));
106 parser_->HandleControlFrameHeadersData(headers.c_str(), headers.length());
109 TEST_F(SpdyHeadersBlockParserTest, NullsSupported) {
110 // Sanity test, verify that we parse out correctly a block with
111 // a single key-value pair when the key and value contain null charecters.
112 std::string expect_key = base_key + string("\0", 1) + IntToString(0);
113 std::string expect_value = base_value + string("\0", 1) + IntToString(0);
114 EXPECT_CALL(handler_, OnKeyValuePair(StringPiece(expect_key),
115 StringPiece(expect_value))).Times(1);
116 string headers(CreateHeaders(1, true));
117 parser_->HandleControlFrameHeadersData(headers.c_str(), headers.length());
120 TEST_F(SpdyHeadersBlockParserTest, MultipleBlocksMultipleHeadersPerBlock) {
121 testing::InSequence s;
123 // The mock doesn't retain storage of arguments, so keep them in scope.
124 std::vector<string> retained_arguments;
125 for (int i = 0; i < kNumHeadersInBlock; i++) {
126 retained_arguments.push_back(base_key + IntToString(i));
127 retained_arguments.push_back(base_value + IntToString(i));
129 // For each block we expect to parse out the headers in order.
130 for (int i = 0; i < kNumHeaderBlocks; i++) {
131 for (int j = 0; j < kNumHeadersInBlock; j++) {
132 EXPECT_CALL(handler_, OnKeyValuePair(
133 StringPiece(retained_arguments[2 * j]),
134 StringPiece(retained_arguments[2 * j + 1]))).Times(1);
137 // Parse the blocks, breaking them into multiple reads at various points.
138 for (int i = 0; i < kNumHeaderBlocks; i++) {
139 unsigned break_index = 4 * i;
140 string headers(CreateHeaders(kNumHeadersInBlock, false));
141 parser_->HandleControlFrameHeadersData(
142 headers.c_str(), headers.length() - break_index);
143 parser_->HandleControlFrameHeadersData(
144 headers.c_str() + headers.length() - break_index, break_index);
148 TEST(SpdyHeadersBlockParserReader, EmptyPrefix) {
149 std::string prefix = "";
150 std::string suffix = "foobar";
151 char buffer[] = "12345";
153 SpdyHeadersBlockParserReader reader(prefix, suffix);
154 EXPECT_EQ(6u, reader.Available());
155 EXPECT_FALSE(reader.ReadN(10, buffer)); // Not enough buffer.
156 EXPECT_TRUE(reader.ReadN(5, buffer));
157 EXPECT_THAT(buffer, ElementsAreArray("fooba"));
158 EXPECT_EQ(1u, reader.Available());
159 EXPECT_THAT(reader.Remainder(), ElementsAre('r'));
162 TEST(SpdyHeadersBlockParserReader, EmptySuffix) {
163 std::string prefix = "foobar";
164 std::string suffix = "";
165 char buffer[] = "12345";
167 SpdyHeadersBlockParserReader reader(prefix, suffix);
168 EXPECT_EQ(6u, reader.Available());
169 EXPECT_FALSE(reader.ReadN(10, buffer)); // Not enough buffer.
170 EXPECT_TRUE(reader.ReadN(5, buffer));
171 EXPECT_THAT(buffer, ElementsAreArray("fooba"));
172 EXPECT_EQ(1u, reader.Available());
173 EXPECT_THAT(reader.Remainder(), ElementsAre('r'));
176 TEST(SpdyHeadersBlockParserReader, ReadInPrefix) {
177 std::string prefix = "abcdef";
178 std::string suffix = "ghijk";
179 char buffer[] = "1234";
181 SpdyHeadersBlockParserReader reader(prefix, suffix);
182 EXPECT_EQ(11u, reader.Available());
183 EXPECT_TRUE(reader.ReadN(4, buffer));
184 EXPECT_THAT(buffer, ElementsAreArray("abcd"));
185 EXPECT_EQ(7u, reader.Available());
186 EXPECT_THAT(reader.Remainder(),
187 ElementsAre('e', 'f', 'g', 'h', 'i', 'j', 'k'));
190 TEST(SpdyHeadersBlockParserReader, ReadPastPrefix) {
191 std::string prefix = "abcdef";
192 std::string suffix = "ghijk";
193 char buffer[] = "12345";
195 SpdyHeadersBlockParserReader reader(prefix, suffix);
196 EXPECT_EQ(11u, reader.Available());
197 EXPECT_TRUE(reader.ReadN(5, buffer));
198 EXPECT_THAT(buffer, ElementsAreArray("abcde"));
200 // One byte of prefix left: read it.
201 EXPECT_EQ(6u, reader.Available());
202 EXPECT_TRUE(reader.ReadN(1, buffer));
203 EXPECT_THAT(buffer, ElementsAreArray("fbcde"));
205 // Read one byte of suffix.
206 EXPECT_EQ(5u, reader.Available());
207 EXPECT_TRUE(reader.ReadN(1, buffer));
208 EXPECT_THAT(buffer, ElementsAreArray("gbcde"));
210 EXPECT_THAT(reader.Remainder(),
211 ElementsAre('h', 'i', 'j', 'k'));
214 TEST(SpdyHeadersBlockParserReader, ReadAcrossSuffix) {
215 std::string prefix = "abcdef";
216 std::string suffix = "ghijk";
217 char buffer[] = "12345678";
219 SpdyHeadersBlockParserReader reader(prefix, suffix);
220 EXPECT_EQ(11u, reader.Available());
221 EXPECT_TRUE(reader.ReadN(8, buffer));
222 EXPECT_THAT(buffer, ElementsAreArray("abcdefgh"));
224 EXPECT_EQ(3u, reader.Available());
225 EXPECT_FALSE(reader.ReadN(4, buffer));
226 EXPECT_TRUE(reader.ReadN(3, buffer));
227 EXPECT_THAT(buffer, ElementsAreArray("ijkdefgh"));
229 EXPECT_EQ(0u, reader.Available());
230 EXPECT_THAT(reader.Remainder(), ElementsAre());