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 "webkit/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 "testing/gtest/include/gtest/gtest.h"
15 #include "webkit/browser/fileapi/file_system_backend.h"
16 #include "webkit/browser/fileapi/file_system_context.h"
17 #include "webkit/browser/fileapi/file_system_operation_context.h"
18 #include "webkit/browser/fileapi/file_system_url.h"
20 using content::AsyncFileTestHelper;
21 using fileapi::FileSystemContext;
22 using fileapi::FileSystemType;
23 using fileapi::FileSystemURL;
24 using fileapi::UploadFileSystemFileElementReader;
30 const char kFileSystemURLOrigin[] = "http://remote";
31 const fileapi::FileSystemType kFileSystemType =
32 fileapi::kFileSystemTypeTemporary;
36 class UploadFileSystemFileElementReaderTest : public testing::Test {
38 UploadFileSystemFileElementReaderTest() {}
40 virtual void SetUp() OVERRIDE {
41 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
43 file_system_context_ = CreateFileSystemContextForTesting(
44 NULL, temp_dir_.path());
46 file_system_context_->OpenFileSystem(
47 GURL(kFileSystemURLOrigin),
49 fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
50 base::Bind(&UploadFileSystemFileElementReaderTest::OnOpenFileSystem,
51 base::Unretained(this)));
52 base::RunLoop().RunUntilIdle();
53 ASSERT_TRUE(file_system_root_url_.is_valid());
55 // Prepare a file on file system.
56 const char kTestData[] = "abcdefghijklmnop0123456789";
57 file_data_.assign(kTestData, kTestData + arraysize(kTestData) - 1);
58 const char kFilename[] = "File.dat";
59 file_url_ = GetFileSystemURL(kFilename);
60 WriteFileSystemFile(kFilename, &file_data_[0], file_data_.size(),
61 &file_modification_time_);
63 // Create and initialize a reader.
65 new UploadFileSystemFileElementReader(file_system_context_.get(),
69 file_modification_time_));
70 net::TestCompletionCallback callback;
71 ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(callback.callback()));
72 EXPECT_EQ(net::OK, callback.WaitForResult());
73 EXPECT_EQ(file_data_.size(), reader_->GetContentLength());
74 EXPECT_EQ(file_data_.size(), reader_->BytesRemaining());
75 EXPECT_FALSE(reader_->IsInMemory());
78 virtual void TearDown() OVERRIDE {
80 base::RunLoop().RunUntilIdle();
84 GURL GetFileSystemURL(const std::string& filename) {
85 return GURL(file_system_root_url_.spec() + filename);
88 void WriteFileSystemFile(const std::string& filename,
91 base::Time* modification_time) {
92 fileapi::FileSystemURL url =
93 file_system_context_->CreateCrackedFileSystemURL(
94 GURL(kFileSystemURLOrigin),
96 base::FilePath().AppendASCII(filename));
98 ASSERT_EQ(base::File::FILE_OK,
99 AsyncFileTestHelper::CreateFileWithData(
100 file_system_context_, url, buf, buf_size));
102 base::File::Info file_info;
103 ASSERT_EQ(base::File::FILE_OK,
104 AsyncFileTestHelper::GetMetadata(
105 file_system_context_, url, &file_info));
106 *modification_time = file_info.last_modified;
109 void OnOpenFileSystem(const GURL& root,
110 const std::string& name,
111 base::File::Error result) {
112 ASSERT_EQ(base::File::FILE_OK, result);
113 ASSERT_TRUE(root.is_valid());
114 file_system_root_url_ = root;
117 base::MessageLoopForIO message_loop_;
118 base::ScopedTempDir temp_dir_;
119 scoped_refptr<FileSystemContext> file_system_context_;
120 GURL file_system_root_url_;
121 std::vector<char> file_data_;
123 base::Time file_modification_time_;
124 scoped_ptr<UploadFileSystemFileElementReader> reader_;
127 TEST_F(UploadFileSystemFileElementReaderTest, ReadAll) {
128 scoped_refptr<net::IOBufferWithSize> buf =
129 new net::IOBufferWithSize(file_data_.size());
130 net::TestCompletionCallback read_callback;
131 ASSERT_EQ(net::ERR_IO_PENDING,
132 reader_->Read(buf.get(), buf->size(), read_callback.callback()));
133 EXPECT_EQ(buf->size(), read_callback.WaitForResult());
134 EXPECT_EQ(0U, reader_->BytesRemaining());
135 EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.end(), buf->data()));
136 // Try to read again.
137 EXPECT_EQ(0, reader_->Read(buf.get(), buf->size(), read_callback.callback()));
140 TEST_F(UploadFileSystemFileElementReaderTest, ReadPartially) {
141 const size_t kHalfSize = file_data_.size() / 2;
142 ASSERT_EQ(file_data_.size(), kHalfSize * 2);
144 scoped_refptr<net::IOBufferWithSize> buf =
145 new net::IOBufferWithSize(kHalfSize);
147 net::TestCompletionCallback read_callback1;
148 ASSERT_EQ(net::ERR_IO_PENDING,
149 reader_->Read(buf.get(), buf->size(), read_callback1.callback()));
150 EXPECT_EQ(buf->size(), read_callback1.WaitForResult());
151 EXPECT_EQ(file_data_.size() - buf->size(), reader_->BytesRemaining());
152 EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.begin() + kHalfSize,
155 net::TestCompletionCallback read_callback2;
156 EXPECT_EQ(net::ERR_IO_PENDING,
157 reader_->Read(buf.get(), buf->size(), read_callback2.callback()));
158 EXPECT_EQ(buf->size(), read_callback2.WaitForResult());
159 EXPECT_EQ(0U, reader_->BytesRemaining());
160 EXPECT_TRUE(std::equal(file_data_.begin() + kHalfSize, file_data_.end(),
164 TEST_F(UploadFileSystemFileElementReaderTest, ReadTooMuch) {
165 const size_t kTooLargeSize = file_data_.size() * 2;
166 scoped_refptr<net::IOBufferWithSize> buf =
167 new net::IOBufferWithSize(kTooLargeSize);
168 net::TestCompletionCallback read_callback;
169 ASSERT_EQ(net::ERR_IO_PENDING,
170 reader_->Read(buf.get(), buf->size(), read_callback.callback()));
171 EXPECT_EQ(static_cast<int>(file_data_.size()), read_callback.WaitForResult());
172 EXPECT_EQ(0U, reader_->BytesRemaining());
173 EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.end(), buf->data()));
176 TEST_F(UploadFileSystemFileElementReaderTest, MultipleInit) {
177 scoped_refptr<net::IOBufferWithSize> buf =
178 new net::IOBufferWithSize(file_data_.size());
181 net::TestCompletionCallback read_callback1;
182 ASSERT_EQ(net::ERR_IO_PENDING,
183 reader_->Read(buf.get(), buf->size(), read_callback1.callback()));
184 EXPECT_EQ(buf->size(), read_callback1.WaitForResult());
185 EXPECT_EQ(0U, reader_->BytesRemaining());
186 EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.end(), buf->data()));
188 // Call Init() again to reset the state.
189 net::TestCompletionCallback init_callback;
190 ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback.callback()));
191 EXPECT_EQ(net::OK, init_callback.WaitForResult());
192 EXPECT_EQ(file_data_.size(), reader_->GetContentLength());
193 EXPECT_EQ(file_data_.size(), reader_->BytesRemaining());
196 net::TestCompletionCallback read_callback2;
197 ASSERT_EQ(net::ERR_IO_PENDING,
198 reader_->Read(buf.get(), buf->size(), read_callback2.callback()));
199 EXPECT_EQ(buf->size(), read_callback2.WaitForResult());
200 EXPECT_EQ(0U, reader_->BytesRemaining());
201 EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.end(), buf->data()));
204 TEST_F(UploadFileSystemFileElementReaderTest, InitDuringAsyncOperation) {
205 scoped_refptr<net::IOBufferWithSize> buf =
206 new net::IOBufferWithSize(file_data_.size());
208 // Start reading all.
209 net::TestCompletionCallback read_callback1;
210 EXPECT_EQ(net::ERR_IO_PENDING,
211 reader_->Read(buf.get(), buf->size(), read_callback1.callback()));
213 // Call Init to cancel the previous read.
214 net::TestCompletionCallback init_callback1;
215 EXPECT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback1.callback()));
217 // Call Init again to cancel the previous init.
218 net::TestCompletionCallback init_callback2;
219 EXPECT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback2.callback()));
220 EXPECT_EQ(net::OK, init_callback2.WaitForResult());
221 EXPECT_EQ(file_data_.size(), reader_->GetContentLength());
222 EXPECT_EQ(file_data_.size(), reader_->BytesRemaining());
225 scoped_refptr<net::IOBufferWithSize> buf2 =
226 new net::IOBufferWithSize(file_data_.size() / 2);
227 net::TestCompletionCallback read_callback2;
228 EXPECT_EQ(net::ERR_IO_PENDING,
229 reader_->Read(buf2.get(), buf2->size(), read_callback2.callback()));
230 EXPECT_EQ(buf2->size(), read_callback2.WaitForResult());
231 EXPECT_EQ(file_data_.size() - buf2->size(), reader_->BytesRemaining());
232 EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.begin() + buf2->size(),
235 // Make sure callbacks are not called for cancelled operations.
236 EXPECT_FALSE(read_callback1.have_result());
237 EXPECT_FALSE(init_callback1.have_result());
240 TEST_F(UploadFileSystemFileElementReaderTest, Range) {
241 const int kOffset = 2;
242 const int kLength = file_data_.size() - kOffset * 3;
243 reader_.reset(new UploadFileSystemFileElementReader(
244 file_system_context_.get(), file_url_, kOffset, kLength, base::Time()));
245 net::TestCompletionCallback init_callback;
246 ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback.callback()));
247 EXPECT_EQ(net::OK, init_callback.WaitForResult());
248 EXPECT_EQ(static_cast<uint64>(kLength), reader_->GetContentLength());
249 EXPECT_EQ(static_cast<uint64>(kLength), reader_->BytesRemaining());
250 scoped_refptr<net::IOBufferWithSize> buf = new net::IOBufferWithSize(kLength);
251 net::TestCompletionCallback read_callback;
252 ASSERT_EQ(net::ERR_IO_PENDING,
253 reader_->Read(buf.get(), buf->size(), read_callback.callback()));
254 EXPECT_EQ(kLength, read_callback.WaitForResult());
255 EXPECT_TRUE(std::equal(file_data_.begin() + kOffset,
256 file_data_.begin() + kOffset + kLength,
260 TEST_F(UploadFileSystemFileElementReaderTest, FileChanged) {
261 // Expect one second before the actual modification time to simulate change.
262 const base::Time expected_modification_time =
263 file_modification_time_ - base::TimeDelta::FromSeconds(1);
265 new UploadFileSystemFileElementReader(file_system_context_.get(),
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_.get(), 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 content