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