1 // Copyright 2013 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.
5 #include "content/browser/fileapi/upload_file_system_file_element_reader.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "content/public/test/async_file_test_helper.h"
11 #include "content/public/test/test_file_system_context.h"
12 #include "net/base/io_buffer.h"
13 #include "net/base/test_completion_callback.h"
14 #include "storage/browser/fileapi/file_system_backend.h"
15 #include "storage/browser/fileapi/file_system_context.h"
16 #include "storage/browser/fileapi/file_system_operation_context.h"
17 #include "storage/browser/fileapi/file_system_url.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 using content::AsyncFileTestHelper
;
21 using storage::FileSystemContext
;
22 using storage::FileSystemType
;
23 using storage::FileSystemURL
;
29 const char kFileSystemURLOrigin
[] = "http://remote";
30 const storage::FileSystemType kFileSystemType
=
31 storage::kFileSystemTypeTemporary
;
35 class UploadFileSystemFileElementReaderTest
: public testing::Test
{
37 UploadFileSystemFileElementReaderTest() {}
39 void SetUp() override
{
40 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
42 file_system_context_
= CreateFileSystemContextForTesting(
43 NULL
, temp_dir_
.path());
45 file_system_context_
->OpenFileSystem(
46 GURL(kFileSystemURLOrigin
),
48 storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT
,
49 base::Bind(&UploadFileSystemFileElementReaderTest::OnOpenFileSystem
,
50 base::Unretained(this)));
51 base::RunLoop().RunUntilIdle();
52 ASSERT_TRUE(file_system_root_url_
.is_valid());
54 // Prepare a file on file system.
55 const char kTestData
[] = "abcdefghijklmnop0123456789";
56 file_data_
.assign(kTestData
, kTestData
+ arraysize(kTestData
) - 1);
57 const char kFilename
[] = "File.dat";
58 file_url_
= GetFileSystemURL(kFilename
);
59 WriteFileSystemFile(kFilename
, &file_data_
[0], file_data_
.size(),
60 &file_modification_time_
);
62 // Create and initialize a reader.
64 new UploadFileSystemFileElementReader(file_system_context_
.get(),
68 file_modification_time_
));
69 net::TestCompletionCallback callback
;
70 ASSERT_EQ(net::ERR_IO_PENDING
, reader_
->Init(callback
.callback()));
71 EXPECT_EQ(net::OK
, callback
.WaitForResult());
72 EXPECT_EQ(file_data_
.size(), reader_
->GetContentLength());
73 EXPECT_EQ(file_data_
.size(), reader_
->BytesRemaining());
74 EXPECT_FALSE(reader_
->IsInMemory());
77 void TearDown() override
{
79 base::RunLoop().RunUntilIdle();
83 GURL
GetFileSystemURL(const std::string
& filename
) {
84 return GURL(file_system_root_url_
.spec() + filename
);
87 void WriteFileSystemFile(const std::string
& filename
,
90 base::Time
* modification_time
) {
91 storage::FileSystemURL url
=
92 file_system_context_
->CreateCrackedFileSystemURL(
93 GURL(kFileSystemURLOrigin
),
95 base::FilePath().AppendASCII(filename
));
97 ASSERT_EQ(base::File::FILE_OK
,
98 AsyncFileTestHelper::CreateFileWithData(
99 file_system_context_
.get(), url
, buf
, buf_size
));
101 base::File::Info file_info
;
102 ASSERT_EQ(base::File::FILE_OK
,
103 AsyncFileTestHelper::GetMetadata(
104 file_system_context_
.get(), url
, &file_info
));
105 *modification_time
= file_info
.last_modified
;
108 void OnOpenFileSystem(const GURL
& root
,
109 const std::string
& name
,
110 base::File::Error result
) {
111 ASSERT_EQ(base::File::FILE_OK
, result
);
112 ASSERT_TRUE(root
.is_valid());
113 file_system_root_url_
= root
;
116 base::MessageLoopForIO message_loop_
;
117 base::ScopedTempDir temp_dir_
;
118 scoped_refptr
<FileSystemContext
> file_system_context_
;
119 GURL file_system_root_url_
;
120 std::vector
<char> file_data_
;
122 base::Time file_modification_time_
;
123 scoped_ptr
<UploadFileSystemFileElementReader
> reader_
;
126 TEST_F(UploadFileSystemFileElementReaderTest
, ReadAll
) {
127 scoped_refptr
<net::IOBufferWithSize
> buf
=
128 new net::IOBufferWithSize(file_data_
.size());
129 net::TestCompletionCallback read_callback
;
130 ASSERT_EQ(net::ERR_IO_PENDING
,
131 reader_
->Read(buf
.get(), buf
->size(), read_callback
.callback()));
132 EXPECT_EQ(buf
->size(), read_callback
.WaitForResult());
133 EXPECT_EQ(0U, reader_
->BytesRemaining());
134 EXPECT_TRUE(std::equal(file_data_
.begin(), file_data_
.end(), buf
->data()));
135 // Try to read again.
136 EXPECT_EQ(0, reader_
->Read(buf
.get(), buf
->size(), read_callback
.callback()));
139 TEST_F(UploadFileSystemFileElementReaderTest
, ReadPartially
) {
140 const size_t kHalfSize
= file_data_
.size() / 2;
141 ASSERT_EQ(file_data_
.size(), kHalfSize
* 2);
143 scoped_refptr
<net::IOBufferWithSize
> buf
=
144 new net::IOBufferWithSize(kHalfSize
);
146 net::TestCompletionCallback read_callback1
;
147 ASSERT_EQ(net::ERR_IO_PENDING
,
148 reader_
->Read(buf
.get(), buf
->size(), read_callback1
.callback()));
149 EXPECT_EQ(buf
->size(), read_callback1
.WaitForResult());
150 EXPECT_EQ(file_data_
.size() - buf
->size(), reader_
->BytesRemaining());
151 EXPECT_TRUE(std::equal(file_data_
.begin(), file_data_
.begin() + kHalfSize
,
154 net::TestCompletionCallback read_callback2
;
155 EXPECT_EQ(net::ERR_IO_PENDING
,
156 reader_
->Read(buf
.get(), buf
->size(), read_callback2
.callback()));
157 EXPECT_EQ(buf
->size(), read_callback2
.WaitForResult());
158 EXPECT_EQ(0U, reader_
->BytesRemaining());
159 EXPECT_TRUE(std::equal(file_data_
.begin() + kHalfSize
, file_data_
.end(),
163 TEST_F(UploadFileSystemFileElementReaderTest
, ReadTooMuch
) {
164 const size_t kTooLargeSize
= file_data_
.size() * 2;
165 scoped_refptr
<net::IOBufferWithSize
> buf
=
166 new net::IOBufferWithSize(kTooLargeSize
);
167 net::TestCompletionCallback read_callback
;
168 ASSERT_EQ(net::ERR_IO_PENDING
,
169 reader_
->Read(buf
.get(), buf
->size(), read_callback
.callback()));
170 EXPECT_EQ(static_cast<int>(file_data_
.size()), read_callback
.WaitForResult());
171 EXPECT_EQ(0U, reader_
->BytesRemaining());
172 EXPECT_TRUE(std::equal(file_data_
.begin(), file_data_
.end(), buf
->data()));
175 TEST_F(UploadFileSystemFileElementReaderTest
, MultipleInit
) {
176 scoped_refptr
<net::IOBufferWithSize
> buf
=
177 new net::IOBufferWithSize(file_data_
.size());
180 net::TestCompletionCallback read_callback1
;
181 ASSERT_EQ(net::ERR_IO_PENDING
,
182 reader_
->Read(buf
.get(), buf
->size(), read_callback1
.callback()));
183 EXPECT_EQ(buf
->size(), read_callback1
.WaitForResult());
184 EXPECT_EQ(0U, reader_
->BytesRemaining());
185 EXPECT_TRUE(std::equal(file_data_
.begin(), file_data_
.end(), buf
->data()));
187 // Call Init() again to reset the state.
188 net::TestCompletionCallback init_callback
;
189 ASSERT_EQ(net::ERR_IO_PENDING
, reader_
->Init(init_callback
.callback()));
190 EXPECT_EQ(net::OK
, init_callback
.WaitForResult());
191 EXPECT_EQ(file_data_
.size(), reader_
->GetContentLength());
192 EXPECT_EQ(file_data_
.size(), reader_
->BytesRemaining());
195 net::TestCompletionCallback read_callback2
;
196 ASSERT_EQ(net::ERR_IO_PENDING
,
197 reader_
->Read(buf
.get(), buf
->size(), read_callback2
.callback()));
198 EXPECT_EQ(buf
->size(), read_callback2
.WaitForResult());
199 EXPECT_EQ(0U, reader_
->BytesRemaining());
200 EXPECT_TRUE(std::equal(file_data_
.begin(), file_data_
.end(), buf
->data()));
203 TEST_F(UploadFileSystemFileElementReaderTest
, InitDuringAsyncOperation
) {
204 scoped_refptr
<net::IOBufferWithSize
> buf
=
205 new net::IOBufferWithSize(file_data_
.size());
207 // Start reading all.
208 net::TestCompletionCallback read_callback1
;
209 EXPECT_EQ(net::ERR_IO_PENDING
,
210 reader_
->Read(buf
.get(), buf
->size(), read_callback1
.callback()));
212 // Call Init to cancel the previous read.
213 net::TestCompletionCallback init_callback1
;
214 EXPECT_EQ(net::ERR_IO_PENDING
, reader_
->Init(init_callback1
.callback()));
216 // Call Init again to cancel the previous init.
217 net::TestCompletionCallback init_callback2
;
218 EXPECT_EQ(net::ERR_IO_PENDING
, reader_
->Init(init_callback2
.callback()));
219 EXPECT_EQ(net::OK
, init_callback2
.WaitForResult());
220 EXPECT_EQ(file_data_
.size(), reader_
->GetContentLength());
221 EXPECT_EQ(file_data_
.size(), reader_
->BytesRemaining());
224 scoped_refptr
<net::IOBufferWithSize
> buf2
=
225 new net::IOBufferWithSize(file_data_
.size() / 2);
226 net::TestCompletionCallback read_callback2
;
227 EXPECT_EQ(net::ERR_IO_PENDING
,
228 reader_
->Read(buf2
.get(), buf2
->size(), read_callback2
.callback()));
229 EXPECT_EQ(buf2
->size(), read_callback2
.WaitForResult());
230 EXPECT_EQ(file_data_
.size() - buf2
->size(), reader_
->BytesRemaining());
231 EXPECT_TRUE(std::equal(file_data_
.begin(), file_data_
.begin() + buf2
->size(),
234 // Make sure callbacks are not called for cancelled operations.
235 EXPECT_FALSE(read_callback1
.have_result());
236 EXPECT_FALSE(init_callback1
.have_result());
239 TEST_F(UploadFileSystemFileElementReaderTest
, Range
) {
240 const int kOffset
= 2;
241 const int kLength
= file_data_
.size() - kOffset
* 3;
242 reader_
.reset(new UploadFileSystemFileElementReader(
243 file_system_context_
.get(), file_url_
, kOffset
, kLength
, base::Time()));
244 net::TestCompletionCallback init_callback
;
245 ASSERT_EQ(net::ERR_IO_PENDING
, reader_
->Init(init_callback
.callback()));
246 EXPECT_EQ(net::OK
, init_callback
.WaitForResult());
247 EXPECT_EQ(static_cast<uint64
>(kLength
), reader_
->GetContentLength());
248 EXPECT_EQ(static_cast<uint64
>(kLength
), reader_
->BytesRemaining());
249 scoped_refptr
<net::IOBufferWithSize
> buf
= new net::IOBufferWithSize(kLength
);
250 net::TestCompletionCallback read_callback
;
251 ASSERT_EQ(net::ERR_IO_PENDING
,
252 reader_
->Read(buf
.get(), buf
->size(), read_callback
.callback()));
253 EXPECT_EQ(kLength
, read_callback
.WaitForResult());
254 EXPECT_TRUE(std::equal(file_data_
.begin() + kOffset
,
255 file_data_
.begin() + kOffset
+ kLength
,
259 TEST_F(UploadFileSystemFileElementReaderTest
, FileChanged
) {
260 // Expect one second before the actual modification time to simulate change.
261 const base::Time expected_modification_time
=
262 file_modification_time_
- base::TimeDelta::FromSeconds(1);
264 new UploadFileSystemFileElementReader(file_system_context_
.get(),
268 expected_modification_time
));
269 net::TestCompletionCallback init_callback
;
270 ASSERT_EQ(net::ERR_IO_PENDING
, reader_
->Init(init_callback
.callback()));
271 EXPECT_EQ(net::ERR_UPLOAD_FILE_CHANGED
, init_callback
.WaitForResult());
274 TEST_F(UploadFileSystemFileElementReaderTest
, WrongURL
) {
275 const GURL wrong_url
= GetFileSystemURL("wrong_file_name.dat");
276 reader_
.reset(new UploadFileSystemFileElementReader(
277 file_system_context_
.get(), wrong_url
, 0, kuint64max
, base::Time()));
278 net::TestCompletionCallback init_callback
;
279 ASSERT_EQ(net::ERR_IO_PENDING
, reader_
->Init(init_callback
.callback()));
280 EXPECT_EQ(net::ERR_FILE_NOT_FOUND
, init_callback
.WaitForResult());
283 } // namespace content