Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(249)

Side by Side Diff: content/browser/fileapi/recursive_operation_delegate_unittest.cc

Issue 2368913003: Populate storage_unittests target. (Closed)
Patch Set: Removed unnecessary include from storage/browser/blob/blob_storage_context_unittest.cc. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 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.
4
5 #include "storage/browser/fileapi/recursive_operation_delegate.h"
6
7 #include <memory>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/files/scoped_temp_dir.h"
13 #include "base/location.h"
14 #include "base/macros.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/run_loop.h"
17 #include "base/single_thread_task_runner.h"
18 #include "base/threading/thread_task_runner_handle.h"
19 #include "content/public/test/sandbox_file_system_test_helper.h"
20 #include "storage/browser/fileapi/file_system_file_util.h"
21 #include "storage/browser/fileapi/file_system_operation.h"
22 #include "storage/browser/fileapi/file_system_operation_runner.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24
25 using storage::FileSystemContext;
26 using storage::FileSystemOperationContext;
27 using storage::FileSystemURL;
28
29 namespace content {
30 namespace {
31
32 class LoggingRecursiveOperation : public storage::RecursiveOperationDelegate {
33 public:
34 struct LogEntry {
35 enum Type {
36 PROCESS_FILE,
37 PROCESS_DIRECTORY,
38 POST_PROCESS_DIRECTORY
39 };
40 Type type;
41 FileSystemURL url;
42 };
43
44 LoggingRecursiveOperation(FileSystemContext* file_system_context,
45 const FileSystemURL& root,
46 const StatusCallback& callback)
47 : storage::RecursiveOperationDelegate(file_system_context),
48 root_(root),
49 callback_(callback),
50 weak_factory_(this) {}
51 ~LoggingRecursiveOperation() override {}
52
53 const std::vector<LogEntry>& log_entries() const { return log_entries_; }
54
55 // RecursiveOperationDelegate overrides.
56 void Run() override { NOTREACHED(); }
57
58 void RunRecursively() override {
59 StartRecursiveOperation(
60 root_, storage::FileSystemOperation::ERROR_BEHAVIOR_ABORT, callback_);
61 }
62
63 void RunRecursivelyWithIgnoringError() {
64 StartRecursiveOperation(
65 root_, storage::FileSystemOperation::ERROR_BEHAVIOR_SKIP, callback_);
66 }
67
68 void ProcessFile(const FileSystemURL& url,
69 const StatusCallback& callback) override {
70 RecordLogEntry(LogEntry::PROCESS_FILE, url);
71
72 if (error_url_.is_valid() && error_url_ == url) {
73 callback.Run(base::File::FILE_ERROR_FAILED);
74 return;
75 }
76
77 operation_runner()->GetMetadata(
78 url, storage::FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY,
79 base::Bind(&LoggingRecursiveOperation::DidGetMetadata,
80 weak_factory_.GetWeakPtr(), callback));
81 }
82
83 void ProcessDirectory(const FileSystemURL& url,
84 const StatusCallback& callback) override {
85 RecordLogEntry(LogEntry::PROCESS_DIRECTORY, url);
86 callback.Run(base::File::FILE_OK);
87 }
88
89 void PostProcessDirectory(const FileSystemURL& url,
90 const StatusCallback& callback) override {
91 RecordLogEntry(LogEntry::POST_PROCESS_DIRECTORY, url);
92 callback.Run(base::File::FILE_OK);
93 }
94
95 void SetEntryToFail(const FileSystemURL& url) { error_url_ = url; }
96
97 private:
98 void RecordLogEntry(LogEntry::Type type, const FileSystemURL& url) {
99 LogEntry entry;
100 entry.type = type;
101 entry.url = url;
102 log_entries_.push_back(entry);
103 }
104
105 void DidGetMetadata(const StatusCallback& callback,
106 base::File::Error result,
107 const base::File::Info& file_info) {
108 if (result != base::File::FILE_OK) {
109 callback.Run(result);
110 return;
111 }
112
113 callback.Run(file_info.is_directory ?
114 base::File::FILE_ERROR_NOT_A_FILE :
115 base::File::FILE_OK);
116 }
117
118 FileSystemURL root_;
119 StatusCallback callback_;
120 std::vector<LogEntry> log_entries_;
121 FileSystemURL error_url_;
122
123 base::WeakPtrFactory<LoggingRecursiveOperation> weak_factory_;
124 DISALLOW_COPY_AND_ASSIGN(LoggingRecursiveOperation);
125 };
126
127 void ReportStatus(base::File::Error* out_error,
128 base::File::Error error) {
129 DCHECK(out_error);
130 *out_error = error;
131 }
132
133 // To test the Cancel() during operation, calls Cancel() of |operation|
134 // after |counter| times message posting.
135 void CallCancelLater(storage::RecursiveOperationDelegate* operation,
136 int counter) {
137 if (counter > 0) {
138 base::ThreadTaskRunnerHandle::Get()->PostTask(
139 FROM_HERE,
140 base::Bind(&CallCancelLater, base::Unretained(operation), counter - 1));
141 return;
142 }
143
144 operation->Cancel();
145 }
146
147 } // namespace
148
149 class RecursiveOperationDelegateTest : public testing::Test {
150 protected:
151 void SetUp() override {
152 EXPECT_TRUE(base_.CreateUniqueTempDir());
153 sandbox_file_system_.SetUp(base_.GetPath().AppendASCII("filesystem"));
154 }
155
156 void TearDown() override { sandbox_file_system_.TearDown(); }
157
158 std::unique_ptr<FileSystemOperationContext> NewContext() {
159 FileSystemOperationContext* context =
160 sandbox_file_system_.NewOperationContext();
161 // Grant enough quota for all test cases.
162 context->set_allowed_bytes_growth(1000000);
163 return base::WrapUnique(context);
164 }
165
166 storage::FileSystemFileUtil* file_util() {
167 return sandbox_file_system_.file_util();
168 }
169
170 FileSystemURL URLForPath(const std::string& path) const {
171 return sandbox_file_system_.CreateURLFromUTF8(path);
172 }
173
174 FileSystemURL CreateFile(const std::string& path) {
175 FileSystemURL url = URLForPath(path);
176 bool created = false;
177 EXPECT_EQ(base::File::FILE_OK,
178 file_util()->EnsureFileExists(NewContext().get(),
179 url, &created));
180 EXPECT_TRUE(created);
181 return url;
182 }
183
184 FileSystemURL CreateDirectory(const std::string& path) {
185 FileSystemURL url = URLForPath(path);
186 EXPECT_EQ(base::File::FILE_OK,
187 file_util()->CreateDirectory(NewContext().get(), url,
188 false /* exclusive */, true));
189 return url;
190 }
191
192 private:
193 base::MessageLoop message_loop_;
194
195 // Common temp base for nondestructive uses.
196 base::ScopedTempDir base_;
197 SandboxFileSystemTestHelper sandbox_file_system_;
198 };
199
200 TEST_F(RecursiveOperationDelegateTest, RootIsFile) {
201 FileSystemURL src_file(CreateFile("src"));
202
203 base::File::Error error = base::File::FILE_ERROR_FAILED;
204 std::unique_ptr<FileSystemOperationContext> context = NewContext();
205 std::unique_ptr<LoggingRecursiveOperation> operation(
206 new LoggingRecursiveOperation(context->file_system_context(), src_file,
207 base::Bind(&ReportStatus, &error)));
208 operation->RunRecursively();
209 base::RunLoop().RunUntilIdle();
210 ASSERT_EQ(base::File::FILE_OK, error);
211
212 const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries =
213 operation->log_entries();
214 ASSERT_EQ(1U, log_entries.size());
215 const LoggingRecursiveOperation::LogEntry& entry = log_entries[0];
216 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE, entry.type);
217 EXPECT_EQ(src_file, entry.url);
218 }
219
220 TEST_F(RecursiveOperationDelegateTest, RootIsDirectory) {
221 FileSystemURL src_root(CreateDirectory("src"));
222 FileSystemURL src_dir1(CreateDirectory("src/dir1"));
223 FileSystemURL src_file1(CreateFile("src/file1"));
224 FileSystemURL src_file2(CreateFile("src/dir1/file2"));
225 FileSystemURL src_file3(CreateFile("src/dir1/file3"));
226
227 base::File::Error error = base::File::FILE_ERROR_FAILED;
228 std::unique_ptr<FileSystemOperationContext> context = NewContext();
229 std::unique_ptr<LoggingRecursiveOperation> operation(
230 new LoggingRecursiveOperation(context->file_system_context(), src_root,
231 base::Bind(&ReportStatus, &error)));
232 operation->RunRecursively();
233 base::RunLoop().RunUntilIdle();
234 ASSERT_EQ(base::File::FILE_OK, error);
235
236 const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries =
237 operation->log_entries();
238 ASSERT_EQ(8U, log_entries.size());
239
240 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
241 log_entries[0].type);
242 EXPECT_EQ(src_root, log_entries[0].url);
243
244 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
245 log_entries[1].type);
246 EXPECT_EQ(src_root, log_entries[1].url);
247
248 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
249 log_entries[2].type);
250 EXPECT_EQ(src_file1, log_entries[2].url);
251
252 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
253 log_entries[3].type);
254 EXPECT_EQ(src_dir1, log_entries[3].url);
255
256 // The order of src/dir1/file2 and src/dir1/file3 depends on the file system
257 // implementation (can be swapped).
258 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
259 log_entries[4].type);
260 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
261 log_entries[5].type);
262 EXPECT_TRUE((src_file2 == log_entries[4].url &&
263 src_file3 == log_entries[5].url) ||
264 (src_file3 == log_entries[4].url &&
265 src_file2 == log_entries[5].url));
266
267 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY,
268 log_entries[6].type);
269 EXPECT_EQ(src_dir1, log_entries[6].url);
270
271 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY,
272 log_entries[7].type);
273 EXPECT_EQ(src_root, log_entries[7].url);
274 }
275
276 TEST_F(RecursiveOperationDelegateTest, Cancel) {
277 FileSystemURL src_root(CreateDirectory("src"));
278 FileSystemURL src_dir1(CreateDirectory("src/dir1"));
279 FileSystemURL src_file1(CreateFile("src/file1"));
280 FileSystemURL src_file2(CreateFile("src/dir1/file2"));
281
282 base::File::Error error = base::File::FILE_ERROR_FAILED;
283 std::unique_ptr<FileSystemOperationContext> context = NewContext();
284 std::unique_ptr<LoggingRecursiveOperation> operation(
285 new LoggingRecursiveOperation(context->file_system_context(), src_root,
286 base::Bind(&ReportStatus, &error)));
287 operation->RunRecursively();
288
289 // Invoke Cancel(), after 5 times message posting.
290 CallCancelLater(operation.get(), 5);
291 base::RunLoop().RunUntilIdle();
292 ASSERT_EQ(base::File::FILE_ERROR_ABORT, error);
293 }
294
295 TEST_F(RecursiveOperationDelegateTest, AbortWithError) {
296 FileSystemURL src_root(CreateDirectory("src"));
297 FileSystemURL src_dir1(CreateDirectory("src/dir1"));
298 FileSystemURL src_file1(CreateFile("src/file1"));
299 FileSystemURL src_file2(CreateFile("src/dir1/file2"));
300 FileSystemURL src_file3(CreateFile("src/dir1/file3"));
301
302 base::File::Error error = base::File::FILE_ERROR_FAILED;
303 std::unique_ptr<FileSystemOperationContext> context = NewContext();
304 std::unique_ptr<LoggingRecursiveOperation> operation(
305 new LoggingRecursiveOperation(context->file_system_context(), src_root,
306 base::Bind(&ReportStatus, &error)));
307 operation->SetEntryToFail(src_file1);
308 operation->RunRecursively();
309 base::RunLoop().RunUntilIdle();
310
311 ASSERT_EQ(base::File::FILE_ERROR_FAILED, error);
312
313 // Confirm that operation has been aborted in the middle.
314 const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries =
315 operation->log_entries();
316 ASSERT_EQ(3U, log_entries.size());
317
318 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
319 log_entries[0].type);
320 EXPECT_EQ(src_root, log_entries[0].url);
321
322 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
323 log_entries[1].type);
324 EXPECT_EQ(src_root, log_entries[1].url);
325
326 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
327 log_entries[2].type);
328 EXPECT_EQ(src_file1, log_entries[2].url);
329 }
330
331 TEST_F(RecursiveOperationDelegateTest, ContinueWithError) {
332 FileSystemURL src_root(CreateDirectory("src"));
333 FileSystemURL src_dir1(CreateDirectory("src/dir1"));
334 FileSystemURL src_file1(CreateFile("src/file1"));
335 FileSystemURL src_file2(CreateFile("src/dir1/file2"));
336 FileSystemURL src_file3(CreateFile("src/dir1/file3"));
337
338 base::File::Error error = base::File::FILE_ERROR_FAILED;
339 std::unique_ptr<FileSystemOperationContext> context = NewContext();
340 std::unique_ptr<LoggingRecursiveOperation> operation(
341 new LoggingRecursiveOperation(context->file_system_context(), src_root,
342 base::Bind(&ReportStatus, &error)));
343 operation->SetEntryToFail(src_file1);
344 operation->RunRecursivelyWithIgnoringError();
345 base::RunLoop().RunUntilIdle();
346
347 // Error code should be base::File::FILE_ERROR_FAILED.
348 ASSERT_EQ(base::File::FILE_ERROR_FAILED, error);
349
350 // Confirm that operation continues after the error.
351 const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries =
352 operation->log_entries();
353 ASSERT_EQ(8U, log_entries.size());
354
355 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
356 log_entries[0].type);
357 EXPECT_EQ(src_root, log_entries[0].url);
358
359 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
360 log_entries[1].type);
361 EXPECT_EQ(src_root, log_entries[1].url);
362
363 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
364 log_entries[2].type);
365 EXPECT_EQ(src_file1, log_entries[2].url);
366
367 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
368 log_entries[3].type);
369 EXPECT_EQ(src_dir1, log_entries[3].url);
370
371 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
372 log_entries[4].type);
373 EXPECT_EQ(src_file3, log_entries[4].url);
374
375 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
376 log_entries[5].type);
377 EXPECT_EQ(src_file2, log_entries[5].url);
378
379 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY,
380 log_entries[6].type);
381 EXPECT_EQ(src_dir1, log_entries[6].url);
382
383 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY,
384 log_entries[7].type);
385 EXPECT_EQ(src_root, log_entries[7].url);
386 }
387
388 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698