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