Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / sync_file_system / local / local_file_change_tracker_unittest.cc
blob8c91a3aa0ac9db65f943f4fac0670f0f97bfefdc
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.
5 #include "chrome/browser/sync_file_system/local/local_file_change_tracker.h"
7 #include <deque>
8 #include <set>
10 #include "base/basictypes.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/stl_util.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "chrome/browser/sync_file_system/local/canned_syncable_file_system.h"
17 #include "chrome/browser/sync_file_system/local/local_file_sync_context.h"
18 #include "chrome/browser/sync_file_system/local/sync_file_system_backend.h"
19 #include "chrome/browser/sync_file_system/sync_status_code.h"
20 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
21 #include "content/public/test/mock_blob_url_request_context.h"
22 #include "storage/browser/fileapi/file_system_context.h"
23 #include "storage/browser/quota/quota_manager.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
26 #include "third_party/leveldatabase/src/include/leveldb/env.h"
28 using storage::FileSystemContext;
29 using storage::FileSystemURL;
30 using storage::FileSystemURLSet;
31 using content::MockBlobURLRequestContext;
32 using content::ScopedTextBlob;
34 namespace sync_file_system {
36 class LocalFileChangeTrackerTest : public testing::Test {
37 public:
38 LocalFileChangeTrackerTest()
39 : in_memory_env_(leveldb::NewMemEnv(leveldb::Env::Default())),
40 file_system_(GURL("http://example.com"),
41 in_memory_env_.get(),
42 base::ThreadTaskRunnerHandle::Get().get(),
43 base::ThreadTaskRunnerHandle::Get().get()) {}
45 void SetUp() override {
46 file_system_.SetUp(CannedSyncableFileSystem::QUOTA_ENABLED);
48 ASSERT_TRUE(base_dir_.CreateUniqueTempDir());
49 sync_context_ =
50 new LocalFileSyncContext(base_dir_.path(),
51 in_memory_env_.get(),
52 base::ThreadTaskRunnerHandle::Get().get(),
53 base::ThreadTaskRunnerHandle::Get().get());
54 ASSERT_EQ(
55 sync_file_system::SYNC_STATUS_OK,
56 file_system_.MaybeInitializeFileSystemContext(sync_context_.get()));
59 void TearDown() override {
60 if (sync_context_.get())
61 sync_context_->ShutdownOnUIThread();
62 sync_context_ = nullptr;
64 message_loop_.RunUntilIdle();
65 file_system_.TearDown();
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();
72 protected:
73 FileSystemURL URL(const std::string& path) {
74 return file_system_.URL(path);
77 FileSystemContext* file_system_context() {
78 return file_system_.file_system_context();
81 LocalFileChangeTracker* change_tracker() {
82 return file_system_.backend()->change_tracker();
85 void VerifyAndClearChange(const FileSystemURL& url,
86 const FileChange& expected_change) {
87 SCOPED_TRACE(testing::Message() << url.DebugString() <<
88 " expecting:" << expected_change.DebugString());
89 // Get the changes for URL and verify.
90 FileChangeList changes;
91 change_tracker()->GetChangesForURL(url, &changes);
92 ASSERT_EQ(1U, changes.size());
93 SCOPED_TRACE(testing::Message() << url.DebugString() <<
94 " actual:" << changes.DebugString());
95 EXPECT_EQ(expected_change, changes.list()[0]);
97 // Clear the URL from the change tracker.
98 change_tracker()->ClearChangesForURL(url);
101 void DropChangesInTracker() {
102 change_tracker()->DropAllChanges();
105 void RestoreChangesFromTrackerDB() {
106 change_tracker()->CollectLastDirtyChanges(file_system_context());
109 void GetAllChangedURLs(storage::FileSystemURLSet* urls) {
110 change_tracker()->GetAllChangedURLs(urls);
113 base::MessageLoopForIO message_loop_;
114 base::ScopedTempDir base_dir_;
115 scoped_ptr<leveldb::Env> in_memory_env_;
116 CannedSyncableFileSystem file_system_;
118 private:
119 scoped_refptr<LocalFileSyncContext> sync_context_;
121 DISALLOW_COPY_AND_ASSIGN(LocalFileChangeTrackerTest);
124 TEST_F(LocalFileChangeTrackerTest, DemoteAndPromote) {
125 EXPECT_EQ(base::File::FILE_OK, file_system_.OpenFileSystem());
127 const char kPath[] = "foo/bar";
128 change_tracker()->OnCreateDirectory(URL(kPath));
130 FileSystemURLSet urls;
131 file_system_.GetChangedURLsInTracker(&urls);
132 ASSERT_EQ(1u, urls.size());
133 EXPECT_EQ(URL(kPath), *urls.begin());
135 change_tracker()->DemoteChangesForURL(URL(kPath));
137 file_system_.GetChangedURLsInTracker(&urls);
138 ASSERT_TRUE(urls.empty());
140 change_tracker()->PromoteDemotedChangesForURL(URL(kPath));
142 file_system_.GetChangedURLsInTracker(&urls);
143 ASSERT_EQ(1u, urls.size());
144 EXPECT_EQ(URL(kPath), *urls.begin());
146 change_tracker()->DemoteChangesForURL(URL(kPath));
147 change_tracker()->OnRemoveDirectory(URL(kPath));
149 file_system_.GetChangedURLsInTracker(&urls);
150 ASSERT_TRUE(urls.empty());
153 TEST_F(LocalFileChangeTrackerTest, GetChanges) {
154 EXPECT_EQ(base::File::FILE_OK, file_system_.OpenFileSystem());
156 // Test URLs (no parent/child relationships, as we test such cases
157 // mainly in LocalFileSyncStatusTest).
158 const char kPath0[] = "test/dir a/dir";
159 const char kPath1[] = "test/dir b";
160 const char kPath2[] = "test/foo.txt";
161 const char kPath3[] = "test/bar";
162 const char kPath4[] = "temporary/dir a";
163 const char kPath5[] = "temporary/foo";
165 change_tracker()->OnCreateDirectory(URL(kPath0));
166 change_tracker()->OnRemoveDirectory(URL(kPath0)); // Offset the create.
167 change_tracker()->OnRemoveDirectory(URL(kPath1));
168 change_tracker()->OnCreateDirectory(URL(kPath2));
169 change_tracker()->OnRemoveFile(URL(kPath3));
170 change_tracker()->OnModifyFile(URL(kPath4));
171 change_tracker()->OnCreateFile(URL(kPath5));
172 change_tracker()->OnRemoveFile(URL(kPath5)); // Recorded as 'delete'.
174 FileSystemURLSet urls;
175 file_system_.GetChangedURLsInTracker(&urls);
177 EXPECT_EQ(5U, urls.size());
178 EXPECT_TRUE(ContainsKey(urls, URL(kPath1)));
179 EXPECT_TRUE(ContainsKey(urls, URL(kPath2)));
180 EXPECT_TRUE(ContainsKey(urls, URL(kPath3)));
181 EXPECT_TRUE(ContainsKey(urls, URL(kPath4)));
182 EXPECT_TRUE(ContainsKey(urls, URL(kPath5)));
184 // Changes for kPath0 must have been offset and removed.
185 EXPECT_FALSE(ContainsKey(urls, URL(kPath0)));
187 // GetNextChangedURLs only returns up to max_urls (i.e. 3) urls.
188 std::deque<FileSystemURL> urls_to_process;
189 change_tracker()->GetNextChangedURLs(&urls_to_process, 3);
190 ASSERT_EQ(3U, urls_to_process.size());
192 // Let it return all.
193 urls_to_process.clear();
194 change_tracker()->GetNextChangedURLs(&urls_to_process, 0);
195 ASSERT_EQ(5U, urls_to_process.size());
197 // The changes must be in the last-modified-time order.
198 EXPECT_EQ(URL(kPath1), urls_to_process[0]);
199 EXPECT_EQ(URL(kPath2), urls_to_process[1]);
200 EXPECT_EQ(URL(kPath3), urls_to_process[2]);
201 EXPECT_EQ(URL(kPath4), urls_to_process[3]);
202 EXPECT_EQ(URL(kPath5), urls_to_process[4]);
204 // Modify kPath4 again.
205 change_tracker()->OnModifyFile(URL(kPath4));
207 // Now the order must be changed.
208 urls_to_process.clear();
209 change_tracker()->GetNextChangedURLs(&urls_to_process, 0);
210 ASSERT_EQ(5U, urls_to_process.size());
211 EXPECT_EQ(URL(kPath1), urls_to_process[0]);
212 EXPECT_EQ(URL(kPath2), urls_to_process[1]);
213 EXPECT_EQ(URL(kPath3), urls_to_process[2]);
214 EXPECT_EQ(URL(kPath5), urls_to_process[3]);
215 EXPECT_EQ(URL(kPath4), urls_to_process[4]);
217 // No changes to promote yet, we've demoted no changes.
218 EXPECT_FALSE(change_tracker()->PromoteDemotedChanges());
220 // Demote changes for kPath1 and kPath3.
221 change_tracker()->DemoteChangesForURL(URL(kPath1));
222 change_tracker()->DemoteChangesForURL(URL(kPath3));
224 // Now we'll get no changes for kPath1 and kPath3 (it's in a separate queue).
225 urls_to_process.clear();
226 change_tracker()->GetNextChangedURLs(&urls_to_process, 0);
227 ASSERT_EQ(3U, urls_to_process.size());
228 EXPECT_EQ(URL(kPath2), urls_to_process[0]);
229 EXPECT_EQ(URL(kPath5), urls_to_process[1]);
230 EXPECT_EQ(URL(kPath4), urls_to_process[2]);
232 // Promote changes.
233 EXPECT_TRUE(change_tracker()->PromoteDemotedChanges());
235 // Now we should have kPath1 and kPath3.
236 urls_to_process.clear();
237 change_tracker()->GetNextChangedURLs(&urls_to_process, 0);
238 ASSERT_EQ(5U, urls_to_process.size());
239 EXPECT_EQ(URL(kPath1), urls_to_process[0]);
240 EXPECT_EQ(URL(kPath2), urls_to_process[1]);
241 EXPECT_EQ(URL(kPath3), urls_to_process[2]);
242 EXPECT_EQ(URL(kPath5), urls_to_process[3]);
243 EXPECT_EQ(URL(kPath4), urls_to_process[4]);
245 // No changes to promote any more.
246 EXPECT_FALSE(change_tracker()->PromoteDemotedChanges());
249 VerifyAndClearChange(URL(kPath1),
250 FileChange(FileChange::FILE_CHANGE_DELETE,
251 sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
252 VerifyAndClearChange(URL(kPath2),
253 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
254 sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
255 VerifyAndClearChange(URL(kPath3),
256 FileChange(FileChange::FILE_CHANGE_DELETE,
257 sync_file_system::SYNC_FILE_TYPE_FILE));
258 VerifyAndClearChange(URL(kPath4),
259 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
260 sync_file_system::SYNC_FILE_TYPE_FILE));
261 VerifyAndClearChange(URL(kPath5),
262 FileChange(FileChange::FILE_CHANGE_DELETE,
263 sync_file_system::SYNC_FILE_TYPE_FILE));
266 TEST_F(LocalFileChangeTrackerTest, RestoreCreateAndModifyChanges) {
267 EXPECT_EQ(base::File::FILE_OK, file_system_.OpenFileSystem());
269 FileSystemURLSet urls;
271 const char kPath0[] = "file a";
272 const char kPath1[] = "dir a";
273 const char kPath2[] = "dir a/dir";
274 const char kPath3[] = "dir a/file a";
275 const char kPath4[] = "dir a/file b";
277 file_system_.GetChangedURLsInTracker(&urls);
278 ASSERT_EQ(0U, urls.size());
280 const std::string kData("Lorem ipsum.");
281 MockBlobURLRequestContext url_request_context(file_system_context());
282 ScopedTextBlob blob(url_request_context, "blob_id:test", kData);
284 // Create files and nested directories.
285 EXPECT_EQ(base::File::FILE_OK,
286 file_system_.CreateFile(URL(kPath0))); // Creates a file.
287 EXPECT_EQ(base::File::FILE_OK,
288 file_system_.CreateDirectory(URL(kPath1))); // Creates a dir.
289 EXPECT_EQ(base::File::FILE_OK,
290 file_system_.CreateDirectory(URL(kPath2))); // Creates another dir.
291 EXPECT_EQ(base::File::FILE_OK,
292 file_system_.CreateFile(URL(kPath3))); // Creates a file.
293 EXPECT_EQ(base::File::FILE_OK,
294 file_system_.TruncateFile(URL(kPath3), 1)); // Modifies the file.
295 EXPECT_EQ(base::File::FILE_OK,
296 file_system_.CreateFile(URL(kPath4))); // Creates another file.
297 EXPECT_EQ(static_cast<int64>(kData.size()), // Modifies the file.
298 file_system_.Write(&url_request_context,
299 URL(kPath4), blob.GetBlobDataHandle()));
301 // Verify the changes.
302 file_system_.GetChangedURLsInTracker(&urls);
303 EXPECT_EQ(5U, urls.size());
305 // Reset the changes in in-memory tracker.
306 DropChangesInTracker();
308 // Make sure we have no in-memory changes in the tracker.
309 file_system_.GetChangedURLsInTracker(&urls);
310 ASSERT_EQ(0U, urls.size());
312 RestoreChangesFromTrackerDB();
314 // Make sure the changes are restored from the DB.
315 file_system_.GetChangedURLsInTracker(&urls);
316 EXPECT_EQ(5U, urls.size());
318 VerifyAndClearChange(URL(kPath0),
319 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
320 sync_file_system::SYNC_FILE_TYPE_FILE));
321 VerifyAndClearChange(URL(kPath1),
322 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
323 sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
324 VerifyAndClearChange(URL(kPath2),
325 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
326 sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
327 VerifyAndClearChange(URL(kPath3),
328 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
329 sync_file_system::SYNC_FILE_TYPE_FILE));
330 VerifyAndClearChange(URL(kPath4),
331 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
332 sync_file_system::SYNC_FILE_TYPE_FILE));
335 TEST_F(LocalFileChangeTrackerTest, RestoreRemoveChanges) {
336 EXPECT_EQ(base::File::FILE_OK, file_system_.OpenFileSystem());
338 FileSystemURLSet urls;
340 const char kPath0[] = "file";
341 const char kPath1[] = "dir a";
342 const char kPath2[] = "dir b";
343 const char kPath3[] = "dir b/file";
344 const char kPath4[] = "dir b/dir c";
345 const char kPath5[] = "dir b/dir c/file";
347 file_system_.GetChangedURLsInTracker(&urls);
348 ASSERT_EQ(0U, urls.size());
350 // Creates and removes a same file.
351 EXPECT_EQ(base::File::FILE_OK,
352 file_system_.CreateFile(URL(kPath0)));
353 EXPECT_EQ(base::File::FILE_OK,
354 file_system_.Remove(URL(kPath0), false /* recursive */));
356 // Creates and removes a same directory.
357 EXPECT_EQ(base::File::FILE_OK,
358 file_system_.CreateDirectory(URL(kPath1)));
359 EXPECT_EQ(base::File::FILE_OK,
360 file_system_.Remove(URL(kPath1), false /* recursive */));
362 // Creates files and nested directories, then removes the parent directory.
363 EXPECT_EQ(base::File::FILE_OK,
364 file_system_.CreateDirectory(URL(kPath2)));
365 EXPECT_EQ(base::File::FILE_OK,
366 file_system_.CreateFile(URL(kPath3)));
367 EXPECT_EQ(base::File::FILE_OK,
368 file_system_.CreateDirectory(URL(kPath4)));
369 EXPECT_EQ(base::File::FILE_OK,
370 file_system_.CreateFile(URL(kPath5)));
371 EXPECT_EQ(base::File::FILE_OK,
372 file_system_.Remove(URL(kPath2), true /* recursive */));
374 file_system_.GetChangedURLsInTracker(&urls);
375 EXPECT_EQ(3U, urls.size());
377 DropChangesInTracker();
379 // Make sure we have no in-memory changes in the tracker.
380 file_system_.GetChangedURLsInTracker(&urls);
381 ASSERT_EQ(0U, urls.size());
383 RestoreChangesFromTrackerDB();
385 // Make sure the changes are restored from the DB.
386 file_system_.GetChangedURLsInTracker(&urls);
387 // Since directories to have been reverted (kPath1, kPath2, kPath4) are
388 // treated as FILE_CHANGE_DELETE, the number of changes should be 6.
389 EXPECT_EQ(6U, urls.size());
391 VerifyAndClearChange(URL(kPath0),
392 FileChange(FileChange::FILE_CHANGE_DELETE,
393 sync_file_system::SYNC_FILE_TYPE_UNKNOWN));
394 VerifyAndClearChange(URL(kPath1),
395 FileChange(FileChange::FILE_CHANGE_DELETE,
396 sync_file_system::SYNC_FILE_TYPE_UNKNOWN));
397 VerifyAndClearChange(URL(kPath2),
398 FileChange(FileChange::FILE_CHANGE_DELETE,
399 sync_file_system::SYNC_FILE_TYPE_UNKNOWN));
400 VerifyAndClearChange(URL(kPath3),
401 FileChange(FileChange::FILE_CHANGE_DELETE,
402 sync_file_system::SYNC_FILE_TYPE_UNKNOWN));
403 VerifyAndClearChange(URL(kPath4),
404 FileChange(FileChange::FILE_CHANGE_DELETE,
405 sync_file_system::SYNC_FILE_TYPE_UNKNOWN));
406 VerifyAndClearChange(URL(kPath5),
407 FileChange(FileChange::FILE_CHANGE_DELETE,
408 sync_file_system::SYNC_FILE_TYPE_UNKNOWN));
411 TEST_F(LocalFileChangeTrackerTest, RestoreCopyChanges) {
412 EXPECT_EQ(base::File::FILE_OK, file_system_.OpenFileSystem());
414 FileSystemURLSet urls;
416 const char kPath0[] = "file a";
417 const char kPath1[] = "dir a";
418 const char kPath2[] = "dir a/dir";
419 const char kPath3[] = "dir a/file a";
420 const char kPath4[] = "dir a/file b";
422 const char kPath0Copy[] = "file b"; // To be copied from kPath0
423 const char kPath1Copy[] = "dir b"; // To be copied from kPath1
424 const char kPath2Copy[] = "dir b/dir"; // To be copied from kPath2
425 const char kPath3Copy[] = "dir b/file a"; // To be copied from kPath3
426 const char kPath4Copy[] = "dir b/file b"; // To be copied from kPath4
428 file_system_.GetChangedURLsInTracker(&urls);
429 ASSERT_EQ(0U, urls.size());
431 const std::string kData("Lorem ipsum.");
432 MockBlobURLRequestContext url_request_context(file_system_context());
433 ScopedTextBlob blob(url_request_context, "blob_id:test", kData);
435 // Create files and nested directories.
436 EXPECT_EQ(base::File::FILE_OK,
437 file_system_.CreateFile(URL(kPath0))); // Creates a file.
438 EXPECT_EQ(base::File::FILE_OK,
439 file_system_.CreateDirectory(URL(kPath1))); // Creates a dir.
440 EXPECT_EQ(base::File::FILE_OK,
441 file_system_.CreateDirectory(URL(kPath2))); // Creates another dir.
442 EXPECT_EQ(base::File::FILE_OK,
443 file_system_.CreateFile(URL(kPath3))); // Creates a file.
444 EXPECT_EQ(base::File::FILE_OK,
445 file_system_.TruncateFile(URL(kPath3), 1)); // Modifies the file.
446 EXPECT_EQ(base::File::FILE_OK,
447 file_system_.CreateFile(URL(kPath4))); // Creates another file.
448 EXPECT_EQ(static_cast<int64>(kData.size()),
449 file_system_.Write(&url_request_context, // Modifies the file.
450 URL(kPath4), blob.GetBlobDataHandle()));
452 // Verify we have 5 changes for preparation.
453 file_system_.GetChangedURLsInTracker(&urls);
454 EXPECT_EQ(5U, urls.size());
455 change_tracker()->ClearChangesForURL(URL(kPath0));
456 change_tracker()->ClearChangesForURL(URL(kPath1));
457 change_tracker()->ClearChangesForURL(URL(kPath2));
458 change_tracker()->ClearChangesForURL(URL(kPath3));
459 change_tracker()->ClearChangesForURL(URL(kPath4));
461 // Make sure we have no changes.
462 file_system_.GetChangedURLsInTracker(&urls);
463 EXPECT_TRUE(urls.empty());
465 // Copy the file and the parent directory.
466 EXPECT_EQ(base::File::FILE_OK,
467 file_system_.Copy(URL(kPath0), URL(kPath0Copy))); // Copy the file.
468 EXPECT_EQ(base::File::FILE_OK,
469 file_system_.Copy(URL(kPath1), URL(kPath1Copy))); // Copy the dir.
471 file_system_.GetChangedURLsInTracker(&urls);
472 EXPECT_EQ(5U, urls.size());
473 DropChangesInTracker();
475 // Make sure we have no in-memory changes in the tracker.
476 file_system_.GetChangedURLsInTracker(&urls);
477 ASSERT_EQ(0U, urls.size());
479 RestoreChangesFromTrackerDB();
481 // Make sure the changes are restored from the DB.
482 file_system_.GetChangedURLsInTracker(&urls);
483 EXPECT_EQ(5U, urls.size());
485 VerifyAndClearChange(URL(kPath0Copy),
486 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
487 sync_file_system::SYNC_FILE_TYPE_FILE));
488 VerifyAndClearChange(URL(kPath1Copy),
489 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
490 sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
491 VerifyAndClearChange(URL(kPath2Copy),
492 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
493 sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
494 VerifyAndClearChange(URL(kPath3Copy),
495 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
496 sync_file_system::SYNC_FILE_TYPE_FILE));
497 VerifyAndClearChange(URL(kPath4Copy),
498 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
499 sync_file_system::SYNC_FILE_TYPE_FILE));
502 TEST_F(LocalFileChangeTrackerTest, RestoreMoveChanges) {
503 EXPECT_EQ(base::File::FILE_OK, file_system_.OpenFileSystem());
505 FileSystemURLSet urls;
507 const char kPath0[] = "file a";
508 const char kPath1[] = "dir a";
509 const char kPath2[] = "dir a/file";
510 const char kPath3[] = "dir a/dir";
511 const char kPath4[] = "dir a/dir/file";
513 const char kPath5[] = "file b"; // To be moved from kPath0.
514 const char kPath6[] = "dir b"; // To be moved from kPath1.
515 const char kPath7[] = "dir b/file"; // To be moved from kPath2.
516 const char kPath8[] = "dir b/dir"; // To be moved from kPath3.
517 const char kPath9[] = "dir b/dir/file"; // To be moved from kPath4.
519 file_system_.GetChangedURLsInTracker(&urls);
520 ASSERT_EQ(0U, urls.size());
522 // Create files and nested directories.
523 EXPECT_EQ(base::File::FILE_OK,
524 file_system_.CreateFile(URL(kPath0)));
525 EXPECT_EQ(base::File::FILE_OK,
526 file_system_.CreateDirectory(URL(kPath1)));
527 EXPECT_EQ(base::File::FILE_OK,
528 file_system_.CreateFile(URL(kPath2)));
529 EXPECT_EQ(base::File::FILE_OK,
530 file_system_.CreateDirectory(URL(kPath3)));
531 EXPECT_EQ(base::File::FILE_OK,
532 file_system_.CreateFile(URL(kPath4)));
534 // Verify we have 5 changes for preparation.
535 file_system_.GetChangedURLsInTracker(&urls);
536 EXPECT_EQ(5U, urls.size());
537 change_tracker()->ClearChangesForURL(URL(kPath0));
538 change_tracker()->ClearChangesForURL(URL(kPath1));
539 change_tracker()->ClearChangesForURL(URL(kPath2));
540 change_tracker()->ClearChangesForURL(URL(kPath3));
541 change_tracker()->ClearChangesForURL(URL(kPath4));
543 // Make sure we have no changes.
544 file_system_.GetChangedURLsInTracker(&urls);
545 EXPECT_TRUE(urls.empty());
547 // Move the file and the parent directory.
548 EXPECT_EQ(base::File::FILE_OK,
549 file_system_.Move(URL(kPath0), URL(kPath5)));
550 EXPECT_EQ(base::File::FILE_OK,
551 file_system_.Move(URL(kPath1), URL(kPath6)));
553 file_system_.GetChangedURLsInTracker(&urls);
554 EXPECT_EQ(10U, urls.size());
556 DropChangesInTracker();
558 // Make sure we have no in-memory changes in the tracker.
559 file_system_.GetChangedURLsInTracker(&urls);
560 ASSERT_EQ(0U, urls.size());
562 RestoreChangesFromTrackerDB();
564 // Make sure the changes are restored from the DB.
565 file_system_.GetChangedURLsInTracker(&urls);
566 // Deletion for child files in the deleted directory cannot be restored,
567 // so we will only have 8 changes.
568 EXPECT_EQ(10U, urls.size());
570 VerifyAndClearChange(URL(kPath0),
571 FileChange(FileChange::FILE_CHANGE_DELETE,
572 sync_file_system::SYNC_FILE_TYPE_UNKNOWN));
573 VerifyAndClearChange(URL(kPath1),
574 FileChange(FileChange::FILE_CHANGE_DELETE,
575 sync_file_system::SYNC_FILE_TYPE_UNKNOWN));
576 VerifyAndClearChange(URL(kPath3),
577 FileChange(FileChange::FILE_CHANGE_DELETE,
578 sync_file_system::SYNC_FILE_TYPE_UNKNOWN));
579 VerifyAndClearChange(URL(kPath5),
580 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
581 sync_file_system::SYNC_FILE_TYPE_FILE));
582 VerifyAndClearChange(URL(kPath6),
583 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
584 sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
585 VerifyAndClearChange(URL(kPath7),
586 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
587 sync_file_system::SYNC_FILE_TYPE_FILE));
588 VerifyAndClearChange(URL(kPath8),
589 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
590 sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
591 VerifyAndClearChange(URL(kPath9),
592 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
593 sync_file_system::SYNC_FILE_TYPE_FILE));
596 TEST_F(LocalFileChangeTrackerTest, NextChangedURLsWithRecursiveCopy) {
597 EXPECT_EQ(base::File::FILE_OK, file_system_.OpenFileSystem());
599 FileSystemURLSet urls;
601 const char kPath0[] = "dir a";
602 const char kPath1[] = "dir a/file";
603 const char kPath2[] = "dir a/dir";
605 const char kPath0Copy[] = "dir b";
606 const char kPath1Copy[] = "dir b/file";
607 const char kPath2Copy[] = "dir b/dir";
609 // Creates kPath0,1,2 and then copies them all.
610 EXPECT_EQ(base::File::FILE_OK,
611 file_system_.CreateDirectory(URL(kPath0)));
612 EXPECT_EQ(base::File::FILE_OK,
613 file_system_.CreateFile(URL(kPath1)));
614 EXPECT_EQ(base::File::FILE_OK,
615 file_system_.CreateDirectory(URL(kPath2)));
616 EXPECT_EQ(base::File::FILE_OK,
617 file_system_.Copy(URL(kPath0), URL(kPath0Copy)));
619 std::deque<FileSystemURL> urls_to_process;
620 change_tracker()->GetNextChangedURLs(&urls_to_process, 0);
621 ASSERT_EQ(6U, urls_to_process.size());
623 // Creation must have occured first.
624 EXPECT_EQ(URL(kPath0), urls_to_process[0]);
625 EXPECT_EQ(URL(kPath1), urls_to_process[1]);
626 EXPECT_EQ(URL(kPath2), urls_to_process[2]);
628 // Then recursive copy took place. The exact order cannot be determined
629 // but the parent directory must have been created first.
630 EXPECT_EQ(URL(kPath0Copy), urls_to_process[3]);
631 EXPECT_TRUE(URL(kPath1Copy) == urls_to_process[4] ||
632 URL(kPath2Copy) == urls_to_process[4]);
633 EXPECT_TRUE(URL(kPath1Copy) == urls_to_process[5] ||
634 URL(kPath2Copy) == urls_to_process[5]);
637 TEST_F(LocalFileChangeTrackerTest, NextChangedURLsWithRecursiveRemove) {
638 EXPECT_EQ(base::File::FILE_OK, file_system_.OpenFileSystem());
640 const char kPath0[] = "dir a";
641 const char kPath1[] = "dir a/file1";
642 const char kPath2[] = "dir a/file2";
644 // Creates kPath0,1,2 and then removes them all.
645 EXPECT_EQ(base::File::FILE_OK,
646 file_system_.CreateDirectory(URL(kPath0)));
647 EXPECT_EQ(base::File::FILE_OK,
648 file_system_.CreateFile(URL(kPath1)));
649 EXPECT_EQ(base::File::FILE_OK,
650 file_system_.CreateFile(URL(kPath2)));
651 EXPECT_EQ(base::File::FILE_OK,
652 file_system_.Remove(URL(kPath0), true /* recursive */));
654 FileSystemURLSet urls;
655 GetAllChangedURLs(&urls);
657 // This is actually not really desirable, but since the directory
658 // creation and deletion have been offset now we only have two
659 // file deletion changes.
661 // NOTE: This will cause 2 local sync for deleting nonexistent files
662 // on the remote side.
664 // TODO(kinuko): For micro optimization we could probably restore the ADD
665 // change type (other than ADD_OR_UPDATE) and offset file ADD+DELETE
666 // changes too.
667 ASSERT_EQ(2U, urls.size());
669 // The exact order of recursive removal cannot be determined.
670 EXPECT_TRUE(ContainsKey(urls, URL(kPath1)));
671 EXPECT_TRUE(ContainsKey(urls, URL(kPath2)));
674 TEST_F(LocalFileChangeTrackerTest, ResetForFileSystem) {
675 EXPECT_EQ(base::File::FILE_OK, file_system_.OpenFileSystem());
677 const char kPath0[] = "dir a";
678 const char kPath1[] = "dir a/file";
679 const char kPath2[] = "dir a/subdir";
680 const char kPath3[] = "dir b";
682 EXPECT_EQ(base::File::FILE_OK,
683 file_system_.CreateDirectory(URL(kPath0)));
684 EXPECT_EQ(base::File::FILE_OK,
685 file_system_.CreateFile(URL(kPath1)));
686 EXPECT_EQ(base::File::FILE_OK,
687 file_system_.CreateDirectory(URL(kPath2)));
688 EXPECT_EQ(base::File::FILE_OK,
689 file_system_.CreateDirectory(URL(kPath3)));
691 FileSystemURLSet urls;
692 GetAllChangedURLs(&urls);
693 EXPECT_EQ(4u, urls.size());
694 EXPECT_TRUE(ContainsKey(urls, URL(kPath0)));
695 EXPECT_TRUE(ContainsKey(urls, URL(kPath1)));
696 EXPECT_TRUE(ContainsKey(urls, URL(kPath2)));
697 EXPECT_TRUE(ContainsKey(urls, URL(kPath3)));
699 // Reset all changes for the file system.
700 change_tracker()->ResetForFileSystem(
701 file_system_.origin(), file_system_.type());
703 GetAllChangedURLs(&urls);
704 EXPECT_TRUE(urls.empty());
706 // Make sure they're gone from the database too.
707 DropChangesInTracker();
708 RestoreChangesFromTrackerDB();
710 GetAllChangedURLs(&urls);
711 EXPECT_TRUE(urls.empty());
714 } // namespace sync_file_system