| Index: net/http/http_stream_parser_unittest.cc
|
| diff --git a/net/http/http_stream_parser_unittest.cc b/net/http/http_stream_parser_unittest.cc
|
| index dcaf1f3e9c3f1fdaf0592f7dae1eb50e9c00f17d..33910395cbcaabad9689498a2696be47c211633f 100644
|
| --- a/net/http/http_stream_parser_unittest.cc
|
| +++ b/net/http/http_stream_parser_unittest.cc
|
| @@ -804,6 +804,63 @@ TEST(HttpStreamParser, ReceivedBytesIncludesContinueHeader) {
|
| EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
|
| }
|
|
|
| +// Test that an HttpStreamParser can be read from after it's received headers
|
| +// and data structures owned by its owner have been deleted. This happens
|
| +// when a ResponseBodyDrainer is used.
|
| +TEST(HttpStreamParser, ReadAfterUnownedObjectsDestroyed) {
|
| + MockWrite writes[] = {
|
| + MockWrite(SYNCHRONOUS, 0,
|
| + "GET /foo.html HTTP/1.1\r\n\r\n"),
|
| + MockWrite(SYNCHRONOUS, 1, "1"),
|
| + };
|
| +
|
| + const int kBodySize = 1;
|
| + MockRead reads[] = {
|
| + MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"),
|
| + MockRead(SYNCHRONOUS, 6, "Content-Length: 1\r\n\r\n"),
|
| + MockRead(SYNCHRONOUS, 6, "Connection: Keep-Alive\r\n\r\n"),
|
| + MockRead(SYNCHRONOUS, 7, "1"),
|
| + MockRead(SYNCHRONOUS, 0, 8), // EOF
|
| + };
|
| +
|
| + StaticSocketDataProvider data(reads, arraysize(reads), writes,
|
| + arraysize(writes));
|
| + data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
|
| +
|
| + scoped_ptr<MockTCPClientSocket> transport(
|
| + new MockTCPClientSocket(AddressList(), NULL, &data));
|
| +
|
| + TestCompletionCallback callback;
|
| + ASSERT_EQ(OK, transport->Connect(callback.callback()));
|
| +
|
| + scoped_ptr<ClientSocketHandle> socket_handle(new ClientSocketHandle);
|
| + socket_handle->SetSocket(transport.PassAs<StreamSocket>());
|
| +
|
| + scoped_ptr<HttpRequestInfo> request_info(new HttpRequestInfo());
|
| + request_info->method = "GET";
|
| + request_info->url = GURL("http://somewhere/foo.html");
|
| +
|
| + scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer);
|
| + HttpStreamParser parser(socket_handle.get(), request_info.get(),
|
| + read_buffer.get(), BoundNetLog());
|
| +
|
| + scoped_ptr<HttpRequestHeaders> request_headers(new HttpRequestHeaders());
|
| + scoped_ptr<HttpResponseInfo> response_info(new HttpResponseInfo());
|
| + ASSERT_EQ(OK, parser.SendRequest("GET /foo.html HTTP/1.1\r\n",
|
| + *request_headers, response_info.get(), callback.callback()));
|
| + ASSERT_EQ(OK, parser.ReadResponseHeaders(callback.callback()));
|
| +
|
| + // If the object that owns the HttpStreamParser is deleted, it takes the
|
| + // objects passed to the HttpStreamParser with it.
|
| + request_info.reset();
|
| + request_headers.reset();
|
| + response_info.reset();
|
| +
|
| + scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize));
|
| + ASSERT_EQ(kBodySize, parser.ReadResponseBody(
|
| + body_buffer.get(), kBodySize, callback.callback()));
|
| +}
|
| +
|
| } // namespace
|
|
|
| } // namespace net
|
|
|