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