OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "net/spdy/spdy_protocol.h" | |
6 | |
7 #include "base/memory/scoped_ptr.h" | |
8 #include "net/spdy/spdy_bitmasks.h" | |
9 #include "net/spdy/spdy_framer.h" | |
10 #include "testing/platform_test.h" | |
11 | |
12 using spdy::CONTROL_FLAG_FIN; | |
13 using spdy::CONTROL_FLAG_NONE; | |
14 using spdy::FlagsAndLength; | |
15 using spdy::GOAWAY; | |
16 using spdy::HEADERS; | |
17 using spdy::NOOP; | |
18 using spdy::NUM_CONTROL_FRAME_TYPES; | |
19 using spdy::PING; | |
20 using spdy::RST_STREAM; | |
21 using spdy::SETTINGS; | |
22 using spdy::SYN_REPLY; | |
23 using spdy::SYN_STREAM; | |
24 using spdy::SettingsFlagsAndId; | |
25 using spdy::SpdyControlFrame; | |
26 using spdy::SpdyControlType; | |
27 using spdy::SpdyDataFrame; | |
28 using spdy::SpdyFrame; | |
29 using spdy::SpdyFramer; | |
30 using spdy::SpdyGoAwayControlFrame; | |
31 using spdy::SpdyHeaderBlock; | |
32 using spdy::SpdyHeadersControlFrame; | |
33 using spdy::SpdyPingControlFrame; | |
34 using spdy::SpdyRstStreamControlFrame; | |
35 using spdy::SpdySettings; | |
36 using spdy::SpdySettingsControlFrame; | |
37 using spdy::SpdyStatusCodes; | |
38 using spdy::SpdySynReplyControlFrame; | |
39 using spdy::SpdySynStreamControlFrame; | |
40 using spdy::SpdyWindowUpdateControlFrame; | |
41 using spdy::WINDOW_UPDATE; | |
42 using spdy::kLengthMask; | |
43 using spdy::kStreamIdMask; | |
44 | |
45 namespace { | |
46 | |
47 // Default SPDY version for unit tests. | |
48 const int SPDY_VERSION_FOR_TESTS = 2; | |
49 | |
50 // Test our protocol constants | |
51 TEST(SpdyProtocolSpdy2Test, ProtocolConstants) { | |
52 EXPECT_EQ(8u, SpdyFrame::kHeaderSize); | |
53 EXPECT_EQ(8u, SpdyDataFrame::size()); | |
54 EXPECT_EQ(8u, SpdyControlFrame::kHeaderSize); | |
55 EXPECT_EQ(18u, SpdySynStreamControlFrame::size()); | |
56 EXPECT_EQ(12u, SpdySynReplyControlFrame::size()); | |
57 EXPECT_EQ(16u, SpdyRstStreamControlFrame::size()); | |
58 EXPECT_EQ(12u, SpdySettingsControlFrame::size()); | |
59 EXPECT_EQ(12u, SpdyPingControlFrame::size()); | |
60 EXPECT_EQ(12u, SpdyGoAwayControlFrame::size()); | |
61 EXPECT_EQ(12u, SpdyHeadersControlFrame::size()); | |
62 EXPECT_EQ(16u, SpdyWindowUpdateControlFrame::size()); | |
63 EXPECT_EQ(4u, sizeof(FlagsAndLength)); | |
64 EXPECT_EQ(1, SYN_STREAM); | |
65 EXPECT_EQ(2, SYN_REPLY); | |
66 EXPECT_EQ(3, RST_STREAM); | |
67 EXPECT_EQ(4, SETTINGS); | |
68 EXPECT_EQ(5, NOOP); | |
69 EXPECT_EQ(6, PING); | |
70 EXPECT_EQ(7, GOAWAY); | |
71 EXPECT_EQ(8, HEADERS); | |
72 EXPECT_EQ(9, WINDOW_UPDATE); | |
73 } | |
74 | |
75 // Test some of the protocol helper functions | |
76 TEST(SpdyProtocolSpdy2Test, FrameStructs) { | |
77 SpdyFrame frame(SpdyFrame::kHeaderSize); | |
78 frame.set_length(12345); | |
79 frame.set_flags(10); | |
80 EXPECT_EQ(12345u, frame.length()); | |
81 EXPECT_EQ(10u, frame.flags()); | |
82 EXPECT_FALSE(frame.is_control_frame()); | |
83 | |
84 frame.set_length(0); | |
85 frame.set_flags(10); | |
86 EXPECT_EQ(0u, frame.length()); | |
87 EXPECT_EQ(10u, frame.flags()); | |
88 EXPECT_FALSE(frame.is_control_frame()); | |
89 } | |
90 | |
91 TEST(SpdyProtocolSpdy2Test, DataFrameStructs) { | |
92 SpdyDataFrame data_frame; | |
93 data_frame.set_stream_id(12345); | |
94 EXPECT_EQ(12345u, data_frame.stream_id()); | |
95 } | |
96 | |
97 TEST(SpdyProtocolSpdy2Test, ControlFrameStructs) { | |
98 SpdyFramer framer(SPDY_VERSION_FOR_TESTS); | |
99 SpdyHeaderBlock headers; | |
100 | |
101 scoped_ptr<SpdySynStreamControlFrame> syn_frame( | |
102 framer.CreateSynStream(123, 456, 2, CONTROL_FLAG_FIN, false, &headers)); | |
103 EXPECT_EQ(framer.protocol_version(), syn_frame->version()); | |
104 EXPECT_TRUE(syn_frame->is_control_frame()); | |
105 EXPECT_EQ(SYN_STREAM, syn_frame->type()); | |
106 EXPECT_EQ(123u, syn_frame->stream_id()); | |
107 EXPECT_EQ(456u, syn_frame->associated_stream_id()); | |
108 EXPECT_EQ(2u, syn_frame->priority()); | |
109 EXPECT_EQ((SPDY_VERSION_FOR_TESTS < 3) ? 2 : 4, | |
110 syn_frame->header_block_len()); | |
111 EXPECT_EQ(1u, syn_frame->flags()); | |
112 syn_frame->set_associated_stream_id(999u); | |
113 EXPECT_EQ(123u, syn_frame->stream_id()); | |
114 EXPECT_EQ(999u, syn_frame->associated_stream_id()); | |
115 | |
116 scoped_ptr<SpdySynReplyControlFrame> syn_reply( | |
117 framer.CreateSynReply(123, CONTROL_FLAG_NONE, false, &headers)); | |
118 EXPECT_EQ(framer.protocol_version(), syn_reply->version()); | |
119 EXPECT_TRUE(syn_reply->is_control_frame()); | |
120 EXPECT_EQ(SYN_REPLY, syn_reply->type()); | |
121 EXPECT_EQ(123u, syn_reply->stream_id()); | |
122 EXPECT_EQ((SPDY_VERSION_FOR_TESTS < 3) ? 2 : 4, | |
123 syn_reply->header_block_len()); | |
124 EXPECT_EQ(0, syn_reply->flags()); | |
125 | |
126 scoped_ptr<SpdyRstStreamControlFrame> rst_frame( | |
127 framer.CreateRstStream(123, spdy::PROTOCOL_ERROR)); | |
128 EXPECT_EQ(framer.protocol_version(), rst_frame->version()); | |
129 EXPECT_TRUE(rst_frame->is_control_frame()); | |
130 EXPECT_EQ(RST_STREAM, rst_frame->type()); | |
131 EXPECT_EQ(123u, rst_frame->stream_id()); | |
132 EXPECT_EQ(spdy::PROTOCOL_ERROR, rst_frame->status()); | |
133 rst_frame->set_status(spdy::INVALID_STREAM); | |
134 EXPECT_EQ(spdy::INVALID_STREAM, rst_frame->status()); | |
135 EXPECT_EQ(0, rst_frame->flags()); | |
136 | |
137 const uint32 kUniqueId = 1234567u; | |
138 const uint32 kUniqueId2 = 31415926u; | |
139 scoped_ptr<SpdyPingControlFrame> ping_frame( | |
140 framer.CreatePingFrame(kUniqueId)); | |
141 EXPECT_EQ(framer.protocol_version(), ping_frame->version()); | |
142 EXPECT_TRUE(ping_frame->is_control_frame()); | |
143 EXPECT_EQ(PING, ping_frame->type()); | |
144 EXPECT_EQ(kUniqueId, ping_frame->unique_id()); | |
145 ping_frame->set_unique_id(kUniqueId2); | |
146 EXPECT_EQ(kUniqueId2, ping_frame->unique_id()); | |
147 | |
148 scoped_ptr<SpdyGoAwayControlFrame> goaway_frame( | |
149 framer.CreateGoAway(123)); | |
150 EXPECT_EQ(framer.protocol_version(), goaway_frame->version()); | |
151 EXPECT_TRUE(goaway_frame->is_control_frame()); | |
152 EXPECT_EQ(GOAWAY, goaway_frame->type()); | |
153 EXPECT_EQ(123u, goaway_frame->last_accepted_stream_id()); | |
154 | |
155 scoped_ptr<SpdyHeadersControlFrame> headers_frame( | |
156 framer.CreateHeaders(123, CONTROL_FLAG_NONE, false, &headers)); | |
157 EXPECT_EQ(framer.protocol_version(), headers_frame->version()); | |
158 EXPECT_TRUE(headers_frame->is_control_frame()); | |
159 EXPECT_EQ(HEADERS, headers_frame->type()); | |
160 EXPECT_EQ(123u, headers_frame->stream_id()); | |
161 EXPECT_EQ((SPDY_VERSION_FOR_TESTS < 3) ? 2 : 4, | |
162 headers_frame->header_block_len()); | |
163 EXPECT_EQ(0, headers_frame->flags()); | |
164 | |
165 scoped_ptr<SpdyWindowUpdateControlFrame> window_update_frame( | |
166 framer.CreateWindowUpdate(123, 456)); | |
167 EXPECT_EQ(framer.protocol_version(), window_update_frame->version()); | |
168 EXPECT_TRUE(window_update_frame->is_control_frame()); | |
169 EXPECT_EQ(WINDOW_UPDATE, window_update_frame->type()); | |
170 EXPECT_EQ(123u, window_update_frame->stream_id()); | |
171 EXPECT_EQ(456u, window_update_frame->delta_window_size()); | |
172 } | |
173 | |
174 TEST(SpdyProtocolSpdy2Test, TestDataFrame) { | |
175 SpdyDataFrame frame; | |
176 | |
177 // Set the stream ID to various values. | |
178 frame.set_stream_id(0); | |
179 EXPECT_EQ(0u, frame.stream_id()); | |
180 EXPECT_FALSE(frame.is_control_frame()); | |
181 frame.set_stream_id(~0 & kStreamIdMask); | |
182 EXPECT_EQ(~0 & kStreamIdMask, frame.stream_id()); | |
183 EXPECT_FALSE(frame.is_control_frame()); | |
184 | |
185 // Set length to various values. Make sure that when you set_length(x), | |
186 // length() == x. Also make sure the flags are unaltered. | |
187 memset(frame.data(), '1', SpdyDataFrame::size()); | |
188 int8 flags = frame.flags(); | |
189 frame.set_length(0); | |
190 EXPECT_EQ(0u, frame.length()); | |
191 EXPECT_EQ(flags, frame.flags()); | |
192 frame.set_length(kLengthMask); | |
193 EXPECT_EQ(kLengthMask, frame.length()); | |
194 EXPECT_EQ(flags, frame.flags()); | |
195 frame.set_length(5u); | |
196 EXPECT_EQ(5u, frame.length()); | |
197 EXPECT_EQ(flags, frame.flags()); | |
198 | |
199 // Set flags to various values. Make sure that when you set_flags(x), | |
200 // flags() == x. Also make sure the length is unaltered. | |
201 memset(frame.data(), '1', SpdyDataFrame::size()); | |
202 uint32 length = frame.length(); | |
203 frame.set_flags(0u); | |
204 EXPECT_EQ(0u, frame.flags()); | |
205 EXPECT_EQ(length, frame.length()); | |
206 int8 all_flags = ~0; | |
207 frame.set_flags(all_flags); | |
208 flags = frame.flags(); | |
209 EXPECT_EQ(all_flags, flags); | |
210 EXPECT_EQ(length, frame.length()); | |
211 frame.set_flags(5u); | |
212 EXPECT_EQ(5u, frame.flags()); | |
213 EXPECT_EQ(length, frame.length()); | |
214 } | |
215 | |
216 // Test various types of SETTINGS frames. | |
217 TEST(SpdyProtocolSpdy2Test, TestSpdySettingsFrame) { | |
218 SpdyFramer framer(SPDY_VERSION_FOR_TESTS); | |
219 | |
220 // Create a settings frame with no settings. | |
221 SpdySettings settings; | |
222 scoped_ptr<SpdySettingsControlFrame> settings_frame( | |
223 framer.CreateSettings(settings)); | |
224 EXPECT_EQ(framer.protocol_version(), settings_frame->version()); | |
225 EXPECT_TRUE(settings_frame->is_control_frame()); | |
226 EXPECT_EQ(SETTINGS, settings_frame->type()); | |
227 EXPECT_EQ(0u, settings_frame->num_entries()); | |
228 | |
229 // We'll add several different ID/Flag combinations and then verify | |
230 // that they encode and decode properly. | |
231 SettingsFlagsAndId ids[] = { | |
232 SettingsFlagsAndId::FromWireFormat(SPDY_VERSION_FOR_TESTS, 0x00000000), | |
233 SettingsFlagsAndId::FromWireFormat(SPDY_VERSION_FOR_TESTS, 0xffffffff), | |
234 SettingsFlagsAndId::FromWireFormat(SPDY_VERSION_FOR_TESTS, 0xff000001), | |
235 SettingsFlagsAndId::FromWireFormat(SPDY_VERSION_FOR_TESTS, 0xffffffff), | |
236 SettingsFlagsAndId::FromWireFormat(SPDY_VERSION_FOR_TESTS, 0x01000002), | |
237 SettingsFlagsAndId(3, 1) | |
238 }; | |
239 | |
240 for (size_t index = 0; index < arraysize(ids); ++index) { | |
241 settings.insert(settings.end(), std::make_pair(ids[index], index)); | |
242 settings_frame.reset(framer.CreateSettings(settings)); | |
243 EXPECT_EQ(framer.protocol_version(), settings_frame->version()); | |
244 EXPECT_TRUE(settings_frame->is_control_frame()); | |
245 EXPECT_EQ(SETTINGS, settings_frame->type()); | |
246 EXPECT_EQ(index + 1, settings_frame->num_entries()); | |
247 | |
248 SpdySettings parsed_settings; | |
249 EXPECT_TRUE(framer.ParseSettings(settings_frame.get(), &parsed_settings)); | |
250 EXPECT_EQ(settings.size(), parsed_settings.size()); | |
251 SpdySettings::const_iterator it = parsed_settings.begin(); | |
252 int pos = 0; | |
253 while (it != parsed_settings.end()) { | |
254 SettingsFlagsAndId parsed = it->first; | |
255 uint32 value = it->second; | |
256 EXPECT_EQ(ids[pos].flags(), parsed.flags()); | |
257 EXPECT_EQ(ids[pos].id(), parsed.id()); | |
258 EXPECT_EQ(static_cast<uint32>(pos), value); | |
259 ++it; | |
260 ++pos; | |
261 } | |
262 } | |
263 } | |
264 | |
265 TEST(SpdyProtocolSpdy2Test, HasHeaderBlock) { | |
266 SpdyControlFrame frame(SpdyControlFrame::kHeaderSize); | |
267 for (SpdyControlType type = SYN_STREAM; | |
268 type < NUM_CONTROL_FRAME_TYPES; | |
269 type = static_cast<SpdyControlType>(type + 1)) { | |
270 frame.set_type(type); | |
271 if (type == SYN_STREAM || type == SYN_REPLY || type == HEADERS) { | |
272 EXPECT_TRUE(frame.has_header_block()); | |
273 } else { | |
274 EXPECT_FALSE(frame.has_header_block()); | |
275 } | |
276 } | |
277 } | |
278 | |
279 // Make sure that overflows both die in debug mode, and do not cause problems | |
280 // in opt mode. Note: The EXPECT_DEBUG_DEATH call does not work on Win32 yet, | |
281 // so we comment it out. | |
282 TEST(SpdyProtocolDeathSpdy2Test, TestDataFrame) { | |
283 SpdyDataFrame frame; | |
284 | |
285 frame.set_stream_id(0); | |
286 // TODO(mbelshe): implement EXPECT_DEBUG_DEATH on windows. | |
287 #if !defined(WIN32) && defined(GTEST_HAS_DEATH_TEST) | |
288 #if !defined(DCHECK_ALWAYS_ON) | |
289 EXPECT_DEBUG_DEATH(frame.set_stream_id(~0), ""); | |
290 #else | |
291 EXPECT_DEATH(frame.set_stream_id(~0), ""); | |
292 #endif | |
293 #endif | |
294 EXPECT_FALSE(frame.is_control_frame()); | |
295 | |
296 frame.set_flags(0); | |
297 #if !defined(WIN32) && defined(GTEST_HAS_DEATH_TEST) | |
298 #if !defined(DCHECK_ALWAYS_ON) | |
299 EXPECT_DEBUG_DEATH(frame.set_length(~0), ""); | |
300 #else | |
301 EXPECT_DEATH(frame.set_length(~0), ""); | |
302 #endif | |
303 #endif | |
304 EXPECT_EQ(0, frame.flags()); | |
305 } | |
306 | |
307 TEST(SpdyProtocolDeathSpdy2Test, TestSpdyControlFrameStreamId) { | |
308 SpdyControlFrame frame_store(SpdySynStreamControlFrame::size()); | |
309 memset(frame_store.data(), '1', SpdyControlFrame::kHeaderSize); | |
310 SpdySynStreamControlFrame* frame = | |
311 reinterpret_cast<SpdySynStreamControlFrame*>(&frame_store); | |
312 | |
313 // Set the stream ID to various values. | |
314 frame->set_stream_id(0); | |
315 EXPECT_EQ(0u, frame->stream_id()); | |
316 EXPECT_FALSE(frame->is_control_frame()); | |
317 frame->set_stream_id(kStreamIdMask); | |
318 EXPECT_EQ(kStreamIdMask, frame->stream_id()); | |
319 EXPECT_FALSE(frame->is_control_frame()); | |
320 } | |
321 | |
322 TEST(SpdyProtocolDeathSpdy2Test, TestSpdyControlFrameVersion) { | |
323 const unsigned int kVersionMask = 0x7fff; | |
324 SpdyControlFrame frame(SpdySynStreamControlFrame::size()); | |
325 memset(frame.data(), '1', SpdyControlFrame::kHeaderSize); | |
326 | |
327 // Set the version to various values, and make sure it does not affect the | |
328 // type. | |
329 frame.set_type(SYN_STREAM); | |
330 frame.set_version(0); | |
331 EXPECT_EQ(0, frame.version()); | |
332 EXPECT_TRUE(frame.is_control_frame()); | |
333 EXPECT_EQ(SYN_STREAM, frame.type()); | |
334 | |
335 SpdySynStreamControlFrame* syn_stream = | |
336 reinterpret_cast<SpdySynStreamControlFrame*>(&frame); | |
337 syn_stream->set_stream_id(~0 & kVersionMask); | |
338 EXPECT_EQ(~0 & kVersionMask, syn_stream->stream_id()); | |
339 EXPECT_TRUE(frame.is_control_frame()); | |
340 EXPECT_EQ(SYN_STREAM, frame.type()); | |
341 } | |
342 | |
343 TEST(SpdyProtocolDeathSpdy2Test, TestSpdyControlFrameType) { | |
344 SpdyControlFrame frame(SpdyControlFrame::kHeaderSize); | |
345 memset(frame.data(), 255, SpdyControlFrame::kHeaderSize); | |
346 | |
347 // type() should be out of bounds. | |
348 EXPECT_FALSE(frame.AppearsToBeAValidControlFrame()); | |
349 | |
350 frame.set_version(SPDY_VERSION_FOR_TESTS); | |
351 uint16 version = frame.version(); | |
352 | |
353 for (int i = SYN_STREAM; i <= spdy::WINDOW_UPDATE; ++i) { | |
354 frame.set_type(static_cast<SpdyControlType>(i)); | |
355 EXPECT_EQ(i, static_cast<int>(frame.type())); | |
356 EXPECT_TRUE(frame.AppearsToBeAValidControlFrame()); | |
357 // Make sure setting type does not alter the version block. | |
358 EXPECT_EQ(version, frame.version()); | |
359 EXPECT_TRUE(frame.is_control_frame()); | |
360 } | |
361 } | |
362 | |
363 TEST(SpdyProtocolDeathSpdy2Test, TestRstStreamStatusBounds) { | |
364 SpdyFramer framer(SPDY_VERSION_FOR_TESTS); | |
365 scoped_ptr<SpdyRstStreamControlFrame> rst_frame; | |
366 | |
367 rst_frame.reset(framer.CreateRstStream(123, spdy::PROTOCOL_ERROR)); | |
368 EXPECT_EQ(spdy::PROTOCOL_ERROR, rst_frame->status()); | |
369 | |
370 rst_frame->set_status(spdy::INVALID); | |
371 EXPECT_EQ(spdy::INVALID, rst_frame->status()); | |
372 | |
373 rst_frame->set_status( | |
374 static_cast<spdy::SpdyStatusCodes>(spdy::INVALID - 1)); | |
375 EXPECT_EQ(spdy::INVALID, rst_frame->status()); | |
376 | |
377 rst_frame->set_status(spdy::NUM_STATUS_CODES); | |
378 EXPECT_EQ(spdy::INVALID, rst_frame->status()); | |
379 } | |
380 | |
381 } // namespace | |
OLD | NEW |