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