Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(190)

Side by Side Diff: net/spdy/hpack/hpack_round_trip_test.cc

Issue 2832973003: Split net/spdy into core and chromium subdirectories. (Closed)
Patch Set: Fix some more build rules. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/spdy/hpack/hpack_output_stream_test.cc ('k') | net/spdy/hpack/hpack_static_table.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 <cmath>
6 #include <ctime>
7 #include <vector>
8
9 #include "base/rand_util.h"
10 #include "net/spdy/hpack/hpack_constants.h"
11 #include "net/spdy/hpack/hpack_decoder.h"
12 #include "net/spdy/hpack/hpack_encoder.h"
13 #include "net/spdy/platform/api/spdy_string.h"
14 #include "net/spdy/spdy_test_utils.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace net {
18 namespace test {
19
20 namespace {
21
22 // Supports testing with the input split at every byte boundary.
23 enum InputSizeParam { ALL_INPUT, ONE_BYTE, ZERO_THEN_ONE_BYTE };
24
25 class HpackRoundTripTest : public ::testing::TestWithParam<InputSizeParam> {
26 protected:
27 HpackRoundTripTest() : encoder_(ObtainHpackHuffmanTable()), decoder_() {}
28
29 void SetUp() override {
30 // Use a small table size to tickle eviction handling.
31 encoder_.ApplyHeaderTableSizeSetting(256);
32 decoder_.ApplyHeaderTableSizeSetting(256);
33 }
34
35 bool RoundTrip(const SpdyHeaderBlock& header_set) {
36 SpdyString encoded;
37 encoder_.EncodeHeaderSet(header_set, &encoded);
38
39 bool success = true;
40 if (GetParam() == ALL_INPUT) {
41 // Pass all the input to the decoder at once.
42 success = decoder_.HandleControlFrameHeadersData(encoded.data(),
43 encoded.size());
44 } else if (GetParam() == ONE_BYTE) {
45 // Pass the input to the decoder one byte at a time.
46 const char* data = encoded.data();
47 for (size_t ndx = 0; ndx < encoded.size() && success; ++ndx) {
48 success = decoder_.HandleControlFrameHeadersData(data + ndx, 1);
49 }
50 } else if (GetParam() == ZERO_THEN_ONE_BYTE) {
51 // Pass the input to the decoder one byte at a time, but before each
52 // byte pass an empty buffer.
53 const char* data = encoded.data();
54 for (size_t ndx = 0; ndx < encoded.size() && success; ++ndx) {
55 success = (decoder_.HandleControlFrameHeadersData(data + ndx, 0) &&
56 decoder_.HandleControlFrameHeadersData(data + ndx, 1));
57 }
58 } else {
59 ADD_FAILURE() << "Unknown param: " << GetParam();
60 }
61
62 if (success) {
63 success = decoder_.HandleControlFrameHeadersComplete(nullptr);
64 }
65
66 EXPECT_EQ(header_set, decoder_.decoded_block());
67 return success;
68 }
69
70 size_t SampleExponential(size_t mean, size_t sanity_bound) {
71 return std::min<size_t>(-std::log(base::RandDouble()) * mean, sanity_bound);
72 }
73
74 HpackEncoder encoder_;
75 HpackDecoder decoder_;
76 };
77
78 INSTANTIATE_TEST_CASE_P(Tests,
79 HpackRoundTripTest,
80 ::testing::Values(ALL_INPUT,
81 ONE_BYTE,
82 ZERO_THEN_ONE_BYTE));
83
84 TEST_P(HpackRoundTripTest, ResponseFixtures) {
85 {
86 SpdyHeaderBlock headers;
87 headers[":status"] = "302";
88 headers["cache-control"] = "private";
89 headers["date"] = "Mon, 21 Oct 2013 20:13:21 GMT";
90 headers["location"] = "https://www.example.com";
91 EXPECT_TRUE(RoundTrip(headers));
92 }
93 {
94 SpdyHeaderBlock headers;
95 headers[":status"] = "200";
96 headers["cache-control"] = "private";
97 headers["date"] = "Mon, 21 Oct 2013 20:13:21 GMT";
98 headers["location"] = "https://www.example.com";
99 EXPECT_TRUE(RoundTrip(headers));
100 }
101 {
102 SpdyHeaderBlock headers;
103 headers[":status"] = "200";
104 headers["cache-control"] = "private";
105 headers["content-encoding"] = "gzip";
106 headers["date"] = "Mon, 21 Oct 2013 20:13:22 GMT";
107 headers["location"] = "https://www.example.com";
108 headers["set-cookie"] =
109 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;"
110 " max-age=3600; version=1";
111 headers["multivalue"] = SpdyString("foo\0bar", 7);
112 EXPECT_TRUE(RoundTrip(headers));
113 }
114 }
115
116 TEST_P(HpackRoundTripTest, RequestFixtures) {
117 {
118 SpdyHeaderBlock headers;
119 headers[":authority"] = "www.example.com";
120 headers[":method"] = "GET";
121 headers[":path"] = "/";
122 headers[":scheme"] = "http";
123 headers["cookie"] = "baz=bing; foo=bar";
124 EXPECT_TRUE(RoundTrip(headers));
125 }
126 {
127 SpdyHeaderBlock headers;
128 headers[":authority"] = "www.example.com";
129 headers[":method"] = "GET";
130 headers[":path"] = "/";
131 headers[":scheme"] = "http";
132 headers["cache-control"] = "no-cache";
133 headers["cookie"] = "foo=bar; spam=eggs";
134 EXPECT_TRUE(RoundTrip(headers));
135 }
136 {
137 SpdyHeaderBlock headers;
138 headers[":authority"] = "www.example.com";
139 headers[":method"] = "GET";
140 headers[":path"] = "/index.html";
141 headers[":scheme"] = "https";
142 headers["custom-key"] = "custom-value";
143 headers["cookie"] = "baz=bing; fizzle=fazzle; garbage";
144 headers["multivalue"] = SpdyString("foo\0bar", 7);
145 EXPECT_TRUE(RoundTrip(headers));
146 }
147 }
148
149 TEST_P(HpackRoundTripTest, RandomizedExamples) {
150 // Grow vectors of names & values, which are seeded with fixtures and then
151 // expanded with dynamically generated data. Samples are taken using the
152 // exponential distribution.
153 std::vector<SpdyString> pseudo_header_names, random_header_names;
154 pseudo_header_names.push_back(":authority");
155 pseudo_header_names.push_back(":path");
156 pseudo_header_names.push_back(":status");
157
158 // TODO(jgraettinger): Enable "cookie" as a name fixture. Crumbs may be
159 // reconstructed in any order, which breaks the simple validation used here.
160
161 std::vector<SpdyString> values;
162 values.push_back("/");
163 values.push_back("/index.html");
164 values.push_back("200");
165 values.push_back("404");
166 values.push_back("");
167 values.push_back("baz=bing; foo=bar; garbage");
168 values.push_back("baz=bing; fizzle=fazzle; garbage");
169
170 int seed = std::time(NULL);
171 LOG(INFO) << "Seeding with srand(" << seed << ")";
172 srand(seed);
173
174 for (size_t i = 0; i != 2000; ++i) {
175 SpdyHeaderBlock headers;
176
177 // Choose a random number of headers to add, and of these a random subset
178 // will be HTTP/2 pseudo headers.
179 size_t header_count = 1 + SampleExponential(7, 50);
180 size_t pseudo_header_count =
181 std::min(header_count, 1 + SampleExponential(7, 50));
182 EXPECT_LE(pseudo_header_count, header_count);
183 for (size_t j = 0; j != header_count; ++j) {
184 SpdyString name, value;
185 // Pseudo headers must be added before regular headers.
186 if (j < pseudo_header_count) {
187 // Choose one of the defined pseudo headers at random.
188 size_t name_index = base::RandGenerator(pseudo_header_names.size());
189 name = pseudo_header_names[name_index];
190 } else {
191 // Randomly reuse an existing header name, or generate a new one.
192 size_t name_index = SampleExponential(20, 200);
193 if (name_index >= random_header_names.size()) {
194 name = base::RandBytesAsString(1 + SampleExponential(5, 30));
195 // A regular header cannot begin with the pseudo header prefix ":".
196 if (name[0] == ':') {
197 name[0] = 'x';
198 }
199 random_header_names.push_back(name);
200 } else {
201 name = random_header_names[name_index];
202 }
203 }
204
205 // Randomly reuse an existing value, or generate a new one.
206 size_t value_index = SampleExponential(20, 200);
207 if (value_index >= values.size()) {
208 SpdyString newvalue =
209 base::RandBytesAsString(1 + SampleExponential(15, 75));
210 // Currently order is not preserved in the encoder. In particular,
211 // when a value is decomposed at \0 delimiters, its parts might get
212 // encoded out of order if some but not all of them already exist in
213 // the header table. For now, avoid \0 bytes in values.
214 std::replace(newvalue.begin(), newvalue.end(), '\x00', '\x01');
215 values.push_back(newvalue);
216 value = values.back();
217 } else {
218 value = values[value_index];
219 }
220 headers[name] = value;
221 }
222 EXPECT_TRUE(RoundTrip(headers));
223 }
224 }
225
226 } // namespace
227
228 } // namespace test
229 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/hpack/hpack_output_stream_test.cc ('k') | net/spdy/hpack/hpack_static_table.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698