local_file_change_tracker_unittest.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
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 "chrome/browser/sync_file_system/local/local_file_change_tracker.h" 6 7#include <deque> 8#include <set> 9 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" 25 26using fileapi::FileSystemContext; 27using fileapi::FileSystemURL; 28using fileapi::FileSystemURLSet; 29using webkit_blob::MockBlobURLRequestContext; 30using webkit_blob::ScopedTextBlob; 31 32namespace sync_file_system { 33 34class LocalFileChangeTrackerTest : public testing::Test { 35 public: 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()) {} 41 42 virtual void SetUp() OVERRIDE { 43 file_system_.SetUp(); 44 45 sync_context_ = 46 new LocalFileSyncContext(base::FilePath(), 47 base::MessageLoopProxy::current().get(), 48 base::MessageLoopProxy::current().get()); 49 ASSERT_EQ( 50 sync_file_system::SYNC_STATUS_OK, 51 file_system_.MaybeInitializeFileSystemContext(sync_context_.get())); 52 } 53 54 virtual void TearDown() OVERRIDE { 55 if (sync_context_.get()) 56 sync_context_->ShutdownOnUIThread(); 57 sync_context_ = NULL; 58 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(); 65 } 66 67 protected: 68 FileSystemURL URL(const std::string& path) { 69 return file_system_.URL(path); 70 } 71 72 FileSystemContext* file_system_context() { 73 return file_system_.file_system_context(); 74 } 75 76 LocalFileChangeTracker* change_tracker() { 77 return file_system_.backend()->change_tracker(); 78 } 79 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]); 91 92 // Clear the URL from the change tracker. 93 change_tracker()->ClearChangesForURL(url); 94 } 95 96 void DropChangesInTracker() { 97 change_tracker()->DropAllChanges(); 98 } 99 100 void RestoreChangesFromTrackerDB() { 101 change_tracker()->CollectLastDirtyChanges(file_system_context()); 102 } 103 104 ScopedEnableSyncFSDirectoryOperation enable_directory_operation_; 105 base::MessageLoop message_loop_; 106 CannedSyncableFileSystem file_system_; 107 108 private: 109 scoped_refptr<LocalFileSyncContext> sync_context_; 110 111 DISALLOW_COPY_AND_ASSIGN(LocalFileChangeTrackerTest); 112}; 113 114TEST_F(LocalFileChangeTrackerTest, GetChanges) { 115 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.OpenFileSystem()); 116 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"; 125 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'. 134 135 FileSystemURLSet urls; 136 file_system_.GetChangedURLsInTracker(&urls); 137 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))); 144 145 // Changes for kPath0 must have been offset and removed. 146 EXPECT_FALSE(ContainsKey(urls, URL(kPath0))); 147 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()); 152 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()); 157 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]); 164 165 // Modify kPath4 again. 166 change_tracker()->OnModifyFile(URL(kPath4)); 167 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]); 177 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)); 193} 194 195TEST_F(LocalFileChangeTrackerTest, RestoreCreateAndModifyChanges) { 196 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.OpenFileSystem()); 197 198 FileSystemURLSet urls; 199 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"; 205 206 file_system_.GetChangedURLsInTracker(&urls); 207 ASSERT_EQ(0U, urls.size()); 208 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); 212 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())); 229 230 // Verify the changes. 231 file_system_.GetChangedURLsInTracker(&urls); 232 EXPECT_EQ(5U, urls.size()); 233 234 // Reset the changes in in-memory tracker. 235 DropChangesInTracker(); 236 237 // Make sure we have no in-memory changes in the tracker. 238 file_system_.GetChangedURLsInTracker(&urls); 239 ASSERT_EQ(0U, urls.size()); 240 241 RestoreChangesFromTrackerDB(); 242 243 // Make sure the changes are restored from the DB. 244 file_system_.GetChangedURLsInTracker(&urls); 245 EXPECT_EQ(5U, urls.size()); 246 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)); 262} 263 264TEST_F(LocalFileChangeTrackerTest, RestoreRemoveChanges) { 265 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.OpenFileSystem()); 266 267 FileSystemURLSet urls; 268 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"; 275 276 file_system_.GetChangedURLsInTracker(&urls); 277 ASSERT_EQ(0U, urls.size()); 278 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 */)); 284 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 */)); 290 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 */)); 302 303 file_system_.GetChangedURLsInTracker(&urls); 304 EXPECT_EQ(3U, urls.size()); 305 306 DropChangesInTracker(); 307 308 // Make sure we have no in-memory changes in the tracker. 309 file_system_.GetChangedURLsInTracker(&urls); 310 ASSERT_EQ(0U, urls.size()); 311 312 RestoreChangesFromTrackerDB(); 313 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()); 319 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)); 338} 339 340TEST_F(LocalFileChangeTrackerTest, RestoreCopyChanges) { 341 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.OpenFileSystem()); 342 343 FileSystemURLSet urls; 344 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"; 350 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 356 357 file_system_.GetChangedURLsInTracker(&urls); 358 ASSERT_EQ(0U, urls.size()); 359 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); 363 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())); 380 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)); 389 390 // Make sure we have no changes. 391 file_system_.GetChangedURLsInTracker(&urls); 392 EXPECT_TRUE(urls.empty()); 393 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. 399 400 file_system_.GetChangedURLsInTracker(&urls); 401 EXPECT_EQ(5U, urls.size()); 402 DropChangesInTracker(); 403 404 // Make sure we have no in-memory changes in the tracker. 405 file_system_.GetChangedURLsInTracker(&urls); 406 ASSERT_EQ(0U, urls.size()); 407 408 RestoreChangesFromTrackerDB(); 409 410 // Make sure the changes are restored from the DB. 411 file_system_.GetChangedURLsInTracker(&urls); 412 EXPECT_EQ(5U, urls.size()); 413 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)); 429} 430 431TEST_F(LocalFileChangeTrackerTest, RestoreMoveChanges) { 432 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.OpenFileSystem()); 433 434 FileSystemURLSet urls; 435 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"; 441 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. 447 448 file_system_.GetChangedURLsInTracker(&urls); 449 ASSERT_EQ(0U, urls.size()); 450 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))); 462 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)); 471 472 // Make sure we have no changes. 473 file_system_.GetChangedURLsInTracker(&urls); 474 EXPECT_TRUE(urls.empty()); 475 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))); 481 482 file_system_.GetChangedURLsInTracker(&urls); 483 EXPECT_EQ(10U, urls.size()); 484 485 DropChangesInTracker(); 486 487 // Make sure we have no in-memory changes in the tracker. 488 file_system_.GetChangedURLsInTracker(&urls); 489 ASSERT_EQ(0U, urls.size()); 490 491 RestoreChangesFromTrackerDB(); 492 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()); 498 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)); 523} 524 525TEST_F(LocalFileChangeTrackerTest, NextChangedURLsWithRecursiveCopy) { 526 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.OpenFileSystem()); 527 528 FileSystemURLSet urls; 529 530 const char kPath0[] = "dir a"; 531 const char kPath1[] = "dir a/file"; 532 const char kPath2[] = "dir a/dir"; 533 534 const char kPath0Copy[] = "dir b"; 535 const char kPath1Copy[] = "dir b/file"; 536 const char kPath2Copy[] = "dir b/dir"; 537 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))); 547 548 std::deque<FileSystemURL> urls_to_process; 549 change_tracker()->GetNextChangedURLs(&urls_to_process, 0); 550 ASSERT_EQ(6U, urls_to_process.size()); 551 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]); 556 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]); 564} 565 566TEST_F(LocalFileChangeTrackerTest, NextChangedURLsWithRecursiveRemove) { 567 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.OpenFileSystem()); 568 569 FileSystemURLSet urls; 570 571 const char kPath0[] = "dir a"; 572 const char kPath1[] = "dir a/file1"; 573 const char kPath2[] = "dir a/file2"; 574 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 */)); 584 585 std::deque<FileSystemURL> urls_to_process; 586 change_tracker()->GetNextChangedURLs(&urls_to_process, 0); 587 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. 591 // 592 // NOTE: This will cause 2 local sync for deleting nonexistent files 593 // on the remote side. 594 // 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 597 // changes too. 598 ASSERT_EQ(2U, urls_to_process.size()); 599 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]); 605} 606 607} // namespace sync_file_system 608