1 // Copyright 2014 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 "chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader.h"
10 #include "base/files/file.h"
11 #include "base/files/file_path.h"
12 #include "base/files/scoped_temp_dir.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/numerics/safe_math.h"
16 #include "base/run_loop.h"
17 #include "chrome/browser/chromeos/file_system_provider/fake_provided_file_system.h"
18 #include "chrome/browser/chromeos/file_system_provider/service.h"
19 #include "chrome/browser/chromeos/file_system_provider/service_factory.h"
20 #include "chrome/test/base/testing_browser_process.h"
21 #include "chrome/test/base/testing_profile.h"
22 #include "chrome/test/base/testing_profile_manager.h"
23 #include "content/public/test/test_browser_thread_bundle.h"
24 #include "content/public/test/test_file_system_context.h"
25 #include "extensions/browser/extension_registry.h"
26 #include "net/base/io_buffer.h"
27 #include "net/base/net_errors.h"
28 #include "storage/browser/fileapi/async_file_util.h"
29 #include "storage/browser/fileapi/external_mount_points.h"
30 #include "storage/browser/fileapi/file_system_url.h"
31 #include "testing/gtest/include/gtest/gtest.h"
34 namespace file_system_provider
{
37 const char kExtensionId
[] = "mbflcebpggnecokmikipoihdbecnjfoj";
38 const char kFileSystemId
[] = "testing-file-system";
40 // Logs callbacks invocations on the file stream reader.
43 EventLogger() : weak_ptr_factory_(this) {}
44 virtual ~EventLogger() {}
46 void OnRead(int result
) { results_
.push_back(result
); }
47 void OnGetLength(int64 result
) { results_
.push_back(result
); }
49 base::WeakPtr
<EventLogger
> GetWeakPtr() {
50 return weak_ptr_factory_
.GetWeakPtr();
53 const std::vector
<int64
>& results() const { return results_
; }
56 std::vector
<int64
> results_
;
57 base::WeakPtrFactory
<EventLogger
> weak_ptr_factory_
;
59 DISALLOW_COPY_AND_ASSIGN(EventLogger
);
62 // Creates a cracked FileSystemURL for tests.
63 storage::FileSystemURL
CreateFileSystemURL(const std::string
& mount_point_name
,
64 const base::FilePath
& file_path
) {
65 const std::string origin
= std::string("chrome-extension://") + kExtensionId
;
66 const storage::ExternalMountPoints
* const mount_points
=
67 storage::ExternalMountPoints::GetSystemInstance();
68 return mount_points
->CreateCrackedFileSystemURL(
70 storage::kFileSystemTypeExternal
,
71 base::FilePath::FromUTF8Unsafe(mount_point_name
).Append(file_path
));
76 class FileSystemProviderFileStreamReader
: public testing::Test
{
78 FileSystemProviderFileStreamReader() : profile_(NULL
), fake_file_(NULL
) {}
79 ~FileSystemProviderFileStreamReader() override
{}
81 void SetUp() override
{
82 ASSERT_TRUE(data_dir_
.CreateUniqueTempDir());
83 profile_manager_
.reset(
84 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
85 ASSERT_TRUE(profile_manager_
->SetUp());
86 profile_
= profile_manager_
->CreateTestingProfile("testing-profile");
88 Service
* service
= Service::Get(profile_
); // Owned by its factory.
89 service
->SetFileSystemFactoryForTesting(
90 base::Bind(&FakeProvidedFileSystem::Create
));
92 const base::File::Error result
= service
->MountFileSystem(
93 kExtensionId
, MountOptions(kFileSystemId
, "Testing File System"));
94 ASSERT_EQ(base::File::FILE_OK
, result
);
95 FakeProvidedFileSystem
* provided_file_system
=
96 static_cast<FakeProvidedFileSystem
*>(
97 service
->GetProvidedFileSystem(kExtensionId
, kFileSystemId
));
98 ASSERT_TRUE(provided_file_system
);
99 fake_file_
= provided_file_system
->GetEntry(base::FilePath(kFakeFilePath
));
100 ASSERT_TRUE(fake_file_
);
101 const ProvidedFileSystemInfo
& file_system_info
=
102 service
->GetProvidedFileSystem(kExtensionId
, kFileSystemId
)
103 ->GetFileSystemInfo();
104 const std::string mount_point_name
=
105 file_system_info
.mount_path().BaseName().AsUTF8Unsafe();
107 file_url_
= CreateFileSystemURL(mount_point_name
,
108 base::FilePath(kFakeFilePath
+ 1));
109 ASSERT_TRUE(file_url_
.is_valid());
110 wrong_file_url_
= CreateFileSystemURL(
111 mount_point_name
, base::FilePath(FILE_PATH_LITERAL("im-not-here.txt")));
112 ASSERT_TRUE(wrong_file_url_
.is_valid());
115 content::TestBrowserThreadBundle thread_bundle_
;
116 base::ScopedTempDir data_dir_
;
117 scoped_ptr
<TestingProfileManager
> profile_manager_
;
118 TestingProfile
* profile_
; // Owned by TestingProfileManager.
119 const FakeEntry
* fake_file_
; // Owned by FakePRovidedFileSystem.
120 storage::FileSystemURL file_url_
;
121 storage::FileSystemURL wrong_file_url_
;
124 TEST_F(FileSystemProviderFileStreamReader
, Read_AllAtOnce
) {
127 const int64 initial_offset
= 0;
128 FileStreamReader
reader(
129 NULL
, file_url_
, initial_offset
, fake_file_
->metadata
->modification_time
);
130 scoped_refptr
<net::IOBuffer
> io_buffer(new net::IOBuffer(
131 base::CheckedNumeric
<size_t>(fake_file_
->metadata
->size
).ValueOrDie()));
134 reader
.Read(io_buffer
.get(),
135 fake_file_
->metadata
->size
,
136 base::Bind(&EventLogger::OnRead
, logger
.GetWeakPtr()));
137 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
138 base::RunLoop().RunUntilIdle();
140 ASSERT_EQ(1u, logger
.results().size());
141 EXPECT_LT(0, logger
.results()[0]);
142 EXPECT_EQ(fake_file_
->metadata
->size
, logger
.results()[0]);
144 std::string
buffer_as_string(io_buffer
->data(), fake_file_
->metadata
->size
);
145 EXPECT_EQ(fake_file_
->contents
, buffer_as_string
);
148 TEST_F(FileSystemProviderFileStreamReader
, Read_WrongFile
) {
151 const int64 initial_offset
= 0;
152 FileStreamReader
reader(NULL
,
155 fake_file_
->metadata
->modification_time
);
156 scoped_refptr
<net::IOBuffer
> io_buffer(new net::IOBuffer(
157 base::CheckedNumeric
<size_t>(fake_file_
->metadata
->size
).ValueOrDie()));
160 reader
.Read(io_buffer
.get(),
161 fake_file_
->metadata
->size
,
162 base::Bind(&EventLogger::OnRead
, logger
.GetWeakPtr()));
163 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
164 base::RunLoop().RunUntilIdle();
166 ASSERT_EQ(1u, logger
.results().size());
167 EXPECT_EQ(net::ERR_FILE_NOT_FOUND
, logger
.results()[0]);
170 TEST_F(FileSystemProviderFileStreamReader
, Read_InChunks
) {
173 const int64 initial_offset
= 0;
174 FileStreamReader
reader(
175 NULL
, file_url_
, initial_offset
, fake_file_
->metadata
->modification_time
);
177 for (int64 offset
= 0; offset
< fake_file_
->metadata
->size
; ++offset
) {
178 scoped_refptr
<net::IOBuffer
> io_buffer(new net::IOBuffer(1));
180 reader
.Read(io_buffer
.get(),
182 base::Bind(&EventLogger::OnRead
, logger
.GetWeakPtr()));
183 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
184 base::RunLoop().RunUntilIdle();
185 ASSERT_EQ(offset
+ 1, static_cast<int64
>(logger
.results().size()));
186 EXPECT_EQ(1, logger
.results()[offset
]);
187 EXPECT_EQ(fake_file_
->contents
[offset
], io_buffer
->data()[0]);
191 TEST_F(FileSystemProviderFileStreamReader
, Read_Slice
) {
194 // Trim first 3 and last 3 characters.
195 const int64 initial_offset
= 3;
196 const int length
= fake_file_
->metadata
->size
- initial_offset
- 3;
197 ASSERT_GT(fake_file_
->metadata
->size
, initial_offset
);
198 ASSERT_LT(0, length
);
200 FileStreamReader
reader(
201 NULL
, file_url_
, initial_offset
, fake_file_
->metadata
->modification_time
);
202 scoped_refptr
<net::IOBuffer
> io_buffer(new net::IOBuffer(length
));
205 reader
.Read(io_buffer
.get(),
207 base::Bind(&EventLogger::OnRead
, logger
.GetWeakPtr()));
208 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
209 base::RunLoop().RunUntilIdle();
211 ASSERT_EQ(1u, logger
.results().size());
212 EXPECT_EQ(length
, logger
.results()[0]);
214 std::string
buffer_as_string(io_buffer
->data(), length
);
215 std::string
expected_buffer(fake_file_
->contents
.data() + initial_offset
,
217 EXPECT_EQ(expected_buffer
, buffer_as_string
);
220 TEST_F(FileSystemProviderFileStreamReader
, Read_Beyond
) {
223 // Request reading 1KB more than available.
224 const int64 initial_offset
= 0;
225 const int length
= fake_file_
->metadata
->size
+ 1024;
227 FileStreamReader
reader(
228 NULL
, file_url_
, initial_offset
, fake_file_
->metadata
->modification_time
);
229 scoped_refptr
<net::IOBuffer
> io_buffer(new net::IOBuffer(length
));
232 reader
.Read(io_buffer
.get(),
234 base::Bind(&EventLogger::OnRead
, logger
.GetWeakPtr()));
235 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
236 base::RunLoop().RunUntilIdle();
238 ASSERT_EQ(1u, logger
.results().size());
239 EXPECT_LT(0, logger
.results()[0]);
240 EXPECT_EQ(fake_file_
->metadata
->size
, logger
.results()[0]);
242 std::string
buffer_as_string(io_buffer
->data(), fake_file_
->metadata
->size
);
243 EXPECT_EQ(fake_file_
->contents
, buffer_as_string
);
246 TEST_F(FileSystemProviderFileStreamReader
, Read_ModifiedFile
) {
249 const int64 initial_offset
= 0;
250 FileStreamReader
reader(NULL
, file_url_
, initial_offset
, base::Time::Max());
252 scoped_refptr
<net::IOBuffer
> io_buffer(new net::IOBuffer(
253 base::CheckedNumeric
<size_t>(fake_file_
->metadata
->size
).ValueOrDie()));
255 reader
.Read(io_buffer
.get(),
256 fake_file_
->metadata
->size
,
257 base::Bind(&EventLogger::OnRead
, logger
.GetWeakPtr()));
259 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
260 base::RunLoop().RunUntilIdle();
262 ASSERT_EQ(1u, logger
.results().size());
263 EXPECT_EQ(net::ERR_UPLOAD_FILE_CHANGED
, logger
.results()[0]);
266 TEST_F(FileSystemProviderFileStreamReader
, Read_ExpectedModificationTimeNull
) {
269 const int64 initial_offset
= 0;
270 FileStreamReader
reader(NULL
, file_url_
, initial_offset
, base::Time());
272 scoped_refptr
<net::IOBuffer
> io_buffer(new net::IOBuffer(
273 base::CheckedNumeric
<size_t>(fake_file_
->metadata
->size
).ValueOrDie()));
275 reader
.Read(io_buffer
.get(),
276 fake_file_
->metadata
->size
,
277 base::Bind(&EventLogger::OnRead
, logger
.GetWeakPtr()));
279 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
280 base::RunLoop().RunUntilIdle();
282 ASSERT_EQ(1u, logger
.results().size());
283 EXPECT_EQ(fake_file_
->metadata
->size
, logger
.results()[0]);
285 std::string
buffer_as_string(io_buffer
->data(), fake_file_
->metadata
->size
);
286 EXPECT_EQ(fake_file_
->contents
, buffer_as_string
);
289 TEST_F(FileSystemProviderFileStreamReader
, GetLength
) {
292 const int64 initial_offset
= 0;
293 FileStreamReader
reader(
294 NULL
, file_url_
, initial_offset
, fake_file_
->metadata
->modification_time
);
296 const int result
= reader
.GetLength(
297 base::Bind(&EventLogger::OnGetLength
, logger
.GetWeakPtr()));
298 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
299 base::RunLoop().RunUntilIdle();
301 ASSERT_EQ(1u, logger
.results().size());
302 EXPECT_LT(0, logger
.results()[0]);
303 EXPECT_EQ(fake_file_
->metadata
->size
, logger
.results()[0]);
306 TEST_F(FileSystemProviderFileStreamReader
, GetLength_WrongFile
) {
309 const int64 initial_offset
= 0;
310 FileStreamReader
reader(NULL
,
313 fake_file_
->metadata
->modification_time
);
315 const int result
= reader
.GetLength(
316 base::Bind(&EventLogger::OnGetLength
, logger
.GetWeakPtr()));
317 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
318 base::RunLoop().RunUntilIdle();
320 ASSERT_EQ(1u, logger
.results().size());
321 EXPECT_EQ(net::ERR_FILE_NOT_FOUND
, logger
.results()[0]);
324 TEST_F(FileSystemProviderFileStreamReader
, GetLength_ModifiedFile
) {
327 const int64 initial_offset
= 0;
328 FileStreamReader
reader(NULL
, file_url_
, initial_offset
, base::Time::Max());
330 const int result
= reader
.GetLength(
331 base::Bind(&EventLogger::OnGetLength
, logger
.GetWeakPtr()));
332 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
333 base::RunLoop().RunUntilIdle();
335 ASSERT_EQ(1u, logger
.results().size());
336 EXPECT_EQ(net::ERR_UPLOAD_FILE_CHANGED
, logger
.results()[0]);
339 TEST_F(FileSystemProviderFileStreamReader
,
340 GetLength_ExpectedModificationTimeNull
) {
343 const int64 initial_offset
= 0;
344 FileStreamReader
reader(NULL
, file_url_
, initial_offset
, base::Time());
346 const int result
= reader
.GetLength(
347 base::Bind(&EventLogger::OnGetLength
, logger
.GetWeakPtr()));
348 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
349 base::RunLoop().RunUntilIdle();
351 ASSERT_EQ(1u, logger
.results().size());
352 EXPECT_LT(0, logger
.results()[0]);
353 EXPECT_EQ(fake_file_
->metadata
->size
, logger
.results()[0]);
356 } // namespace file_system_provider
357 } // namespace chromeos