Make all QUIC streams owned by the session.  Add a Visitor interface to the stream, so that consumer can be informed when the stream will be deleted.

Merge internal change: 40355686

[email protected]

Review URL: https://chromiumcodereview.appspot.com/11644084

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@174559 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index ff8a749..0226d406 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -73,6 +73,20 @@
   DISALLOW_COPY_AND_ASSIGN(TestCollector);
 };
 
+// Subclass of QuicHttpStream that closes itself when the first piece of data
+// is received.
+class AutoClosingStream : public QuicHttpStream {
+ public:
+  explicit AutoClosingStream(QuicReliableClientStream* stream)
+      : QuicHttpStream(stream) {
+  }
+
+  virtual int OnDataReceived(const char* data, int length) {
+    Close(false);
+    return OK;
+  }
+};
+
 }  // namespace
 
 class QuicHttpStreamTest : public ::testing::Test {
@@ -92,6 +106,7 @@
 
   QuicHttpStreamTest()
       : net_log_(BoundNetLog()),
+        use_closing_stream_(false),
         read_buffer_(new IOBufferWithSize(4096)),
         guid_(2),
         framer_(QuicDecrypter::Create(kNULL), QuicEncrypter::Create(kNULL)),
@@ -159,8 +174,11 @@
     message.tag = kSHLO;
     session_->GetCryptoStream()->OnHandshakeMessage(message);
     EXPECT_TRUE(session_->IsCryptoHandshakeComplete());
-    stream_.reset(new QuicHttpStream(session_->CreateOutgoingReliableStream()));
-  }
+    QuicReliableClientStream* stream =
+        session_->CreateOutgoingReliableStream();
+    stream_.reset(use_closing_stream_ ? new AutoClosingStream(stream) :
+                  new QuicHttpStream(stream));
+   }
 
   // Returns a newly created packet to send kData on stream 1.
   QuicEncryptedPacket* ConstructDataPacket(
@@ -176,14 +194,27 @@
   // Returns a newly created packet to send ack data.
   QuicEncryptedPacket* ConstructAckPacket(
       QuicPacketSequenceNumber sequence_number,
-      QuicPacketSequenceNumber largest_received) {
+      QuicPacketSequenceNumber largest_received,
+      QuicPacketSequenceNumber least_unacked) {
     InitializeHeader(sequence_number);
 
-    QuicAckFrame ack(largest_received, sequence_number);
+    QuicAckFrame ack(largest_received, least_unacked);
     return ConstructPacket(header_, QuicFrame(&ack));
   }
 
+  // Returns a newly created packet to send ack data.
+  QuicEncryptedPacket* ConstructRstPacket(
+      QuicPacketSequenceNumber sequence_number,
+      QuicStreamId stream_id,
+      QuicStreamOffset offset) {
+    InitializeHeader(sequence_number);
+
+    QuicRstStreamFrame rst(stream_id, offset, QUIC_NO_ERROR);
+    return ConstructPacket(header_, QuicFrame(&rst));
+  }
+
   BoundNetLog net_log_;
+  bool use_closing_stream_;
   MockScheduler* scheduler_;
   TestCollector* collector_;
   scoped_refptr<TestTaskRunner> runner_;
@@ -247,7 +278,7 @@
 TEST_F(QuicHttpStreamTest, GetRequest) {
   AddWrite(SYNCHRONOUS, ConstructDataPacket(1, kFin, 0,
                                             "GET / HTTP/1.1\r\n\r\n"));
-  AddWrite(SYNCHRONOUS, ConstructAckPacket(2, 2));
+  AddWrite(SYNCHRONOUS, ConstructAckPacket(2, 2, 2));
   Initialize();
 
   request_.method = "GET";
@@ -260,7 +291,7 @@
   EXPECT_EQ(&response_, stream_->GetResponseInfo());
 
   // Ack the request.
-  scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 1));
+  scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 1, 1));
   ProcessPacket(*ack);
 
   EXPECT_EQ(ERR_IO_PENDING,
@@ -290,7 +321,7 @@
 TEST_F(QuicHttpStreamTest, GetRequestFullResponseInSinglePacket) {
   AddWrite(SYNCHRONOUS, ConstructDataPacket(1, kFin, 0,
                                             "GET / HTTP/1.1\r\n\r\n"));
-  AddWrite(SYNCHRONOUS, ConstructAckPacket(2, 2));
+  AddWrite(SYNCHRONOUS, ConstructAckPacket(2, 2, 2));
   Initialize();
 
   request_.method = "GET";
@@ -303,7 +334,7 @@
   EXPECT_EQ(&response_, stream_->GetResponseInfo());
 
   // Ack the request.
-  scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 1));
+  scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 1, 1));
   ProcessPacket(*ack);
 
   EXPECT_EQ(ERR_IO_PENDING,
@@ -336,8 +367,8 @@
   AddWrite(SYNCHRONOUS, ConstructDataPacket(1, kNoFin, 0, kRequestData));
   AddWrite(SYNCHRONOUS, ConstructDataPacket(2, kFin, strlen(kRequestData),
                                             kUploadData));
-  AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2));
-  AddWrite(SYNCHRONOUS, ConstructAckPacket(4, 3));
+  AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 3));
+  AddWrite(SYNCHRONOUS, ConstructAckPacket(4, 3, 4));
 
   Initialize();
 
@@ -357,7 +388,7 @@
   EXPECT_EQ(&response_, stream_->GetResponseInfo());
 
   // Ack both packets in the request.
-  scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 2));
+  scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 2, 1));
   ProcessPacket(*ack);
 
   // Send the response headers (but not the body).
@@ -388,6 +419,42 @@
   EXPECT_TRUE(AtEof());
 }
 
+TEST_F(QuicHttpStreamTest, DestroyedEarly) {
+  const char kRequest[] = "GET / HTTP/1.1\r\n\r\n";
+  AddWrite(SYNCHRONOUS, ConstructDataPacket(1, kFin, 0, kRequest));
+  AddWrite(SYNCHRONOUS, ConstructRstPacket(2, 3, strlen(kRequest)));
+  AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 2));
+  use_closing_stream_ = true;
+  Initialize();
+
+  request_.method = "GET";
+  request_.url = GURL("http://www.google.com/");
+
+  //stream_.reset(new TestStream(session_->CreateOutgoingReliableStream()));
+  EXPECT_EQ(OK, stream_->InitializeStream(&request_, net_log_,
+                                         callback_.callback()));
+  EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
+                                    callback_.callback()));
+  EXPECT_EQ(&response_, stream_->GetResponseInfo());
+
+  // Ack the request.
+  scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 1, 1));
+  ProcessPacket(*ack);
+  EXPECT_EQ(ERR_IO_PENDING,
+            stream_->ReadResponseHeaders(callback_.callback()));
+
+  // Send the response with a body.
+  const char kResponseHeaders[] = "HTTP/1.1 404 OK\r\n"
+      "Content-Type: text/plain\r\n\r\nhello world!";
+  scoped_ptr<QuicEncryptedPacket> resp(
+      ConstructDataPacket(2, kFin, 0, kResponseHeaders));
+
+  // In the course of processing this packet, the QuicHttpStream close itself.
+  ProcessPacket(*resp);
+
+  EXPECT_TRUE(AtEof());
+}
+
 }  // namespace test
 
 }  // namespace net