326cb058e2030158e6df138ee3536ea62d393b20
[platform/framework/web/crosswalk.git] / src / net / spdy / spdy_headers_block_parser_test.cc
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.
4
5 #include "net/spdy/spdy_headers_block_parser.h"
6
7 #include <string>
8
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"
13
14 namespace net {
15
16 using base::IntToString;
17 using base::StringPiece;
18 using std::string;
19 using testing::ElementsAre;
20 using testing::ElementsAreArray;
21
22 class MockKeyValueHandler : public KeyValueHandler {
23  public:
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&));
27 };
28
29 class SpdyHeadersBlockParserTest : public testing::Test {
30  public:
31   virtual ~SpdyHeadersBlockParserTest() {}
32
33  protected:
34   virtual void SetUp() {
35     // Create a parser using the mock handler.
36     parser_.reset(new SpdyHeadersBlockParser(&handler_));
37   }
38
39   MockKeyValueHandler handler_;
40   scoped_ptr<SpdyHeadersBlockParser> parser_;
41
42   // Create a header block with a specified number of headers.
43   static string CreateHeaders(uint32_t num_headers, bool insert_nulls) {
44     string headers;
45     char length_field[sizeof(uint32_t)];
46
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));
50
51     // Second, write the key-value pairs.
52     for (uint32_t i = 0; i < num_headers; i++) {
53       // Build the key.
54       string key;
55       if (insert_nulls) {
56         key = string(base_key) + string("\0", 1) + IntToString(i);
57       } else {
58         key = string(base_key) + IntToString(i);
59       }
60       // Encode the key as SPDY header.
61       StoreInt(key.length(), length_field);
62       headers += string(length_field, sizeof(length_field));
63       headers += key;
64
65       // Build the value.
66       string value;
67       if (insert_nulls) {
68         value = string(base_value) + string("\0", 1) + IntToString(i);
69       } else {
70         value = string(base_value) + IntToString(i);
71       }
72       // Encode the value as SPDY header.
73       StoreInt(value.length(), length_field);
74       headers += string(length_field, sizeof(length_field));
75       headers += value;
76     }
77
78     return headers;
79   }
80
81   static const char* base_key;
82   static const char* base_value;
83
84   // Number of headers and header blocks used in the tests.
85   static const int kNumHeadersInBlock = 10;
86   static const int kNumHeaderBlocks = 10;
87
88  private:
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));
92   }
93 };
94
95 const char* SpdyHeadersBlockParserTest::base_key = "test_key";
96 const char* SpdyHeadersBlockParserTest::base_value = "test_value";
97
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());
107 }
108
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());
118 }
119
120 TEST_F(SpdyHeadersBlockParserTest, MultipleBlocksMultipleHeadersPerBlock) {
121   testing::InSequence s;
122
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));
128   }
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);
135     }
136   }
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);
145   }
146 }
147
148 TEST(SpdyHeadersBlockParserReader, EmptyPrefix) {
149   std::string prefix = "";
150   std::string suffix = "foobar";
151   char buffer[] = "12345";
152
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'));
160 }
161
162 TEST(SpdyHeadersBlockParserReader, EmptySuffix) {
163   std::string prefix = "foobar";
164   std::string suffix = "";
165   char buffer[] = "12345";
166
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'));
174 }
175
176 TEST(SpdyHeadersBlockParserReader, ReadInPrefix) {
177   std::string prefix = "abcdef";
178   std::string suffix = "ghijk";
179   char buffer[] = "1234";
180
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'));
188 }
189
190 TEST(SpdyHeadersBlockParserReader, ReadPastPrefix) {
191   std::string prefix = "abcdef";
192   std::string suffix = "ghijk";
193   char buffer[] = "12345";
194
195   SpdyHeadersBlockParserReader reader(prefix, suffix);
196   EXPECT_EQ(11u, reader.Available());
197   EXPECT_TRUE(reader.ReadN(5, buffer));
198   EXPECT_THAT(buffer, ElementsAreArray("abcde"));
199
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"));
204
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"));
209
210   EXPECT_THAT(reader.Remainder(),
211             ElementsAre('h', 'i', 'j', 'k'));
212 }
213
214 TEST(SpdyHeadersBlockParserReader, ReadAcrossSuffix) {
215   std::string prefix = "abcdef";
216   std::string suffix = "ghijk";
217   char buffer[] = "12345678";
218
219   SpdyHeadersBlockParserReader reader(prefix, suffix);
220   EXPECT_EQ(11u, reader.Available());
221   EXPECT_TRUE(reader.ReadN(8, buffer));
222   EXPECT_THAT(buffer, ElementsAreArray("abcdefgh"));
223
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"));
228
229   EXPECT_EQ(0u, reader.Available());
230   EXPECT_THAT(reader.Remainder(), ElementsAre());
231 }
232
233 }  // namespace net