| OLD | NEW |
| 1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2008 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/directory_watcher.h" | 5 #include "base/directory_watcher.h" |
| 6 | 6 |
| 7 #include <fstream> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "build/build_config.h" | 9 #include "base/basictypes.h" |
| 10 | |
| 11 #include "base/file_path.h" | 10 #include "base/file_path.h" |
| 12 #include "base/file_util.h" | 11 #include "base/file_util.h" |
| 13 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
| 14 #include "base/path_service.h" | 13 #include "base/path_service.h" |
| 15 #include "base/platform_thread.h" | 14 #include "base/platform_thread.h" |
| 16 #include "base/string_util.h" | 15 #include "base/string_util.h" |
| 17 #if defined(OS_WIN) | |
| 18 #include "base/win_util.h" | |
| 19 #endif | |
| 20 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 21 | 17 |
| 22 // TODO(phajdan.jr): Clean up ifdefs in this file when Linux/Windows differences | |
| 23 // get sorted out. | |
| 24 | |
| 25 namespace { | 18 namespace { |
| 26 | 19 |
| 27 // For tests where we wait a bit to verify nothing happened | 20 // For tests where we wait a bit to verify nothing happened |
| 28 const int kWaitForEventTime = 500; | 21 const int kWaitForEventTime = 500; |
| 29 | 22 |
| 30 // Unfortunately Windows supports only recursive watches and Linux | |
| 31 // only non-recursive ones. | |
| 32 #if defined(OS_WIN) | |
| 33 const bool kDefaultRecursiveValue = true; | |
| 34 #elif defined(OS_LINUX) | |
| 35 const bool kDefaultRecursiveValue = false; | |
| 36 #endif | |
| 37 | |
| 38 } // namespace | 23 } // namespace |
| 39 | 24 |
| 40 class DirectoryWatcherTest : public testing::Test, | 25 class DirectoryWatcherTest : public testing::Test, |
| 41 public DirectoryWatcher::Delegate { | 26 public DirectoryWatcher::Delegate { |
| 42 protected: | 27 protected: |
| 43 virtual void SetUp() { | 28 virtual void SetUp() { |
| 44 // Name a subdirectory of the temp directory. | 29 // Name a subdirectory of the temp directory. |
| 45 FilePath path; | 30 FilePath path; |
| 46 ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &path)); | 31 ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &path)); |
| 47 test_dir_ = path.Append(FILE_PATH_LITERAL("DirectoryWatcherTest")); | 32 test_dir_ = path.Append(FILE_PATH_LITERAL("DirectoryWatcherTest")); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 int quit_mod_count_; | 104 int quit_mod_count_; |
| 120 | 105 |
| 121 // Keep track of original thread id to verify that callbacks are called | 106 // Keep track of original thread id to verify that callbacks are called |
| 122 // on the same thread. | 107 // on the same thread. |
| 123 PlatformThreadId original_thread_id_; | 108 PlatformThreadId original_thread_id_; |
| 124 }; | 109 }; |
| 125 | 110 |
| 126 // Basic test: add a file and verify we notice it. | 111 // Basic test: add a file and verify we notice it. |
| 127 TEST_F(DirectoryWatcherTest, NewFile) { | 112 TEST_F(DirectoryWatcherTest, NewFile) { |
| 128 DirectoryWatcher watcher; | 113 DirectoryWatcher watcher; |
| 129 ASSERT_TRUE(watcher.Watch(test_dir_, this, kDefaultRecursiveValue)); | 114 ASSERT_TRUE(watcher.Watch(test_dir_, this, false)); |
| 130 | 115 |
| 131 SetExpectedNumberOfModifications(2); | 116 SetExpectedNumberOfModifications(2); |
| 132 WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some content"); | 117 WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some content"); |
| 133 VerifyExpectedNumberOfModifications(); | 118 VerifyExpectedNumberOfModifications(); |
| 134 } | 119 } |
| 135 | 120 |
| 136 // Verify that modifying a file is caught. | 121 // Verify that modifying a file is caught. |
| 137 TEST_F(DirectoryWatcherTest, ModifiedFile) { | 122 TEST_F(DirectoryWatcherTest, ModifiedFile) { |
| 138 DirectoryWatcher watcher; | 123 DirectoryWatcher watcher; |
| 139 ASSERT_TRUE(watcher.Watch(test_dir_, this, kDefaultRecursiveValue)); | 124 ASSERT_TRUE(watcher.Watch(test_dir_, this, false)); |
| 140 | 125 |
| 141 // Write a file to the test dir. | 126 // Write a file to the test dir. |
| 142 SetExpectedNumberOfModifications(2); | 127 SetExpectedNumberOfModifications(2); |
| 143 WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some content"); | 128 WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some content"); |
| 144 VerifyExpectedNumberOfModifications(); | 129 VerifyExpectedNumberOfModifications(); |
| 145 | 130 |
| 146 // Now make sure we get notified if the file is modified. | 131 // Now make sure we get notified if the file is modified. |
| 147 WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some new content"); | 132 WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some new content"); |
| 148 // Use a more forgiving function to check because on Linux you will get | 133 // Use a more forgiving function to check because on Linux you will get |
| 149 // 1 notification, and on Windows 2 (and nothing seems to convince it to | 134 // 1 notification, and on Windows 2 (and nothing seems to convince it to |
| 150 // send less notifications). | 135 // send less notifications). |
| 151 WaitForFirstNotification(); | 136 WaitForFirstNotification(); |
| 152 } | 137 } |
| 153 | 138 |
| 154 // Verify that letting the watcher go out of scope stops notifications. | 139 // Verify that letting the watcher go out of scope stops notifications. |
| 155 TEST_F(DirectoryWatcherTest, Unregister) { | 140 TEST_F(DirectoryWatcherTest, Unregister) { |
| 156 { | 141 { |
| 157 DirectoryWatcher watcher; | 142 DirectoryWatcher watcher; |
| 158 ASSERT_TRUE(watcher.Watch(test_dir_, this, kDefaultRecursiveValue)); | 143 ASSERT_TRUE(watcher.Watch(test_dir_, this, false)); |
| 159 | 144 |
| 160 // And then let it fall out of scope, clearing its watch. | 145 // And then let it fall out of scope, clearing its watch. |
| 161 } | 146 } |
| 162 | 147 |
| 163 // Write a file to the test dir. | 148 // Write a file to the test dir. |
| 164 SetExpectedNumberOfModifications(0); | 149 SetExpectedNumberOfModifications(0); |
| 165 WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some content"); | 150 WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some content"); |
| 166 VerifyExpectedNumberOfModifications(); | 151 VerifyExpectedNumberOfModifications(); |
| 167 } | 152 } |
| 168 | 153 |
| 169 TEST_F(DirectoryWatcherTest, SubDir) { | 154 TEST_F(DirectoryWatcherTest, SubDirRecursive) { |
| 170 FilePath subdir(FILE_PATH_LITERAL("SubDir")); | 155 FilePath subdir(FILE_PATH_LITERAL("SubDir")); |
| 171 ASSERT_TRUE(file_util::CreateDirectory(test_dir_.Append(subdir))); | 156 ASSERT_TRUE(file_util::CreateDirectory(test_dir_.Append(subdir))); |
| 172 | 157 |
| 173 #if defined(OS_WIN) | 158 #if !defined(OS_WIN) |
| 174 // TODO(port): Recursive watches are not implemented on Linux. | 159 // TODO(port): Recursive watches are not implemented on Linux. |
| 160 return; |
| 161 #endif // !defined(OS_WIN) |
| 175 | 162 |
| 176 // Verify that modifications to a subdirectory are noticed by recursive watch. | 163 // Verify that modifications to a subdirectory are noticed by recursive watch. |
| 177 { | 164 DirectoryWatcher watcher; |
| 178 DirectoryWatcher watcher; | 165 ASSERT_TRUE(watcher.Watch(test_dir_, this, true)); |
| 179 ASSERT_TRUE(watcher.Watch(test_dir_, this, true)); | 166 // Write a file to the subdir. |
| 180 // Write a file to the subdir. | 167 SetExpectedNumberOfModifications(2); |
| 181 SetExpectedNumberOfModifications(2); | 168 FilePath test_path = subdir.AppendASCII("test_file"); |
| 182 FilePath test_path = subdir.AppendASCII("test_file"); | 169 WriteTestDirFile(test_path.value(), "some content"); |
| 183 WriteTestDirFile(test_path.value(), "some content"); | 170 VerifyExpectedNumberOfModifications(); |
| 184 VerifyExpectedNumberOfModifications(); | 171 } |
| 185 } | |
| 186 #endif // defined(OS_WIN) | |
| 187 | 172 |
| 188 #if !defined(OS_WIN) | 173 TEST_F(DirectoryWatcherTest, SubDirNonRecursive) { |
| 189 // TODO: Enable when the root cause of http://crbug.com/5072 is fixed. | 174 FilePath subdir(FILE_PATH_LITERAL("SubDir")); |
| 175 ASSERT_TRUE(file_util::CreateDirectory(test_dir_.Append(subdir))); |
| 176 |
| 177 // Create a test file before the test. On Windows we get a notification |
| 178 // when creating a file in a subdir even with a non-recursive watch. |
| 179 FilePath test_path = subdir.AppendASCII("test_file"); |
| 180 WriteTestDirFile(test_path.value(), "some content"); |
| 190 | 181 |
| 191 // Verify that modifications to a subdirectory are not noticed | 182 // Verify that modifications to a subdirectory are not noticed |
| 192 // by a not-recursive watch. | 183 // by a not-recursive watch. |
| 193 { | 184 DirectoryWatcher watcher; |
| 194 DirectoryWatcher watcher; | 185 ASSERT_TRUE(watcher.Watch(test_dir_, this, false)); |
| 195 ASSERT_TRUE(watcher.Watch(test_dir_, this, false)); | 186 |
| 196 // Write a file to the subdir. | 187 // Modify the test file. There should be no notifications. |
| 197 SetExpectedNumberOfModifications(0); | 188 SetExpectedNumberOfModifications(0); |
| 198 FilePath test_path = subdir.AppendASCII("test_file"); | 189 WriteTestDirFile(test_path.value(), "some other content"); |
| 199 WriteTestDirFile(test_path.value(), "some content"); | 190 VerifyExpectedNumberOfModifications(); |
| 200 VerifyExpectedNumberOfModifications(); | |
| 201 } | |
| 202 #endif // !defined(OS_WIN) | |
| 203 } | 191 } |
| 204 | 192 |
| 205 namespace { | 193 namespace { |
| 206 // Used by the DeleteDuringNotify test below. | 194 // Used by the DeleteDuringNotify test below. |
| 207 // Deletes the DirectoryWatcher when it's notified. | 195 // Deletes the DirectoryWatcher when it's notified. |
| 208 class Deleter : public DirectoryWatcher::Delegate { | 196 class Deleter : public DirectoryWatcher::Delegate { |
| 209 public: | 197 public: |
| 210 Deleter(DirectoryWatcher* watcher, MessageLoop* loop) | 198 Deleter(DirectoryWatcher* watcher, MessageLoop* loop) |
| 211 : watcher_(watcher), | 199 : watcher_(watcher), |
| 212 loop_(loop) { | 200 loop_(loop) { |
| 213 } | 201 } |
| 214 | 202 |
| 215 virtual void OnDirectoryChanged(const FilePath& path) { | 203 virtual void OnDirectoryChanged(const FilePath& path) { |
| 216 watcher_.reset(NULL); | 204 watcher_.reset(NULL); |
| 217 loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask()); | 205 loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
| 218 } | 206 } |
| 219 | 207 |
| 220 scoped_ptr<DirectoryWatcher> watcher_; | 208 scoped_ptr<DirectoryWatcher> watcher_; |
| 221 MessageLoop* loop_; | 209 MessageLoop* loop_; |
| 222 }; | 210 }; |
| 223 } // anonymous namespace | 211 } // anonymous namespace |
| 224 | 212 |
| 225 // Verify that deleting a watcher during the callback | 213 // Verify that deleting a watcher during the callback |
| 226 TEST_F(DirectoryWatcherTest, DeleteDuringNotify) { | 214 TEST_F(DirectoryWatcherTest, DeleteDuringNotify) { |
| 227 DirectoryWatcher* watcher = new DirectoryWatcher; | 215 DirectoryWatcher* watcher = new DirectoryWatcher; |
| 228 Deleter deleter(watcher, &loop_); // Takes ownership of watcher. | 216 Deleter deleter(watcher, &loop_); // Takes ownership of watcher. |
| 229 ASSERT_TRUE(watcher->Watch(test_dir_, &deleter, kDefaultRecursiveValue)); | 217 ASSERT_TRUE(watcher->Watch(test_dir_, &deleter, false)); |
| 230 | 218 |
| 231 WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some content"); | 219 WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some content"); |
| 232 loop_.Run(); | 220 loop_.Run(); |
| 233 | 221 |
| 234 // We win if we haven't crashed yet. | 222 // We win if we haven't crashed yet. |
| 235 // Might as well double-check it got deleted, too. | 223 // Might as well double-check it got deleted, too. |
| 236 ASSERT_TRUE(deleter.watcher_.get() == NULL); | 224 ASSERT_TRUE(deleter.watcher_.get() == NULL); |
| 237 } | 225 } |
| 238 | 226 |
| 239 TEST_F(DirectoryWatcherTest, MultipleWatchersSingleFile) { | 227 TEST_F(DirectoryWatcherTest, MultipleWatchersSingleFile) { |
| 240 DirectoryWatcher watcher1, watcher2; | 228 DirectoryWatcher watcher1, watcher2; |
| 241 ASSERT_TRUE(watcher1.Watch(test_dir_, this, kDefaultRecursiveValue)); | 229 ASSERT_TRUE(watcher1.Watch(test_dir_, this, false)); |
| 242 ASSERT_TRUE(watcher2.Watch(test_dir_, this, kDefaultRecursiveValue)); | 230 ASSERT_TRUE(watcher2.Watch(test_dir_, this, false)); |
| 243 | 231 |
| 244 SetExpectedNumberOfModifications(4); // Each watcher should fire twice. | 232 SetExpectedNumberOfModifications(4); // Each watcher should fire twice. |
| 245 WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some content"); | 233 WriteTestDirFile(FILE_PATH_LITERAL("test_file"), "some content"); |
| 246 VerifyExpectedNumberOfModifications(); | 234 VerifyExpectedNumberOfModifications(); |
| 247 } | 235 } |
| 248 | 236 |
| 249 TEST_F(DirectoryWatcherTest, MultipleWatchersDifferentFiles) { | 237 TEST_F(DirectoryWatcherTest, MultipleWatchersDifferentFiles) { |
| 250 const int kNumberOfWatchers = 5; | 238 const int kNumberOfWatchers = 5; |
| 251 DirectoryWatcher watchers[kNumberOfWatchers]; | 239 DirectoryWatcher watchers[kNumberOfWatchers]; |
| 252 FilePath subdirs[kNumberOfWatchers]; | 240 FilePath subdirs[kNumberOfWatchers]; |
| 253 for (int i = 0; i < kNumberOfWatchers; i++) { | 241 for (int i = 0; i < kNumberOfWatchers; i++) { |
| 254 subdirs[i] = FilePath(FILE_PATH_LITERAL("Dir")).AppendASCII(IntToString(i)); | 242 subdirs[i] = FilePath(FILE_PATH_LITERAL("Dir")).AppendASCII(IntToString(i)); |
| 255 ASSERT_TRUE(file_util::CreateDirectory(test_dir_.Append(subdirs[i]))); | 243 ASSERT_TRUE(file_util::CreateDirectory(test_dir_.Append(subdirs[i]))); |
| 256 | 244 |
| 257 ASSERT_TRUE(watchers[i].Watch(test_dir_.Append(subdirs[i]), this, | 245 ASSERT_TRUE(watchers[i].Watch(test_dir_.Append(subdirs[i]), this, false)); |
| 258 kDefaultRecursiveValue)); | |
| 259 } | 246 } |
| 260 for (int i = 0; i < kNumberOfWatchers; i++) { | 247 for (int i = 0; i < kNumberOfWatchers; i++) { |
| 261 // Verify that we only get modifications from one watcher (each watcher has | 248 // Verify that we only get modifications from one watcher (each watcher has |
| 262 // different directory). | 249 // different directory). |
| 263 | 250 |
| 264 ASSERT_EQ(0, directory_mods_); | 251 ASSERT_EQ(0, directory_mods_); |
| 265 | 252 |
| 266 // Write a file to the subdir. | 253 // Write a file to the subdir. |
| 267 FilePath test_path = subdirs[i].AppendASCII("test_file"); | 254 FilePath test_path = subdirs[i].AppendASCII("test_file"); |
| 268 SetExpectedNumberOfModifications(2); | 255 SetExpectedNumberOfModifications(2); |
| 269 WriteTestDirFile(test_path.value(), "some content"); | 256 WriteTestDirFile(test_path.value(), "some content"); |
| 270 VerifyExpectedNumberOfModifications(); | 257 VerifyExpectedNumberOfModifications(); |
| 271 | 258 |
| 272 directory_mods_ = 0; | 259 directory_mods_ = 0; |
| 273 } | 260 } |
| 274 } | 261 } |
| 275 | 262 |
| 276 // Verify that watching a directory that doesn't exist fails, but doesn't | 263 // Verify that watching a directory that doesn't exist fails, but doesn't |
| 277 // asssert. | 264 // asssert. |
| 278 // Basic test: add a file and verify we notice it. | 265 // Basic test: add a file and verify we notice it. |
| 279 TEST_F(DirectoryWatcherTest, NonExistentDirectory) { | 266 TEST_F(DirectoryWatcherTest, NonExistentDirectory) { |
| 280 DirectoryWatcher watcher; | 267 DirectoryWatcher watcher; |
| 281 ASSERT_FALSE(watcher.Watch(test_dir_.AppendASCII("does-not-exist"), this, | 268 ASSERT_FALSE(watcher.Watch(test_dir_.AppendASCII("does-not-exist"), this, |
| 282 kDefaultRecursiveValue)); | 269 false)); |
| 283 } | 270 } |
| OLD | NEW |