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