• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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