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