Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync_file_system / local / syncable_file_system_unittest.cc
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
24 using base::PlatformFileError;
25 using content::SandboxFileSystemTestHelper;
26 using fileapi::FileSystemContext;
27 using fileapi::FileSystemOperationContext;
28 using fileapi::FileSystemURL;
29 using fileapi::FileSystemURLSet;
30 using quota::QuotaManager;
31 using quota::QuotaStatusCode;
32
33 namespace sync_file_system {
34
35 class 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.
117 TEST_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, &quota));
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, &quota));
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, &quota));
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, &quota));
172   EXPECT_EQ(0, usage);
173
174   // Restore the system default quota.
175   QuotaManager::kSyncableStorageDefaultHostQuota = kOriginalQuota;
176 }
177
178 // Combined testing with LocalFileChangeTracker.
179 TEST_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).
254 TEST_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