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 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9
10 #include "net/base/elements_upload_data_stream.h"
11
12 #include <stdint.h>
13
14 #include <algorithm>
15 #include <limits>
16 #include <string_view>
17 #include <vector>
18
19 #include "base/containers/span.h"
20 #include "base/files/file_path.h"
21 #include "base/files/file_util.h"
22 #include "base/files/scoped_temp_dir.h"
23 #include "base/functional/bind.h"
24 #include "base/location.h"
25 #include "base/run_loop.h"
26 #include "base/task/single_thread_task_runner.h"
27 #include "base/time/time.h"
28 #include "net/base/completion_once_callback.h"
29 #include "net/base/io_buffer.h"
30 #include "net/base/net_errors.h"
31 #include "net/base/test_completion_callback.h"
32 #include "net/base/upload_bytes_element_reader.h"
33 #include "net/base/upload_data_stream.h"
34 #include "net/base/upload_file_element_reader.h"
35 #include "net/log/net_log_with_source.h"
36 #include "net/test/gtest_util.h"
37 #include "net/test/test_with_task_environment.h"
38 #include "testing/gmock/include/gmock/gmock.h"
39 #include "testing/gtest/include/gtest/gtest.h"
40 #include "testing/platform_test.h"
41
42 using net::test::IsError;
43 using net::test::IsOk;
44
45 using ::testing::DoAll;
46 using ::testing::Invoke;
47 using ::testing::Return;
48 using ::testing::_;
49
50 namespace net {
51
52 namespace {
53
54 const char kTestData[] = "0123456789";
55 const size_t kTestDataSize = std::size(kTestData) - 1;
56 const size_t kTestBufferSize = 1 << 14; // 16KB.
57
58 // Reads data from the upload data stream, and returns the data as string.
ReadFromUploadDataStream(UploadDataStream * stream)59 std::string ReadFromUploadDataStream(UploadDataStream* stream) {
60 std::string data_read;
61 auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestBufferSize);
62 while (!stream->IsEOF()) {
63 TestCompletionCallback callback;
64 const int result =
65 stream->Read(buf.get(), kTestBufferSize, callback.callback());
66 const int bytes_read =
67 result != ERR_IO_PENDING ? result : callback.WaitForResult();
68 data_read.append(buf->data(), bytes_read);
69 }
70 return data_read;
71 }
72
73 // A mock class of UploadElementReader.
74 class MockUploadElementReader : public UploadElementReader {
75 public:
MockUploadElementReader(int content_length,bool is_in_memory)76 MockUploadElementReader(int content_length, bool is_in_memory)
77 : content_length_(content_length),
78 bytes_remaining_(content_length),
79 is_in_memory_(is_in_memory) {}
80
81 ~MockUploadElementReader() override = default;
82
83 // UploadElementReader overrides.
Init(CompletionOnceCallback callback)84 int Init(CompletionOnceCallback callback) override {
85 // This is a back to get around Gmock's lack of support for move-only types.
86 return Init(&callback);
87 }
88 MOCK_METHOD1(Init, int(CompletionOnceCallback* callback));
GetContentLength() const89 uint64_t GetContentLength() const override { return content_length_; }
BytesRemaining() const90 uint64_t BytesRemaining() const override { return bytes_remaining_; }
IsInMemory() const91 bool IsInMemory() const override { return is_in_memory_; }
Read(IOBuffer * buf,int buf_length,CompletionOnceCallback callback)92 int Read(IOBuffer* buf,
93 int buf_length,
94 CompletionOnceCallback callback) override {
95 return Read(buf, buf_length, &callback);
96 }
97 MOCK_METHOD3(Read,
98 int(IOBuffer* buf,
99 int buf_length,
100 CompletionOnceCallback* callback));
101
102 // Sets expectation to return the specified result from Init() asynchronously.
SetAsyncInitExpectation(int result)103 void SetAsyncInitExpectation(int result) {
104 init_result_ = result;
105 EXPECT_CALL(*this, Init(_))
106 .WillOnce(DoAll(Invoke(this, &MockUploadElementReader::OnInit),
107 Return(ERR_IO_PENDING)));
108 }
109
110 // Sets expectation to return the specified result from Read().
SetReadExpectation(int result)111 void SetReadExpectation(int result) {
112 read_result_ = result;
113 EXPECT_CALL(*this, Read(_, _, _))
114 .WillOnce(Invoke(this, &MockUploadElementReader::OnRead));
115 }
116
117 private:
OnInit(CompletionOnceCallback * callback)118 void OnInit(CompletionOnceCallback* callback) {
119 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
120 FROM_HERE, base::BindOnce(std::move(*callback), init_result_));
121 }
122
OnRead(IOBuffer * buf,int buf_length,CompletionOnceCallback * callback)123 int OnRead(IOBuffer* buf, int buf_length, CompletionOnceCallback* callback) {
124 if (read_result_ > 0)
125 bytes_remaining_ = std::max(0, bytes_remaining_ - read_result_);
126 if (IsInMemory()) {
127 return read_result_;
128 } else {
129 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
130 FROM_HERE, base::BindOnce(std::move(*callback), read_result_));
131 return ERR_IO_PENDING;
132 }
133 }
134
135 int content_length_;
136 int bytes_remaining_;
137 bool is_in_memory_;
138
139 // Result value returned from Init().
140 int init_result_ = OK;
141
142 // Result value returned from Read().
143 int read_result_ = OK;
144 };
145
146 } // namespace
147
148 class ElementsUploadDataStreamTest : public PlatformTest,
149 public WithTaskEnvironment {
150 public:
SetUp()151 void SetUp() override {
152 PlatformTest::SetUp();
153 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
154 }
~ElementsUploadDataStreamTest()155 ~ElementsUploadDataStreamTest() override {
156 element_readers_.clear();
157 base::RunLoop().RunUntilIdle();
158 }
159
160 void FileChangedHelper(const base::FilePath& file_path,
161 const base::Time& time,
162 bool error_expected);
163
164 base::ScopedTempDir temp_dir_;
165 std::vector<std::unique_ptr<UploadElementReader>> element_readers_;
166 };
167
TEST_F(ElementsUploadDataStreamTest,EmptyUploadData)168 TEST_F(ElementsUploadDataStreamTest, EmptyUploadData) {
169 std::unique_ptr<UploadDataStream> stream(
170 std::make_unique<ElementsUploadDataStream>(std::move(element_readers_),
171 0));
172 ASSERT_THAT(stream->Init(CompletionOnceCallback(), NetLogWithSource()),
173 IsOk());
174 EXPECT_TRUE(stream->IsInMemory());
175 EXPECT_EQ(0U, stream->size());
176 EXPECT_EQ(0U, stream->position());
177 EXPECT_TRUE(stream->IsEOF());
178 }
179
TEST_F(ElementsUploadDataStreamTest,ConsumeAllBytes)180 TEST_F(ElementsUploadDataStreamTest, ConsumeAllBytes) {
181 element_readers_.push_back(std::make_unique<UploadBytesElementReader>(
182 base::byte_span_from_cstring(kTestData)));
183 std::unique_ptr<UploadDataStream> stream(
184 std::make_unique<ElementsUploadDataStream>(std::move(element_readers_),
185 0));
186 ASSERT_THAT(stream->Init(CompletionOnceCallback(), NetLogWithSource()),
187 IsOk());
188 EXPECT_TRUE(stream->IsInMemory());
189 EXPECT_EQ(kTestDataSize, stream->size());
190 EXPECT_EQ(0U, stream->position());
191 EXPECT_FALSE(stream->IsEOF());
192 auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestBufferSize);
193 while (!stream->IsEOF()) {
194 int bytes_read =
195 stream->Read(buf.get(), kTestBufferSize, CompletionOnceCallback());
196 ASSERT_LE(0, bytes_read); // Not an error.
197 }
198 EXPECT_EQ(kTestDataSize, stream->position());
199 ASSERT_TRUE(stream->IsEOF());
200 }
201
TEST_F(ElementsUploadDataStreamTest,File)202 TEST_F(ElementsUploadDataStreamTest, File) {
203 base::FilePath temp_file_path;
204 ASSERT_TRUE(
205 base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &temp_file_path));
206 ASSERT_TRUE(base::WriteFile(temp_file_path, kTestData));
207
208 element_readers_.push_back(std::make_unique<UploadFileElementReader>(
209 base::SingleThreadTaskRunner::GetCurrentDefault().get(), temp_file_path,
210 0, std::numeric_limits<uint64_t>::max(), base::Time()));
211
212 TestCompletionCallback init_callback;
213 std::unique_ptr<UploadDataStream> stream(
214 std::make_unique<ElementsUploadDataStream>(std::move(element_readers_),
215 0));
216 ASSERT_THAT(stream->Init(init_callback.callback(), NetLogWithSource()),
217 IsError(ERR_IO_PENDING));
218 ASSERT_THAT(init_callback.WaitForResult(), IsOk());
219 EXPECT_FALSE(stream->IsInMemory());
220 EXPECT_EQ(kTestDataSize, stream->size());
221 EXPECT_EQ(0U, stream->position());
222 EXPECT_FALSE(stream->IsEOF());
223 auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestBufferSize);
224 while (!stream->IsEOF()) {
225 TestCompletionCallback read_callback;
226 ASSERT_EQ(
227 ERR_IO_PENDING,
228 stream->Read(buf.get(), kTestBufferSize, read_callback.callback()));
229 ASSERT_LE(0, read_callback.WaitForResult()); // Not an error.
230 }
231 EXPECT_EQ(kTestDataSize, stream->position());
232 ASSERT_TRUE(stream->IsEOF());
233 }
234
TEST_F(ElementsUploadDataStreamTest,FileSmallerThanLength)235 TEST_F(ElementsUploadDataStreamTest, FileSmallerThanLength) {
236 base::FilePath temp_file_path;
237 ASSERT_TRUE(
238 base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &temp_file_path));
239 ASSERT_TRUE(base::WriteFile(temp_file_path, kTestData));
240 const uint64_t kFakeSize = kTestDataSize * 2;
241
242 UploadFileElementReader::ScopedOverridingContentLengthForTests
243 overriding_content_length(kFakeSize);
244
245 element_readers_.push_back(std::make_unique<UploadFileElementReader>(
246 base::SingleThreadTaskRunner::GetCurrentDefault().get(), temp_file_path,
247 0, std::numeric_limits<uint64_t>::max(), base::Time()));
248
249 TestCompletionCallback init_callback;
250 std::unique_ptr<UploadDataStream> stream(
251 std::make_unique<ElementsUploadDataStream>(std::move(element_readers_),
252 0));
253 ASSERT_THAT(stream->Init(init_callback.callback(), NetLogWithSource()),
254 IsError(ERR_IO_PENDING));
255 ASSERT_THAT(init_callback.WaitForResult(), IsOk());
256 EXPECT_FALSE(stream->IsInMemory());
257 EXPECT_EQ(kFakeSize, stream->size());
258 EXPECT_EQ(0U, stream->position());
259
260 auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestBufferSize);
261 EXPECT_FALSE(stream->IsEOF());
262
263 TestCompletionCallback read_callback;
264 ASSERT_EQ(ERR_IO_PENDING,
265 stream->Read(buf.get(), kTestBufferSize, read_callback.callback()));
266 int bytes_read = read_callback.WaitForResult();
267
268 EXPECT_EQ(10, bytes_read);
269 EXPECT_EQ(10U, stream->position());
270
271 // UpdateDataStream will return error if there is something wrong.
272 EXPECT_EQ(ERR_UPLOAD_FILE_CHANGED,
273 stream->Read(buf.get(), kTestBufferSize, read_callback.callback()));
274 EXPECT_EQ(10U, stream->position());
275
276 EXPECT_FALSE(stream->IsEOF());
277 }
278
TEST_F(ElementsUploadDataStreamTest,ReadErrorSync)279 TEST_F(ElementsUploadDataStreamTest, ReadErrorSync) {
280 // This element cannot be read.
281 auto reader = std::make_unique<MockUploadElementReader>(kTestDataSize, true);
282 EXPECT_CALL(*reader, Init(_)).WillOnce(Return(OK));
283 reader->SetReadExpectation(ERR_FAILED);
284 element_readers_.push_back(std::move(reader));
285
286 // This element is ignored because of the error from the previous reader.
287 element_readers_.push_back(std::make_unique<UploadBytesElementReader>(
288 base::byte_span_from_cstring(kTestData)));
289
290 std::unique_ptr<UploadDataStream> stream(
291 std::make_unique<ElementsUploadDataStream>(std::move(element_readers_),
292 0));
293
294 // Run Init().
295 ASSERT_THAT(stream->Init(CompletionOnceCallback(), NetLogWithSource()),
296 IsOk());
297 EXPECT_EQ(kTestDataSize * 2, stream->size());
298 EXPECT_EQ(0U, stream->position());
299 EXPECT_FALSE(stream->IsEOF());
300
301 // Prepare a buffer filled with non-zero data.
302 auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestBufferSize);
303 std::fill_n(buf->data(), kTestBufferSize, -1);
304
305 // Read() results in success even when the reader returns error.
306 EXPECT_EQ(ERR_FAILED,
307 stream->Read(buf.get(), kTestBufferSize, CompletionOnceCallback()));
308 EXPECT_EQ(0U, stream->position());
309 EXPECT_FALSE(stream->IsEOF());
310
311 // The buffer is filled with zero.
312 EXPECT_EQ(0, std::count(buf->data(), buf->data() + kTestBufferSize, 0));
313 }
314
TEST_F(ElementsUploadDataStreamTest,ReadErrorAsync)315 TEST_F(ElementsUploadDataStreamTest, ReadErrorAsync) {
316 // This element cannot be read.
317 auto reader = std::make_unique<MockUploadElementReader>(kTestDataSize, false);
318 reader->SetAsyncInitExpectation(OK);
319 reader->SetReadExpectation(ERR_FAILED);
320 element_readers_.push_back(std::move(reader));
321
322 // This element is ignored because of the error from the previous reader.
323 element_readers_.push_back(std::make_unique<UploadBytesElementReader>(
324 base::byte_span_from_cstring(kTestData)));
325
326 std::unique_ptr<UploadDataStream> stream(
327 std::make_unique<ElementsUploadDataStream>(std::move(element_readers_),
328 0));
329
330 // Run Init().
331 TestCompletionCallback init_callback;
332 ASSERT_THAT(stream->Init(init_callback.callback(), NetLogWithSource()),
333 IsError(ERR_IO_PENDING));
334 EXPECT_THAT(init_callback.WaitForResult(), IsOk());
335 EXPECT_EQ(kTestDataSize * 2, stream->size());
336 EXPECT_EQ(0U, stream->position());
337 EXPECT_FALSE(stream->IsEOF());
338
339 // Prepare a buffer filled with non-zero data.
340 auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestBufferSize);
341 std::fill_n(buf->data(), kTestBufferSize, -1);
342
343 // Read() results in success even when the reader returns error.
344 TestCompletionCallback read_callback;
345 ASSERT_EQ(ERR_IO_PENDING,
346 stream->Read(buf.get(), kTestBufferSize, read_callback.callback()));
347 EXPECT_THAT(read_callback.WaitForResult(), IsError(ERR_FAILED));
348 EXPECT_EQ(0U, stream->position());
349 EXPECT_FALSE(stream->IsEOF());
350
351 // The buffer is empty
352 EXPECT_EQ(0, std::count(buf->data(), buf->data() + kTestBufferSize, 0));
353 }
354
TEST_F(ElementsUploadDataStreamTest,FileAndBytes)355 TEST_F(ElementsUploadDataStreamTest, FileAndBytes) {
356 base::FilePath temp_file_path;
357 ASSERT_TRUE(
358 base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &temp_file_path));
359 ASSERT_TRUE(base::WriteFile(temp_file_path, kTestData));
360
361 const uint64_t kFileRangeOffset = 1;
362 const uint64_t kFileRangeLength = 4;
363 element_readers_.push_back(std::make_unique<UploadFileElementReader>(
364 base::SingleThreadTaskRunner::GetCurrentDefault().get(), temp_file_path,
365 kFileRangeOffset, kFileRangeLength, base::Time()));
366
367 element_readers_.push_back(std::make_unique<UploadBytesElementReader>(
368 base::byte_span_from_cstring(kTestData)));
369
370 const uint64_t kStreamSize = kTestDataSize + kFileRangeLength;
371 TestCompletionCallback init_callback;
372 std::unique_ptr<UploadDataStream> stream(
373 std::make_unique<ElementsUploadDataStream>(std::move(element_readers_),
374 0));
375 ASSERT_THAT(stream->Init(init_callback.callback(), NetLogWithSource()),
376 IsError(ERR_IO_PENDING));
377 ASSERT_THAT(init_callback.WaitForResult(), IsOk());
378 EXPECT_FALSE(stream->IsInMemory());
379 EXPECT_EQ(kStreamSize, stream->size());
380 EXPECT_EQ(0U, stream->position());
381 EXPECT_FALSE(stream->IsEOF());
382 auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestBufferSize);
383 while (!stream->IsEOF()) {
384 TestCompletionCallback read_callback;
385 const int result =
386 stream->Read(buf.get(), kTestBufferSize, read_callback.callback());
387 const int bytes_read =
388 result != ERR_IO_PENDING ? result : read_callback.WaitForResult();
389 ASSERT_LE(0, bytes_read); // Not an error.
390 }
391 EXPECT_EQ(kStreamSize, stream->position());
392 ASSERT_TRUE(stream->IsEOF());
393 }
394
395 // Init() with on-memory and not-on-memory readers.
TEST_F(ElementsUploadDataStreamTest,InitAsync)396 TEST_F(ElementsUploadDataStreamTest, InitAsync) {
397 // Create UploadDataStream with mock readers.
398 auto reader = std::make_unique<MockUploadElementReader>(kTestDataSize, true);
399 EXPECT_CALL(*reader, Init(_)).WillOnce(Return(OK));
400 element_readers_.push_back(std::move(reader));
401
402 auto reader2 = std::make_unique<MockUploadElementReader>(kTestDataSize, true);
403 EXPECT_CALL(*reader2, Init(_)).WillOnce(Return(OK));
404 element_readers_.push_back(std::move(reader2));
405
406 auto reader3 =
407 std::make_unique<MockUploadElementReader>(kTestDataSize, false);
408 reader3->SetAsyncInitExpectation(OK);
409 element_readers_.push_back(std::move(reader3));
410
411 auto reader4 =
412 std::make_unique<MockUploadElementReader>(kTestDataSize, false);
413 reader4->SetAsyncInitExpectation(OK);
414 element_readers_.push_back(std::move(reader4));
415
416 auto reader5 = std::make_unique<MockUploadElementReader>(kTestDataSize, true);
417 EXPECT_CALL(*reader5, Init(_)).WillOnce(Return(OK));
418 element_readers_.push_back(std::move(reader5));
419
420 std::unique_ptr<UploadDataStream> stream(
421 std::make_unique<ElementsUploadDataStream>(std::move(element_readers_),
422 0));
423
424 // Run Init().
425 TestCompletionCallback callback;
426 ASSERT_THAT(stream->Init(callback.callback(), NetLogWithSource()),
427 IsError(ERR_IO_PENDING));
428 EXPECT_THAT(callback.WaitForResult(), IsOk());
429 }
430
431 // Init() of a reader fails asynchronously.
TEST_F(ElementsUploadDataStreamTest,InitAsyncFailureAsync)432 TEST_F(ElementsUploadDataStreamTest, InitAsyncFailureAsync) {
433 // Create UploadDataStream with a mock reader.
434 auto reader = std::make_unique<MockUploadElementReader>(kTestDataSize, false);
435 reader->SetAsyncInitExpectation(ERR_FAILED);
436 element_readers_.push_back(std::move(reader));
437
438 std::unique_ptr<UploadDataStream> stream(
439 std::make_unique<ElementsUploadDataStream>(std::move(element_readers_),
440 0));
441
442 // Run Init().
443 TestCompletionCallback callback;
444 ASSERT_THAT(stream->Init(callback.callback(), NetLogWithSource()),
445 IsError(ERR_IO_PENDING));
446 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_FAILED));
447 }
448
449 // Init() of a reader fails synchronously.
TEST_F(ElementsUploadDataStreamTest,InitAsyncFailureSync)450 TEST_F(ElementsUploadDataStreamTest, InitAsyncFailureSync) {
451 // Create UploadDataStream with mock readers.
452 auto reader = std::make_unique<MockUploadElementReader>(kTestDataSize, false);
453 reader->SetAsyncInitExpectation(OK);
454 element_readers_.push_back(std::move(reader));
455
456 auto reader2 = std::make_unique<MockUploadElementReader>(kTestDataSize, true);
457 EXPECT_CALL(*reader2, Init(_)).WillOnce(Return(ERR_FAILED));
458 element_readers_.push_back(std::move(reader2));
459
460 std::unique_ptr<UploadDataStream> stream(
461 std::make_unique<ElementsUploadDataStream>(std::move(element_readers_),
462 0));
463
464 // Run Init().
465 TestCompletionCallback callback;
466 ASSERT_THAT(stream->Init(callback.callback(), NetLogWithSource()),
467 IsError(ERR_IO_PENDING));
468 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_FAILED));
469 }
470
471 // Read with a buffer whose size is same as the data.
TEST_F(ElementsUploadDataStreamTest,ReadAsyncWithExactSizeBuffer)472 TEST_F(ElementsUploadDataStreamTest, ReadAsyncWithExactSizeBuffer) {
473 element_readers_.push_back(std::make_unique<UploadBytesElementReader>(
474 base::byte_span_from_cstring(kTestData)));
475 std::unique_ptr<UploadDataStream> stream(
476 std::make_unique<ElementsUploadDataStream>(std::move(element_readers_),
477 0));
478
479 ASSERT_THAT(stream->Init(CompletionOnceCallback(), NetLogWithSource()),
480 IsOk());
481 EXPECT_TRUE(stream->IsInMemory());
482 EXPECT_EQ(kTestDataSize, stream->size());
483 EXPECT_EQ(0U, stream->position());
484 EXPECT_FALSE(stream->IsEOF());
485 auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestDataSize);
486 int bytes_read =
487 stream->Read(buf.get(), kTestDataSize, CompletionOnceCallback());
488 ASSERT_TRUE(bytes_read); // Not an error.
489 EXPECT_EQ(kTestDataSize, stream->position());
490 ASSERT_TRUE(stream->IsEOF());
491 }
492
493 // Async Read() with on-memory and not-on-memory readers.
TEST_F(ElementsUploadDataStreamTest,ReadAsync)494 TEST_F(ElementsUploadDataStreamTest, ReadAsync) {
495 // Create UploadDataStream with mock readers.
496 auto reader = std::make_unique<MockUploadElementReader>(kTestDataSize, true);
497 EXPECT_CALL(*reader, Init(_)).WillOnce(Return(OK));
498 reader->SetReadExpectation(kTestDataSize);
499 element_readers_.push_back(std::move(reader));
500
501 auto reader2 =
502 std::make_unique<MockUploadElementReader>(kTestDataSize, false);
503 reader2->SetAsyncInitExpectation(OK);
504 reader2->SetReadExpectation(kTestDataSize);
505 element_readers_.push_back(std::move(reader2));
506
507 auto reader3 = std::make_unique<MockUploadElementReader>(kTestDataSize, true);
508 EXPECT_CALL(*reader3, Init(_)).WillOnce(Return(OK));
509 reader3->SetReadExpectation(kTestDataSize);
510 element_readers_.push_back(std::move(reader3));
511
512 auto reader4 =
513 std::make_unique<MockUploadElementReader>(kTestDataSize, false);
514 reader4->SetAsyncInitExpectation(OK);
515 reader4->SetReadExpectation(kTestDataSize);
516 element_readers_.push_back(std::move(reader4));
517
518 std::unique_ptr<UploadDataStream> stream(
519 std::make_unique<ElementsUploadDataStream>(std::move(element_readers_),
520 0));
521
522 // Run Init().
523 TestCompletionCallback init_callback;
524 EXPECT_THAT(stream->Init(init_callback.callback(), NetLogWithSource()),
525 IsError(ERR_IO_PENDING));
526 EXPECT_THAT(init_callback.WaitForResult(), IsOk());
527
528 auto buf = base::MakeRefCounted<IOBufferWithSize>(kTestBufferSize);
529
530 // Consume the first element.
531 TestCompletionCallback read_callback1;
532 EXPECT_TRUE(
533 stream->Read(buf.get(), kTestDataSize, read_callback1.callback()));
534 base::RunLoop().RunUntilIdle();
535 EXPECT_FALSE(read_callback1.have_result());
536
537 // Consume the second element.
538 TestCompletionCallback read_callback2;
539 ASSERT_EQ(ERR_IO_PENDING,
540 stream->Read(buf.get(), kTestDataSize, read_callback2.callback()));
541 EXPECT_TRUE(read_callback2.WaitForResult());
542
543 // Consume the third and the fourth elements.
544 TestCompletionCallback read_callback3;
545 ASSERT_EQ(ERR_IO_PENDING, stream->Read(buf.get(), kTestDataSize * 2,
546 read_callback3.callback()));
547 EXPECT_EQ(static_cast<int>(kTestDataSize * 2),
548 read_callback3.WaitForResult());
549 }
550
FileChangedHelper(const base::FilePath & file_path,const base::Time & time,bool error_expected)551 void ElementsUploadDataStreamTest::FileChangedHelper(
552 const base::FilePath& file_path,
553 const base::Time& time,
554 bool error_expected) {
555 // Don't use element_readers_ here, as this function is called twice, and
556 // reusing element_readers_ is wrong.
557 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
558 element_readers.push_back(std::make_unique<UploadFileElementReader>(
559 base::SingleThreadTaskRunner::GetCurrentDefault().get(), file_path, 1, 2,
560 time));
561
562 TestCompletionCallback init_callback;
563 std::unique_ptr<UploadDataStream> stream(
564 std::make_unique<ElementsUploadDataStream>(std::move(element_readers),
565 0));
566 ASSERT_THAT(stream->Init(init_callback.callback(), NetLogWithSource()),
567 IsError(ERR_IO_PENDING));
568 int error_code = init_callback.WaitForResult();
569 if (error_expected)
570 ASSERT_THAT(error_code, IsError(ERR_UPLOAD_FILE_CHANGED));
571 else
572 ASSERT_THAT(error_code, IsOk());
573 }
574
TEST_F(ElementsUploadDataStreamTest,FileChanged)575 TEST_F(ElementsUploadDataStreamTest, FileChanged) {
576 base::FilePath temp_file_path;
577 ASSERT_TRUE(
578 base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &temp_file_path));
579 ASSERT_TRUE(base::WriteFile(temp_file_path, kTestData));
580
581 base::File::Info file_info;
582 ASSERT_TRUE(base::GetFileInfo(temp_file_path, &file_info));
583
584 // Test file not changed.
585 FileChangedHelper(temp_file_path, file_info.last_modified, false);
586
587 // Test file changed.
588 FileChangedHelper(temp_file_path, file_info.last_modified - base::Seconds(1),
589 true);
590 }
591
TEST_F(ElementsUploadDataStreamTest,MultipleInit)592 TEST_F(ElementsUploadDataStreamTest, MultipleInit) {
593 base::FilePath temp_file_path;
594 ASSERT_TRUE(
595 base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &temp_file_path));
596 ASSERT_TRUE(base::WriteFile(temp_file_path, kTestData));
597
598 // Prepare data.
599 element_readers_.push_back(std::make_unique<UploadBytesElementReader>(
600 base::byte_span_from_cstring(kTestData)));
601 element_readers_.push_back(std::make_unique<UploadFileElementReader>(
602 base::SingleThreadTaskRunner::GetCurrentDefault().get(), temp_file_path,
603 0, std::numeric_limits<uint64_t>::max(), base::Time()));
604 std::unique_ptr<UploadDataStream> stream(
605 std::make_unique<ElementsUploadDataStream>(std::move(element_readers_),
606 0));
607
608 std::string expected_data(kTestData, kTestData + kTestDataSize);
609 expected_data += expected_data;
610
611 // Call Init().
612 TestCompletionCallback init_callback1;
613 ASSERT_THAT(stream->Init(init_callback1.callback(), NetLogWithSource()),
614 IsError(ERR_IO_PENDING));
615 ASSERT_THAT(init_callback1.WaitForResult(), IsOk());
616 EXPECT_FALSE(stream->IsEOF());
617 EXPECT_EQ(kTestDataSize * 2, stream->size());
618
619 // Read.
620 EXPECT_EQ(expected_data, ReadFromUploadDataStream(stream.get()));
621 EXPECT_TRUE(stream->IsEOF());
622
623 // Call Init() again to reset.
624 TestCompletionCallback init_callback2;
625 ASSERT_THAT(stream->Init(init_callback2.callback(), NetLogWithSource()),
626 IsError(ERR_IO_PENDING));
627 ASSERT_THAT(init_callback2.WaitForResult(), IsOk());
628 EXPECT_FALSE(stream->IsEOF());
629 EXPECT_EQ(kTestDataSize * 2, stream->size());
630
631 // Read again.
632 EXPECT_EQ(expected_data, ReadFromUploadDataStream(stream.get()));
633 EXPECT_TRUE(stream->IsEOF());
634 }
635
TEST_F(ElementsUploadDataStreamTest,MultipleInitAsync)636 TEST_F(ElementsUploadDataStreamTest, MultipleInitAsync) {
637 base::FilePath temp_file_path;
638 ASSERT_TRUE(
639 base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &temp_file_path));
640 ASSERT_TRUE(base::WriteFile(temp_file_path, kTestData));
641 TestCompletionCallback test_callback;
642
643 // Prepare data.
644 element_readers_.push_back(std::make_unique<UploadBytesElementReader>(
645 base::byte_span_from_cstring(kTestData)));
646 element_readers_.push_back(std::make_unique<UploadFileElementReader>(
647 base::SingleThreadTaskRunner::GetCurrentDefault().get(), temp_file_path,
648 0, std::numeric_limits<uint64_t>::max(), base::Time()));
649 std::unique_ptr<UploadDataStream> stream(
650 std::make_unique<ElementsUploadDataStream>(std::move(element_readers_),
651 0));
652
653 std::string expected_data(kTestData, kTestData + kTestDataSize);
654 expected_data += expected_data;
655
656 // Call Init().
657 ASSERT_THAT(stream->Init(test_callback.callback(), NetLogWithSource()),
658 IsError(ERR_IO_PENDING));
659 EXPECT_THAT(test_callback.WaitForResult(), IsOk());
660 EXPECT_FALSE(stream->IsEOF());
661 EXPECT_EQ(kTestDataSize * 2, stream->size());
662
663 // Read.
664 EXPECT_EQ(expected_data, ReadFromUploadDataStream(stream.get()));
665 EXPECT_TRUE(stream->IsEOF());
666
667 // Call Init() again to reset.
668 ASSERT_THAT(stream->Init(test_callback.callback(), NetLogWithSource()),
669 IsError(ERR_IO_PENDING));
670 EXPECT_THAT(test_callback.WaitForResult(), IsOk());
671 EXPECT_FALSE(stream->IsEOF());
672 EXPECT_EQ(kTestDataSize * 2, stream->size());
673
674 // Read again.
675 EXPECT_EQ(expected_data, ReadFromUploadDataStream(stream.get()));
676 EXPECT_TRUE(stream->IsEOF());
677 }
678
TEST_F(ElementsUploadDataStreamTest,InitToReset)679 TEST_F(ElementsUploadDataStreamTest, InitToReset) {
680 base::FilePath temp_file_path;
681 ASSERT_TRUE(
682 base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &temp_file_path));
683 ASSERT_TRUE(base::WriteFile(temp_file_path, kTestData));
684
685 // Prepare data.
686 element_readers_.push_back(std::make_unique<UploadBytesElementReader>(
687 base::byte_span_from_cstring(kTestData)));
688 element_readers_.push_back(std::make_unique<UploadFileElementReader>(
689 base::SingleThreadTaskRunner::GetCurrentDefault().get(), temp_file_path,
690 0, std::numeric_limits<uint64_t>::max(), base::Time()));
691 std::unique_ptr<UploadDataStream> stream(
692 std::make_unique<ElementsUploadDataStream>(std::move(element_readers_),
693 0));
694
695 std::vector<char> expected_data(kTestData, kTestData + kTestDataSize);
696 expected_data.insert(expected_data.end(), kTestData,
697 kTestData + kTestDataSize);
698
699 // Call Init().
700 TestCompletionCallback init_callback1;
701 ASSERT_THAT(stream->Init(init_callback1.callback(), NetLogWithSource()),
702 IsError(ERR_IO_PENDING));
703 EXPECT_THAT(init_callback1.WaitForResult(), IsOk());
704 EXPECT_FALSE(stream->IsEOF());
705 EXPECT_EQ(kTestDataSize * 2, stream->size());
706
707 // Read some.
708 TestCompletionCallback read_callback1;
709 std::vector<char> buf(kTestDataSize + kTestDataSize / 2);
710 auto wrapped_buffer = base::MakeRefCounted<WrappedIOBuffer>(buf);
711 EXPECT_EQ(
712 ERR_IO_PENDING,
713 stream->Read(wrapped_buffer.get(), buf.size(),
714 read_callback1.callback()));
715 EXPECT_EQ(static_cast<int>(buf.size()), read_callback1.WaitForResult());
716 EXPECT_EQ(buf.size(), stream->position());
717
718 // Call Init to reset the state.
719 TestCompletionCallback init_callback2;
720 ASSERT_THAT(stream->Init(init_callback2.callback(), NetLogWithSource()),
721 IsError(ERR_IO_PENDING));
722 EXPECT_THAT(init_callback2.WaitForResult(), IsOk());
723 EXPECT_FALSE(stream->IsEOF());
724 EXPECT_EQ(kTestDataSize * 2, stream->size());
725
726 // Read.
727 TestCompletionCallback read_callback2;
728 std::vector<char> buf2(kTestDataSize * 2);
729 auto wrapped_buffer2 = base::MakeRefCounted<WrappedIOBuffer>(buf2);
730 EXPECT_EQ(ERR_IO_PENDING,
731 stream->Read(
732 wrapped_buffer2.get(), buf2.size(), read_callback2.callback()));
733 EXPECT_EQ(static_cast<int>(buf2.size()), read_callback2.WaitForResult());
734 EXPECT_EQ(expected_data, buf2);
735 }
736
TEST_F(ElementsUploadDataStreamTest,InitDuringAsyncInit)737 TEST_F(ElementsUploadDataStreamTest, InitDuringAsyncInit) {
738 base::FilePath temp_file_path;
739 ASSERT_TRUE(
740 base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &temp_file_path));
741 ASSERT_TRUE(base::WriteFile(temp_file_path, kTestData));
742
743 // Prepare data.
744 element_readers_.push_back(std::make_unique<UploadBytesElementReader>(
745 base::byte_span_from_cstring(kTestData)));
746 element_readers_.push_back(std::make_unique<UploadFileElementReader>(
747 base::SingleThreadTaskRunner::GetCurrentDefault().get(), temp_file_path,
748 0, std::numeric_limits<uint64_t>::max(), base::Time()));
749 std::unique_ptr<UploadDataStream> stream(
750 std::make_unique<ElementsUploadDataStream>(std::move(element_readers_),
751 0));
752
753 std::vector<char> expected_data(kTestData, kTestData + kTestDataSize);
754 expected_data.insert(expected_data.end(), kTestData,
755 kTestData + kTestDataSize);
756
757 // Start Init.
758 TestCompletionCallback init_callback1;
759 EXPECT_THAT(stream->Init(init_callback1.callback(), NetLogWithSource()),
760 IsError(ERR_IO_PENDING));
761
762 // Call Init again to cancel the previous init.
763 TestCompletionCallback init_callback2;
764 EXPECT_THAT(stream->Init(init_callback2.callback(), NetLogWithSource()),
765 IsError(ERR_IO_PENDING));
766 EXPECT_THAT(init_callback2.WaitForResult(), IsOk());
767 EXPECT_FALSE(stream->IsEOF());
768 EXPECT_EQ(kTestDataSize * 2, stream->size());
769
770 // Read.
771 TestCompletionCallback read_callback2;
772 std::vector<char> buf2(kTestDataSize * 2);
773 auto wrapped_buffer2 = base::MakeRefCounted<WrappedIOBuffer>(buf2);
774 EXPECT_EQ(ERR_IO_PENDING,
775 stream->Read(
776 wrapped_buffer2.get(), buf2.size(), read_callback2.callback()));
777 EXPECT_EQ(static_cast<int>(buf2.size()), read_callback2.WaitForResult());
778 EXPECT_EQ(expected_data, buf2);
779 EXPECT_TRUE(stream->IsEOF());
780
781 // Make sure callbacks are not called for cancelled operations.
782 EXPECT_FALSE(init_callback1.have_result());
783 }
784
TEST_F(ElementsUploadDataStreamTest,InitDuringAsyncRead)785 TEST_F(ElementsUploadDataStreamTest, InitDuringAsyncRead) {
786 base::FilePath temp_file_path;
787 ASSERT_TRUE(
788 base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &temp_file_path));
789 ASSERT_TRUE(base::WriteFile(temp_file_path, kTestData));
790
791 // Prepare data.
792 element_readers_.push_back(std::make_unique<UploadBytesElementReader>(
793 base::byte_span_from_cstring(kTestData)));
794 element_readers_.push_back(std::make_unique<UploadFileElementReader>(
795 base::SingleThreadTaskRunner::GetCurrentDefault().get(), temp_file_path,
796 0, std::numeric_limits<uint64_t>::max(), base::Time()));
797 std::unique_ptr<UploadDataStream> stream(
798 std::make_unique<ElementsUploadDataStream>(std::move(element_readers_),
799 0));
800
801 std::vector<char> expected_data(kTestData, kTestData + kTestDataSize);
802 expected_data.insert(expected_data.end(), kTestData,
803 kTestData + kTestDataSize);
804
805 // Call Init().
806 TestCompletionCallback init_callback1;
807 ASSERT_THAT(stream->Init(init_callback1.callback(), NetLogWithSource()),
808 IsError(ERR_IO_PENDING));
809 EXPECT_THAT(init_callback1.WaitForResult(), IsOk());
810 EXPECT_FALSE(stream->IsEOF());
811 EXPECT_EQ(kTestDataSize * 2, stream->size());
812
813 // Start reading.
814 TestCompletionCallback read_callback1;
815 std::vector<char> buf(kTestDataSize * 2);
816 auto wrapped_buffer = base::MakeRefCounted<WrappedIOBuffer>(buf);
817 EXPECT_EQ(
818 ERR_IO_PENDING,
819 stream->Read(wrapped_buffer.get(), buf.size(),
820 read_callback1.callback()));
821
822 // Call Init to cancel the previous read.
823 TestCompletionCallback init_callback2;
824 EXPECT_THAT(stream->Init(init_callback2.callback(), NetLogWithSource()),
825 IsError(ERR_IO_PENDING));
826 EXPECT_THAT(init_callback2.WaitForResult(), IsOk());
827 EXPECT_FALSE(stream->IsEOF());
828 EXPECT_EQ(kTestDataSize * 2, stream->size());
829
830 // Read.
831 TestCompletionCallback read_callback2;
832 std::vector<char> buf2(kTestDataSize * 2);
833 auto wrapped_buffer2 = base::MakeRefCounted<WrappedIOBuffer>(buf2);
834 EXPECT_EQ(ERR_IO_PENDING,
835 stream->Read(
836 wrapped_buffer2.get(), buf2.size(), read_callback2.callback()));
837 EXPECT_EQ(static_cast<int>(buf2.size()), read_callback2.WaitForResult());
838 EXPECT_EQ(expected_data, buf2);
839 EXPECT_TRUE(stream->IsEOF());
840
841 // Make sure callbacks are not called for cancelled operations.
842 EXPECT_FALSE(read_callback1.have_result());
843 }
844
845 } // namespace net
846