xref: /aosp_15_r20/external/cronet/net/http/http_stream_parser_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 <string_view>
13 #include <utility>
14 #include <vector>
15 
16 #include "base/files/file_path.h"
17 #include "base/files/file_util.h"
18 #include "base/files/scoped_temp_dir.h"
19 #include "base/functional/bind.h"
20 #include "base/memory/ref_counted.h"
21 #include "base/run_loop.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 std::string_view kPayload = "";
295   const std::string_view 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, std::string_view(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, std::string_view(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, std::string_view(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, std::string_view(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(
1215       "a fake websocket frame",
1216       std::string_view(read_buffer->StartOfBuffer(), 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(std::string_view string_piece)1250   void AddRead(std::string_view string_piece) {
1251     reads_.emplace_back(SYNCHRONOUS, string_piece.data(), string_piece.length(),
1252                         sequence_number_++);
1253   }
1254 
AddAsyncRead(std::string_view string_piece)1255   void AddAsyncRead(std::string_view string_piece) {
1256     reads_.emplace_back(ASYNC, string_piece.data(), string_piece.length(),
1257                         sequence_number_++);
1258   }
1259 
SetupParserAndSendRequest()1260   void SetupParserAndSendRequest() {
1261     reads_.emplace_back(SYNCHRONOUS, 0, sequence_number_++);  // EOF
1262 
1263     data_ = std::make_unique<SequencedSocketData>(reads_, writes_);
1264     stream_socket_ = CreateConnectedSocket(data_.get());
1265 
1266     request_info_.method = "GET";
1267     request_info_.url = url_;
1268     request_info_.load_flags = LOAD_NORMAL;
1269 
1270     parser_ = std::make_unique<HttpStreamParser>(
1271         stream_socket_.get(), false /* is_reused */, &request_info_,
1272         read_buffer(), NetLogWithSource());
1273 
1274     TestCompletionCallback callback;
1275     ASSERT_EQ(OK, parser_->SendRequest("GET / HTTP/1.1\r\n", request_headers_,
1276                                        TRAFFIC_ANNOTATION_FOR_TESTS,
1277                                        &response_info_, callback.callback()));
1278   }
1279 
ReadHeadersExpectingError(Error error)1280   void ReadHeadersExpectingError(Error error) {
1281     TestCompletionCallback callback;
1282     EXPECT_THAT(parser_->ReadResponseHeaders(callback.callback()),
1283                 IsError(error));
1284   }
1285 
ReadHeaders()1286   void ReadHeaders() { ReadHeadersExpectingError(OK); }
1287 
ReadBody(int user_buf_len,int * read_lengths)1288   std::string ReadBody(int user_buf_len, int* read_lengths) {
1289     TestCompletionCallback callback;
1290     auto buffer = base::MakeRefCounted<IOBufferWithSize>(user_buf_len);
1291     int rv;
1292     int i = 0;
1293     std::string body;
1294     while (true) {
1295       rv = parser_->ReadResponseBody(
1296           buffer.get(), user_buf_len, callback.callback());
1297       EXPECT_EQ(read_lengths[i], rv);
1298       if (rv == ERR_IO_PENDING) {
1299         rv = callback.WaitForResult();
1300         i++;
1301         EXPECT_EQ(read_lengths[i], rv);
1302       }
1303       if (rv > 0)
1304         body.append(buffer->data(), rv);
1305       i++;
1306       if (rv <= 0)
1307         return body;
1308     }
1309   }
1310 
1311  private:
1312   GURL url_;
1313 
1314   HttpRequestHeaders request_headers_;
1315   HttpResponseInfo response_info_;
1316   HttpRequestInfo request_info_;
1317   scoped_refptr<GrowableIOBuffer> read_buffer_;
1318   std::vector<MockRead> reads_;
1319   std::vector<MockWrite> writes_;
1320   std::unique_ptr<StreamSocket> stream_socket_;
1321   std::unique_ptr<SequencedSocketData> data_;
1322   std::unique_ptr<HttpStreamParser> parser_;
1323   int sequence_number_ = 0;
1324 };
1325 
1326 // Test that HTTP/0.9 works as expected, only on ports where it should be
1327 // enabled.
TEST(HttpStreamParser,Http09PortTests)1328 TEST(HttpStreamParser, Http09PortTests) {
1329   struct TestCase {
1330     const char* url;
1331 
1332     // Expected result when trying to read headers and response is an HTTP/0.9
1333     // non-Shoutcast response.
1334     Error expected_09_header_error;
1335 
1336     // Expected result when trying to read headers for a shoutcast response.
1337     Error expected_shoutcast_header_error;
1338   };
1339 
1340   const TestCase kTestCases[] = {
1341       // Default ports should work for HTTP/0.9, regardless of whether the port
1342       // is explicitly specified or not.
1343       {"http://foo.com/", OK, OK},
1344       {"http://foo.com:80/", OK, OK},
1345       {"https://foo.com/", OK, OK},
1346       {"https://foo.com:443/", OK, OK},
1347 
1348       // Non-standard ports should not support HTTP/0.9, by default.
1349       {"http://foo.com:8080/", ERR_INVALID_HTTP_RESPONSE, OK},
1350       {"https://foo.com:8080/", ERR_INVALID_HTTP_RESPONSE,
1351        ERR_INVALID_HTTP_RESPONSE},
1352       {"http://foo.com:443/", ERR_INVALID_HTTP_RESPONSE, OK},
1353       {"https://foo.com:80/", ERR_INVALID_HTTP_RESPONSE,
1354        ERR_INVALID_HTTP_RESPONSE},
1355   };
1356 
1357   const std::string kResponse = "hello\r\nworld\r\n";
1358 
1359   for (const auto& test_case : kTestCases) {
1360     SimpleGetRunner get_runner;
1361     get_runner.set_url(GURL(test_case.url));
1362     get_runner.AddRead(kResponse);
1363     get_runner.SetupParserAndSendRequest();
1364 
1365     get_runner.ReadHeadersExpectingError(test_case.expected_09_header_error);
1366     if (test_case.expected_09_header_error != OK)
1367       continue;
1368 
1369     ASSERT_TRUE(get_runner.response_info()->headers);
1370     EXPECT_EQ("HTTP/0.9 200 OK",
1371               get_runner.response_info()->headers->GetStatusLine());
1372 
1373     EXPECT_EQ(0, get_runner.parser()->received_bytes());
1374     int read_lengths[] = {static_cast<int>(kResponse.size()), 0};
1375     get_runner.ReadBody(kResponse.size(), read_lengths);
1376     EXPECT_EQ(kResponse.size(),
1377               static_cast<size_t>(get_runner.parser()->received_bytes()));
1378     EXPECT_EQ(HttpConnectionInfo::kHTTP0_9,
1379               get_runner.response_info()->connection_info);
1380   }
1381 
1382   const std::string kShoutcastResponse = "ICY 200 blah\r\n\r\n";
1383   for (const auto& test_case : kTestCases) {
1384     SimpleGetRunner get_runner;
1385     get_runner.set_url(GURL(test_case.url));
1386     get_runner.AddRead(kShoutcastResponse);
1387     get_runner.SetupParserAndSendRequest();
1388 
1389     get_runner.ReadHeadersExpectingError(
1390         test_case.expected_shoutcast_header_error);
1391     if (test_case.expected_shoutcast_header_error != OK)
1392       continue;
1393 
1394     ASSERT_TRUE(get_runner.response_info()->headers);
1395     EXPECT_EQ("HTTP/0.9 200 OK",
1396               get_runner.response_info()->headers->GetStatusLine());
1397 
1398     EXPECT_EQ(0, get_runner.parser()->received_bytes());
1399     int read_lengths[] = {static_cast<int>(kShoutcastResponse.size()), 0};
1400     get_runner.ReadBody(kShoutcastResponse.size(), read_lengths);
1401     EXPECT_EQ(kShoutcastResponse.size(),
1402               static_cast<size_t>(get_runner.parser()->received_bytes()));
1403     EXPECT_EQ(HttpConnectionInfo::kHTTP0_9,
1404               get_runner.response_info()->connection_info);
1405   }
1406 }
1407 
TEST(HttpStreamParser,ContinueWithBody)1408 TEST(HttpStreamParser, ContinueWithBody) {
1409   const std::string kResponse =
1410       "HTTP/1.1 100 Continue\r\n\r\nhello\r\nworld\r\n";
1411 
1412   SimpleGetRunner get_runner;
1413   get_runner.set_url(GURL("http://foo.com/"));
1414   get_runner.AddRead(kResponse);
1415   get_runner.SetupParserAndSendRequest();
1416 
1417   get_runner.ReadHeadersExpectingError(OK);
1418   ASSERT_TRUE(get_runner.response_info()->headers);
1419   EXPECT_EQ("HTTP/1.1 100 Continue",
1420             get_runner.response_info()->headers->GetStatusLine());
1421 
1422   // We ignore informational responses and start reading the next response in
1423   // the stream. This simulates the behavior.
1424   get_runner.ReadHeadersExpectingError(ERR_INVALID_HTTP_RESPONSE);
1425 }
1426 
TEST(HttpStreamParser,NullFails)1427 TEST(HttpStreamParser, NullFails) {
1428   const char kTestHeaders[] =
1429       "HTTP/1.1 200 OK\r\n"
1430       "Foo: Bar\r\n"
1431       "Content-Length: 4\r\n\r\n";
1432 
1433   // Try inserting a null at each position in kTestHeaders. Every location
1434   // should result in an error.
1435   //
1436   // Need to start at 4 because HttpStreamParser will treat the response as
1437   // HTTP/0.9 if it doesn't see "HTTP", and need to end at -1 because "\r\n\r"
1438   // is currently treated as a valid end of header marker.
1439   for (size_t i = 4; i < std::size(kTestHeaders) - 1; ++i) {
1440     std::string read_data(kTestHeaders);
1441     read_data.insert(i, 1, '\0');
1442     read_data.append("body");
1443     SimpleGetRunner get_runner;
1444     get_runner.set_url(GURL("http://foo.test/"));
1445     get_runner.AddRead(read_data);
1446     get_runner.SetupParserAndSendRequest();
1447 
1448     get_runner.ReadHeadersExpectingError(ERR_INVALID_HTTP_RESPONSE);
1449   }
1450 }
1451 
1452 // Make sure that Shoutcast is recognized when receiving one byte at a time.
TEST(HttpStreamParser,ShoutcastSingleByteReads)1453 TEST(HttpStreamParser, ShoutcastSingleByteReads) {
1454   SimpleGetRunner get_runner;
1455   get_runner.set_url(GURL("http://foo.com:8080/"));
1456   get_runner.AddRead("i");
1457   get_runner.AddRead("c");
1458   get_runner.AddRead("Y");
1459   // Needed because HttpStreamParser::Read returns ERR_CONNECTION_CLOSED on
1460   // small response headers, which HttpNetworkTransaction replaces with net::OK.
1461   // TODO(mmenke): Can we just change that behavior?
1462   get_runner.AddRead(" Extra stuff");
1463   get_runner.SetupParserAndSendRequest();
1464 
1465   get_runner.ReadHeadersExpectingError(OK);
1466   EXPECT_EQ("HTTP/0.9 200 OK",
1467             get_runner.response_info()->headers->GetStatusLine());
1468 }
1469 
1470 // Make sure that Shoutcast is recognized when receiving any string starting
1471 // with "ICY", regardless of capitalization, and without a space following it
1472 // (The latter behavior is just to match HTTP detection).
TEST(HttpStreamParser,ShoutcastWeirdHeader)1473 TEST(HttpStreamParser, ShoutcastWeirdHeader) {
1474   SimpleGetRunner get_runner;
1475   get_runner.set_url(GURL("http://foo.com:8080/"));
1476   get_runner.AddRead("iCyCreamSundae");
1477   get_runner.SetupParserAndSendRequest();
1478 
1479   get_runner.ReadHeadersExpectingError(OK);
1480   EXPECT_EQ("HTTP/0.9 200 OK",
1481             get_runner.response_info()->headers->GetStatusLine());
1482 }
1483 
1484 // Make sure that HTTP/0.9 isn't allowed in the truncated header case on a weird
1485 // port.
TEST(HttpStreamParser,Http09TruncatedHeaderPortTest)1486 TEST(HttpStreamParser, Http09TruncatedHeaderPortTest) {
1487   SimpleGetRunner get_runner;
1488   get_runner.set_url(GURL("http://foo.com:8080/"));
1489   std::string response = "HT";
1490   get_runner.AddRead(response);
1491   get_runner.SetupParserAndSendRequest();
1492 
1493   get_runner.ReadHeadersExpectingError(ERR_INVALID_HTTP_RESPONSE);
1494 }
1495 
1496 // Test basic case where there is no keep-alive or extra data from the socket,
1497 // and the entire response is received in a single read.
TEST(HttpStreamParser,ReceivedBytesNormal)1498 TEST(HttpStreamParser, ReceivedBytesNormal) {
1499   std::string headers =
1500       "HTTP/1.0 200 OK\r\n"
1501       "Content-Length: 7\r\n\r\n";
1502   std::string body = "content";
1503   std::string response = headers + body;
1504 
1505   SimpleGetRunner get_runner;
1506   get_runner.AddRead(response);
1507   get_runner.SetupParserAndSendRequest();
1508   get_runner.ReadHeaders();
1509   int64_t headers_size = headers.size();
1510   EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1511   int body_size = body.size();
1512   int read_lengths[] = {body_size, 0};
1513   get_runner.ReadBody(body_size, read_lengths);
1514   int64_t response_size = response.size();
1515   EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1516   EXPECT_EQ(HttpConnectionInfo::kHTTP1_0,
1517             get_runner.response_info()->connection_info);
1518 }
1519 
1520 // Test that bytes that represent "next" response are not counted
1521 // as current response "received_bytes".
TEST(HttpStreamParser,ReceivedBytesExcludesNextResponse)1522 TEST(HttpStreamParser, ReceivedBytesExcludesNextResponse) {
1523   std::string headers = "HTTP/1.1 200 OK\r\n"
1524       "Content-Length:  8\r\n\r\n";
1525   std::string body = "content8";
1526   std::string response = headers + body;
1527   std::string next_response = "HTTP/1.1 200 OK\r\n\r\nFOO";
1528   std::string data = response + next_response;
1529 
1530   SimpleGetRunner get_runner;
1531   get_runner.AddRead(data);
1532   get_runner.SetupParserAndSendRequest();
1533   get_runner.ReadHeaders();
1534   EXPECT_EQ(39, get_runner.parser()->received_bytes());
1535   int64_t headers_size = headers.size();
1536   EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1537   int body_size = body.size();
1538   int read_lengths[] = {body_size, 0};
1539   get_runner.ReadBody(body_size, read_lengths);
1540   int64_t response_size = response.size();
1541   EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1542   EXPECT_EQ(0, get_runner.read_buffer()->offset());
1543   EXPECT_EQ(HttpConnectionInfo::kHTTP1_1,
1544             get_runner.response_info()->connection_info);
1545 }
1546 
1547 // Test that "received_bytes" calculation works fine when last read
1548 // contains more data than requested by user.
1549 // We send data in two reads:
1550 // 1) Headers + beginning of response
1551 // 2) remaining part of response + next response start
1552 // We setup user read buffer so it fully accepts the beginning of response
1553 // body, but it is larger than remaining part of body.
TEST(HttpStreamParser,ReceivedBytesMultiReadExcludesNextResponse)1554 TEST(HttpStreamParser, ReceivedBytesMultiReadExcludesNextResponse) {
1555   std::string headers = "HTTP/1.1 200 OK\r\n"
1556       "Content-Length: 36\r\n\r\n";
1557   int64_t user_buf_len = 32;
1558   std::string body_start = std::string(user_buf_len, '#');
1559   int body_start_size = body_start.size();
1560   EXPECT_EQ(user_buf_len, body_start_size);
1561   std::string response_start = headers + body_start;
1562   std::string body_end = "abcd";
1563   std::string next_response = "HTTP/1.1 200 OK\r\n\r\nFOO";
1564   std::string response_end = body_end + next_response;
1565 
1566   SimpleGetRunner get_runner;
1567   get_runner.AddRead(response_start);
1568   get_runner.AddRead(response_end);
1569   get_runner.SetupParserAndSendRequest();
1570   get_runner.ReadHeaders();
1571   int64_t headers_size = headers.size();
1572   EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1573   int body_end_size = body_end.size();
1574   int read_lengths[] = {body_start_size, body_end_size, 0};
1575   get_runner.ReadBody(body_start_size, read_lengths);
1576   int64_t response_size = response_start.size() + body_end_size;
1577   EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1578   EXPECT_EQ(0, get_runner.read_buffer()->offset());
1579   EXPECT_FALSE(get_runner.parser()->CanReuseConnection());
1580 }
1581 
TEST(HttpStreamParser,ReceivedBytesMultiReadExcludesExtraData)1582 TEST(HttpStreamParser, ReceivedBytesMultiReadExcludesExtraData) {
1583   const std::string headers =
1584       "HTTP/1.1 200 OK\r\n"
1585       "Content-Length: 36\r\n\r\n";
1586   const int64_t user_buf_len = 32;
1587   const std::string body_start = std::string(user_buf_len, '#');
1588   const int body_start_size = body_start.size();
1589   EXPECT_EQ(user_buf_len, body_start_size);
1590   const std::string body_end = "abcd";
1591   const int body_end_size = body_end.size();
1592   const std::string body = body_start + body_end;
1593   const int body_size = body.size();
1594   const std::string extra_data = "HTTP/1.1 200 OK\r\n\r\nFOO";
1595   const std::string read_data = body + extra_data;
1596 
1597   SimpleGetRunner get_runner;
1598   get_runner.AddRead(headers);
1599   get_runner.AddRead(read_data);
1600   get_runner.SetupParserAndSendRequest();
1601   get_runner.ReadHeaders();
1602   const int headers_size = headers.size();
1603   EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1604   int read_lengths[] = {body_start_size, body_end_size, 0};
1605   get_runner.ReadBody(body_start_size, read_lengths);
1606   const int response_size = headers_size + body_size;
1607   EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1608   EXPECT_EQ(0, get_runner.read_buffer()->offset());
1609   EXPECT_FALSE(get_runner.parser()->CanReuseConnection());
1610 }
1611 
TEST(HttpStreamParser,ReceivedBytesAsyncMultiReadExcludesExtraData)1612 TEST(HttpStreamParser, ReceivedBytesAsyncMultiReadExcludesExtraData) {
1613   base::test::SingleThreadTaskEnvironment task_environment;
1614 
1615   const std::string headers =
1616       "HTTP/1.1 200 OK\r\n"
1617       "Content-Length: 36\r\n\r\n";
1618   const int64_t user_buf_len = 32;
1619   const std::string body_start = std::string(user_buf_len, '#');
1620   const int body_start_size = body_start.size();
1621   EXPECT_EQ(user_buf_len, body_start_size);
1622   const std::string body_end = "abcd";
1623   const int body_end_size = body_end.size();
1624   const std::string body = body_start + body_end;
1625   const int body_size = body.size();
1626   const std::string extra_data = "HTTP/1.1 200 OK\r\n\r\nFOO";
1627   const std::string read_data = body_end + extra_data;
1628 
1629   SimpleGetRunner get_runner;
1630   get_runner.AddRead(headers);
1631   get_runner.AddRead(body_start);
1632   get_runner.AddAsyncRead(read_data);
1633   get_runner.SetupParserAndSendRequest();
1634   get_runner.ReadHeaders();
1635   const int headers_size = headers.size();
1636   EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1637   int read_lengths[] = {body_start_size, -1, body_end_size, 0};
1638   get_runner.ReadBody(body_start_size, read_lengths);
1639   const int response_size = headers_size + body_size;
1640   EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1641   EXPECT_EQ(0, get_runner.read_buffer()->offset());
1642   EXPECT_FALSE(get_runner.parser()->CanReuseConnection());
1643 }
1644 
TEST(HttpStreamParser,ReceivedBytesExcludesExtraDataLargeBuffer)1645 TEST(HttpStreamParser, ReceivedBytesExcludesExtraDataLargeBuffer) {
1646   const std::string headers =
1647       "HTTP/1.1 200 OK\r\n"
1648       "Content-Length: 36\r\n\r\n";
1649   const std::string body = std::string(36, '#');
1650   const int body_size = body.size();
1651   const std::string extra_data = std::string(14, '!');
1652   const std::string response = headers + body + extra_data;
1653   const int response_size = response.size();
1654 
1655   SimpleGetRunner get_runner;
1656   get_runner.AddRead(response);
1657   get_runner.SetupParserAndSendRequest();
1658   get_runner.ReadHeaders();
1659   const int headers_size = headers.size();
1660   EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1661   int read_lengths[] = {body_size, 0};
1662   get_runner.ReadBody(response_size, read_lengths);
1663   const int actual_response_size = headers_size + body_size;
1664   EXPECT_EQ(actual_response_size, get_runner.parser()->received_bytes());
1665   EXPECT_EQ(0, get_runner.read_buffer()->offset());
1666   EXPECT_FALSE(get_runner.parser()->CanReuseConnection());
1667 }
1668 
TEST(HttpStreamParser,ReceivedBytesExcludesExtraDataSmallBuffer)1669 TEST(HttpStreamParser, ReceivedBytesExcludesExtraDataSmallBuffer) {
1670   const std::string headers =
1671       "HTTP/1.1 200 OK\r\n"
1672       "Content-Length: 36\r\n\r\n";
1673   const std::string body = std::string(36, '#');
1674   const int body_size = body.size();
1675   const std::string extra_data = std::string(14, '!');
1676   const std::string response = headers + body + extra_data;
1677 
1678   SimpleGetRunner get_runner;
1679   get_runner.AddRead(response);
1680   get_runner.SetupParserAndSendRequest();
1681   get_runner.ReadHeaders();
1682   const int headers_size = headers.size();
1683   EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1684   int read_lengths[] = {10, 10, 10, 6, 0};
1685   get_runner.ReadBody(10, read_lengths);
1686   const int actual_response_size = headers_size + body_size;
1687   EXPECT_EQ(actual_response_size, get_runner.parser()->received_bytes());
1688   EXPECT_EQ(0, get_runner.read_buffer()->offset());
1689   EXPECT_FALSE(get_runner.parser()->CanReuseConnection());
1690 }
1691 
1692 // Test that "received_bytes" calculation works fine when there is no
1693 // network activity at all; that is when all data is read from read buffer.
1694 // In this case read buffer contains two responses. We expect that only
1695 // bytes that correspond to the first one are taken into account.
TEST(HttpStreamParser,ReceivedBytesFromReadBufExcludesNextResponse)1696 TEST(HttpStreamParser, ReceivedBytesFromReadBufExcludesNextResponse) {
1697   std::string headers = "HTTP/1.1 200 OK\r\n"
1698       "Content-Length: 7\r\n\r\n";
1699   std::string body = "content";
1700   std::string response = headers + body;
1701   std::string next_response = "HTTP/1.1 200 OK\r\n\r\nFOO";
1702   std::string data = response + next_response;
1703 
1704   SimpleGetRunner get_runner;
1705   get_runner.AddInitialData(data);
1706   get_runner.SetupParserAndSendRequest();
1707   get_runner.ReadHeaders();
1708   int64_t headers_size = headers.size();
1709   EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1710   int body_size = body.size();
1711   int read_lengths[] = {body_size, 0};
1712   get_runner.ReadBody(body_size, read_lengths);
1713   int64_t response_size = response.size();
1714   EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1715   EXPECT_EQ(0, get_runner.read_buffer()->offset());
1716   EXPECT_FALSE(get_runner.parser()->CanReuseConnection());
1717 }
1718 
1719 // Test calculating "received_bytes" when part of request has been already
1720 // loaded and placed to read buffer by previous stream parser.
TEST(HttpStreamParser,ReceivedBytesUseReadBuf)1721 TEST(HttpStreamParser, ReceivedBytesUseReadBuf) {
1722   std::string buffer = "HTTP/1.1 200 OK\r\n";
1723   std::string remaining_headers = "Content-Length: 7\r\n\r\n";
1724   int64_t headers_size = buffer.size() + remaining_headers.size();
1725   std::string body = "content";
1726   std::string response = remaining_headers + body;
1727 
1728   SimpleGetRunner get_runner;
1729   get_runner.AddInitialData(buffer);
1730   get_runner.AddRead(response);
1731   get_runner.SetupParserAndSendRequest();
1732   get_runner.ReadHeaders();
1733   EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1734   int body_size = body.size();
1735   int read_lengths[] = {body_size, 0};
1736   get_runner.ReadBody(body_size, read_lengths);
1737   EXPECT_EQ(headers_size + body_size, get_runner.parser()->received_bytes());
1738   EXPECT_EQ(0, get_runner.read_buffer()->offset());
1739 }
1740 
1741 // Test the case when the resulting read_buf contains both unused bytes and
1742 // bytes ejected by chunked-encoding filter.
TEST(HttpStreamParser,ReceivedBytesChunkedTransferExcludesNextResponse)1743 TEST(HttpStreamParser, ReceivedBytesChunkedTransferExcludesNextResponse) {
1744   std::string response = "HTTP/1.1 200 OK\r\n"
1745       "Transfer-Encoding: chunked\r\n\r\n"
1746       "7\r\nChunk 1\r\n"
1747       "8\r\nChunky 2\r\n"
1748       "6\r\nTest 3\r\n"
1749       "0\r\n\r\n";
1750   std::string next_response = "foo bar\r\n";
1751   std::string data = response + next_response;
1752 
1753   SimpleGetRunner get_runner;
1754   get_runner.AddInitialData(data);
1755   get_runner.SetupParserAndSendRequest();
1756   get_runner.ReadHeaders();
1757   int read_lengths[] = {4, 3, 6, 2, 6, 0};
1758   get_runner.ReadBody(7, read_lengths);
1759   int64_t response_size = response.size();
1760   EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1761   int64_t next_response_size = next_response.size();
1762   EXPECT_EQ(next_response_size, get_runner.read_buffer()->offset());
1763 }
1764 
1765 // Test that data transfered in multiple reads is correctly processed.
1766 // We feed data into 4-bytes reads. Also we set length of read
1767 // buffer to 5-bytes to test all possible buffer misaligments.
TEST(HttpStreamParser,ReceivedBytesMultipleReads)1768 TEST(HttpStreamParser, ReceivedBytesMultipleReads) {
1769   std::string headers = "HTTP/1.1 200 OK\r\n"
1770       "Content-Length: 33\r\n\r\n";
1771   std::string body = "foo bar baz\r\n"
1772       "sputnik mir babushka";
1773   std::string response = headers + body;
1774 
1775   size_t receive_length = 4;
1776   std::vector<std::string> blocks;
1777   for (size_t i = 0; i < response.size(); i += receive_length) {
1778     size_t length = std::min(receive_length, response.size() - i);
1779     blocks.push_back(response.substr(i, length));
1780   }
1781 
1782   SimpleGetRunner get_runner;
1783   for (const auto& block : blocks)
1784     get_runner.AddRead(block);
1785   get_runner.SetupParserAndSendRequest();
1786   get_runner.ReadHeaders();
1787   int64_t headers_size = headers.size();
1788   EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1789   int read_lengths[] = {1, 4, 4, 4, 4, 4, 4, 4, 4, 0};
1790   get_runner.ReadBody(receive_length + 1, read_lengths);
1791   int64_t response_size = response.size();
1792   EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1793 }
1794 
1795 // Test timing information of responses that don't have informational (1xx)
1796 // response headers.
TEST(HttpStreamParser,NonInformationalResponseStart)1797 TEST(HttpStreamParser, NonInformationalResponseStart) {
1798   base::test::TaskEnvironment task_environment(
1799       base::test::TaskEnvironment::TimeSource::MOCK_TIME);
1800 
1801   std::string response_headers1 = "HTTP/1.1 200 OK\r\n";
1802   std::string response_headers2 = "Content-Length: 7\r\n\r\n";
1803   int64_t response_headers_size =
1804       response_headers1.size() + response_headers2.size();
1805 
1806   std::string response_body = "content";
1807   int64_t response_size = response_headers_size + response_body.size();
1808 
1809   MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n")};
1810 
1811   MockRead reads[] = {
1812       // Add pauses between header fragments so that the test runner can advance
1813       // the mock clock to test timing information.
1814       MockRead(ASYNC, 1, response_headers1.c_str()),
1815       MockRead(ASYNC, ERR_IO_PENDING, 2),
1816       MockRead(ASYNC, 3, response_headers2.c_str()),
1817       MockRead(ASYNC, 4, response_body.c_str()),
1818   };
1819 
1820   // Set up the sequenced socket data.
1821   SequencedSocketData sequenced_socket_data(reads, writes);
1822   std::unique_ptr<StreamSocket> stream_socket =
1823       CreateConnectedSocket(&sequenced_socket_data);
1824 
1825   // Set up the http stream parser.
1826   HttpRequestInfo request;
1827   auto read_buffer = base::MakeRefCounted<GrowableIOBuffer>();
1828   HttpStreamParser parser(stream_socket.get(), /*connection_is_reused=*/false,
1829                           &request, read_buffer.get(), NetLogWithSource());
1830 
1831   // Send a request.
1832   HttpResponseInfo response;
1833   TestCompletionCallback callback;
1834   EXPECT_THAT(parser.SendRequest("GET / HTTP/1.1\r\n", HttpRequestHeaders(),
1835                                  TRAFFIC_ANNOTATION_FOR_TESTS, &response,
1836                                  callback.callback()),
1837               IsOk());
1838 
1839   EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
1840               IsError(ERR_IO_PENDING));
1841   task_environment.AdvanceClock(base::Seconds(1));
1842 
1843   // [seq=1 --> seq=2] The parser reads the first fragment of the response
1844   // headers and then pauses to advance the mock clock.
1845   base::TimeTicks first_response_start_time = task_environment.NowTicks();
1846   sequenced_socket_data.RunUntilPaused();
1847   task_environment.AdvanceClock(base::Seconds(1));
1848 
1849   // [seq=3] The parser reads the second fragment of the response headers.
1850   sequenced_socket_data.Resume();
1851   EXPECT_THAT(callback.WaitForResult(), IsOk());
1852 
1853   // Check the received headers.
1854   EXPECT_EQ(200, response.headers->response_code());
1855   EXPECT_EQ(response_headers_size, parser.received_bytes());
1856 
1857   // No informational responses were served. The first response start time
1858   // should be equal to the non-informational response start time.
1859   EXPECT_EQ(parser.first_response_start_time(), first_response_start_time);
1860   EXPECT_EQ(parser.non_informational_response_start_time(),
1861             first_response_start_time);
1862 
1863   // [seq=4] The parser reads the response body.
1864   auto body_buffer =
1865       base::MakeRefCounted<IOBufferWithSize>(response_body.size());
1866   int result = parser.ReadResponseBody(body_buffer.get(), response_body.size(),
1867                                        callback.callback());
1868   EXPECT_THAT(callback.GetResult(result), response_body.size());
1869 
1870   // Check the received body.
1871   EXPECT_EQ(response_size, parser.received_bytes());
1872 }
1873 
1874 // Test timing information of responses that don't have informational (1xx)
1875 // response headers, and have no response body.
TEST(HttpStreamParser,NonInformationalResponseStartWithoutBody)1876 TEST(HttpStreamParser, NonInformationalResponseStartWithoutBody) {
1877   base::test::TaskEnvironment task_environment(
1878       base::test::TaskEnvironment::TimeSource::MOCK_TIME);
1879 
1880   std::string response_headers1 = "HTTP/1.1 200 OK\r\n";
1881   std::string response_headers2 = "Content-Length: 0\r\n\r\n";
1882   int64_t response_size = response_headers1.size() + response_headers2.size();
1883 
1884   MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n")};
1885 
1886   MockRead reads[] = {
1887       // Add pauses between header fragments so that the test runner can advance
1888       // the mock clock to test timing information.
1889       MockRead(ASYNC, 1, response_headers1.c_str()),
1890       MockRead(ASYNC, ERR_IO_PENDING, 2),
1891       MockRead(ASYNC, 3, response_headers2.c_str()),
1892   };
1893 
1894   // Set up the sequenced socket data.
1895   SequencedSocketData sequenced_socket_data(reads, writes);
1896   std::unique_ptr<StreamSocket> stream_socket =
1897       CreateConnectedSocket(&sequenced_socket_data);
1898 
1899   // Set up the http stream parser.
1900   HttpRequestInfo request;
1901   auto read_buffer = base::MakeRefCounted<GrowableIOBuffer>();
1902   HttpStreamParser parser(stream_socket.get(), /*connection_is_reused=*/false,
1903                           &request, read_buffer.get(), NetLogWithSource());
1904 
1905   // Send a request.
1906   HttpResponseInfo response;
1907   TestCompletionCallback callback;
1908   EXPECT_THAT(parser.SendRequest("GET / HTTP/1.1\r\n", HttpRequestHeaders(),
1909                                  TRAFFIC_ANNOTATION_FOR_TESTS, &response,
1910                                  callback.callback()),
1911               IsOk());
1912 
1913   EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
1914               IsError(ERR_IO_PENDING));
1915   task_environment.AdvanceClock(base::Seconds(1));
1916 
1917   // [seq=1 --> seq=2] The parser reads the first fragment of the response
1918   // headers and then pauses to advance the mock clock.
1919   base::TimeTicks first_response_start_time = task_environment.NowTicks();
1920   sequenced_socket_data.RunUntilPaused();
1921   task_environment.AdvanceClock(base::Seconds(1));
1922 
1923   // [seq=3] The parser reads the second fragment of the response headers.
1924   sequenced_socket_data.Resume();
1925   EXPECT_THAT(callback.WaitForResult(), IsOk());
1926 
1927   // Check the received headers.
1928   EXPECT_EQ(200, response.headers->response_code());
1929   EXPECT_EQ(response_size, parser.received_bytes());
1930 
1931   // No informational responses were served. The first response start time
1932   // should be equal to the non-informational response start time.
1933   EXPECT_EQ(parser.first_response_start_time(), first_response_start_time);
1934   EXPECT_EQ(parser.non_informational_response_start_time(),
1935             first_response_start_time);
1936 
1937   // [seq=4] The parser reads the response body.
1938   auto body_buffer = base::MakeRefCounted<IOBufferWithSize>(10);
1939   int result = parser.ReadResponseBody(body_buffer.get(), body_buffer->size(),
1940                                        callback.callback());
1941   EXPECT_THAT(callback.GetResult(result), IsError(OK));
1942 }
1943 
1944 // Test that "continue" HTTP header is counted as "received_bytes".
TEST(HttpStreamParser,ReceivedBytesIncludesContinueHeader)1945 TEST(HttpStreamParser, ReceivedBytesIncludesContinueHeader) {
1946   base::test::TaskEnvironment task_environment(
1947       base::test::TaskEnvironment::TimeSource::MOCK_TIME);
1948 
1949   std::string status100_response_headers1 = "HTTP/1.1 100 ";
1950   std::string status100_response_headers2 = "Continue\r\n\r\n";
1951   int64_t status100_response_headers_size =
1952       status100_response_headers1.size() + status100_response_headers2.size();
1953 
1954   std::string response_headers1 = "HTTP/1.1 200 OK\r\n";
1955   std::string response_headers2 = "Content-Length: 7\r\n\r\n";
1956   int64_t response_headers_size =
1957       response_headers1.size() + response_headers2.size();
1958 
1959   std::string response_body = "content";
1960   int64_t response_size = status100_response_headers_size +
1961                           response_headers_size + response_body.size();
1962 
1963   MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n")};
1964 
1965   MockRead reads[] = {
1966       // Add pauses between header fragments so that the test runner can advance
1967       // the mock clock to test timing information.
1968 
1969       // 100 response headers.
1970       MockRead(ASYNC, 1, status100_response_headers1.c_str()),
1971       MockRead(ASYNC, ERR_IO_PENDING, 2),
1972       MockRead(ASYNC, 3, status100_response_headers2.c_str()),
1973       MockRead(ASYNC, ERR_IO_PENDING, 4),
1974 
1975       // 200 response headers and body.
1976       MockRead(ASYNC, 5, response_headers1.c_str()),
1977       MockRead(ASYNC, ERR_IO_PENDING, 6),
1978       MockRead(ASYNC, 7, response_headers2.c_str()),
1979       MockRead(ASYNC, 8, response_body.c_str()),
1980   };
1981 
1982   // Set up the sequenced socket data.
1983   SequencedSocketData sequenced_socket_data(reads, writes);
1984   std::unique_ptr<StreamSocket> stream_socket =
1985       CreateConnectedSocket(&sequenced_socket_data);
1986 
1987   // Set up the http stream parser.
1988   HttpRequestInfo request;
1989   auto read_buffer = base::MakeRefCounted<GrowableIOBuffer>();
1990   HttpStreamParser parser(stream_socket.get(), /*connection_is_reused=*/false,
1991                           &request, read_buffer.get(), NetLogWithSource());
1992 
1993   // Send a request.
1994   HttpResponseInfo response;
1995   TestCompletionCallback callback;
1996   EXPECT_THAT(parser.SendRequest("GET / HTTP/1.1\r\n", HttpRequestHeaders(),
1997                                  TRAFFIC_ANNOTATION_FOR_TESTS, &response,
1998                                  callback.callback()),
1999               IsOk());
2000 
2001   EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
2002               IsError(ERR_IO_PENDING));
2003 
2004   // [seq=1 --> seq=2] The parser reads the first fragment of the informational
2005   // response headers and then pauses to advance the mock clock.
2006   base::TimeTicks first_response_start_time = task_environment.NowTicks();
2007   sequenced_socket_data.RunUntilPaused();
2008   task_environment.AdvanceClock(base::Seconds(1));
2009 
2010   // [seq=3] The parser reads the second fragment of the informational response
2011   // headers.
2012   sequenced_socket_data.Resume();
2013   EXPECT_THAT(callback.WaitForResult(), IsOk());
2014 
2015   // Check the received headers.
2016   EXPECT_EQ(100, response.headers->response_code());
2017   EXPECT_EQ(status100_response_headers_size, parser.received_bytes());
2018 
2019   EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
2020               IsError(ERR_IO_PENDING));
2021 
2022   // [seq=4] The parser pauses to advance the clock.
2023   sequenced_socket_data.RunUntilPaused();
2024   task_environment.AdvanceClock(base::Seconds(1));
2025 
2026   // [seq=5 --> seq=6] The parser reads the first fragment of the
2027   // non-informational response headers and then pauses to advance the mock
2028   // clock.
2029   base::TimeTicks non_informational_response_start_time =
2030       task_environment.NowTicks();
2031   sequenced_socket_data.Resume();
2032   sequenced_socket_data.RunUntilPaused();
2033   task_environment.AdvanceClock(base::Seconds(1));
2034 
2035   // [seq=7] The parser reads the second fragment of the non-informational
2036   // response headers.
2037   sequenced_socket_data.Resume();
2038   EXPECT_THAT(callback.WaitForResult(), IsOk());
2039   task_environment.AdvanceClock(base::Seconds(1));
2040 
2041   // Check the received headers.
2042   EXPECT_EQ(200, response.headers->response_code());
2043   EXPECT_EQ(status100_response_headers_size + response_headers_size,
2044             parser.received_bytes());
2045 
2046   // The first response start time should be captured at the time the first
2047   // fragment of the informational response headers is received.
2048   EXPECT_EQ(parser.first_response_start_time(), first_response_start_time);
2049   // The non-informational response start time should be captured at the time
2050   // the first fragment of the non-informational response headers is received.
2051   EXPECT_EQ(parser.non_informational_response_start_time(),
2052             non_informational_response_start_time);
2053   // The first response start time should be earlier than the non-informational
2054   // response start time.
2055   EXPECT_LT(parser.first_response_start_time(),
2056             parser.non_informational_response_start_time());
2057 
2058   // [seq=8] The parser reads the non-informational response body.
2059   auto body_buffer =
2060       base::MakeRefCounted<IOBufferWithSize>(response_body.size());
2061   int result = parser.ReadResponseBody(body_buffer.get(), response_body.size(),
2062                                        callback.callback());
2063   EXPECT_THAT(callback.GetResult(result), response_body.size());
2064 
2065   // Check the received body.
2066   EXPECT_EQ(response_size, parser.received_bytes());
2067 }
2068 
2069 // Test that "early hints" HTTP header is counted as "received_bytes".
2070 // 103 Early Hints hasn't been implemented yet and should be ignored, but we
2071 // collect timing information for the experiment (https://crbug.com/1093693).
TEST(HttpStreamParser,EarlyHints)2072 TEST(HttpStreamParser, EarlyHints) {
2073   base::test::TaskEnvironment task_environment(
2074       base::test::TaskEnvironment::TimeSource::MOCK_TIME);
2075 
2076   std::string status103_response_headers1 = "HTTP/1.1 103 Early Hints\r\n";
2077   std::string status103_response_headers2 =
2078       "Link: </style.css>; rel=preload; as=style\r\n";
2079   std::string status103_response_headers3 =
2080       "Link: </script.js>; rel=preload; as=script\r\n\r\n";
2081   int64_t status103_response_headers_size = status103_response_headers1.size() +
2082                                             status103_response_headers2.size() +
2083                                             status103_response_headers3.size();
2084 
2085   std::string response_headers1 = "HTTP/1.1 200 OK\r\n";
2086   std::string response_headers2 = "Content-Length: 7\r\n\r\n";
2087   int64_t response_headers_size =
2088       response_headers1.size() + response_headers2.size();
2089 
2090   std::string response_body = "content";
2091   int64_t response_size = status103_response_headers_size +
2092                           response_headers_size + response_body.size();
2093 
2094   MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n")};
2095 
2096   MockRead reads[] = {
2097       // Add pauses between header fragments so that the test runner can advance
2098       // the mock clock to test timing information.
2099 
2100       // 103 Early Hints response headers.
2101       MockRead(ASYNC, 1, status103_response_headers1.c_str()),
2102       MockRead(ASYNC, ERR_IO_PENDING, 2),
2103       MockRead(ASYNC, 3, status103_response_headers2.c_str()),
2104       MockRead(ASYNC, ERR_IO_PENDING, 4),
2105       MockRead(ASYNC, 5, status103_response_headers3.c_str()),
2106       MockRead(ASYNC, ERR_IO_PENDING, 6),
2107 
2108       // 200 response headers and body.
2109       MockRead(ASYNC, 7, response_headers1.c_str()),
2110       MockRead(ASYNC, ERR_IO_PENDING, 8),
2111       MockRead(ASYNC, 9, response_headers2.c_str()),
2112       MockRead(ASYNC, 10, response_body.c_str()),
2113   };
2114 
2115   // Set up the sequenced socket data.
2116   SequencedSocketData sequenced_socket_data(reads, writes);
2117   std::unique_ptr<StreamSocket> stream_socket =
2118       CreateConnectedSocket(&sequenced_socket_data);
2119 
2120   // Set up the http stream parser.
2121   HttpRequestInfo request;
2122   auto read_buffer = base::MakeRefCounted<GrowableIOBuffer>();
2123   HttpStreamParser parser(stream_socket.get(), /*connection_is_reused=*/false,
2124                           &request, read_buffer.get(), NetLogWithSource());
2125 
2126   // Send a request.
2127   HttpResponseInfo response;
2128   TestCompletionCallback callback;
2129   EXPECT_THAT(parser.SendRequest("GET / HTTP/1.1\r\n", HttpRequestHeaders(),
2130                                  TRAFFIC_ANNOTATION_FOR_TESTS, &response,
2131                                  callback.callback()),
2132               IsOk());
2133 
2134   EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
2135               IsError(ERR_IO_PENDING));
2136 
2137   // [seq=1 --> seq=2] The parser reads the first fragment of the informational
2138   // response headers and then pauses to advance the mock clock.
2139   base::TimeTicks first_response_start_time = task_environment.NowTicks();
2140   sequenced_socket_data.RunUntilPaused();
2141   task_environment.AdvanceClock(base::Seconds(1));
2142 
2143   // [seq=3 --> seq=4] The parser reads the second fragment of the informational
2144   // response headers and then pauses to advance the mock clock.
2145   sequenced_socket_data.Resume();
2146   sequenced_socket_data.RunUntilPaused();
2147   task_environment.AdvanceClock(base::Seconds(1));
2148 
2149   // [seq=5] The parser reads the third fragment of the informational response
2150   // headers.
2151   sequenced_socket_data.Resume();
2152   EXPECT_THAT(callback.WaitForResult(), IsOk());
2153 
2154   // Check the received headers.
2155   EXPECT_EQ(103, response.headers->response_code());
2156   EXPECT_EQ(status103_response_headers_size, parser.received_bytes());
2157 
2158   EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
2159               IsError(ERR_IO_PENDING));
2160 
2161   // [seq=6] The parser pauses to advance the clock.
2162   sequenced_socket_data.RunUntilPaused();
2163   task_environment.AdvanceClock(base::Seconds(1));
2164 
2165   // [seq=7 --> seq=8] The parser reads the first fragment of the
2166   // non-informational response headers and then pauses to advance the mock
2167   // clock.
2168   base::TimeTicks non_informational_response_start_time =
2169       task_environment.NowTicks();
2170   sequenced_socket_data.Resume();
2171   sequenced_socket_data.RunUntilPaused();
2172   task_environment.AdvanceClock(base::Seconds(1));
2173 
2174   // [seq=9] The parser reads the second fragment of the non-informational
2175   // response headers.
2176   sequenced_socket_data.Resume();
2177   EXPECT_THAT(callback.WaitForResult(), IsOk());
2178   task_environment.AdvanceClock(base::Seconds(1));
2179 
2180   // Check the received headers.
2181   EXPECT_EQ(200, response.headers->response_code());
2182   EXPECT_EQ(status103_response_headers_size + response_headers_size,
2183             parser.received_bytes());
2184 
2185   // The first response start time and first early hints time should be captured
2186   // at the time the first fragment of the informational response headers is
2187   // received.
2188   EXPECT_EQ(parser.first_response_start_time(), first_response_start_time);
2189   EXPECT_EQ(parser.first_early_hints_time(), first_response_start_time);
2190   // The non-informational response start time should be captured at the time
2191   // the first fragment of the non-informational response headers is received.
2192   EXPECT_EQ(parser.non_informational_response_start_time(),
2193             non_informational_response_start_time);
2194   // The first response start time should be earlier than the non-informational
2195   // response start time.
2196   EXPECT_LT(parser.first_response_start_time(),
2197             parser.non_informational_response_start_time());
2198 
2199   // [seq=10] The parser reads the non-informational response body.
2200   auto body_buffer =
2201       base::MakeRefCounted<IOBufferWithSize>(response_body.size());
2202   int result = parser.ReadResponseBody(body_buffer.get(), response_body.size(),
2203                                        callback.callback());
2204   EXPECT_THAT(callback.GetResult(result), response_body.size());
2205 
2206   // Check the received body.
2207   EXPECT_EQ(response_size, parser.received_bytes());
2208 }
2209 
2210 // Test the case where informational response headers and non-informational
2211 // response headers are packed in the same fragment.
TEST(HttpStreamParser,MixedResponseHeaders)2212 TEST(HttpStreamParser, MixedResponseHeaders) {
2213   base::test::TaskEnvironment task_environment(
2214       base::test::TaskEnvironment::TimeSource::MOCK_TIME);
2215 
2216   std::string status100_response_headers = "HTTP/1.1 100 ";
2217   std::string mixed_response_headers = "Continue\r\n\r\nHTTP/1.1 200 OK\r\n";
2218   std::string response_headers = "Content-Length: 7\r\n\r\n";
2219   int64_t status100_response_headers_size =
2220       status100_response_headers.size() + 12;
2221   int64_t response_headers_size = response_headers.size() + 17;
2222 
2223   std::string response_body = "content";
2224   int64_t response_size = status100_response_headers_size +
2225                           response_headers_size + response_body.size();
2226 
2227   MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n")};
2228 
2229   MockRead reads[] = {
2230       // Add pauses between header fragments so that the test runner can advance
2231       // the mock clock to test timing information.
2232 
2233       // 100 response headers.
2234       MockRead(ASYNC, 1, status100_response_headers.c_str()),
2235       MockRead(ASYNC, ERR_IO_PENDING, 2),
2236 
2237       // Mixed response headers.
2238       MockRead(ASYNC, 3, mixed_response_headers.c_str()),
2239       MockRead(ASYNC, ERR_IO_PENDING, 4),
2240 
2241       // 200 response headers and body.
2242       MockRead(ASYNC, 5, response_headers.c_str()),
2243       MockRead(ASYNC, 6, response_body.c_str()),
2244   };
2245 
2246   // Set up the sequenced socket data.
2247   SequencedSocketData sequenced_socket_data(reads, writes);
2248   std::unique_ptr<StreamSocket> stream_socket =
2249       CreateConnectedSocket(&sequenced_socket_data);
2250 
2251   // Set up the http stream parser.
2252   HttpRequestInfo request;
2253   auto read_buffer = base::MakeRefCounted<GrowableIOBuffer>();
2254   HttpStreamParser parser(stream_socket.get(), /*connection_is_reused=*/false,
2255                           &request, read_buffer.get(), NetLogWithSource());
2256 
2257   // Send a request.
2258   HttpResponseInfo response;
2259   TestCompletionCallback callback;
2260   EXPECT_THAT(parser.SendRequest("GET / HTTP/1.1\r\n", HttpRequestHeaders(),
2261                                  TRAFFIC_ANNOTATION_FOR_TESTS, &response,
2262                                  callback.callback()),
2263               IsOk());
2264 
2265   EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
2266               IsError(ERR_IO_PENDING));
2267 
2268   // [seq=1 --> seq=2] The parser reads the first fragment of the informational
2269   // response headers and then pauses to advance the mock clock.
2270   base::TimeTicks first_response_start_time = task_environment.NowTicks();
2271   sequenced_socket_data.RunUntilPaused();
2272   task_environment.AdvanceClock(base::Seconds(1));
2273 
2274   // [seq=3] The parser reads the second fragment of the informational response
2275   // headers.
2276   sequenced_socket_data.Resume();
2277   EXPECT_THAT(callback.WaitForResult(), IsOk());
2278 
2279   // Check the received headers.
2280   EXPECT_EQ(100, response.headers->response_code());
2281   EXPECT_EQ(status100_response_headers_size, parser.received_bytes());
2282 
2283   EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
2284               IsError(ERR_IO_PENDING));
2285 
2286   // [seq=3 --> seq=4] The parser reads the first fragment of the
2287   // non-informational response headers and then pauses to advance the mock
2288   // clock.
2289   base::TimeTicks non_informational_response_start_time =
2290       task_environment.NowTicks();
2291   sequenced_socket_data.RunUntilPaused();
2292   task_environment.AdvanceClock(base::Seconds(1));
2293 
2294   // [seq=5] The parser reads the second fragment of the non-informational
2295   // response headers.
2296   sequenced_socket_data.Resume();
2297   EXPECT_THAT(callback.WaitForResult(), IsOk());
2298 
2299   // Check the received headers.
2300   EXPECT_EQ(200, response.headers->response_code());
2301   EXPECT_EQ(status100_response_headers_size + response_headers_size,
2302             parser.received_bytes());
2303 
2304   // The first response start time should be captured at the time the first
2305   // fragment of the informational response headers is received.
2306   EXPECT_EQ(parser.first_response_start_time(), first_response_start_time);
2307   // The non-informational response start time should be captured at the time
2308   // the first fragment of the non-informational response headers is received.
2309   EXPECT_EQ(parser.non_informational_response_start_time(),
2310             non_informational_response_start_time);
2311   // The first response start time should be earlier than the non-informational
2312   // response start time.
2313   EXPECT_LT(parser.first_response_start_time(),
2314             parser.non_informational_response_start_time());
2315 
2316   // [seq=6] The parser reads the non-informational response body.
2317   auto body_buffer =
2318       base::MakeRefCounted<IOBufferWithSize>(response_body.size());
2319   int result = parser.ReadResponseBody(body_buffer.get(), response_body.size(),
2320                                        callback.callback());
2321   EXPECT_THAT(callback.GetResult(result), response_body.size());
2322 
2323   // Check the received body.
2324   EXPECT_EQ(response_size, parser.received_bytes());
2325 }
2326 
2327 // Test that an HttpStreamParser can be read from after it's received headers
2328 // and data structures owned by its owner have been deleted.  This happens
2329 // when a ResponseBodyDrainer is used.
TEST(HttpStreamParser,ReadAfterUnownedObjectsDestroyed)2330 TEST(HttpStreamParser, ReadAfterUnownedObjectsDestroyed) {
2331   MockWrite writes[] = {
2332     MockWrite(SYNCHRONOUS, 0,
2333               "GET /foo.html HTTP/1.1\r\n\r\n"),
2334   };
2335 
2336   const int kBodySize = 1;
2337   MockRead reads[] = {
2338       MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
2339       MockRead(SYNCHRONOUS, 2, "Content-Length: 1\r\n"),
2340       MockRead(SYNCHRONOUS, 3, "Connection: Keep-Alive\r\n\r\n"),
2341       MockRead(SYNCHRONOUS, 4, "1"),
2342       MockRead(SYNCHRONOUS, 0, 5),  // EOF
2343   };
2344 
2345   SequencedSocketData data(reads, writes);
2346   std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
2347 
2348   auto request_info = std::make_unique<HttpRequestInfo>();
2349   request_info->method = "GET";
2350   request_info->url = GURL("http://somewhere/foo.html");
2351 
2352   scoped_refptr<GrowableIOBuffer> read_buffer =
2353       base::MakeRefCounted<GrowableIOBuffer>();
2354   HttpStreamParser parser(stream_socket.get(), false /* is_reused */,
2355                           request_info.get(), read_buffer.get(),
2356                           NetLogWithSource());
2357 
2358   auto request_headers = std::make_unique<HttpRequestHeaders>();
2359   auto response_info = std::make_unique<HttpResponseInfo>();
2360   TestCompletionCallback callback;
2361   ASSERT_EQ(
2362       OK, parser.SendRequest("GET /foo.html HTTP/1.1\r\n", *request_headers,
2363                              TRAFFIC_ANNOTATION_FOR_TESTS, response_info.get(),
2364                              callback.callback()));
2365   ASSERT_THAT(parser.ReadResponseHeaders(callback.callback()), IsOk());
2366 
2367   // If the object that owns the HttpStreamParser is deleted, it takes the
2368   // objects passed to the HttpStreamParser with it.
2369   request_info.reset();
2370   request_headers.reset();
2371   response_info.reset();
2372 
2373   auto body_buffer = base::MakeRefCounted<IOBufferWithSize>(kBodySize);
2374   ASSERT_EQ(kBodySize, parser.ReadResponseBody(
2375       body_buffer.get(), kBodySize, callback.callback()));
2376 
2377   EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
2378   EXPECT_EQ(CountReadBytes(reads), parser.received_bytes());
2379 }
2380 
2381 // Case where one byte is received at a time.
TEST(HttpStreamParser,ReceiveOneByteAtATime)2382 TEST(HttpStreamParser, ReceiveOneByteAtATime) {
2383   const std::string kResponseHeaders =
2384       "HTTP/1.0 200 OK\r\n"
2385       "Foo: Bar\r\n\r\n";
2386   const std::string kResponseBody = "hi";
2387 
2388   SimpleGetRunner get_runner;
2389   for (size_t i = 0; i < kResponseHeaders.length(); ++i) {
2390     get_runner.AddRead(std::string_view(kResponseHeaders.data() + i, 1));
2391   }
2392   for (size_t i = 0; i < kResponseBody.length(); ++i) {
2393     get_runner.AddRead(std::string_view(kResponseBody.data() + i, 1));
2394   }
2395   // EOF
2396   get_runner.AddRead("");
2397 
2398   get_runner.SetupParserAndSendRequest();
2399   get_runner.ReadHeaders();
2400   std::string header_value;
2401   EXPECT_TRUE(get_runner.response_info()->headers->GetNormalizedHeader(
2402       "Foo", &header_value));
2403   EXPECT_EQ("Bar", header_value);
2404   int read_lengths[] = {1, 1, 0};
2405   EXPECT_EQ(kResponseBody,
2406             get_runner.ReadBody(kResponseBody.size(), read_lengths));
2407 }
2408 
2409 }  // namespace
2410 
2411 }  // namespace net
2412