OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "base/stl_util.h" | |
6 #include "testing/gtest/include/gtest/gtest.h" | |
7 #include "webkit/browser/fileapi/file_system_context.h" | |
8 #include "webkit/browser/fileapi/file_system_file_util.h" | |
9 #include "webkit/browser/fileapi/file_system_operation_context.h" | |
10 #include "webkit/browser/fileapi/file_system_task_runners.h" | |
11 #include "webkit/browser/fileapi/isolated_context.h" | |
12 #include "webkit/browser/fileapi/local_file_system_operation.h" | |
13 #include "webkit/browser/fileapi/sandbox_file_system_test_helper.h" | |
14 #include "webkit/common/fileapi/file_system_types.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" | |
21 | |
22 using base::PlatformFileError; | |
23 using fileapi::FileSystemContext; | |
24 using fileapi::FileSystemOperationContext; | |
25 using fileapi::FileSystemURL; | |
26 using fileapi::FileSystemURLSet; | |
27 using fileapi::SandboxFileSystemTestHelper; | |
28 using quota::QuotaManager; | |
29 using quota::QuotaStatusCode; | |
30 | |
31 namespace sync_file_system { | |
32 | |
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) {} | |
40 | |
41 virtual void SetUp() { | |
42 file_system_.SetUp(); | |
43 | |
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_)); | |
48 } | |
49 | |
50 virtual void TearDown() { | |
51 if (sync_context_) | |
52 sync_context_->ShutdownOnUIThread(); | |
53 sync_context_ = NULL; | |
54 | |
55 file_system_.TearDown(); | |
56 | |
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"); | |
61 } | |
62 | |
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()); | |
75 | |
76 // Clear the URL from the change tracker. | |
77 change_tracker()->ClearChangesForURL(url); | |
78 } | |
79 | |
80 FileSystemURL URL(const std::string& path) { | |
81 return file_system_.URL(path); | |
82 } | |
83 | |
84 FileSystemContext* file_system_context() { | |
85 return file_system_.file_system_context(); | |
86 } | |
87 | |
88 LocalFileChangeTracker* change_tracker() { | |
89 return file_system_context()->change_tracker(); | |
90 } | |
91 | |
92 base::ScopedTempDir data_dir_; | |
93 base::MessageLoop message_loop_; | |
94 | |
95 CannedSyncableFileSystem file_system_; | |
96 scoped_refptr<LocalFileSyncContext> sync_context_; | |
97 | |
98 base::WeakPtrFactory<SyncableFileSystemTest> weak_factory_; | |
99 | |
100 DISALLOW_COPY_AND_ASSIGN(SyncableFileSystemTest); | |
101 }; | |
102 | |
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()); | |
108 | |
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"))); | |
114 | |
115 const int64 kOriginalQuota = QuotaManager::kSyncableStorageDefaultHostQuota; | |
116 | |
117 const int64 kQuota = 12345 * 1024; | |
118 QuotaManager::kSyncableStorageDefaultHostQuota = kQuota; | |
119 int64 usage, quota; | |
120 EXPECT_EQ(quota::kQuotaStatusOk, | |
121 file_system_.GetUsageAndQuota(&usage, "a)); | |
122 | |
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); | |
127 | |
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"))); | |
132 | |
133 EXPECT_EQ(base::PLATFORM_FILE_OK, | |
134 file_system_.TruncateFile(URL("dir/foo"), kFileSizeToExtend)); | |
135 | |
136 int64 new_usage; | |
137 EXPECT_EQ(quota::kQuotaStatusOk, | |
138 file_system_.GetUsageAndQuota(&new_usage, "a)); | |
139 EXPECT_EQ(kFileSizeToExtend, new_usage - usage); | |
140 | |
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)); | |
146 | |
147 usage = new_usage; | |
148 EXPECT_EQ(quota::kQuotaStatusOk, | |
149 file_system_.GetUsageAndQuota(&new_usage, "a)); | |
150 EXPECT_EQ(usage, new_usage); | |
151 | |
152 // Deletes the file system. | |
153 EXPECT_EQ(base::PLATFORM_FILE_OK, | |
154 file_system_.DeleteFileSystem()); | |
155 | |
156 // Now the usage must be zero. | |
157 EXPECT_EQ(quota::kQuotaStatusOk, | |
158 file_system_.GetUsageAndQuota(&usage, "a)); | |
159 EXPECT_EQ(0, usage); | |
160 | |
161 // Restore the system default quota. | |
162 QuotaManager::kSyncableStorageDefaultHostQuota = kOriginalQuota; | |
163 } | |
164 | |
165 // Combined testing with LocalFileChangeTracker. | |
166 TEST_F(SyncableFileSystemTest, ChangeTrackerSimple) { | |
167 EXPECT_EQ(base::PLATFORM_FILE_OK, | |
168 file_system_.OpenFileSystem()); | |
169 | |
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"; | |
174 | |
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. | |
186 | |
187 FileSystemURLSet urls; | |
188 file_system_.GetChangedURLsInTracker(&urls); | |
189 | |
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))); | |
194 | |
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)); | |
204 | |
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 */)); | |
210 | |
211 // The changes will be offset. | |
212 urls.clear(); | |
213 file_system_.GetChangedURLsInTracker(&urls); | |
214 EXPECT_TRUE(urls.empty()); | |
215 | |
216 // Recursively removes the kPath0 directory. | |
217 EXPECT_EQ(base::PLATFORM_FILE_OK, | |
218 file_system_.Remove(URL(kPath0), true /* recursive */)); | |
219 | |
220 urls.clear(); | |
221 file_system_.GetChangedURLsInTracker(&urls); | |
222 | |
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))); | |
228 | |
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)); | |
238 } | |
239 | |
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()); | |
245 | |
246 // Try some directory operations (which should fail). | |
247 EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, | |
248 file_system_.CreateDirectory(URL("dir"))); | |
249 | |
250 // Set up another (non-syncable) local file system. | |
251 SandboxFileSystemTestHelper other_file_system_( | |
252 GURL("http://foo.com/"), fileapi::kFileSystemTypeTemporary); | |
253 other_file_system_.SetUp(file_system_.file_system_context()); | |
254 | |
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"); | |
258 | |
259 bool created = false; | |
260 scoped_ptr<FileSystemOperationContext> operation_context; | |
261 | |
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 */)); | |
268 | |
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); | |
275 | |
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"))); | |
280 | |
281 other_file_system_.TearDown(); | |
282 } | |
283 | |
284 } // namespace sync_file_system | |
OLD | NEW |