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