Chromium Code Reviews| 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 ASSERT_TRUE(WriteFile(test_file(), "content")); | |
|
Mattias Nissler (ping if slow)
2011/09/02 11:34:32
do you need the WriteFile()? I guess it shouldn't
Craig
2011/09/03 07:46:05
I put it in initially because I wanted the test to
| |
| 519 ASSERT_TRUE(file_util::CreateSymbolicLink(test_file(), test_link())); | |
| 520 FilePathWatcher watcher; | |
| 521 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); | |
| 522 ASSERT_TRUE(SetupWatch(test_link(), &watcher, delegate.get())); | |
| 523 | |
| 524 // Now make sure we get notified if the link is deleted. | |
| 525 ASSERT_TRUE(file_util::Delete(test_link(), false)); | |
| 526 ASSERT_TRUE(WaitForEvents()); | |
| 527 } | |
| 528 | |
| 529 // Verify that modifying a target file that a link is pointing to | |
| 530 // when we are watching the link is caught. | |
| 531 TEST_F(FilePathWatcherTest, ModifiedLinkedFile) { | |
| 532 ASSERT_TRUE(WriteFile(test_file(), "content")); | |
| 533 ASSERT_TRUE(file_util::CreateSymbolicLink(test_file(), test_link())); | |
| 534 FilePathWatcher watcher; | |
| 535 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); | |
| 536 // Note that we are watching the symlink. | |
| 537 ASSERT_TRUE(SetupWatch(test_link(), &watcher, delegate.get())); | |
| 538 | |
| 539 // Now make sure we get notified if the file is modified. | |
| 540 ASSERT_TRUE(WriteFile(test_file(), "new content")); | |
| 541 ASSERT_TRUE(WaitForEvents()); | |
| 542 } | |
| 543 | |
| 544 // Verify that creating a target file that a link is pointing to | |
| 545 // when we are watching the link is caught. | |
| 546 TEST_F(FilePathWatcherTest, CreateTargetLinkedFile) { | |
| 547 ASSERT_TRUE(file_util::CreateSymbolicLink(test_file(), test_link())); | |
| 548 FilePathWatcher watcher; | |
| 549 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); | |
| 550 // Note that we are watching the symlink. | |
| 551 ASSERT_TRUE(SetupWatch(test_link(), &watcher, delegate.get())); | |
| 552 | |
| 553 // Now make sure we get notified if the target file is created. | |
| 554 ASSERT_TRUE(WriteFile(test_file(), "content")); | |
| 555 ASSERT_TRUE(WaitForEvents()); | |
| 556 } | |
| 557 | |
| 558 // Verify that deleting a target file that a link is pointing to | |
| 559 // when we are watching the link is caught. | |
| 560 TEST_F(FilePathWatcherTest, DeleteTargetLinkedFile) { | |
| 561 ASSERT_TRUE(WriteFile(test_file(), "content")); | |
| 562 ASSERT_TRUE(file_util::CreateSymbolicLink(test_file(), test_link())); | |
| 563 FilePathWatcher watcher; | |
| 564 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); | |
| 565 // Note that we are watching the symlink. | |
| 566 ASSERT_TRUE(SetupWatch(test_link(), &watcher, delegate.get())); | |
| 567 | |
| 568 // Now make sure we get notified if the target file is deleted. | |
| 569 ASSERT_TRUE(file_util::Delete(test_file(), false)); | |
| 570 ASSERT_TRUE(WaitForEvents()); | |
| 571 } | |
| 572 | |
| 573 // Verify that watching a file whose parent directory is a link that | |
| 574 // doesn't exist yet works if the symlink is created eventually. | |
| 575 TEST_F(FilePathWatcherTest, LinkedDirectoryPart1) { | |
| 576 FilePathWatcher watcher; | |
| 577 FilePath dir(temp_dir_.path().AppendASCII("dir")); | |
| 578 FilePath link_dir(temp_dir_.path().AppendASCII("dir.lnk")); | |
| 579 FilePath file(dir.AppendASCII("file")); | |
| 580 FilePath linkfile(link_dir.AppendASCII("file")); | |
| 581 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); | |
| 582 // dir/file should exist. | |
| 583 ASSERT_TRUE(file_util::CreateDirectory(dir)); | |
| 584 ASSERT_TRUE(WriteFile(file, "content")); | |
| 585 // Note that we are watching dir.lnk/file which doesn't exist yet. | |
| 586 ASSERT_TRUE(SetupWatch(linkfile, &watcher, delegate.get())); | |
| 587 | |
| 588 ASSERT_TRUE(file_util::CreateSymbolicLink(dir, link_dir)); | |
| 589 VLOG(1) << "Waiting for link creation"; | |
| 590 ASSERT_TRUE(WaitForEvents()); | |
| 591 | |
| 592 ASSERT_TRUE(WriteFile(file, "content v2")); | |
| 593 VLOG(1) << "Waiting for file change"; | |
| 594 ASSERT_TRUE(WaitForEvents()); | |
| 595 | |
| 596 ASSERT_TRUE(file_util::Delete(file, false)); | |
| 597 VLOG(1) << "Waiting for file deletion"; | |
| 598 ASSERT_TRUE(WaitForEvents()); | |
| 599 } | |
| 600 | |
| 601 // Verify that watching a file whose parent directory is a | |
| 602 // dangling symlink works if the directory is created eventually. | |
| 603 TEST_F(FilePathWatcherTest, LinkedDirectoryPart2) { | |
| 604 FilePathWatcher watcher; | |
| 605 FilePath dir(temp_dir_.path().AppendASCII("dir")); | |
| 606 FilePath link_dir(temp_dir_.path().AppendASCII("dir.lnk")); | |
| 607 FilePath file(dir.AppendASCII("file")); | |
| 608 FilePath linkfile(link_dir.AppendASCII("file")); | |
| 609 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); | |
| 610 // Now create the link from dir.lnk pointing to dir but | |
| 611 // neither dir nor dir/file exist yet. | |
| 612 ASSERT_TRUE(file_util::CreateSymbolicLink(dir, link_dir)); | |
| 613 // Note that we are watching dir.lnk/file. | |
| 614 ASSERT_TRUE(SetupWatch(linkfile, &watcher, delegate.get())); | |
| 615 | |
| 616 ASSERT_TRUE(file_util::CreateDirectory(dir)); | |
| 617 ASSERT_TRUE(WriteFile(file, "content")); | |
| 618 VLOG(1) << "Waiting for dir/file creation"; | |
| 619 ASSERT_TRUE(WaitForEvents()); | |
| 620 | |
| 621 ASSERT_TRUE(WriteFile(file, "content v2")); | |
| 622 VLOG(1) << "Waiting for file change"; | |
| 623 ASSERT_TRUE(WaitForEvents()); | |
| 624 | |
| 625 ASSERT_TRUE(file_util::Delete(file, false)); | |
| 626 VLOG(1) << "Waiting for file deletion"; | |
| 627 ASSERT_TRUE(WaitForEvents()); | |
| 628 } | |
| 629 | |
| 630 // Verify that watching a file with a symlink on the path | |
| 631 // to the file works. | |
| 632 TEST_F(FilePathWatcherTest, LinkedDirectoryPart3) { | |
| 633 FilePathWatcher watcher; | |
| 634 FilePath dir(temp_dir_.path().AppendASCII("dir")); | |
| 635 FilePath link_dir(temp_dir_.path().AppendASCII("dir.lnk")); | |
| 636 FilePath file(dir.AppendASCII("file")); | |
| 637 FilePath linkfile(link_dir.AppendASCII("file")); | |
| 638 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); | |
| 639 ASSERT_TRUE(file_util::CreateDirectory(dir)); | |
| 640 ASSERT_TRUE(file_util::CreateSymbolicLink(dir, link_dir)); | |
| 641 // Note that we are watching dir.lnk/file but the file doesn't exist yet. | |
| 642 ASSERT_TRUE(SetupWatch(linkfile, &watcher, delegate.get())); | |
| 643 | |
| 644 ASSERT_TRUE(WriteFile(file, "content")); | |
| 645 VLOG(1) << "Waiting for file creation"; | |
| 646 ASSERT_TRUE(WaitForEvents()); | |
| 647 | |
| 648 ASSERT_TRUE(WriteFile(file, "content v2")); | |
| 649 VLOG(1) << "Waiting for file change"; | |
| 650 ASSERT_TRUE(WaitForEvents()); | |
| 651 | |
| 652 ASSERT_TRUE(file_util::Delete(file, false)); | |
| 653 VLOG(1) << "Waiting for file deletion"; | |
| 654 ASSERT_TRUE(WaitForEvents()); | |
| 655 } | |
| 656 | |
| 657 #endif // OS_LINUX | |
| 658 | |
| 497 enum Permission { | 659 enum Permission { |
| 498 Read, | 660 Read, |
| 499 Write, | 661 Write, |
| 500 Execute | 662 Execute |
| 501 }; | 663 }; |
| 502 | 664 |
| 503 bool ChangeFilePermissions(const FilePath& path, Permission perm, bool allow) { | 665 bool ChangeFilePermissions(const FilePath& path, Permission perm, bool allow) { |
| 504 #if defined(OS_POSIX) | 666 #if defined(OS_POSIX) |
| 505 struct stat stat_buf; | 667 struct stat stat_buf; |
| 506 | 668 |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 619 ASSERT_TRUE(ChangeFilePermissions(test_dir1, Execute, false)); | 781 ASSERT_TRUE(ChangeFilePermissions(test_dir1, Execute, false)); |
| 620 ASSERT_TRUE(WaitForEvents()); | 782 ASSERT_TRUE(WaitForEvents()); |
| 621 ASSERT_TRUE(ChangeFilePermissions(test_dir1, Execute, true)); | 783 ASSERT_TRUE(ChangeFilePermissions(test_dir1, Execute, true)); |
| 622 } | 784 } |
| 623 | 785 |
| 624 #endif // OS_MACOSX | 786 #endif // OS_MACOSX |
| 625 } // namespace | 787 } // namespace |
| 626 | 788 |
| 627 } // namespace files | 789 } // namespace files |
| 628 } // namespace base | 790 } // namespace base |
| OLD | NEW |