1 // Copyright 2012 The Chromium Authors
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/http/http_stream_parser.h"
6
7 #include <stdint.h>
8
9 #include <algorithm>
10 #include <memory>
11 #include <string>
12 #include <utility>
13 #include <vector>
14
15 #include "base/files/file_path.h"
16 #include "base/files/file_util.h"
17 #include "base/files/scoped_temp_dir.h"
18 #include "base/functional/bind.h"
19 #include "base/memory/ref_counted.h"
20 #include "base/run_loop.h"
21 #include "base/strings/string_piece.h"
22 #include "base/task/single_thread_task_runner.h"
23 #include "base/test/task_environment.h"
24 #include "net/base/chunked_upload_data_stream.h"
25 #include "net/base/elements_upload_data_stream.h"
26 #include "net/base/io_buffer.h"
27 #include "net/base/load_flags.h"
28 #include "net/base/net_errors.h"
29 #include "net/base/test_completion_callback.h"
30 #include "net/base/upload_bytes_element_reader.h"
31 #include "net/base/upload_file_element_reader.h"
32 #include "net/http/http_connection_info.h"
33 #include "net/http/http_request_headers.h"
34 #include "net/http/http_request_info.h"
35 #include "net/http/http_response_headers.h"
36 #include "net/http/http_response_info.h"
37 #include "net/socket/socket_test_util.h"
38 #include "net/socket/stream_socket.h"
39 #include "net/test/gtest_util.h"
40 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
41 #include "testing/gmock/include/gmock/gmock.h"
42 #include "testing/gtest/include/gtest/gtest.h"
43 #include "url/gurl.h"
44
45 using net::test::IsError;
46 using net::test::IsOk;
47
48 namespace net {
49
50 namespace {
51
52 const size_t kOutputSize = 1024; // Just large enough for this test.
53 // The number of bytes that can fit in a buffer of kOutputSize.
54 const size_t kMaxPayloadSize =
55 kOutputSize - HttpStreamParser::kChunkHeaderFooterSize;
56
57 // Helper method to create a connected ClientSocketHandle using |data|.
58 // Modifies |data|.
CreateConnectedSocket(SequencedSocketData * data)59 std::unique_ptr<StreamSocket> CreateConnectedSocket(SequencedSocketData* data) {
60 data->set_connect_data(MockConnect(SYNCHRONOUS, OK));
61
62 auto socket =
63 std::make_unique<MockTCPClientSocket>(net::AddressList(), nullptr, data);
64
65 TestCompletionCallback callback;
66 EXPECT_THAT(socket->Connect(callback.callback()), IsOk());
67
68 return socket;
69 }
70
71 class ReadErrorUploadDataStream : public UploadDataStream {
72 public:
73 enum class FailureMode { SYNC, ASYNC };
74
ReadErrorUploadDataStream(FailureMode mode)75 explicit ReadErrorUploadDataStream(FailureMode mode)
76 : UploadDataStream(true, 0), async_(mode) {}
77
78 ReadErrorUploadDataStream(const ReadErrorUploadDataStream&) = delete;
79 ReadErrorUploadDataStream& operator=(const ReadErrorUploadDataStream&) =
80 delete;
81
82 private:
CompleteRead()83 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
84
85 // UploadDataStream implementation:
InitInternal(const NetLogWithSource & net_log)86 int InitInternal(const NetLogWithSource& net_log) override { return OK; }
87
ReadInternal(IOBuffer * buf,int buf_len)88 int ReadInternal(IOBuffer* buf, int buf_len) override {
89 if (async_ == FailureMode::ASYNC) {
90 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
91 FROM_HERE, base::BindOnce(&ReadErrorUploadDataStream::CompleteRead,
92 weak_factory_.GetWeakPtr()));
93 return ERR_IO_PENDING;
94 }
95 return ERR_FAILED;
96 }
97
ResetInternal()98 void ResetInternal() override {}
99
100 const FailureMode async_;
101
102 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_{this};
103 };
104
TEST(HttpStreamParser,DataReadErrorSynchronous)105 TEST(HttpStreamParser, DataReadErrorSynchronous) {
106 MockWrite writes[] = {
107 MockWrite(SYNCHRONOUS, 0, "POST / HTTP/1.1\r\n"),
108 MockWrite(SYNCHRONOUS, 1, "Content-Length: 12\r\n\r\n"),
109 };
110
111 SequencedSocketData data(base::span<MockRead>(), writes);
112 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
113
114 ReadErrorUploadDataStream upload_data_stream(
115 ReadErrorUploadDataStream::FailureMode::SYNC);
116
117 // Test upload progress before init.
118 UploadProgress progress = upload_data_stream.GetUploadProgress();
119 EXPECT_EQ(0u, progress.size());
120 EXPECT_EQ(0u, progress.position());
121
122 ASSERT_THAT(upload_data_stream.Init(TestCompletionCallback().callback(),
123 NetLogWithSource()),
124 IsOk());
125
126 // Test upload progress after init.
127 progress = upload_data_stream.GetUploadProgress();
128 EXPECT_EQ(0u, progress.size());
129 EXPECT_EQ(0u, progress.position());
130
131 HttpRequestInfo request;
132 request.method = "POST";
133 request.url = GURL("http://localhost");
134 request.upload_data_stream = &upload_data_stream;
135
136 scoped_refptr<GrowableIOBuffer> read_buffer =
137 base::MakeRefCounted<GrowableIOBuffer>();
138 HttpStreamParser parser(stream_socket.get(), false /* is_reused */, &request,
139 read_buffer.get(), NetLogWithSource());
140
141 HttpRequestHeaders headers;
142 headers.SetHeader("Content-Length", "12");
143
144 HttpResponseInfo response;
145 TestCompletionCallback callback;
146 int result = parser.SendRequest("POST / HTTP/1.1\r\n", headers,
147 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
148 callback.callback());
149 EXPECT_THAT(callback.GetResult(result), IsError(ERR_FAILED));
150
151 progress = upload_data_stream.GetUploadProgress();
152 EXPECT_EQ(0u, progress.size());
153 EXPECT_EQ(0u, progress.position());
154
155 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
156 }
157
TEST(HttpStreamParser,DataReadErrorAsynchronous)158 TEST(HttpStreamParser, DataReadErrorAsynchronous) {
159 base::test::TaskEnvironment task_environment;
160
161 MockWrite writes[] = {
162 MockWrite(ASYNC, 0, "POST / HTTP/1.1\r\n"),
163 MockWrite(ASYNC, 1, "Content-Length: 12\r\n\r\n"),
164 };
165
166 SequencedSocketData data(base::span<MockRead>(), writes);
167 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
168
169 ReadErrorUploadDataStream upload_data_stream(
170 ReadErrorUploadDataStream::FailureMode::ASYNC);
171 ASSERT_THAT(upload_data_stream.Init(TestCompletionCallback().callback(),
172 NetLogWithSource()),
173 IsOk());
174
175 HttpRequestInfo request;
176 request.method = "POST";
177 request.url = GURL("http://localhost");
178 request.upload_data_stream = &upload_data_stream;
179
180 scoped_refptr<GrowableIOBuffer> read_buffer =
181 base::MakeRefCounted<GrowableIOBuffer>();
182 HttpStreamParser parser(stream_socket.get(), false /* is_reused */, &request,
183 read_buffer.get(), NetLogWithSource());
184
185 HttpRequestHeaders headers;
186 headers.SetHeader("Content-Length", "12");
187
188 HttpResponseInfo response;
189 TestCompletionCallback callback;
190 int result = parser.SendRequest("POST / HTTP/1.1\r\n", headers,
191 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
192 callback.callback());
193 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
194
195 UploadProgress progress = upload_data_stream.GetUploadProgress();
196 EXPECT_EQ(0u, progress.size());
197 EXPECT_EQ(0u, progress.position());
198
199 EXPECT_THAT(callback.GetResult(result), IsError(ERR_FAILED));
200
201 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
202 }
203
204 class InitAsyncUploadDataStream : public ChunkedUploadDataStream {
205 public:
InitAsyncUploadDataStream(int64_t identifier)206 explicit InitAsyncUploadDataStream(int64_t identifier)
207 : ChunkedUploadDataStream(identifier) {}
208
209 InitAsyncUploadDataStream(const InitAsyncUploadDataStream&) = delete;
210 InitAsyncUploadDataStream& operator=(const InitAsyncUploadDataStream&) =
211 delete;
212
213 private:
CompleteInit()214 void CompleteInit() { UploadDataStream::OnInitCompleted(OK); }
215
InitInternal(const NetLogWithSource & net_log)216 int InitInternal(const NetLogWithSource& net_log) override {
217 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
218 FROM_HERE, base::BindOnce(&InitAsyncUploadDataStream::CompleteInit,
219 weak_factory_.GetWeakPtr()));
220 return ERR_IO_PENDING;
221 }
222
223 base::WeakPtrFactory<InitAsyncUploadDataStream> weak_factory_{this};
224 };
225
TEST(HttpStreamParser,InitAsynchronousUploadDataStream)226 TEST(HttpStreamParser, InitAsynchronousUploadDataStream) {
227 base::test::TaskEnvironment task_environment;
228
229 InitAsyncUploadDataStream upload_data_stream(0);
230
231 TestCompletionCallback callback;
232 int result = upload_data_stream.Init(callback.callback(), NetLogWithSource());
233 ASSERT_THAT(result, IsError(ERR_IO_PENDING));
234
235 // Should be empty progress while initialization is in progress.
236 UploadProgress progress = upload_data_stream.GetUploadProgress();
237 EXPECT_EQ(0u, progress.size());
238 EXPECT_EQ(0u, progress.position());
239 EXPECT_THAT(callback.GetResult(result), IsOk());
240
241 // Initialization complete.
242 progress = upload_data_stream.GetUploadProgress();
243 EXPECT_EQ(0u, progress.size());
244 EXPECT_EQ(0u, progress.position());
245
246 HttpRequestInfo request;
247 request.method = "POST";
248 request.url = GURL("http://localhost");
249 request.upload_data_stream = &upload_data_stream;
250
251 static const char kChunk[] = "Chunk 1";
252 MockWrite writes[] = {
253 MockWrite(ASYNC, 0, "POST / HTTP/1.1\r\n"),
254 MockWrite(ASYNC, 1, "Transfer-Encoding: chunked\r\n\r\n"),
255 MockWrite(ASYNC, 2, "7\r\nChunk 1\r\n"),
256 };
257
258 SequencedSocketData data(base::span<MockRead>(), writes);
259 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
260
261 scoped_refptr<GrowableIOBuffer> read_buffer =
262 base::MakeRefCounted<GrowableIOBuffer>();
263 HttpStreamParser parser(stream_socket.get(), false /* is_reused */, &request,
264 read_buffer.get(), NetLogWithSource());
265
266 HttpRequestHeaders headers;
267 headers.SetHeader("Transfer-Encoding", "chunked");
268
269 HttpResponseInfo response;
270 TestCompletionCallback callback1;
271 int result1 = parser.SendRequest("POST / HTTP/1.1\r\n", headers,
272 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
273 callback1.callback());
274 EXPECT_EQ(ERR_IO_PENDING, result1);
275 base::RunLoop().RunUntilIdle();
276 upload_data_stream.AppendData(kChunk, std::size(kChunk) - 1, true);
277
278 // Check progress after read completes.
279 progress = upload_data_stream.GetUploadProgress();
280 EXPECT_EQ(0u, progress.size());
281 EXPECT_EQ(7u, progress.position());
282
283 // Check progress after reset.
284 upload_data_stream.Reset();
285 progress = upload_data_stream.GetUploadProgress();
286 EXPECT_EQ(0u, progress.size());
287 EXPECT_EQ(0u, progress.position());
288 }
289
290 // The empty payload is how the last chunk is encoded.
TEST(HttpStreamParser,EncodeChunk_EmptyPayload)291 TEST(HttpStreamParser, EncodeChunk_EmptyPayload) {
292 char output[kOutputSize];
293
294 const base::StringPiece kPayload = "";
295 const base::StringPiece kExpected = "0\r\n\r\n";
296 const int num_bytes_written =
297 HttpStreamParser::EncodeChunk(kPayload, output, sizeof(output));
298 ASSERT_EQ(kExpected.size(), static_cast<size_t>(num_bytes_written));
299 EXPECT_EQ(kExpected, base::StringPiece(output, num_bytes_written));
300 }
301
TEST(HttpStreamParser,EncodeChunk_ShortPayload)302 TEST(HttpStreamParser, EncodeChunk_ShortPayload) {
303 char output[kOutputSize];
304
305 const std::string kPayload("foo\x00\x11\x22", 6);
306 // 11 = payload size + sizeof("6") + CRLF x 2.
307 const std::string kExpected("6\r\nfoo\x00\x11\x22\r\n", 11);
308 const int num_bytes_written =
309 HttpStreamParser::EncodeChunk(kPayload, output, sizeof(output));
310 ASSERT_EQ(kExpected.size(), static_cast<size_t>(num_bytes_written));
311 EXPECT_EQ(kExpected, base::StringPiece(output, num_bytes_written));
312 }
313
TEST(HttpStreamParser,EncodeChunk_LargePayload)314 TEST(HttpStreamParser, EncodeChunk_LargePayload) {
315 char output[kOutputSize];
316
317 const std::string kPayload(1000, '\xff'); // '\xff' x 1000.
318 // 3E8 = 1000 in hex.
319 const std::string kExpected = "3E8\r\n" + kPayload + "\r\n";
320 const int num_bytes_written =
321 HttpStreamParser::EncodeChunk(kPayload, output, sizeof(output));
322 ASSERT_EQ(kExpected.size(), static_cast<size_t>(num_bytes_written));
323 EXPECT_EQ(kExpected, base::StringPiece(output, num_bytes_written));
324 }
325
TEST(HttpStreamParser,EncodeChunk_FullPayload)326 TEST(HttpStreamParser, EncodeChunk_FullPayload) {
327 char output[kOutputSize];
328
329 const std::string kPayload(kMaxPayloadSize, '\xff');
330 // 3F4 = 1012 in hex.
331 const std::string kExpected = "3F4\r\n" + kPayload + "\r\n";
332 const int num_bytes_written =
333 HttpStreamParser::EncodeChunk(kPayload, output, sizeof(output));
334 ASSERT_EQ(kExpected.size(), static_cast<size_t>(num_bytes_written));
335 EXPECT_EQ(kExpected, base::StringPiece(output, num_bytes_written));
336 }
337
TEST(HttpStreamParser,EncodeChunk_TooLargePayload)338 TEST(HttpStreamParser, EncodeChunk_TooLargePayload) {
339 char output[kOutputSize];
340
341 // The payload is one byte larger the output buffer size.
342 const std::string kPayload(kMaxPayloadSize + 1, '\xff');
343 const int num_bytes_written =
344 HttpStreamParser::EncodeChunk(kPayload, output, sizeof(output));
345 ASSERT_THAT(num_bytes_written, IsError(ERR_INVALID_ARGUMENT));
346 }
347
TEST(HttpStreamParser,ShouldMergeRequestHeadersAndBody_NoBody)348 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_NoBody) {
349 // Shouldn't be merged if upload data is non-existent.
350 ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody("some header",
351 nullptr));
352 }
353
TEST(HttpStreamParser,ShouldMergeRequestHeadersAndBody_EmptyBody)354 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_EmptyBody) {
355 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
356 std::unique_ptr<UploadDataStream> body(
357 std::make_unique<ElementsUploadDataStream>(std::move(element_readers),
358 0));
359 ASSERT_THAT(body->Init(CompletionOnceCallback(), NetLogWithSource()), IsOk());
360 // Shouldn't be merged if upload data is empty.
361 ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody(
362 "some header", body.get()));
363 }
364
TEST(HttpStreamParser,ShouldMergeRequestHeadersAndBody_ChunkedBody)365 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_ChunkedBody) {
366 const std::string payload = "123";
367 auto body = std::make_unique<ChunkedUploadDataStream>(0);
368 body->AppendData(payload.data(), payload.size(), true);
369 ASSERT_THAT(
370 body->Init(TestCompletionCallback().callback(), NetLogWithSource()),
371 IsOk());
372 // Shouldn't be merged if upload data carries chunked data.
373 ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody(
374 "some header", body.get()));
375 }
376
TEST(HttpStreamParser,ShouldMergeRequestHeadersAndBody_FileBody)377 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_FileBody) {
378 base::test::TaskEnvironment task_environment(
379 base::test::TaskEnvironment::MainThreadType::IO);
380
381 // Create an empty temporary file.
382 base::ScopedTempDir temp_dir;
383 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
384 base::FilePath temp_file_path;
385 ASSERT_TRUE(
386 base::CreateTemporaryFileInDir(temp_dir.GetPath(), &temp_file_path));
387
388 {
389 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
390
391 element_readers.push_back(std::make_unique<UploadFileElementReader>(
392 base::SingleThreadTaskRunner::GetCurrentDefault().get(), temp_file_path,
393 0, 0, base::Time()));
394
395 std::unique_ptr<UploadDataStream> body(
396 std::make_unique<ElementsUploadDataStream>(std::move(element_readers),
397 0));
398 TestCompletionCallback callback;
399 ASSERT_THAT(body->Init(callback.callback(), NetLogWithSource()),
400 IsError(ERR_IO_PENDING));
401 ASSERT_THAT(callback.WaitForResult(), IsOk());
402 // Shouldn't be merged if upload data carries a file, as it's not in-memory.
403 ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody(
404 "some header", body.get()));
405 }
406
407 // UploadFileElementReaders may post clean-up tasks on destruction.
408 base::RunLoop().RunUntilIdle();
409 }
410
TEST(HttpStreamParser,ShouldMergeRequestHeadersAndBody_SmallBodyInMemory)411 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_SmallBodyInMemory) {
412 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
413 const std::string payload = "123";
414 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
415 payload.data(), payload.size()));
416
417 std::unique_ptr<UploadDataStream> body(
418 std::make_unique<ElementsUploadDataStream>(std::move(element_readers),
419 0));
420 ASSERT_THAT(body->Init(CompletionOnceCallback(), NetLogWithSource()), IsOk());
421 // Yes, should be merged if the in-memory body is small here.
422 ASSERT_TRUE(HttpStreamParser::ShouldMergeRequestHeadersAndBody(
423 "some header", body.get()));
424 }
425
TEST(HttpStreamParser,ShouldMergeRequestHeadersAndBody_LargeBodyInMemory)426 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_LargeBodyInMemory) {
427 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
428 const std::string payload(10000, 'a'); // 'a' x 10000.
429 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
430 payload.data(), payload.size()));
431
432 std::unique_ptr<UploadDataStream> body(
433 std::make_unique<ElementsUploadDataStream>(std::move(element_readers),
434 0));
435 ASSERT_THAT(body->Init(CompletionOnceCallback(), NetLogWithSource()), IsOk());
436 // Shouldn't be merged if the in-memory body is large here.
437 ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody(
438 "some header", body.get()));
439 }
440
TEST(HttpStreamParser,SentBytesNoHeaders)441 TEST(HttpStreamParser, SentBytesNoHeaders) {
442 MockWrite writes[] = {
443 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n"),
444 };
445
446 SequencedSocketData data(base::span<MockRead>(), writes);
447 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
448
449 HttpRequestInfo request;
450 request.method = "GET";
451 request.url = GURL("http://localhost");
452
453 scoped_refptr<GrowableIOBuffer> read_buffer =
454 base::MakeRefCounted<GrowableIOBuffer>();
455 HttpStreamParser parser(stream_socket.get(), false /* is_reused */, &request,
456 read_buffer.get(), NetLogWithSource());
457
458 HttpResponseInfo response;
459 TestCompletionCallback callback;
460 EXPECT_EQ(OK, parser.SendRequest("GET / HTTP/1.1\r\n", HttpRequestHeaders(),
461 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
462 callback.callback()));
463
464 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
465 }
466
TEST(HttpStreamParser,SentBytesWithHeaders)467 TEST(HttpStreamParser, SentBytesWithHeaders) {
468 MockWrite writes[] = {
469 MockWrite(SYNCHRONOUS, 0,
470 "GET / HTTP/1.1\r\n"
471 "Host: localhost\r\n"
472 "Connection: Keep-Alive\r\n\r\n"),
473 };
474
475 SequencedSocketData data(base::span<MockRead>(), writes);
476 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
477
478 HttpRequestInfo request;
479 request.method = "GET";
480 request.url = GURL("http://localhost");
481
482 scoped_refptr<GrowableIOBuffer> read_buffer =
483 base::MakeRefCounted<GrowableIOBuffer>();
484 HttpStreamParser parser(stream_socket.get(), false /* is_reused */, &request,
485 read_buffer.get(), NetLogWithSource());
486
487 HttpRequestHeaders headers;
488 headers.SetHeader("Host", "localhost");
489 headers.SetHeader("Connection", "Keep-Alive");
490
491 HttpResponseInfo response;
492 TestCompletionCallback callback;
493 EXPECT_EQ(OK, parser.SendRequest("GET / HTTP/1.1\r\n", headers,
494 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
495 callback.callback()));
496
497 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
498 }
499
TEST(HttpStreamParser,SentBytesWithHeadersMultiWrite)500 TEST(HttpStreamParser, SentBytesWithHeadersMultiWrite) {
501 MockWrite writes[] = {
502 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n"),
503 MockWrite(SYNCHRONOUS, 1, "Host: localhost\r\n"),
504 MockWrite(SYNCHRONOUS, 2, "Connection: Keep-Alive\r\n\r\n"),
505 };
506
507 SequencedSocketData data(base::span<MockRead>(), writes);
508 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
509
510 HttpRequestInfo request;
511 request.method = "GET";
512 request.url = GURL("http://localhost");
513
514 scoped_refptr<GrowableIOBuffer> read_buffer =
515 base::MakeRefCounted<GrowableIOBuffer>();
516 HttpStreamParser parser(stream_socket.get(), false /* is_reused */, &request,
517 read_buffer.get(), NetLogWithSource());
518
519 HttpRequestHeaders headers;
520 headers.SetHeader("Host", "localhost");
521 headers.SetHeader("Connection", "Keep-Alive");
522
523 HttpResponseInfo response;
524 TestCompletionCallback callback;
525
526 EXPECT_EQ(OK, parser.SendRequest("GET / HTTP/1.1\r\n", headers,
527 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
528 callback.callback()));
529
530 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
531 }
532
TEST(HttpStreamParser,SentBytesWithErrorWritingHeaders)533 TEST(HttpStreamParser, SentBytesWithErrorWritingHeaders) {
534 MockWrite writes[] = {
535 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n"),
536 MockWrite(SYNCHRONOUS, 1, "Host: localhost\r\n"),
537 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET, 2),
538 };
539
540 SequencedSocketData data(base::span<MockRead>(), writes);
541 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
542
543 HttpRequestInfo request;
544 request.method = "GET";
545 request.url = GURL("http://localhost");
546
547 scoped_refptr<GrowableIOBuffer> read_buffer =
548 base::MakeRefCounted<GrowableIOBuffer>();
549 HttpStreamParser parser(stream_socket.get(), false /* is_reused */, &request,
550 read_buffer.get(), NetLogWithSource());
551
552 HttpRequestHeaders headers;
553 headers.SetHeader("Host", "localhost");
554 headers.SetHeader("Connection", "Keep-Alive");
555
556 HttpResponseInfo response;
557 TestCompletionCallback callback;
558 EXPECT_EQ(ERR_CONNECTION_RESET,
559 parser.SendRequest("GET / HTTP/1.1\r\n", headers,
560 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
561 callback.callback()));
562
563 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
564 }
565
TEST(HttpStreamParser,SentBytesPost)566 TEST(HttpStreamParser, SentBytesPost) {
567 MockWrite writes[] = {
568 MockWrite(SYNCHRONOUS, 0, "POST / HTTP/1.1\r\n"),
569 MockWrite(SYNCHRONOUS, 1, "Content-Length: 12\r\n\r\n"),
570 MockWrite(SYNCHRONOUS, 2, "hello world!"),
571 };
572
573 SequencedSocketData data(base::span<MockRead>(), writes);
574 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
575
576 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
577 element_readers.push_back(
578 std::make_unique<UploadBytesElementReader>("hello world!", 12));
579 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
580 ASSERT_THAT(upload_data_stream.Init(TestCompletionCallback().callback(),
581 NetLogWithSource()),
582 IsOk());
583
584 HttpRequestInfo request;
585 request.method = "POST";
586 request.url = GURL("http://localhost");
587 request.upload_data_stream = &upload_data_stream;
588
589 scoped_refptr<GrowableIOBuffer> read_buffer =
590 base::MakeRefCounted<GrowableIOBuffer>();
591 HttpStreamParser parser(stream_socket.get(), false /* is_reused */, &request,
592 read_buffer.get(), NetLogWithSource());
593
594 HttpRequestHeaders headers;
595 headers.SetHeader("Content-Length", "12");
596
597 HttpResponseInfo response;
598 TestCompletionCallback callback;
599 EXPECT_EQ(OK, parser.SendRequest("POST / HTTP/1.1\r\n", headers,
600 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
601 callback.callback()));
602
603 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
604
605 UploadProgress progress = upload_data_stream.GetUploadProgress();
606 EXPECT_EQ(12u, progress.size());
607 EXPECT_EQ(12u, progress.position());
608 }
609
TEST(HttpStreamParser,SentBytesChunkedPostError)610 TEST(HttpStreamParser, SentBytesChunkedPostError) {
611 base::test::TaskEnvironment task_environment;
612
613 static const char kChunk[] = "Chunk 1";
614
615 MockWrite writes[] = {
616 MockWrite(ASYNC, 0, "POST / HTTP/1.1\r\n"),
617 MockWrite(ASYNC, 1, "Transfer-Encoding: chunked\r\n\r\n"),
618 MockWrite(ASYNC, 2, "7\r\nChunk 1\r\n"),
619 MockWrite(SYNCHRONOUS, ERR_FAILED, 3),
620 };
621
622 SequencedSocketData data(base::span<MockRead>(), writes);
623 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
624
625 ChunkedUploadDataStream upload_data_stream(0);
626 ASSERT_THAT(upload_data_stream.Init(TestCompletionCallback().callback(),
627 NetLogWithSource()),
628 IsOk());
629
630 HttpRequestInfo request;
631 request.method = "POST";
632 request.url = GURL("http://localhost");
633 request.upload_data_stream = &upload_data_stream;
634
635 scoped_refptr<GrowableIOBuffer> read_buffer =
636 base::MakeRefCounted<GrowableIOBuffer>();
637 HttpStreamParser parser(stream_socket.get(), false /* is_reused */, &request,
638 read_buffer.get(), NetLogWithSource());
639
640 HttpRequestHeaders headers;
641 headers.SetHeader("Transfer-Encoding", "chunked");
642
643 HttpResponseInfo response;
644 TestCompletionCallback callback;
645 EXPECT_EQ(ERR_IO_PENDING, parser.SendRequest("POST / HTTP/1.1\r\n", headers,
646 TRAFFIC_ANNOTATION_FOR_TESTS,
647 &response, callback.callback()));
648
649 base::RunLoop().RunUntilIdle();
650 upload_data_stream.AppendData(kChunk, std::size(kChunk) - 1, false);
651
652 base::RunLoop().RunUntilIdle();
653 // This write should fail.
654 upload_data_stream.AppendData(kChunk, std::size(kChunk) - 1, false);
655 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_FAILED));
656
657 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
658
659 UploadProgress progress = upload_data_stream.GetUploadProgress();
660 EXPECT_EQ(0u, progress.size());
661 EXPECT_EQ(14u, progress.position());
662 }
663
664 // Test to ensure the HttpStreamParser state machine does not get confused
665 // when sending a request with a chunked body with only one chunk that becomes
666 // available asynchronously.
TEST(HttpStreamParser,AsyncSingleChunkAndAsyncSocket)667 TEST(HttpStreamParser, AsyncSingleChunkAndAsyncSocket) {
668 base::test::TaskEnvironment task_environment;
669
670 static const char kChunk[] = "Chunk";
671
672 MockWrite writes[] = {
673 MockWrite(ASYNC, 0,
674 "GET /one.html HTTP/1.1\r\n"
675 "Transfer-Encoding: chunked\r\n\r\n"),
676 MockWrite(ASYNC, 1, "5\r\nChunk\r\n"),
677 MockWrite(ASYNC, 2, "0\r\n\r\n"),
678 };
679
680 // The size of the response body, as reflected in the Content-Length of the
681 // MockRead below.
682 static const int kBodySize = 8;
683
684 MockRead reads[] = {
685 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n"),
686 MockRead(ASYNC, 4, "Content-Length: 8\r\n\r\n"),
687 MockRead(ASYNC, 5, "one.html"),
688 MockRead(SYNCHRONOUS, 0, 6), // EOF
689 };
690
691 ChunkedUploadDataStream upload_stream(0);
692 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
693 NetLogWithSource()),
694 IsOk());
695
696 SequencedSocketData data(reads, writes);
697 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
698
699 HttpRequestInfo request_info;
700 request_info.method = "GET";
701 request_info.url = GURL("http://localhost");
702 request_info.upload_data_stream = &upload_stream;
703
704 scoped_refptr<GrowableIOBuffer> read_buffer =
705 base::MakeRefCounted<GrowableIOBuffer>();
706 HttpStreamParser parser(stream_socket.get(), false /* is_reused */,
707 &request_info, read_buffer.get(), NetLogWithSource());
708
709 HttpRequestHeaders request_headers;
710 request_headers.SetHeader("Transfer-Encoding", "chunked");
711
712 HttpResponseInfo response_info;
713 TestCompletionCallback callback;
714 // This will attempt to Write() the initial request and headers, which will
715 // complete asynchronously.
716 ASSERT_EQ(ERR_IO_PENDING,
717 parser.SendRequest("GET /one.html HTTP/1.1\r\n", request_headers,
718 TRAFFIC_ANNOTATION_FOR_TESTS, &response_info,
719 callback.callback()));
720
721 // Complete the initial request write. Callback should not have been invoked.
722 base::RunLoop().RunUntilIdle();
723 ASSERT_FALSE(callback.have_result());
724
725 // Now append the only chunk and wait for the callback.
726 upload_stream.AppendData(kChunk, std::size(kChunk) - 1, true);
727 ASSERT_THAT(callback.WaitForResult(), IsOk());
728
729 // Attempt to read the response status and the response headers.
730 ASSERT_THAT(parser.ReadResponseHeaders(callback.callback()),
731 IsError(ERR_IO_PENDING));
732 ASSERT_THAT(callback.WaitForResult(), IsOk());
733
734 // Finally, attempt to read the response body.
735 auto body_buffer = base::MakeRefCounted<IOBufferWithSize>(kBodySize);
736 ASSERT_EQ(ERR_IO_PENDING,
737 parser.ReadResponseBody(body_buffer.get(), kBodySize,
738 callback.callback()));
739 ASSERT_EQ(kBodySize, callback.WaitForResult());
740
741 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
742 EXPECT_EQ(CountReadBytes(reads), parser.received_bytes());
743 }
744
745 // Test to ensure the HttpStreamParser state machine does not get confused
746 // when sending a request with a chunked body with only one chunk that is
747 // available synchronously.
TEST(HttpStreamParser,SyncSingleChunkAndAsyncSocket)748 TEST(HttpStreamParser, SyncSingleChunkAndAsyncSocket) {
749 base::test::TaskEnvironment task_environment;
750
751 static const char kChunk[] = "Chunk";
752
753 MockWrite writes[] = {
754 MockWrite(ASYNC, 0,
755 "GET /one.html HTTP/1.1\r\n"
756 "Transfer-Encoding: chunked\r\n\r\n"),
757 MockWrite(ASYNC, 1, "5\r\nChunk\r\n"),
758 MockWrite(ASYNC, 2, "0\r\n\r\n"),
759 };
760
761 // The size of the response body, as reflected in the Content-Length of the
762 // MockRead below.
763 static const int kBodySize = 8;
764
765 MockRead reads[] = {
766 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n"),
767 MockRead(ASYNC, 4, "Content-Length: 8\r\n\r\n"),
768 MockRead(ASYNC, 5, "one.html"),
769 MockRead(SYNCHRONOUS, 0, 6), // EOF
770 };
771
772 ChunkedUploadDataStream upload_stream(0);
773 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
774 NetLogWithSource()),
775 IsOk());
776 // Append the only chunk.
777 upload_stream.AppendData(kChunk, std::size(kChunk) - 1, true);
778
779 SequencedSocketData data(reads, writes);
780 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
781
782 HttpRequestInfo request_info;
783 request_info.method = "GET";
784 request_info.url = GURL("http://localhost");
785 request_info.upload_data_stream = &upload_stream;
786
787 scoped_refptr<GrowableIOBuffer> read_buffer =
788 base::MakeRefCounted<GrowableIOBuffer>();
789 HttpStreamParser parser(stream_socket.get(), false /* is_reused */,
790 &request_info, read_buffer.get(), NetLogWithSource());
791
792 HttpRequestHeaders request_headers;
793 request_headers.SetHeader("Transfer-Encoding", "chunked");
794
795 HttpResponseInfo response_info;
796 TestCompletionCallback callback;
797 // This will attempt to Write() the initial request and headers, which will
798 // complete asynchronously.
799 ASSERT_EQ(ERR_IO_PENDING,
800 parser.SendRequest("GET /one.html HTTP/1.1\r\n", request_headers,
801 TRAFFIC_ANNOTATION_FOR_TESTS, &response_info,
802 callback.callback()));
803 ASSERT_THAT(callback.WaitForResult(), IsOk());
804
805 // Attempt to read the response status and the response headers.
806 ASSERT_THAT(parser.ReadResponseHeaders(callback.callback()),
807 IsError(ERR_IO_PENDING));
808 ASSERT_THAT(callback.WaitForResult(), IsOk());
809
810 // Finally, attempt to read the response body.
811 auto body_buffer = base::MakeRefCounted<IOBufferWithSize>(kBodySize);
812 ASSERT_EQ(ERR_IO_PENDING,
813 parser.ReadResponseBody(body_buffer.get(), kBodySize,
814 callback.callback()));
815 ASSERT_EQ(kBodySize, callback.WaitForResult());
816
817 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
818 EXPECT_EQ(CountReadBytes(reads), parser.received_bytes());
819 }
820
821 // Test to ensure the HttpStreamParser state machine does not get confused
822 // when sending a request with a chunked body, where chunks become available
823 // asynchronously, over a socket where writes may also complete
824 // asynchronously.
825 // This is a regression test for http://crbug.com/132243
TEST(HttpStreamParser,AsyncChunkAndAsyncSocketWithMultipleChunks)826 TEST(HttpStreamParser, AsyncChunkAndAsyncSocketWithMultipleChunks) {
827 base::test::TaskEnvironment task_environment;
828
829 // The chunks that will be written in the request, as reflected in the
830 // MockWrites below.
831 static const char kChunk1[] = "Chunk 1";
832 static const char kChunk2[] = "Chunky 2";
833 static const char kChunk3[] = "Test 3";
834
835 MockWrite writes[] = {
836 MockWrite(ASYNC, 0,
837 "GET /one.html HTTP/1.1\r\n"
838 "Transfer-Encoding: chunked\r\n\r\n"),
839 MockWrite(ASYNC, 1, "7\r\nChunk 1\r\n"),
840 MockWrite(ASYNC, 2, "8\r\nChunky 2\r\n"),
841 MockWrite(ASYNC, 3, "6\r\nTest 3\r\n"),
842 MockWrite(ASYNC, 4, "0\r\n\r\n"),
843 };
844
845 // The size of the response body, as reflected in the Content-Length of the
846 // MockRead below.
847 static const int kBodySize = 8;
848
849 MockRead reads[] = {
850 MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\n"),
851 MockRead(ASYNC, 6, "Content-Length: 8\r\n\r\n"),
852 MockRead(ASYNC, 7, "one.html"),
853 MockRead(SYNCHRONOUS, 0, 8), // EOF
854 };
855
856 ChunkedUploadDataStream upload_stream(0);
857 upload_stream.AppendData(kChunk1, std::size(kChunk1) - 1, false);
858 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
859 NetLogWithSource()),
860 IsOk());
861
862 SequencedSocketData data(reads, writes);
863 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
864
865 HttpRequestInfo request_info;
866 request_info.method = "GET";
867 request_info.url = GURL("http://localhost");
868 request_info.upload_data_stream = &upload_stream;
869
870 scoped_refptr<GrowableIOBuffer> read_buffer =
871 base::MakeRefCounted<GrowableIOBuffer>();
872 HttpStreamParser parser(stream_socket.get(), false /* is_reused */,
873 &request_info, read_buffer.get(), NetLogWithSource());
874
875 HttpRequestHeaders request_headers;
876 request_headers.SetHeader("Transfer-Encoding", "chunked");
877
878 HttpResponseInfo response_info;
879 TestCompletionCallback callback;
880 // This will attempt to Write() the initial request and headers, which will
881 // complete asynchronously.
882 ASSERT_EQ(ERR_IO_PENDING,
883 parser.SendRequest("GET /one.html HTTP/1.1\r\n", request_headers,
884 TRAFFIC_ANNOTATION_FOR_TESTS, &response_info,
885 callback.callback()));
886 ASSERT_FALSE(callback.have_result());
887
888 // Sending the request and the first chunk completes.
889 base::RunLoop().RunUntilIdle();
890 ASSERT_FALSE(callback.have_result());
891
892 // Now append another chunk.
893 upload_stream.AppendData(kChunk2, std::size(kChunk2) - 1, false);
894 ASSERT_FALSE(callback.have_result());
895
896 // Add the final chunk, while the write for the second is still pending,
897 // which should not confuse the state machine.
898 upload_stream.AppendData(kChunk3, std::size(kChunk3) - 1, true);
899 ASSERT_FALSE(callback.have_result());
900
901 // Wait for writes to complete.
902 ASSERT_THAT(callback.WaitForResult(), IsOk());
903
904 // Attempt to read the response status and the response headers.
905 ASSERT_THAT(parser.ReadResponseHeaders(callback.callback()),
906 IsError(ERR_IO_PENDING));
907 ASSERT_THAT(callback.WaitForResult(), IsOk());
908
909 // Finally, attempt to read the response body.
910 auto body_buffer = base::MakeRefCounted<IOBufferWithSize>(kBodySize);
911 ASSERT_EQ(ERR_IO_PENDING,
912 parser.ReadResponseBody(body_buffer.get(), kBodySize,
913 callback.callback()));
914 ASSERT_EQ(kBodySize, callback.WaitForResult());
915
916 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
917 EXPECT_EQ(CountReadBytes(reads), parser.received_bytes());
918 }
919
920 // Test to ensure the HttpStreamParser state machine does not get confused
921 // when there's only one "chunk" with 0 bytes, and is received from the
922 // UploadStream only after sending the request headers successfully.
TEST(HttpStreamParser,AsyncEmptyChunkedUpload)923 TEST(HttpStreamParser, AsyncEmptyChunkedUpload) {
924 base::test::TaskEnvironment task_environment;
925
926 MockWrite writes[] = {
927 MockWrite(ASYNC, 0,
928 "GET /one.html HTTP/1.1\r\n"
929 "Transfer-Encoding: chunked\r\n\r\n"),
930 MockWrite(ASYNC, 1, "0\r\n\r\n"),
931 };
932
933 // The size of the response body, as reflected in the Content-Length of the
934 // MockRead below.
935 const int kBodySize = 8;
936
937 MockRead reads[] = {
938 MockRead(ASYNC, 2, "HTTP/1.1 200 OK\r\n"),
939 MockRead(ASYNC, 3, "Content-Length: 8\r\n\r\n"),
940 MockRead(ASYNC, 4, "one.html"),
941 MockRead(SYNCHRONOUS, 0, 5), // EOF
942 };
943
944 ChunkedUploadDataStream upload_stream(0);
945 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
946 NetLogWithSource()),
947 IsOk());
948
949 SequencedSocketData data(reads, writes);
950 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
951
952 HttpRequestInfo request_info;
953 request_info.method = "GET";
954 request_info.url = GURL("http://localhost");
955 request_info.upload_data_stream = &upload_stream;
956
957 scoped_refptr<GrowableIOBuffer> read_buffer =
958 base::MakeRefCounted<GrowableIOBuffer>();
959 HttpStreamParser parser(stream_socket.get(), false /* is_reused */,
960 &request_info, read_buffer.get(), NetLogWithSource());
961
962 HttpRequestHeaders request_headers;
963 request_headers.SetHeader("Transfer-Encoding", "chunked");
964
965 HttpResponseInfo response_info;
966 TestCompletionCallback callback;
967 // This will attempt to Write() the initial request and headers, which will
968 // complete asynchronously.
969 ASSERT_EQ(ERR_IO_PENDING,
970 parser.SendRequest("GET /one.html HTTP/1.1\r\n", request_headers,
971 TRAFFIC_ANNOTATION_FOR_TESTS, &response_info,
972 callback.callback()));
973
974 // Now append the terminal 0-byte "chunk".
975 upload_stream.AppendData(nullptr, 0, true);
976 ASSERT_FALSE(callback.have_result());
977
978 ASSERT_THAT(callback.WaitForResult(), IsOk());
979
980 // Attempt to read the response status and the response headers.
981 ASSERT_THAT(parser.ReadResponseHeaders(callback.callback()),
982 IsError(ERR_IO_PENDING));
983 ASSERT_THAT(callback.WaitForResult(), IsOk());
984
985 // Finally, attempt to read the response body.
986 auto body_buffer = base::MakeRefCounted<IOBufferWithSize>(kBodySize);
987 ASSERT_EQ(ERR_IO_PENDING,
988 parser.ReadResponseBody(body_buffer.get(), kBodySize,
989 callback.callback()));
990 ASSERT_EQ(kBodySize, callback.WaitForResult());
991
992 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
993 EXPECT_EQ(CountReadBytes(reads), parser.received_bytes());
994 }
995
996 // Test to ensure the HttpStreamParser state machine does not get confused
997 // when there's only one "chunk" with 0 bytes, which was already appended before
998 // the request was started.
TEST(HttpStreamParser,SyncEmptyChunkedUpload)999 TEST(HttpStreamParser, SyncEmptyChunkedUpload) {
1000 base::test::TaskEnvironment task_environment;
1001
1002 MockWrite writes[] = {
1003 MockWrite(ASYNC, 0,
1004 "GET /one.html HTTP/1.1\r\n"
1005 "Transfer-Encoding: chunked\r\n\r\n"),
1006 MockWrite(ASYNC, 1, "0\r\n\r\n"),
1007 };
1008
1009 // The size of the response body, as reflected in the Content-Length of the
1010 // MockRead below.
1011 const int kBodySize = 8;
1012
1013 MockRead reads[] = {
1014 MockRead(ASYNC, 2, "HTTP/1.1 200 OK\r\n"),
1015 MockRead(ASYNC, 3, "Content-Length: 8\r\n\r\n"),
1016 MockRead(ASYNC, 4, "one.html"),
1017 MockRead(SYNCHRONOUS, 0, 5), // EOF
1018 };
1019
1020 ChunkedUploadDataStream upload_stream(0);
1021 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
1022 NetLogWithSource()),
1023 IsOk());
1024 // Append final empty chunk.
1025 upload_stream.AppendData(nullptr, 0, true);
1026
1027 SequencedSocketData data(reads, writes);
1028 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
1029
1030 HttpRequestInfo request_info;
1031 request_info.method = "GET";
1032 request_info.url = GURL("http://localhost");
1033 request_info.upload_data_stream = &upload_stream;
1034
1035 scoped_refptr<GrowableIOBuffer> read_buffer =
1036 base::MakeRefCounted<GrowableIOBuffer>();
1037 HttpStreamParser parser(stream_socket.get(), false /* is_reused */,
1038 &request_info, read_buffer.get(), NetLogWithSource());
1039
1040 HttpRequestHeaders request_headers;
1041 request_headers.SetHeader("Transfer-Encoding", "chunked");
1042
1043 HttpResponseInfo response_info;
1044 TestCompletionCallback callback;
1045 // This will attempt to Write() the initial request and headers, which will
1046 // complete asynchronously.
1047 ASSERT_EQ(ERR_IO_PENDING,
1048 parser.SendRequest("GET /one.html HTTP/1.1\r\n", request_headers,
1049 TRAFFIC_ANNOTATION_FOR_TESTS, &response_info,
1050 callback.callback()));
1051
1052 // Complete writing the request headers and body.
1053 ASSERT_THAT(callback.WaitForResult(), IsOk());
1054
1055 // Attempt to read the response status and the response headers.
1056 ASSERT_THAT(parser.ReadResponseHeaders(callback.callback()),
1057 IsError(ERR_IO_PENDING));
1058 ASSERT_THAT(callback.WaitForResult(), IsOk());
1059
1060 // Finally, attempt to read the response body.
1061 auto body_buffer = base::MakeRefCounted<IOBufferWithSize>(kBodySize);
1062 ASSERT_EQ(ERR_IO_PENDING,
1063 parser.ReadResponseBody(body_buffer.get(), kBodySize,
1064 callback.callback()));
1065 ASSERT_EQ(kBodySize, callback.WaitForResult());
1066
1067 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
1068 EXPECT_EQ(CountReadBytes(reads), parser.received_bytes());
1069 }
1070
TEST(HttpStreamParser,TruncatedHeaders)1071 TEST(HttpStreamParser, TruncatedHeaders) {
1072 MockRead truncated_status_reads[] = {
1073 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 20"),
1074 MockRead(SYNCHRONOUS, 0, 2), // EOF
1075 };
1076
1077 MockRead truncated_after_status_reads[] = {
1078 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Ok\r\n"),
1079 MockRead(SYNCHRONOUS, 0, 2), // EOF
1080 };
1081
1082 MockRead truncated_in_header_reads[] = {
1083 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Ok\r\nHead"),
1084 MockRead(SYNCHRONOUS, 0, 2), // EOF
1085 };
1086
1087 MockRead truncated_after_header_reads[] = {
1088 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Ok\r\nHeader: foo\r\n"),
1089 MockRead(SYNCHRONOUS, 0, 2), // EOF
1090 };
1091
1092 MockRead truncated_after_final_newline_reads[] = {
1093 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Ok\r\nHeader: foo\r\n\r"),
1094 MockRead(SYNCHRONOUS, 0, 2), // EOF
1095 };
1096
1097 MockRead not_truncated_reads[] = {
1098 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Ok\r\nHeader: foo\r\n\r\n"),
1099 MockRead(SYNCHRONOUS, 0, 2), // EOF
1100 };
1101
1102 base::span<MockRead> reads[] = {
1103 truncated_status_reads,
1104 truncated_after_status_reads,
1105 truncated_in_header_reads,
1106 truncated_after_header_reads,
1107 truncated_after_final_newline_reads,
1108 not_truncated_reads,
1109 };
1110
1111 MockWrite writes[] = {
1112 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n"),
1113 };
1114
1115 enum {
1116 HTTP = 0,
1117 HTTPS,
1118 NUM_PROTOCOLS,
1119 };
1120
1121 for (size_t protocol = 0; protocol < NUM_PROTOCOLS; protocol++) {
1122 SCOPED_TRACE(protocol);
1123
1124 for (size_t i = 0; i < std::size(reads); i++) {
1125 SCOPED_TRACE(i);
1126 SequencedSocketData data(reads[i], writes);
1127 std::unique_ptr<StreamSocket> stream_socket(CreateConnectedSocket(&data));
1128
1129 HttpRequestInfo request_info;
1130 request_info.method = "GET";
1131 if (protocol == HTTP) {
1132 request_info.url = GURL("http://localhost");
1133 } else {
1134 request_info.url = GURL("https://localhost");
1135 }
1136 request_info.load_flags = LOAD_NORMAL;
1137
1138 scoped_refptr<GrowableIOBuffer> read_buffer =
1139 base::MakeRefCounted<GrowableIOBuffer>();
1140 HttpStreamParser parser(stream_socket.get(), false /* is_reused */,
1141 &request_info, read_buffer.get(),
1142 NetLogWithSource());
1143
1144 HttpRequestHeaders request_headers;
1145 HttpResponseInfo response_info;
1146 TestCompletionCallback callback;
1147 ASSERT_EQ(OK, parser.SendRequest("GET / HTTP/1.1\r\n", request_headers,
1148 TRAFFIC_ANNOTATION_FOR_TESTS,
1149 &response_info, callback.callback()));
1150
1151 int rv = parser.ReadResponseHeaders(callback.callback());
1152 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
1153 if (i == std::size(reads) - 1) {
1154 EXPECT_THAT(rv, IsOk());
1155 EXPECT_TRUE(response_info.headers.get());
1156 EXPECT_EQ(CountReadBytes(reads[i]), parser.received_bytes());
1157 } else {
1158 if (protocol == HTTP) {
1159 EXPECT_THAT(rv, IsError(ERR_CONNECTION_CLOSED));
1160 EXPECT_TRUE(response_info.headers.get());
1161 EXPECT_EQ(CountReadBytes(reads[i]), parser.received_bytes());
1162 } else {
1163 EXPECT_THAT(rv, IsError(ERR_RESPONSE_HEADERS_TRUNCATED));
1164 EXPECT_FALSE(response_info.headers.get());
1165 EXPECT_EQ(0, parser.received_bytes());
1166 }
1167 }
1168 }
1169 }
1170 }
1171
1172 // Confirm that on 101 response, the headers are parsed but the data that
1173 // follows remains in the buffer.
TEST(HttpStreamParser,WebSocket101Response)1174 TEST(HttpStreamParser, WebSocket101Response) {
1175 MockRead reads[] = {
1176 MockRead(SYNCHRONOUS, 1,
1177 "HTTP/1.1 101 Switching Protocols\r\n"
1178 "Upgrade: websocket\r\n"
1179 "Connection: Upgrade\r\n"
1180 "\r\n"
1181 "a fake websocket frame"),
1182 };
1183
1184 MockWrite writes[] = {
1185 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n"),
1186 };
1187
1188 SequencedSocketData data(reads, writes);
1189 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
1190
1191 HttpRequestInfo request_info;
1192 request_info.method = "GET";
1193 request_info.url = GURL("http://localhost");
1194 request_info.load_flags = LOAD_NORMAL;
1195
1196 scoped_refptr<GrowableIOBuffer> read_buffer =
1197 base::MakeRefCounted<GrowableIOBuffer>();
1198 HttpStreamParser parser(stream_socket.get(), false /* is_reused */,
1199 &request_info, read_buffer.get(), NetLogWithSource());
1200
1201 HttpRequestHeaders request_headers;
1202 HttpResponseInfo response_info;
1203 TestCompletionCallback callback;
1204 ASSERT_EQ(OK, parser.SendRequest("GET / HTTP/1.1\r\n", request_headers,
1205 TRAFFIC_ANNOTATION_FOR_TESTS, &response_info,
1206 callback.callback()));
1207
1208 EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()), IsOk());
1209 ASSERT_TRUE(response_info.headers.get());
1210 EXPECT_EQ(101, response_info.headers->response_code());
1211 EXPECT_TRUE(response_info.headers->HasHeaderValue("Connection", "Upgrade"));
1212 EXPECT_TRUE(response_info.headers->HasHeaderValue("Upgrade", "websocket"));
1213 EXPECT_EQ(read_buffer->capacity(), read_buffer->offset());
1214 EXPECT_EQ("a fake websocket frame",
1215 base::StringPiece(read_buffer->StartOfBuffer(),
1216 read_buffer->capacity()));
1217
1218 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
1219 EXPECT_EQ(CountReadBytes(reads) -
1220 static_cast<int64_t>(strlen("a fake websocket frame")),
1221 parser.received_bytes());
1222 }
1223
1224 // Helper class for constructing HttpStreamParser and running GET requests.
1225 class SimpleGetRunner {
1226 public:
SimpleGetRunner()1227 SimpleGetRunner()
1228 : url_("http://localhost"),
1229 read_buffer_(base::MakeRefCounted<GrowableIOBuffer>()) {
1230 writes_.emplace_back(
1231 MockWrite(SYNCHRONOUS, sequence_number_++, "GET / HTTP/1.1\r\n\r\n"));
1232 }
1233
set_url(const GURL & url)1234 void set_url(const GURL& url) { url_ = url; }
1235
parser()1236 HttpStreamParser* parser() { return parser_.get(); }
read_buffer()1237 GrowableIOBuffer* read_buffer() { return read_buffer_.get(); }
response_info()1238 HttpResponseInfo* response_info() { return &response_info_; }
1239
AddInitialData(const std::string & data)1240 void AddInitialData(const std::string& data) {
1241 int offset = read_buffer_->offset();
1242 int size = data.size();
1243 read_buffer_->SetCapacity(offset + size);
1244 memcpy(read_buffer_->StartOfBuffer() + offset, data.data(), size);
1245 read_buffer_->set_offset(offset + size);
1246 }
1247
1248 // The data used to back |string_piece| must stay alive until all mock data
1249 // has been read.
AddRead(base::StringPiece string_piece)1250 void AddRead(base::StringPiece string_piece) {
1251 reads_.emplace_back(SYNCHRONOUS, string_piece.data(), string_piece.length(),
1252 sequence_number_++);
1253 }
1254
SetupParserAndSendRequest()1255 void SetupParserAndSendRequest() {
1256 reads_.emplace_back(SYNCHRONOUS, 0, sequence_number_++); // EOF
1257
1258 data_ = std::make_unique<SequencedSocketData>(reads_, writes_);
1259 stream_socket_ = CreateConnectedSocket(data_.get());
1260
1261 request_info_.method = "GET";
1262 request_info_.url = url_;
1263 request_info_.load_flags = LOAD_NORMAL;
1264
1265 parser_ = std::make_unique<HttpStreamParser>(
1266 stream_socket_.get(), false /* is_reused */, &request_info_,
1267 read_buffer(), NetLogWithSource());
1268
1269 TestCompletionCallback callback;
1270 ASSERT_EQ(OK, parser_->SendRequest("GET / HTTP/1.1\r\n", request_headers_,
1271 TRAFFIC_ANNOTATION_FOR_TESTS,
1272 &response_info_, callback.callback()));
1273 }
1274
ReadHeadersExpectingError(Error error)1275 void ReadHeadersExpectingError(Error error) {
1276 TestCompletionCallback callback;
1277 EXPECT_THAT(parser_->ReadResponseHeaders(callback.callback()),
1278 IsError(error));
1279 }
1280
ReadHeaders()1281 void ReadHeaders() { ReadHeadersExpectingError(OK); }
1282
ReadBody(int user_buf_len,int * read_lengths)1283 std::string ReadBody(int user_buf_len, int* read_lengths) {
1284 TestCompletionCallback callback;
1285 auto buffer = base::MakeRefCounted<IOBufferWithSize>(user_buf_len);
1286 int rv;
1287 int i = 0;
1288 std::string body;
1289 while (true) {
1290 rv = parser_->ReadResponseBody(
1291 buffer.get(), user_buf_len, callback.callback());
1292 EXPECT_EQ(read_lengths[i], rv);
1293 if (rv > 0)
1294 body.append(buffer->data(), rv);
1295 i++;
1296 if (rv <= 0)
1297 return body;
1298 }
1299 }
1300
1301 private:
1302 GURL url_;
1303
1304 HttpRequestHeaders request_headers_;
1305 HttpResponseInfo response_info_;
1306 HttpRequestInfo request_info_;
1307 scoped_refptr<GrowableIOBuffer> read_buffer_;
1308 std::vector<MockRead> reads_;
1309 std::vector<MockWrite> writes_;
1310 std::unique_ptr<StreamSocket> stream_socket_;
1311 std::unique_ptr<SequencedSocketData> data_;
1312 std::unique_ptr<HttpStreamParser> parser_;
1313 int sequence_number_ = 0;
1314 };
1315
1316 // Test that HTTP/0.9 works as expected, only on ports where it should be
1317 // enabled.
TEST(HttpStreamParser,Http09PortTests)1318 TEST(HttpStreamParser, Http09PortTests) {
1319 struct TestCase {
1320 const char* url;
1321
1322 // Expected result when trying to read headers and response is an HTTP/0.9
1323 // non-Shoutcast response.
1324 Error expected_09_header_error;
1325
1326 // Expected result when trying to read headers for a shoutcast response.
1327 Error expected_shoutcast_header_error;
1328 };
1329
1330 const TestCase kTestCases[] = {
1331 // Default ports should work for HTTP/0.9, regardless of whether the port
1332 // is explicitly specified or not.
1333 {"http://foo.com/", OK, OK},
1334 {"http://foo.com:80/", OK, OK},
1335 {"https://foo.com/", OK, OK},
1336 {"https://foo.com:443/", OK, OK},
1337
1338 // Non-standard ports should not support HTTP/0.9, by default.
1339 {"http://foo.com:8080/", ERR_INVALID_HTTP_RESPONSE, OK},
1340 {"https://foo.com:8080/", ERR_INVALID_HTTP_RESPONSE,
1341 ERR_INVALID_HTTP_RESPONSE},
1342 {"http://foo.com:443/", ERR_INVALID_HTTP_RESPONSE, OK},
1343 {"https://foo.com:80/", ERR_INVALID_HTTP_RESPONSE,
1344 ERR_INVALID_HTTP_RESPONSE},
1345 };
1346
1347 const std::string kResponse = "hello\r\nworld\r\n";
1348
1349 for (const auto& test_case : kTestCases) {
1350 SimpleGetRunner get_runner;
1351 get_runner.set_url(GURL(test_case.url));
1352 get_runner.AddRead(kResponse);
1353 get_runner.SetupParserAndSendRequest();
1354
1355 get_runner.ReadHeadersExpectingError(test_case.expected_09_header_error);
1356 if (test_case.expected_09_header_error != OK)
1357 continue;
1358
1359 ASSERT_TRUE(get_runner.response_info()->headers);
1360 EXPECT_EQ("HTTP/0.9 200 OK",
1361 get_runner.response_info()->headers->GetStatusLine());
1362
1363 EXPECT_EQ(0, get_runner.parser()->received_bytes());
1364 int read_lengths[] = {static_cast<int>(kResponse.size()), 0};
1365 get_runner.ReadBody(kResponse.size(), read_lengths);
1366 EXPECT_EQ(kResponse.size(),
1367 static_cast<size_t>(get_runner.parser()->received_bytes()));
1368 EXPECT_EQ(HttpConnectionInfo::kHTTP0_9,
1369 get_runner.response_info()->connection_info);
1370 }
1371
1372 const std::string kShoutcastResponse = "ICY 200 blah\r\n\r\n";
1373 for (const auto& test_case : kTestCases) {
1374 SimpleGetRunner get_runner;
1375 get_runner.set_url(GURL(test_case.url));
1376 get_runner.AddRead(kShoutcastResponse);
1377 get_runner.SetupParserAndSendRequest();
1378
1379 get_runner.ReadHeadersExpectingError(
1380 test_case.expected_shoutcast_header_error);
1381 if (test_case.expected_shoutcast_header_error != OK)
1382 continue;
1383
1384 ASSERT_TRUE(get_runner.response_info()->headers);
1385 EXPECT_EQ("HTTP/0.9 200 OK",
1386 get_runner.response_info()->headers->GetStatusLine());
1387
1388 EXPECT_EQ(0, get_runner.parser()->received_bytes());
1389 int read_lengths[] = {static_cast<int>(kShoutcastResponse.size()), 0};
1390 get_runner.ReadBody(kShoutcastResponse.size(), read_lengths);
1391 EXPECT_EQ(kShoutcastResponse.size(),
1392 static_cast<size_t>(get_runner.parser()->received_bytes()));
1393 EXPECT_EQ(HttpConnectionInfo::kHTTP0_9,
1394 get_runner.response_info()->connection_info);
1395 }
1396 }
1397
TEST(HttpStreamParser,ContinueWithBody)1398 TEST(HttpStreamParser, ContinueWithBody) {
1399 const std::string kResponse =
1400 "HTTP/1.1 100 Continue\r\n\r\nhello\r\nworld\r\n";
1401
1402 SimpleGetRunner get_runner;
1403 get_runner.set_url(GURL("http://foo.com/"));
1404 get_runner.AddRead(kResponse);
1405 get_runner.SetupParserAndSendRequest();
1406
1407 get_runner.ReadHeadersExpectingError(OK);
1408 ASSERT_TRUE(get_runner.response_info()->headers);
1409 EXPECT_EQ("HTTP/1.1 100 Continue",
1410 get_runner.response_info()->headers->GetStatusLine());
1411
1412 // We ignore informational responses and start reading the next response in
1413 // the stream. This simulates the behavior.
1414 get_runner.ReadHeadersExpectingError(ERR_INVALID_HTTP_RESPONSE);
1415 }
1416
TEST(HttpStreamParser,NullFails)1417 TEST(HttpStreamParser, NullFails) {
1418 const char kTestHeaders[] =
1419 "HTTP/1.1 200 OK\r\n"
1420 "Foo: Bar\r\n"
1421 "Content-Length: 4\r\n\r\n";
1422
1423 // Try inserting a null at each position in kTestHeaders. Every location
1424 // should result in an error.
1425 //
1426 // Need to start at 4 because HttpStreamParser will treat the response as
1427 // HTTP/0.9 if it doesn't see "HTTP", and need to end at -1 because "\r\n\r"
1428 // is currently treated as a valid end of header marker.
1429 for (size_t i = 4; i < std::size(kTestHeaders) - 1; ++i) {
1430 std::string read_data(kTestHeaders);
1431 read_data.insert(i, 1, '\0');
1432 read_data.append("body");
1433 SimpleGetRunner get_runner;
1434 get_runner.set_url(GURL("http://foo.test/"));
1435 get_runner.AddRead(read_data);
1436 get_runner.SetupParserAndSendRequest();
1437
1438 get_runner.ReadHeadersExpectingError(ERR_INVALID_HTTP_RESPONSE);
1439 }
1440 }
1441
1442 // Make sure that Shoutcast is recognized when receiving one byte at a time.
TEST(HttpStreamParser,ShoutcastSingleByteReads)1443 TEST(HttpStreamParser, ShoutcastSingleByteReads) {
1444 SimpleGetRunner get_runner;
1445 get_runner.set_url(GURL("http://foo.com:8080/"));
1446 get_runner.AddRead("i");
1447 get_runner.AddRead("c");
1448 get_runner.AddRead("Y");
1449 // Needed because HttpStreamParser::Read returns ERR_CONNECTION_CLOSED on
1450 // small response headers, which HttpNetworkTransaction replaces with net::OK.
1451 // TODO(mmenke): Can we just change that behavior?
1452 get_runner.AddRead(" Extra stuff");
1453 get_runner.SetupParserAndSendRequest();
1454
1455 get_runner.ReadHeadersExpectingError(OK);
1456 EXPECT_EQ("HTTP/0.9 200 OK",
1457 get_runner.response_info()->headers->GetStatusLine());
1458 }
1459
1460 // Make sure that Shoutcast is recognized when receiving any string starting
1461 // with "ICY", regardless of capitalization, and without a space following it
1462 // (The latter behavior is just to match HTTP detection).
TEST(HttpStreamParser,ShoutcastWeirdHeader)1463 TEST(HttpStreamParser, ShoutcastWeirdHeader) {
1464 SimpleGetRunner get_runner;
1465 get_runner.set_url(GURL("http://foo.com:8080/"));
1466 get_runner.AddRead("iCyCreamSundae");
1467 get_runner.SetupParserAndSendRequest();
1468
1469 get_runner.ReadHeadersExpectingError(OK);
1470 EXPECT_EQ("HTTP/0.9 200 OK",
1471 get_runner.response_info()->headers->GetStatusLine());
1472 }
1473
1474 // Make sure that HTTP/0.9 isn't allowed in the truncated header case on a weird
1475 // port.
TEST(HttpStreamParser,Http09TruncatedHeaderPortTest)1476 TEST(HttpStreamParser, Http09TruncatedHeaderPortTest) {
1477 SimpleGetRunner get_runner;
1478 get_runner.set_url(GURL("http://foo.com:8080/"));
1479 std::string response = "HT";
1480 get_runner.AddRead(response);
1481 get_runner.SetupParserAndSendRequest();
1482
1483 get_runner.ReadHeadersExpectingError(ERR_INVALID_HTTP_RESPONSE);
1484 }
1485
1486 // Test basic case where there is no keep-alive or extra data from the socket,
1487 // and the entire response is received in a single read.
TEST(HttpStreamParser,ReceivedBytesNormal)1488 TEST(HttpStreamParser, ReceivedBytesNormal) {
1489 std::string headers =
1490 "HTTP/1.0 200 OK\r\n"
1491 "Content-Length: 7\r\n\r\n";
1492 std::string body = "content";
1493 std::string response = headers + body;
1494
1495 SimpleGetRunner get_runner;
1496 get_runner.AddRead(response);
1497 get_runner.SetupParserAndSendRequest();
1498 get_runner.ReadHeaders();
1499 int64_t headers_size = headers.size();
1500 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1501 int body_size = body.size();
1502 int read_lengths[] = {body_size, 0};
1503 get_runner.ReadBody(body_size, read_lengths);
1504 int64_t response_size = response.size();
1505 EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1506 EXPECT_EQ(HttpConnectionInfo::kHTTP1_0,
1507 get_runner.response_info()->connection_info);
1508 }
1509
1510 // Test that bytes that represent "next" response are not counted
1511 // as current response "received_bytes".
TEST(HttpStreamParser,ReceivedBytesExcludesNextResponse)1512 TEST(HttpStreamParser, ReceivedBytesExcludesNextResponse) {
1513 std::string headers = "HTTP/1.1 200 OK\r\n"
1514 "Content-Length: 8\r\n\r\n";
1515 std::string body = "content8";
1516 std::string response = headers + body;
1517 std::string next_response = "HTTP/1.1 200 OK\r\n\r\nFOO";
1518 std::string data = response + next_response;
1519
1520 SimpleGetRunner get_runner;
1521 get_runner.AddRead(data);
1522 get_runner.SetupParserAndSendRequest();
1523 get_runner.ReadHeaders();
1524 EXPECT_EQ(39, get_runner.parser()->received_bytes());
1525 int64_t headers_size = headers.size();
1526 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1527 int body_size = body.size();
1528 int read_lengths[] = {body_size, 0};
1529 get_runner.ReadBody(body_size, read_lengths);
1530 int64_t response_size = response.size();
1531 EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1532 int64_t next_response_size = next_response.size();
1533 EXPECT_EQ(next_response_size, get_runner.read_buffer()->offset());
1534 EXPECT_EQ(HttpConnectionInfo::kHTTP1_1,
1535 get_runner.response_info()->connection_info);
1536 }
1537
1538 // Test that "received_bytes" calculation works fine when last read
1539 // contains more data than requested by user.
1540 // We send data in two reads:
1541 // 1) Headers + beginning of response
1542 // 2) remaining part of response + next response start
1543 // We setup user read buffer so it fully accepts the beginnig of response
1544 // body, but it is larger that remaining part of body.
TEST(HttpStreamParser,ReceivedBytesMultiReadExcludesNextResponse)1545 TEST(HttpStreamParser, ReceivedBytesMultiReadExcludesNextResponse) {
1546 std::string headers = "HTTP/1.1 200 OK\r\n"
1547 "Content-Length: 36\r\n\r\n";
1548 int64_t user_buf_len = 32;
1549 std::string body_start = std::string(user_buf_len, '#');
1550 int body_start_size = body_start.size();
1551 EXPECT_EQ(user_buf_len, body_start_size);
1552 std::string response_start = headers + body_start;
1553 std::string body_end = "abcd";
1554 std::string next_response = "HTTP/1.1 200 OK\r\n\r\nFOO";
1555 std::string response_end = body_end + next_response;
1556
1557 SimpleGetRunner get_runner;
1558 get_runner.AddRead(response_start);
1559 get_runner.AddRead(response_end);
1560 get_runner.SetupParserAndSendRequest();
1561 get_runner.ReadHeaders();
1562 int64_t headers_size = headers.size();
1563 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1564 int body_end_size = body_end.size();
1565 int read_lengths[] = {body_start_size, body_end_size, 0};
1566 get_runner.ReadBody(body_start_size, read_lengths);
1567 int64_t response_size = response_start.size() + body_end_size;
1568 EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1569 int64_t next_response_size = next_response.size();
1570 EXPECT_EQ(next_response_size, get_runner.read_buffer()->offset());
1571 }
1572
1573 // Test that "received_bytes" calculation works fine when there is no
1574 // network activity at all; that is when all data is read from read buffer.
1575 // In this case read buffer contains two responses. We expect that only
1576 // bytes that correspond to the first one are taken into account.
TEST(HttpStreamParser,ReceivedBytesFromReadBufExcludesNextResponse)1577 TEST(HttpStreamParser, ReceivedBytesFromReadBufExcludesNextResponse) {
1578 std::string headers = "HTTP/1.1 200 OK\r\n"
1579 "Content-Length: 7\r\n\r\n";
1580 std::string body = "content";
1581 std::string response = headers + body;
1582 std::string next_response = "HTTP/1.1 200 OK\r\n\r\nFOO";
1583 std::string data = response + next_response;
1584
1585 SimpleGetRunner get_runner;
1586 get_runner.AddInitialData(data);
1587 get_runner.SetupParserAndSendRequest();
1588 get_runner.ReadHeaders();
1589 int64_t headers_size = headers.size();
1590 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1591 int body_size = body.size();
1592 int read_lengths[] = {body_size, 0};
1593 get_runner.ReadBody(body_size, read_lengths);
1594 int64_t response_size = response.size();
1595 EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1596 int64_t next_response_size = next_response.size();
1597 EXPECT_EQ(next_response_size, get_runner.read_buffer()->offset());
1598 }
1599
1600 // Test calculating "received_bytes" when part of request has been already
1601 // loaded and placed to read buffer by previous stream parser.
TEST(HttpStreamParser,ReceivedBytesUseReadBuf)1602 TEST(HttpStreamParser, ReceivedBytesUseReadBuf) {
1603 std::string buffer = "HTTP/1.1 200 OK\r\n";
1604 std::string remaining_headers = "Content-Length: 7\r\n\r\n";
1605 int64_t headers_size = buffer.size() + remaining_headers.size();
1606 std::string body = "content";
1607 std::string response = remaining_headers + body;
1608
1609 SimpleGetRunner get_runner;
1610 get_runner.AddInitialData(buffer);
1611 get_runner.AddRead(response);
1612 get_runner.SetupParserAndSendRequest();
1613 get_runner.ReadHeaders();
1614 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1615 int body_size = body.size();
1616 int read_lengths[] = {body_size, 0};
1617 get_runner.ReadBody(body_size, read_lengths);
1618 EXPECT_EQ(headers_size + body_size, get_runner.parser()->received_bytes());
1619 EXPECT_EQ(0, get_runner.read_buffer()->offset());
1620 }
1621
1622 // Test the case when the resulting read_buf contains both unused bytes and
1623 // bytes ejected by chunked-encoding filter.
TEST(HttpStreamParser,ReceivedBytesChunkedTransferExcludesNextResponse)1624 TEST(HttpStreamParser, ReceivedBytesChunkedTransferExcludesNextResponse) {
1625 std::string response = "HTTP/1.1 200 OK\r\n"
1626 "Transfer-Encoding: chunked\r\n\r\n"
1627 "7\r\nChunk 1\r\n"
1628 "8\r\nChunky 2\r\n"
1629 "6\r\nTest 3\r\n"
1630 "0\r\n\r\n";
1631 std::string next_response = "foo bar\r\n";
1632 std::string data = response + next_response;
1633
1634 SimpleGetRunner get_runner;
1635 get_runner.AddInitialData(data);
1636 get_runner.SetupParserAndSendRequest();
1637 get_runner.ReadHeaders();
1638 int read_lengths[] = {4, 3, 6, 2, 6, 0};
1639 get_runner.ReadBody(7, read_lengths);
1640 int64_t response_size = response.size();
1641 EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1642 int64_t next_response_size = next_response.size();
1643 EXPECT_EQ(next_response_size, get_runner.read_buffer()->offset());
1644 }
1645
1646 // Test that data transfered in multiple reads is correctly processed.
1647 // We feed data into 4-bytes reads. Also we set length of read
1648 // buffer to 5-bytes to test all possible buffer misaligments.
TEST(HttpStreamParser,ReceivedBytesMultipleReads)1649 TEST(HttpStreamParser, ReceivedBytesMultipleReads) {
1650 std::string headers = "HTTP/1.1 200 OK\r\n"
1651 "Content-Length: 33\r\n\r\n";
1652 std::string body = "foo bar baz\r\n"
1653 "sputnik mir babushka";
1654 std::string response = headers + body;
1655
1656 size_t receive_length = 4;
1657 std::vector<std::string> blocks;
1658 for (size_t i = 0; i < response.size(); i += receive_length) {
1659 size_t length = std::min(receive_length, response.size() - i);
1660 blocks.push_back(response.substr(i, length));
1661 }
1662
1663 SimpleGetRunner get_runner;
1664 for (const auto& block : blocks)
1665 get_runner.AddRead(block);
1666 get_runner.SetupParserAndSendRequest();
1667 get_runner.ReadHeaders();
1668 int64_t headers_size = headers.size();
1669 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1670 int read_lengths[] = {1, 4, 4, 4, 4, 4, 4, 4, 4, 0};
1671 get_runner.ReadBody(receive_length + 1, read_lengths);
1672 int64_t response_size = response.size();
1673 EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1674 }
1675
1676 // Test timing information of responses that don't have informational (1xx)
1677 // response headers.
TEST(HttpStreamParser,NonInformationalResponseStart)1678 TEST(HttpStreamParser, NonInformationalResponseStart) {
1679 base::test::TaskEnvironment task_environment(
1680 base::test::TaskEnvironment::TimeSource::MOCK_TIME);
1681
1682 std::string response_headers1 = "HTTP/1.1 200 OK\r\n";
1683 std::string response_headers2 = "Content-Length: 7\r\n\r\n";
1684 int64_t response_headers_size =
1685 response_headers1.size() + response_headers2.size();
1686
1687 std::string response_body = "content";
1688 int64_t response_size = response_headers_size + response_body.size();
1689
1690 MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n")};
1691
1692 MockRead reads[] = {
1693 // Add pauses between header fragments so that the test runner can advance
1694 // the mock clock to test timing information.
1695 MockRead(ASYNC, 1, response_headers1.c_str()),
1696 MockRead(ASYNC, ERR_IO_PENDING, 2),
1697 MockRead(ASYNC, 3, response_headers2.c_str()),
1698 MockRead(ASYNC, 4, response_body.c_str()),
1699 };
1700
1701 // Set up the sequenced socket data.
1702 SequencedSocketData sequenced_socket_data(reads, writes);
1703 std::unique_ptr<StreamSocket> stream_socket =
1704 CreateConnectedSocket(&sequenced_socket_data);
1705
1706 // Set up the http stream parser.
1707 HttpRequestInfo request;
1708 auto read_buffer = base::MakeRefCounted<GrowableIOBuffer>();
1709 HttpStreamParser parser(stream_socket.get(), /*connection_is_reused=*/false,
1710 &request, read_buffer.get(), NetLogWithSource());
1711
1712 // Send a request.
1713 HttpResponseInfo response;
1714 TestCompletionCallback callback;
1715 EXPECT_THAT(parser.SendRequest("GET / HTTP/1.1\r\n", HttpRequestHeaders(),
1716 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
1717 callback.callback()),
1718 IsOk());
1719
1720 EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
1721 IsError(ERR_IO_PENDING));
1722 task_environment.AdvanceClock(base::Seconds(1));
1723
1724 // [seq=1 --> seq=2] The parser reads the first fragment of the response
1725 // headers and then pauses to advance the mock clock.
1726 base::TimeTicks first_response_start_time = task_environment.NowTicks();
1727 sequenced_socket_data.RunUntilPaused();
1728 task_environment.AdvanceClock(base::Seconds(1));
1729
1730 // [seq=3] The parser reads the second fragment of the response headers.
1731 sequenced_socket_data.Resume();
1732 EXPECT_THAT(callback.WaitForResult(), IsOk());
1733
1734 // Check the received headers.
1735 EXPECT_EQ(200, response.headers->response_code());
1736 EXPECT_EQ(response_headers_size, parser.received_bytes());
1737
1738 // No informational responses were served. The first response start time
1739 // should be equal to the non-informational response start time.
1740 EXPECT_EQ(parser.first_response_start_time(), first_response_start_time);
1741 EXPECT_EQ(parser.non_informational_response_start_time(),
1742 first_response_start_time);
1743
1744 // [seq=4] The parser reads the response body.
1745 auto body_buffer =
1746 base::MakeRefCounted<IOBufferWithSize>(response_body.size());
1747 int result = parser.ReadResponseBody(body_buffer.get(), response_body.size(),
1748 callback.callback());
1749 EXPECT_THAT(callback.GetResult(result), response_body.size());
1750
1751 // Check the received body.
1752 EXPECT_EQ(response_size, parser.received_bytes());
1753 }
1754
1755 // Test that "continue" HTTP header is counted as "received_bytes".
TEST(HttpStreamParser,ReceivedBytesIncludesContinueHeader)1756 TEST(HttpStreamParser, ReceivedBytesIncludesContinueHeader) {
1757 base::test::TaskEnvironment task_environment(
1758 base::test::TaskEnvironment::TimeSource::MOCK_TIME);
1759
1760 std::string status100_response_headers1 = "HTTP/1.1 100 ";
1761 std::string status100_response_headers2 = "Continue\r\n\r\n";
1762 int64_t status100_response_headers_size =
1763 status100_response_headers1.size() + status100_response_headers2.size();
1764
1765 std::string response_headers1 = "HTTP/1.1 200 OK\r\n";
1766 std::string response_headers2 = "Content-Length: 7\r\n\r\n";
1767 int64_t response_headers_size =
1768 response_headers1.size() + response_headers2.size();
1769
1770 std::string response_body = "content";
1771 int64_t response_size = status100_response_headers_size +
1772 response_headers_size + response_body.size();
1773
1774 MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n")};
1775
1776 MockRead reads[] = {
1777 // Add pauses between header fragments so that the test runner can advance
1778 // the mock clock to test timing information.
1779
1780 // 100 response headers.
1781 MockRead(ASYNC, 1, status100_response_headers1.c_str()),
1782 MockRead(ASYNC, ERR_IO_PENDING, 2),
1783 MockRead(ASYNC, 3, status100_response_headers2.c_str()),
1784 MockRead(ASYNC, ERR_IO_PENDING, 4),
1785
1786 // 200 response headers and body.
1787 MockRead(ASYNC, 5, response_headers1.c_str()),
1788 MockRead(ASYNC, ERR_IO_PENDING, 6),
1789 MockRead(ASYNC, 7, response_headers2.c_str()),
1790 MockRead(ASYNC, 8, response_body.c_str()),
1791 };
1792
1793 // Set up the sequenced socket data.
1794 SequencedSocketData sequenced_socket_data(reads, writes);
1795 std::unique_ptr<StreamSocket> stream_socket =
1796 CreateConnectedSocket(&sequenced_socket_data);
1797
1798 // Set up the http stream parser.
1799 HttpRequestInfo request;
1800 auto read_buffer = base::MakeRefCounted<GrowableIOBuffer>();
1801 HttpStreamParser parser(stream_socket.get(), /*connection_is_reused=*/false,
1802 &request, read_buffer.get(), NetLogWithSource());
1803
1804 // Send a request.
1805 HttpResponseInfo response;
1806 TestCompletionCallback callback;
1807 EXPECT_THAT(parser.SendRequest("GET / HTTP/1.1\r\n", HttpRequestHeaders(),
1808 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
1809 callback.callback()),
1810 IsOk());
1811
1812 EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
1813 IsError(ERR_IO_PENDING));
1814
1815 // [seq=1 --> seq=2] The parser reads the first fragment of the informational
1816 // response headers and then pauses to advance the mock clock.
1817 base::TimeTicks first_response_start_time = task_environment.NowTicks();
1818 sequenced_socket_data.RunUntilPaused();
1819 task_environment.AdvanceClock(base::Seconds(1));
1820
1821 // [seq=3] The parser reads the second fragment of the informational response
1822 // headers.
1823 sequenced_socket_data.Resume();
1824 EXPECT_THAT(callback.WaitForResult(), IsOk());
1825
1826 // Check the received headers.
1827 EXPECT_EQ(100, response.headers->response_code());
1828 EXPECT_EQ(status100_response_headers_size, parser.received_bytes());
1829
1830 EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
1831 IsError(ERR_IO_PENDING));
1832
1833 // [seq=4] The parser pauses to advance the clock.
1834 sequenced_socket_data.RunUntilPaused();
1835 task_environment.AdvanceClock(base::Seconds(1));
1836
1837 // [seq=5 --> seq=6] The parser reads the first fragment of the
1838 // non-informational response headers and then pauses to advance the mock
1839 // clock.
1840 base::TimeTicks non_informational_response_start_time =
1841 task_environment.NowTicks();
1842 sequenced_socket_data.Resume();
1843 sequenced_socket_data.RunUntilPaused();
1844 task_environment.AdvanceClock(base::Seconds(1));
1845
1846 // [seq=7] The parser reads the second fragment of the non-informational
1847 // response headers.
1848 sequenced_socket_data.Resume();
1849 EXPECT_THAT(callback.WaitForResult(), IsOk());
1850 task_environment.AdvanceClock(base::Seconds(1));
1851
1852 // Check the received headers.
1853 EXPECT_EQ(200, response.headers->response_code());
1854 EXPECT_EQ(status100_response_headers_size + response_headers_size,
1855 parser.received_bytes());
1856
1857 // The first response start time should be captured at the time the first
1858 // fragment of the informational response headers is received.
1859 EXPECT_EQ(parser.first_response_start_time(), first_response_start_time);
1860 // The non-informational response start time should be captured at the time
1861 // the first fragment of the non-informational response headers is received.
1862 EXPECT_EQ(parser.non_informational_response_start_time(),
1863 non_informational_response_start_time);
1864 // The first response start time should be earlier than the non-informational
1865 // response start time.
1866 EXPECT_LT(parser.first_response_start_time(),
1867 parser.non_informational_response_start_time());
1868
1869 // [seq=8] The parser reads the non-informational response body.
1870 auto body_buffer =
1871 base::MakeRefCounted<IOBufferWithSize>(response_body.size());
1872 int result = parser.ReadResponseBody(body_buffer.get(), response_body.size(),
1873 callback.callback());
1874 EXPECT_THAT(callback.GetResult(result), response_body.size());
1875
1876 // Check the received body.
1877 EXPECT_EQ(response_size, parser.received_bytes());
1878 }
1879
1880 // Test that "early hints" HTTP header is counted as "received_bytes".
1881 // 103 Early Hints hasn't been implemented yet and should be ignored, but we
1882 // collect timing information for the experiment (https://crbug.com/1093693).
TEST(HttpStreamParser,EarlyHints)1883 TEST(HttpStreamParser, EarlyHints) {
1884 base::test::TaskEnvironment task_environment(
1885 base::test::TaskEnvironment::TimeSource::MOCK_TIME);
1886
1887 std::string status103_response_headers1 = "HTTP/1.1 103 Early Hints\r\n";
1888 std::string status103_response_headers2 =
1889 "Link: </style.css>; rel=preload; as=style\r\n";
1890 std::string status103_response_headers3 =
1891 "Link: </script.js>; rel=preload; as=script\r\n\r\n";
1892 int64_t status103_response_headers_size = status103_response_headers1.size() +
1893 status103_response_headers2.size() +
1894 status103_response_headers3.size();
1895
1896 std::string response_headers1 = "HTTP/1.1 200 OK\r\n";
1897 std::string response_headers2 = "Content-Length: 7\r\n\r\n";
1898 int64_t response_headers_size =
1899 response_headers1.size() + response_headers2.size();
1900
1901 std::string response_body = "content";
1902 int64_t response_size = status103_response_headers_size +
1903 response_headers_size + response_body.size();
1904
1905 MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n")};
1906
1907 MockRead reads[] = {
1908 // Add pauses between header fragments so that the test runner can advance
1909 // the mock clock to test timing information.
1910
1911 // 103 Early Hints response headers.
1912 MockRead(ASYNC, 1, status103_response_headers1.c_str()),
1913 MockRead(ASYNC, ERR_IO_PENDING, 2),
1914 MockRead(ASYNC, 3, status103_response_headers2.c_str()),
1915 MockRead(ASYNC, ERR_IO_PENDING, 4),
1916 MockRead(ASYNC, 5, status103_response_headers3.c_str()),
1917 MockRead(ASYNC, ERR_IO_PENDING, 6),
1918
1919 // 200 response headers and body.
1920 MockRead(ASYNC, 7, response_headers1.c_str()),
1921 MockRead(ASYNC, ERR_IO_PENDING, 8),
1922 MockRead(ASYNC, 9, response_headers2.c_str()),
1923 MockRead(ASYNC, 10, response_body.c_str()),
1924 };
1925
1926 // Set up the sequenced socket data.
1927 SequencedSocketData sequenced_socket_data(reads, writes);
1928 std::unique_ptr<StreamSocket> stream_socket =
1929 CreateConnectedSocket(&sequenced_socket_data);
1930
1931 // Set up the http stream parser.
1932 HttpRequestInfo request;
1933 auto read_buffer = base::MakeRefCounted<GrowableIOBuffer>();
1934 HttpStreamParser parser(stream_socket.get(), /*connection_is_reused=*/false,
1935 &request, read_buffer.get(), NetLogWithSource());
1936
1937 // Send a request.
1938 HttpResponseInfo response;
1939 TestCompletionCallback callback;
1940 EXPECT_THAT(parser.SendRequest("GET / HTTP/1.1\r\n", HttpRequestHeaders(),
1941 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
1942 callback.callback()),
1943 IsOk());
1944
1945 EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
1946 IsError(ERR_IO_PENDING));
1947
1948 // [seq=1 --> seq=2] The parser reads the first fragment of the informational
1949 // response headers and then pauses to advance the mock clock.
1950 base::TimeTicks first_response_start_time = task_environment.NowTicks();
1951 sequenced_socket_data.RunUntilPaused();
1952 task_environment.AdvanceClock(base::Seconds(1));
1953
1954 // [seq=3 --> seq=4] The parser reads the second fragment of the informational
1955 // response headers and then pauses to advance the mock clock.
1956 sequenced_socket_data.Resume();
1957 sequenced_socket_data.RunUntilPaused();
1958 task_environment.AdvanceClock(base::Seconds(1));
1959
1960 // [seq=5] The parser reads the third fragment of the informational response
1961 // headers.
1962 sequenced_socket_data.Resume();
1963 EXPECT_THAT(callback.WaitForResult(), IsOk());
1964
1965 // Check the received headers.
1966 EXPECT_EQ(103, response.headers->response_code());
1967 EXPECT_EQ(status103_response_headers_size, parser.received_bytes());
1968
1969 EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
1970 IsError(ERR_IO_PENDING));
1971
1972 // [seq=6] The parser pauses to advance the clock.
1973 sequenced_socket_data.RunUntilPaused();
1974 task_environment.AdvanceClock(base::Seconds(1));
1975
1976 // [seq=7 --> seq=8] The parser reads the first fragment of the
1977 // non-informational response headers and then pauses to advance the mock
1978 // clock.
1979 base::TimeTicks non_informational_response_start_time =
1980 task_environment.NowTicks();
1981 sequenced_socket_data.Resume();
1982 sequenced_socket_data.RunUntilPaused();
1983 task_environment.AdvanceClock(base::Seconds(1));
1984
1985 // [seq=9] The parser reads the second fragment of the non-informational
1986 // response headers.
1987 sequenced_socket_data.Resume();
1988 EXPECT_THAT(callback.WaitForResult(), IsOk());
1989 task_environment.AdvanceClock(base::Seconds(1));
1990
1991 // Check the received headers.
1992 EXPECT_EQ(200, response.headers->response_code());
1993 EXPECT_EQ(status103_response_headers_size + response_headers_size,
1994 parser.received_bytes());
1995
1996 // The first response start time and first early hints time should be captured
1997 // at the time the first fragment of the informational response headers is
1998 // received.
1999 EXPECT_EQ(parser.first_response_start_time(), first_response_start_time);
2000 EXPECT_EQ(parser.first_early_hints_time(), first_response_start_time);
2001 // The non-informational response start time should be captured at the time
2002 // the first fragment of the non-informational response headers is received.
2003 EXPECT_EQ(parser.non_informational_response_start_time(),
2004 non_informational_response_start_time);
2005 // The first response start time should be earlier than the non-informational
2006 // response start time.
2007 EXPECT_LT(parser.first_response_start_time(),
2008 parser.non_informational_response_start_time());
2009
2010 // [seq=10] The parser reads the non-informational response body.
2011 auto body_buffer =
2012 base::MakeRefCounted<IOBufferWithSize>(response_body.size());
2013 int result = parser.ReadResponseBody(body_buffer.get(), response_body.size(),
2014 callback.callback());
2015 EXPECT_THAT(callback.GetResult(result), response_body.size());
2016
2017 // Check the received body.
2018 EXPECT_EQ(response_size, parser.received_bytes());
2019 }
2020
2021 // Test the case where informational response headers and non-informational
2022 // response headers are packed in the same fragment.
TEST(HttpStreamParser,MixedResponseHeaders)2023 TEST(HttpStreamParser, MixedResponseHeaders) {
2024 base::test::TaskEnvironment task_environment(
2025 base::test::TaskEnvironment::TimeSource::MOCK_TIME);
2026
2027 std::string status100_response_headers = "HTTP/1.1 100 ";
2028 std::string mixed_response_headers = "Continue\r\n\r\nHTTP/1.1 200 OK\r\n";
2029 std::string response_headers = "Content-Length: 7\r\n\r\n";
2030 int64_t status100_response_headers_size =
2031 status100_response_headers.size() + 12;
2032 int64_t response_headers_size = response_headers.size() + 17;
2033
2034 std::string response_body = "content";
2035 int64_t response_size = status100_response_headers_size +
2036 response_headers_size + response_body.size();
2037
2038 MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n")};
2039
2040 MockRead reads[] = {
2041 // Add pauses between header fragments so that the test runner can advance
2042 // the mock clock to test timing information.
2043
2044 // 100 response headers.
2045 MockRead(ASYNC, 1, status100_response_headers.c_str()),
2046 MockRead(ASYNC, ERR_IO_PENDING, 2),
2047
2048 // Mixed response headers.
2049 MockRead(ASYNC, 3, mixed_response_headers.c_str()),
2050 MockRead(ASYNC, ERR_IO_PENDING, 4),
2051
2052 // 200 response headers and body.
2053 MockRead(ASYNC, 5, response_headers.c_str()),
2054 MockRead(ASYNC, 6, response_body.c_str()),
2055 };
2056
2057 // Set up the sequenced socket data.
2058 SequencedSocketData sequenced_socket_data(reads, writes);
2059 std::unique_ptr<StreamSocket> stream_socket =
2060 CreateConnectedSocket(&sequenced_socket_data);
2061
2062 // Set up the http stream parser.
2063 HttpRequestInfo request;
2064 auto read_buffer = base::MakeRefCounted<GrowableIOBuffer>();
2065 HttpStreamParser parser(stream_socket.get(), /*connection_is_reused=*/false,
2066 &request, read_buffer.get(), NetLogWithSource());
2067
2068 // Send a request.
2069 HttpResponseInfo response;
2070 TestCompletionCallback callback;
2071 EXPECT_THAT(parser.SendRequest("GET / HTTP/1.1\r\n", HttpRequestHeaders(),
2072 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
2073 callback.callback()),
2074 IsOk());
2075
2076 EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
2077 IsError(ERR_IO_PENDING));
2078
2079 // [seq=1 --> seq=2] The parser reads the first fragment of the informational
2080 // response headers and then pauses to advance the mock clock.
2081 base::TimeTicks first_response_start_time = task_environment.NowTicks();
2082 sequenced_socket_data.RunUntilPaused();
2083 task_environment.AdvanceClock(base::Seconds(1));
2084
2085 // [seq=3] The parser reads the second fragment of the informational response
2086 // headers.
2087 sequenced_socket_data.Resume();
2088 EXPECT_THAT(callback.WaitForResult(), IsOk());
2089
2090 // Check the received headers.
2091 EXPECT_EQ(100, response.headers->response_code());
2092 EXPECT_EQ(status100_response_headers_size, parser.received_bytes());
2093
2094 EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
2095 IsError(ERR_IO_PENDING));
2096
2097 // [seq=3 --> seq=4] The parser reads the first fragment of the
2098 // non-informational response headers and then pauses to advance the mock
2099 // clock.
2100 base::TimeTicks non_informational_response_start_time =
2101 task_environment.NowTicks();
2102 sequenced_socket_data.RunUntilPaused();
2103 task_environment.AdvanceClock(base::Seconds(1));
2104
2105 // [seq=5] The parser reads the second fragment of the non-informational
2106 // response headers.
2107 sequenced_socket_data.Resume();
2108 EXPECT_THAT(callback.WaitForResult(), IsOk());
2109
2110 // Check the received headers.
2111 EXPECT_EQ(200, response.headers->response_code());
2112 EXPECT_EQ(status100_response_headers_size + response_headers_size,
2113 parser.received_bytes());
2114
2115 // The first response start time should be captured at the time the first
2116 // fragment of the informational response headers is received.
2117 EXPECT_EQ(parser.first_response_start_time(), first_response_start_time);
2118 // The non-informational response start time should be captured at the time
2119 // the first fragment of the non-informational response headers is received.
2120 EXPECT_EQ(parser.non_informational_response_start_time(),
2121 non_informational_response_start_time);
2122 // The first response start time should be earlier than the non-informational
2123 // response start time.
2124 EXPECT_LT(parser.first_response_start_time(),
2125 parser.non_informational_response_start_time());
2126
2127 // [seq=6] The parser reads the non-informational response body.
2128 auto body_buffer =
2129 base::MakeRefCounted<IOBufferWithSize>(response_body.size());
2130 int result = parser.ReadResponseBody(body_buffer.get(), response_body.size(),
2131 callback.callback());
2132 EXPECT_THAT(callback.GetResult(result), response_body.size());
2133
2134 // Check the received body.
2135 EXPECT_EQ(response_size, parser.received_bytes());
2136 }
2137
2138 // Test that an HttpStreamParser can be read from after it's received headers
2139 // and data structures owned by its owner have been deleted. This happens
2140 // when a ResponseBodyDrainer is used.
TEST(HttpStreamParser,ReadAfterUnownedObjectsDestroyed)2141 TEST(HttpStreamParser, ReadAfterUnownedObjectsDestroyed) {
2142 MockWrite writes[] = {
2143 MockWrite(SYNCHRONOUS, 0,
2144 "GET /foo.html HTTP/1.1\r\n\r\n"),
2145 };
2146
2147 const int kBodySize = 1;
2148 MockRead reads[] = {
2149 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
2150 MockRead(SYNCHRONOUS, 2, "Content-Length: 1\r\n"),
2151 MockRead(SYNCHRONOUS, 3, "Connection: Keep-Alive\r\n\r\n"),
2152 MockRead(SYNCHRONOUS, 4, "1"),
2153 MockRead(SYNCHRONOUS, 0, 5), // EOF
2154 };
2155
2156 SequencedSocketData data(reads, writes);
2157 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
2158
2159 auto request_info = std::make_unique<HttpRequestInfo>();
2160 request_info->method = "GET";
2161 request_info->url = GURL("http://somewhere/foo.html");
2162
2163 scoped_refptr<GrowableIOBuffer> read_buffer =
2164 base::MakeRefCounted<GrowableIOBuffer>();
2165 HttpStreamParser parser(stream_socket.get(), false /* is_reused */,
2166 request_info.get(), read_buffer.get(),
2167 NetLogWithSource());
2168
2169 auto request_headers = std::make_unique<HttpRequestHeaders>();
2170 auto response_info = std::make_unique<HttpResponseInfo>();
2171 TestCompletionCallback callback;
2172 ASSERT_EQ(
2173 OK, parser.SendRequest("GET /foo.html HTTP/1.1\r\n", *request_headers,
2174 TRAFFIC_ANNOTATION_FOR_TESTS, response_info.get(),
2175 callback.callback()));
2176 ASSERT_THAT(parser.ReadResponseHeaders(callback.callback()), IsOk());
2177
2178 // If the object that owns the HttpStreamParser is deleted, it takes the
2179 // objects passed to the HttpStreamParser with it.
2180 request_info.reset();
2181 request_headers.reset();
2182 response_info.reset();
2183
2184 auto body_buffer = base::MakeRefCounted<IOBufferWithSize>(kBodySize);
2185 ASSERT_EQ(kBodySize, parser.ReadResponseBody(
2186 body_buffer.get(), kBodySize, callback.callback()));
2187
2188 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
2189 EXPECT_EQ(CountReadBytes(reads), parser.received_bytes());
2190 }
2191
2192 // Case where one byte is received at a time.
TEST(HttpStreamParser,ReceiveOneByteAtATime)2193 TEST(HttpStreamParser, ReceiveOneByteAtATime) {
2194 const std::string kResponseHeaders =
2195 "HTTP/1.0 200 OK\r\n"
2196 "Foo: Bar\r\n\r\n";
2197 const std::string kResponseBody = "hi";
2198
2199 SimpleGetRunner get_runner;
2200 for (size_t i = 0; i < kResponseHeaders.length(); ++i) {
2201 get_runner.AddRead(base::StringPiece(kResponseHeaders.data() + i, 1));
2202 }
2203 for (size_t i = 0; i < kResponseBody.length(); ++i) {
2204 get_runner.AddRead(base::StringPiece(kResponseBody.data() + i, 1));
2205 }
2206 // EOF
2207 get_runner.AddRead("");
2208
2209 get_runner.SetupParserAndSendRequest();
2210 get_runner.ReadHeaders();
2211 std::string header_value;
2212 EXPECT_TRUE(get_runner.response_info()->headers->GetNormalizedHeader(
2213 "Foo", &header_value));
2214 EXPECT_EQ("Bar", header_value);
2215 int read_lengths[] = {1, 1, 0};
2216 EXPECT_EQ(kResponseBody,
2217 get_runner.ReadBody(kResponseBody.size(), read_lengths));
2218 }
2219
2220 } // namespace
2221
2222 } // namespace net
2223