OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/files/file_path_watcher.h" | 5 #include "base/files/file_path_watcher.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #if defined(OS_WIN) | 9 #if defined(OS_WIN) |
10 #include <windows.h> | 10 #include <windows.h> |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 } | 158 } |
159 | 159 |
160 virtual void TearDown() { | 160 virtual void TearDown() { |
161 loop_.RunAllPending(); | 161 loop_.RunAllPending(); |
162 } | 162 } |
163 | 163 |
164 FilePath test_file() { | 164 FilePath test_file() { |
165 return temp_dir_.path().AppendASCII("FilePathWatcherTest"); | 165 return temp_dir_.path().AppendASCII("FilePathWatcherTest"); |
166 } | 166 } |
167 | 167 |
| 168 FilePath test_link() { |
| 169 return temp_dir_.path().AppendASCII("FilePathWatcherTest.lnk"); |
| 170 } |
| 171 |
168 // Write |content| to |file|. Returns true on success. | 172 // Write |content| to |file|. Returns true on success. |
169 bool WriteFile(const FilePath& file, const std::string& content) { | 173 bool WriteFile(const FilePath& file, const std::string& content) { |
170 int write_size = file_util::WriteFile(file, content.c_str(), | 174 int write_size = file_util::WriteFile(file, content.c_str(), |
171 content.length()); | 175 content.length()); |
172 return write_size == static_cast<int>(content.length()); | 176 return write_size == static_cast<int>(content.length()); |
173 } | 177 } |
174 | 178 |
175 bool SetupWatch(const FilePath& target, | 179 bool SetupWatch(const FilePath& target, |
176 FilePathWatcher* watcher, | 180 FilePathWatcher* watcher, |
177 FilePathWatcher::Delegate* delegate) WARN_UNUSED_RESULT { | 181 FilePathWatcher::Delegate* delegate) WARN_UNUSED_RESULT { |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
487 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); | 491 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); |
488 ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get())); | 492 ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get())); |
489 | 493 |
490 // Now make sure we get notified if the file is modified. | 494 // Now make sure we get notified if the file is modified. |
491 ASSERT_TRUE(file_util::MakeFileUnreadable(test_file())); | 495 ASSERT_TRUE(file_util::MakeFileUnreadable(test_file())); |
492 ASSERT_TRUE(WaitForEvents()); | 496 ASSERT_TRUE(WaitForEvents()); |
493 } | 497 } |
494 | 498 |
495 #endif // !OS_LINUX | 499 #endif // !OS_LINUX |
496 | 500 |
| 501 #if defined(OS_LINUX) |
| 502 |
| 503 // Verify that creating a symlink is caught. |
| 504 TEST_F(FilePathWatcherTest, CreateLink) { |
| 505 FilePathWatcher watcher; |
| 506 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); |
| 507 // Note that we are watching the symlink |
| 508 ASSERT_TRUE(SetupWatch(test_link(), &watcher, delegate.get())); |
| 509 |
| 510 // Now make sure we get notified if the link is created. |
| 511 // Note that test_file() doesn't have to exist. |
| 512 ASSERT_TRUE(file_util::CreateSymbolicLink(test_file(), test_link())); |
| 513 ASSERT_TRUE(WaitForEvents()); |
| 514 } |
| 515 |
| 516 // Verify that deleting a symlink is caught. |
| 517 TEST_F(FilePathWatcherTest, DeleteLink) { |
| 518 // Unfortunately this test case only works if the link target exists. |
| 519 // TODO(craig) fix this as part of crbug.com/91561. |
| 520 ASSERT_TRUE(WriteFile(test_file(), "content")); |
| 521 ASSERT_TRUE(file_util::CreateSymbolicLink(test_file(), test_link())); |
| 522 FilePathWatcher watcher; |
| 523 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); |
| 524 ASSERT_TRUE(SetupWatch(test_link(), &watcher, delegate.get())); |
| 525 |
| 526 // Now make sure we get notified if the link is deleted. |
| 527 ASSERT_TRUE(file_util::Delete(test_link(), false)); |
| 528 ASSERT_TRUE(WaitForEvents()); |
| 529 } |
| 530 |
| 531 // Verify that modifying a target file that a link is pointing to |
| 532 // when we are watching the link is caught. |
| 533 TEST_F(FilePathWatcherTest, ModifiedLinkedFile) { |
| 534 ASSERT_TRUE(WriteFile(test_file(), "content")); |
| 535 ASSERT_TRUE(file_util::CreateSymbolicLink(test_file(), test_link())); |
| 536 FilePathWatcher watcher; |
| 537 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); |
| 538 // Note that we are watching the symlink. |
| 539 ASSERT_TRUE(SetupWatch(test_link(), &watcher, delegate.get())); |
| 540 |
| 541 // Now make sure we get notified if the file is modified. |
| 542 ASSERT_TRUE(WriteFile(test_file(), "new content")); |
| 543 ASSERT_TRUE(WaitForEvents()); |
| 544 } |
| 545 |
| 546 // Verify that creating a target file that a link is pointing to |
| 547 // when we are watching the link is caught. |
| 548 TEST_F(FilePathWatcherTest, CreateTargetLinkedFile) { |
| 549 ASSERT_TRUE(file_util::CreateSymbolicLink(test_file(), test_link())); |
| 550 FilePathWatcher watcher; |
| 551 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); |
| 552 // Note that we are watching the symlink. |
| 553 ASSERT_TRUE(SetupWatch(test_link(), &watcher, delegate.get())); |
| 554 |
| 555 // Now make sure we get notified if the target file is created. |
| 556 ASSERT_TRUE(WriteFile(test_file(), "content")); |
| 557 ASSERT_TRUE(WaitForEvents()); |
| 558 } |
| 559 |
| 560 // Verify that deleting a target file that a link is pointing to |
| 561 // when we are watching the link is caught. |
| 562 TEST_F(FilePathWatcherTest, DeleteTargetLinkedFile) { |
| 563 ASSERT_TRUE(WriteFile(test_file(), "content")); |
| 564 ASSERT_TRUE(file_util::CreateSymbolicLink(test_file(), test_link())); |
| 565 FilePathWatcher watcher; |
| 566 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); |
| 567 // Note that we are watching the symlink. |
| 568 ASSERT_TRUE(SetupWatch(test_link(), &watcher, delegate.get())); |
| 569 |
| 570 // Now make sure we get notified if the target file is deleted. |
| 571 ASSERT_TRUE(file_util::Delete(test_file(), false)); |
| 572 ASSERT_TRUE(WaitForEvents()); |
| 573 } |
| 574 |
| 575 // Verify that watching a file whose parent directory is a link that |
| 576 // doesn't exist yet works if the symlink is created eventually. |
| 577 TEST_F(FilePathWatcherTest, LinkedDirectoryPart1) { |
| 578 FilePathWatcher watcher; |
| 579 FilePath dir(temp_dir_.path().AppendASCII("dir")); |
| 580 FilePath link_dir(temp_dir_.path().AppendASCII("dir.lnk")); |
| 581 FilePath file(dir.AppendASCII("file")); |
| 582 FilePath linkfile(link_dir.AppendASCII("file")); |
| 583 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); |
| 584 // dir/file should exist. |
| 585 ASSERT_TRUE(file_util::CreateDirectory(dir)); |
| 586 ASSERT_TRUE(WriteFile(file, "content")); |
| 587 // Note that we are watching dir.lnk/file which doesn't exist yet. |
| 588 ASSERT_TRUE(SetupWatch(linkfile, &watcher, delegate.get())); |
| 589 |
| 590 ASSERT_TRUE(file_util::CreateSymbolicLink(dir, link_dir)); |
| 591 VLOG(1) << "Waiting for link creation"; |
| 592 ASSERT_TRUE(WaitForEvents()); |
| 593 |
| 594 ASSERT_TRUE(WriteFile(file, "content v2")); |
| 595 VLOG(1) << "Waiting for file change"; |
| 596 ASSERT_TRUE(WaitForEvents()); |
| 597 |
| 598 ASSERT_TRUE(file_util::Delete(file, false)); |
| 599 VLOG(1) << "Waiting for file deletion"; |
| 600 ASSERT_TRUE(WaitForEvents()); |
| 601 } |
| 602 |
| 603 // Verify that watching a file whose parent directory is a |
| 604 // dangling symlink works if the directory is created eventually. |
| 605 TEST_F(FilePathWatcherTest, LinkedDirectoryPart2) { |
| 606 FilePathWatcher watcher; |
| 607 FilePath dir(temp_dir_.path().AppendASCII("dir")); |
| 608 FilePath link_dir(temp_dir_.path().AppendASCII("dir.lnk")); |
| 609 FilePath file(dir.AppendASCII("file")); |
| 610 FilePath linkfile(link_dir.AppendASCII("file")); |
| 611 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); |
| 612 // Now create the link from dir.lnk pointing to dir but |
| 613 // neither dir nor dir/file exist yet. |
| 614 ASSERT_TRUE(file_util::CreateSymbolicLink(dir, link_dir)); |
| 615 // Note that we are watching dir.lnk/file. |
| 616 ASSERT_TRUE(SetupWatch(linkfile, &watcher, delegate.get())); |
| 617 |
| 618 ASSERT_TRUE(file_util::CreateDirectory(dir)); |
| 619 ASSERT_TRUE(WriteFile(file, "content")); |
| 620 VLOG(1) << "Waiting for dir/file creation"; |
| 621 ASSERT_TRUE(WaitForEvents()); |
| 622 |
| 623 ASSERT_TRUE(WriteFile(file, "content v2")); |
| 624 VLOG(1) << "Waiting for file change"; |
| 625 ASSERT_TRUE(WaitForEvents()); |
| 626 |
| 627 ASSERT_TRUE(file_util::Delete(file, false)); |
| 628 VLOG(1) << "Waiting for file deletion"; |
| 629 ASSERT_TRUE(WaitForEvents()); |
| 630 } |
| 631 |
| 632 // Verify that watching a file with a symlink on the path |
| 633 // to the file works. |
| 634 TEST_F(FilePathWatcherTest, LinkedDirectoryPart3) { |
| 635 FilePathWatcher watcher; |
| 636 FilePath dir(temp_dir_.path().AppendASCII("dir")); |
| 637 FilePath link_dir(temp_dir_.path().AppendASCII("dir.lnk")); |
| 638 FilePath file(dir.AppendASCII("file")); |
| 639 FilePath linkfile(link_dir.AppendASCII("file")); |
| 640 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); |
| 641 ASSERT_TRUE(file_util::CreateDirectory(dir)); |
| 642 ASSERT_TRUE(file_util::CreateSymbolicLink(dir, link_dir)); |
| 643 // Note that we are watching dir.lnk/file but the file doesn't exist yet. |
| 644 ASSERT_TRUE(SetupWatch(linkfile, &watcher, delegate.get())); |
| 645 |
| 646 ASSERT_TRUE(WriteFile(file, "content")); |
| 647 VLOG(1) << "Waiting for file creation"; |
| 648 ASSERT_TRUE(WaitForEvents()); |
| 649 |
| 650 ASSERT_TRUE(WriteFile(file, "content v2")); |
| 651 VLOG(1) << "Waiting for file change"; |
| 652 ASSERT_TRUE(WaitForEvents()); |
| 653 |
| 654 ASSERT_TRUE(file_util::Delete(file, false)); |
| 655 VLOG(1) << "Waiting for file deletion"; |
| 656 ASSERT_TRUE(WaitForEvents()); |
| 657 } |
| 658 |
| 659 #endif // OS_LINUX |
| 660 |
497 enum Permission { | 661 enum Permission { |
498 Read, | 662 Read, |
499 Write, | 663 Write, |
500 Execute | 664 Execute |
501 }; | 665 }; |
502 | 666 |
503 bool ChangeFilePermissions(const FilePath& path, Permission perm, bool allow) { | 667 bool ChangeFilePermissions(const FilePath& path, Permission perm, bool allow) { |
504 #if defined(OS_POSIX) | 668 #if defined(OS_POSIX) |
505 struct stat stat_buf; | 669 struct stat stat_buf; |
506 | 670 |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
619 ASSERT_TRUE(ChangeFilePermissions(test_dir1, Execute, false)); | 783 ASSERT_TRUE(ChangeFilePermissions(test_dir1, Execute, false)); |
620 ASSERT_TRUE(WaitForEvents()); | 784 ASSERT_TRUE(WaitForEvents()); |
621 ASSERT_TRUE(ChangeFilePermissions(test_dir1, Execute, true)); | 785 ASSERT_TRUE(ChangeFilePermissions(test_dir1, Execute, true)); |
622 } | 786 } |
623 | 787 |
624 #endif // OS_MACOSX | 788 #endif // OS_MACOSX |
625 } // namespace | 789 } // namespace |
626 | 790 |
627 } // namespace files | 791 } // namespace files |
628 } // namespace base | 792 } // namespace base |
OLD | NEW |