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 <vector>
12
13 #include "base/files/file_path.h"
14 #include "base/files/file_util.h"
15 #include "base/files/scoped_temp_dir.h"
16 #include "base/functional/bind.h"
17 #include "base/location.h"
18 #include "base/run_loop.h"
19 #include "base/strings/string_piece.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 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(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 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(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 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(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 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(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 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(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 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(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 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(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 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(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 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(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 scoped_refptr<IOBuffer> wrapped_buffer =
705 base::MakeRefCounted<WrappedIOBuffer>(&buf[0]);
706 EXPECT_EQ(
707 ERR_IO_PENDING,
708 stream->Read(wrapped_buffer.get(), buf.size(),
709 read_callback1.callback()));
710 EXPECT_EQ(static_cast<int>(buf.size()), read_callback1.WaitForResult());
711 EXPECT_EQ(buf.size(), stream->position());
712
713 // Call Init to reset the state.
714 TestCompletionCallback init_callback2;
715 ASSERT_THAT(stream->Init(init_callback2.callback(), NetLogWithSource()),
716 IsError(ERR_IO_PENDING));
717 EXPECT_THAT(init_callback2.WaitForResult(), IsOk());
718 EXPECT_FALSE(stream->IsEOF());
719 EXPECT_EQ(kTestDataSize * 2, stream->size());
720
721 // Read.
722 TestCompletionCallback read_callback2;
723 std::vector<char> buf2(kTestDataSize * 2);
724 scoped_refptr<IOBuffer> wrapped_buffer2 =
725 base::MakeRefCounted<WrappedIOBuffer>(&buf2[0]);
726 EXPECT_EQ(ERR_IO_PENDING,
727 stream->Read(
728 wrapped_buffer2.get(), buf2.size(), read_callback2.callback()));
729 EXPECT_EQ(static_cast<int>(buf2.size()), read_callback2.WaitForResult());
730 EXPECT_EQ(expected_data, buf2);
731 }
732
TEST_F(ElementsUploadDataStreamTest,InitDuringAsyncInit)733 TEST_F(ElementsUploadDataStreamTest, InitDuringAsyncInit) {
734 base::FilePath temp_file_path;
735 ASSERT_TRUE(
736 base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &temp_file_path));
737 ASSERT_TRUE(base::WriteFile(temp_file_path, kTestData));
738
739 // Prepare data.
740 element_readers_.push_back(
741 std::make_unique<UploadBytesElementReader>(kTestData, kTestDataSize));
742 element_readers_.push_back(std::make_unique<UploadFileElementReader>(
743 base::SingleThreadTaskRunner::GetCurrentDefault().get(), temp_file_path,
744 0, std::numeric_limits<uint64_t>::max(), base::Time()));
745 std::unique_ptr<UploadDataStream> stream(
746 std::make_unique<ElementsUploadDataStream>(std::move(element_readers_),
747 0));
748
749 std::vector<char> expected_data(kTestData, kTestData + kTestDataSize);
750 expected_data.insert(expected_data.end(), kTestData,
751 kTestData + kTestDataSize);
752
753 // Start Init.
754 TestCompletionCallback init_callback1;
755 EXPECT_THAT(stream->Init(init_callback1.callback(), NetLogWithSource()),
756 IsError(ERR_IO_PENDING));
757
758 // Call Init again to cancel the previous init.
759 TestCompletionCallback init_callback2;
760 EXPECT_THAT(stream->Init(init_callback2.callback(), NetLogWithSource()),
761 IsError(ERR_IO_PENDING));
762 EXPECT_THAT(init_callback2.WaitForResult(), IsOk());
763 EXPECT_FALSE(stream->IsEOF());
764 EXPECT_EQ(kTestDataSize * 2, stream->size());
765
766 // Read.
767 TestCompletionCallback read_callback2;
768 std::vector<char> buf2(kTestDataSize * 2);
769 scoped_refptr<IOBuffer> wrapped_buffer2 =
770 base::MakeRefCounted<WrappedIOBuffer>(&buf2[0]);
771 EXPECT_EQ(ERR_IO_PENDING,
772 stream->Read(
773 wrapped_buffer2.get(), buf2.size(), read_callback2.callback()));
774 EXPECT_EQ(static_cast<int>(buf2.size()), read_callback2.WaitForResult());
775 EXPECT_EQ(expected_data, buf2);
776 EXPECT_TRUE(stream->IsEOF());
777
778 // Make sure callbacks are not called for cancelled operations.
779 EXPECT_FALSE(init_callback1.have_result());
780 }
781
TEST_F(ElementsUploadDataStreamTest,InitDuringAsyncRead)782 TEST_F(ElementsUploadDataStreamTest, InitDuringAsyncRead) {
783 base::FilePath temp_file_path;
784 ASSERT_TRUE(
785 base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &temp_file_path));
786 ASSERT_TRUE(base::WriteFile(temp_file_path, kTestData));
787
788 // Prepare data.
789 element_readers_.push_back(
790 std::make_unique<UploadBytesElementReader>(kTestData, kTestDataSize));
791 element_readers_.push_back(std::make_unique<UploadFileElementReader>(
792 base::SingleThreadTaskRunner::GetCurrentDefault().get(), temp_file_path,
793 0, std::numeric_limits<uint64_t>::max(), base::Time()));
794 std::unique_ptr<UploadDataStream> stream(
795 std::make_unique<ElementsUploadDataStream>(std::move(element_readers_),
796 0));
797
798 std::vector<char> expected_data(kTestData, kTestData + kTestDataSize);
799 expected_data.insert(expected_data.end(), kTestData,
800 kTestData + kTestDataSize);
801
802 // Call Init().
803 TestCompletionCallback init_callback1;
804 ASSERT_THAT(stream->Init(init_callback1.callback(), NetLogWithSource()),
805 IsError(ERR_IO_PENDING));
806 EXPECT_THAT(init_callback1.WaitForResult(), IsOk());
807 EXPECT_FALSE(stream->IsEOF());
808 EXPECT_EQ(kTestDataSize * 2, stream->size());
809
810 // Start reading.
811 TestCompletionCallback read_callback1;
812 std::vector<char> buf(kTestDataSize * 2);
813 scoped_refptr<IOBuffer> wrapped_buffer =
814 base::MakeRefCounted<WrappedIOBuffer>(&buf[0]);
815 EXPECT_EQ(
816 ERR_IO_PENDING,
817 stream->Read(wrapped_buffer.get(), buf.size(),
818 read_callback1.callback()));
819
820 // Call Init to cancel the previous read.
821 TestCompletionCallback init_callback2;
822 EXPECT_THAT(stream->Init(init_callback2.callback(), NetLogWithSource()),
823 IsError(ERR_IO_PENDING));
824 EXPECT_THAT(init_callback2.WaitForResult(), IsOk());
825 EXPECT_FALSE(stream->IsEOF());
826 EXPECT_EQ(kTestDataSize * 2, stream->size());
827
828 // Read.
829 TestCompletionCallback read_callback2;
830 std::vector<char> buf2(kTestDataSize * 2);
831 scoped_refptr<IOBuffer> wrapped_buffer2 =
832 base::MakeRefCounted<WrappedIOBuffer>(&buf2[0]);
833 EXPECT_EQ(ERR_IO_PENDING,
834 stream->Read(
835 wrapped_buffer2.get(), buf2.size(), read_callback2.callback()));
836 EXPECT_EQ(static_cast<int>(buf2.size()), read_callback2.WaitForResult());
837 EXPECT_EQ(expected_data, buf2);
838 EXPECT_TRUE(stream->IsEOF());
839
840 // Make sure callbacks are not called for cancelled operations.
841 EXPECT_FALSE(read_callback1.have_result());
842 }
843
844 } // namespace net
845