async_file_test_helper.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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.
4
5#include "base/bind.h"
6#include "base/files/file_util.h"
7#include "base/files/scoped_temp_dir.h"
8#include "base/run_loop.h"
9#include "content/public/test/async_file_test_helper.h"
10#include "storage/browser/fileapi/file_system_backend.h"
11#include "storage/browser/fileapi/file_system_context.h"
12#include "storage/browser/fileapi/file_system_operation_runner.h"
13#include "storage/browser/fileapi/file_system_url.h"
14#include "storage/browser/quota/quota_manager.h"
15#include "storage/common/fileapi/file_system_util.h"
16#include "testing/gtest/include/gtest/gtest.h"
17
18namespace content {
19
20typedef storage::FileSystemOperation::FileEntryList FileEntryList;
21
22namespace {
23
24void AssignAndQuit(base::RunLoop* run_loop,
25                   base::File::Error* result_out,
26                   base::File::Error result) {
27  *result_out = result;
28  run_loop->Quit();
29}
30
31base::Callback<void(base::File::Error)>
32AssignAndQuitCallback(base::RunLoop* run_loop,
33                      base::File::Error* result) {
34  return base::Bind(&AssignAndQuit, run_loop, base::Unretained(result));
35}
36
37void GetMetadataCallback(base::RunLoop* run_loop,
38                         base::File::Error* result_out,
39                         base::File::Info* file_info_out,
40                         base::File::Error result,
41                         const base::File::Info& file_info) {
42  *result_out = result;
43  if (file_info_out)
44    *file_info_out = file_info;
45  run_loop->Quit();
46}
47
48void CreateSnapshotFileCallback(
49    base::RunLoop* run_loop,
50    base::File::Error* result_out,
51    base::FilePath* platform_path_out,
52    base::File::Error result,
53    const base::File::Info& file_info,
54    const base::FilePath& platform_path,
55    const scoped_refptr<storage::ShareableFileReference>& file_ref) {
56  DCHECK(!file_ref.get());
57  *result_out = result;
58  if (platform_path_out)
59    *platform_path_out = platform_path;
60  run_loop->Quit();
61}
62
63void ReadDirectoryCallback(base::RunLoop* run_loop,
64                           base::File::Error* result_out,
65                           FileEntryList* entries_out,
66                           base::File::Error result,
67                           const FileEntryList& entries,
68                           bool has_more) {
69  *result_out = result;
70  entries_out->insert(entries_out->end(), entries.begin(), entries.end());
71  if (result != base::File::FILE_OK || !has_more)
72    run_loop->Quit();
73}
74
75void DidGetUsageAndQuota(storage::QuotaStatusCode* status_out,
76                         int64* usage_out,
77                         int64* quota_out,
78                         storage::QuotaStatusCode status,
79                         int64 usage,
80                         int64 quota) {
81  if (status_out)
82    *status_out = status;
83  if (usage_out)
84    *usage_out = usage;
85  if (quota_out)
86    *quota_out = quota;
87}
88
89}  // namespace
90
91const int64 AsyncFileTestHelper::kDontCheckSize = -1;
92
93base::File::Error AsyncFileTestHelper::Copy(
94    storage::FileSystemContext* context,
95    const storage::FileSystemURL& src,
96    const storage::FileSystemURL& dest) {
97  return CopyWithProgress(context, src, dest, CopyProgressCallback());
98}
99
100base::File::Error AsyncFileTestHelper::CopyWithProgress(
101    storage::FileSystemContext* context,
102    const storage::FileSystemURL& src,
103    const storage::FileSystemURL& dest,
104    const CopyProgressCallback& progress_callback) {
105  base::File::Error result = base::File::FILE_ERROR_FAILED;
106  base::RunLoop run_loop;
107  context->operation_runner()->Copy(src,
108                                    dest,
109                                    storage::FileSystemOperation::OPTION_NONE,
110                                    progress_callback,
111                                    AssignAndQuitCallback(&run_loop, &result));
112  run_loop.Run();
113  return result;
114}
115
116base::File::Error AsyncFileTestHelper::Move(
117    storage::FileSystemContext* context,
118    const storage::FileSystemURL& src,
119    const storage::FileSystemURL& dest) {
120  base::File::Error result = base::File::FILE_ERROR_FAILED;
121  base::RunLoop run_loop;
122  context->operation_runner()->Move(src,
123                                    dest,
124                                    storage::FileSystemOperation::OPTION_NONE,
125                                    AssignAndQuitCallback(&run_loop, &result));
126  run_loop.Run();
127  return result;
128}
129
130base::File::Error AsyncFileTestHelper::Remove(
131    storage::FileSystemContext* context,
132    const storage::FileSystemURL& url,
133    bool recursive) {
134  base::File::Error result = base::File::FILE_ERROR_FAILED;
135  base::RunLoop run_loop;
136  context->operation_runner()->Remove(
137      url, recursive, AssignAndQuitCallback(&run_loop, &result));
138  run_loop.Run();
139  return result;
140}
141
142base::File::Error AsyncFileTestHelper::ReadDirectory(
143    storage::FileSystemContext* context,
144    const storage::FileSystemURL& url,
145    FileEntryList* entries) {
146  base::File::Error result = base::File::FILE_ERROR_FAILED;
147  DCHECK(entries);
148  entries->clear();
149  base::RunLoop run_loop;
150  context->operation_runner()->ReadDirectory(
151      url, base::Bind(&ReadDirectoryCallback, &run_loop, &result, entries));
152  run_loop.Run();
153  return result;
154}
155
156base::File::Error AsyncFileTestHelper::CreateDirectory(
157    storage::FileSystemContext* context,
158    const storage::FileSystemURL& url) {
159  base::File::Error result = base::File::FILE_ERROR_FAILED;
160  base::RunLoop run_loop;
161  context->operation_runner()->CreateDirectory(
162      url,
163      false /* exclusive */,
164      false /* recursive */,
165      AssignAndQuitCallback(&run_loop, &result));
166  run_loop.Run();
167  return result;
168}
169
170base::File::Error AsyncFileTestHelper::CreateFile(
171    storage::FileSystemContext* context,
172    const storage::FileSystemURL& url) {
173  base::File::Error result = base::File::FILE_ERROR_FAILED;
174  base::RunLoop run_loop;
175  context->operation_runner()->CreateFile(
176      url, false /* exclusive */,
177      AssignAndQuitCallback(&run_loop, &result));
178  run_loop.Run();
179  return result;
180}
181
182base::File::Error AsyncFileTestHelper::CreateFileWithData(
183    storage::FileSystemContext* context,
184    const storage::FileSystemURL& url,
185    const char* buf,
186    int buf_size) {
187  base::ScopedTempDir dir;
188  if (!dir.CreateUniqueTempDir())
189    return base::File::FILE_ERROR_FAILED;
190  base::FilePath local_path = dir.path().AppendASCII("tmp");
191  if (buf_size != base::WriteFile(local_path, buf, buf_size))
192    return base::File::FILE_ERROR_FAILED;
193  base::File::Error result = base::File::FILE_ERROR_FAILED;
194  base::RunLoop run_loop;
195  context->operation_runner()->CopyInForeignFile(
196      local_path, url, AssignAndQuitCallback(&run_loop, &result));
197  run_loop.Run();
198  return result;
199}
200
201base::File::Error AsyncFileTestHelper::TruncateFile(
202    storage::FileSystemContext* context,
203    const storage::FileSystemURL& url,
204    size_t size) {
205  base::RunLoop run_loop;
206  base::File::Error result = base::File::FILE_ERROR_FAILED;
207  context->operation_runner()->Truncate(
208      url, size, AssignAndQuitCallback(&run_loop, &result));
209  run_loop.Run();
210  return result;
211}
212
213base::File::Error AsyncFileTestHelper::GetMetadata(
214    storage::FileSystemContext* context,
215    const storage::FileSystemURL& url,
216    base::File::Info* file_info) {
217  base::File::Error result = base::File::FILE_ERROR_FAILED;
218  base::RunLoop run_loop;
219  context->operation_runner()->GetMetadata(
220      url, base::Bind(&GetMetadataCallback, &run_loop, &result,
221                      file_info));
222  run_loop.Run();
223  return result;
224}
225
226base::File::Error AsyncFileTestHelper::GetPlatformPath(
227    storage::FileSystemContext* context,
228    const storage::FileSystemURL& url,
229    base::FilePath* platform_path) {
230  base::File::Error result = base::File::FILE_ERROR_FAILED;
231  base::RunLoop run_loop;
232  context->operation_runner()->CreateSnapshotFile(
233      url, base::Bind(&CreateSnapshotFileCallback, &run_loop, &result,
234                      platform_path));
235  run_loop.Run();
236  return result;
237}
238
239bool AsyncFileTestHelper::FileExists(storage::FileSystemContext* context,
240                                     const storage::FileSystemURL& url,
241                                     int64 expected_size) {
242  base::File::Info file_info;
243  base::File::Error result = GetMetadata(context, url, &file_info);
244  if (result != base::File::FILE_OK || file_info.is_directory)
245    return false;
246  return expected_size == kDontCheckSize || file_info.size == expected_size;
247}
248
249bool AsyncFileTestHelper::DirectoryExists(storage::FileSystemContext* context,
250                                          const storage::FileSystemURL& url) {
251  base::File::Info file_info;
252  base::File::Error result = GetMetadata(context, url, &file_info);
253  return (result == base::File::FILE_OK) && file_info.is_directory;
254}
255
256storage::QuotaStatusCode AsyncFileTestHelper::GetUsageAndQuota(
257    storage::QuotaManager* quota_manager,
258    const GURL& origin,
259    storage::FileSystemType type,
260    int64* usage,
261    int64* quota) {
262  storage::QuotaStatusCode status = storage::kQuotaStatusUnknown;
263  quota_manager->GetUsageAndQuota(
264      origin,
265      FileSystemTypeToQuotaStorageType(type),
266      base::Bind(&DidGetUsageAndQuota, &status, usage, quota));
267  base::RunLoop().RunUntilIdle();
268  return status;
269}
270
271}  // namespace storage
272