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 "storage/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 "storage/browser/fileapi/external_mount_points.h"
19 #include "storage/browser/fileapi/file_system_context.h"
20 #include "storage/browser/fileapi/file_system_file_util.h"
21 #include "testing/gtest/include/gtest/gtest.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 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 void TearDown() override
{ base::RunLoop().RunUntilIdle(); }
90 storage::FileSystemFileStreamReader
* CreateFileReader(
91 const std::string
& file_name
,
93 const base::Time
& expected_modification_time
) {
94 return new FileSystemFileStreamReader(file_system_context_
.get(),
95 GetFileSystemURL(file_name
),
97 expected_modification_time
);
100 base::Time
test_file_modification_time() const {
101 return test_file_modification_time_
;
104 void WriteFile(const std::string
& file_name
,
107 base::Time
* modification_time
) {
108 FileSystemURL url
= GetFileSystemURL(file_name
);
110 ASSERT_EQ(base::File::FILE_OK
,
111 content::AsyncFileTestHelper::CreateFileWithData(
112 file_system_context_
.get(), url
, buf
, buf_size
));
114 base::File::Info file_info
;
115 ASSERT_EQ(base::File::FILE_OK
,
116 AsyncFileTestHelper::GetMetadata(
117 file_system_context_
.get(), url
, &file_info
));
118 if (modification_time
)
119 *modification_time
= file_info
.last_modified
;
123 static void OnOpenFileSystem(const GURL
& root_url
,
124 const std::string
& name
,
125 base::File::Error result
) {
126 ASSERT_EQ(base::File::FILE_OK
, result
);
129 FileSystemURL
GetFileSystemURL(const std::string
& file_name
) {
130 return file_system_context_
->CreateCrackedFileSystemURL(
132 storage::kFileSystemTypeTemporary
,
133 base::FilePath().AppendASCII(file_name
));
136 base::MessageLoopForIO message_loop_
;
137 base::ScopedTempDir temp_dir_
;
138 scoped_refptr
<FileSystemContext
> file_system_context_
;
139 base::Time test_file_modification_time_
;
142 TEST_F(FileSystemFileStreamReaderTest
, NonExistent
) {
143 const char kFileName
[] = "nonexistent";
144 scoped_ptr
<FileSystemFileStreamReader
> reader(
145 CreateFileReader(kFileName
, 0, base::Time()));
148 ReadFromReader(reader
.get(), &data
, 10, &result
);
149 ASSERT_EQ(net::ERR_FILE_NOT_FOUND
, result
);
150 ASSERT_EQ(0U, data
.size());
153 TEST_F(FileSystemFileStreamReaderTest
, Empty
) {
154 const char kFileName
[] = "empty";
155 WriteFile(kFileName
, NULL
, 0, NULL
);
157 scoped_ptr
<FileSystemFileStreamReader
> reader(
158 CreateFileReader(kFileName
, 0, base::Time()));
161 ReadFromReader(reader
.get(), &data
, 10, &result
);
162 ASSERT_EQ(net::OK
, result
);
163 ASSERT_EQ(0U, data
.size());
165 net::TestInt64CompletionCallback callback
;
166 int64 length_result
= reader
->GetLength(callback
.callback());
167 if (length_result
== net::ERR_IO_PENDING
)
168 length_result
= callback
.WaitForResult();
169 ASSERT_EQ(0, length_result
);
172 TEST_F(FileSystemFileStreamReaderTest
, GetLengthNormal
) {
173 scoped_ptr
<FileSystemFileStreamReader
> reader(
174 CreateFileReader(kTestFileName
, 0, test_file_modification_time()));
175 net::TestInt64CompletionCallback callback
;
176 int64 result
= reader
->GetLength(callback
.callback());
177 if (result
== net::ERR_IO_PENDING
)
178 result
= callback
.WaitForResult();
179 ASSERT_EQ(kTestDataSize
, result
);
182 TEST_F(FileSystemFileStreamReaderTest
, GetLengthAfterModified
) {
183 // Pass a fake expected modifictaion time so that the expectation fails.
184 base::Time fake_expected_modification_time
=
185 test_file_modification_time() - base::TimeDelta::FromSeconds(10);
187 scoped_ptr
<FileSystemFileStreamReader
> reader(
188 CreateFileReader(kTestFileName
, 0, fake_expected_modification_time
));
189 net::TestInt64CompletionCallback callback
;
190 int64 result
= reader
->GetLength(callback
.callback());
191 if (result
== net::ERR_IO_PENDING
)
192 result
= callback
.WaitForResult();
193 ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED
, result
);
195 // With NULL expected modification time this should work.
196 reader
.reset(CreateFileReader(kTestFileName
, 0, base::Time()));
197 result
= reader
->GetLength(callback
.callback());
198 if (result
== net::ERR_IO_PENDING
)
199 result
= callback
.WaitForResult();
200 ASSERT_EQ(kTestDataSize
, result
);
203 TEST_F(FileSystemFileStreamReaderTest
, GetLengthWithOffset
) {
204 scoped_ptr
<FileSystemFileStreamReader
> reader(
205 CreateFileReader(kTestFileName
, 3, base::Time()));
206 net::TestInt64CompletionCallback callback
;
207 int64 result
= reader
->GetLength(callback
.callback());
208 if (result
== net::ERR_IO_PENDING
)
209 result
= callback
.WaitForResult();
210 // Initial offset does not affect the result of GetLength.
211 ASSERT_EQ(kTestDataSize
, result
);
214 TEST_F(FileSystemFileStreamReaderTest
, ReadNormal
) {
215 scoped_ptr
<FileSystemFileStreamReader
> reader(
216 CreateFileReader(kTestFileName
, 0, test_file_modification_time()));
219 ReadFromReader(reader
.get(), &data
, kTestDataSize
, &result
);
220 ASSERT_EQ(net::OK
, result
);
221 ASSERT_EQ(kTestData
, data
);
224 TEST_F(FileSystemFileStreamReaderTest
, ReadAfterModified
) {
225 // Pass a fake expected modifictaion time so that the expectation fails.
226 base::Time fake_expected_modification_time
=
227 test_file_modification_time() - base::TimeDelta::FromSeconds(10);
229 scoped_ptr
<FileSystemFileStreamReader
> reader(
230 CreateFileReader(kTestFileName
, 0, fake_expected_modification_time
));
233 ReadFromReader(reader
.get(), &data
, kTestDataSize
, &result
);
234 ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED
, result
);
235 ASSERT_EQ(0U, data
.size());
237 // With NULL expected modification time this should work.
239 reader
.reset(CreateFileReader(kTestFileName
, 0, base::Time()));
240 ReadFromReader(reader
.get(), &data
, kTestDataSize
, &result
);
241 ASSERT_EQ(net::OK
, result
);
242 ASSERT_EQ(kTestData
, data
);
245 TEST_F(FileSystemFileStreamReaderTest
, ReadWithOffset
) {
246 scoped_ptr
<FileSystemFileStreamReader
> reader(
247 CreateFileReader(kTestFileName
, 3, base::Time()));
250 ReadFromReader(reader
.get(), &data
, kTestDataSize
, &result
);
251 ASSERT_EQ(net::OK
, result
);
252 ASSERT_EQ(&kTestData
[3], data
);
255 TEST_F(FileSystemFileStreamReaderTest
, DeleteWithUnfinishedRead
) {
256 scoped_ptr
<FileSystemFileStreamReader
> reader(
257 CreateFileReader(kTestFileName
, 0, base::Time()));
259 net::TestCompletionCallback callback
;
260 scoped_refptr
<net::IOBufferWithSize
> buf(
261 new net::IOBufferWithSize(kTestDataSize
));
262 int rv
= reader
->Read(buf
.get(), buf
->size(), base::Bind(&NeverCalled
));
263 ASSERT_TRUE(rv
== net::ERR_IO_PENDING
|| rv
>= 0);
265 // Delete immediately.
266 // Should not crash; nor should NeverCalled be callback.
270 } // namespace content