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/run_loop.h"
16 #include "chrome/browser/chromeos/file_system_provider/fake_provided_file_system.h"
17 #include "chrome/browser/chromeos/file_system_provider/service.h"
18 #include "chrome/browser/chromeos/file_system_provider/service_factory.h"
19 #include "chrome/test/base/testing_browser_process.h"
20 #include "chrome/test/base/testing_profile.h"
21 #include "chrome/test/base/testing_profile_manager.h"
22 #include "content/public/test/test_browser_thread_bundle.h"
23 #include "content/public/test/test_file_system_context.h"
24 #include "extensions/browser/extension_registry.h"
25 #include "net/base/io_buffer.h"
26 #include "net/base/net_errors.h"
27 #include "storage/browser/fileapi/async_file_util.h"
28 #include "storage/browser/fileapi/external_mount_points.h"
29 #include "storage/browser/fileapi/file_system_url.h"
30 #include "testing/gtest/include/gtest/gtest.h"
33 namespace file_system_provider
{
36 const char kExtensionId
[] = "mbflcebpggnecokmikipoihdbecnjfoj";
37 const char kFileSystemId
[] = "testing-file-system";
39 // Logs callbacks invocations on the file stream reader.
42 EventLogger() : weak_ptr_factory_(this) {}
43 virtual ~EventLogger() {}
45 void OnRead(int result
) { results_
.push_back(result
); }
46 void OnGetLength(int64 result
) { results_
.push_back(result
); }
48 base::WeakPtr
<EventLogger
> GetWeakPtr() {
49 return weak_ptr_factory_
.GetWeakPtr();
52 const std::vector
<int64
>& results() const { return results_
; }
55 std::vector
<int64
> results_
;
56 base::WeakPtrFactory
<EventLogger
> weak_ptr_factory_
;
58 DISALLOW_COPY_AND_ASSIGN(EventLogger
);
61 // Creates a cracked FileSystemURL for tests.
62 storage::FileSystemURL
CreateFileSystemURL(const std::string
& mount_point_name
,
63 const base::FilePath
& file_path
) {
64 const std::string origin
= std::string("chrome-extension://") + kExtensionId
;
65 const storage::ExternalMountPoints
* const mount_points
=
66 storage::ExternalMountPoints::GetSystemInstance();
67 return mount_points
->CreateCrackedFileSystemURL(
69 storage::kFileSystemTypeExternal
,
70 base::FilePath::FromUTF8Unsafe(mount_point_name
).Append(file_path
));
73 // Creates a Service instance. Used to be able to destroy the service in
75 KeyedService
* CreateService(content::BrowserContext
* context
) {
76 return new Service(Profile::FromBrowserContext(context
),
77 extensions::ExtensionRegistry::Get(context
));
82 class FileSystemProviderFileStreamReader
: public testing::Test
{
84 FileSystemProviderFileStreamReader() : profile_(NULL
), fake_file_(NULL
) {}
85 ~FileSystemProviderFileStreamReader() override
{}
87 void SetUp() override
{
88 ASSERT_TRUE(data_dir_
.CreateUniqueTempDir());
89 profile_manager_
.reset(
90 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
91 ASSERT_TRUE(profile_manager_
->SetUp());
92 profile_
= profile_manager_
->CreateTestingProfile("testing-profile");
94 ServiceFactory::GetInstance()->SetTestingFactory(profile_
, &CreateService
);
95 Service
* service
= Service::Get(profile_
); // Owned by its factory.
96 service
->SetFileSystemFactoryForTesting(
97 base::Bind(&FakeProvidedFileSystem::Create
));
99 const base::File::Error result
= service
->MountFileSystem(
100 kExtensionId
, MountOptions(kFileSystemId
, "Testing File System"));
101 ASSERT_EQ(base::File::FILE_OK
, result
);
102 FakeProvidedFileSystem
* provided_file_system
=
103 static_cast<FakeProvidedFileSystem
*>(
104 service
->GetProvidedFileSystem(kExtensionId
, kFileSystemId
));
105 ASSERT_TRUE(provided_file_system
);
106 fake_file_
= provided_file_system
->GetEntry(base::FilePath(kFakeFilePath
));
107 ASSERT_TRUE(fake_file_
);
108 const ProvidedFileSystemInfo
& file_system_info
=
109 service
->GetProvidedFileSystem(kExtensionId
, kFileSystemId
)
110 ->GetFileSystemInfo();
111 const std::string mount_point_name
=
112 file_system_info
.mount_path().BaseName().AsUTF8Unsafe();
114 file_url_
= CreateFileSystemURL(mount_point_name
,
115 base::FilePath(kFakeFilePath
+ 1));
116 ASSERT_TRUE(file_url_
.is_valid());
117 wrong_file_url_
= CreateFileSystemURL(
118 mount_point_name
, base::FilePath(FILE_PATH_LITERAL("im-not-here.txt")));
119 ASSERT_TRUE(wrong_file_url_
.is_valid());
122 void TearDown() override
{
123 // Setting the testing factory to NULL will destroy the created service
124 // associated with the testing profile.
125 ServiceFactory::GetInstance()->SetTestingFactory(profile_
, NULL
);
128 content::TestBrowserThreadBundle thread_bundle_
;
129 base::ScopedTempDir data_dir_
;
130 scoped_ptr
<TestingProfileManager
> profile_manager_
;
131 TestingProfile
* profile_
; // Owned by TestingProfileManager.
132 const FakeEntry
* fake_file_
; // Owned by FakePRovidedFileSystem.
133 storage::FileSystemURL file_url_
;
134 storage::FileSystemURL wrong_file_url_
;
137 TEST_F(FileSystemProviderFileStreamReader
, Read_AllAtOnce
) {
140 const int64 initial_offset
= 0;
141 FileStreamReader
reader(
142 NULL
, file_url_
, initial_offset
, fake_file_
->metadata
->modification_time
);
143 scoped_refptr
<net::IOBuffer
> io_buffer(
144 new net::IOBuffer(fake_file_
->metadata
->size
));
147 reader
.Read(io_buffer
.get(),
148 fake_file_
->metadata
->size
,
149 base::Bind(&EventLogger::OnRead
, logger
.GetWeakPtr()));
150 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
151 base::RunLoop().RunUntilIdle();
153 ASSERT_EQ(1u, logger
.results().size());
154 EXPECT_LT(0, logger
.results()[0]);
155 EXPECT_EQ(fake_file_
->metadata
->size
, logger
.results()[0]);
157 std::string
buffer_as_string(io_buffer
->data(), fake_file_
->metadata
->size
);
158 EXPECT_EQ(fake_file_
->contents
, buffer_as_string
);
161 TEST_F(FileSystemProviderFileStreamReader
, Read_WrongFile
) {
164 const int64 initial_offset
= 0;
165 FileStreamReader
reader(NULL
,
168 fake_file_
->metadata
->modification_time
);
169 scoped_refptr
<net::IOBuffer
> io_buffer(
170 new net::IOBuffer(fake_file_
->metadata
->size
));
173 reader
.Read(io_buffer
.get(),
174 fake_file_
->metadata
->size
,
175 base::Bind(&EventLogger::OnRead
, logger
.GetWeakPtr()));
176 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
177 base::RunLoop().RunUntilIdle();
179 ASSERT_EQ(1u, logger
.results().size());
180 EXPECT_EQ(net::ERR_FILE_NOT_FOUND
, logger
.results()[0]);
183 TEST_F(FileSystemProviderFileStreamReader
, Read_InChunks
) {
186 const int64 initial_offset
= 0;
187 FileStreamReader
reader(
188 NULL
, file_url_
, initial_offset
, fake_file_
->metadata
->modification_time
);
190 for (int64 offset
= 0; offset
< fake_file_
->metadata
->size
; ++offset
) {
191 scoped_refptr
<net::IOBuffer
> io_buffer(new net::IOBuffer(1));
193 reader
.Read(io_buffer
.get(),
195 base::Bind(&EventLogger::OnRead
, logger
.GetWeakPtr()));
196 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
197 base::RunLoop().RunUntilIdle();
198 ASSERT_EQ(offset
+ 1, static_cast<int64
>(logger
.results().size()));
199 EXPECT_EQ(1, logger
.results()[offset
]);
200 EXPECT_EQ(fake_file_
->contents
[offset
], io_buffer
->data()[0]);
204 TEST_F(FileSystemProviderFileStreamReader
, Read_Slice
) {
207 // Trim first 3 and last 3 characters.
208 const int64 initial_offset
= 3;
209 const int length
= fake_file_
->metadata
->size
- initial_offset
- 3;
210 ASSERT_GT(fake_file_
->metadata
->size
, initial_offset
);
211 ASSERT_LT(0, length
);
213 FileStreamReader
reader(
214 NULL
, file_url_
, initial_offset
, fake_file_
->metadata
->modification_time
);
215 scoped_refptr
<net::IOBuffer
> io_buffer(new net::IOBuffer(length
));
218 reader
.Read(io_buffer
.get(),
220 base::Bind(&EventLogger::OnRead
, logger
.GetWeakPtr()));
221 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
222 base::RunLoop().RunUntilIdle();
224 ASSERT_EQ(1u, logger
.results().size());
225 EXPECT_EQ(length
, logger
.results()[0]);
227 std::string
buffer_as_string(io_buffer
->data(), length
);
228 std::string
expected_buffer(fake_file_
->contents
.data() + initial_offset
,
230 EXPECT_EQ(expected_buffer
, buffer_as_string
);
233 TEST_F(FileSystemProviderFileStreamReader
, Read_Beyond
) {
236 // Request reading 1KB more than available.
237 const int64 initial_offset
= 0;
238 const int length
= fake_file_
->metadata
->size
+ 1024;
240 FileStreamReader
reader(
241 NULL
, file_url_
, initial_offset
, fake_file_
->metadata
->modification_time
);
242 scoped_refptr
<net::IOBuffer
> io_buffer(new net::IOBuffer(length
));
245 reader
.Read(io_buffer
.get(),
247 base::Bind(&EventLogger::OnRead
, logger
.GetWeakPtr()));
248 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
249 base::RunLoop().RunUntilIdle();
251 ASSERT_EQ(1u, logger
.results().size());
252 EXPECT_LT(0, logger
.results()[0]);
253 EXPECT_EQ(fake_file_
->metadata
->size
, logger
.results()[0]);
255 std::string
buffer_as_string(io_buffer
->data(), fake_file_
->metadata
->size
);
256 EXPECT_EQ(fake_file_
->contents
, buffer_as_string
);
259 TEST_F(FileSystemProviderFileStreamReader
, Read_ModifiedFile
) {
262 const int64 initial_offset
= 0;
263 FileStreamReader
reader(NULL
, file_url_
, initial_offset
, base::Time::Max());
265 scoped_refptr
<net::IOBuffer
> io_buffer(
266 new net::IOBuffer(fake_file_
->metadata
->size
));
268 reader
.Read(io_buffer
.get(),
269 fake_file_
->metadata
->size
,
270 base::Bind(&EventLogger::OnRead
, logger
.GetWeakPtr()));
272 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
273 base::RunLoop().RunUntilIdle();
275 ASSERT_EQ(1u, logger
.results().size());
276 EXPECT_EQ(net::ERR_UPLOAD_FILE_CHANGED
, logger
.results()[0]);
279 TEST_F(FileSystemProviderFileStreamReader
, Read_ExpectedModificationTimeNull
) {
282 const int64 initial_offset
= 0;
283 FileStreamReader
reader(NULL
, file_url_
, initial_offset
, base::Time());
285 scoped_refptr
<net::IOBuffer
> io_buffer(
286 new net::IOBuffer(fake_file_
->metadata
->size
));
288 reader
.Read(io_buffer
.get(),
289 fake_file_
->metadata
->size
,
290 base::Bind(&EventLogger::OnRead
, logger
.GetWeakPtr()));
292 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
293 base::RunLoop().RunUntilIdle();
295 ASSERT_EQ(1u, logger
.results().size());
296 EXPECT_EQ(fake_file_
->metadata
->size
, logger
.results()[0]);
298 std::string
buffer_as_string(io_buffer
->data(), fake_file_
->metadata
->size
);
299 EXPECT_EQ(fake_file_
->contents
, buffer_as_string
);
302 TEST_F(FileSystemProviderFileStreamReader
, GetLength
) {
305 const int64 initial_offset
= 0;
306 FileStreamReader
reader(
307 NULL
, file_url_
, initial_offset
, fake_file_
->metadata
->modification_time
);
309 const int result
= reader
.GetLength(
310 base::Bind(&EventLogger::OnGetLength
, logger
.GetWeakPtr()));
311 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
312 base::RunLoop().RunUntilIdle();
314 ASSERT_EQ(1u, logger
.results().size());
315 EXPECT_LT(0, logger
.results()[0]);
316 EXPECT_EQ(fake_file_
->metadata
->size
, logger
.results()[0]);
319 TEST_F(FileSystemProviderFileStreamReader
, GetLength_WrongFile
) {
322 const int64 initial_offset
= 0;
323 FileStreamReader
reader(NULL
,
326 fake_file_
->metadata
->modification_time
);
328 const int result
= reader
.GetLength(
329 base::Bind(&EventLogger::OnGetLength
, logger
.GetWeakPtr()));
330 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
331 base::RunLoop().RunUntilIdle();
333 ASSERT_EQ(1u, logger
.results().size());
334 EXPECT_EQ(net::ERR_FILE_NOT_FOUND
, logger
.results()[0]);
337 TEST_F(FileSystemProviderFileStreamReader
, GetLength_ModifiedFile
) {
340 const int64 initial_offset
= 0;
341 FileStreamReader
reader(NULL
, file_url_
, initial_offset
, base::Time::Max());
343 const int result
= reader
.GetLength(
344 base::Bind(&EventLogger::OnGetLength
, logger
.GetWeakPtr()));
345 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
346 base::RunLoop().RunUntilIdle();
348 ASSERT_EQ(1u, logger
.results().size());
349 EXPECT_EQ(net::ERR_UPLOAD_FILE_CHANGED
, logger
.results()[0]);
352 TEST_F(FileSystemProviderFileStreamReader
,
353 GetLength_ExpectedModificationTimeNull
) {
356 const int64 initial_offset
= 0;
357 FileStreamReader
reader(NULL
, file_url_
, initial_offset
, base::Time());
359 const int result
= reader
.GetLength(
360 base::Bind(&EventLogger::OnGetLength
, logger
.GetWeakPtr()));
361 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
362 base::RunLoop().RunUntilIdle();
364 ASSERT_EQ(1u, logger
.results().size());
365 EXPECT_LT(0, logger
.results()[0]);
366 EXPECT_EQ(fake_file_
->metadata
->size
, logger
.results()[0]);
369 } // namespace file_system_provider
370 } // namespace chromeos