1 // Copyright (c) 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.
8 #include "base/basictypes.h"
10 #include "base/files/scoped_temp_dir.h"
11 #include "base/message_loop.h"
12 #include "base/run_loop.h"
13 #include "base/stl_util.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "webkit/fileapi/async_file_test_helper.h"
16 #include "webkit/fileapi/external_mount_points.h"
17 #include "webkit/fileapi/file_system_context.h"
18 #include "webkit/fileapi/file_system_mount_point_provider.h"
19 #include "webkit/fileapi/file_system_operation.h"
20 #include "webkit/fileapi/file_system_task_runners.h"
21 #include "webkit/fileapi/file_system_url.h"
22 #include "webkit/fileapi/file_system_util.h"
23 #include "webkit/fileapi/mock_file_system_options.h"
24 #include "webkit/fileapi/test_file_set.h"
25 #include "webkit/quota/mock_quota_manager.h"
26 #include "webkit/quota/mock_special_storage_policy.h"
27 #include "webkit/quota/quota_manager.h"
31 typedef FileSystemOperation::FileEntryList FileEntryList
;
33 class CrossOperationTestHelper
{
35 CrossOperationTestHelper(
37 FileSystemType src_type
,
38 FileSystemType dest_type
)
41 dest_type_(dest_type
) {}
43 ~CrossOperationTestHelper() {
44 file_system_context_
= NULL
;
45 quota_manager_proxy_
->SimulateQuotaManagerDestroyed();
46 quota_manager_
= NULL
;
47 quota_manager_proxy_
= NULL
;
48 MessageLoop::current()->RunUntilIdle();
52 ASSERT_TRUE(base_
.CreateUniqueTempDir());
53 base::FilePath base_dir
= base_
.path();
54 quota_manager_
= new quota::MockQuotaManager(
55 false /* is_incognito */, base_dir
,
56 base::MessageLoopProxy::current(),
57 base::MessageLoopProxy::current(),
58 NULL
/* special storage policy */);
59 quota_manager_proxy_
= new quota::MockQuotaManagerProxy(
61 base::MessageLoopProxy::current());
62 file_system_context_
= new FileSystemContext(
63 FileSystemTaskRunners::CreateMockTaskRunners(),
64 ExternalMountPoints::CreateRefCounted().get(),
65 make_scoped_refptr(new quota::MockSpecialStoragePolicy
),
68 CreateAllowFileAccessOptions());
70 // Prepare the origin's root directory.
71 FileSystemMountPointProvider
* mount_point_provider
=
72 file_system_context_
->GetMountPointProvider(src_type_
);
73 mount_point_provider
->GetFileSystemRootPathOnFileThread(
74 SourceURL(std::string()), true /* create */);
75 mount_point_provider
=
76 file_system_context_
->GetMountPointProvider(dest_type_
);
77 mount_point_provider
->GetFileSystemRootPathOnFileThread(
78 DestURL(std::string()), true /* create */);
80 // Grant relatively big quota initially.
81 quota_manager_
->SetQuota(origin_
,
82 FileSystemTypeToQuotaStorageType(src_type_
),
84 quota_manager_
->SetQuota(origin_
,
85 FileSystemTypeToQuotaStorageType(dest_type_
),
89 int64
GetSourceUsage() {
91 GetUsageAndQuota(src_type_
, &usage
, NULL
);
95 int64
GetDestUsage() {
97 GetUsageAndQuota(dest_type_
, &usage
, NULL
);
101 FileSystemURL
SourceURL(const std::string
& path
) {
102 return file_system_context_
->CreateCrackedFileSystemURL(
103 origin_
, src_type_
, base::FilePath::FromUTF8Unsafe(path
));
106 FileSystemURL
DestURL(const std::string
& path
) {
107 return file_system_context_
->CreateCrackedFileSystemURL(
108 origin_
, dest_type_
, base::FilePath::FromUTF8Unsafe(path
));
111 base::PlatformFileError
Copy(const FileSystemURL
& src
,
112 const FileSystemURL
& dest
) {
113 return AsyncFileTestHelper::Copy(file_system_context_
, src
, dest
);
116 base::PlatformFileError
Move(const FileSystemURL
& src
,
117 const FileSystemURL
& dest
) {
118 return AsyncFileTestHelper::Move(file_system_context_
, src
, dest
);
121 base::PlatformFileError
SetUpTestCaseFiles(
122 const FileSystemURL
& root
,
123 const test::TestCaseRecord
* const test_cases
,
124 size_t test_case_size
) {
125 base::PlatformFileError result
= base::PLATFORM_FILE_ERROR_FAILED
;
126 for (size_t i
= 0; i
< test_case_size
; ++i
) {
127 const test::TestCaseRecord
& test_case
= test_cases
[i
];
128 FileSystemURL url
= file_system_context_
->CreateCrackedFileSystemURL(
131 root
.virtual_path().Append(test_case
.path
));
132 if (test_case
.is_directory
)
133 result
= CreateDirectory(url
);
135 result
= CreateFile(url
, test_case
.data_file_size
);
136 EXPECT_EQ(base::PLATFORM_FILE_OK
, result
) << url
.DebugString();
137 if (result
!= base::PLATFORM_FILE_OK
)
143 void VerifyTestCaseFiles(
144 const FileSystemURL
& root
,
145 const test::TestCaseRecord
* const test_cases
,
146 size_t test_case_size
) {
147 std::map
<base::FilePath
, const test::TestCaseRecord
*> test_case_map
;
148 for (size_t i
= 0; i
< test_case_size
; ++i
)
150 base::FilePath(test_cases
[i
].path
).NormalizePathSeparators()] =
153 std::queue
<FileSystemURL
> directories
;
154 FileEntryList entries
;
155 directories
.push(root
);
156 while (!directories
.empty()) {
157 FileSystemURL dir
= directories
.front();
159 ASSERT_EQ(base::PLATFORM_FILE_OK
, ReadDirectory(dir
, &entries
));
160 for (size_t i
= 0; i
< entries
.size(); ++i
) {
161 FileSystemURL url
= file_system_context_
->CreateCrackedFileSystemURL(
164 dir
.virtual_path().Append(entries
[i
].name
));
165 base::FilePath relative
;
166 root
.virtual_path().AppendRelativePath(url
.virtual_path(), &relative
);
167 relative
= relative
.NormalizePathSeparators();
168 ASSERT_TRUE(ContainsKey(test_case_map
, relative
));
169 if (entries
[i
].is_directory
) {
170 EXPECT_TRUE(test_case_map
[relative
]->is_directory
);
171 directories
.push(url
);
173 EXPECT_FALSE(test_case_map
[relative
]->is_directory
);
174 EXPECT_TRUE(FileExists(url
, test_case_map
[relative
]->data_file_size
));
176 test_case_map
.erase(relative
);
179 EXPECT_TRUE(test_case_map
.empty());
182 base::PlatformFileError
ReadDirectory(const FileSystemURL
& url
,
183 FileEntryList
* entries
) {
184 return AsyncFileTestHelper::ReadDirectory(
185 file_system_context_
, url
, entries
);
188 base::PlatformFileError
CreateDirectory(const FileSystemURL
& url
) {
189 return AsyncFileTestHelper::CreateDirectory(
190 file_system_context_
, url
);
193 base::PlatformFileError
CreateFile(const FileSystemURL
& url
, size_t size
) {
194 base::PlatformFileError result
=
195 AsyncFileTestHelper::CreateFile(file_system_context_
, url
);
196 if (result
!= base::PLATFORM_FILE_OK
)
198 return AsyncFileTestHelper::TruncateFile(file_system_context_
, url
, size
);
201 bool FileExists(const FileSystemURL
& url
, int64 expected_size
) {
202 return AsyncFileTestHelper::FileExists(
203 file_system_context_
, url
, expected_size
);
206 bool DirectoryExists(const FileSystemURL
& url
) {
207 return AsyncFileTestHelper::DirectoryExists(file_system_context_
, url
);
211 void GetUsageAndQuota(FileSystemType type
, int64
* usage
, int64
* quota
) {
212 quota::QuotaStatusCode status
=
213 AsyncFileTestHelper::GetUsageAndQuota(
214 quota_manager_
, origin_
, type
, usage
, quota
);
215 ASSERT_EQ(quota::kQuotaStatusOk
, status
);
219 base::ScopedTempDir base_
;
222 const FileSystemType src_type_
;
223 const FileSystemType dest_type_
;
225 MessageLoop message_loop_
;
226 scoped_refptr
<FileSystemContext
> file_system_context_
;
227 scoped_refptr
<quota::MockQuotaManagerProxy
> quota_manager_proxy_
;
228 scoped_refptr
<quota::MockQuotaManager
> quota_manager_
;
230 DISALLOW_COPY_AND_ASSIGN(CrossOperationTestHelper
);
233 TEST(LocalFileSystemCrossOperationTest
, CopySingleFile
) {
234 CrossOperationTestHelper
helper(GURL("http://foo"),
235 kFileSystemTypeTemporary
,
236 kFileSystemTypePersistent
);
239 FileSystemURL src
= helper
.SourceURL("a");
240 FileSystemURL dest
= helper
.DestURL("b");
241 int64 src_initial_usage
= helper
.GetSourceUsage();
242 int64 dest_initial_usage
= helper
.GetDestUsage();
244 // Set up a source file.
245 ASSERT_EQ(base::PLATFORM_FILE_OK
, helper
.CreateFile(src
, 10));
246 int64 src_increase
= helper
.GetSourceUsage() - src_initial_usage
;
249 ASSERT_EQ(base::PLATFORM_FILE_OK
, helper
.Copy(src
, dest
));
252 ASSERT_TRUE(helper
.FileExists(src
, 10));
253 ASSERT_TRUE(helper
.FileExists(dest
, 10));
255 int64 src_new_usage
= helper
.GetSourceUsage();
256 ASSERT_EQ(src_initial_usage
+ src_increase
, src_new_usage
);
258 int64 dest_increase
= helper
.GetDestUsage() - dest_initial_usage
;
259 ASSERT_EQ(src_increase
, dest_increase
);
262 TEST(LocalFileSystemCrossOperationTest
, MoveSingleFile
) {
263 CrossOperationTestHelper
helper(GURL("http://foo"),
264 kFileSystemTypeTemporary
,
265 kFileSystemTypePersistent
);
268 FileSystemURL src
= helper
.SourceURL("a");
269 FileSystemURL dest
= helper
.DestURL("b");
270 int64 src_initial_usage
= helper
.GetSourceUsage();
271 int64 dest_initial_usage
= helper
.GetDestUsage();
273 // Set up a source file.
274 ASSERT_EQ(base::PLATFORM_FILE_OK
, helper
.CreateFile(src
, 10));
275 int64 src_increase
= helper
.GetSourceUsage() - src_initial_usage
;
278 ASSERT_EQ(base::PLATFORM_FILE_OK
, helper
.Move(src
, dest
));
281 ASSERT_FALSE(helper
.FileExists(src
, AsyncFileTestHelper::kDontCheckSize
));
282 ASSERT_TRUE(helper
.FileExists(dest
, 10));
284 int64 src_new_usage
= helper
.GetSourceUsage();
285 ASSERT_EQ(src_initial_usage
, src_new_usage
);
287 int64 dest_increase
= helper
.GetDestUsage() - dest_initial_usage
;
288 ASSERT_EQ(src_increase
, dest_increase
);
291 TEST(LocalFileSystemCrossOperationTest
, CopySingleDirectory
) {
292 CrossOperationTestHelper
helper(GURL("http://foo"),
293 kFileSystemTypeTemporary
,
294 kFileSystemTypePersistent
);
297 FileSystemURL src
= helper
.SourceURL("a");
298 FileSystemURL dest
= helper
.DestURL("b");
299 int64 src_initial_usage
= helper
.GetSourceUsage();
300 int64 dest_initial_usage
= helper
.GetDestUsage();
302 // Set up a source directory.
303 ASSERT_EQ(base::PLATFORM_FILE_OK
, helper
.CreateDirectory(src
));
304 int64 src_increase
= helper
.GetSourceUsage() - src_initial_usage
;
307 ASSERT_EQ(base::PLATFORM_FILE_OK
, helper
.Copy(src
, dest
));
310 ASSERT_TRUE(helper
.DirectoryExists(src
));
311 ASSERT_TRUE(helper
.DirectoryExists(dest
));
313 int64 src_new_usage
= helper
.GetSourceUsage();
314 ASSERT_EQ(src_initial_usage
+ src_increase
, src_new_usage
);
316 int64 dest_increase
= helper
.GetDestUsage() - dest_initial_usage
;
317 ASSERT_EQ(src_increase
, dest_increase
);
320 TEST(LocalFileSystemCrossOperationTest
, MoveSingleDirectory
) {
321 CrossOperationTestHelper
helper(GURL("http://foo"),
322 kFileSystemTypeTemporary
,
323 kFileSystemTypePersistent
);
326 FileSystemURL src
= helper
.SourceURL("a");
327 FileSystemURL dest
= helper
.DestURL("b");
328 int64 src_initial_usage
= helper
.GetSourceUsage();
329 int64 dest_initial_usage
= helper
.GetDestUsage();
331 // Set up a source directory.
332 ASSERT_EQ(base::PLATFORM_FILE_OK
, helper
.CreateDirectory(src
));
333 int64 src_increase
= helper
.GetSourceUsage() - src_initial_usage
;
336 ASSERT_EQ(base::PLATFORM_FILE_OK
, helper
.Move(src
, dest
));
339 ASSERT_FALSE(helper
.DirectoryExists(src
));
340 ASSERT_TRUE(helper
.DirectoryExists(dest
));
342 int64 src_new_usage
= helper
.GetSourceUsage();
343 ASSERT_EQ(src_initial_usage
, src_new_usage
);
345 int64 dest_increase
= helper
.GetDestUsage() - dest_initial_usage
;
346 ASSERT_EQ(src_increase
, dest_increase
);
349 TEST(LocalFileSystemCrossOperationTest
, CopyDirectory
) {
350 CrossOperationTestHelper
helper(GURL("http://foo"),
351 kFileSystemTypeTemporary
,
352 kFileSystemTypePersistent
);
355 FileSystemURL src
= helper
.SourceURL("a");
356 FileSystemURL dest
= helper
.DestURL("b");
357 int64 src_initial_usage
= helper
.GetSourceUsage();
358 int64 dest_initial_usage
= helper
.GetDestUsage();
360 // Set up a source directory.
361 ASSERT_EQ(base::PLATFORM_FILE_OK
, helper
.CreateDirectory(src
));
362 ASSERT_EQ(base::PLATFORM_FILE_OK
,
363 helper
.SetUpTestCaseFiles(src
,
364 test::kRegularTestCases
,
365 test::kRegularTestCaseSize
));
366 int64 src_increase
= helper
.GetSourceUsage() - src_initial_usage
;
369 ASSERT_EQ(base::PLATFORM_FILE_OK
, helper
.Copy(src
, dest
));
372 ASSERT_TRUE(helper
.DirectoryExists(src
));
373 ASSERT_TRUE(helper
.DirectoryExists(dest
));
375 helper
.VerifyTestCaseFiles(dest
,
376 test::kRegularTestCases
,
377 test::kRegularTestCaseSize
);
379 int64 src_new_usage
= helper
.GetSourceUsage();
380 ASSERT_EQ(src_initial_usage
+ src_increase
, src_new_usage
);
382 int64 dest_increase
= helper
.GetDestUsage() - dest_initial_usage
;
383 ASSERT_EQ(src_increase
, dest_increase
);
386 TEST(LocalFileSystemCrossOperationTest
, MoveDirectory
) {
387 CrossOperationTestHelper
helper(GURL("http://foo"),
388 kFileSystemTypeTemporary
,
389 kFileSystemTypePersistent
);
392 FileSystemURL src
= helper
.SourceURL("a");
393 FileSystemURL dest
= helper
.DestURL("b");
394 int64 src_initial_usage
= helper
.GetSourceUsage();
395 int64 dest_initial_usage
= helper
.GetDestUsage();
397 // Set up a source directory.
398 ASSERT_EQ(base::PLATFORM_FILE_OK
, helper
.CreateDirectory(src
));
399 ASSERT_EQ(base::PLATFORM_FILE_OK
,
400 helper
.SetUpTestCaseFiles(src
,
401 test::kRegularTestCases
,
402 test::kRegularTestCaseSize
));
403 int64 src_increase
= helper
.GetSourceUsage() - src_initial_usage
;
406 ASSERT_EQ(base::PLATFORM_FILE_OK
, helper
.Move(src
, dest
));
409 ASSERT_FALSE(helper
.DirectoryExists(src
));
410 ASSERT_TRUE(helper
.DirectoryExists(dest
));
412 helper
.VerifyTestCaseFiles(dest
,
413 test::kRegularTestCases
,
414 test::kRegularTestCaseSize
);
416 int64 src_new_usage
= helper
.GetSourceUsage();
417 ASSERT_EQ(src_initial_usage
, src_new_usage
);
419 int64 dest_increase
= helper
.GetDestUsage() - dest_initial_usage
;
420 ASSERT_EQ(src_increase
, dest_increase
);
423 } // namespace fileapi