Index: base/directory_watcher_unittest.cc |
=================================================================== |
--- base/directory_watcher_unittest.cc (revision 0) |
+++ base/directory_watcher_unittest.cc (revision 0) |
@@ -0,0 +1,174 @@ |
+// Copyright (c) 2008 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "base/directory_watcher.h" |
+ |
+#include <fstream> |
+ |
+#include "base/file_path.h" |
+#include "base/file_util.h" |
+#include "base/logging.h" |
+#include "base/message_loop.h" |
+#include "base/path_service.h" |
+#include "base/string_util.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+// For tests where we wait a bit to verify nothing happened |
+namespace { |
+const int kWaitForEventTime = 500; |
+} |
+ |
+class DirectoryWatcherTest : public testing::Test, |
+ public DirectoryWatcher::Delegate { |
+ protected: |
+ virtual void SetUp() { |
+ // Name a subdirectory of the temp directory. |
+ std::wstring path_str; |
+ ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &path_str)); |
+ test_dir_ = FilePath(path_str).Append( |
+ FILE_PATH_LITERAL("DirectoryWatcherTest")); |
+ |
+ // Create a fresh, empty copy of this directory. |
+ file_util::Delete(test_dir_.value(), true); |
+ file_util::CreateDirectory(test_dir_.value()); |
+ |
+ directory_mods_ = 0; |
+ quit_mod_count_ = 0; |
+ } |
+ |
+ virtual void OnDirectoryChanged(const FilePath& path) { |
+ ++directory_mods_; |
+ if (directory_mods_ == quit_mod_count_) |
+ MessageLoop::current()->Quit(); |
+ } |
+ |
+ virtual void TearDown() { |
+ // Clean up test directory. |
+ ASSERT_TRUE(file_util::Delete(test_dir_.value(), true)); |
+ ASSERT_FALSE(file_util::PathExists(test_dir_.value())); |
+ } |
+ |
+ // Write |content| to a file under the test directory. |
+ void WriteTestDirFile(const FilePath::StringType& filename, |
+ const std::string& content) { |
+ FilePath path = test_dir_.Append(filename); |
+ |
+ std::ofstream file; |
+ file.open(WideToUTF8(path.value()).c_str()); |
+ file << content; |
+ file.close(); |
+ } |
+ |
+ // Run the message loop until we've seen |n| directory modifications. |
+ void LoopUntilModsEqual(int n) { |
+ quit_mod_count_ = n; |
+ loop_.Run(); |
+ } |
+ |
+ MessageLoopForIO loop_; |
darin (slow to review)
2008/10/17 02:43:51
I don't think DirectoryWatcher is limited to only
|
+ |
+ // 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 directory mods which, when reached, cause us to quit |
+ // our message loop. |
+ int quit_mod_count_; |
+}; |
+ |
+// Basic test: add a file and verify we notice it. |
+TEST_F(DirectoryWatcherTest, NewFile) { |
+ DirectoryWatcher watcher; |
+ ASSERT_TRUE(watcher.Watch(test_dir_, this)); |
+ |
+ WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some content"); |
+ LoopUntilModsEqual(2); |
+} |
+ |
+// Verify that modifying a file is caught. |
+TEST_F(DirectoryWatcherTest, ModifiedFile) { |
+ DirectoryWatcher watcher; |
+ ASSERT_TRUE(watcher.Watch(test_dir_, this)); |
+ |
+ // Write a file to the test dir. |
+ WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some content"); |
+ LoopUntilModsEqual(2); |
+ |
+ // Now make sure we get notified if the file is modified. |
+ WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some new content"); |
+ LoopUntilModsEqual(3); |
+} |
+ |
+// Verify that letting the watcher go out of scope stops notifications. |
+TEST_F(DirectoryWatcherTest, Unregister) { |
+ { |
+ DirectoryWatcher watcher; |
+ ASSERT_TRUE(watcher.Watch(test_dir_, this)); |
+ |
+ // And then let it fall out of scope, clearing its watch. |
+ } |
+ |
+ // Write a file to the test dir. |
+ WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some content"); |
+ |
+ // We won't get a notification, so we just wait around a bit to verify |
+ // that notification doesn't come. |
+ loop_.PostDelayedTask(FROM_HERE, new MessageLoop::QuitTask, |
+ kWaitForEventTime); |
+ loop_.Run(); |
+ |
+ ASSERT_EQ(directory_mods_, 0); |
+} |
+ |
+// Verify that modifications to a subdirectory isn't noticed. |
+TEST_F(DirectoryWatcherTest, SubDir) { |
+ FilePath subdir = test_dir_.Append(FILE_PATH_LITERAL("SubDir")); |
+ ASSERT_TRUE(file_util::CreateDirectory(subdir.value())); |
+ |
+ DirectoryWatcher watcher; |
+ ASSERT_TRUE(watcher.Watch(test_dir_, this)); |
+ // Write a file to the subdir. |
+ FilePath test_path = subdir.Append(FILE_PATH_LITERAL("test_file")); |
+ WriteTestDirFile(test_path.value(), "some content"); |
+ |
+ // We won't get a notification, so we just wait around a bit to verify |
+ // that notification doesn't come. |
+ loop_.PostDelayedTask(FROM_HERE, new MessageLoop::QuitTask, |
+ kWaitForEventTime); |
+ loop_.Run(); |
+ |
+ // We shouldn't have been notified and shouldn't have crashed. |
+ ASSERT_EQ(directory_mods_, 0); |
+} |
+ |
+namespace { |
+// Used by the DeleteDuringNotify test below. |
+// Deletes the DirectoryWatcher when it's notified. |
+class Deleter : public DirectoryWatcher::Delegate { |
+ public: |
+ Deleter(DirectoryWatcher* watcher) : watcher_(watcher) {} |
+ virtual void OnDirectoryChanged(const FilePath& path) { |
+ watcher_.reset(NULL); |
+ MessageLoop::current()->Quit(); |
+ } |
+ |
+ scoped_ptr<DirectoryWatcher> watcher_; |
+}; |
+} // anonymous namespace |
+ |
+// Verify that deleting a watcher during the callback |
+TEST_F(DirectoryWatcherTest, DeleteDuringNotify) { |
+ DirectoryWatcher* watcher = new DirectoryWatcher; |
+ Deleter deleter(watcher); // Takes ownership of watcher. |
+ ASSERT_TRUE(watcher->Watch(test_dir_, &deleter)); |
+ |
+ WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some content"); |
+ LoopUntilModsEqual(2); |
+ |
+ // We win if we haven't crashed yet. |
+ // Might as well double-check it got deleted, too. |
+ ASSERT_TRUE(deleter.watcher_.get() == NULL); |
+} |
Property changes on: base\directory_watcher_unittest.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |