summaryrefslogtreecommitdiffstats
path: root/base/directory_watcher_unittest.cc
diff options
context:
space:
mode:
authorevanm@google.com <evanm@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-17 02:45:56 +0000
committerevanm@google.com <evanm@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-17 02:45:56 +0000
commit9e8d4f92df67dd8d4c8d4097035aaf6279fe84ba (patch)
treeed08cb639f07c35da5eabc10f4519cb88c10ae64 /base/directory_watcher_unittest.cc
parent9b6633c2877f08381f84f60a33a5eeb9bfa0f3e0 (diff)
downloadchromium_src-9e8d4f92df67dd8d4c8d4097035aaf6279fe84ba.zip
chromium_src-9e8d4f92df67dd8d4c8d4097035aaf6279fe84ba.tar.gz
chromium_src-9e8d4f92df67dd8d4c8d4097035aaf6279fe84ba.tar.bz2
Add a DirectoryWatcher class, allowing objects to be notified whenever
a directory's contents change. Review URL: http://codereview.chromium.org/6377 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@3504 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/directory_watcher_unittest.cc')
-rw-r--r--base/directory_watcher_unittest.cc174
1 files changed, 174 insertions, 0 deletions
diff --git a/base/directory_watcher_unittest.cc b/base/directory_watcher_unittest.cc
new file mode 100644
index 0000000..5121287
--- /dev/null
+++ b/base/directory_watcher_unittest.cc
@@ -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();
+ }
+
+ MessageLoop loop_;
+
+ // 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);
+}