| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/http/http_stream_parser.h" | 5 #include "net/http/http_stream_parser.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 namespace { | 36 namespace { |
| 37 | 37 |
| 38 const size_t kOutputSize = 1024; // Just large enough for this test. | 38 const size_t kOutputSize = 1024; // Just large enough for this test. |
| 39 // The number of bytes that can fit in a buffer of kOutputSize. | 39 // The number of bytes that can fit in a buffer of kOutputSize. |
| 40 const size_t kMaxPayloadSize = | 40 const size_t kMaxPayloadSize = |
| 41 kOutputSize - HttpStreamParser::kChunkHeaderFooterSize; | 41 kOutputSize - HttpStreamParser::kChunkHeaderFooterSize; |
| 42 | 42 |
| 43 // Helper method to create a connected ClientSocketHandle using |data|. | 43 // Helper method to create a connected ClientSocketHandle using |data|. |
| 44 // Modifies |data|. | 44 // Modifies |data|. |
| 45 scoped_ptr<ClientSocketHandle> CreateConnectedSocketHandle( | 45 scoped_ptr<ClientSocketHandle> CreateConnectedSocketHandle( |
| 46 DeterministicSocketData* data) { | 46 SequencedSocketData* data) { |
| 47 data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); | 47 data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); |
| 48 | 48 |
| 49 scoped_ptr<DeterministicMockTCPClientSocket> transport( | 49 scoped_ptr<MockTCPClientSocket> socket( |
| 50 new DeterministicMockTCPClientSocket(nullptr, data)); | 50 new MockTCPClientSocket(net::AddressList(), nullptr, data)); |
| 51 data->set_delegate(transport->AsWeakPtr()); | 51 data->set_socket(socket.get()); |
| 52 | 52 |
| 53 TestCompletionCallback callback; | 53 TestCompletionCallback callback; |
| 54 EXPECT_EQ(OK, transport->Connect(callback.callback())); | 54 EXPECT_EQ(OK, socket->Connect(callback.callback())); |
| 55 | 55 |
| 56 scoped_ptr<ClientSocketHandle> socket_handle(new ClientSocketHandle); | 56 scoped_ptr<ClientSocketHandle> socket_handle(new ClientSocketHandle); |
| 57 socket_handle->SetSocket(transport.Pass()); | 57 socket_handle->SetSocket(socket.Pass()); |
| 58 return socket_handle.Pass(); | 58 return socket_handle.Pass(); |
| 59 } | 59 } |
| 60 | 60 |
| 61 // The empty payload is how the last chunk is encoded. | 61 // The empty payload is how the last chunk is encoded. |
| 62 TEST(HttpStreamParser, EncodeChunk_EmptyPayload) { | 62 TEST(HttpStreamParser, EncodeChunk_EmptyPayload) { |
| 63 char output[kOutputSize]; | 63 char output[kOutputSize]; |
| 64 | 64 |
| 65 const base::StringPiece kPayload = ""; | 65 const base::StringPiece kPayload = ""; |
| 66 const base::StringPiece kExpected = "0\r\n\r\n"; | 66 const base::StringPiece kExpected = "0\r\n\r\n"; |
| 67 const int num_bytes_written = | 67 const int num_bytes_written = |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 MockRead reads[] = { | 222 MockRead reads[] = { |
| 223 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n"), | 223 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n"), |
| 224 MockRead(ASYNC, 4, "Content-Length: 8\r\n\r\n"), | 224 MockRead(ASYNC, 4, "Content-Length: 8\r\n\r\n"), |
| 225 MockRead(ASYNC, 5, "one.html"), | 225 MockRead(ASYNC, 5, "one.html"), |
| 226 MockRead(SYNCHRONOUS, 0, 6), // EOF | 226 MockRead(SYNCHRONOUS, 0, 6), // EOF |
| 227 }; | 227 }; |
| 228 | 228 |
| 229 ChunkedUploadDataStream upload_stream(0); | 229 ChunkedUploadDataStream upload_stream(0); |
| 230 ASSERT_EQ(OK, upload_stream.Init(TestCompletionCallback().callback())); | 230 ASSERT_EQ(OK, upload_stream.Init(TestCompletionCallback().callback())); |
| 231 | 231 |
| 232 DeterministicSocketData data(reads, arraysize(reads), writes, | 232 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes)); |
| 233 arraysize(writes)); | |
| 234 scoped_ptr<ClientSocketHandle> socket_handle = | 233 scoped_ptr<ClientSocketHandle> socket_handle = |
| 235 CreateConnectedSocketHandle(&data); | 234 CreateConnectedSocketHandle(&data); |
| 236 | 235 |
| 237 HttpRequestInfo request_info; | 236 HttpRequestInfo request_info; |
| 238 request_info.method = "GET"; | 237 request_info.method = "GET"; |
| 239 request_info.url = GURL("http://localhost"); | 238 request_info.url = GURL("http://localhost"); |
| 240 request_info.upload_data_stream = &upload_stream; | 239 request_info.upload_data_stream = &upload_stream; |
| 241 | 240 |
| 242 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); | 241 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); |
| 243 HttpStreamParser parser(socket_handle.get(), &request_info, read_buffer.get(), | 242 HttpStreamParser parser(socket_handle.get(), &request_info, read_buffer.get(), |
| 244 BoundNetLog()); | 243 BoundNetLog()); |
| 245 | 244 |
| 246 HttpRequestHeaders request_headers; | 245 HttpRequestHeaders request_headers; |
| 247 request_headers.SetHeader("Transfer-Encoding", "chunked"); | 246 request_headers.SetHeader("Transfer-Encoding", "chunked"); |
| 248 | 247 |
| 249 HttpResponseInfo response_info; | 248 HttpResponseInfo response_info; |
| 250 TestCompletionCallback callback; | 249 TestCompletionCallback callback; |
| 251 // This will attempt to Write() the initial request and headers, which will | 250 // This will attempt to Write() the initial request and headers, which will |
| 252 // complete asynchronously. | 251 // complete asynchronously. |
| 253 ASSERT_EQ(ERR_IO_PENDING, | 252 ASSERT_EQ(ERR_IO_PENDING, |
| 254 parser.SendRequest("GET /one.html HTTP/1.1\r\n", request_headers, | 253 parser.SendRequest("GET /one.html HTTP/1.1\r\n", request_headers, |
| 255 &response_info, callback.callback())); | 254 &response_info, callback.callback())); |
| 256 | 255 |
| 257 // Complete the initial request write. | 256 // Complete the initial request write. Callback should not have been invoked. |
| 258 data.RunFor(1); | 257 base::RunLoop().RunUntilIdle(); |
| 259 ASSERT_FALSE(callback.have_result()); | 258 ASSERT_FALSE(callback.have_result()); |
| 260 | 259 |
| 261 // Now append the only chunk. | 260 // Now append the only chunk and wait for the callback. |
| 262 upload_stream.AppendData(kChunk, arraysize(kChunk) - 1, true); | 261 upload_stream.AppendData(kChunk, arraysize(kChunk) - 1, true); |
| 263 // Write the chunk. | |
| 264 data.RunFor(1); | |
| 265 ASSERT_FALSE(callback.have_result()); | |
| 266 | |
| 267 // Write the trailer. | |
| 268 data.RunFor(1); | |
| 269 ASSERT_TRUE(callback.have_result()); | |
| 270 ASSERT_EQ(OK, callback.WaitForResult()); | 262 ASSERT_EQ(OK, callback.WaitForResult()); |
| 271 | 263 |
| 272 // Attempt to read the response status and the response headers. | 264 // Attempt to read the response status and the response headers. |
| 273 ASSERT_EQ(ERR_IO_PENDING, parser.ReadResponseHeaders(callback.callback())); | 265 ASSERT_EQ(ERR_IO_PENDING, parser.ReadResponseHeaders(callback.callback())); |
| 274 data.RunFor(2); | |
| 275 ASSERT_TRUE(callback.have_result()); | |
| 276 ASSERT_GT(callback.WaitForResult(), 0); | 266 ASSERT_GT(callback.WaitForResult(), 0); |
| 277 | 267 |
| 278 // Finally, attempt to read the response body. | 268 // Finally, attempt to read the response body. |
| 279 scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize)); | 269 scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize)); |
| 280 ASSERT_EQ(ERR_IO_PENDING, | 270 ASSERT_EQ(ERR_IO_PENDING, |
| 281 parser.ReadResponseBody(body_buffer.get(), kBodySize, | 271 parser.ReadResponseBody(body_buffer.get(), kBodySize, |
| 282 callback.callback())); | 272 callback.callback())); |
| 283 data.RunFor(1); | |
| 284 ASSERT_TRUE(callback.have_result()); | |
| 285 ASSERT_EQ(kBodySize, callback.WaitForResult()); | 273 ASSERT_EQ(kBodySize, callback.WaitForResult()); |
| 286 } | 274 } |
| 287 | 275 |
| 288 // Test to ensure the HttpStreamParser state machine does not get confused | 276 // Test to ensure the HttpStreamParser state machine does not get confused |
| 289 // when sending a request with a chunked body with only one chunk that is | 277 // when sending a request with a chunked body with only one chunk that is |
| 290 // available synchronously. | 278 // available synchronously. |
| 291 TEST(HttpStreamParser, SyncSingleChunkAndAsyncSocket) { | 279 TEST(HttpStreamParser, SyncSingleChunkAndAsyncSocket) { |
| 292 static const char kChunk[] = "Chunk"; | 280 static const char kChunk[] = "Chunk"; |
| 293 | 281 |
| 294 MockWrite writes[] = { | 282 MockWrite writes[] = { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 308 MockRead(ASYNC, 4, "Content-Length: 8\r\n\r\n"), | 296 MockRead(ASYNC, 4, "Content-Length: 8\r\n\r\n"), |
| 309 MockRead(ASYNC, 5, "one.html"), | 297 MockRead(ASYNC, 5, "one.html"), |
| 310 MockRead(SYNCHRONOUS, 0, 6), // EOF | 298 MockRead(SYNCHRONOUS, 0, 6), // EOF |
| 311 }; | 299 }; |
| 312 | 300 |
| 313 ChunkedUploadDataStream upload_stream(0); | 301 ChunkedUploadDataStream upload_stream(0); |
| 314 ASSERT_EQ(OK, upload_stream.Init(TestCompletionCallback().callback())); | 302 ASSERT_EQ(OK, upload_stream.Init(TestCompletionCallback().callback())); |
| 315 // Append the only chunk. | 303 // Append the only chunk. |
| 316 upload_stream.AppendData(kChunk, arraysize(kChunk) - 1, true); | 304 upload_stream.AppendData(kChunk, arraysize(kChunk) - 1, true); |
| 317 | 305 |
| 318 DeterministicSocketData data(reads, arraysize(reads), writes, | 306 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes)); |
| 319 arraysize(writes)); | |
| 320 scoped_ptr<ClientSocketHandle> socket_handle = | 307 scoped_ptr<ClientSocketHandle> socket_handle = |
| 321 CreateConnectedSocketHandle(&data); | 308 CreateConnectedSocketHandle(&data); |
| 322 | 309 |
| 323 HttpRequestInfo request_info; | 310 HttpRequestInfo request_info; |
| 324 request_info.method = "GET"; | 311 request_info.method = "GET"; |
| 325 request_info.url = GURL("http://localhost"); | 312 request_info.url = GURL("http://localhost"); |
| 326 request_info.upload_data_stream = &upload_stream; | 313 request_info.upload_data_stream = &upload_stream; |
| 327 | 314 |
| 328 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); | 315 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); |
| 329 HttpStreamParser parser(socket_handle.get(), &request_info, read_buffer.get(), | 316 HttpStreamParser parser(socket_handle.get(), &request_info, read_buffer.get(), |
| 330 BoundNetLog()); | 317 BoundNetLog()); |
| 331 | 318 |
| 332 HttpRequestHeaders request_headers; | 319 HttpRequestHeaders request_headers; |
| 333 request_headers.SetHeader("Transfer-Encoding", "chunked"); | 320 request_headers.SetHeader("Transfer-Encoding", "chunked"); |
| 334 | 321 |
| 335 HttpResponseInfo response_info; | 322 HttpResponseInfo response_info; |
| 336 TestCompletionCallback callback; | 323 TestCompletionCallback callback; |
| 337 // This will attempt to Write() the initial request and headers, which will | 324 // This will attempt to Write() the initial request and headers, which will |
| 338 // complete asynchronously. | 325 // complete asynchronously. |
| 339 ASSERT_EQ(ERR_IO_PENDING, | 326 ASSERT_EQ(ERR_IO_PENDING, |
| 340 parser.SendRequest("GET /one.html HTTP/1.1\r\n", request_headers, | 327 parser.SendRequest("GET /one.html HTTP/1.1\r\n", request_headers, |
| 341 &response_info, callback.callback())); | 328 &response_info, callback.callback())); |
| 342 | |
| 343 // Write the request and the only chunk. | |
| 344 data.RunFor(2); | |
| 345 | |
| 346 // Write the trailer. | |
| 347 data.RunFor(1); | |
| 348 ASSERT_TRUE(callback.have_result()); | |
| 349 ASSERT_EQ(OK, callback.WaitForResult()); | 329 ASSERT_EQ(OK, callback.WaitForResult()); |
| 350 | 330 |
| 351 // Attempt to read the response status and the response headers. | 331 // Attempt to read the response status and the response headers. |
| 352 ASSERT_EQ(ERR_IO_PENDING, parser.ReadResponseHeaders(callback.callback())); | 332 ASSERT_EQ(ERR_IO_PENDING, parser.ReadResponseHeaders(callback.callback())); |
| 353 data.RunFor(2); | |
| 354 ASSERT_TRUE(callback.have_result()); | |
| 355 ASSERT_GT(callback.WaitForResult(), 0); | 333 ASSERT_GT(callback.WaitForResult(), 0); |
| 356 | 334 |
| 357 // Finally, attempt to read the response body. | 335 // Finally, attempt to read the response body. |
| 358 scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize)); | 336 scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize)); |
| 359 ASSERT_EQ(ERR_IO_PENDING, | 337 ASSERT_EQ(ERR_IO_PENDING, |
| 360 parser.ReadResponseBody(body_buffer.get(), kBodySize, | 338 parser.ReadResponseBody(body_buffer.get(), kBodySize, |
| 361 callback.callback())); | 339 callback.callback())); |
| 362 data.RunFor(1); | |
| 363 ASSERT_TRUE(callback.have_result()); | |
| 364 ASSERT_EQ(kBodySize, callback.WaitForResult()); | 340 ASSERT_EQ(kBodySize, callback.WaitForResult()); |
| 365 } | 341 } |
| 366 | 342 |
| 367 // Test to ensure the HttpStreamParser state machine does not get confused | 343 // Test to ensure the HttpStreamParser state machine does not get confused |
| 368 // when sending a request with a chunked body, where chunks become available | 344 // when sending a request with a chunked body, where chunks become available |
| 369 // asynchronously, over a socket where writes may also complete | 345 // asynchronously, over a socket where writes may also complete |
| 370 // asynchronously. | 346 // asynchronously. |
| 371 // This is a regression test for http://crbug.com/132243 | 347 // This is a regression test for http://crbug.com/132243 |
| 372 TEST(HttpStreamParser, AsyncChunkAndAsyncSocketWithMultipleChunks) { | 348 TEST(HttpStreamParser, AsyncChunkAndAsyncSocketWithMultipleChunks) { |
| 373 // The chunks that will be written in the request, as reflected in the | 349 // The chunks that will be written in the request, as reflected in the |
| (...skipping 20 matching lines...) Expand all Loading... |
| 394 MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\n"), | 370 MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\n"), |
| 395 MockRead(ASYNC, 6, "Content-Length: 8\r\n\r\n"), | 371 MockRead(ASYNC, 6, "Content-Length: 8\r\n\r\n"), |
| 396 MockRead(ASYNC, 7, "one.html"), | 372 MockRead(ASYNC, 7, "one.html"), |
| 397 MockRead(SYNCHRONOUS, 0, 8), // EOF | 373 MockRead(SYNCHRONOUS, 0, 8), // EOF |
| 398 }; | 374 }; |
| 399 | 375 |
| 400 ChunkedUploadDataStream upload_stream(0); | 376 ChunkedUploadDataStream upload_stream(0); |
| 401 upload_stream.AppendData(kChunk1, arraysize(kChunk1) - 1, false); | 377 upload_stream.AppendData(kChunk1, arraysize(kChunk1) - 1, false); |
| 402 ASSERT_EQ(OK, upload_stream.Init(TestCompletionCallback().callback())); | 378 ASSERT_EQ(OK, upload_stream.Init(TestCompletionCallback().callback())); |
| 403 | 379 |
| 404 DeterministicSocketData data(reads, arraysize(reads), writes, | 380 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes)); |
| 405 arraysize(writes)); | |
| 406 scoped_ptr<ClientSocketHandle> socket_handle = | 381 scoped_ptr<ClientSocketHandle> socket_handle = |
| 407 CreateConnectedSocketHandle(&data); | 382 CreateConnectedSocketHandle(&data); |
| 408 | 383 |
| 409 HttpRequestInfo request_info; | 384 HttpRequestInfo request_info; |
| 410 request_info.method = "GET"; | 385 request_info.method = "GET"; |
| 411 request_info.url = GURL("http://localhost"); | 386 request_info.url = GURL("http://localhost"); |
| 412 request_info.upload_data_stream = &upload_stream; | 387 request_info.upload_data_stream = &upload_stream; |
| 413 | 388 |
| 414 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); | 389 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); |
| 415 HttpStreamParser parser( | 390 HttpStreamParser parser( |
| 416 socket_handle.get(), &request_info, read_buffer.get(), BoundNetLog()); | 391 socket_handle.get(), &request_info, read_buffer.get(), BoundNetLog()); |
| 417 | 392 |
| 418 HttpRequestHeaders request_headers; | 393 HttpRequestHeaders request_headers; |
| 419 request_headers.SetHeader("Transfer-Encoding", "chunked"); | 394 request_headers.SetHeader("Transfer-Encoding", "chunked"); |
| 420 | 395 |
| 421 HttpResponseInfo response_info; | 396 HttpResponseInfo response_info; |
| 422 TestCompletionCallback callback; | 397 TestCompletionCallback callback; |
| 423 // This will attempt to Write() the initial request and headers, which will | 398 // This will attempt to Write() the initial request and headers, which will |
| 424 // complete asynchronously. | 399 // complete asynchronously. |
| 425 ASSERT_EQ(ERR_IO_PENDING, | 400 ASSERT_EQ(ERR_IO_PENDING, |
| 426 parser.SendRequest("GET /one.html HTTP/1.1\r\n", request_headers, | 401 parser.SendRequest("GET /one.html HTTP/1.1\r\n", request_headers, |
| 427 &response_info, callback.callback())); | 402 &response_info, callback.callback())); |
| 428 | |
| 429 // Complete the initial request write. Additionally, this should enqueue the | |
| 430 // first chunk. | |
| 431 data.RunFor(1); | |
| 432 ASSERT_FALSE(callback.have_result()); | 403 ASSERT_FALSE(callback.have_result()); |
| 433 | 404 |
| 434 // Now append another chunk (while the first write is still pending), which | 405 // Sending the request and the first chunk completes. |
| 435 // should not confuse the state machine. | 406 base::RunLoop().RunUntilIdle(); |
| 407 ASSERT_FALSE(callback.have_result()); |
| 408 |
| 409 // Now append another chunk. |
| 436 upload_stream.AppendData(kChunk2, arraysize(kChunk2) - 1, false); | 410 upload_stream.AppendData(kChunk2, arraysize(kChunk2) - 1, false); |
| 437 ASSERT_FALSE(callback.have_result()); | 411 ASSERT_FALSE(callback.have_result()); |
| 438 | 412 |
| 439 // Complete writing the first chunk, which should then enqueue the second | 413 // Add the final chunk, while the write for the second is still pending, |
| 440 // chunk for writing and return, because it is set to complete | 414 // which should not confuse the state machine. |
| 441 // asynchronously. | |
| 442 data.RunFor(1); | |
| 443 ASSERT_FALSE(callback.have_result()); | |
| 444 | |
| 445 // Complete writing the second chunk. However, because no chunks are | |
| 446 // available yet, no further writes should be called until a new chunk is | |
| 447 // added. | |
| 448 data.RunFor(1); | |
| 449 ASSERT_FALSE(callback.have_result()); | |
| 450 | |
| 451 // Add the final chunk. This will enqueue another write, but it will not | |
| 452 // complete due to the async nature. | |
| 453 upload_stream.AppendData(kChunk3, arraysize(kChunk3) - 1, true); | 415 upload_stream.AppendData(kChunk3, arraysize(kChunk3) - 1, true); |
| 454 ASSERT_FALSE(callback.have_result()); | 416 ASSERT_FALSE(callback.have_result()); |
| 455 | 417 |
| 456 // Finalize writing the last chunk, which will enqueue the trailer. | 418 // Wait for writes to complete. |
| 457 data.RunFor(1); | |
| 458 ASSERT_FALSE(callback.have_result()); | |
| 459 | |
| 460 // Finalize writing the trailer. | |
| 461 data.RunFor(1); | |
| 462 ASSERT_TRUE(callback.have_result()); | |
| 463 ASSERT_EQ(OK, callback.WaitForResult()); | 419 ASSERT_EQ(OK, callback.WaitForResult()); |
| 464 | 420 |
| 465 // Attempt to read the response status and the response headers. | 421 // Attempt to read the response status and the response headers. |
| 466 ASSERT_EQ(ERR_IO_PENDING, parser.ReadResponseHeaders(callback.callback())); | 422 ASSERT_EQ(ERR_IO_PENDING, parser.ReadResponseHeaders(callback.callback())); |
| 467 data.RunFor(2); | |
| 468 ASSERT_TRUE(callback.have_result()); | |
| 469 ASSERT_GT(callback.WaitForResult(), 0); | 423 ASSERT_GT(callback.WaitForResult(), 0); |
| 470 | 424 |
| 471 // Finally, attempt to read the response body. | 425 // Finally, attempt to read the response body. |
| 472 scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize)); | 426 scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize)); |
| 473 ASSERT_EQ(ERR_IO_PENDING, | 427 ASSERT_EQ(ERR_IO_PENDING, |
| 474 parser.ReadResponseBody(body_buffer.get(), kBodySize, | 428 parser.ReadResponseBody(body_buffer.get(), kBodySize, |
| 475 callback.callback())); | 429 callback.callback())); |
| 476 data.RunFor(1); | |
| 477 ASSERT_TRUE(callback.have_result()); | |
| 478 ASSERT_EQ(kBodySize, callback.WaitForResult()); | 430 ASSERT_EQ(kBodySize, callback.WaitForResult()); |
| 479 } | 431 } |
| 480 | 432 |
| 481 // Test to ensure the HttpStreamParser state machine does not get confused | 433 // Test to ensure the HttpStreamParser state machine does not get confused |
| 482 // when there's only one "chunk" with 0 bytes, and is received from the | 434 // when there's only one "chunk" with 0 bytes, and is received from the |
| 483 // UploadStream only after sending the request headers successfully. | 435 // UploadStream only after sending the request headers successfully. |
| 484 TEST(HttpStreamParser, AsyncEmptyChunkedUpload) { | 436 TEST(HttpStreamParser, AsyncEmptyChunkedUpload) { |
| 485 MockWrite writes[] = { | 437 MockWrite writes[] = { |
| 486 MockWrite(ASYNC, 0, | 438 MockWrite(ASYNC, 0, |
| 487 "GET /one.html HTTP/1.1\r\n" | 439 "GET /one.html HTTP/1.1\r\n" |
| 488 "Transfer-Encoding: chunked\r\n\r\n"), | 440 "Transfer-Encoding: chunked\r\n\r\n"), |
| 489 MockWrite(ASYNC, 1, "0\r\n\r\n"), | 441 MockWrite(ASYNC, 1, "0\r\n\r\n"), |
| 490 }; | 442 }; |
| 491 | 443 |
| 492 // The size of the response body, as reflected in the Content-Length of the | 444 // The size of the response body, as reflected in the Content-Length of the |
| 493 // MockRead below. | 445 // MockRead below. |
| 494 const int kBodySize = 8; | 446 const int kBodySize = 8; |
| 495 | 447 |
| 496 MockRead reads[] = { | 448 MockRead reads[] = { |
| 497 MockRead(ASYNC, 2, "HTTP/1.1 200 OK\r\n"), | 449 MockRead(ASYNC, 2, "HTTP/1.1 200 OK\r\n"), |
| 498 MockRead(ASYNC, 3, "Content-Length: 8\r\n\r\n"), | 450 MockRead(ASYNC, 3, "Content-Length: 8\r\n\r\n"), |
| 499 MockRead(ASYNC, 4, "one.html"), | 451 MockRead(ASYNC, 4, "one.html"), |
| 500 MockRead(SYNCHRONOUS, 0, 5), // EOF | 452 MockRead(SYNCHRONOUS, 0, 5), // EOF |
| 501 }; | 453 }; |
| 502 | 454 |
| 503 ChunkedUploadDataStream upload_stream(0); | 455 ChunkedUploadDataStream upload_stream(0); |
| 504 ASSERT_EQ(OK, upload_stream.Init(TestCompletionCallback().callback())); | 456 ASSERT_EQ(OK, upload_stream.Init(TestCompletionCallback().callback())); |
| 505 | 457 |
| 506 DeterministicSocketData data(reads, arraysize(reads), writes, | 458 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes)); |
| 507 arraysize(writes)); | |
| 508 scoped_ptr<ClientSocketHandle> socket_handle = | 459 scoped_ptr<ClientSocketHandle> socket_handle = |
| 509 CreateConnectedSocketHandle(&data); | 460 CreateConnectedSocketHandle(&data); |
| 510 | 461 |
| 511 HttpRequestInfo request_info; | 462 HttpRequestInfo request_info; |
| 512 request_info.method = "GET"; | 463 request_info.method = "GET"; |
| 513 request_info.url = GURL("http://localhost"); | 464 request_info.url = GURL("http://localhost"); |
| 514 request_info.upload_data_stream = &upload_stream; | 465 request_info.upload_data_stream = &upload_stream; |
| 515 | 466 |
| 516 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); | 467 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); |
| 517 HttpStreamParser parser(socket_handle.get(), &request_info, read_buffer.get(), | 468 HttpStreamParser parser(socket_handle.get(), &request_info, read_buffer.get(), |
| 518 BoundNetLog()); | 469 BoundNetLog()); |
| 519 | 470 |
| 520 HttpRequestHeaders request_headers; | 471 HttpRequestHeaders request_headers; |
| 521 request_headers.SetHeader("Transfer-Encoding", "chunked"); | 472 request_headers.SetHeader("Transfer-Encoding", "chunked"); |
| 522 | 473 |
| 523 HttpResponseInfo response_info; | 474 HttpResponseInfo response_info; |
| 524 TestCompletionCallback callback; | 475 TestCompletionCallback callback; |
| 525 // This will attempt to Write() the initial request and headers, which will | 476 // This will attempt to Write() the initial request and headers, which will |
| 526 // complete asynchronously. | 477 // complete asynchronously. |
| 527 ASSERT_EQ(ERR_IO_PENDING, | 478 ASSERT_EQ(ERR_IO_PENDING, |
| 528 parser.SendRequest("GET /one.html HTTP/1.1\r\n", request_headers, | 479 parser.SendRequest("GET /one.html HTTP/1.1\r\n", request_headers, |
| 529 &response_info, callback.callback())); | 480 &response_info, callback.callback())); |
| 530 | 481 |
| 531 // Complete writing the request headers. | |
| 532 data.RunFor(1); | |
| 533 ASSERT_FALSE(callback.have_result()); | |
| 534 | |
| 535 // Now append the terminal 0-byte "chunk". | 482 // Now append the terminal 0-byte "chunk". |
| 536 upload_stream.AppendData(nullptr, 0, true); | 483 upload_stream.AppendData(nullptr, 0, true); |
| 537 ASSERT_FALSE(callback.have_result()); | 484 ASSERT_FALSE(callback.have_result()); |
| 538 | 485 |
| 539 // Finalize writing the trailer. | |
| 540 data.RunFor(1); | |
| 541 ASSERT_TRUE(callback.have_result()); | |
| 542 ASSERT_EQ(OK, callback.WaitForResult()); | 486 ASSERT_EQ(OK, callback.WaitForResult()); |
| 543 | 487 |
| 544 // Attempt to read the response status and the response headers. | 488 // Attempt to read the response status and the response headers. |
| 545 ASSERT_EQ(ERR_IO_PENDING, parser.ReadResponseHeaders(callback.callback())); | 489 ASSERT_EQ(ERR_IO_PENDING, parser.ReadResponseHeaders(callback.callback())); |
| 546 data.RunFor(2); | |
| 547 ASSERT_TRUE(callback.have_result()); | |
| 548 ASSERT_GT(callback.WaitForResult(), 0); | 490 ASSERT_GT(callback.WaitForResult(), 0); |
| 549 | 491 |
| 550 // Finally, attempt to read the response body. | 492 // Finally, attempt to read the response body. |
| 551 scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize)); | 493 scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize)); |
| 552 ASSERT_EQ(ERR_IO_PENDING, | 494 ASSERT_EQ(ERR_IO_PENDING, |
| 553 parser.ReadResponseBody(body_buffer.get(), kBodySize, | 495 parser.ReadResponseBody(body_buffer.get(), kBodySize, |
| 554 callback.callback())); | 496 callback.callback())); |
| 555 data.RunFor(1); | |
| 556 ASSERT_TRUE(callback.have_result()); | |
| 557 ASSERT_EQ(kBodySize, callback.WaitForResult()); | 497 ASSERT_EQ(kBodySize, callback.WaitForResult()); |
| 558 } | 498 } |
| 559 | 499 |
| 560 // Test to ensure the HttpStreamParser state machine does not get confused | 500 // Test to ensure the HttpStreamParser state machine does not get confused |
| 561 // when there's only one "chunk" with 0 bytes, which was already appended before | 501 // when there's only one "chunk" with 0 bytes, which was already appended before |
| 562 // the request was started. | 502 // the request was started. |
| 563 TEST(HttpStreamParser, SyncEmptyChunkedUpload) { | 503 TEST(HttpStreamParser, SyncEmptyChunkedUpload) { |
| 564 MockWrite writes[] = { | 504 MockWrite writes[] = { |
| 565 MockWrite(ASYNC, 0, | 505 MockWrite(ASYNC, 0, |
| 566 "GET /one.html HTTP/1.1\r\n" | 506 "GET /one.html HTTP/1.1\r\n" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 577 MockRead(ASYNC, 3, "Content-Length: 8\r\n\r\n"), | 517 MockRead(ASYNC, 3, "Content-Length: 8\r\n\r\n"), |
| 578 MockRead(ASYNC, 4, "one.html"), | 518 MockRead(ASYNC, 4, "one.html"), |
| 579 MockRead(SYNCHRONOUS, 0, 5), // EOF | 519 MockRead(SYNCHRONOUS, 0, 5), // EOF |
| 580 }; | 520 }; |
| 581 | 521 |
| 582 ChunkedUploadDataStream upload_stream(0); | 522 ChunkedUploadDataStream upload_stream(0); |
| 583 ASSERT_EQ(OK, upload_stream.Init(TestCompletionCallback().callback())); | 523 ASSERT_EQ(OK, upload_stream.Init(TestCompletionCallback().callback())); |
| 584 // Append final empty chunk. | 524 // Append final empty chunk. |
| 585 upload_stream.AppendData(nullptr, 0, true); | 525 upload_stream.AppendData(nullptr, 0, true); |
| 586 | 526 |
| 587 DeterministicSocketData data(reads, arraysize(reads), writes, | 527 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes)); |
| 588 arraysize(writes)); | |
| 589 scoped_ptr<ClientSocketHandle> socket_handle = | 528 scoped_ptr<ClientSocketHandle> socket_handle = |
| 590 CreateConnectedSocketHandle(&data); | 529 CreateConnectedSocketHandle(&data); |
| 591 | 530 |
| 592 HttpRequestInfo request_info; | 531 HttpRequestInfo request_info; |
| 593 request_info.method = "GET"; | 532 request_info.method = "GET"; |
| 594 request_info.url = GURL("http://localhost"); | 533 request_info.url = GURL("http://localhost"); |
| 595 request_info.upload_data_stream = &upload_stream; | 534 request_info.upload_data_stream = &upload_stream; |
| 596 | 535 |
| 597 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); | 536 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); |
| 598 HttpStreamParser parser(socket_handle.get(), &request_info, read_buffer.get(), | 537 HttpStreamParser parser(socket_handle.get(), &request_info, read_buffer.get(), |
| 599 BoundNetLog()); | 538 BoundNetLog()); |
| 600 | 539 |
| 601 HttpRequestHeaders request_headers; | 540 HttpRequestHeaders request_headers; |
| 602 request_headers.SetHeader("Transfer-Encoding", "chunked"); | 541 request_headers.SetHeader("Transfer-Encoding", "chunked"); |
| 603 | 542 |
| 604 HttpResponseInfo response_info; | 543 HttpResponseInfo response_info; |
| 605 TestCompletionCallback callback; | 544 TestCompletionCallback callback; |
| 606 // This will attempt to Write() the initial request and headers, which will | 545 // This will attempt to Write() the initial request and headers, which will |
| 607 // complete asynchronously. | 546 // complete asynchronously. |
| 608 ASSERT_EQ(ERR_IO_PENDING, | 547 ASSERT_EQ(ERR_IO_PENDING, |
| 609 parser.SendRequest("GET /one.html HTTP/1.1\r\n", request_headers, | 548 parser.SendRequest("GET /one.html HTTP/1.1\r\n", request_headers, |
| 610 &response_info, callback.callback())); | 549 &response_info, callback.callback())); |
| 611 | 550 |
| 612 // Complete writing the request headers and body. | 551 // Complete writing the request headers and body. |
| 613 data.RunFor(2); | |
| 614 ASSERT_TRUE(callback.have_result()); | |
| 615 ASSERT_EQ(OK, callback.WaitForResult()); | 552 ASSERT_EQ(OK, callback.WaitForResult()); |
| 616 | 553 |
| 617 // Attempt to read the response status and the response headers. | 554 // Attempt to read the response status and the response headers. |
| 618 ASSERT_EQ(ERR_IO_PENDING, parser.ReadResponseHeaders(callback.callback())); | 555 ASSERT_EQ(ERR_IO_PENDING, parser.ReadResponseHeaders(callback.callback())); |
| 619 data.RunFor(2); | |
| 620 ASSERT_TRUE(callback.have_result()); | |
| 621 ASSERT_GT(callback.WaitForResult(), 0); | 556 ASSERT_GT(callback.WaitForResult(), 0); |
| 622 | 557 |
| 623 // Finally, attempt to read the response body. | 558 // Finally, attempt to read the response body. |
| 624 scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize)); | 559 scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize)); |
| 625 ASSERT_EQ(ERR_IO_PENDING, | 560 ASSERT_EQ(ERR_IO_PENDING, |
| 626 parser.ReadResponseBody(body_buffer.get(), kBodySize, | 561 parser.ReadResponseBody(body_buffer.get(), kBodySize, |
| 627 callback.callback())); | 562 callback.callback())); |
| 628 data.RunFor(1); | |
| 629 ASSERT_TRUE(callback.have_result()); | |
| 630 ASSERT_EQ(kBodySize, callback.WaitForResult()); | 563 ASSERT_EQ(kBodySize, callback.WaitForResult()); |
| 631 } | 564 } |
| 632 | 565 |
| 633 TEST(HttpStreamParser, TruncatedHeaders) { | 566 TEST(HttpStreamParser, TruncatedHeaders) { |
| 634 MockRead truncated_status_reads[] = { | 567 MockRead truncated_status_reads[] = { |
| 635 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 20"), | 568 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 20"), |
| 636 MockRead(SYNCHRONOUS, 0, 2), // EOF | 569 MockRead(SYNCHRONOUS, 0, 2), // EOF |
| 637 }; | 570 }; |
| 638 | 571 |
| 639 MockRead truncated_after_status_reads[] = { | 572 MockRead truncated_after_status_reads[] = { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 678 HTTP = 0, | 611 HTTP = 0, |
| 679 HTTPS, | 612 HTTPS, |
| 680 NUM_PROTOCOLS, | 613 NUM_PROTOCOLS, |
| 681 }; | 614 }; |
| 682 | 615 |
| 683 for (size_t protocol = 0; protocol < NUM_PROTOCOLS; protocol++) { | 616 for (size_t protocol = 0; protocol < NUM_PROTOCOLS; protocol++) { |
| 684 SCOPED_TRACE(protocol); | 617 SCOPED_TRACE(protocol); |
| 685 | 618 |
| 686 for (size_t i = 0; i < arraysize(reads); i++) { | 619 for (size_t i = 0; i < arraysize(reads); i++) { |
| 687 SCOPED_TRACE(i); | 620 SCOPED_TRACE(i); |
| 688 DeterministicSocketData data(reads[i], 2, writes, arraysize(writes)); | 621 SequencedSocketData data(reads[i], 2, writes, arraysize(writes)); |
| 689 data.set_connect_data(MockConnect(SYNCHRONOUS, OK)); | 622 scoped_ptr<ClientSocketHandle> socket_handle( |
| 690 data.SetStop(3); | 623 CreateConnectedSocketHandle(&data)); |
| 691 | |
| 692 scoped_ptr<DeterministicMockTCPClientSocket> transport( | |
| 693 new DeterministicMockTCPClientSocket(NULL, &data)); | |
| 694 data.set_delegate(transport->AsWeakPtr()); | |
| 695 | |
| 696 TestCompletionCallback callback; | |
| 697 int rv = transport->Connect(callback.callback()); | |
| 698 ASSERT_EQ(OK, rv); | |
| 699 | |
| 700 scoped_ptr<ClientSocketHandle> socket_handle(new ClientSocketHandle); | |
| 701 socket_handle->SetSocket(transport.Pass()); | |
| 702 | 624 |
| 703 HttpRequestInfo request_info; | 625 HttpRequestInfo request_info; |
| 704 request_info.method = "GET"; | 626 request_info.method = "GET"; |
| 705 if (protocol == HTTP) { | 627 if (protocol == HTTP) { |
| 706 request_info.url = GURL("http://localhost"); | 628 request_info.url = GURL("http://localhost"); |
| 707 } else { | 629 } else { |
| 708 request_info.url = GURL("https://localhost"); | 630 request_info.url = GURL("https://localhost"); |
| 709 } | 631 } |
| 710 request_info.load_flags = LOAD_NORMAL; | 632 request_info.load_flags = LOAD_NORMAL; |
| 711 | 633 |
| 712 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); | 634 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); |
| 713 HttpStreamParser parser( | 635 HttpStreamParser parser( |
| 714 socket_handle.get(), &request_info, read_buffer.get(), BoundNetLog()); | 636 socket_handle.get(), &request_info, read_buffer.get(), BoundNetLog()); |
| 715 | 637 |
| 716 HttpRequestHeaders request_headers; | 638 HttpRequestHeaders request_headers; |
| 717 HttpResponseInfo response_info; | 639 HttpResponseInfo response_info; |
| 718 rv = parser.SendRequest("GET / HTTP/1.1\r\n", request_headers, | 640 TestCompletionCallback callback; |
| 719 &response_info, callback.callback()); | 641 ASSERT_EQ(OK, parser.SendRequest("GET / HTTP/1.1\r\n", request_headers, |
| 720 ASSERT_EQ(OK, rv); | 642 &response_info, callback.callback())); |
| 721 | 643 |
| 722 rv = parser.ReadResponseHeaders(callback.callback()); | 644 int rv = parser.ReadResponseHeaders(callback.callback()); |
| 723 if (i == arraysize(reads) - 1) { | 645 if (i == arraysize(reads) - 1) { |
| 724 EXPECT_EQ(OK, rv); | 646 EXPECT_EQ(OK, rv); |
| 725 EXPECT_TRUE(response_info.headers.get()); | 647 EXPECT_TRUE(response_info.headers.get()); |
| 726 } else { | 648 } else { |
| 727 if (protocol == HTTP) { | 649 if (protocol == HTTP) { |
| 728 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv); | 650 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv); |
| 729 EXPECT_TRUE(response_info.headers.get()); | 651 EXPECT_TRUE(response_info.headers.get()); |
| 730 } else { | 652 } else { |
| 731 EXPECT_EQ(ERR_RESPONSE_HEADERS_TRUNCATED, rv); | 653 EXPECT_EQ(ERR_RESPONSE_HEADERS_TRUNCATED, rv); |
| 732 EXPECT_FALSE(response_info.headers.get()); | 654 EXPECT_FALSE(response_info.headers.get()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 745 "Upgrade: websocket\r\n" | 667 "Upgrade: websocket\r\n" |
| 746 "Connection: Upgrade\r\n" | 668 "Connection: Upgrade\r\n" |
| 747 "\r\n" | 669 "\r\n" |
| 748 "a fake websocket frame"), | 670 "a fake websocket frame"), |
| 749 }; | 671 }; |
| 750 | 672 |
| 751 MockWrite writes[] = { | 673 MockWrite writes[] = { |
| 752 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n"), | 674 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n"), |
| 753 }; | 675 }; |
| 754 | 676 |
| 755 DeterministicSocketData data(reads, arraysize(reads), | 677 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes)); |
| 756 writes, arraysize(writes)); | 678 scoped_ptr<ClientSocketHandle> socket_handle = |
| 757 data.set_connect_data(MockConnect(SYNCHRONOUS, OK)); | 679 CreateConnectedSocketHandle(&data); |
| 758 data.SetStop(2); | |
| 759 | |
| 760 scoped_ptr<DeterministicMockTCPClientSocket> transport( | |
| 761 new DeterministicMockTCPClientSocket(NULL, &data)); | |
| 762 data.set_delegate(transport->AsWeakPtr()); | |
| 763 | |
| 764 TestCompletionCallback callback; | |
| 765 int rv = transport->Connect(callback.callback()); | |
| 766 ASSERT_EQ(OK, rv); | |
| 767 | |
| 768 scoped_ptr<ClientSocketHandle> socket_handle(new ClientSocketHandle); | |
| 769 socket_handle->SetSocket(transport.Pass()); | |
| 770 | 680 |
| 771 HttpRequestInfo request_info; | 681 HttpRequestInfo request_info; |
| 772 request_info.method = "GET"; | 682 request_info.method = "GET"; |
| 773 request_info.url = GURL("http://localhost"); | 683 request_info.url = GURL("http://localhost"); |
| 774 request_info.load_flags = LOAD_NORMAL; | 684 request_info.load_flags = LOAD_NORMAL; |
| 775 | 685 |
| 776 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); | 686 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); |
| 777 HttpStreamParser parser( | 687 HttpStreamParser parser( |
| 778 socket_handle.get(), &request_info, read_buffer.get(), BoundNetLog()); | 688 socket_handle.get(), &request_info, read_buffer.get(), BoundNetLog()); |
| 779 | 689 |
| 780 HttpRequestHeaders request_headers; | 690 HttpRequestHeaders request_headers; |
| 781 HttpResponseInfo response_info; | 691 HttpResponseInfo response_info; |
| 782 rv = parser.SendRequest("GET / HTTP/1.1\r\n", request_headers, | 692 TestCompletionCallback callback; |
| 783 &response_info, callback.callback()); | 693 ASSERT_EQ(OK, parser.SendRequest("GET / HTTP/1.1\r\n", request_headers, |
| 784 ASSERT_EQ(OK, rv); | 694 &response_info, callback.callback())); |
| 785 | 695 |
| 786 rv = parser.ReadResponseHeaders(callback.callback()); | 696 EXPECT_EQ(OK, parser.ReadResponseHeaders(callback.callback())); |
| 787 EXPECT_EQ(OK, rv); | |
| 788 ASSERT_TRUE(response_info.headers.get()); | 697 ASSERT_TRUE(response_info.headers.get()); |
| 789 EXPECT_EQ(101, response_info.headers->response_code()); | 698 EXPECT_EQ(101, response_info.headers->response_code()); |
| 790 EXPECT_TRUE(response_info.headers->HasHeaderValue("Connection", "Upgrade")); | 699 EXPECT_TRUE(response_info.headers->HasHeaderValue("Connection", "Upgrade")); |
| 791 EXPECT_TRUE(response_info.headers->HasHeaderValue("Upgrade", "websocket")); | 700 EXPECT_TRUE(response_info.headers->HasHeaderValue("Upgrade", "websocket")); |
| 792 EXPECT_EQ(read_buffer->capacity(), read_buffer->offset()); | 701 EXPECT_EQ(read_buffer->capacity(), read_buffer->offset()); |
| 793 EXPECT_EQ("a fake websocket frame", | 702 EXPECT_EQ("a fake websocket frame", |
| 794 base::StringPiece(read_buffer->StartOfBuffer(), | 703 base::StringPiece(read_buffer->StartOfBuffer(), |
| 795 read_buffer->capacity())); | 704 read_buffer->capacity())); |
| 796 } | 705 } |
| 797 | 706 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 815 read_buffer_->set_offset(offset + size); | 724 read_buffer_->set_offset(offset + size); |
| 816 } | 725 } |
| 817 | 726 |
| 818 void AddRead(const std::string& data) { | 727 void AddRead(const std::string& data) { |
| 819 reads_.push_back(MockRead(SYNCHRONOUS, sequence_number_++, data.data())); | 728 reads_.push_back(MockRead(SYNCHRONOUS, sequence_number_++, data.data())); |
| 820 } | 729 } |
| 821 | 730 |
| 822 void SetupParserAndSendRequest() { | 731 void SetupParserAndSendRequest() { |
| 823 reads_.push_back(MockRead(SYNCHRONOUS, 0, sequence_number_++)); // EOF | 732 reads_.push_back(MockRead(SYNCHRONOUS, 0, sequence_number_++)); // EOF |
| 824 | 733 |
| 825 socket_handle_.reset(new ClientSocketHandle); | 734 data_.reset(new SequencedSocketData(&reads_.front(), reads_.size(), |
| 826 data_.reset(new DeterministicSocketData( | 735 &writes_.front(), writes_.size())); |
| 827 &reads_.front(), reads_.size(), &writes_.front(), writes_.size())); | 736 socket_handle_ = CreateConnectedSocketHandle(data_.get()); |
| 828 data_->set_connect_data(MockConnect(SYNCHRONOUS, OK)); | |
| 829 data_->SetStop(reads_.size() + writes_.size()); | |
| 830 | |
| 831 transport_.reset(new DeterministicMockTCPClientSocket(NULL, data_.get())); | |
| 832 data_->set_delegate(transport_->AsWeakPtr()); | |
| 833 | |
| 834 TestCompletionCallback callback; | |
| 835 int rv = transport_->Connect(callback.callback()); | |
| 836 rv = callback.GetResult(rv); | |
| 837 ASSERT_EQ(OK, rv); | |
| 838 | |
| 839 socket_handle_->SetSocket(transport_.Pass()); | |
| 840 | 737 |
| 841 request_info_.method = "GET"; | 738 request_info_.method = "GET"; |
| 842 request_info_.url = GURL("http://localhost"); | 739 request_info_.url = GURL("http://localhost"); |
| 843 request_info_.load_flags = LOAD_NORMAL; | 740 request_info_.load_flags = LOAD_NORMAL; |
| 844 | 741 |
| 845 parser_.reset(new HttpStreamParser( | 742 parser_.reset(new HttpStreamParser( |
| 846 socket_handle_.get(), &request_info_, read_buffer(), BoundNetLog())); | 743 socket_handle_.get(), &request_info_, read_buffer(), BoundNetLog())); |
| 847 | 744 |
| 848 rv = parser_->SendRequest("GET / HTTP/1.1\r\n", request_headers_, | 745 TestCompletionCallback callback; |
| 849 &response_info_, callback.callback()); | 746 ASSERT_EQ(OK, parser_->SendRequest("GET / HTTP/1.1\r\n", request_headers_, |
| 850 ASSERT_EQ(OK, rv); | 747 &response_info_, callback.callback())); |
| 851 } | 748 } |
| 852 | 749 |
| 853 void ReadHeaders() { | 750 void ReadHeaders() { |
| 854 TestCompletionCallback callback; | 751 TestCompletionCallback callback; |
| 855 EXPECT_EQ(OK, parser_->ReadResponseHeaders(callback.callback())); | 752 EXPECT_EQ(OK, parser_->ReadResponseHeaders(callback.callback())); |
| 856 } | 753 } |
| 857 | 754 |
| 858 void ReadBody(int user_buf_len, int* read_lengths) { | 755 void ReadBody(int user_buf_len, int* read_lengths) { |
| 859 TestCompletionCallback callback; | 756 TestCompletionCallback callback; |
| 860 scoped_refptr<IOBuffer> buffer = new IOBuffer(user_buf_len); | 757 scoped_refptr<IOBuffer> buffer = new IOBuffer(user_buf_len); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 871 } | 768 } |
| 872 | 769 |
| 873 private: | 770 private: |
| 874 HttpRequestHeaders request_headers_; | 771 HttpRequestHeaders request_headers_; |
| 875 HttpResponseInfo response_info_; | 772 HttpResponseInfo response_info_; |
| 876 HttpRequestInfo request_info_; | 773 HttpRequestInfo request_info_; |
| 877 scoped_refptr<GrowableIOBuffer> read_buffer_; | 774 scoped_refptr<GrowableIOBuffer> read_buffer_; |
| 878 std::vector<MockRead> reads_; | 775 std::vector<MockRead> reads_; |
| 879 std::vector<MockWrite> writes_; | 776 std::vector<MockWrite> writes_; |
| 880 scoped_ptr<ClientSocketHandle> socket_handle_; | 777 scoped_ptr<ClientSocketHandle> socket_handle_; |
| 881 scoped_ptr<DeterministicSocketData> data_; | 778 scoped_ptr<SequencedSocketData> data_; |
| 882 scoped_ptr<DeterministicMockTCPClientSocket> transport_; | |
| 883 scoped_ptr<HttpStreamParser> parser_; | 779 scoped_ptr<HttpStreamParser> parser_; |
| 884 int sequence_number_; | 780 int sequence_number_; |
| 885 }; | 781 }; |
| 886 | 782 |
| 887 // Test that HTTP/0.9 response size is correctly calculated. | 783 // Test that HTTP/0.9 response size is correctly calculated. |
| 888 TEST(HttpStreamParser, ReceivedBytesNoHeaders) { | 784 TEST(HttpStreamParser, ReceivedBytesNoHeaders) { |
| 889 std::string response = "hello\r\nworld\r\n"; | 785 std::string response = "hello\r\nworld\r\n"; |
| 890 | 786 |
| 891 SimpleGetRunner get_runner; | 787 SimpleGetRunner get_runner; |
| 892 get_runner.AddRead(response); | 788 get_runner.AddRead(response); |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1111 EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); | 1007 EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); |
| 1112 } | 1008 } |
| 1113 | 1009 |
| 1114 // Test that an HttpStreamParser can be read from after it's received headers | 1010 // Test that an HttpStreamParser can be read from after it's received headers |
| 1115 // and data structures owned by its owner have been deleted. This happens | 1011 // and data structures owned by its owner have been deleted. This happens |
| 1116 // when a ResponseBodyDrainer is used. | 1012 // when a ResponseBodyDrainer is used. |
| 1117 TEST(HttpStreamParser, ReadAfterUnownedObjectsDestroyed) { | 1013 TEST(HttpStreamParser, ReadAfterUnownedObjectsDestroyed) { |
| 1118 MockWrite writes[] = { | 1014 MockWrite writes[] = { |
| 1119 MockWrite(SYNCHRONOUS, 0, | 1015 MockWrite(SYNCHRONOUS, 0, |
| 1120 "GET /foo.html HTTP/1.1\r\n\r\n"), | 1016 "GET /foo.html HTTP/1.1\r\n\r\n"), |
| 1121 MockWrite(SYNCHRONOUS, 1, "1"), | |
| 1122 }; | 1017 }; |
| 1123 | 1018 |
| 1124 const int kBodySize = 1; | 1019 const int kBodySize = 1; |
| 1125 MockRead reads[] = { | 1020 MockRead reads[] = { |
| 1126 MockRead(SYNCHRONOUS, 5, "HTTP/1.1 200 OK\r\n"), | 1021 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), |
| 1127 MockRead(SYNCHRONOUS, 6, "Content-Length: 1\r\n\r\n"), | 1022 MockRead(SYNCHRONOUS, 2, "Content-Length: 1\r\n\r\n"), |
| 1128 MockRead(SYNCHRONOUS, 6, "Connection: Keep-Alive\r\n\r\n"), | 1023 MockRead(SYNCHRONOUS, 3, "Connection: Keep-Alive\r\n\r\n"), |
| 1129 MockRead(SYNCHRONOUS, 7, "1"), | 1024 MockRead(SYNCHRONOUS, 4, "1"), |
| 1130 MockRead(SYNCHRONOUS, 0, 8), // EOF | 1025 MockRead(SYNCHRONOUS, 0, 5), // EOF |
| 1131 }; | 1026 }; |
| 1132 | 1027 |
| 1133 StaticSocketDataProvider data(reads, arraysize(reads), writes, | 1028 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes)); |
| 1134 arraysize(writes)); | 1029 scoped_ptr<ClientSocketHandle> socket_handle = |
| 1135 data.set_connect_data(MockConnect(SYNCHRONOUS, OK)); | 1030 CreateConnectedSocketHandle(&data); |
| 1136 | |
| 1137 scoped_ptr<MockTCPClientSocket> transport( | |
| 1138 new MockTCPClientSocket(AddressList(), NULL, &data)); | |
| 1139 | |
| 1140 TestCompletionCallback callback; | |
| 1141 ASSERT_EQ(OK, transport->Connect(callback.callback())); | |
| 1142 | |
| 1143 scoped_ptr<ClientSocketHandle> socket_handle(new ClientSocketHandle); | |
| 1144 socket_handle->SetSocket(transport.Pass()); | |
| 1145 | 1031 |
| 1146 scoped_ptr<HttpRequestInfo> request_info(new HttpRequestInfo()); | 1032 scoped_ptr<HttpRequestInfo> request_info(new HttpRequestInfo()); |
| 1147 request_info->method = "GET"; | 1033 request_info->method = "GET"; |
| 1148 request_info->url = GURL("http://somewhere/foo.html"); | 1034 request_info->url = GURL("http://somewhere/foo.html"); |
| 1149 | 1035 |
| 1150 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); | 1036 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); |
| 1151 HttpStreamParser parser(socket_handle.get(), request_info.get(), | 1037 HttpStreamParser parser(socket_handle.get(), request_info.get(), |
| 1152 read_buffer.get(), BoundNetLog()); | 1038 read_buffer.get(), BoundNetLog()); |
| 1153 | 1039 |
| 1154 scoped_ptr<HttpRequestHeaders> request_headers(new HttpRequestHeaders()); | 1040 scoped_ptr<HttpRequestHeaders> request_headers(new HttpRequestHeaders()); |
| 1155 scoped_ptr<HttpResponseInfo> response_info(new HttpResponseInfo()); | 1041 scoped_ptr<HttpResponseInfo> response_info(new HttpResponseInfo()); |
| 1042 TestCompletionCallback callback; |
| 1156 ASSERT_EQ(OK, parser.SendRequest("GET /foo.html HTTP/1.1\r\n", | 1043 ASSERT_EQ(OK, parser.SendRequest("GET /foo.html HTTP/1.1\r\n", |
| 1157 *request_headers, response_info.get(), callback.callback())); | 1044 *request_headers, response_info.get(), callback.callback())); |
| 1158 ASSERT_EQ(OK, parser.ReadResponseHeaders(callback.callback())); | 1045 ASSERT_EQ(OK, parser.ReadResponseHeaders(callback.callback())); |
| 1159 | 1046 |
| 1160 // If the object that owns the HttpStreamParser is deleted, it takes the | 1047 // If the object that owns the HttpStreamParser is deleted, it takes the |
| 1161 // objects passed to the HttpStreamParser with it. | 1048 // objects passed to the HttpStreamParser with it. |
| 1162 request_info.reset(); | 1049 request_info.reset(); |
| 1163 request_headers.reset(); | 1050 request_headers.reset(); |
| 1164 response_info.reset(); | 1051 response_info.reset(); |
| 1165 | 1052 |
| 1166 scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize)); | 1053 scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize)); |
| 1167 ASSERT_EQ(kBodySize, parser.ReadResponseBody( | 1054 ASSERT_EQ(kBodySize, parser.ReadResponseBody( |
| 1168 body_buffer.get(), kBodySize, callback.callback())); | 1055 body_buffer.get(), kBodySize, callback.callback())); |
| 1169 } | 1056 } |
| 1170 | 1057 |
| 1171 } // namespace | 1058 } // namespace |
| 1172 | 1059 |
| 1173 } // namespace net | 1060 } // namespace net |
| OLD | NEW |