Only sync parent directory once after a leveldb file rename.
[chromium-blink-merge.git] / webkit / fileapi / syncable / syncable_file_system_unittest.cc
blob51edd4d6ce194295bd1d3edf1a5298a62d7eefe0
1 // Copyright (c) 2012 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 "base/stl_util.h"
6 #include "testing/gtest/include/gtest/gtest.h"
7 #include "webkit/fileapi/file_system_context.h"
8 #include "webkit/fileapi/file_system_file_util.h"
9 #include "webkit/fileapi/file_system_operation_context.h"
10 #include "webkit/fileapi/file_system_task_runners.h"
11 #include "webkit/fileapi/file_system_types.h"
12 #include "webkit/fileapi/isolated_context.h"
13 #include "webkit/fileapi/local_file_system_operation.h"
14 #include "webkit/fileapi/local_file_system_test_helper.h"
15 #include "webkit/fileapi/syncable/canned_syncable_file_system.h"
16 #include "webkit/fileapi/syncable/local_file_change_tracker.h"
17 #include "webkit/fileapi/syncable/local_file_sync_context.h"
18 #include "webkit/fileapi/syncable/syncable_file_system_util.h"
19 #include "webkit/quota/quota_manager.h"
20 #include "webkit/quota/quota_types.h"
22 using base::PlatformFileError;
23 using fileapi::FileSystemContext;
24 using fileapi::FileSystemOperationContext;
25 using fileapi::FileSystemURL;
26 using fileapi::FileSystemURLSet;
27 using fileapi::LocalFileSystemTestOriginHelper;
28 using quota::QuotaManager;
29 using quota::QuotaStatusCode;
31 namespace sync_file_system {
33 class SyncableFileSystemTest : public testing::Test {
34 public:
35 SyncableFileSystemTest()
36 : file_system_(GURL("http://example.com/"), "test",
37 base::MessageLoopProxy::current(),
38 base::MessageLoopProxy::current()),
39 weak_factory_(this) {}
41 virtual void SetUp() {
42 file_system_.SetUp();
44 sync_context_ = new LocalFileSyncContext(base::MessageLoopProxy::current(),
45 base::MessageLoopProxy::current());
46 ASSERT_EQ(sync_file_system::SYNC_STATUS_OK,
47 file_system_.MaybeInitializeFileSystemContext(sync_context_));
50 virtual void TearDown() {
51 if (sync_context_)
52 sync_context_->ShutdownOnUIThread();
53 sync_context_ = NULL;
55 file_system_.TearDown();
57 // Make sure we don't leave the external filesystem.
58 // (CannedSyncableFileSystem::TearDown does not do this as there may be
59 // multiple syncable file systems registered for the name)
60 RevokeSyncableFileSystem("test");
63 protected:
64 void VerifyAndClearChange(const FileSystemURL& url,
65 const FileChange& expected_change) {
66 SCOPED_TRACE(testing::Message() << url.DebugString() <<
67 " expecting:" << expected_change.DebugString());
68 // Get the changes for URL and verify.
69 FileChangeList changes;
70 change_tracker()->GetChangesForURL(url, &changes);
71 ASSERT_EQ(1U, changes.size());
72 SCOPED_TRACE(testing::Message() << url.DebugString() <<
73 " actual:" << changes.DebugString());
74 EXPECT_EQ(expected_change, changes.front());
76 // Clear the URL from the change tracker.
77 change_tracker()->ClearChangesForURL(url);
80 FileSystemURL URL(const std::string& path) {
81 return file_system_.URL(path);
84 FileSystemContext* file_system_context() {
85 return file_system_.file_system_context();
88 LocalFileChangeTracker* change_tracker() {
89 return file_system_context()->change_tracker();
92 base::ScopedTempDir data_dir_;
93 base::MessageLoop message_loop_;
95 CannedSyncableFileSystem file_system_;
96 scoped_refptr<LocalFileSyncContext> sync_context_;
98 base::WeakPtrFactory<SyncableFileSystemTest> weak_factory_;
100 DISALLOW_COPY_AND_ASSIGN(SyncableFileSystemTest);
103 // Brief combined testing. Just see if all the sandbox feature works.
104 TEST_F(SyncableFileSystemTest, SyncableLocalSandboxCombined) {
105 // Opens a syncable file system.
106 EXPECT_EQ(base::PLATFORM_FILE_OK,
107 file_system_.OpenFileSystem());
109 // Do some operations.
110 EXPECT_EQ(base::PLATFORM_FILE_OK,
111 file_system_.CreateDirectory(URL("dir")));
112 EXPECT_EQ(base::PLATFORM_FILE_OK,
113 file_system_.CreateFile(URL("dir/foo")));
115 const int64 kOriginalQuota = QuotaManager::kSyncableStorageDefaultHostQuota;
117 const int64 kQuota = 12345 * 1024;
118 QuotaManager::kSyncableStorageDefaultHostQuota = kQuota;
119 int64 usage, quota;
120 EXPECT_EQ(quota::kQuotaStatusOk,
121 file_system_.GetUsageAndQuota(&usage, &quota));
123 // Returned quota must be what we overrode. Usage must be greater than 0
124 // as creating a file or directory consumes some space.
125 EXPECT_EQ(kQuota, quota);
126 EXPECT_GT(usage, 0);
128 // Truncate to extend an existing file and see if the usage reflects it.
129 const int64 kFileSizeToExtend = 333;
130 EXPECT_EQ(base::PLATFORM_FILE_OK,
131 file_system_.CreateFile(URL("dir/foo")));
133 EXPECT_EQ(base::PLATFORM_FILE_OK,
134 file_system_.TruncateFile(URL("dir/foo"), kFileSizeToExtend));
136 int64 new_usage;
137 EXPECT_EQ(quota::kQuotaStatusOk,
138 file_system_.GetUsageAndQuota(&new_usage, &quota));
139 EXPECT_EQ(kFileSizeToExtend, new_usage - usage);
141 // Shrink the quota to the current usage, try to extend the file further
142 // and see if it fails.
143 QuotaManager::kSyncableStorageDefaultHostQuota = new_usage;
144 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
145 file_system_.TruncateFile(URL("dir/foo"), kFileSizeToExtend + 1));
147 usage = new_usage;
148 EXPECT_EQ(quota::kQuotaStatusOk,
149 file_system_.GetUsageAndQuota(&new_usage, &quota));
150 EXPECT_EQ(usage, new_usage);
152 // Deletes the file system.
153 EXPECT_EQ(base::PLATFORM_FILE_OK,
154 file_system_.DeleteFileSystem());
156 // Now the usage must be zero.
157 EXPECT_EQ(quota::kQuotaStatusOk,
158 file_system_.GetUsageAndQuota(&usage, &quota));
159 EXPECT_EQ(0, usage);
161 // Restore the system default quota.
162 QuotaManager::kSyncableStorageDefaultHostQuota = kOriginalQuota;
165 // Combined testing with LocalFileChangeTracker.
166 TEST_F(SyncableFileSystemTest, ChangeTrackerSimple) {
167 EXPECT_EQ(base::PLATFORM_FILE_OK,
168 file_system_.OpenFileSystem());
170 const char kPath0[] = "dir a";
171 const char kPath1[] = "dir a/dir"; // child of kPath0
172 const char kPath2[] = "dir a/file"; // child of kPath0
173 const char kPath3[] = "dir b";
175 // Do some operations.
176 EXPECT_EQ(base::PLATFORM_FILE_OK,
177 file_system_.CreateDirectory(URL(kPath0))); // Creates a dir.
178 EXPECT_EQ(base::PLATFORM_FILE_OK,
179 file_system_.CreateDirectory(URL(kPath1))); // Creates another.
180 EXPECT_EQ(base::PLATFORM_FILE_OK,
181 file_system_.CreateFile(URL(kPath2))); // Creates a file.
182 EXPECT_EQ(base::PLATFORM_FILE_OK,
183 file_system_.TruncateFile(URL(kPath2), 1)); // Modifies the file.
184 EXPECT_EQ(base::PLATFORM_FILE_OK,
185 file_system_.TruncateFile(URL(kPath2), 2)); // Modifies it again.
187 FileSystemURLSet urls;
188 file_system_.GetChangedURLsInTracker(&urls);
190 EXPECT_EQ(3U, urls.size());
191 EXPECT_TRUE(ContainsKey(urls, URL(kPath0)));
192 EXPECT_TRUE(ContainsKey(urls, URL(kPath1)));
193 EXPECT_TRUE(ContainsKey(urls, URL(kPath2)));
195 VerifyAndClearChange(URL(kPath0),
196 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
197 sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
198 VerifyAndClearChange(URL(kPath1),
199 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
200 sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
201 VerifyAndClearChange(URL(kPath2),
202 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
203 sync_file_system::SYNC_FILE_TYPE_FILE));
205 // Creates and removes a same directory.
206 EXPECT_EQ(base::PLATFORM_FILE_OK,
207 file_system_.CreateDirectory(URL(kPath3)));
208 EXPECT_EQ(base::PLATFORM_FILE_OK,
209 file_system_.Remove(URL(kPath3), false /* recursive */));
211 // The changes will be offset.
212 urls.clear();
213 file_system_.GetChangedURLsInTracker(&urls);
214 EXPECT_TRUE(urls.empty());
216 // Recursively removes the kPath0 directory.
217 EXPECT_EQ(base::PLATFORM_FILE_OK,
218 file_system_.Remove(URL(kPath0), true /* recursive */));
220 urls.clear();
221 file_system_.GetChangedURLsInTracker(&urls);
223 // kPath0 and its all chidren (kPath1 and kPath2) must have been deleted.
224 EXPECT_EQ(3U, urls.size());
225 EXPECT_TRUE(ContainsKey(urls, URL(kPath0)));
226 EXPECT_TRUE(ContainsKey(urls, URL(kPath1)));
227 EXPECT_TRUE(ContainsKey(urls, URL(kPath2)));
229 VerifyAndClearChange(URL(kPath0),
230 FileChange(FileChange::FILE_CHANGE_DELETE,
231 sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
232 VerifyAndClearChange(URL(kPath1),
233 FileChange(FileChange::FILE_CHANGE_DELETE,
234 sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
235 VerifyAndClearChange(URL(kPath2),
236 FileChange(FileChange::FILE_CHANGE_DELETE,
237 sync_file_system::SYNC_FILE_TYPE_FILE));
240 // Make sure directory operation is disabled (when it's configured so).
241 TEST_F(SyncableFileSystemTest, DisableDirectoryOperations) {
242 SetEnableSyncFSDirectoryOperation(false);
243 EXPECT_EQ(base::PLATFORM_FILE_OK,
244 file_system_.OpenFileSystem());
246 // Try some directory operations (which should fail).
247 EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION,
248 file_system_.CreateDirectory(URL("dir")));
250 // Set up another (non-syncable) local file system.
251 LocalFileSystemTestOriginHelper other_file_system_(
252 GURL("http://foo.com/"), fileapi::kFileSystemTypeTemporary);
253 other_file_system_.SetUp(file_system_.file_system_context());
255 // Create directory '/a' and file '/a/b' in the other file system.
256 const FileSystemURL kSrcDir = other_file_system_.CreateURLFromUTF8("/a");
257 const FileSystemURL kSrcChild = other_file_system_.CreateURLFromUTF8("/a/b");
259 bool created = false;
260 scoped_ptr<FileSystemOperationContext> operation_context;
262 operation_context.reset(other_file_system_.NewOperationContext());
263 operation_context->set_allowed_bytes_growth(1024);
264 EXPECT_EQ(base::PLATFORM_FILE_OK,
265 other_file_system_.file_util()->CreateDirectory(
266 operation_context.get(),
267 kSrcDir, false /* exclusive */, false /* recursive */));
269 operation_context.reset(other_file_system_.NewOperationContext());
270 operation_context->set_allowed_bytes_growth(1024);
271 EXPECT_EQ(base::PLATFORM_FILE_OK,
272 other_file_system_.file_util()->EnsureFileExists(
273 operation_context.get(), kSrcChild, &created));
274 EXPECT_TRUE(created);
276 // Now try copying the directory into the syncable file system, which should
277 // fail if directory operation is disabled. (http://crbug.com/161442)
278 EXPECT_NE(base::PLATFORM_FILE_OK,
279 file_system_.Copy(kSrcDir, URL("dest")));
281 other_file_system_.TearDown();
284 } // namespace sync_file_system