Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / net / quic / quic_session_test.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/quic/quic_session.h"
6
7 #include <set>
8 #include <vector>
9
10 #include "base/basictypes.h"
11 #include "base/containers/hash_tables.h"
12 #include "net/quic/crypto/crypto_protocol.h"
13 #include "net/quic/quic_crypto_stream.h"
14 #include "net/quic/quic_flags.h"
15 #include "net/quic/quic_protocol.h"
16 #include "net/quic/quic_utils.h"
17 #include "net/quic/reliable_quic_stream.h"
18 #include "net/quic/test_tools/quic_connection_peer.h"
19 #include "net/quic/test_tools/quic_data_stream_peer.h"
20 #include "net/quic/test_tools/quic_session_peer.h"
21 #include "net/quic/test_tools/quic_test_utils.h"
22 #include "net/quic/test_tools/reliable_quic_stream_peer.h"
23 #include "net/spdy/spdy_framer.h"
24 #include "net/test/gtest_util.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27
28 using base::hash_map;
29 using std::set;
30 using std::vector;
31 using testing::_;
32 using testing::InSequence;
33 using testing::InvokeWithoutArgs;
34 using testing::Return;
35 using testing::StrictMock;
36
37 namespace net {
38 namespace test {
39 namespace {
40
41 const QuicPriority kHighestPriority = 0;
42 const QuicPriority kSomeMiddlePriority = 3;
43
44 class TestCryptoStream : public QuicCryptoStream {
45  public:
46   explicit TestCryptoStream(QuicSession* session)
47       : QuicCryptoStream(session) {
48   }
49
50   virtual void OnHandshakeMessage(
51       const CryptoHandshakeMessage& message) OVERRIDE {
52     encryption_established_ = true;
53     handshake_confirmed_ = true;
54     CryptoHandshakeMessage msg;
55     string error_details;
56     session()->config()->SetInitialFlowControlWindowToSend(
57         kInitialFlowControlWindowForTest);
58     session()->config()->ToHandshakeMessage(&msg);
59     const QuicErrorCode error = session()->config()->ProcessPeerHello(
60         msg, CLIENT, &error_details);
61     EXPECT_EQ(QUIC_NO_ERROR, error);
62     session()->OnConfigNegotiated();
63     session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
64   }
65
66   MOCK_METHOD0(OnCanWrite, void());
67 };
68
69 class TestStream : public QuicDataStream {
70  public:
71   TestStream(QuicStreamId id, QuicSession* session)
72       : QuicDataStream(id, session) {
73   }
74
75   using ReliableQuicStream::CloseWriteSide;
76
77   virtual uint32 ProcessData(const char* data, uint32 data_len) {
78     return data_len;
79   }
80
81   void SendBody(const string& data, bool fin) {
82     WriteOrBufferData(data, fin, NULL);
83   }
84
85   MOCK_METHOD0(OnCanWrite, void());
86 };
87
88 // Poor man's functor for use as callback in a mock.
89 class StreamBlocker {
90  public:
91   StreamBlocker(QuicSession* session, QuicStreamId stream_id)
92       : session_(session),
93         stream_id_(stream_id) {
94   }
95
96   void MarkWriteBlocked() {
97     session_->MarkWriteBlocked(stream_id_, kSomeMiddlePriority);
98   }
99
100  private:
101   QuicSession* const session_;
102   const QuicStreamId stream_id_;
103 };
104
105 class TestSession : public QuicSession {
106  public:
107   explicit TestSession(QuicConnection* connection)
108       : QuicSession(connection, DefaultQuicConfig()),
109         crypto_stream_(this),
110         writev_consumes_all_data_(false) {
111   }
112
113   virtual TestCryptoStream* GetCryptoStream() OVERRIDE {
114     return &crypto_stream_;
115   }
116
117   virtual TestStream* CreateOutgoingDataStream() OVERRIDE {
118     TestStream* stream = new TestStream(GetNextStreamId(), this);
119     ActivateStream(stream);
120     return stream;
121   }
122
123   virtual TestStream* CreateIncomingDataStream(QuicStreamId id) OVERRIDE {
124     return new TestStream(id, this);
125   }
126
127   bool IsClosedStream(QuicStreamId id) {
128     return QuicSession::IsClosedStream(id);
129   }
130
131   QuicDataStream* GetIncomingDataStream(QuicStreamId stream_id) {
132     return QuicSession::GetIncomingDataStream(stream_id);
133   }
134
135   virtual QuicConsumedData WritevData(
136       QuicStreamId id,
137       const IOVector& data,
138       QuicStreamOffset offset,
139       bool fin,
140       QuicAckNotifier::DelegateInterface* ack_notifier_delegate) OVERRIDE {
141     // Always consumes everything.
142     if (writev_consumes_all_data_) {
143       return QuicConsumedData(data.TotalBufferSize(), fin);
144     } else {
145       return QuicSession::WritevData(id, data, offset, fin,
146                                      ack_notifier_delegate);
147     }
148   }
149
150   void set_writev_consumes_all_data(bool val) {
151     writev_consumes_all_data_ = val;
152   }
153
154   QuicConsumedData SendStreamData() {
155     return WritevData(5, IOVector(), 0, true, NULL);
156   }
157
158  private:
159   TestCryptoStream crypto_stream_;
160
161   bool writev_consumes_all_data_;
162 };
163
164 class QuicSessionTest : public ::testing::TestWithParam<QuicVersion> {
165  protected:
166   QuicSessionTest()
167       : connection_(new MockConnection(true, SupportedVersions(GetParam()))),
168         session_(connection_) {
169     headers_[":host"] = "www.google.com";
170     headers_[":path"] = "/index.hml";
171     headers_[":scheme"] = "http";
172     headers_["cookie"] =
173         "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; "
174         "__utmc=160408618; "
175         "GX=DQAAAOEAAACWJYdewdE9rIrW6qw3PtVi2-d729qaa-74KqOsM1NVQblK4VhX"
176         "hoALMsy6HOdDad2Sz0flUByv7etmo3mLMidGrBoljqO9hSVA40SLqpG_iuKKSHX"
177         "RW3Np4bq0F0SDGDNsW0DSmTS9ufMRrlpARJDS7qAI6M3bghqJp4eABKZiRqebHT"
178         "pMU-RXvTI5D5oCF1vYxYofH_l1Kviuiy3oQ1kS1enqWgbhJ2t61_SNdv-1XJIS0"
179         "O3YeHLmVCs62O6zp89QwakfAWK9d3IDQvVSJzCQsvxvNIvaZFa567MawWlXg0Rh"
180         "1zFMi5vzcns38-8_Sns; "
181         "GA=v*2%2Fmem*57968640*47239936%2Fmem*57968640*47114716%2Fno-nm-"
182         "yj*15%2Fno-cc-yj*5%2Fpc-ch*133685%2Fpc-s-cr*133947%2Fpc-s-t*1339"
183         "47%2Fno-nm-yj*4%2Fno-cc-yj*1%2Fceft-as*1%2Fceft-nqas*0%2Fad-ra-c"
184         "v_p%2Fad-nr-cv_p-f*1%2Fad-v-cv_p*859%2Fad-ns-cv_p-f*1%2Ffn-v-ad%"
185         "2Fpc-t*250%2Fpc-cm*461%2Fpc-s-cr*722%2Fpc-s-t*722%2Fau_p*4"
186         "SICAID=AJKiYcHdKgxum7KMXG0ei2t1-W4OD1uW-ecNsCqC0wDuAXiDGIcT_HA2o1"
187         "3Rs1UKCuBAF9g8rWNOFbxt8PSNSHFuIhOo2t6bJAVpCsMU5Laa6lewuTMYI8MzdQP"
188         "ARHKyW-koxuhMZHUnGBJAM1gJODe0cATO_KGoX4pbbFxxJ5IicRxOrWK_5rU3cdy6"
189         "edlR9FsEdH6iujMcHkbE5l18ehJDwTWmBKBzVD87naobhMMrF6VvnDGxQVGp9Ir_b"
190         "Rgj3RWUoPumQVCxtSOBdX0GlJOEcDTNCzQIm9BSfetog_eP_TfYubKudt5eMsXmN6"
191         "QnyXHeGeK2UINUzJ-D30AFcpqYgH9_1BvYSpi7fc7_ydBU8TaD8ZRxvtnzXqj0RfG"
192         "tuHghmv3aD-uzSYJ75XDdzKdizZ86IG6Fbn1XFhYZM-fbHhm3mVEXnyRW4ZuNOLFk"
193         "Fas6LMcVC6Q8QLlHYbXBpdNFuGbuZGUnav5C-2I_-46lL0NGg3GewxGKGHvHEfoyn"
194         "EFFlEYHsBQ98rXImL8ySDycdLEFvBPdtctPmWCfTxwmoSMLHU2SCVDhbqMWU5b0yr"
195         "JBCScs_ejbKaqBDoB7ZGxTvqlrB__2ZmnHHjCr8RgMRtKNtIeuZAo ";
196   }
197
198   void CheckClosedStreams() {
199     for (int i = kCryptoStreamId; i < 100; i++) {
200       if (closed_streams_.count(i) == 0) {
201         EXPECT_FALSE(session_.IsClosedStream(i)) << " stream id: " << i;
202       } else {
203         EXPECT_TRUE(session_.IsClosedStream(i)) << " stream id: " << i;
204       }
205     }
206   }
207
208   void CloseStream(QuicStreamId id) {
209     session_.CloseStream(id);
210     closed_streams_.insert(id);
211   }
212
213   QuicVersion version() const { return connection_->version(); }
214
215   MockConnection* connection_;
216   TestSession session_;
217   set<QuicStreamId> closed_streams_;
218   SpdyHeaderBlock headers_;
219 };
220
221 INSTANTIATE_TEST_CASE_P(Tests, QuicSessionTest,
222                         ::testing::ValuesIn(QuicSupportedVersions()));
223
224 TEST_P(QuicSessionTest, PeerAddress) {
225   EXPECT_EQ(IPEndPoint(Loopback4(), kTestPort), session_.peer_address());
226 }
227
228 TEST_P(QuicSessionTest, IsCryptoHandshakeConfirmed) {
229   EXPECT_FALSE(session_.IsCryptoHandshakeConfirmed());
230   CryptoHandshakeMessage message;
231   session_.GetCryptoStream()->OnHandshakeMessage(message);
232   EXPECT_TRUE(session_.IsCryptoHandshakeConfirmed());
233 }
234
235 TEST_P(QuicSessionTest, IsClosedStreamDefault) {
236   // Ensure that no streams are initially closed.
237   for (int i = kCryptoStreamId; i < 100; i++) {
238     EXPECT_FALSE(session_.IsClosedStream(i)) << "stream id: " << i;
239   }
240 }
241
242 TEST_P(QuicSessionTest, ImplicitlyCreatedStreams) {
243   ASSERT_TRUE(session_.GetIncomingDataStream(7) != NULL);
244   // Both 3 and 5 should be implicitly created.
245   EXPECT_FALSE(session_.IsClosedStream(3));
246   EXPECT_FALSE(session_.IsClosedStream(5));
247   ASSERT_TRUE(session_.GetIncomingDataStream(5) != NULL);
248   ASSERT_TRUE(session_.GetIncomingDataStream(3) != NULL);
249 }
250
251 TEST_P(QuicSessionTest, IsClosedStreamLocallyCreated) {
252   TestStream* stream2 = session_.CreateOutgoingDataStream();
253   EXPECT_EQ(2u, stream2->id());
254   TestStream* stream4 = session_.CreateOutgoingDataStream();
255   EXPECT_EQ(4u, stream4->id());
256
257   CheckClosedStreams();
258   CloseStream(4);
259   CheckClosedStreams();
260   CloseStream(2);
261   CheckClosedStreams();
262 }
263
264 TEST_P(QuicSessionTest, IsClosedStreamPeerCreated) {
265   QuicStreamId stream_id1 = 5;
266   QuicStreamId stream_id2 = stream_id1 + 2;
267   QuicDataStream* stream1 = session_.GetIncomingDataStream(stream_id1);
268   QuicDataStreamPeer::SetHeadersDecompressed(stream1, true);
269   QuicDataStream* stream2 = session_.GetIncomingDataStream(stream_id2);
270   QuicDataStreamPeer::SetHeadersDecompressed(stream2, true);
271
272   CheckClosedStreams();
273   CloseStream(stream_id1);
274   CheckClosedStreams();
275   CloseStream(stream_id2);
276   // Create a stream explicitly, and another implicitly.
277   QuicDataStream* stream3 = session_.GetIncomingDataStream(stream_id2 + 4);
278   QuicDataStreamPeer::SetHeadersDecompressed(stream3, true);
279   CheckClosedStreams();
280   // Close one, but make sure the other is still not closed
281   CloseStream(stream3->id());
282   CheckClosedStreams();
283 }
284
285 TEST_P(QuicSessionTest, StreamIdTooLarge) {
286   QuicStreamId stream_id = 5;
287   session_.GetIncomingDataStream(stream_id);
288   EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_STREAM_ID));
289   session_.GetIncomingDataStream(stream_id + kMaxStreamIdDelta + 2);
290 }
291
292 TEST_P(QuicSessionTest, DecompressionError) {
293   QuicHeadersStream* stream = QuicSessionPeer::GetHeadersStream(&session_);
294   const unsigned char data[] = {
295     0x80, 0x03, 0x00, 0x01,  // SPDY/3 SYN_STREAM frame
296     0x00, 0x00, 0x00, 0x25,  // flags/length
297     0x00, 0x00, 0x00, 0x05,  // stream id
298     0x00, 0x00, 0x00, 0x00,  // associated stream id
299     0x00, 0x00,
300     'a',  'b',  'c',  'd'    // invalid compressed data
301   };
302   EXPECT_CALL(*connection_,
303               SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
304                                              "SPDY framing error."));
305   stream->ProcessRawData(reinterpret_cast<const char*>(data),
306                          arraysize(data));
307 }
308
309 TEST_P(QuicSessionTest, DebugDFatalIfMarkingClosedStreamWriteBlocked) {
310   TestStream* stream2 = session_.CreateOutgoingDataStream();
311   // Close the stream.
312   stream2->Reset(QUIC_BAD_APPLICATION_PAYLOAD);
313   // TODO(rtenneti): enable when chromium supports EXPECT_DEBUG_DFATAL.
314   /*
315   QuicStreamId kClosedStreamId = stream2->id();
316   EXPECT_DEBUG_DFATAL(
317       session_.MarkWriteBlocked(kClosedStreamId, kSomeMiddlePriority),
318       "Marking unknown stream 2 blocked.");
319   */
320 }
321
322 TEST_P(QuicSessionTest, DebugDFatalIfMarkWriteBlockedCalledWithWrongPriority) {
323   const QuicPriority kDifferentPriority = 0;
324
325   TestStream* stream2 = session_.CreateOutgoingDataStream();
326   EXPECT_NE(kDifferentPriority, stream2->EffectivePriority());
327   // TODO(rtenneti): enable when chromium supports EXPECT_DEBUG_DFATAL.
328   /*
329   EXPECT_DEBUG_DFATAL(
330       session_.MarkWriteBlocked(stream2->id(), kDifferentPriority),
331       "Priorities do not match.  Got: 0 Expected: 3");
332   */
333 }
334
335 TEST_P(QuicSessionTest, OnCanWrite) {
336   TestStream* stream2 = session_.CreateOutgoingDataStream();
337   TestStream* stream4 = session_.CreateOutgoingDataStream();
338   TestStream* stream6 = session_.CreateOutgoingDataStream();
339
340   session_.MarkWriteBlocked(stream2->id(), kSomeMiddlePriority);
341   session_.MarkWriteBlocked(stream6->id(), kSomeMiddlePriority);
342   session_.MarkWriteBlocked(stream4->id(), kSomeMiddlePriority);
343
344   InSequence s;
345   StreamBlocker stream2_blocker(&session_, stream2->id());
346   EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(
347       // Reregister, to test the loop limit.
348       InvokeWithoutArgs(&stream2_blocker, &StreamBlocker::MarkWriteBlocked));
349   EXPECT_CALL(*stream6, OnCanWrite());
350   EXPECT_CALL(*stream4, OnCanWrite());
351   session_.OnCanWrite();
352   EXPECT_TRUE(session_.HasPendingWrites());
353 }
354
355 TEST_P(QuicSessionTest, OnCanWriteBundlesStreams) {
356   // Drive congestion control manually.
357   MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
358   QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
359
360   TestStream* stream2 = session_.CreateOutgoingDataStream();
361   TestStream* stream4 = session_.CreateOutgoingDataStream();
362   TestStream* stream6 = session_.CreateOutgoingDataStream();
363
364   session_.MarkWriteBlocked(stream2->id(), kSomeMiddlePriority);
365   session_.MarkWriteBlocked(stream6->id(), kSomeMiddlePriority);
366   session_.MarkWriteBlocked(stream4->id(), kSomeMiddlePriority);
367
368
369   EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _)).WillRepeatedly(
370       Return(QuicTime::Delta::Zero()));
371   EXPECT_CALL(*send_algorithm, GetCongestionWindow()).WillOnce(
372       Return(kMaxPacketSize * 10));
373   EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(IgnoreResult(
374       InvokeWithoutArgs(&session_, &TestSession::SendStreamData)));
375   EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(IgnoreResult(
376       InvokeWithoutArgs(&session_, &TestSession::SendStreamData)));
377   EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(IgnoreResult(
378       InvokeWithoutArgs(&session_, &TestSession::SendStreamData)));
379   MockPacketWriter* writer =
380       static_cast<MockPacketWriter*>(
381           QuicConnectionPeer::GetWriter(session_.connection()));
382   EXPECT_CALL(*writer, WritePacket(_, _, _, _)).WillOnce(
383                   Return(WriteResult(WRITE_STATUS_OK, 0)));
384   EXPECT_CALL(*send_algorithm, OnPacketSent(_, _, _, _, _));
385   session_.OnCanWrite();
386   EXPECT_FALSE(session_.HasPendingWrites());
387 }
388
389 TEST_P(QuicSessionTest, OnCanWriteCongestionControlBlocks) {
390   InSequence s;
391
392   // Drive congestion control manually.
393   MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
394   QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
395
396   TestStream* stream2 = session_.CreateOutgoingDataStream();
397   TestStream* stream4 = session_.CreateOutgoingDataStream();
398   TestStream* stream6 = session_.CreateOutgoingDataStream();
399
400   session_.MarkWriteBlocked(stream2->id(), kSomeMiddlePriority);
401   session_.MarkWriteBlocked(stream6->id(), kSomeMiddlePriority);
402   session_.MarkWriteBlocked(stream4->id(), kSomeMiddlePriority);
403
404   StreamBlocker stream2_blocker(&session_, stream2->id());
405   EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _)).WillOnce(Return(
406       QuicTime::Delta::Zero()));
407   EXPECT_CALL(*stream2, OnCanWrite());
408   EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _)).WillOnce(Return(
409       QuicTime::Delta::Zero()));
410   EXPECT_CALL(*stream6, OnCanWrite());
411   EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _)).WillOnce(Return(
412       QuicTime::Delta::Infinite()));
413   // stream4->OnCanWrite is not called.
414
415   session_.OnCanWrite();
416   EXPECT_TRUE(session_.HasPendingWrites());
417
418   // Still congestion-control blocked.
419   EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _)).WillOnce(Return(
420       QuicTime::Delta::Infinite()));
421   session_.OnCanWrite();
422   EXPECT_TRUE(session_.HasPendingWrites());
423
424   // stream4->OnCanWrite is called once the connection stops being
425   // congestion-control blocked.
426   EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _)).WillOnce(Return(
427       QuicTime::Delta::Zero()));
428   EXPECT_CALL(*stream4, OnCanWrite());
429   session_.OnCanWrite();
430   EXPECT_FALSE(session_.HasPendingWrites());
431 }
432
433 TEST_P(QuicSessionTest, BufferedHandshake) {
434   EXPECT_FALSE(session_.HasPendingHandshake());  // Default value.
435
436   // Test that blocking other streams does not change our status.
437   TestStream* stream2 = session_.CreateOutgoingDataStream();
438   StreamBlocker stream2_blocker(&session_, stream2->id());
439   stream2_blocker.MarkWriteBlocked();
440   EXPECT_FALSE(session_.HasPendingHandshake());
441
442   TestStream* stream3 = session_.CreateOutgoingDataStream();
443   StreamBlocker stream3_blocker(&session_, stream3->id());
444   stream3_blocker.MarkWriteBlocked();
445   EXPECT_FALSE(session_.HasPendingHandshake());
446
447   // Blocking (due to buffering of) the Crypto stream is detected.
448   session_.MarkWriteBlocked(kCryptoStreamId, kHighestPriority);
449   EXPECT_TRUE(session_.HasPendingHandshake());
450
451   TestStream* stream4 = session_.CreateOutgoingDataStream();
452   StreamBlocker stream4_blocker(&session_, stream4->id());
453   stream4_blocker.MarkWriteBlocked();
454   EXPECT_TRUE(session_.HasPendingHandshake());
455
456   InSequence s;
457   // Force most streams to re-register, which is common scenario when we block
458   // the Crypto stream, and only the crypto stream can "really" write.
459
460   // Due to prioritization, we *should* be asked to write the crypto stream
461   // first.
462   // Don't re-register the crypto stream (which signals complete writing).
463   TestCryptoStream* crypto_stream = session_.GetCryptoStream();
464   EXPECT_CALL(*crypto_stream, OnCanWrite());
465
466   // Re-register all other streams, to show they weren't able to proceed.
467   EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(
468       InvokeWithoutArgs(&stream2_blocker, &StreamBlocker::MarkWriteBlocked));
469
470   EXPECT_CALL(*stream3, OnCanWrite()).WillOnce(
471       InvokeWithoutArgs(&stream3_blocker, &StreamBlocker::MarkWriteBlocked));
472
473   EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(
474       InvokeWithoutArgs(&stream4_blocker, &StreamBlocker::MarkWriteBlocked));
475
476   session_.OnCanWrite();
477   EXPECT_TRUE(session_.HasPendingWrites());
478   EXPECT_FALSE(session_.HasPendingHandshake());  // Crypto stream wrote.
479 }
480
481 TEST_P(QuicSessionTest, OnCanWriteWithClosedStream) {
482   TestStream* stream2 = session_.CreateOutgoingDataStream();
483   TestStream* stream4 = session_.CreateOutgoingDataStream();
484   TestStream* stream6 = session_.CreateOutgoingDataStream();
485
486   session_.MarkWriteBlocked(stream2->id(), kSomeMiddlePriority);
487   session_.MarkWriteBlocked(stream6->id(), kSomeMiddlePriority);
488   session_.MarkWriteBlocked(stream4->id(), kSomeMiddlePriority);
489   CloseStream(stream6->id());
490
491   InSequence s;
492   EXPECT_CALL(*stream2, OnCanWrite());
493   EXPECT_CALL(*stream4, OnCanWrite());
494   session_.OnCanWrite();
495   EXPECT_FALSE(session_.HasPendingWrites());
496 }
497
498 TEST_P(QuicSessionTest, SendGoAway) {
499   EXPECT_CALL(*connection_,
500               SendGoAway(QUIC_PEER_GOING_AWAY, 0u, "Going Away."));
501   session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
502   EXPECT_TRUE(session_.goaway_sent());
503
504   EXPECT_CALL(*connection_,
505               SendRstStream(3u, QUIC_STREAM_PEER_GOING_AWAY, 0)).Times(0);
506   EXPECT_TRUE(session_.GetIncomingDataStream(3u));
507 }
508
509 TEST_P(QuicSessionTest, DoNotSendGoAwayTwice) {
510   EXPECT_CALL(*connection_,
511               SendGoAway(QUIC_PEER_GOING_AWAY, 0u, "Going Away.")).Times(1);
512   session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
513   EXPECT_TRUE(session_.goaway_sent());
514   session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
515 }
516
517 TEST_P(QuicSessionTest, IncreasedTimeoutAfterCryptoHandshake) {
518   EXPECT_EQ(kDefaultInitialTimeoutSecs,
519             QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
520   CryptoHandshakeMessage msg;
521   session_.GetCryptoStream()->OnHandshakeMessage(msg);
522   EXPECT_EQ(kDefaultTimeoutSecs,
523             QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
524 }
525
526 TEST_P(QuicSessionTest, RstStreamBeforeHeadersDecompressed) {
527   QuicStreamId stream_id1 = 5;
528   // Send two bytes of payload.
529   QuicStreamFrame data1(stream_id1, false, 0, MakeIOVector("HT"));
530   vector<QuicStreamFrame> frames;
531   frames.push_back(data1);
532   session_.OnStreamFrames(frames);
533   EXPECT_EQ(1u, session_.GetNumOpenStreams());
534
535   QuicRstStreamFrame rst1(stream_id1, QUIC_STREAM_NO_ERROR, 0);
536   session_.OnRstStream(rst1);
537   EXPECT_EQ(0u, session_.GetNumOpenStreams());
538   // Connection should remain alive.
539   EXPECT_TRUE(connection_->connected());
540 }
541
542 TEST_P(QuicSessionTest, MultipleRstStreamsCauseSingleConnectionClose) {
543   // If multiple invalid reset stream frames arrive in a single packet, this
544   // should trigger a connection close. However there is no need to send
545   // multiple connection close frames.
546
547   // Create valid stream.
548   const QuicStreamId kStreamId = 5;
549   QuicStreamFrame data1(kStreamId, false, 0, MakeIOVector("HT"));
550   vector<QuicStreamFrame> frames;
551   frames.push_back(data1);
552   session_.OnStreamFrames(frames);
553   EXPECT_EQ(1u, session_.GetNumOpenStreams());
554
555   // Process first invalid stream reset, resulting in the connection being
556   // closed.
557   EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_STREAM_ID))
558       .Times(1);
559   QuicStreamId kLargeInvalidStreamId = 99999999;
560   QuicRstStreamFrame rst1(kLargeInvalidStreamId, QUIC_STREAM_NO_ERROR, 0);
561   session_.OnRstStream(rst1);
562   QuicConnectionPeer::CloseConnection(connection_);
563
564   // Processing of second invalid stream reset should not result in the
565   // connection being closed for a second time.
566   QuicRstStreamFrame rst2(kLargeInvalidStreamId, QUIC_STREAM_NO_ERROR, 0);
567   session_.OnRstStream(rst2);
568 }
569
570 TEST_P(QuicSessionTest, HandshakeUnblocksFlowControlBlockedStream) {
571   // Test that if a stream is flow control blocked, then on receipt of the SHLO
572   // containing a suitable send window offset, the stream becomes unblocked.
573   if (version() < QUIC_VERSION_17) {
574     return;
575   }
576   ValueRestore<bool> old_flag(&FLAGS_enable_quic_stream_flow_control_2, true);
577
578   // Ensure that Writev consumes all the data it is given (simulate no socket
579   // blocking).
580   session_.set_writev_consumes_all_data(true);
581
582   // Create a stream, and send enough data to make it flow control blocked.
583   TestStream* stream2 = session_.CreateOutgoingDataStream();
584   string body(kDefaultFlowControlSendWindow, '.');
585   EXPECT_FALSE(stream2->flow_controller()->IsBlocked());
586   stream2->SendBody(body, false);
587   EXPECT_TRUE(stream2->flow_controller()->IsBlocked());
588
589   // Now complete the crypto handshake, resulting in an increased flow control
590   // send window.
591   CryptoHandshakeMessage msg;
592   session_.GetCryptoStream()->OnHandshakeMessage(msg);
593
594   // Stream is now unblocked.
595   EXPECT_FALSE(stream2->flow_controller()->IsBlocked());
596 }
597
598 TEST_P(QuicSessionTest, InvalidFlowControlWindowInHandshake) {
599   // Test that receipt of an invalid (< default) flow control window from peer
600   // results in the connection being torn down.
601   if (version() < QUIC_VERSION_17) {
602     return;
603   }
604   ValueRestore<bool> old_flag(&FLAGS_enable_quic_stream_flow_control_2, true);
605
606   uint32 kInvalidWindow = kDefaultFlowControlSendWindow - 1;
607
608   CryptoHandshakeMessage msg;
609   string error_details;
610   session_.config()->SetInitialFlowControlWindowToSend(kInvalidWindow);
611   session_.config()->ToHandshakeMessage(&msg);
612   const QuicErrorCode error =
613       session_.config()->ProcessPeerHello(msg, CLIENT, &error_details);
614   EXPECT_EQ(QUIC_NO_ERROR, error);
615
616   EXPECT_CALL(*connection_, SendConnectionClose(QUIC_FLOW_CONTROL_ERROR));
617   session_.OnConfigNegotiated();
618 }
619
620 }  // namespace
621 }  // namespace test
622 }  // namespace net