1 // Copyright (c) 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 "webkit/fileapi/upload_file_system_file_element_reader.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/message_loop.h"
9 #include "net/base/io_buffer.h"
10 #include "net/base/test_completion_callback.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "webkit/browser/fileapi/file_system_file_util.h"
13 #include "webkit/browser/fileapi/file_system_mount_point_provider.h"
14 #include "webkit/browser/fileapi/mock_file_system_context.h"
15 #include "webkit/fileapi/file_system_context.h"
16 #include "webkit/fileapi/file_system_operation_context.h"
17 #include "webkit/fileapi/file_system_url.h"
23 const char kFileSystemURLOrigin
[] = "http://remote";
24 const fileapi::FileSystemType kFileSystemType
=
25 fileapi::kFileSystemTypeTemporary
;
29 class UploadFileSystemFileElementReaderTest
: public testing::Test
{
31 UploadFileSystemFileElementReaderTest()
32 : message_loop_(base::MessageLoop::TYPE_IO
) {}
34 virtual void SetUp() OVERRIDE
{
35 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
37 file_system_context_
= fileapi::CreateFileSystemContextForTesting(
38 NULL
, temp_dir_
.path());
40 file_system_context_
->OpenFileSystem(
41 GURL(kFileSystemURLOrigin
),
44 base::Bind(&UploadFileSystemFileElementReaderTest::OnValidateFileSystem
,
45 base::Unretained(this)));
46 base::MessageLoop::current()->RunUntilIdle();
47 ASSERT_TRUE(file_system_root_url_
.is_valid());
49 // Prepare a file on file system.
50 const char kTestData
[] = "abcdefghijklmnop0123456789";
51 file_data_
.assign(kTestData
, kTestData
+ arraysize(kTestData
) - 1);
52 const char kFilename
[] = "File.dat";
53 file_url_
= GetFileSystemURL(kFilename
);
54 WriteFileSystemFile(kFilename
, &file_data_
[0], file_data_
.size(),
55 &file_modification_time_
);
57 // Create and initialize a reader.
58 reader_
.reset(new UploadFileSystemFileElementReader(
59 file_system_context_
, file_url_
, 0, kuint64max
,
60 file_modification_time_
));
61 net::TestCompletionCallback callback
;
62 ASSERT_EQ(net::ERR_IO_PENDING
, reader_
->Init(callback
.callback()));
63 EXPECT_EQ(net::OK
, callback
.WaitForResult());
64 EXPECT_EQ(file_data_
.size(), reader_
->GetContentLength());
65 EXPECT_EQ(file_data_
.size(), reader_
->BytesRemaining());
66 EXPECT_FALSE(reader_
->IsInMemory());
70 GURL
GetFileSystemURL(const std::string
& filename
) {
71 return GURL(file_system_root_url_
.spec() + filename
);
74 void WriteFileSystemFile(const std::string
& filename
,
77 base::Time
* modification_time
) {
78 fileapi::FileSystemURL url
=
79 file_system_context_
->CreateCrackedFileSystemURL(
80 GURL(kFileSystemURLOrigin
),
82 base::FilePath().AppendASCII(filename
));
84 fileapi::FileSystemFileUtil
* file_util
=
85 file_system_context_
->GetFileUtil(kFileSystemType
);
87 fileapi::FileSystemOperationContext
context(file_system_context_
);
88 context
.set_allowed_bytes_growth(1024);
90 base::PlatformFile handle
= base::kInvalidPlatformFileValue
;
92 ASSERT_EQ(base::PLATFORM_FILE_OK
, file_util
->CreateOrOpen(
95 base::PLATFORM_FILE_CREATE
| base::PLATFORM_FILE_WRITE
,
99 ASSERT_NE(base::kInvalidPlatformFileValue
, handle
);
101 base::WritePlatformFile(handle
, 0 /* offset */, buf
, buf_size
));
102 base::ClosePlatformFile(handle
);
104 base::PlatformFileInfo file_info
;
105 base::FilePath platform_path
;
106 ASSERT_EQ(base::PLATFORM_FILE_OK
,
107 file_util
->GetFileInfo(&context
, url
, &file_info
,
109 *modification_time
= file_info
.last_modified
;
112 void OnValidateFileSystem(base::PlatformFileError result
,
113 const std::string
& name
,
115 ASSERT_EQ(base::PLATFORM_FILE_OK
, result
);
116 ASSERT_TRUE(root
.is_valid());
117 file_system_root_url_
= root
;
120 base::MessageLoop message_loop_
;
121 base::ScopedTempDir temp_dir_
;
122 scoped_refptr
<FileSystemContext
> file_system_context_
;
123 GURL file_system_root_url_
;
124 std::vector
<char> file_data_
;
126 base::Time file_modification_time_
;
127 scoped_ptr
<UploadFileSystemFileElementReader
> reader_
;
130 TEST_F(UploadFileSystemFileElementReaderTest
, ReadAll
) {
131 scoped_refptr
<net::IOBufferWithSize
> buf
=
132 new net::IOBufferWithSize(file_data_
.size());
133 net::TestCompletionCallback read_callback
;
134 ASSERT_EQ(net::ERR_IO_PENDING
, reader_
->Read(buf
, buf
->size(),
135 read_callback
.callback()));
136 EXPECT_EQ(buf
->size(), read_callback
.WaitForResult());
137 EXPECT_EQ(0U, reader_
->BytesRemaining());
138 EXPECT_TRUE(std::equal(file_data_
.begin(), file_data_
.end(), buf
->data()));
139 // Try to read again.
140 EXPECT_EQ(0, reader_
->Read(buf
, buf
->size(), read_callback
.callback()));
143 TEST_F(UploadFileSystemFileElementReaderTest
, ReadPartially
) {
144 const size_t kHalfSize
= file_data_
.size() / 2;
145 ASSERT_EQ(file_data_
.size(), kHalfSize
* 2);
147 scoped_refptr
<net::IOBufferWithSize
> buf
=
148 new net::IOBufferWithSize(kHalfSize
);
150 net::TestCompletionCallback read_callback1
;
151 ASSERT_EQ(net::ERR_IO_PENDING
, reader_
->Read(buf
, buf
->size(),
152 read_callback1
.callback()));
153 EXPECT_EQ(buf
->size(), read_callback1
.WaitForResult());
154 EXPECT_EQ(file_data_
.size() - buf
->size(), reader_
->BytesRemaining());
155 EXPECT_TRUE(std::equal(file_data_
.begin(), file_data_
.begin() + kHalfSize
,
158 net::TestCompletionCallback read_callback2
;
159 EXPECT_EQ(net::ERR_IO_PENDING
, reader_
->Read(buf
, buf
->size(),
160 read_callback2
.callback()));
161 EXPECT_EQ(buf
->size(), read_callback2
.WaitForResult());
162 EXPECT_EQ(0U, reader_
->BytesRemaining());
163 EXPECT_TRUE(std::equal(file_data_
.begin() + kHalfSize
, file_data_
.end(),
167 TEST_F(UploadFileSystemFileElementReaderTest
, ReadTooMuch
) {
168 const size_t kTooLargeSize
= file_data_
.size() * 2;
169 scoped_refptr
<net::IOBufferWithSize
> buf
=
170 new net::IOBufferWithSize(kTooLargeSize
);
171 net::TestCompletionCallback read_callback
;
172 ASSERT_EQ(net::ERR_IO_PENDING
, reader_
->Read(buf
, buf
->size(),
173 read_callback
.callback()));
174 EXPECT_EQ(static_cast<int>(file_data_
.size()), read_callback
.WaitForResult());
175 EXPECT_EQ(0U, reader_
->BytesRemaining());
176 EXPECT_TRUE(std::equal(file_data_
.begin(), file_data_
.end(), buf
->data()));
179 TEST_F(UploadFileSystemFileElementReaderTest
, MultipleInit
) {
180 scoped_refptr
<net::IOBufferWithSize
> buf
=
181 new net::IOBufferWithSize(file_data_
.size());
184 net::TestCompletionCallback read_callback1
;
185 ASSERT_EQ(net::ERR_IO_PENDING
, reader_
->Read(buf
, buf
->size(),
186 read_callback1
.callback()));
187 EXPECT_EQ(buf
->size(), read_callback1
.WaitForResult());
188 EXPECT_EQ(0U, reader_
->BytesRemaining());
189 EXPECT_TRUE(std::equal(file_data_
.begin(), file_data_
.end(), buf
->data()));
191 // Call Init() again to reset the state.
192 net::TestCompletionCallback init_callback
;
193 ASSERT_EQ(net::ERR_IO_PENDING
, reader_
->Init(init_callback
.callback()));
194 EXPECT_EQ(net::OK
, init_callback
.WaitForResult());
195 EXPECT_EQ(file_data_
.size(), reader_
->GetContentLength());
196 EXPECT_EQ(file_data_
.size(), reader_
->BytesRemaining());
199 net::TestCompletionCallback read_callback2
;
200 ASSERT_EQ(net::ERR_IO_PENDING
, reader_
->Read(buf
, buf
->size(),
201 read_callback2
.callback()));
202 EXPECT_EQ(buf
->size(), read_callback2
.WaitForResult());
203 EXPECT_EQ(0U, reader_
->BytesRemaining());
204 EXPECT_TRUE(std::equal(file_data_
.begin(), file_data_
.end(), buf
->data()));
207 TEST_F(UploadFileSystemFileElementReaderTest
, InitDuringAsyncOperation
) {
208 scoped_refptr
<net::IOBufferWithSize
> buf
=
209 new net::IOBufferWithSize(file_data_
.size());
211 // Start reading all.
212 net::TestCompletionCallback read_callback1
;
213 EXPECT_EQ(net::ERR_IO_PENDING
, reader_
->Read(buf
, buf
->size(),
214 read_callback1
.callback()));
216 // Call Init to cancel the previous read.
217 net::TestCompletionCallback init_callback1
;
218 EXPECT_EQ(net::ERR_IO_PENDING
, reader_
->Init(init_callback1
.callback()));
220 // Call Init again to cancel the previous init.
221 net::TestCompletionCallback init_callback2
;
222 EXPECT_EQ(net::ERR_IO_PENDING
, reader_
->Init(init_callback2
.callback()));
223 EXPECT_EQ(net::OK
, init_callback2
.WaitForResult());
224 EXPECT_EQ(file_data_
.size(), reader_
->GetContentLength());
225 EXPECT_EQ(file_data_
.size(), reader_
->BytesRemaining());
228 scoped_refptr
<net::IOBufferWithSize
> buf2
=
229 new net::IOBufferWithSize(file_data_
.size() / 2);
230 net::TestCompletionCallback read_callback2
;
231 EXPECT_EQ(net::ERR_IO_PENDING
, reader_
->Read(buf2
, buf2
->size(),
232 read_callback2
.callback()));
233 EXPECT_EQ(buf2
->size(), read_callback2
.WaitForResult());
234 EXPECT_EQ(file_data_
.size() - buf2
->size(), reader_
->BytesRemaining());
235 EXPECT_TRUE(std::equal(file_data_
.begin(), file_data_
.begin() + buf2
->size(),
238 // Make sure callbacks are not called for cancelled operations.
239 EXPECT_FALSE(read_callback1
.have_result());
240 EXPECT_FALSE(init_callback1
.have_result());
243 TEST_F(UploadFileSystemFileElementReaderTest
, Range
) {
244 const int kOffset
= 2;
245 const int kLength
= file_data_
.size() - kOffset
* 3;
246 reader_
.reset(new UploadFileSystemFileElementReader(
247 file_system_context_
, file_url_
, kOffset
, kLength
, base::Time()));
248 net::TestCompletionCallback init_callback
;
249 ASSERT_EQ(net::ERR_IO_PENDING
, reader_
->Init(init_callback
.callback()));
250 EXPECT_EQ(net::OK
, init_callback
.WaitForResult());
251 EXPECT_EQ(static_cast<uint64
>(kLength
), reader_
->GetContentLength());
252 EXPECT_EQ(static_cast<uint64
>(kLength
), reader_
->BytesRemaining());
253 scoped_refptr
<net::IOBufferWithSize
> buf
= new net::IOBufferWithSize(kLength
);
254 net::TestCompletionCallback read_callback
;
255 ASSERT_EQ(net::ERR_IO_PENDING
, reader_
->Read(buf
, buf
->size(),
256 read_callback
.callback()));
257 EXPECT_EQ(kLength
, read_callback
.WaitForResult());
258 EXPECT_TRUE(std::equal(file_data_
.begin() + kOffset
,
259 file_data_
.begin() + kOffset
+ kLength
,
263 TEST_F(UploadFileSystemFileElementReaderTest
, FileChanged
) {
264 // Expect one second before the actual modification time to simulate change.
265 const base::Time expected_modification_time
=
266 file_modification_time_
- base::TimeDelta::FromSeconds(1);
267 reader_
.reset(new UploadFileSystemFileElementReader(
268 file_system_context_
, file_url_
, 0, kuint64max
,
269 expected_modification_time
));
270 net::TestCompletionCallback init_callback
;
271 ASSERT_EQ(net::ERR_IO_PENDING
, reader_
->Init(init_callback
.callback()));
272 EXPECT_EQ(net::ERR_UPLOAD_FILE_CHANGED
, init_callback
.WaitForResult());
275 TEST_F(UploadFileSystemFileElementReaderTest
, WrongURL
) {
276 const GURL wrong_url
= GetFileSystemURL("wrong_file_name.dat");
277 reader_
.reset(new UploadFileSystemFileElementReader(
278 file_system_context_
, wrong_url
, 0, kuint64max
, base::Time()));
279 net::TestCompletionCallback init_callback
;
280 ASSERT_EQ(net::ERR_IO_PENDING
, reader_
->Init(init_callback
.callback()));
281 EXPECT_EQ(net::ERR_FILE_NOT_FOUND
, init_callback
.WaitForResult());
284 } // namespace fileapi