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 |