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_writer.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";
38 const char kTextToWrite
[] = "This is a test of FileStreamWriter.";
40 // Pushes a value to the passed log vector.
41 void LogValue(std::vector
<int>* log
, int value
) {
42 log
->push_back(value
);
45 // Creates a cracked FileSystemURL for tests.
46 storage::FileSystemURL
CreateFileSystemURL(const std::string
& mount_point_name
,
47 const base::FilePath
& file_path
) {
48 const std::string origin
= std::string("chrome-extension://") + kExtensionId
;
49 const storage::ExternalMountPoints
* const mount_points
=
50 storage::ExternalMountPoints::GetSystemInstance();
51 return mount_points
->CreateCrackedFileSystemURL(
53 storage::kFileSystemTypeExternal
,
54 base::FilePath::FromUTF8Unsafe(mount_point_name
).Append(file_path
));
57 // Creates a Service instance. Used to be able to destroy the service in
59 KeyedService
* CreateService(content::BrowserContext
* context
) {
60 return new Service(Profile::FromBrowserContext(context
),
61 extensions::ExtensionRegistry::Get(context
));
66 class FileSystemProviderFileStreamWriter
: public testing::Test
{
68 FileSystemProviderFileStreamWriter() {}
69 ~FileSystemProviderFileStreamWriter() override
{}
71 void SetUp() override
{
72 ASSERT_TRUE(data_dir_
.CreateUniqueTempDir());
73 profile_manager_
.reset(
74 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
75 ASSERT_TRUE(profile_manager_
->SetUp());
76 profile_
= profile_manager_
->CreateTestingProfile("testing-profile");
78 ServiceFactory::GetInstance()->SetTestingFactory(profile_
, &CreateService
);
79 Service
* service
= Service::Get(profile_
); // Owned by its factory.
80 service
->SetFileSystemFactoryForTesting(
81 base::Bind(&FakeProvidedFileSystem::Create
));
83 const base::File::Error result
= service
->MountFileSystem(
84 kExtensionId
, MountOptions(kFileSystemId
, "Testing File System"));
85 ASSERT_EQ(base::File::FILE_OK
, result
);
86 provided_file_system_
= static_cast<FakeProvidedFileSystem
*>(
87 service
->GetProvidedFileSystem(kExtensionId
, kFileSystemId
));
88 ASSERT_TRUE(provided_file_system_
);
89 const ProvidedFileSystemInfo
& file_system_info
=
90 provided_file_system_
->GetFileSystemInfo();
91 const std::string mount_point_name
=
92 file_system_info
.mount_path().BaseName().AsUTF8Unsafe();
94 file_url_
= CreateFileSystemURL(mount_point_name
,
95 base::FilePath(kFakeFilePath
+ 1));
96 ASSERT_TRUE(file_url_
.is_valid());
97 wrong_file_url_
= CreateFileSystemURL(
98 mount_point_name
, base::FilePath(FILE_PATH_LITERAL("im-not-here.txt")));
99 ASSERT_TRUE(wrong_file_url_
.is_valid());
102 void TearDown() override
{
103 // Setting the testing factory to NULL will destroy the created service
104 // associated with the testing profile.
105 ServiceFactory::GetInstance()->SetTestingFactory(profile_
, NULL
);
108 content::TestBrowserThreadBundle thread_bundle_
;
109 base::ScopedTempDir data_dir_
;
110 scoped_ptr
<TestingProfileManager
> profile_manager_
;
111 TestingProfile
* profile_
; // Owned by TestingProfileManager.
112 FakeProvidedFileSystem
* provided_file_system_
; // Owned by Service.
113 storage::FileSystemURL file_url_
;
114 storage::FileSystemURL wrong_file_url_
;
117 TEST_F(FileSystemProviderFileStreamWriter
, Write
) {
118 std::vector
<int> write_log
;
120 const int64 initial_offset
= 0;
121 FileStreamWriter
writer(file_url_
, initial_offset
);
122 scoped_refptr
<net::IOBuffer
> io_buffer(new net::StringIOBuffer(kTextToWrite
));
125 const int result
= writer
.Write(io_buffer
.get(),
126 sizeof(kTextToWrite
) - 1,
127 base::Bind(&LogValue
, &write_log
));
128 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
129 base::RunLoop().RunUntilIdle();
131 ASSERT_EQ(1u, write_log
.size());
132 EXPECT_LT(0, write_log
[0]);
133 EXPECT_EQ(sizeof(kTextToWrite
) - 1, static_cast<size_t>(write_log
[0]));
135 const FakeEntry
* const entry
=
136 provided_file_system_
->GetEntry(base::FilePath(kFakeFilePath
));
139 EXPECT_EQ(kTextToWrite
,
140 entry
->contents
.substr(0, sizeof(kTextToWrite
) - 1));
143 // Write additional data to be sure, that the writer's offset is shifted
146 const int result
= writer
.Write(io_buffer
.get(),
147 sizeof(kTextToWrite
) - 1,
148 base::Bind(&LogValue
, &write_log
));
149 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
150 base::RunLoop().RunUntilIdle();
152 ASSERT_EQ(2u, write_log
.size());
153 EXPECT_LT(0, write_log
[0]);
154 EXPECT_EQ(sizeof(kTextToWrite
) - 1, static_cast<size_t>(write_log
[0]));
156 const FakeEntry
* const entry
=
157 provided_file_system_
->GetEntry(base::FilePath(kFakeFilePath
));
160 // The testing text is written twice.
161 const std::string expected_contents
=
162 std::string(kTextToWrite
) + kTextToWrite
;
163 EXPECT_EQ(expected_contents
,
164 entry
->contents
.substr(0, expected_contents
.size()));
168 TEST_F(FileSystemProviderFileStreamWriter
, Cancel
) {
169 std::vector
<int> write_log
;
171 const int64 initial_offset
= 0;
172 FileStreamWriter
writer(file_url_
, initial_offset
);
173 scoped_refptr
<net::IOBuffer
> io_buffer(new net::StringIOBuffer(kTextToWrite
));
175 const int write_result
= writer
.Write(io_buffer
.get(),
176 sizeof(kTextToWrite
) - 1,
177 base::Bind(&LogValue
, &write_log
));
178 EXPECT_EQ(net::ERR_IO_PENDING
, write_result
);
180 std::vector
<int> cancel_log
;
181 const int cancel_result
= writer
.Cancel(base::Bind(&LogValue
, &cancel_log
));
182 EXPECT_EQ(net::ERR_IO_PENDING
, cancel_result
);
183 base::RunLoop().RunUntilIdle();
185 EXPECT_EQ(0u, write_log
.size());
186 ASSERT_EQ(1u, cancel_log
.size());
187 EXPECT_EQ(net::OK
, cancel_log
[0]);
190 TEST_F(FileSystemProviderFileStreamWriter
, Cancel_NotRunning
) {
191 std::vector
<int> write_log
;
193 const int64 initial_offset
= 0;
194 FileStreamWriter
writer(file_url_
, initial_offset
);
195 scoped_refptr
<net::IOBuffer
> io_buffer(new net::StringIOBuffer(kTextToWrite
));
197 std::vector
<int> cancel_log
;
198 const int cancel_result
= writer
.Cancel(base::Bind(&LogValue
, &cancel_log
));
199 EXPECT_EQ(net::ERR_UNEXPECTED
, cancel_result
);
200 base::RunLoop().RunUntilIdle();
202 EXPECT_EQ(0u, write_log
.size());
203 EXPECT_EQ(0u, cancel_log
.size()); // Result returned synchronously.
206 TEST_F(FileSystemProviderFileStreamWriter
, Write_WrongFile
) {
207 std::vector
<int> write_log
;
209 const int64 initial_offset
= 0;
210 FileStreamWriter
writer(wrong_file_url_
, initial_offset
);
211 scoped_refptr
<net::IOBuffer
> io_buffer(new net::StringIOBuffer(kTextToWrite
));
213 const int result
= writer
.Write(io_buffer
.get(),
214 sizeof(kTextToWrite
) - 1,
215 base::Bind(&LogValue
, &write_log
));
216 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
217 base::RunLoop().RunUntilIdle();
219 ASSERT_EQ(1u, write_log
.size());
220 EXPECT_EQ(net::ERR_FILE_NOT_FOUND
, write_log
[0]);
223 TEST_F(FileSystemProviderFileStreamWriter
, Write_Append
) {
224 std::vector
<int> write_log
;
226 const FakeEntry
* const entry
=
227 provided_file_system_
->GetEntry(base::FilePath(kFakeFilePath
));
230 const std::string original_contents
= entry
->contents
;
231 const int64 initial_offset
= entry
->metadata
->size
;
232 ASSERT_LT(0, initial_offset
);
234 FileStreamWriter
writer(file_url_
, initial_offset
);
235 scoped_refptr
<net::IOBuffer
> io_buffer(new net::StringIOBuffer(kTextToWrite
));
237 const int result
= writer
.Write(io_buffer
.get(),
238 sizeof(kTextToWrite
) - 1,
239 base::Bind(&LogValue
, &write_log
));
240 EXPECT_EQ(net::ERR_IO_PENDING
, result
);
241 base::RunLoop().RunUntilIdle();
243 ASSERT_EQ(1u, write_log
.size());
244 EXPECT_EQ(sizeof(kTextToWrite
) - 1, static_cast<size_t>(write_log
[0]));
246 const std::string expected_contents
= original_contents
+ kTextToWrite
;
247 EXPECT_EQ(expected_contents
, entry
->contents
);
250 } // namespace file_system_provider
251 } // namespace chromeos