| Index: base/directory_watcher_unittest.cc
|
| diff --git a/base/directory_watcher_unittest.cc b/base/directory_watcher_unittest.cc
|
| index fabd46fe524b90dcc51350d3dcf19192e6e918e2..9ca5cda9c9a18611fc78cfc2ff3bc2567f988d9d 100644
|
| --- a/base/directory_watcher_unittest.cc
|
| +++ b/base/directory_watcher_unittest.cc
|
| @@ -21,12 +21,20 @@
|
| namespace {
|
|
|
| // For tests where we wait a bit to verify nothing happened
|
| -const int kWaitForEventTime = 500;
|
| +const int kWaitForEventTime = 1000;
|
|
|
| -} // namespace
|
| +class DirectoryWatcherTest : public testing::Test {
|
| + public:
|
| + // Implementation of DirectoryWatcher on Mac requires UI loop.
|
| + DirectoryWatcherTest() : loop_(MessageLoop::TYPE_UI) {
|
| + }
|
| +
|
| + void OnTestDelegateFirstNotification(const FilePath& path) {
|
| + notified_delegates_++;
|
| + if (notified_delegates_ >= expected_notified_delegates_)
|
| + MessageLoop::current()->Quit();
|
| + }
|
|
|
| -class DirectoryWatcherTest : public testing::Test,
|
| - public DirectoryWatcher::Delegate {
|
| protected:
|
| virtual void SetUp() {
|
| // Name a subdirectory of the temp directory.
|
| @@ -37,20 +45,6 @@ class DirectoryWatcherTest : public testing::Test,
|
| // Create a fresh, empty copy of this directory.
|
| file_util::Delete(test_dir_, true);
|
| file_util::CreateDirectory(test_dir_);
|
| -
|
| - directory_mods_ = 0;
|
| - quit_mod_count_ = 0;
|
| -
|
| - original_thread_id_ = PlatformThread::CurrentId();
|
| - }
|
| -
|
| - virtual void OnDirectoryChanged(const FilePath& path) {
|
| - EXPECT_EQ(original_thread_id_, PlatformThread::CurrentId());
|
| - ++directory_mods_;
|
| - // The exact number is verified by VerifyExpectedNumberOfModifications.
|
| - // Sometimes we don't want such check, see WaitForFirstNotification.
|
| - if (directory_mods_ >= quit_mod_count_)
|
| - MessageLoop::current()->Quit();
|
| }
|
|
|
| virtual void TearDown() {
|
| @@ -69,29 +63,31 @@ class DirectoryWatcherTest : public testing::Test,
|
| file_util::WriteFile(path, content.c_str(), content.length());
|
| }
|
|
|
| - void SetExpectedNumberOfModifications(int n) {
|
| - quit_mod_count_ = n;
|
| + void SetExpectedNumberOfNotifiedDelegates(int n) {
|
| + notified_delegates_ = 0;
|
| + expected_notified_delegates_ = n;
|
| }
|
|
|
| - void VerifyExpectedNumberOfModifications() {
|
| - // Check that we get at least the expected number of notifications.
|
| - if (quit_mod_count_ - directory_mods_ > 0)
|
| + void VerifyExpectedNumberOfNotifiedDelegates() {
|
| + // Check that we get at least the expected number of notified delegates.
|
| + if (expected_notified_delegates_ - notified_delegates_ > 0)
|
| loop_.Run();
|
|
|
| - // Check that we get no more than the expected number of notifications.
|
| + // Check that we get no more than the expected number of notified delegates.
|
| loop_.PostDelayedTask(FROM_HERE, new MessageLoop::QuitTask,
|
| kWaitForEventTime);
|
| loop_.Run();
|
| - EXPECT_EQ(quit_mod_count_, directory_mods_);
|
| + EXPECT_EQ(expected_notified_delegates_, notified_delegates_);
|
| }
|
|
|
| - // Only use this function if you don't care about getting
|
| - // too many notifications. Useful for tests where you get
|
| - // different number of notifications on different platforms.
|
| - void WaitForFirstNotification() {
|
| - directory_mods_ = 0;
|
| - SetExpectedNumberOfModifications(1);
|
| - loop_.Run();
|
| + // We need this function for reliable tests on Mac OS X. FSEvents API
|
| + // has a latency interval and can merge multiple events into one,
|
| + // and we need a clear distinction between events triggered by test setup code
|
| + // and test code.
|
| + void SyncIfPOSIX() {
|
| +#if defined(OS_POSIX)
|
| + sync();
|
| +#endif // defined(OS_POSIX)
|
| }
|
|
|
| MessageLoop loop_;
|
| @@ -99,12 +95,42 @@ class DirectoryWatcherTest : public testing::Test,
|
| // The path to a temporary directory used for testing.
|
| FilePath test_dir_;
|
|
|
| - // The number of times a directory modification has been observed.
|
| - int directory_mods_;
|
| + // The number of test delegates which received their notification.
|
| + int notified_delegates_;
|
| +
|
| + // The number of notified test delegates after which we quit the message loop.
|
| + int expected_notified_delegates_;
|
| +};
|
|
|
| - // The number of directory mods which, when reached, cause us to quit
|
| - // our message loop.
|
| - int quit_mod_count_;
|
| +class TestDelegate : public DirectoryWatcher::Delegate {
|
| + public:
|
| + TestDelegate(DirectoryWatcherTest* test)
|
| + : test_(test),
|
| + got_notification_(false),
|
| + original_thread_id_(PlatformThread::CurrentId()) {
|
| + }
|
| +
|
| + bool got_notification() const {
|
| + return got_notification_;
|
| + }
|
| +
|
| + void reset() {
|
| + got_notification_ = false;
|
| + }
|
| +
|
| + virtual void OnDirectoryChanged(const FilePath& path) {
|
| + EXPECT_EQ(original_thread_id_, PlatformThread::CurrentId());
|
| + if (!got_notification_)
|
| + test_->OnTestDelegateFirstNotification(path);
|
| + got_notification_ = true;
|
| + }
|
| +
|
| + private:
|
| + // Hold a pointer to current test fixture to inform it on first notification.
|
| + DirectoryWatcherTest* test_;
|
| +
|
| + // Set to true after first notification.
|
| + bool got_notification_;
|
|
|
| // Keep track of original thread id to verify that callbacks are called
|
| // on the same thread.
|
| @@ -114,63 +140,68 @@ class DirectoryWatcherTest : public testing::Test,
|
| // Basic test: add a file and verify we notice it.
|
| TEST_F(DirectoryWatcherTest, NewFile) {
|
| DirectoryWatcher watcher;
|
| - ASSERT_TRUE(watcher.Watch(test_dir_, this, false));
|
| + TestDelegate delegate(this);
|
| + ASSERT_TRUE(watcher.Watch(test_dir_, &delegate, false));
|
|
|
| - SetExpectedNumberOfModifications(2);
|
| + SetExpectedNumberOfNotifiedDelegates(1);
|
| WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some content");
|
| - VerifyExpectedNumberOfModifications();
|
| + VerifyExpectedNumberOfNotifiedDelegates();
|
| }
|
|
|
| // Verify that modifying a file is caught.
|
| TEST_F(DirectoryWatcherTest, ModifiedFile) {
|
| - DirectoryWatcher watcher;
|
| - ASSERT_TRUE(watcher.Watch(test_dir_, this, false));
|
| -
|
| // Write a file to the test dir.
|
| - SetExpectedNumberOfModifications(2);
|
| WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some content");
|
| - VerifyExpectedNumberOfModifications();
|
| +
|
| + SyncIfPOSIX();
|
| +
|
| + DirectoryWatcher watcher;
|
| + TestDelegate delegate(this);
|
| + ASSERT_TRUE(watcher.Watch(test_dir_, &delegate, false));
|
|
|
| // Now make sure we get notified if the file is modified.
|
| + SetExpectedNumberOfNotifiedDelegates(1);
|
| WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some new content");
|
| - // Use a more forgiving function to check because on Linux you will get
|
| - // 1 notification, and on Windows 2 (and nothing seems to convince it to
|
| - // send less notifications).
|
| - WaitForFirstNotification();
|
| + VerifyExpectedNumberOfNotifiedDelegates();
|
| }
|
|
|
| // Verify that letting the watcher go out of scope stops notifications.
|
| TEST_F(DirectoryWatcherTest, Unregister) {
|
| + TestDelegate delegate(this);
|
| +
|
| {
|
| DirectoryWatcher watcher;
|
| - ASSERT_TRUE(watcher.Watch(test_dir_, this, false));
|
| + ASSERT_TRUE(watcher.Watch(test_dir_, &delegate, false));
|
|
|
| // And then let it fall out of scope, clearing its watch.
|
| }
|
|
|
| // Write a file to the test dir.
|
| - SetExpectedNumberOfModifications(0);
|
| + SetExpectedNumberOfNotifiedDelegates(0);
|
| WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some content");
|
| - VerifyExpectedNumberOfModifications();
|
| + VerifyExpectedNumberOfNotifiedDelegates();
|
| }
|
|
|
| TEST_F(DirectoryWatcherTest, SubDirRecursive) {
|
| FilePath subdir(FILE_PATH_LITERAL("SubDir"));
|
| ASSERT_TRUE(file_util::CreateDirectory(test_dir_.Append(subdir)));
|
|
|
| -#if !defined(OS_WIN)
|
| +#if defined(OS_LINUX)
|
| // TODO(port): Recursive watches are not implemented on Linux.
|
| return;
|
| #endif // !defined(OS_WIN)
|
|
|
| + SyncIfPOSIX();
|
| +
|
| // Verify that modifications to a subdirectory are noticed by recursive watch.
|
| + TestDelegate delegate(this);
|
| DirectoryWatcher watcher;
|
| - ASSERT_TRUE(watcher.Watch(test_dir_, this, true));
|
| + ASSERT_TRUE(watcher.Watch(test_dir_, &delegate, true));
|
| // Write a file to the subdir.
|
| - SetExpectedNumberOfModifications(2);
|
| + SetExpectedNumberOfNotifiedDelegates(1);
|
| FilePath test_path = subdir.AppendASCII("test_file");
|
| WriteTestDirFile(test_path.value(), "some content");
|
| - VerifyExpectedNumberOfModifications();
|
| + VerifyExpectedNumberOfNotifiedDelegates();
|
| }
|
|
|
| TEST_F(DirectoryWatcherTest, SubDirNonRecursive) {
|
| @@ -189,15 +220,18 @@ TEST_F(DirectoryWatcherTest, SubDirNonRecursive) {
|
| FilePath test_path = subdir.AppendASCII("test_file");
|
| WriteTestDirFile(test_path.value(), "some content");
|
|
|
| + SyncIfPOSIX();
|
| +
|
| // Verify that modifications to a subdirectory are not noticed
|
| // by a not-recursive watch.
|
| DirectoryWatcher watcher;
|
| - ASSERT_TRUE(watcher.Watch(test_dir_, this, false));
|
| + TestDelegate delegate(this);
|
| + ASSERT_TRUE(watcher.Watch(test_dir_, &delegate, false));
|
|
|
| // Modify the test file. There should be no notifications.
|
| - SetExpectedNumberOfModifications(0);
|
| + SetExpectedNumberOfNotifiedDelegates(0);
|
| WriteTestDirFile(test_path.value(), "some other content");
|
| - VerifyExpectedNumberOfModifications();
|
| + VerifyExpectedNumberOfNotifiedDelegates();
|
| }
|
|
|
| namespace {
|
| @@ -236,37 +270,41 @@ TEST_F(DirectoryWatcherTest, DeleteDuringNotify) {
|
|
|
| TEST_F(DirectoryWatcherTest, MultipleWatchersSingleFile) {
|
| DirectoryWatcher watcher1, watcher2;
|
| - ASSERT_TRUE(watcher1.Watch(test_dir_, this, false));
|
| - ASSERT_TRUE(watcher2.Watch(test_dir_, this, false));
|
| + TestDelegate delegate1(this), delegate2(this);
|
| + ASSERT_TRUE(watcher1.Watch(test_dir_, &delegate1, false));
|
| + ASSERT_TRUE(watcher2.Watch(test_dir_, &delegate2, false));
|
|
|
| - SetExpectedNumberOfModifications(4); // Each watcher should fire twice.
|
| + SetExpectedNumberOfNotifiedDelegates(2);
|
| WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some content");
|
| - VerifyExpectedNumberOfModifications();
|
| + VerifyExpectedNumberOfNotifiedDelegates();
|
| }
|
|
|
| TEST_F(DirectoryWatcherTest, MultipleWatchersDifferentFiles) {
|
| const int kNumberOfWatchers = 5;
|
| DirectoryWatcher watchers[kNumberOfWatchers];
|
| + TestDelegate delegates[kNumberOfWatchers] = {this, this, this, this, this};
|
| FilePath subdirs[kNumberOfWatchers];
|
| for (int i = 0; i < kNumberOfWatchers; i++) {
|
| subdirs[i] = FilePath(FILE_PATH_LITERAL("Dir")).AppendASCII(IntToString(i));
|
| ASSERT_TRUE(file_util::CreateDirectory(test_dir_.Append(subdirs[i])));
|
|
|
| - ASSERT_TRUE(watchers[i].Watch(test_dir_.Append(subdirs[i]), this, false));
|
| + ASSERT_TRUE(watchers[i].Watch(test_dir_.Append(subdirs[i]), &delegates[i],
|
| + false));
|
| }
|
| for (int i = 0; i < kNumberOfWatchers; i++) {
|
| // Verify that we only get modifications from one watcher (each watcher has
|
| // different directory).
|
|
|
| - ASSERT_EQ(0, directory_mods_);
|
| + for (int j = 0; j < kNumberOfWatchers; j++)
|
| + delegates[j].reset();
|
|
|
| // Write a file to the subdir.
|
| FilePath test_path = subdirs[i].AppendASCII("test_file");
|
| - SetExpectedNumberOfModifications(2);
|
| + SetExpectedNumberOfNotifiedDelegates(1);
|
| WriteTestDirFile(test_path.value(), "some content");
|
| - VerifyExpectedNumberOfModifications();
|
| + VerifyExpectedNumberOfNotifiedDelegates();
|
|
|
| - directory_mods_ = 0;
|
| + loop_.RunAllPending();
|
| }
|
| }
|
|
|
| @@ -275,6 +313,8 @@ TEST_F(DirectoryWatcherTest, MultipleWatchersDifferentFiles) {
|
| // Basic test: add a file and verify we notice it.
|
| TEST_F(DirectoryWatcherTest, NonExistentDirectory) {
|
| DirectoryWatcher watcher;
|
| - ASSERT_FALSE(watcher.Watch(test_dir_.AppendASCII("does-not-exist"), this,
|
| + ASSERT_FALSE(watcher.Watch(test_dir_.AppendASCII("does-not-exist"), NULL,
|
| false));
|
| }
|
| +
|
| +} // namespace
|
|
|