Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: content/common/file_path_watcher/file_path_watcher_browsertest.cc

Issue 6731064: kqueue implementation of FilePathWatcher on Mac. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: missed a nit or two Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "content/common/file_path_watcher/file_path_watcher.h" 5 #include "content/common/file_path_watcher/file_path_watcher.h"
6 6
7 #include <set> 7 #include <set>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
11 #include "base/file_path.h" 11 #include "base/file_path.h"
12 #include "base/file_util.h" 12 #include "base/file_util.h"
13 #include "base/memory/scoped_temp_dir.h" 13 #include "base/memory/scoped_temp_dir.h"
14 #include "base/message_loop.h" 14 #include "base/message_loop.h"
15 #include "base/message_loop_proxy.h" 15 #include "base/message_loop_proxy.h"
16 #include "base/path_service.h" 16 #include "base/path_service.h"
17 #include "base/string_util.h" 17 #include "base/string_util.h"
18 #include "base/stl_util-inl.h" 18 #include "base/stl_util-inl.h"
19 #include "base/synchronization/waitable_event.h" 19 #include "base/synchronization/waitable_event.h"
20 #include "base/test/test_timeouts.h" 20 #include "base/test/test_timeouts.h"
21 #include "base/threading/thread.h" 21 #include "base/threading/thread.h"
22 #include "testing/gtest/include/gtest/gtest.h" 22 #include "testing/gtest/include/gtest/gtest.h"
23 23
24 #if defined(OS_MACOSX)
25 // TODO(mnissler): There are flakes on Mac (http://crbug.com/54822) at least for
26 // FilePathWatcherTest.MultipleWatchersSingleFile.
27 #define MAYBE(name) FLAKY_ ## name
28 #else
29 #define MAYBE(name) name
30 #endif
31
32 namespace { 24 namespace {
33 25
34 class TestDelegate; 26 class TestDelegate;
35 27
36 // Aggregates notifications from the test delegates and breaks the message loop 28 // Aggregates notifications from the test delegates and breaks the message loop
37 // the test thread is waiting on once they all came in. 29 // the test thread is waiting on once they all came in.
38 class NotificationCollector 30 class NotificationCollector
39 : public base::RefCountedThreadSafe<NotificationCollector> { 31 : public base::RefCountedThreadSafe<NotificationCollector> {
40 public: 32 public:
41 NotificationCollector() 33 NotificationCollector()
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 DISALLOW_COPY_AND_ASSIGN(TestDelegate); 98 DISALLOW_COPY_AND_ASSIGN(TestDelegate);
107 }; 99 };
108 100
109 // A helper class for setting up watches on the file thread. 101 // A helper class for setting up watches on the file thread.
110 class SetupWatchTask : public Task { 102 class SetupWatchTask : public Task {
111 public: 103 public:
112 SetupWatchTask(const FilePath& target, 104 SetupWatchTask(const FilePath& target,
113 FilePathWatcher* watcher, 105 FilePathWatcher* watcher,
114 FilePathWatcher::Delegate* delegate, 106 FilePathWatcher::Delegate* delegate,
115 bool* result, 107 bool* result,
116 base::WaitableEvent* completion, 108 base::WaitableEvent* completion)
117 base::MessageLoopProxy* mac_run_loop)
118 : target_(target), 109 : target_(target),
119 watcher_(watcher), 110 watcher_(watcher),
120 delegate_(delegate), 111 delegate_(delegate),
121 result_(result), 112 result_(result),
122 completion_(completion), 113 completion_(completion) {}
123 mac_run_loop_(mac_run_loop) {}
124 114
125 void Run() { 115 void Run() {
126 *result_ = watcher_->Watch(target_, delegate_, mac_run_loop_); 116 *result_ = watcher_->Watch(target_, delegate_);
127 completion_->Signal(); 117 completion_->Signal();
128 } 118 }
129 119
130 private: 120 private:
131 const FilePath target_; 121 const FilePath target_;
132 FilePathWatcher* watcher_; 122 FilePathWatcher* watcher_;
133 FilePathWatcher::Delegate* delegate_; 123 FilePathWatcher::Delegate* delegate_;
134 bool* result_; 124 bool* result_;
135 base::WaitableEvent* completion_; 125 base::WaitableEvent* completion_;
136 scoped_refptr<base::MessageLoopProxy> mac_run_loop_;
137 126
138 DISALLOW_COPY_AND_ASSIGN(SetupWatchTask); 127 DISALLOW_COPY_AND_ASSIGN(SetupWatchTask);
139 }; 128 };
140 129
141 class FilePathWatcherTest : public testing::Test { 130 class FilePathWatcherTest : public testing::Test {
142 public: 131 public:
143 FilePathWatcherTest() 132 FilePathWatcherTest()
144 : loop_(MessageLoop::TYPE_UI), 133 : file_thread_("FilePathWatcherTest") { }
145 file_thread_("FilePathWatcherTest") { }
146 134
147 virtual ~FilePathWatcherTest() { } 135 virtual ~FilePathWatcherTest() { }
148 136
149 protected: 137 protected:
150 virtual void SetUp() { 138 virtual void SetUp() {
151 // Create a separate file thread in order to test proper thread usage. 139 // Create a separate file thread in order to test proper thread usage.
152 base::Thread::Options options(MessageLoop::TYPE_IO, 0); 140 base::Thread::Options options(MessageLoop::TYPE_IO, 0);
153 ASSERT_TRUE(file_thread_.StartWithOptions(options)); 141 ASSERT_TRUE(file_thread_.StartWithOptions(options));
154 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 142 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
155 collector_ = new NotificationCollector(); 143 collector_ = new NotificationCollector();
(...skipping 17 matching lines...) Expand all
173 bool SetupWatch(const FilePath& target, 161 bool SetupWatch(const FilePath& target,
174 FilePathWatcher* watcher, 162 FilePathWatcher* watcher,
175 FilePathWatcher::Delegate* delegate) WARN_UNUSED_RESULT { 163 FilePathWatcher::Delegate* delegate) WARN_UNUSED_RESULT {
176 base::WaitableEvent completion(false, false); 164 base::WaitableEvent completion(false, false);
177 bool result; 165 bool result;
178 file_thread_.message_loop_proxy()->PostTask(FROM_HERE, 166 file_thread_.message_loop_proxy()->PostTask(FROM_HERE,
179 new SetupWatchTask(target, 167 new SetupWatchTask(target,
180 watcher, 168 watcher,
181 delegate, 169 delegate,
182 &result, 170 &result,
183 &completion, 171 &completion));
184 base::MessageLoopProxy::CreateForCurrentThread()));
185 completion.Wait(); 172 completion.Wait();
186 return result; 173 return result;
187 } 174 }
188 175
189 bool WaitForEvents() WARN_UNUSED_RESULT { 176 bool WaitForEvents() WARN_UNUSED_RESULT {
190 collector_->Reset(); 177 collector_->Reset();
191 loop_.Run(); 178 loop_.Run();
192 return collector_->Success(); 179 return collector_->Success();
193 } 180 }
194 181
195 NotificationCollector* collector() { return collector_.get(); } 182 NotificationCollector* collector() { return collector_.get(); }
196 183
197 MessageLoop loop_; 184 MessageLoop loop_;
198 base::Thread file_thread_; 185 base::Thread file_thread_;
199 ScopedTempDir temp_dir_; 186 ScopedTempDir temp_dir_;
200 scoped_refptr<NotificationCollector> collector_; 187 scoped_refptr<NotificationCollector> collector_;
201 }; 188 };
202 189
203 // Basic test: Create the file and verify that we notice. 190 // Basic test: Create the file and verify that we notice.
204 TEST_F(FilePathWatcherTest, MAYBE(NewFile)) { 191 TEST_F(FilePathWatcherTest, NewFile) {
205 FilePathWatcher watcher; 192 FilePathWatcher watcher;
206 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); 193 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector()));
207 ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get())); 194 ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get()));
208 195
209 ASSERT_TRUE(WriteFile(test_file(), "content")); 196 ASSERT_TRUE(WriteFile(test_file(), "content"));
210 ASSERT_TRUE(WaitForEvents()); 197 ASSERT_TRUE(WaitForEvents());
211 } 198 }
212 199
213 // Verify that modifying the file is caught. 200 // Verify that modifying the file is caught.
214 TEST_F(FilePathWatcherTest, MAYBE(ModifiedFile)) { 201 TEST_F(FilePathWatcherTest, ModifiedFile) {
215 ASSERT_TRUE(WriteFile(test_file(), "content")); 202 ASSERT_TRUE(WriteFile(test_file(), "content"));
216 203
217 FilePathWatcher watcher; 204 FilePathWatcher watcher;
218 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); 205 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector()));
219 ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get())); 206 ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get()));
220 207
221 // Now make sure we get notified if the file is modified. 208 // Now make sure we get notified if the file is modified.
222 ASSERT_TRUE(WriteFile(test_file(), "new content")); 209 ASSERT_TRUE(WriteFile(test_file(), "new content"));
223 ASSERT_TRUE(WaitForEvents()); 210 ASSERT_TRUE(WaitForEvents());
224 } 211 }
225 212
226 // Verify that moving the file into place is caught. 213 // Verify that moving the file into place is caught.
227 TEST_F(FilePathWatcherTest, MAYBE(MovedFile)) { 214 TEST_F(FilePathWatcherTest, MovedFile) {
228 FilePath source_file(temp_dir_.path().AppendASCII("source")); 215 FilePath source_file(temp_dir_.path().AppendASCII("source"));
229 ASSERT_TRUE(WriteFile(source_file, "content")); 216 ASSERT_TRUE(WriteFile(source_file, "content"));
230 217
231 FilePathWatcher watcher; 218 FilePathWatcher watcher;
232 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); 219 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector()));
233 ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get())); 220 ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get()));
234 221
235 // Now make sure we get notified if the file is modified. 222 // Now make sure we get notified if the file is modified.
236 ASSERT_TRUE(file_util::Move(source_file, test_file())); 223 ASSERT_TRUE(file_util::Move(source_file, test_file()));
237 ASSERT_TRUE(WaitForEvents()); 224 ASSERT_TRUE(WaitForEvents());
238 } 225 }
239 226
240 TEST_F(FilePathWatcherTest, MAYBE(DeletedFile)) { 227 TEST_F(FilePathWatcherTest, DeletedFile) {
241 ASSERT_TRUE(WriteFile(test_file(), "content")); 228 ASSERT_TRUE(WriteFile(test_file(), "content"));
242 229
243 FilePathWatcher watcher; 230 FilePathWatcher watcher;
244 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); 231 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector()));
245 ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get())); 232 ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get()));
246 233
247 // Now make sure we get notified if the file is deleted. 234 // Now make sure we get notified if the file is deleted.
248 file_util::Delete(test_file(), false); 235 file_util::Delete(test_file(), false);
249 ASSERT_TRUE(WaitForEvents()); 236 ASSERT_TRUE(WaitForEvents());
250 } 237 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 // Verify that deleting the watcher works even if there is a pending 272 // Verify that deleting the watcher works even if there is a pending
286 // notification. 273 // notification.
287 TEST_F(FilePathWatcherTest, DestroyWithPendingNotification) { 274 TEST_F(FilePathWatcherTest, DestroyWithPendingNotification) {
288 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector())); 275 scoped_refptr<TestDelegate> delegate(new TestDelegate(collector()));
289 FilePathWatcher* watcher = new FilePathWatcher; 276 FilePathWatcher* watcher = new FilePathWatcher;
290 ASSERT_TRUE(SetupWatch(test_file(), watcher, delegate.get())); 277 ASSERT_TRUE(SetupWatch(test_file(), watcher, delegate.get()));
291 ASSERT_TRUE(WriteFile(test_file(), "content")); 278 ASSERT_TRUE(WriteFile(test_file(), "content"));
292 file_thread_.message_loop_proxy()->DeleteSoon(FROM_HERE, watcher); 279 file_thread_.message_loop_proxy()->DeleteSoon(FROM_HERE, watcher);
293 } 280 }
294 281
295 TEST_F(FilePathWatcherTest, MAYBE(MultipleWatchersSingleFile)) { 282 TEST_F(FilePathWatcherTest, MultipleWatchersSingleFile) {
296 FilePathWatcher watcher1, watcher2; 283 FilePathWatcher watcher1, watcher2;
297 scoped_refptr<TestDelegate> delegate1(new TestDelegate(collector())); 284 scoped_refptr<TestDelegate> delegate1(new TestDelegate(collector()));
298 scoped_refptr<TestDelegate> delegate2(new TestDelegate(collector())); 285 scoped_refptr<TestDelegate> delegate2(new TestDelegate(collector()));
299 ASSERT_TRUE(SetupWatch(test_file(), &watcher1, delegate1.get())); 286 ASSERT_TRUE(SetupWatch(test_file(), &watcher1, delegate1.get()));
300 ASSERT_TRUE(SetupWatch(test_file(), &watcher2, delegate2.get())); 287 ASSERT_TRUE(SetupWatch(test_file(), &watcher2, delegate2.get()));
301 288
302 ASSERT_TRUE(WriteFile(test_file(), "content")); 289 ASSERT_TRUE(WriteFile(test_file(), "content"));
303 ASSERT_TRUE(WaitForEvents()); 290 ASSERT_TRUE(WaitForEvents());
304 } 291 }
305 292
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 ASSERT_TRUE(SetupWatch(dir, &watcher, delegate.get())); 385 ASSERT_TRUE(SetupWatch(dir, &watcher, delegate.get()));
399 386
400 ASSERT_TRUE(file_util::CreateDirectory(dir)); 387 ASSERT_TRUE(file_util::CreateDirectory(dir));
401 VLOG(1) << "Waiting for directory creation"; 388 VLOG(1) << "Waiting for directory creation";
402 ASSERT_TRUE(WaitForEvents()); 389 ASSERT_TRUE(WaitForEvents());
403 390
404 ASSERT_TRUE(WriteFile(file1, "content")); 391 ASSERT_TRUE(WriteFile(file1, "content"));
405 VLOG(1) << "Waiting for file1 creation"; 392 VLOG(1) << "Waiting for file1 creation";
406 ASSERT_TRUE(WaitForEvents()); 393 ASSERT_TRUE(WaitForEvents());
407 394
395 #if !defined(OS_MACOSX)
396 // Mac implementation does not detect files modified in a directory.
408 ASSERT_TRUE(WriteFile(file1, "content v2")); 397 ASSERT_TRUE(WriteFile(file1, "content v2"));
409 VLOG(1) << "Waiting for file1 modification"; 398 VLOG(1) << "Waiting for file1 modification";
410 ASSERT_TRUE(WaitForEvents()); 399 ASSERT_TRUE(WaitForEvents());
400 #endif // !OS_MACOSX
411 401
412 ASSERT_TRUE(file_util::Delete(file1, false)); 402 ASSERT_TRUE(file_util::Delete(file1, false));
413 VLOG(1) << "Waiting for file1 deletion"; 403 VLOG(1) << "Waiting for file1 deletion";
414 ASSERT_TRUE(WaitForEvents()); 404 ASSERT_TRUE(WaitForEvents());
415 405
416 ASSERT_TRUE(WriteFile(file2, "content")); 406 ASSERT_TRUE(WriteFile(file2, "content"));
417 VLOG(1) << "Waiting for file2 creation"; 407 VLOG(1) << "Waiting for file2 creation";
418 ASSERT_TRUE(WaitForEvents()); 408 ASSERT_TRUE(WaitForEvents());
419 } 409 }
420 410
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 ASSERT_TRUE(SetupWatch(dest_file, &file_watcher, file_delegate.get())); 450 ASSERT_TRUE(SetupWatch(dest_file, &file_watcher, file_delegate.get()));
461 scoped_refptr<TestDelegate> subdir_delegate(new TestDelegate(collector())); 451 scoped_refptr<TestDelegate> subdir_delegate(new TestDelegate(collector()));
462 ASSERT_TRUE(SetupWatch(dest_subdir, &subdir_watcher, subdir_delegate.get())); 452 ASSERT_TRUE(SetupWatch(dest_subdir, &subdir_watcher, subdir_delegate.get()));
463 453
464 // Move the directory into place, s.t. the watched file appears. 454 // Move the directory into place, s.t. the watched file appears.
465 ASSERT_TRUE(file_util::Move(source_dir, dest_dir)); 455 ASSERT_TRUE(file_util::Move(source_dir, dest_dir));
466 ASSERT_TRUE(WaitForEvents()); 456 ASSERT_TRUE(WaitForEvents());
467 } 457 }
468 458
469 } // namespace 459 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698