chrome/browser/extensions: Remove use of MessageLoopProxy and deprecated MessageLoop...
[chromium-blink-merge.git] / content / browser / fileapi / recursive_operation_delegate_unittest.cc
blob54b9626ae0d5126ef17caa39af640d668d346297
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.
5 #include "storage/browser/fileapi/recursive_operation_delegate.h"
7 #include <vector>
9 #include "base/basictypes.h"
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/run_loop.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/thread_task_runner_handle.h"
17 #include "content/public/test/sandbox_file_system_test_helper.h"
18 #include "storage/browser/fileapi/file_system_file_util.h"
19 #include "storage/browser/fileapi/file_system_operation.h"
20 #include "storage/browser/fileapi/file_system_operation_runner.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 using storage::FileSystemContext;
24 using storage::FileSystemOperationContext;
25 using storage::FileSystemURL;
27 namespace content {
28 namespace {
30 class LoggingRecursiveOperation : public storage::RecursiveOperationDelegate {
31 public:
32 struct LogEntry {
33 enum Type {
34 PROCESS_FILE,
35 PROCESS_DIRECTORY,
36 POST_PROCESS_DIRECTORY
38 Type type;
39 FileSystemURL url;
42 LoggingRecursiveOperation(FileSystemContext* file_system_context,
43 const FileSystemURL& root,
44 const StatusCallback& callback)
45 : storage::RecursiveOperationDelegate(file_system_context),
46 root_(root),
47 callback_(callback),
48 weak_factory_(this) {}
49 ~LoggingRecursiveOperation() override {}
51 const std::vector<LogEntry>& log_entries() const { return log_entries_; }
53 // RecursiveOperationDelegate overrides.
54 void Run() override { NOTREACHED(); }
56 void RunRecursively() override { StartRecursiveOperation(root_, callback_); }
58 void ProcessFile(const FileSystemURL& url,
59 const StatusCallback& callback) override {
60 RecordLogEntry(LogEntry::PROCESS_FILE, url);
61 operation_runner()->GetMetadata(
62 url,
63 base::Bind(&LoggingRecursiveOperation::DidGetMetadata,
64 weak_factory_.GetWeakPtr(), callback));
67 void ProcessDirectory(const FileSystemURL& url,
68 const StatusCallback& callback) override {
69 RecordLogEntry(LogEntry::PROCESS_DIRECTORY, url);
70 callback.Run(base::File::FILE_OK);
73 void PostProcessDirectory(const FileSystemURL& url,
74 const StatusCallback& callback) override {
75 RecordLogEntry(LogEntry::POST_PROCESS_DIRECTORY, url);
76 callback.Run(base::File::FILE_OK);
79 private:
80 void RecordLogEntry(LogEntry::Type type, const FileSystemURL& url) {
81 LogEntry entry;
82 entry.type = type;
83 entry.url = url;
84 log_entries_.push_back(entry);
87 void DidGetMetadata(const StatusCallback& callback,
88 base::File::Error result,
89 const base::File::Info& file_info) {
90 if (result != base::File::FILE_OK) {
91 callback.Run(result);
92 return;
95 callback.Run(file_info.is_directory ?
96 base::File::FILE_ERROR_NOT_A_FILE :
97 base::File::FILE_OK);
100 FileSystemURL root_;
101 StatusCallback callback_;
102 std::vector<LogEntry> log_entries_;
104 base::WeakPtrFactory<LoggingRecursiveOperation> weak_factory_;
105 DISALLOW_COPY_AND_ASSIGN(LoggingRecursiveOperation);
108 void ReportStatus(base::File::Error* out_error,
109 base::File::Error error) {
110 DCHECK(out_error);
111 *out_error = error;
114 // To test the Cancel() during operation, calls Cancel() of |operation|
115 // after |counter| times message posting.
116 void CallCancelLater(storage::RecursiveOperationDelegate* operation,
117 int counter) {
118 if (counter > 0) {
119 base::ThreadTaskRunnerHandle::Get()->PostTask(
120 FROM_HERE,
121 base::Bind(&CallCancelLater, base::Unretained(operation), counter - 1));
122 return;
125 operation->Cancel();
128 } // namespace
130 class RecursiveOperationDelegateTest : public testing::Test {
131 protected:
132 void SetUp() override {
133 EXPECT_TRUE(base_.CreateUniqueTempDir());
134 sandbox_file_system_.SetUp(base_.path().AppendASCII("filesystem"));
137 void TearDown() override { sandbox_file_system_.TearDown(); }
139 scoped_ptr<FileSystemOperationContext> NewContext() {
140 FileSystemOperationContext* context =
141 sandbox_file_system_.NewOperationContext();
142 // Grant enough quota for all test cases.
143 context->set_allowed_bytes_growth(1000000);
144 return make_scoped_ptr(context);
147 storage::FileSystemFileUtil* file_util() {
148 return sandbox_file_system_.file_util();
151 FileSystemURL URLForPath(const std::string& path) const {
152 return sandbox_file_system_.CreateURLFromUTF8(path);
155 FileSystemURL CreateFile(const std::string& path) {
156 FileSystemURL url = URLForPath(path);
157 bool created = false;
158 EXPECT_EQ(base::File::FILE_OK,
159 file_util()->EnsureFileExists(NewContext().get(),
160 url, &created));
161 EXPECT_TRUE(created);
162 return url;
165 FileSystemURL CreateDirectory(const std::string& path) {
166 FileSystemURL url = URLForPath(path);
167 EXPECT_EQ(base::File::FILE_OK,
168 file_util()->CreateDirectory(NewContext().get(), url,
169 false /* exclusive */, true));
170 return url;
173 private:
174 base::MessageLoop message_loop_;
176 // Common temp base for nondestructive uses.
177 base::ScopedTempDir base_;
178 SandboxFileSystemTestHelper sandbox_file_system_;
181 TEST_F(RecursiveOperationDelegateTest, RootIsFile) {
182 FileSystemURL src_file(CreateFile("src"));
184 base::File::Error error = base::File::FILE_ERROR_FAILED;
185 scoped_ptr<FileSystemOperationContext> context = NewContext();
186 scoped_ptr<LoggingRecursiveOperation> operation(
187 new LoggingRecursiveOperation(
188 context->file_system_context(), src_file,
189 base::Bind(&ReportStatus, &error)));
190 operation->RunRecursively();
191 base::RunLoop().RunUntilIdle();
192 ASSERT_EQ(base::File::FILE_OK, error);
194 const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries =
195 operation->log_entries();
196 ASSERT_EQ(1U, log_entries.size());
197 const LoggingRecursiveOperation::LogEntry& entry = log_entries[0];
198 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE, entry.type);
199 EXPECT_EQ(src_file, entry.url);
202 TEST_F(RecursiveOperationDelegateTest, RootIsDirectory) {
203 FileSystemURL src_root(CreateDirectory("src"));
204 FileSystemURL src_dir1(CreateDirectory("src/dir1"));
205 FileSystemURL src_file1(CreateFile("src/file1"));
206 FileSystemURL src_file2(CreateFile("src/dir1/file2"));
207 FileSystemURL src_file3(CreateFile("src/dir1/file3"));
209 base::File::Error error = base::File::FILE_ERROR_FAILED;
210 scoped_ptr<FileSystemOperationContext> context = NewContext();
211 scoped_ptr<LoggingRecursiveOperation> operation(
212 new LoggingRecursiveOperation(
213 context->file_system_context(), src_root,
214 base::Bind(&ReportStatus, &error)));
215 operation->RunRecursively();
216 base::RunLoop().RunUntilIdle();
217 ASSERT_EQ(base::File::FILE_OK, error);
219 const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries =
220 operation->log_entries();
221 ASSERT_EQ(8U, log_entries.size());
223 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
224 log_entries[0].type);
225 EXPECT_EQ(src_root, log_entries[0].url);
227 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
228 log_entries[1].type);
229 EXPECT_EQ(src_root, log_entries[1].url);
231 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
232 log_entries[2].type);
233 EXPECT_EQ(src_file1, log_entries[2].url);
235 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
236 log_entries[3].type);
237 EXPECT_EQ(src_dir1, log_entries[3].url);
239 // The order of src/dir1/file2 and src/dir1/file3 depends on the file system
240 // implementation (can be swapped).
241 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
242 log_entries[4].type);
243 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
244 log_entries[5].type);
245 EXPECT_TRUE((src_file2 == log_entries[4].url &&
246 src_file3 == log_entries[5].url) ||
247 (src_file3 == log_entries[4].url &&
248 src_file2 == log_entries[5].url));
250 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY,
251 log_entries[6].type);
252 EXPECT_EQ(src_dir1, log_entries[6].url);
254 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY,
255 log_entries[7].type);
256 EXPECT_EQ(src_root, log_entries[7].url);
259 TEST_F(RecursiveOperationDelegateTest, Cancel) {
260 FileSystemURL src_root(CreateDirectory("src"));
261 FileSystemURL src_dir1(CreateDirectory("src/dir1"));
262 FileSystemURL src_file1(CreateFile("src/file1"));
263 FileSystemURL src_file2(CreateFile("src/dir1/file2"));
265 base::File::Error error = base::File::FILE_ERROR_FAILED;
266 scoped_ptr<FileSystemOperationContext> context = NewContext();
267 scoped_ptr<LoggingRecursiveOperation> operation(
268 new LoggingRecursiveOperation(
269 context->file_system_context(), src_root,
270 base::Bind(&ReportStatus, &error)));
271 operation->RunRecursively();
273 // Invoke Cancel(), after 5 times message posting.
274 CallCancelLater(operation.get(), 5);
275 base::RunLoop().RunUntilIdle();
276 ASSERT_EQ(base::File::FILE_ERROR_ABORT, error);
279 } // namespace content