IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / browser / fileapi / recursive_operation_delegate_unittest.cc
blobd3671fe89f8d9ab53ec6f174c9a929f9534bb3e5
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 namespace fileapi {
23 namespace {
25 class LoggingRecursiveOperation : public RecursiveOperationDelegate {
26 public:
27 struct LogEntry {
28 enum Type {
29 PROCESS_FILE,
30 PROCESS_DIRECTORY,
31 POST_PROCESS_DIRECTORY
33 Type type;
34 FileSystemURL url;
37 LoggingRecursiveOperation(FileSystemContext* file_system_context,
38 const FileSystemURL& root,
39 const StatusCallback& callback)
40 : RecursiveOperationDelegate(file_system_context),
41 root_(root),
42 callback_(callback),
43 weak_factory_(this) {
45 virtual ~LoggingRecursiveOperation() {}
47 const std::vector<LogEntry>& log_entries() const { return log_entries_; }
49 // RecursiveOperationDelegate overrides.
50 virtual void Run() OVERRIDE {
51 NOTREACHED();
54 virtual void RunRecursively() OVERRIDE {
55 StartRecursiveOperation(root_, callback_);
58 virtual 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 virtual void ProcessDirectory(const FileSystemURL& url,
68 const StatusCallback& callback) OVERRIDE {
69 RecordLogEntry(LogEntry::PROCESS_DIRECTORY, url);
70 callback.Run(base::PLATFORM_FILE_OK);
73 virtual void PostProcessDirectory(const FileSystemURL& url,
74 const StatusCallback& callback) OVERRIDE {
75 RecordLogEntry(LogEntry::POST_PROCESS_DIRECTORY, url);
76 callback.Run(base::PLATFORM_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::PlatformFileError result,
89 const base::PlatformFileInfo& file_info) {
90 if (result != base::PLATFORM_FILE_OK) {
91 callback.Run(result);
92 return;
95 callback.Run(file_info.is_directory ?
96 base::PLATFORM_FILE_ERROR_NOT_A_FILE :
97 base::PLATFORM_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::PlatformFileError* out_error,
109 base::PlatformFileError 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(RecursiveOperationDelegate* operation, int counter) {
117 if (counter > 0) {
118 base::MessageLoopProxy::current()->PostTask(
119 FROM_HERE,
120 base::Bind(&CallCancelLater, base::Unretained(operation), counter - 1));
121 return;
124 operation->Cancel();
127 } // namespace
129 class RecursiveOperationDelegateTest : public testing::Test {
130 protected:
131 virtual void SetUp() OVERRIDE {
132 EXPECT_TRUE(base_.CreateUniqueTempDir());
133 sandbox_file_system_.SetUp(base_.path().AppendASCII("filesystem"));
136 virtual void TearDown() OVERRIDE {
137 sandbox_file_system_.TearDown();
140 scoped_ptr<FileSystemOperationContext> NewContext() {
141 FileSystemOperationContext* context =
142 sandbox_file_system_.NewOperationContext();
143 // Grant enough quota for all test cases.
144 context->set_allowed_bytes_growth(1000000);
145 return make_scoped_ptr(context);
148 FileSystemFileUtil* file_util() {
149 return sandbox_file_system_.file_util();
152 FileSystemURL URLForPath(const std::string& path) const {
153 return sandbox_file_system_.CreateURLFromUTF8(path);
156 FileSystemURL CreateFile(const std::string& path) {
157 FileSystemURL url = URLForPath(path);
158 bool created = false;
159 EXPECT_EQ(base::PLATFORM_FILE_OK,
160 file_util()->EnsureFileExists(NewContext().get(),
161 url, &created));
162 EXPECT_TRUE(created);
163 return url;
166 FileSystemURL CreateDirectory(const std::string& path) {
167 FileSystemURL url = URLForPath(path);
168 EXPECT_EQ(base::PLATFORM_FILE_OK,
169 file_util()->CreateDirectory(NewContext().get(), url,
170 false /* exclusive */, true));
171 return url;
174 private:
175 base::MessageLoop message_loop_;
177 // Common temp base for nondestructive uses.
178 base::ScopedTempDir base_;
179 SandboxFileSystemTestHelper sandbox_file_system_;
182 TEST_F(RecursiveOperationDelegateTest, RootIsFile) {
183 FileSystemURL src_file(CreateFile("src"));
185 base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
186 scoped_ptr<FileSystemOperationContext> context = NewContext();
187 scoped_ptr<LoggingRecursiveOperation> operation(
188 new LoggingRecursiveOperation(
189 context->file_system_context(), src_file,
190 base::Bind(&ReportStatus, &error)));
191 operation->RunRecursively();
192 base::RunLoop().RunUntilIdle();
193 ASSERT_EQ(base::PLATFORM_FILE_OK, error);
195 const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries =
196 operation->log_entries();
197 ASSERT_EQ(1U, log_entries.size());
198 const LoggingRecursiveOperation::LogEntry& entry = log_entries[0];
199 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE, entry.type);
200 EXPECT_EQ(src_file, entry.url);
203 TEST_F(RecursiveOperationDelegateTest, RootIsDirectory) {
204 FileSystemURL src_root(CreateDirectory("src"));
205 FileSystemURL src_dir1(CreateDirectory("src/dir1"));
206 FileSystemURL src_file1(CreateFile("src/file1"));
207 FileSystemURL src_file2(CreateFile("src/dir1/file2"));
208 FileSystemURL src_file3(CreateFile("src/dir1/file3"));
210 base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
211 scoped_ptr<FileSystemOperationContext> context = NewContext();
212 scoped_ptr<LoggingRecursiveOperation> operation(
213 new LoggingRecursiveOperation(
214 context->file_system_context(), src_root,
215 base::Bind(&ReportStatus, &error)));
216 operation->RunRecursively();
217 base::RunLoop().RunUntilIdle();
218 ASSERT_EQ(base::PLATFORM_FILE_OK, error);
220 const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries =
221 operation->log_entries();
222 ASSERT_EQ(8U, log_entries.size());
224 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
225 log_entries[0].type);
226 EXPECT_EQ(src_root, log_entries[0].url);
228 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
229 log_entries[1].type);
230 EXPECT_EQ(src_root, log_entries[1].url);
232 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
233 log_entries[2].type);
234 EXPECT_EQ(src_file1, log_entries[2].url);
236 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
237 log_entries[3].type);
238 EXPECT_EQ(src_dir1, log_entries[3].url);
240 // The order of src/dir1/file2 and src/dir1/file3 depends on the file system
241 // implementation (can be swapped).
242 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
243 log_entries[4].type);
244 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
245 log_entries[5].type);
246 EXPECT_TRUE((src_file2 == log_entries[4].url &&
247 src_file3 == log_entries[5].url) ||
248 (src_file3 == log_entries[4].url &&
249 src_file2 == log_entries[5].url));
251 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY,
252 log_entries[6].type);
253 EXPECT_EQ(src_dir1, log_entries[6].url);
255 EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY,
256 log_entries[7].type);
257 EXPECT_EQ(src_root, log_entries[7].url);
260 TEST_F(RecursiveOperationDelegateTest, Cancel) {
261 FileSystemURL src_root(CreateDirectory("src"));
262 FileSystemURL src_dir1(CreateDirectory("src/dir1"));
263 FileSystemURL src_file1(CreateFile("src/file1"));
264 FileSystemURL src_file2(CreateFile("src/dir1/file2"));
266 base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
267 scoped_ptr<FileSystemOperationContext> context = NewContext();
268 scoped_ptr<LoggingRecursiveOperation> operation(
269 new LoggingRecursiveOperation(
270 context->file_system_context(), src_root,
271 base::Bind(&ReportStatus, &error)));
272 operation->RunRecursively();
274 // Invoke Cancel(), after 5 times message posting.
275 CallCancelLater(operation.get(), 5);
276 base::RunLoop().RunUntilIdle();
277 ASSERT_EQ(base::PLATFORM_FILE_ERROR_ABORT, error);
280 } // namespace fileapi