Remove PlatformFile from profile_browsertest
[chromium-blink-merge.git] / content / browser / fileapi / recursive_operation_delegate_unittest.cc
bloba96a21213a23431842b025dd28bfc653db189cf0
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 "webkit/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/message_loop/message_loop.h"
14 #include "base/message_loop/message_loop_proxy.h"
15 #include "base/run_loop.h"
16 #include "content/public/test/sandbox_file_system_test_helper.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "webkit/browser/fileapi/file_system_file_util.h"
19 #include "webkit/browser/fileapi/file_system_operation.h"
20 #include "webkit/browser/fileapi/file_system_operation_runner.h"
22 using fileapi::FileSystemContext;
23 using fileapi::FileSystemOperationContext;
24 using fileapi::FileSystemURL;
26 namespace content {
27 namespace {
29 class LoggingRecursiveOperation : public fileapi::RecursiveOperationDelegate {
30 public:
31 struct LogEntry {
32 enum Type {
33 PROCESS_FILE,
34 PROCESS_DIRECTORY,
35 POST_PROCESS_DIRECTORY
37 Type type;
38 FileSystemURL url;
41 LoggingRecursiveOperation(FileSystemContext* file_system_context,
42 const FileSystemURL& root,
43 const StatusCallback& callback)
44 : fileapi::RecursiveOperationDelegate(file_system_context),
45 root_(root),
46 callback_(callback),
47 weak_factory_(this) {
49 virtual ~LoggingRecursiveOperation() {}
51 const std::vector<LogEntry>& log_entries() const { return log_entries_; }
53 // RecursiveOperationDelegate overrides.
54 virtual void Run() OVERRIDE {
55 NOTREACHED();
58 virtual void RunRecursively() OVERRIDE {
59 StartRecursiveOperation(root_, callback_);
62 virtual void ProcessFile(const FileSystemURL& url,
63 const StatusCallback& callback) OVERRIDE {
64 RecordLogEntry(LogEntry::PROCESS_FILE, url);
65 operation_runner()->GetMetadata(
66 url,
67 base::Bind(&LoggingRecursiveOperation::DidGetMetadata,
68 weak_factory_.GetWeakPtr(), callback));
71 virtual void ProcessDirectory(const FileSystemURL& url,
72 const StatusCallback& callback) OVERRIDE {
73 RecordLogEntry(LogEntry::PROCESS_DIRECTORY, url);
74 callback.Run(base::File::FILE_OK);
77 virtual void PostProcessDirectory(const FileSystemURL& url,
78 const StatusCallback& callback) OVERRIDE {
79 RecordLogEntry(LogEntry::POST_PROCESS_DIRECTORY, url);
80 callback.Run(base::File::FILE_OK);
83 private:
84 void RecordLogEntry(LogEntry::Type type, const FileSystemURL& url) {
85 LogEntry entry;
86 entry.type = type;
87 entry.url = url;
88 log_entries_.push_back(entry);
91 void DidGetMetadata(const StatusCallback& callback,
92 base::File::Error result,
93 const base::File::Info& file_info) {
94 if (result != base::File::FILE_OK) {
95 callback.Run(result);
96 return;
99 callback.Run(file_info.is_directory ?
100 base::File::FILE_ERROR_NOT_A_FILE :
101 base::File::FILE_OK);
104 FileSystemURL root_;
105 StatusCallback callback_;
106 std::vector<LogEntry> log_entries_;
108 base::WeakPtrFactory<LoggingRecursiveOperation> weak_factory_;
109 DISALLOW_COPY_AND_ASSIGN(LoggingRecursiveOperation);
112 void ReportStatus(base::File::Error* out_error,
113 base::File::Error error) {
114 DCHECK(out_error);
115 *out_error = error;
118 // To test the Cancel() during operation, calls Cancel() of |operation|
119 // after |counter| times message posting.
120 void CallCancelLater(fileapi::RecursiveOperationDelegate* operation,
121 int counter) {
122 if (counter > 0) {
123 base::MessageLoopProxy::current()->PostTask(
124 FROM_HERE,
125 base::Bind(&CallCancelLater, base::Unretained(operation), counter - 1));
126 return;
129 operation->Cancel();
132 } // namespace
134 class RecursiveOperationDelegateTest : public testing::Test {
135 protected:
136 virtual void SetUp() OVERRIDE {
137 EXPECT_TRUE(base_.CreateUniqueTempDir());
138 sandbox_file_system_.SetUp(base_.path().AppendASCII("filesystem"));
141 virtual void TearDown() OVERRIDE {
142 sandbox_file_system_.TearDown();
145 scoped_ptr<FileSystemOperationContext> NewContext() {
146 FileSystemOperationContext* context =
147 sandbox_file_system_.NewOperationContext();
148 // Grant enough quota for all test cases.
149 context->set_allowed_bytes_growth(1000000);
150 return make_scoped_ptr(context);
153 fileapi::FileSystemFileUtil* file_util() {
154 return sandbox_file_system_.file_util();
157 FileSystemURL URLForPath(const std::string& path) const {
158 return sandbox_file_system_.CreateURLFromUTF8(path);
161 FileSystemURL CreateFile(const std::string& path) {
162 FileSystemURL url = URLForPath(path);
163 bool created = false;
164 EXPECT_EQ(base::File::FILE_OK,
165 file_util()->EnsureFileExists(NewContext().get(),
166 url, &created));
167 EXPECT_TRUE(created);
168 return url;
171 FileSystemURL CreateDirectory(const std::string& path) {
172 FileSystemURL url = URLForPath(path);
173 EXPECT_EQ(base::File::FILE_OK,
174 file_util()->CreateDirectory(NewContext().get(), url,
175 false /* exclusive */, true));
176 return url;
179 private:
180 base::MessageLoop message_loop_;
182 // Common temp base for nondestructive uses.
183 base::ScopedTempDir base_;
184 SandboxFileSystemTestHelper sandbox_file_system_;
187 TEST_F(RecursiveOperationDelegateTest, RootIsFile) {
188 FileSystemURL src_file(CreateFile("src"));
190 base::File::Error error = base::File::FILE_ERROR_FAILED;
191 scoped_ptr<FileSystemOperationContext> context = NewContext();
192 scoped_ptr<LoggingRecursiveOperation> operation(
193 new LoggingRecursiveOperation(
194 context->file_system_context(), src_file,
195 base::Bind(&ReportStatus, &error)));
196 operation->RunRecursively();
197 base::RunLoop().RunUntilIdle();
198 ASSERT_EQ(base::File::FILE_OK, error);
200 const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries =
201 operation->log_entries();
202 ASSERT_EQ(1U, log_entries.size());
203 const LoggingRecursiveOperation::LogEntry& entry = log_entries[0];
204 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE, entry.type);
205 EXPECT_EQ(src_file, entry.url);
208 TEST_F(RecursiveOperationDelegateTest, RootIsDirectory) {
209 FileSystemURL src_root(CreateDirectory("src"));
210 FileSystemURL src_dir1(CreateDirectory("src/dir1"));
211 FileSystemURL src_file1(CreateFile("src/file1"));
212 FileSystemURL src_file2(CreateFile("src/dir1/file2"));
213 FileSystemURL src_file3(CreateFile("src/dir1/file3"));
215 base::File::Error error = base::File::FILE_ERROR_FAILED;
216 scoped_ptr<FileSystemOperationContext> context = NewContext();
217 scoped_ptr<LoggingRecursiveOperation> operation(
218 new LoggingRecursiveOperation(
219 context->file_system_context(), src_root,
220 base::Bind(&ReportStatus, &error)));
221 operation->RunRecursively();
222 base::RunLoop().RunUntilIdle();
223 ASSERT_EQ(base::File::FILE_OK, error);
225 const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries =
226 operation->log_entries();
227 ASSERT_EQ(8U, log_entries.size());
229 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
230 log_entries[0].type);
231 EXPECT_EQ(src_root, log_entries[0].url);
233 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
234 log_entries[1].type);
235 EXPECT_EQ(src_root, log_entries[1].url);
237 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
238 log_entries[2].type);
239 EXPECT_EQ(src_file1, log_entries[2].url);
241 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
242 log_entries[3].type);
243 EXPECT_EQ(src_dir1, log_entries[3].url);
245 // The order of src/dir1/file2 and src/dir1/file3 depends on the file system
246 // implementation (can be swapped).
247 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
248 log_entries[4].type);
249 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
250 log_entries[5].type);
251 EXPECT_TRUE((src_file2 == log_entries[4].url &&
252 src_file3 == log_entries[5].url) ||
253 (src_file3 == log_entries[4].url &&
254 src_file2 == log_entries[5].url));
256 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY,
257 log_entries[6].type);
258 EXPECT_EQ(src_dir1, log_entries[6].url);
260 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY,
261 log_entries[7].type);
262 EXPECT_EQ(src_root, log_entries[7].url);
265 TEST_F(RecursiveOperationDelegateTest, Cancel) {
266 FileSystemURL src_root(CreateDirectory("src"));
267 FileSystemURL src_dir1(CreateDirectory("src/dir1"));
268 FileSystemURL src_file1(CreateFile("src/file1"));
269 FileSystemURL src_file2(CreateFile("src/dir1/file2"));
271 base::File::Error error = base::File::FILE_ERROR_FAILED;
272 scoped_ptr<FileSystemOperationContext> context = NewContext();
273 scoped_ptr<LoggingRecursiveOperation> operation(
274 new LoggingRecursiveOperation(
275 context->file_system_context(), src_root,
276 base::Bind(&ReportStatus, &error)));
277 operation->RunRecursively();
279 // Invoke Cancel(), after 5 times message posting.
280 CallCancelLater(operation.get(), 5);
281 base::RunLoop().RunUntilIdle();
282 ASSERT_EQ(base::File::FILE_ERROR_ABORT, error);
285 } // namespace content