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