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/file_system_file_stream_reader.h"
10 #include "base/files/scoped_temp_dir.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/run_loop.h"
13 #include "content/public/test/async_file_test_helper.h"
14 #include "content/public/test/test_file_system_context.h"
15 #include "net/base/io_buffer.h"
16 #include "net/base/net_errors.h"
17 #include "net/base/test_completion_callback.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "webkit/browser/fileapi/external_mount_points.h"
20 #include "webkit/browser/fileapi/file_system_context.h"
21 #include "webkit/browser/fileapi/file_system_file_util.h"
23 using content::AsyncFileTestHelper
;
24 using storage::FileSystemContext
;
25 using storage::FileSystemFileStreamReader
;
26 using storage::FileSystemType
;
27 using storage::FileSystemURL
;
33 const char kURLOrigin
[] = "http://remote/";
34 const char kTestFileName
[] = "test.dat";
35 const char kTestData
[] = "0123456789";
36 const int kTestDataSize
= arraysize(kTestData
) - 1;
38 void ReadFromReader(storage::FileSystemFileStreamReader
* reader
,
42 ASSERT_TRUE(reader
!= NULL
);
43 ASSERT_TRUE(result
!= NULL
);
45 net::TestCompletionCallback callback
;
46 size_t total_bytes_read
= 0;
47 while (total_bytes_read
< size
) {
48 scoped_refptr
<net::IOBufferWithSize
> buf(
49 new net::IOBufferWithSize(size
- total_bytes_read
));
50 int rv
= reader
->Read(buf
.get(), buf
->size(), callback
.callback());
51 if (rv
== net::ERR_IO_PENDING
)
52 rv
= callback
.WaitForResult();
57 total_bytes_read
+= rv
;
58 data
->append(buf
->data(), rv
);
62 void NeverCalled(int unused
) { ADD_FAILURE(); }
66 class FileSystemFileStreamReaderTest
: public testing::Test
{
68 FileSystemFileStreamReaderTest() {}
70 virtual void SetUp() OVERRIDE
{
71 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
73 file_system_context_
= CreateFileSystemContextForTesting(
74 NULL
, temp_dir_
.path());
76 file_system_context_
->OpenFileSystem(
78 storage::kFileSystemTypeTemporary
,
79 storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT
,
80 base::Bind(&OnOpenFileSystem
));
81 base::RunLoop().RunUntilIdle();
83 WriteFile(kTestFileName
, kTestData
, kTestDataSize
,
84 &test_file_modification_time_
);
87 virtual void TearDown() OVERRIDE
{
88 base::RunLoop().RunUntilIdle();
92 storage::FileSystemFileStreamReader
* CreateFileReader(
93 const std::string
& file_name
,
95 const base::Time
& expected_modification_time
) {
96 return new FileSystemFileStreamReader(file_system_context_
.get(),
97 GetFileSystemURL(file_name
),
99 expected_modification_time
);
102 base::Time
test_file_modification_time() const {
103 return test_file_modification_time_
;
106 void WriteFile(const std::string
& file_name
,
109 base::Time
* modification_time
) {
110 FileSystemURL url
= GetFileSystemURL(file_name
);
112 ASSERT_EQ(base::File::FILE_OK
,
113 content::AsyncFileTestHelper::CreateFileWithData(
114 file_system_context_
, url
, buf
, buf_size
));
116 base::File::Info file_info
;
117 ASSERT_EQ(base::File::FILE_OK
,
118 AsyncFileTestHelper::GetMetadata(
119 file_system_context_
, url
, &file_info
));
120 if (modification_time
)
121 *modification_time
= file_info
.last_modified
;
125 static void OnOpenFileSystem(const GURL
& root_url
,
126 const std::string
& name
,
127 base::File::Error result
) {
128 ASSERT_EQ(base::File::FILE_OK
, result
);
131 FileSystemURL
GetFileSystemURL(const std::string
& file_name
) {
132 return file_system_context_
->CreateCrackedFileSystemURL(
134 storage::kFileSystemTypeTemporary
,
135 base::FilePath().AppendASCII(file_name
));
138 base::MessageLoopForIO message_loop_
;
139 base::ScopedTempDir temp_dir_
;
140 scoped_refptr
<FileSystemContext
> file_system_context_
;
141 base::Time test_file_modification_time_
;
144 TEST_F(FileSystemFileStreamReaderTest
, NonExistent
) {
145 const char kFileName
[] = "nonexistent";
146 scoped_ptr
<FileSystemFileStreamReader
> reader(
147 CreateFileReader(kFileName
, 0, base::Time()));
150 ReadFromReader(reader
.get(), &data
, 10, &result
);
151 ASSERT_EQ(net::ERR_FILE_NOT_FOUND
, result
);
152 ASSERT_EQ(0U, data
.size());
155 TEST_F(FileSystemFileStreamReaderTest
, Empty
) {
156 const char kFileName
[] = "empty";
157 WriteFile(kFileName
, NULL
, 0, NULL
);
159 scoped_ptr
<FileSystemFileStreamReader
> reader(
160 CreateFileReader(kFileName
, 0, base::Time()));
163 ReadFromReader(reader
.get(), &data
, 10, &result
);
164 ASSERT_EQ(net::OK
, result
);
165 ASSERT_EQ(0U, data
.size());
167 net::TestInt64CompletionCallback callback
;
168 int64 length_result
= reader
->GetLength(callback
.callback());
169 if (length_result
== net::ERR_IO_PENDING
)
170 length_result
= callback
.WaitForResult();
171 ASSERT_EQ(0, length_result
);
174 TEST_F(FileSystemFileStreamReaderTest
, GetLengthNormal
) {
175 scoped_ptr
<FileSystemFileStreamReader
> reader(
176 CreateFileReader(kTestFileName
, 0, test_file_modification_time()));
177 net::TestInt64CompletionCallback callback
;
178 int64 result
= reader
->GetLength(callback
.callback());
179 if (result
== net::ERR_IO_PENDING
)
180 result
= callback
.WaitForResult();
181 ASSERT_EQ(kTestDataSize
, result
);
184 TEST_F(FileSystemFileStreamReaderTest
, GetLengthAfterModified
) {
185 // Pass a fake expected modifictaion time so that the expectation fails.
186 base::Time fake_expected_modification_time
=
187 test_file_modification_time() - base::TimeDelta::FromSeconds(10);
189 scoped_ptr
<FileSystemFileStreamReader
> reader(
190 CreateFileReader(kTestFileName
, 0, fake_expected_modification_time
));
191 net::TestInt64CompletionCallback callback
;
192 int64 result
= reader
->GetLength(callback
.callback());
193 if (result
== net::ERR_IO_PENDING
)
194 result
= callback
.WaitForResult();
195 ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED
, result
);
197 // With NULL expected modification time this should work.
198 reader
.reset(CreateFileReader(kTestFileName
, 0, base::Time()));
199 result
= reader
->GetLength(callback
.callback());
200 if (result
== net::ERR_IO_PENDING
)
201 result
= callback
.WaitForResult();
202 ASSERT_EQ(kTestDataSize
, result
);
205 TEST_F(FileSystemFileStreamReaderTest
, GetLengthWithOffset
) {
206 scoped_ptr
<FileSystemFileStreamReader
> reader(
207 CreateFileReader(kTestFileName
, 3, base::Time()));
208 net::TestInt64CompletionCallback callback
;
209 int64 result
= reader
->GetLength(callback
.callback());
210 if (result
== net::ERR_IO_PENDING
)
211 result
= callback
.WaitForResult();
212 // Initial offset does not affect the result of GetLength.
213 ASSERT_EQ(kTestDataSize
, result
);
216 TEST_F(FileSystemFileStreamReaderTest
, ReadNormal
) {
217 scoped_ptr
<FileSystemFileStreamReader
> reader(
218 CreateFileReader(kTestFileName
, 0, test_file_modification_time()));
221 ReadFromReader(reader
.get(), &data
, kTestDataSize
, &result
);
222 ASSERT_EQ(net::OK
, result
);
223 ASSERT_EQ(kTestData
, data
);
226 TEST_F(FileSystemFileStreamReaderTest
, ReadAfterModified
) {
227 // Pass a fake expected modifictaion time so that the expectation fails.
228 base::Time fake_expected_modification_time
=
229 test_file_modification_time() - base::TimeDelta::FromSeconds(10);
231 scoped_ptr
<FileSystemFileStreamReader
> reader(
232 CreateFileReader(kTestFileName
, 0, fake_expected_modification_time
));
235 ReadFromReader(reader
.get(), &data
, kTestDataSize
, &result
);
236 ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED
, result
);
237 ASSERT_EQ(0U, data
.size());
239 // With NULL expected modification time this should work.
241 reader
.reset(CreateFileReader(kTestFileName
, 0, base::Time()));
242 ReadFromReader(reader
.get(), &data
, kTestDataSize
, &result
);
243 ASSERT_EQ(net::OK
, result
);
244 ASSERT_EQ(kTestData
, data
);
247 TEST_F(FileSystemFileStreamReaderTest
, ReadWithOffset
) {
248 scoped_ptr
<FileSystemFileStreamReader
> reader(
249 CreateFileReader(kTestFileName
, 3, base::Time()));
252 ReadFromReader(reader
.get(), &data
, kTestDataSize
, &result
);
253 ASSERT_EQ(net::OK
, result
);
254 ASSERT_EQ(&kTestData
[3], data
);
257 TEST_F(FileSystemFileStreamReaderTest
, DeleteWithUnfinishedRead
) {
258 scoped_ptr
<FileSystemFileStreamReader
> reader(
259 CreateFileReader(kTestFileName
, 0, base::Time()));
261 net::TestCompletionCallback callback
;
262 scoped_refptr
<net::IOBufferWithSize
> buf(
263 new net::IOBufferWithSize(kTestDataSize
));
264 int rv
= reader
->Read(buf
.get(), buf
->size(), base::Bind(&NeverCalled
));
265 ASSERT_TRUE(rv
== net::ERR_IO_PENDING
|| rv
>= 0);
267 // Delete immediately.
268 // Should not crash; nor should NeverCalled be callback.
272 } // namespace content