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

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

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

Powered by Google App Engine
This is Rietveld 408576698