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

Side by Side Diff: net/spdy/spdy_stream_unittest.cc

Issue 992733002: Remove //net (except for Android test stuff) and sdch (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 9 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/spdy_stream_test_util.cc ('k') | net/spdy/spdy_test_util_common.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 2013 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 <cstddef>
6 #include <string>
7 #include <vector>
8
9 #include "base/memory/ref_counted.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/stl_util.h"
12 #include "base/strings/string_piece.h"
13 #include "net/base/completion_callback.h"
14 #include "net/base/net_log_unittest.h"
15 #include "net/base/request_priority.h"
16 #include "net/socket/next_proto.h"
17 #include "net/socket/socket_test_util.h"
18 #include "net/spdy/buffered_spdy_framer.h"
19 #include "net/spdy/spdy_http_utils.h"
20 #include "net/spdy/spdy_protocol.h"
21 #include "net/spdy/spdy_session.h"
22 #include "net/spdy/spdy_stream.h"
23 #include "net/spdy/spdy_stream_test_util.h"
24 #include "net/spdy/spdy_test_util_common.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26
27 // TODO(ukai): factor out common part with spdy_http_stream_unittest.cc
28 //
29 namespace net {
30
31 namespace test {
32
33 namespace {
34
35 const char kStreamUrl[] = "http://www.google.com/";
36 const char kPostBody[] = "\0hello!\xff";
37 const size_t kPostBodyLength = arraysize(kPostBody);
38 const base::StringPiece kPostBodyStringPiece(kPostBody, kPostBodyLength);
39
40 class SpdyStreamTest : public ::testing::Test,
41 public ::testing::WithParamInterface<NextProto> {
42 protected:
43 // A function that takes a SpdyStream and the number of bytes which
44 // will unstall the next frame completely.
45 typedef base::Callback<void(const base::WeakPtr<SpdyStream>&, int32)>
46 UnstallFunction;
47
48 SpdyStreamTest()
49 : spdy_util_(GetParam()),
50 session_deps_(GetParam()),
51 offset_(0) {}
52
53 base::WeakPtr<SpdySession> CreateDefaultSpdySession() {
54 SpdySessionKey key(HostPortPair("www.google.com", 80),
55 ProxyServer::Direct(),
56 PRIVACY_MODE_DISABLED);
57 return CreateInsecureSpdySession(session_, key, BoundNetLog());
58 }
59
60 void TearDown() override { base::MessageLoop::current()->RunUntilIdle(); }
61
62 void RunResumeAfterUnstallRequestResponseTest(
63 const UnstallFunction& unstall_function);
64
65 void RunResumeAfterUnstallBidirectionalTest(
66 const UnstallFunction& unstall_function);
67
68 // Add{Read,Write}() populates lists that are eventually passed to a
69 // SocketData class. |frame| must live for the whole test.
70
71 void AddRead(const SpdyFrame& frame) {
72 reads_.push_back(CreateMockRead(frame, offset_++));
73 }
74
75 void AddWrite(const SpdyFrame& frame) {
76 writes_.push_back(CreateMockWrite(frame, offset_++));
77 }
78
79 void AddReadEOF() {
80 reads_.push_back(MockRead(ASYNC, 0, offset_++));
81 }
82
83 MockRead* GetReads() {
84 return vector_as_array(&reads_);
85 }
86
87 size_t GetNumReads() const {
88 return reads_.size();
89 }
90
91 MockWrite* GetWrites() {
92 return vector_as_array(&writes_);
93 }
94
95 int GetNumWrites() const {
96 return writes_.size();
97 }
98
99 SpdyTestUtil spdy_util_;
100 SpdySessionDependencies session_deps_;
101 scoped_refptr<HttpNetworkSession> session_;
102
103 private:
104 // Used by Add{Read,Write}() above.
105 std::vector<MockWrite> writes_;
106 std::vector<MockRead> reads_;
107 int offset_;
108 };
109
110 INSTANTIATE_TEST_CASE_P(
111 NextProto,
112 SpdyStreamTest,
113 testing::Values(kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
114
115 TEST_P(SpdyStreamTest, SendDataAfterOpen) {
116 GURL url(kStreamUrl);
117
118 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
119
120 scoped_ptr<SpdyFrame> req(
121 spdy_util_.ConstructSpdyPost(
122 kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
123 AddWrite(*req);
124
125 scoped_ptr<SpdyFrame> resp(
126 spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
127 AddRead(*resp);
128
129 scoped_ptr<SpdyFrame> msg(
130 spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
131 AddWrite(*msg);
132
133 scoped_ptr<SpdyFrame> echo(
134 spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
135 AddRead(*echo);
136
137 AddReadEOF();
138
139 OrderedSocketData data(GetReads(), GetNumReads(),
140 GetWrites(), GetNumWrites());
141 MockConnect connect_data(SYNCHRONOUS, OK);
142 data.set_connect_data(connect_data);
143
144 session_deps_.socket_factory->AddSocketDataProvider(&data);
145
146 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
147
148 base::WeakPtr<SpdyStream> stream =
149 CreateStreamSynchronously(
150 SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, BoundNetLog());
151 ASSERT_TRUE(stream.get() != NULL);
152
153 StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
154 stream->SetDelegate(&delegate);
155
156 EXPECT_FALSE(stream->HasUrlFromHeaders());
157
158 scoped_ptr<SpdyHeaderBlock> headers(
159 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
160 EXPECT_EQ(ERR_IO_PENDING,
161 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
162 EXPECT_TRUE(stream->HasUrlFromHeaders());
163 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
164
165 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
166
167 EXPECT_TRUE(delegate.send_headers_completed());
168 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
169 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
170 delegate.TakeReceivedData());
171 EXPECT_TRUE(data.at_write_eof());
172 }
173
174 TEST_P(SpdyStreamTest, PushedStream) {
175 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
176
177 AddReadEOF();
178
179 OrderedSocketData data(GetReads(), GetNumReads(),
180 GetWrites(), GetNumWrites());
181 MockConnect connect_data(SYNCHRONOUS, OK);
182 data.set_connect_data(connect_data);
183
184 session_deps_.socket_factory->AddSocketDataProvider(&data);
185
186 base::WeakPtr<SpdySession> spdy_session(CreateDefaultSpdySession());
187
188 // Conjure up a stream.
189 SpdyStream stream(SPDY_PUSH_STREAM, spdy_session, GURL(), DEFAULT_PRIORITY,
190 SpdySession::GetInitialWindowSize(kProtoSPDY31),
191 SpdySession::GetInitialWindowSize(kProtoSPDY31),
192 BoundNetLog());
193 stream.set_stream_id(2);
194 EXPECT_FALSE(stream.HasUrlFromHeaders());
195
196 // Set required request headers.
197 SpdyHeaderBlock request_headers;
198 spdy_util_.AddUrlToHeaderBlock(kStreamUrl, &request_headers);
199 stream.OnPushPromiseHeadersReceived(request_headers);
200
201 // Send some basic response headers.
202 SpdyHeaderBlock response;
203 response[spdy_util_.GetStatusKey()] = "200";
204 response[spdy_util_.GetVersionKey()] = "OK";
205 stream.OnInitialResponseHeadersReceived(
206 response, base::Time::Now(), base::TimeTicks::Now());
207
208 // And some more headers.
209 // TODO(baranovich): not valid for HTTP 2.
210 SpdyHeaderBlock headers;
211 headers["alpha"] = "beta";
212 stream.OnAdditionalResponseHeadersReceived(headers);
213
214 EXPECT_TRUE(stream.HasUrlFromHeaders());
215 EXPECT_EQ(kStreamUrl, stream.GetUrlFromHeaders().spec());
216
217 StreamDelegateDoNothing delegate(stream.GetWeakPtr());
218 stream.SetDelegate(&delegate);
219
220 base::MessageLoop::current()->RunUntilIdle();
221
222 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
223 EXPECT_EQ("beta", delegate.GetResponseHeaderValue("alpha"));
224
225 EXPECT_TRUE(spdy_session == NULL);
226 }
227
228 TEST_P(SpdyStreamTest, StreamError) {
229 GURL url(kStreamUrl);
230
231 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
232
233 scoped_ptr<SpdyFrame> req(
234 spdy_util_.ConstructSpdyPost(
235 kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
236 AddWrite(*req);
237
238 scoped_ptr<SpdyFrame> resp(
239 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
240 AddRead(*resp);
241
242 scoped_ptr<SpdyFrame> msg(
243 spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
244 AddWrite(*msg);
245
246 scoped_ptr<SpdyFrame> echo(
247 spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
248 AddRead(*echo);
249
250 AddReadEOF();
251
252 CapturingBoundNetLog log;
253
254 OrderedSocketData data(GetReads(), GetNumReads(),
255 GetWrites(), GetNumWrites());
256 MockConnect connect_data(SYNCHRONOUS, OK);
257 data.set_connect_data(connect_data);
258
259 session_deps_.socket_factory->AddSocketDataProvider(&data);
260
261 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
262
263 base::WeakPtr<SpdyStream> stream =
264 CreateStreamSynchronously(
265 SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, log.bound());
266 ASSERT_TRUE(stream.get() != NULL);
267
268 StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
269 stream->SetDelegate(&delegate);
270
271 EXPECT_FALSE(stream->HasUrlFromHeaders());
272
273 scoped_ptr<SpdyHeaderBlock> headers(
274 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
275 EXPECT_EQ(ERR_IO_PENDING,
276 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
277 EXPECT_TRUE(stream->HasUrlFromHeaders());
278 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
279
280 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
281
282 const SpdyStreamId stream_id = delegate.stream_id();
283
284 EXPECT_TRUE(delegate.send_headers_completed());
285 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
286 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
287 delegate.TakeReceivedData());
288 EXPECT_TRUE(data.at_write_eof());
289
290 // Check that the NetLog was filled reasonably.
291 net::CapturingNetLog::CapturedEntryList entries;
292 log.GetEntries(&entries);
293 EXPECT_LT(0u, entries.size());
294
295 // Check that we logged SPDY_STREAM_ERROR correctly.
296 int pos = net::ExpectLogContainsSomewhere(
297 entries, 0,
298 net::NetLog::TYPE_SPDY_STREAM_ERROR,
299 net::NetLog::PHASE_NONE);
300
301 int stream_id2;
302 ASSERT_TRUE(entries[pos].GetIntegerValue("stream_id", &stream_id2));
303 EXPECT_EQ(static_cast<int>(stream_id), stream_id2);
304 }
305
306 // Make sure that large blocks of data are properly split up into
307 // frame-sized chunks for a request/response (i.e., an HTTP-like)
308 // stream.
309 TEST_P(SpdyStreamTest, SendLargeDataAfterOpenRequestResponse) {
310 GURL url(kStreamUrl);
311
312 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
313
314 scoped_ptr<SpdyFrame> req(
315 spdy_util_.ConstructSpdyPost(
316 kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
317 AddWrite(*req);
318
319 std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
320 scoped_ptr<SpdyFrame> chunk(
321 spdy_util_.ConstructSpdyBodyFrame(
322 1, chunk_data.data(), chunk_data.length(), false));
323 AddWrite(*chunk);
324 AddWrite(*chunk);
325
326 scoped_ptr<SpdyFrame> last_chunk(
327 spdy_util_.ConstructSpdyBodyFrame(
328 1, chunk_data.data(), chunk_data.length(), true));
329 AddWrite(*last_chunk);
330
331 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
332 AddRead(*resp);
333
334 AddReadEOF();
335
336 OrderedSocketData data(GetReads(), GetNumReads(),
337 GetWrites(), GetNumWrites());
338 MockConnect connect_data(SYNCHRONOUS, OK);
339 data.set_connect_data(connect_data);
340
341 session_deps_.socket_factory->AddSocketDataProvider(&data);
342
343 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
344
345 base::WeakPtr<SpdyStream> stream =
346 CreateStreamSynchronously(
347 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
348 ASSERT_TRUE(stream.get() != NULL);
349
350 std::string body_data(3 * kMaxSpdyFrameChunkSize, 'x');
351 StreamDelegateWithBody delegate(stream, body_data);
352 stream->SetDelegate(&delegate);
353
354 EXPECT_FALSE(stream->HasUrlFromHeaders());
355
356 scoped_ptr<SpdyHeaderBlock> headers(
357 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
358 EXPECT_EQ(ERR_IO_PENDING,
359 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
360 EXPECT_TRUE(stream->HasUrlFromHeaders());
361 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
362
363 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
364
365 EXPECT_TRUE(delegate.send_headers_completed());
366 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
367 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
368 EXPECT_TRUE(data.at_write_eof());
369 }
370
371 // Make sure that large blocks of data are properly split up into
372 // frame-sized chunks for a bidirectional (i.e., non-HTTP-like)
373 // stream.
374 TEST_P(SpdyStreamTest, SendLargeDataAfterOpenBidirectional) {
375 GURL url(kStreamUrl);
376
377 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
378
379 scoped_ptr<SpdyFrame> req(
380 spdy_util_.ConstructSpdyPost(
381 kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
382 AddWrite(*req);
383
384 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
385 AddRead(*resp);
386
387 std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
388 scoped_ptr<SpdyFrame> chunk(
389 spdy_util_.ConstructSpdyBodyFrame(
390 1, chunk_data.data(), chunk_data.length(), false));
391 AddWrite(*chunk);
392 AddWrite(*chunk);
393 AddWrite(*chunk);
394
395 AddReadEOF();
396
397 OrderedSocketData data(GetReads(), GetNumReads(),
398 GetWrites(), GetNumWrites());
399 MockConnect connect_data(SYNCHRONOUS, OK);
400 data.set_connect_data(connect_data);
401
402 session_deps_.socket_factory->AddSocketDataProvider(&data);
403
404 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
405
406 base::WeakPtr<SpdyStream> stream =
407 CreateStreamSynchronously(
408 SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, BoundNetLog());
409 ASSERT_TRUE(stream.get() != NULL);
410
411 std::string body_data(3 * kMaxSpdyFrameChunkSize, 'x');
412 StreamDelegateSendImmediate delegate(stream, body_data);
413 stream->SetDelegate(&delegate);
414
415 EXPECT_FALSE(stream->HasUrlFromHeaders());
416
417 scoped_ptr<SpdyHeaderBlock> headers(
418 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
419 EXPECT_EQ(ERR_IO_PENDING,
420 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
421 EXPECT_TRUE(stream->HasUrlFromHeaders());
422 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
423
424 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
425
426 EXPECT_TRUE(delegate.send_headers_completed());
427 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
428 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
429 EXPECT_TRUE(data.at_write_eof());
430 }
431
432 // Receiving a header with uppercase ASCII should result in a protocol
433 // error.
434 TEST_P(SpdyStreamTest, UpperCaseHeaders) {
435 GURL url(kStreamUrl);
436
437 session_ =
438 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
439
440 scoped_ptr<SpdyFrame> syn(
441 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
442 AddWrite(*syn);
443
444 const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
445 scoped_ptr<SpdyFrame>
446 reply(spdy_util_.ConstructSpdyGetSynReply(kExtraHeaders, 1, 1));
447 AddRead(*reply);
448
449 scoped_ptr<SpdyFrame> rst(
450 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
451 AddWrite(*rst);
452
453 AddReadEOF();
454
455 DeterministicSocketData data(GetReads(), GetNumReads(),
456 GetWrites(), GetNumWrites());
457 MockConnect connect_data(SYNCHRONOUS, OK);
458 data.set_connect_data(connect_data);
459
460 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
461
462 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
463
464 base::WeakPtr<SpdyStream> stream =
465 CreateStreamSynchronously(
466 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
467 ASSERT_TRUE(stream.get() != NULL);
468
469 StreamDelegateDoNothing delegate(stream);
470 stream->SetDelegate(&delegate);
471
472 EXPECT_FALSE(stream->HasUrlFromHeaders());
473
474 scoped_ptr<SpdyHeaderBlock> headers(
475 spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
476 EXPECT_EQ(ERR_IO_PENDING,
477 stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
478 EXPECT_TRUE(stream->HasUrlFromHeaders());
479 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
480
481 data.RunFor(4);
482
483 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, delegate.WaitForClose());
484 }
485
486 // Receiving a header with uppercase ASCII should result in a protocol
487 // error even for a push stream.
488 TEST_P(SpdyStreamTest, UpperCaseHeadersOnPush) {
489 GURL url(kStreamUrl);
490
491 session_ =
492 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
493
494 scoped_ptr<SpdyFrame> syn(
495 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
496 AddWrite(*syn);
497
498 scoped_ptr<SpdyFrame>
499 reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
500 AddRead(*reply);
501
502 const char* const extra_headers[] = {"X-UpperCase", "yes"};
503 scoped_ptr<SpdyFrame>
504 push(spdy_util_.ConstructSpdyPush(extra_headers, 1, 2, 1, kStreamUrl));
505 AddRead(*push);
506
507 scoped_ptr<SpdyFrame> rst(
508 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
509 AddWrite(*rst);
510
511 AddReadEOF();
512
513 DeterministicSocketData data(GetReads(), GetNumReads(),
514 GetWrites(), GetNumWrites());
515 MockConnect connect_data(SYNCHRONOUS, OK);
516 data.set_connect_data(connect_data);
517
518 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
519
520 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
521
522 base::WeakPtr<SpdyStream> stream =
523 CreateStreamSynchronously(
524 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
525 ASSERT_TRUE(stream.get() != NULL);
526
527 StreamDelegateDoNothing delegate(stream);
528 stream->SetDelegate(&delegate);
529
530 EXPECT_FALSE(stream->HasUrlFromHeaders());
531
532 scoped_ptr<SpdyHeaderBlock> headers(
533 spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
534 EXPECT_EQ(ERR_IO_PENDING,
535 stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
536 EXPECT_TRUE(stream->HasUrlFromHeaders());
537 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
538
539 data.RunFor(4);
540
541 base::WeakPtr<SpdyStream> push_stream;
542 EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
543 EXPECT_FALSE(push_stream);
544
545 data.RunFor(1);
546
547 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
548 }
549
550 // Receiving a header with uppercase ASCII in a HEADERS frame should
551 // result in a protocol error.
552 TEST_P(SpdyStreamTest, UpperCaseHeadersInHeadersFrame) {
553 GURL url(kStreamUrl);
554
555 session_ =
556 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
557
558 scoped_ptr<SpdyFrame> syn(
559 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
560 AddWrite(*syn);
561
562 scoped_ptr<SpdyFrame>
563 reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
564 AddRead(*reply);
565
566 scoped_ptr<SpdyFrame>
567 push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl));
568 AddRead(*push);
569
570 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
571 (*late_headers)["X-UpperCase"] = "yes";
572 scoped_ptr<SpdyFrame> headers_frame(
573 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
574 false,
575 2,
576 LOWEST,
577 HEADERS,
578 CONTROL_FLAG_NONE,
579 0));
580 AddRead(*headers_frame);
581
582 scoped_ptr<SpdyFrame> rst(
583 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
584 AddWrite(*rst);
585
586 AddReadEOF();
587
588 DeterministicSocketData data(GetReads(), GetNumReads(),
589 GetWrites(), GetNumWrites());
590 MockConnect connect_data(SYNCHRONOUS, OK);
591 data.set_connect_data(connect_data);
592
593 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
594
595 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
596
597 base::WeakPtr<SpdyStream> stream =
598 CreateStreamSynchronously(
599 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
600 ASSERT_TRUE(stream.get() != NULL);
601
602 StreamDelegateDoNothing delegate(stream);
603 stream->SetDelegate(&delegate);
604
605 EXPECT_FALSE(stream->HasUrlFromHeaders());
606
607 scoped_ptr<SpdyHeaderBlock> headers(
608 spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
609 EXPECT_EQ(ERR_IO_PENDING,
610 stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
611 EXPECT_TRUE(stream->HasUrlFromHeaders());
612 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
613
614 data.RunFor(3);
615
616 base::WeakPtr<SpdyStream> push_stream;
617 EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
618 EXPECT_TRUE(push_stream);
619
620 data.RunFor(1);
621
622 EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
623 EXPECT_FALSE(push_stream);
624
625 data.RunFor(2);
626
627 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
628 }
629
630 // Receiving a duplicate header in a HEADERS frame should result in a
631 // protocol error.
632 TEST_P(SpdyStreamTest, DuplicateHeaders) {
633 GURL url(kStreamUrl);
634
635 session_ =
636 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
637
638 scoped_ptr<SpdyFrame> syn(
639 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
640 AddWrite(*syn);
641
642 scoped_ptr<SpdyFrame>
643 reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
644 AddRead(*reply);
645
646 scoped_ptr<SpdyFrame>
647 push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl));
648 AddRead(*push);
649
650 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
651 (*late_headers)[spdy_util_.GetStatusKey()] = "500 Server Error";
652 scoped_ptr<SpdyFrame> headers_frame(
653 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
654 false,
655 2,
656 LOWEST,
657 HEADERS,
658 CONTROL_FLAG_NONE,
659 0));
660 AddRead(*headers_frame);
661
662 scoped_ptr<SpdyFrame> rst(
663 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
664 AddWrite(*rst);
665
666 AddReadEOF();
667
668 DeterministicSocketData data(GetReads(), GetNumReads(),
669 GetWrites(), GetNumWrites());
670 MockConnect connect_data(SYNCHRONOUS, OK);
671 data.set_connect_data(connect_data);
672
673 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
674
675 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
676
677 base::WeakPtr<SpdyStream> stream =
678 CreateStreamSynchronously(
679 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
680 ASSERT_TRUE(stream.get() != NULL);
681
682 StreamDelegateDoNothing delegate(stream);
683 stream->SetDelegate(&delegate);
684
685 EXPECT_FALSE(stream->HasUrlFromHeaders());
686
687 scoped_ptr<SpdyHeaderBlock> headers(
688 spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
689 EXPECT_EQ(ERR_IO_PENDING,
690 stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
691 EXPECT_TRUE(stream->HasUrlFromHeaders());
692 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
693
694 data.RunFor(3);
695
696 base::WeakPtr<SpdyStream> push_stream;
697 EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
698 EXPECT_TRUE(push_stream);
699
700 data.RunFor(1);
701
702 EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
703 EXPECT_FALSE(push_stream);
704
705 data.RunFor(2);
706
707 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
708 }
709
710 // The tests below are only for SPDY/3 and above.
711
712 // Call IncreaseSendWindowSize on a stream with a large enough delta
713 // to overflow an int32. The SpdyStream should handle that case
714 // gracefully.
715 TEST_P(SpdyStreamTest, IncreaseSendWindowSizeOverflow) {
716 session_ =
717 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
718
719 scoped_ptr<SpdyFrame> req(
720 spdy_util_.ConstructSpdyPost(
721 kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
722 AddWrite(*req);
723
724 // Triggered by the overflowing call to IncreaseSendWindowSize
725 // below.
726 scoped_ptr<SpdyFrame> rst(
727 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
728 AddWrite(*rst);
729
730 AddReadEOF();
731
732 CapturingBoundNetLog log;
733
734 DeterministicSocketData data(GetReads(), GetNumReads(),
735 GetWrites(), GetNumWrites());
736 MockConnect connect_data(SYNCHRONOUS, OK);
737 data.set_connect_data(connect_data);
738
739 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
740
741 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
742 GURL url(kStreamUrl);
743
744 base::WeakPtr<SpdyStream> stream =
745 CreateStreamSynchronously(
746 SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, log.bound());
747 ASSERT_TRUE(stream.get() != NULL);
748 StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
749 stream->SetDelegate(&delegate);
750
751 scoped_ptr<SpdyHeaderBlock> headers(
752 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
753 EXPECT_EQ(ERR_IO_PENDING,
754 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
755 EXPECT_TRUE(stream->HasUrlFromHeaders());
756 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
757
758 data.RunFor(1);
759
760 int32 old_send_window_size = stream->send_window_size();
761 ASSERT_GT(old_send_window_size, 0);
762 int32 delta_window_size = kint32max - old_send_window_size + 1;
763 stream->IncreaseSendWindowSize(delta_window_size);
764 EXPECT_EQ(NULL, stream.get());
765
766 data.RunFor(2);
767
768 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, delegate.WaitForClose());
769 }
770
771 // Functions used with
772 // RunResumeAfterUnstall{RequestResponse,Bidirectional}Test().
773
774 void StallStream(const base::WeakPtr<SpdyStream>& stream) {
775 // Reduce the send window size to 0 to stall.
776 while (stream->send_window_size() > 0) {
777 stream->DecreaseSendWindowSize(
778 std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
779 }
780 }
781
782 void IncreaseStreamSendWindowSize(const base::WeakPtr<SpdyStream>& stream,
783 int32 delta_window_size) {
784 EXPECT_TRUE(stream->send_stalled_by_flow_control());
785 stream->IncreaseSendWindowSize(delta_window_size);
786 EXPECT_FALSE(stream->send_stalled_by_flow_control());
787 }
788
789 void AdjustStreamSendWindowSize(const base::WeakPtr<SpdyStream>& stream,
790 int32 delta_window_size) {
791 // Make sure that negative adjustments are handled properly.
792 EXPECT_TRUE(stream->send_stalled_by_flow_control());
793 stream->AdjustSendWindowSize(-delta_window_size);
794 EXPECT_TRUE(stream->send_stalled_by_flow_control());
795 stream->AdjustSendWindowSize(+delta_window_size);
796 EXPECT_TRUE(stream->send_stalled_by_flow_control());
797 stream->AdjustSendWindowSize(+delta_window_size);
798 EXPECT_FALSE(stream->send_stalled_by_flow_control());
799 }
800
801 // Given an unstall function, runs a test to make sure that a
802 // request/response (i.e., an HTTP-like) stream resumes after a stall
803 // and unstall.
804 void SpdyStreamTest::RunResumeAfterUnstallRequestResponseTest(
805 const UnstallFunction& unstall_function) {
806 GURL url(kStreamUrl);
807
808 session_ =
809 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
810
811 scoped_ptr<SpdyFrame> req(
812 spdy_util_.ConstructSpdyPost(
813 kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
814 AddWrite(*req);
815
816 scoped_ptr<SpdyFrame> body(
817 spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, true));
818 AddWrite(*body);
819
820 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
821 AddRead(*resp);
822
823 AddReadEOF();
824
825 DeterministicSocketData data(GetReads(), GetNumReads(),
826 GetWrites(), GetNumWrites());
827 MockConnect connect_data(SYNCHRONOUS, OK);
828 data.set_connect_data(connect_data);
829
830 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
831
832 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
833
834 base::WeakPtr<SpdyStream> stream =
835 CreateStreamSynchronously(
836 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
837 ASSERT_TRUE(stream.get() != NULL);
838
839 StreamDelegateWithBody delegate(stream, kPostBodyStringPiece);
840 stream->SetDelegate(&delegate);
841
842 EXPECT_FALSE(stream->HasUrlFromHeaders());
843 EXPECT_FALSE(stream->send_stalled_by_flow_control());
844
845 scoped_ptr<SpdyHeaderBlock> headers(
846 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
847 EXPECT_EQ(ERR_IO_PENDING,
848 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
849 EXPECT_TRUE(stream->HasUrlFromHeaders());
850 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
851
852 StallStream(stream);
853
854 data.RunFor(1);
855
856 EXPECT_TRUE(stream->send_stalled_by_flow_control());
857
858 unstall_function.Run(stream, kPostBodyLength);
859
860 EXPECT_FALSE(stream->send_stalled_by_flow_control());
861
862 data.RunFor(3);
863
864 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
865
866 EXPECT_TRUE(delegate.send_headers_completed());
867 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
868 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
869 EXPECT_TRUE(data.at_write_eof());
870 }
871
872 TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseRequestResponse) {
873 RunResumeAfterUnstallRequestResponseTest(
874 base::Bind(&IncreaseStreamSendWindowSize));
875 }
876
877 TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustRequestResponse) {
878 RunResumeAfterUnstallRequestResponseTest(
879 base::Bind(&AdjustStreamSendWindowSize));
880 }
881
882 // Given an unstall function, runs a test to make sure that a
883 // bidirectional (i.e., non-HTTP-like) stream resumes after a stall
884 // and unstall.
885 void SpdyStreamTest::RunResumeAfterUnstallBidirectionalTest(
886 const UnstallFunction& unstall_function) {
887 GURL url(kStreamUrl);
888
889 session_ =
890 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
891
892 scoped_ptr<SpdyFrame> req(
893 spdy_util_.ConstructSpdyPost(
894 kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
895 AddWrite(*req);
896
897 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
898 AddRead(*resp);
899
900 scoped_ptr<SpdyFrame> msg(
901 spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
902 AddWrite(*msg);
903
904 scoped_ptr<SpdyFrame> echo(
905 spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
906 AddRead(*echo);
907
908 AddReadEOF();
909
910 DeterministicSocketData data(GetReads(), GetNumReads(),
911 GetWrites(), GetNumWrites());
912 MockConnect connect_data(SYNCHRONOUS, OK);
913 data.set_connect_data(connect_data);
914
915 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
916
917 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
918
919 base::WeakPtr<SpdyStream> stream =
920 CreateStreamSynchronously(
921 SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, BoundNetLog());
922 ASSERT_TRUE(stream.get() != NULL);
923
924 StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
925 stream->SetDelegate(&delegate);
926
927 EXPECT_FALSE(stream->HasUrlFromHeaders());
928
929 scoped_ptr<SpdyHeaderBlock> headers(
930 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
931 EXPECT_EQ(ERR_IO_PENDING,
932 stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
933 EXPECT_TRUE(stream->HasUrlFromHeaders());
934 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
935
936 data.RunFor(1);
937
938 EXPECT_FALSE(stream->send_stalled_by_flow_control());
939
940 StallStream(stream);
941
942 data.RunFor(1);
943
944 EXPECT_TRUE(stream->send_stalled_by_flow_control());
945
946 unstall_function.Run(stream, kPostBodyLength);
947
948 EXPECT_FALSE(stream->send_stalled_by_flow_control());
949
950 data.RunFor(3);
951
952 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
953
954 EXPECT_TRUE(delegate.send_headers_completed());
955 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
956 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
957 delegate.TakeReceivedData());
958 EXPECT_TRUE(data.at_write_eof());
959 }
960
961 TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseBidirectional) {
962 RunResumeAfterUnstallBidirectionalTest(
963 base::Bind(&IncreaseStreamSendWindowSize));
964 }
965
966 TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustBidirectional) {
967 RunResumeAfterUnstallBidirectionalTest(
968 base::Bind(&AdjustStreamSendWindowSize));
969 }
970
971 // Test calculation of amount of bytes received from network.
972 TEST_P(SpdyStreamTest, ReceivedBytes) {
973 GURL url(kStreamUrl);
974
975 session_ =
976 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
977
978 scoped_ptr<SpdyFrame> syn(
979 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
980 AddWrite(*syn);
981
982 scoped_ptr<SpdyFrame>
983 reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
984 AddRead(*reply);
985
986 scoped_ptr<SpdyFrame> msg(
987 spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
988 AddRead(*msg);
989
990 AddReadEOF();
991
992 DeterministicSocketData data(GetReads(), GetNumReads(),
993 GetWrites(), GetNumWrites());
994 MockConnect connect_data(SYNCHRONOUS, OK);
995 data.set_connect_data(connect_data);
996
997 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
998
999 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1000
1001 base::WeakPtr<SpdyStream> stream =
1002 CreateStreamSynchronously(
1003 SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
1004 ASSERT_TRUE(stream.get() != NULL);
1005
1006 StreamDelegateDoNothing delegate(stream);
1007 stream->SetDelegate(&delegate);
1008
1009 EXPECT_FALSE(stream->HasUrlFromHeaders());
1010
1011 scoped_ptr<SpdyHeaderBlock> headers(
1012 spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
1013 EXPECT_EQ(ERR_IO_PENDING,
1014 stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
1015 EXPECT_TRUE(stream->HasUrlFromHeaders());
1016 EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
1017
1018 int64 reply_frame_len = reply->size();
1019 int64 data_header_len = spdy_util_.CreateFramer(false)
1020 ->GetDataFrameMinimumSize();
1021 int64 data_frame_len = data_header_len + kPostBodyLength;
1022 int64 response_len = reply_frame_len + data_frame_len;
1023
1024 EXPECT_EQ(0, stream->raw_received_bytes());
1025 data.RunFor(1); // SYN
1026 EXPECT_EQ(0, stream->raw_received_bytes());
1027 data.RunFor(1); // REPLY
1028 EXPECT_EQ(reply_frame_len, stream->raw_received_bytes());
1029 data.RunFor(1); // DATA
1030 EXPECT_EQ(response_len, stream->raw_received_bytes());
1031 data.RunFor(1); // FIN
1032
1033 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
1034 }
1035
1036 } // namespace
1037
1038 } // namespace test
1039
1040 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/spdy_stream_test_util.cc ('k') | net/spdy/spdy_test_util_common.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698