Roll src/third_party/skia 57a48a7:de7665a
[chromium-blink-merge.git] / net / spdy / buffered_spdy_framer_unittest.cc
blob2f87551659adc51622965d7eff7d2e3abb33c7e5
1 // Copyright (c) 2012 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/buffered_spdy_framer.h"
7 #include "net/spdy/spdy_test_util_common.h"
8 #include "testing/platform_test.h"
10 namespace net {
12 namespace {
14 class TestBufferedSpdyVisitor : public BufferedSpdyFramerVisitorInterface {
15 public:
16 explicit TestBufferedSpdyVisitor(SpdyMajorVersion spdy_version)
17 : buffered_spdy_framer_(spdy_version, true),
18 error_count_(0),
19 setting_count_(0),
20 syn_frame_count_(0),
21 syn_reply_frame_count_(0),
22 headers_frame_count_(0),
23 push_promise_frame_count_(0),
24 header_stream_id_(static_cast<SpdyStreamId>(-1)),
25 promised_stream_id_(static_cast<SpdyStreamId>(-1)) {
28 void OnError(SpdyFramer::SpdyError error_code) override {
29 LOG(INFO) << "SpdyFramer Error: " << error_code;
30 error_count_++;
33 void OnStreamError(SpdyStreamId stream_id,
34 const std::string& description) override {
35 LOG(INFO) << "SpdyFramer Error on stream: " << stream_id << " "
36 << description;
37 error_count_++;
40 void OnSynStream(SpdyStreamId stream_id,
41 SpdyStreamId associated_stream_id,
42 SpdyPriority priority,
43 bool fin,
44 bool unidirectional,
45 const SpdyHeaderBlock& headers) override {
46 header_stream_id_ = stream_id;
47 EXPECT_NE(header_stream_id_, SpdyFramer::kInvalidStream);
48 syn_frame_count_++;
49 headers_ = headers;
52 void OnSynReply(SpdyStreamId stream_id,
53 bool fin,
54 const SpdyHeaderBlock& headers) override {
55 header_stream_id_ = stream_id;
56 EXPECT_NE(header_stream_id_, SpdyFramer::kInvalidStream);
57 syn_reply_frame_count_++;
58 headers_ = headers;
61 void OnHeaders(SpdyStreamId stream_id,
62 bool has_priority,
63 SpdyPriority priority,
64 bool fin,
65 const SpdyHeaderBlock& headers) override {
66 header_stream_id_ = stream_id;
67 EXPECT_NE(header_stream_id_, SpdyFramer::kInvalidStream);
68 headers_frame_count_++;
69 headers_ = headers;
72 void OnDataFrameHeader(SpdyStreamId stream_id,
73 size_t length,
74 bool fin) override {
75 ADD_FAILURE() << "Unexpected OnDataFrameHeader call.";
78 void OnStreamFrameData(SpdyStreamId stream_id,
79 const char* data,
80 size_t len,
81 bool fin) override {
82 LOG(FATAL) << "Unexpected OnStreamFrameData call.";
85 void OnSettings(bool clear_persisted) override {}
87 void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {
88 setting_count_++;
91 void OnPing(SpdyPingId unique_id, bool is_ack) override {}
93 void OnRstStream(SpdyStreamId stream_id,
94 SpdyRstStreamStatus status) override {}
96 void OnGoAway(SpdyStreamId last_accepted_stream_id,
97 SpdyGoAwayStatus status) override {}
99 bool OnCredentialFrameData(const char*, size_t) {
100 LOG(FATAL) << "Unexpected OnCredentialFrameData call.";
101 return false;
104 void OnDataFrameHeader(const SpdyFrame* frame) {
105 LOG(FATAL) << "Unexpected OnDataFrameHeader call.";
108 void OnRstStream(const SpdyFrame& frame) {}
109 void OnGoAway(const SpdyFrame& frame) {}
110 void OnPing(const SpdyFrame& frame) {}
111 void OnWindowUpdate(SpdyStreamId stream_id,
112 uint32 delta_window_size) override {}
114 void OnPushPromise(SpdyStreamId stream_id,
115 SpdyStreamId promised_stream_id,
116 const SpdyHeaderBlock& headers) override {
117 header_stream_id_ = stream_id;
118 EXPECT_NE(header_stream_id_, SpdyFramer::kInvalidStream);
119 push_promise_frame_count_++;
120 promised_stream_id_ = promised_stream_id;
121 EXPECT_NE(promised_stream_id_, SpdyFramer::kInvalidStream);
122 headers_ = headers;
125 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
126 return true;
129 void OnCredential(const SpdyFrame& frame) {}
131 // Convenience function which runs a framer simulation with particular input.
132 void SimulateInFramer(const unsigned char* input, size_t size) {
133 buffered_spdy_framer_.set_visitor(this);
134 size_t input_remaining = size;
135 const char* input_ptr = reinterpret_cast<const char*>(input);
136 while (input_remaining > 0 &&
137 buffered_spdy_framer_.error_code() == SpdyFramer::SPDY_NO_ERROR) {
138 // To make the tests more interesting, we feed random (amd small) chunks
139 // into the framer. This simulates getting strange-sized reads from
140 // the socket.
141 const size_t kMaxReadSize = 32;
142 size_t bytes_read =
143 (rand() % std::min(input_remaining, kMaxReadSize)) + 1;
144 size_t bytes_processed =
145 buffered_spdy_framer_.ProcessInput(input_ptr, bytes_read);
146 input_remaining -= bytes_processed;
147 input_ptr += bytes_processed;
151 BufferedSpdyFramer buffered_spdy_framer_;
153 // Counters from the visitor callbacks.
154 int error_count_;
155 int setting_count_;
156 int syn_frame_count_;
157 int syn_reply_frame_count_;
158 int headers_frame_count_;
159 int push_promise_frame_count_;
161 // Header block streaming state:
162 SpdyStreamId header_stream_id_;
163 SpdyStreamId promised_stream_id_;
165 // Headers from OnSyn, OnSynReply, OnHeaders and OnPushPromise for
166 // verification.
167 SpdyHeaderBlock headers_;
170 } // namespace
172 class BufferedSpdyFramerTest
173 : public PlatformTest,
174 public ::testing::WithParamInterface<NextProto> {
175 protected:
176 // Returns true if the two header blocks have equivalent content.
177 bool CompareHeaderBlocks(const SpdyHeaderBlock* expected,
178 const SpdyHeaderBlock* actual) {
179 if (expected->size() != actual->size()) {
180 LOG(ERROR) << "Expected " << expected->size() << " headers; actually got "
181 << actual->size() << ".";
182 return false;
184 for (SpdyHeaderBlock::const_iterator it = expected->begin();
185 it != expected->end();
186 ++it) {
187 SpdyHeaderBlock::const_iterator it2 = actual->find(it->first);
188 if (it2 == actual->end()) {
189 LOG(ERROR) << "Expected header name '" << it->first << "'.";
190 return false;
192 if (it->second.compare(it2->second) != 0) {
193 LOG(ERROR) << "Expected header named '" << it->first
194 << "' to have a value of '" << it->second
195 << "'. The actual value received was '" << it2->second
196 << "'.";
197 return false;
200 return true;
203 SpdyMajorVersion spdy_version() {
204 return NextProtoToSpdyMajorVersion(GetParam());
208 INSTANTIATE_TEST_CASE_P(NextProto,
209 BufferedSpdyFramerTest,
210 testing::Values(kProtoSPDY31,
211 kProtoSPDY4_14,
212 kProtoSPDY4));
214 TEST_P(BufferedSpdyFramerTest, OnSetting) {
215 SpdyFramer framer(spdy_version());
216 SpdySettingsIR settings_ir;
217 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, false, false, 2);
218 settings_ir.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, false, false, 3);
219 scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
220 TestBufferedSpdyVisitor visitor(spdy_version());
222 visitor.SimulateInFramer(
223 reinterpret_cast<unsigned char*>(control_frame->data()),
224 control_frame->size());
225 EXPECT_EQ(0, visitor.error_count_);
226 EXPECT_EQ(2, visitor.setting_count_);
229 TEST_P(BufferedSpdyFramerTest, ReadSynStreamHeaderBlock) {
230 if (spdy_version() > SPDY3) {
231 // SYN_STREAM not supported in SPDY>3.
232 return;
234 SpdyHeaderBlock headers;
235 headers["aa"] = "vv";
236 headers["bb"] = "ww";
237 BufferedSpdyFramer framer(spdy_version(), true);
238 scoped_ptr<SpdyFrame> control_frame(
239 framer.CreateSynStream(1, // stream_id
240 0, // associated_stream_id
241 1, // priority
242 CONTROL_FLAG_NONE,
243 &headers));
244 EXPECT_TRUE(control_frame.get() != NULL);
246 TestBufferedSpdyVisitor visitor(spdy_version());
247 visitor.SimulateInFramer(
248 reinterpret_cast<unsigned char*>(control_frame.get()->data()),
249 control_frame.get()->size());
250 EXPECT_EQ(0, visitor.error_count_);
251 EXPECT_EQ(1, visitor.syn_frame_count_);
252 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
253 EXPECT_EQ(0, visitor.headers_frame_count_);
254 EXPECT_EQ(0, visitor.push_promise_frame_count_);
255 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
258 TEST_P(BufferedSpdyFramerTest, ReadSynReplyHeaderBlock) {
259 if (spdy_version() > SPDY3) {
260 // SYN_REPLY not supported in SPDY>3.
261 return;
263 SpdyHeaderBlock headers;
264 headers["alpha"] = "beta";
265 headers["gamma"] = "delta";
266 BufferedSpdyFramer framer(spdy_version(), true);
267 scoped_ptr<SpdyFrame> control_frame(
268 framer.CreateSynReply(1, // stream_id
269 CONTROL_FLAG_NONE,
270 &headers));
271 EXPECT_TRUE(control_frame.get() != NULL);
273 TestBufferedSpdyVisitor visitor(spdy_version());
274 visitor.SimulateInFramer(
275 reinterpret_cast<unsigned char*>(control_frame.get()->data()),
276 control_frame.get()->size());
277 EXPECT_EQ(0, visitor.error_count_);
278 EXPECT_EQ(0, visitor.syn_frame_count_);
279 EXPECT_EQ(0, visitor.push_promise_frame_count_);
280 if (spdy_version() < SPDY4) {
281 EXPECT_EQ(1, visitor.syn_reply_frame_count_);
282 EXPECT_EQ(0, visitor.headers_frame_count_);
283 } else {
284 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
285 EXPECT_EQ(1, visitor.headers_frame_count_);
287 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
290 TEST_P(BufferedSpdyFramerTest, ReadHeadersHeaderBlock) {
291 SpdyHeaderBlock headers;
292 headers["alpha"] = "beta";
293 headers["gamma"] = "delta";
294 BufferedSpdyFramer framer(spdy_version(), true);
295 scoped_ptr<SpdyFrame> control_frame(
296 framer.CreateHeaders(1, // stream_id
297 CONTROL_FLAG_NONE,
298 0, // priority
299 &headers));
300 EXPECT_TRUE(control_frame.get() != NULL);
302 TestBufferedSpdyVisitor visitor(spdy_version());
303 visitor.SimulateInFramer(
304 reinterpret_cast<unsigned char*>(control_frame.get()->data()),
305 control_frame.get()->size());
306 EXPECT_EQ(0, visitor.error_count_);
307 EXPECT_EQ(0, visitor.syn_frame_count_);
308 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
309 EXPECT_EQ(1, visitor.headers_frame_count_);
310 EXPECT_EQ(0, visitor.push_promise_frame_count_);
311 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
314 TEST_P(BufferedSpdyFramerTest, ReadPushPromiseHeaderBlock) {
315 if (spdy_version() < SPDY4)
316 return;
317 SpdyHeaderBlock headers;
318 headers["alpha"] = "beta";
319 headers["gamma"] = "delta";
320 BufferedSpdyFramer framer(spdy_version(), true);
321 scoped_ptr<SpdyFrame> control_frame(
322 framer.CreatePushPromise(1, 2, &headers));
323 EXPECT_TRUE(control_frame.get() != NULL);
325 TestBufferedSpdyVisitor visitor(spdy_version());
326 visitor.SimulateInFramer(
327 reinterpret_cast<unsigned char*>(control_frame.get()->data()),
328 control_frame.get()->size());
329 EXPECT_EQ(0, visitor.error_count_);
330 EXPECT_EQ(0, visitor.syn_frame_count_);
331 EXPECT_EQ(0, visitor.syn_reply_frame_count_);
332 EXPECT_EQ(0, visitor.headers_frame_count_);
333 EXPECT_EQ(1, visitor.push_promise_frame_count_);
334 EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
335 EXPECT_EQ(1u, visitor.header_stream_id_);
336 EXPECT_EQ(2u, visitor.promised_stream_id_);
339 } // namespace net