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"
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/message_loop/message_loop_proxy.h"
15 #include "base/stl_util.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 "testing/gtest/include/gtest/gtest.h"
22 #include "webkit/browser/blob/mock_blob_url_request_context.h"
23 #include "webkit/browser/fileapi/file_system_context.h"
24 #include "webkit/browser/quota/quota_manager.h"
26 using fileapi::FileSystemContext;
27 using fileapi::FileSystemURL;
28 using fileapi::FileSystemURLSet;
29 using webkit_blob::MockBlobURLRequestContext;
30 using webkit_blob::ScopedTextBlob;
32 namespace sync_file_system {
34 class LocalFileChangeTrackerTest : public testing::Test {
36 LocalFileChangeTrackerTest()
37 : message_loop_(base::MessageLoop::TYPE_IO),
38 file_system_(GURL("http://example.com"),
39 base::MessageLoopProxy::current().get(),
40 base::MessageLoopProxy::current().get()) {}
42 virtual void SetUp() OVERRIDE {
46 new LocalFileSyncContext(base::FilePath(),
47 base::MessageLoopProxy::current().get(),
48 base::MessageLoopProxy::current().get());
50 sync_file_system::SYNC_STATUS_OK,
51 file_system_.MaybeInitializeFileSystemContext(sync_context_.get()));
54 virtual void TearDown() OVERRIDE {
55 if (sync_context_.get())
56 sync_context_->ShutdownOnUIThread();
59 message_loop_.RunUntilIdle();
60 file_system_.TearDown();
61 // Make sure we don't leave the external filesystem.
62 // (CannedSyncableFileSystem::TearDown does not do this as there may be
63 // multiple syncable file systems registered for the name)
64 RevokeSyncableFileSystem();
68 FileSystemURL URL(const std::string& path) {
69 return file_system_.URL(path);
72 FileSystemContext* file_system_context() {
73 return file_system_.file_system_context();
76 LocalFileChangeTracker* change_tracker() {
77 return file_system_.backend()->change_tracker();
80 void VerifyAndClearChange(const FileSystemURL& url,
81 const FileChange& expected_change) {
82 SCOPED_TRACE(testing::Message() << url.DebugString() <<
83 " expecting:" << expected_change.DebugString());
84 // Get the changes for URL and verify.
85 FileChangeList changes;
86 change_tracker()->GetChangesForURL(url, &changes);
87 ASSERT_EQ(1U, changes.size());
88 SCOPED_TRACE(testing::Message() << url.DebugString() <<
89 " actual:" << changes.DebugString());
90 EXPECT_EQ(expected_change, changes.list()[0]);
92 // Clear the URL from the change tracker.
93 change_tracker()->ClearChangesForURL(url);
96 void DropChangesInTracker() {
97 change_tracker()->DropAllChanges();
100 void RestoreChangesFromTrackerDB() {
101 change_tracker()->CollectLastDirtyChanges(file_system_context());
104 ScopedEnableSyncFSDirectoryOperation enable_directory_operation_;
105 base::MessageLoop message_loop_;
106 CannedSyncableFileSystem file_system_;
109 scoped_refptr<LocalFileSyncContext> sync_context_;
111 DISALLOW_COPY_AND_ASSIGN(LocalFileChangeTrackerTest);
114 TEST_F(LocalFileChangeTrackerTest, GetChanges) {
115 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.OpenFileSystem());
117 // Test URLs (no parent/child relationships, as we test such cases
118 // mainly in LocalFileSyncStatusTest).
119 const char kPath0[] = "test/dir a/dir";
120 const char kPath1[] = "test/dir b";
121 const char kPath2[] = "test/foo.txt";
122 const char kPath3[] = "test/bar";
123 const char kPath4[] = "temporary/dir a";
124 const char kPath5[] = "temporary/foo";
126 change_tracker()->OnCreateDirectory(URL(kPath0));
127 change_tracker()->OnRemoveDirectory(URL(kPath0)); // Offset the create.
128 change_tracker()->OnRemoveDirectory(URL(kPath1));
129 change_tracker()->OnCreateDirectory(URL(kPath2));
130 change_tracker()->OnRemoveFile(URL(kPath3));
131 change_tracker()->OnModifyFile(URL(kPath4));
132 change_tracker()->OnCreateFile(URL(kPath5));
133 change_tracker()->OnRemoveFile(URL(kPath5)); // Recorded as 'delete'.
135 FileSystemURLSet urls;
136 file_system_.GetChangedURLsInTracker(&urls);
138 EXPECT_EQ(5U, urls.size());
139 EXPECT_TRUE(ContainsKey(urls, URL(kPath1)));
140 EXPECT_TRUE(ContainsKey(urls, URL(kPath2)));
141 EXPECT_TRUE(ContainsKey(urls, URL(kPath3)));
142 EXPECT_TRUE(ContainsKey(urls, URL(kPath4)));
143 EXPECT_TRUE(ContainsKey(urls, URL(kPath5)));
145 // Changes for kPath0 must have been offset and removed.
146 EXPECT_FALSE(ContainsKey(urls, URL(kPath0)));
148 // GetNextChangedURLs only returns up to max_urls (i.e. 3) urls.
149 std::deque<FileSystemURL> urls_to_process;
150 change_tracker()->GetNextChangedURLs(&urls_to_process, 3);
151 ASSERT_EQ(3U, urls_to_process.size());
153 // Let it return all.
154 urls_to_process.clear();
155 change_tracker()->GetNextChangedURLs(&urls_to_process, 0);
156 ASSERT_EQ(5U, urls_to_process.size());
158 // The changes must be in the last-modified-time order.
159 EXPECT_EQ(URL(kPath1), urls_to_process[0]);
160 EXPECT_EQ(URL(kPath2), urls_to_process[1]);
161 EXPECT_EQ(URL(kPath3), urls_to_process[2]);
162 EXPECT_EQ(URL(kPath4), urls_to_process[3]);
163 EXPECT_EQ(URL(kPath5), urls_to_process[4]);
165 // Modify kPath4 again.
166 change_tracker()->OnModifyFile(URL(kPath4));
168 // Now the order must be changed.
169 urls_to_process.clear();
170 change_tracker()->GetNextChangedURLs(&urls_to_process, 0);
171 ASSERT_EQ(5U, urls_to_process.size());
172 EXPECT_EQ(URL(kPath1), urls_to_process[0]);
173 EXPECT_EQ(URL(kPath2), urls_to_process[1]);
174 EXPECT_EQ(URL(kPath3), urls_to_process[2]);
175 EXPECT_EQ(URL(kPath5), urls_to_process[3]);
176 EXPECT_EQ(URL(kPath4), urls_to_process[4]);
178 VerifyAndClearChange(URL(kPath1),
179 FileChange(FileChange::FILE_CHANGE_DELETE,
180 sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
181 VerifyAndClearChange(URL(kPath2),
182 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
183 sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
184 VerifyAndClearChange(URL(kPath3),
185 FileChange(FileChange::FILE_CHANGE_DELETE,
186 sync_file_system::SYNC_FILE_TYPE_FILE));
187 VerifyAndClearChange(URL(kPath4),
188 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
189 sync_file_system::SYNC_FILE_TYPE_FILE));
190 VerifyAndClearChange(URL(kPath5),
191 FileChange(FileChange::FILE_CHANGE_DELETE,
192 sync_file_system::SYNC_FILE_TYPE_FILE));
195 TEST_F(LocalFileChangeTrackerTest, RestoreCreateAndModifyChanges) {
196 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.OpenFileSystem());
198 FileSystemURLSet urls;
200 const char kPath0[] = "file a";
201 const char kPath1[] = "dir a";
202 const char kPath2[] = "dir a/dir";
203 const char kPath3[] = "dir a/file a";
204 const char kPath4[] = "dir a/file b";
206 file_system_.GetChangedURLsInTracker(&urls);
207 ASSERT_EQ(0U, urls.size());
209 const std::string kData("Lorem ipsum.");
210 MockBlobURLRequestContext url_request_context(file_system_context());
211 ScopedTextBlob blob(url_request_context, "blob_id:test", kData);
213 // Create files and nested directories.
214 EXPECT_EQ(base::PLATFORM_FILE_OK,
215 file_system_.CreateFile(URL(kPath0))); // Creates a file.
216 EXPECT_EQ(base::PLATFORM_FILE_OK,
217 file_system_.CreateDirectory(URL(kPath1))); // Creates a dir.
218 EXPECT_EQ(base::PLATFORM_FILE_OK,
219 file_system_.CreateDirectory(URL(kPath2))); // Creates another dir.
220 EXPECT_EQ(base::PLATFORM_FILE_OK,
221 file_system_.CreateFile(URL(kPath3))); // Creates a file.
222 EXPECT_EQ(base::PLATFORM_FILE_OK,
223 file_system_.TruncateFile(URL(kPath3), 1)); // Modifies the file.
224 EXPECT_EQ(base::PLATFORM_FILE_OK,
225 file_system_.CreateFile(URL(kPath4))); // Creates another file.
226 EXPECT_EQ(static_cast<int64>(kData.size()), // Modifies the file.
227 file_system_.Write(&url_request_context,
228 URL(kPath4), blob.GetBlobDataHandle()));
230 // Verify the changes.
231 file_system_.GetChangedURLsInTracker(&urls);
232 EXPECT_EQ(5U, urls.size());
234 // Reset the changes in in-memory tracker.
235 DropChangesInTracker();
237 // Make sure we have no in-memory changes in the tracker.
238 file_system_.GetChangedURLsInTracker(&urls);
239 ASSERT_EQ(0U, urls.size());
241 RestoreChangesFromTrackerDB();
243 // Make sure the changes are restored from the DB.
244 file_system_.GetChangedURLsInTracker(&urls);
245 EXPECT_EQ(5U, urls.size());
247 VerifyAndClearChange(URL(kPath0),
248 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
249 sync_file_system::SYNC_FILE_TYPE_FILE));
250 VerifyAndClearChange(URL(kPath1),
251 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
252 sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
253 VerifyAndClearChange(URL(kPath2),
254 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
255 sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
256 VerifyAndClearChange(URL(kPath3),
257 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
258 sync_file_system::SYNC_FILE_TYPE_FILE));
259 VerifyAndClearChange(URL(kPath4),
260 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
261 sync_file_system::SYNC_FILE_TYPE_FILE));
264 TEST_F(LocalFileChangeTrackerTest, RestoreRemoveChanges) {
265 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.OpenFileSystem());
267 FileSystemURLSet urls;
269 const char kPath0[] = "file";
270 const char kPath1[] = "dir a";
271 const char kPath2[] = "dir b";
272 const char kPath3[] = "dir b/file";
273 const char kPath4[] = "dir b/dir c";
274 const char kPath5[] = "dir b/dir c/file";
276 file_system_.GetChangedURLsInTracker(&urls);
277 ASSERT_EQ(0U, urls.size());
279 // Creates and removes a same file.
280 EXPECT_EQ(base::PLATFORM_FILE_OK,
281 file_system_.CreateFile(URL(kPath0)));
282 EXPECT_EQ(base::PLATFORM_FILE_OK,
283 file_system_.Remove(URL(kPath0), false /* recursive */));
285 // Creates and removes a same directory.
286 EXPECT_EQ(base::PLATFORM_FILE_OK,
287 file_system_.CreateDirectory(URL(kPath1)));
288 EXPECT_EQ(base::PLATFORM_FILE_OK,
289 file_system_.Remove(URL(kPath1), false /* recursive */));
291 // Creates files and nested directories, then removes the parent directory.
292 EXPECT_EQ(base::PLATFORM_FILE_OK,
293 file_system_.CreateDirectory(URL(kPath2)));
294 EXPECT_EQ(base::PLATFORM_FILE_OK,
295 file_system_.CreateFile(URL(kPath3)));
296 EXPECT_EQ(base::PLATFORM_FILE_OK,
297 file_system_.CreateDirectory(URL(kPath4)));
298 EXPECT_EQ(base::PLATFORM_FILE_OK,
299 file_system_.CreateFile(URL(kPath5)));
300 EXPECT_EQ(base::PLATFORM_FILE_OK,
301 file_system_.Remove(URL(kPath2), true /* recursive */));
303 file_system_.GetChangedURLsInTracker(&urls);
304 EXPECT_EQ(3U, urls.size());
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 // Since directories to have been reverted (kPath1, kPath2, kPath4) are
317 // treated as FILE_CHANGE_DELETE, the number of changes should be 6.
318 EXPECT_EQ(6U, urls.size());
320 VerifyAndClearChange(URL(kPath0),
321 FileChange(FileChange::FILE_CHANGE_DELETE,
322 sync_file_system::SYNC_FILE_TYPE_UNKNOWN));
323 VerifyAndClearChange(URL(kPath1),
324 FileChange(FileChange::FILE_CHANGE_DELETE,
325 sync_file_system::SYNC_FILE_TYPE_UNKNOWN));
326 VerifyAndClearChange(URL(kPath2),
327 FileChange(FileChange::FILE_CHANGE_DELETE,
328 sync_file_system::SYNC_FILE_TYPE_UNKNOWN));
329 VerifyAndClearChange(URL(kPath3),
330 FileChange(FileChange::FILE_CHANGE_DELETE,
331 sync_file_system::SYNC_FILE_TYPE_UNKNOWN));
332 VerifyAndClearChange(URL(kPath4),
333 FileChange(FileChange::FILE_CHANGE_DELETE,
334 sync_file_system::SYNC_FILE_TYPE_UNKNOWN));
335 VerifyAndClearChange(URL(kPath5),
336 FileChange(FileChange::FILE_CHANGE_DELETE,
337 sync_file_system::SYNC_FILE_TYPE_UNKNOWN));
340 TEST_F(LocalFileChangeTrackerTest, RestoreCopyChanges) {
341 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.OpenFileSystem());
343 FileSystemURLSet urls;
345 const char kPath0[] = "file a";
346 const char kPath1[] = "dir a";
347 const char kPath2[] = "dir a/dir";
348 const char kPath3[] = "dir a/file a";
349 const char kPath4[] = "dir a/file b";
351 const char kPath0Copy[] = "file b"; // To be copied from kPath0
352 const char kPath1Copy[] = "dir b"; // To be copied from kPath1
353 const char kPath2Copy[] = "dir b/dir"; // To be copied from kPath2
354 const char kPath3Copy[] = "dir b/file a"; // To be copied from kPath3
355 const char kPath4Copy[] = "dir b/file b"; // To be copied from kPath4
357 file_system_.GetChangedURLsInTracker(&urls);
358 ASSERT_EQ(0U, urls.size());
360 const std::string kData("Lorem ipsum.");
361 MockBlobURLRequestContext url_request_context(file_system_context());
362 ScopedTextBlob blob(url_request_context, "blob_id:test", kData);
364 // Create files and nested directories.
365 EXPECT_EQ(base::PLATFORM_FILE_OK,
366 file_system_.CreateFile(URL(kPath0))); // Creates a file.
367 EXPECT_EQ(base::PLATFORM_FILE_OK,
368 file_system_.CreateDirectory(URL(kPath1))); // Creates a dir.
369 EXPECT_EQ(base::PLATFORM_FILE_OK,
370 file_system_.CreateDirectory(URL(kPath2))); // Creates another dir.
371 EXPECT_EQ(base::PLATFORM_FILE_OK,
372 file_system_.CreateFile(URL(kPath3))); // Creates a file.
373 EXPECT_EQ(base::PLATFORM_FILE_OK,
374 file_system_.TruncateFile(URL(kPath3), 1)); // Modifies the file.
375 EXPECT_EQ(base::PLATFORM_FILE_OK,
376 file_system_.CreateFile(URL(kPath4))); // Creates another file.
377 EXPECT_EQ(static_cast<int64>(kData.size()),
378 file_system_.Write(&url_request_context, // Modifies the file.
379 URL(kPath4), blob.GetBlobDataHandle()));
381 // Verify we have 5 changes for preparation.
382 file_system_.GetChangedURLsInTracker(&urls);
383 EXPECT_EQ(5U, urls.size());
384 change_tracker()->ClearChangesForURL(URL(kPath0));
385 change_tracker()->ClearChangesForURL(URL(kPath1));
386 change_tracker()->ClearChangesForURL(URL(kPath2));
387 change_tracker()->ClearChangesForURL(URL(kPath3));
388 change_tracker()->ClearChangesForURL(URL(kPath4));
390 // Make sure we have no changes.
391 file_system_.GetChangedURLsInTracker(&urls);
392 EXPECT_TRUE(urls.empty());
394 // Copy the file and the parent directory.
395 EXPECT_EQ(base::PLATFORM_FILE_OK,
396 file_system_.Copy(URL(kPath0), URL(kPath0Copy))); // Copy the file.
397 EXPECT_EQ(base::PLATFORM_FILE_OK,
398 file_system_.Copy(URL(kPath1), URL(kPath1Copy))); // Copy the dir.
400 file_system_.GetChangedURLsInTracker(&urls);
401 EXPECT_EQ(5U, urls.size());
402 DropChangesInTracker();
404 // Make sure we have no in-memory changes in the tracker.
405 file_system_.GetChangedURLsInTracker(&urls);
406 ASSERT_EQ(0U, urls.size());
408 RestoreChangesFromTrackerDB();
410 // Make sure the changes are restored from the DB.
411 file_system_.GetChangedURLsInTracker(&urls);
412 EXPECT_EQ(5U, urls.size());
414 VerifyAndClearChange(URL(kPath0Copy),
415 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
416 sync_file_system::SYNC_FILE_TYPE_FILE));
417 VerifyAndClearChange(URL(kPath1Copy),
418 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
419 sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
420 VerifyAndClearChange(URL(kPath2Copy),
421 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
422 sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
423 VerifyAndClearChange(URL(kPath3Copy),
424 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
425 sync_file_system::SYNC_FILE_TYPE_FILE));
426 VerifyAndClearChange(URL(kPath4Copy),
427 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
428 sync_file_system::SYNC_FILE_TYPE_FILE));
431 TEST_F(LocalFileChangeTrackerTest, RestoreMoveChanges) {
432 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.OpenFileSystem());
434 FileSystemURLSet urls;
436 const char kPath0[] = "file a";
437 const char kPath1[] = "dir a";
438 const char kPath2[] = "dir a/file";
439 const char kPath3[] = "dir a/dir";
440 const char kPath4[] = "dir a/dir/file";
442 const char kPath5[] = "file b"; // To be moved from kPath0.
443 const char kPath6[] = "dir b"; // To be moved from kPath1.
444 const char kPath7[] = "dir b/file"; // To be moved from kPath2.
445 const char kPath8[] = "dir b/dir"; // To be moved from kPath3.
446 const char kPath9[] = "dir b/dir/file"; // To be moved from kPath4.
448 file_system_.GetChangedURLsInTracker(&urls);
449 ASSERT_EQ(0U, urls.size());
451 // Create files and nested directories.
452 EXPECT_EQ(base::PLATFORM_FILE_OK,
453 file_system_.CreateFile(URL(kPath0)));
454 EXPECT_EQ(base::PLATFORM_FILE_OK,
455 file_system_.CreateDirectory(URL(kPath1)));
456 EXPECT_EQ(base::PLATFORM_FILE_OK,
457 file_system_.CreateFile(URL(kPath2)));
458 EXPECT_EQ(base::PLATFORM_FILE_OK,
459 file_system_.CreateDirectory(URL(kPath3)));
460 EXPECT_EQ(base::PLATFORM_FILE_OK,
461 file_system_.CreateFile(URL(kPath4)));
463 // Verify we have 5 changes for preparation.
464 file_system_.GetChangedURLsInTracker(&urls);
465 EXPECT_EQ(5U, urls.size());
466 change_tracker()->ClearChangesForURL(URL(kPath0));
467 change_tracker()->ClearChangesForURL(URL(kPath1));
468 change_tracker()->ClearChangesForURL(URL(kPath2));
469 change_tracker()->ClearChangesForURL(URL(kPath3));
470 change_tracker()->ClearChangesForURL(URL(kPath4));
472 // Make sure we have no changes.
473 file_system_.GetChangedURLsInTracker(&urls);
474 EXPECT_TRUE(urls.empty());
476 // Move the file and the parent directory.
477 EXPECT_EQ(base::PLATFORM_FILE_OK,
478 file_system_.Move(URL(kPath0), URL(kPath5)));
479 EXPECT_EQ(base::PLATFORM_FILE_OK,
480 file_system_.Move(URL(kPath1), URL(kPath6)));
482 file_system_.GetChangedURLsInTracker(&urls);
483 EXPECT_EQ(10U, urls.size());
485 DropChangesInTracker();
487 // Make sure we have no in-memory changes in the tracker.
488 file_system_.GetChangedURLsInTracker(&urls);
489 ASSERT_EQ(0U, urls.size());
491 RestoreChangesFromTrackerDB();
493 // Make sure the changes are restored from the DB.
494 file_system_.GetChangedURLsInTracker(&urls);
495 // Deletion for child files in the deleted directory cannot be restored,
496 // so we will only have 8 changes.
497 EXPECT_EQ(8U, urls.size());
499 VerifyAndClearChange(URL(kPath0),
500 FileChange(FileChange::FILE_CHANGE_DELETE,
501 sync_file_system::SYNC_FILE_TYPE_UNKNOWN));
502 VerifyAndClearChange(URL(kPath1),
503 FileChange(FileChange::FILE_CHANGE_DELETE,
504 sync_file_system::SYNC_FILE_TYPE_UNKNOWN));
505 VerifyAndClearChange(URL(kPath3),
506 FileChange(FileChange::FILE_CHANGE_DELETE,
507 sync_file_system::SYNC_FILE_TYPE_UNKNOWN));
508 VerifyAndClearChange(URL(kPath5),
509 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
510 sync_file_system::SYNC_FILE_TYPE_FILE));
511 VerifyAndClearChange(URL(kPath6),
512 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
513 sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
514 VerifyAndClearChange(URL(kPath7),
515 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
516 sync_file_system::SYNC_FILE_TYPE_FILE));
517 VerifyAndClearChange(URL(kPath8),
518 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
519 sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
520 VerifyAndClearChange(URL(kPath9),
521 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
522 sync_file_system::SYNC_FILE_TYPE_FILE));
525 TEST_F(LocalFileChangeTrackerTest, NextChangedURLsWithRecursiveCopy) {
526 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.OpenFileSystem());
528 FileSystemURLSet urls;
530 const char kPath0[] = "dir a";
531 const char kPath1[] = "dir a/file";
532 const char kPath2[] = "dir a/dir";
534 const char kPath0Copy[] = "dir b";
535 const char kPath1Copy[] = "dir b/file";
536 const char kPath2Copy[] = "dir b/dir";
538 // Creates kPath0,1,2 and then copies them all.
539 EXPECT_EQ(base::PLATFORM_FILE_OK,
540 file_system_.CreateDirectory(URL(kPath0)));
541 EXPECT_EQ(base::PLATFORM_FILE_OK,
542 file_system_.CreateFile(URL(kPath1)));
543 EXPECT_EQ(base::PLATFORM_FILE_OK,
544 file_system_.CreateDirectory(URL(kPath2)));
545 EXPECT_EQ(base::PLATFORM_FILE_OK,
546 file_system_.Copy(URL(kPath0), URL(kPath0Copy)));
548 std::deque<FileSystemURL> urls_to_process;
549 change_tracker()->GetNextChangedURLs(&urls_to_process, 0);
550 ASSERT_EQ(6U, urls_to_process.size());
552 // Creation must have occured first.
553 EXPECT_EQ(URL(kPath0), urls_to_process[0]);
554 EXPECT_EQ(URL(kPath1), urls_to_process[1]);
555 EXPECT_EQ(URL(kPath2), urls_to_process[2]);
557 // Then recursive copy took place. The exact order cannot be determined
558 // but the parent directory must have been created first.
559 EXPECT_EQ(URL(kPath0Copy), urls_to_process[3]);
560 EXPECT_TRUE(URL(kPath1Copy) == urls_to_process[4] ||
561 URL(kPath2Copy) == urls_to_process[4]);
562 EXPECT_TRUE(URL(kPath1Copy) == urls_to_process[5] ||
563 URL(kPath2Copy) == urls_to_process[5]);
566 TEST_F(LocalFileChangeTrackerTest, NextChangedURLsWithRecursiveRemove) {
567 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.OpenFileSystem());
569 FileSystemURLSet urls;
571 const char kPath0[] = "dir a";
572 const char kPath1[] = "dir a/file1";
573 const char kPath2[] = "dir a/file2";
575 // Creates kPath0,1,2 and then removes them all.
576 EXPECT_EQ(base::PLATFORM_FILE_OK,
577 file_system_.CreateDirectory(URL(kPath0)));
578 EXPECT_EQ(base::PLATFORM_FILE_OK,
579 file_system_.CreateFile(URL(kPath1)));
580 EXPECT_EQ(base::PLATFORM_FILE_OK,
581 file_system_.CreateFile(URL(kPath2)));
582 EXPECT_EQ(base::PLATFORM_FILE_OK,
583 file_system_.Remove(URL(kPath0), true /* recursive */));
585 std::deque<FileSystemURL> urls_to_process;
586 change_tracker()->GetNextChangedURLs(&urls_to_process, 0);
588 // This is actually not really desirable, but since the directory
589 // creation and deletion have been offset now we only have two
590 // file deletion changes.
592 // NOTE: This will cause 2 local sync for deleting nonexistent files
593 // on the remote side.
595 // TODO(kinuko): For micro optimization we could probably restore the ADD
596 // change type (other than ADD_OR_UPDATE) and offset file ADD+DELETE
598 ASSERT_EQ(2U, urls_to_process.size());
600 // The exact order of recursive removal cannot be determined.
601 EXPECT_TRUE(URL(kPath1) == urls_to_process[0] ||
602 URL(kPath2) == urls_to_process[0]);
603 EXPECT_TRUE(URL(kPath1) == urls_to_process[1] ||
604 URL(kPath2) == urls_to_process[1]);
607 } // namespace sync_file_system