OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "base/file_path_component_watcher.h" |
| 6 |
| 7 #include <gtest/gtest.h> |
| 8 |
| 9 #include "base/basictypes.h" |
| 10 #include "base/file_util.h" |
| 11 #include "base/message_loop.h" |
| 12 #include "base/scoped_ptr.h" |
| 13 #include "base/scoped_temp_dir.h" |
| 14 #include "base/test/test_timeouts.h" |
| 15 |
| 16 #if defined(OS_MACOSX) |
| 17 |
| 18 namespace { |
| 19 |
| 20 class TestDelegate : public base::FilePathComponentWatcher::Delegate { |
| 21 public: |
| 22 TestDelegate() |
| 23 : components_changed_(false), watch_again_(false), error_(false) { } |
| 24 virtual ~TestDelegate() { } |
| 25 virtual void OnFilePathComponentsChanged( |
| 26 base::FilePathComponentWatcher* watcher, |
| 27 const FilePath& old_path, |
| 28 const FilePath& new_path) { |
| 29 components_changed_ = true; |
| 30 old_path_ = old_path; |
| 31 new_path_ = new_path; |
| 32 if (watch_again_) { |
| 33 if (!watcher->Watch(new_path_, this)) { |
| 34 error_ = true; |
| 35 } |
| 36 watch_again_ = false; |
| 37 } |
| 38 MessageLoop::current()->Quit(); |
| 39 } |
| 40 |
| 41 bool components_changed_; |
| 42 bool watch_again_; |
| 43 bool error_; |
| 44 FilePath old_path_; |
| 45 FilePath new_path_; |
| 46 }; |
| 47 |
| 48 class FilePathComponentWatcherTest : public testing::Test { |
| 49 public: |
| 50 // Implementation of FilePathWatcher on Mac requires UI loop. |
| 51 FilePathComponentWatcherTest() |
| 52 : loop_(MessageLoop::TYPE_UI), delegate_(new TestDelegate) { |
| 53 } |
| 54 |
| 55 protected: |
| 56 virtual void SetUp() { |
| 57 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| 58 } |
| 59 |
| 60 virtual void TearDown() { |
| 61 loop_.RunAllPending(); |
| 62 } |
| 63 |
| 64 FilePath test_file() { |
| 65 return temp_dir_.path().AppendASCII("FilePathWatcherTest"); |
| 66 } |
| 67 |
| 68 // Write |content| to |file|. Returns true on success. |
| 69 bool WriteFile(const FilePath& file, const std::string& content) { |
| 70 int write_size = file_util::WriteFile(file, content.c_str(), |
| 71 content.length()); |
| 72 return write_size == static_cast<int>(content.length()); |
| 73 } |
| 74 |
| 75 void WaitForEvents() { |
| 76 loop_.Run(); |
| 77 } |
| 78 |
| 79 MessageLoop loop_; |
| 80 ScopedTempDir temp_dir_; |
| 81 base::FilePathComponentWatcher file_watcher_; |
| 82 scoped_refptr<TestDelegate> delegate_; |
| 83 }; |
| 84 |
| 85 // RunnableFunctions for tests below |
| 86 void ChangeAttr(bool *success, const FilePath& path, mode_t mode) { |
| 87 *success = chmod(path.value().c_str(), mode) == 0; |
| 88 } |
| 89 |
| 90 void Move(bool *success, const FilePath& old_path, const FilePath& new_path) { |
| 91 *success = file_util::Move(old_path, new_path); |
| 92 } |
| 93 |
| 94 void Delete(bool *success, const FilePath& path) { |
| 95 *success = file_util::Delete(path, true); |
| 96 } |
| 97 |
| 98 TEST_F(FilePathComponentWatcherTest, AttrChange) { |
| 99 FilePath source_dir(temp_dir_.path().AppendASCII("source")); |
| 100 FilePath source_file(source_dir.AppendASCII("file")); |
| 101 |
| 102 // Setup a directory hierarchy. |
| 103 ASSERT_TRUE(file_util::CreateDirectory(source_dir)); |
| 104 ASSERT_TRUE(WriteFile(source_file, "content")); |
| 105 |
| 106 ASSERT_TRUE(file_watcher_.Watch(source_file, delegate_)); |
| 107 bool success; |
| 108 loop_.PostTask(FROM_HERE, NewRunnableFunction(ChangeAttr, |
| 109 &success, |
| 110 source_file, |
| 111 S_IRWXU | S_IRWXG | S_IRWXO)); |
| 112 loop_.PostDelayedTask(FROM_HERE, |
| 113 new MessageLoop::QuitTask, |
| 114 TestTimeouts::action_timeout_ms()); |
| 115 WaitForEvents(); |
| 116 |
| 117 ASSERT_TRUE(success); |
| 118 ASSERT_TRUE(delegate_->components_changed_); |
| 119 ASSERT_TRUE(file_util::AreReferringToSameObject(delegate_->old_path_, |
| 120 source_file)); |
| 121 ASSERT_TRUE(file_util::AreReferringToSameObject(delegate_->new_path_, |
| 122 source_file)); |
| 123 } |
| 124 |
| 125 TEST_F(FilePathComponentWatcherTest, InheritedAttrChange) { |
| 126 FilePath source_dir1(temp_dir_.path().AppendASCII("source1")); |
| 127 FilePath source_dir2(source_dir1.AppendASCII("source2")); |
| 128 FilePath source_file(source_dir2.AppendASCII("file")); |
| 129 |
| 130 // Setup a directory hierarchy. |
| 131 ASSERT_TRUE(file_util::CreateDirectory(source_dir2)); |
| 132 ASSERT_TRUE(WriteFile(source_file, "content")); |
| 133 |
| 134 ASSERT_TRUE(file_watcher_.Watch(source_file, delegate_)); |
| 135 |
| 136 bool success; |
| 137 loop_.PostTask(FROM_HERE, NewRunnableFunction(ChangeAttr, |
| 138 &success, |
| 139 source_dir1, |
| 140 S_IRWXU | S_IRWXG | S_IRWXO)); |
| 141 loop_.PostDelayedTask(FROM_HERE, |
| 142 new MessageLoop::QuitTask, |
| 143 TestTimeouts::action_timeout_ms()); |
| 144 WaitForEvents(); |
| 145 |
| 146 ASSERT_TRUE(success); |
| 147 ASSERT_TRUE(delegate_->components_changed_); |
| 148 ASSERT_TRUE(file_util::AreReferringToSameObject(delegate_->old_path_, |
| 149 source_file)); |
| 150 ASSERT_TRUE(file_util::AreReferringToSameObject(delegate_->new_path_, |
| 151 source_file)); |
| 152 } |
| 153 |
| 154 TEST_F(FilePathComponentWatcherTest, InheritedMove) { |
| 155 FilePath source_dir1(temp_dir_.path().AppendASCII("source1")); |
| 156 FilePath source_dir2(source_dir1.AppendASCII("source2")); |
| 157 FilePath source_file(source_dir2.AppendASCII("file")); |
| 158 FilePath new_sourcedir1(temp_dir_.path().AppendASCII("new_source1")); |
| 159 FilePath new_sourcedir2(new_sourcedir1.AppendASCII("source2")); |
| 160 FilePath new_source_file(new_sourcedir2.AppendASCII("file")); |
| 161 |
| 162 // Setup a directory hierarchy. |
| 163 ASSERT_TRUE(file_util::CreateDirectory(source_dir2)); |
| 164 ASSERT_TRUE(WriteFile(source_file, "content")); |
| 165 |
| 166 ASSERT_TRUE(file_watcher_.Watch(source_file, delegate_)); |
| 167 |
| 168 bool success; |
| 169 loop_.PostTask(FROM_HERE, NewRunnableFunction(Move, |
| 170 &success, |
| 171 source_dir1, |
| 172 new_sourcedir1)); |
| 173 loop_.PostDelayedTask(FROM_HERE, |
| 174 new MessageLoop::QuitTask, |
| 175 TestTimeouts::action_timeout_ms()); |
| 176 WaitForEvents(); |
| 177 |
| 178 ASSERT_TRUE(success); |
| 179 ASSERT_TRUE(delegate_->components_changed_); |
| 180 |
| 181 ASSERT_TRUE(file_util::AreReferringToSameObject(delegate_->new_path_, |
| 182 new_source_file)); |
| 183 |
| 184 // File has been moved, so these paths will no longer exist |
| 185 ASSERT_FALSE(file_util::PathExists(delegate_->old_path_)); |
| 186 ASSERT_FALSE(file_util::PathExists(source_file)); |
| 187 } |
| 188 |
| 189 TEST_F(FilePathComponentWatcherTest, Delete) { |
| 190 FilePath source_dir1(temp_dir_.path().AppendASCII("source1")); |
| 191 FilePath source_dir2(source_dir1.AppendASCII("source2")); |
| 192 FilePath source_file(source_dir2.AppendASCII("file")); |
| 193 |
| 194 // Setup a directory hierarchy. |
| 195 ASSERT_TRUE(file_util::CreateDirectory(source_dir2)); |
| 196 ASSERT_TRUE(WriteFile(source_file, "content")); |
| 197 |
| 198 ASSERT_TRUE(file_watcher_.Watch(source_file, delegate_)); |
| 199 |
| 200 bool success; |
| 201 loop_.PostTask(FROM_HERE, NewRunnableFunction(Delete, &success, source_file)); |
| 202 loop_.PostDelayedTask(FROM_HERE, |
| 203 new MessageLoop::QuitTask, |
| 204 TestTimeouts::action_timeout_ms()); |
| 205 WaitForEvents(); |
| 206 |
| 207 ASSERT_TRUE(success); |
| 208 ASSERT_TRUE(delegate_->components_changed_); |
| 209 |
| 210 // File has been deleted, so these paths will no longer exist |
| 211 ASSERT_FALSE(file_util::PathExists(delegate_->old_path_)); |
| 212 ASSERT_FALSE(file_util::PathExists(source_file)); |
| 213 } |
| 214 |
| 215 TEST_F(FilePathComponentWatcherTest, WatchAgain) { |
| 216 FilePath source_dir1(temp_dir_.path().AppendASCII("source1")); |
| 217 FilePath source_dir2(source_dir1.AppendASCII("source2")); |
| 218 FilePath source_file(source_dir2.AppendASCII("file")); |
| 219 |
| 220 // Setup a directory hierarchy. |
| 221 ASSERT_TRUE(file_util::CreateDirectory(source_dir2)); |
| 222 ASSERT_TRUE(WriteFile(source_file, "content")); |
| 223 |
| 224 ASSERT_TRUE(file_watcher_.Watch(source_file, delegate_)); |
| 225 |
| 226 bool success; |
| 227 delegate_->watch_again_ = true; |
| 228 loop_.PostTask(FROM_HERE, NewRunnableFunction(ChangeAttr, |
| 229 &success, |
| 230 source_dir1, |
| 231 S_IRWXU | S_IRWXG | S_IRWXO)); |
| 232 loop_.PostDelayedTask(FROM_HERE, |
| 233 new MessageLoop::QuitTask, |
| 234 TestTimeouts::action_timeout_ms()); |
| 235 WaitForEvents(); |
| 236 |
| 237 ASSERT_TRUE(success); |
| 238 ASSERT_TRUE(delegate_->components_changed_); |
| 239 ASSERT_FALSE(delegate_->error_); |
| 240 ASSERT_FALSE(delegate_->watch_again_); |
| 241 delegate_->components_changed_ = false; |
| 242 |
| 243 loop_.PostTask(FROM_HERE, NewRunnableFunction(ChangeAttr, |
| 244 &success, |
| 245 source_dir1, |
| 246 S_IRWXU | S_IRWXG | S_IROTH)); |
| 247 loop_.PostDelayedTask(FROM_HERE, |
| 248 new MessageLoop::QuitTask, |
| 249 TestTimeouts::action_timeout_ms()); |
| 250 WaitForEvents(); |
| 251 ASSERT_TRUE(success); |
| 252 ASSERT_TRUE(delegate_->components_changed_); |
| 253 ASSERT_FALSE(delegate_->error_); |
| 254 ASSERT_FALSE(delegate_->watch_again_); |
| 255 } |
| 256 |
| 257 } |
| 258 |
| 259 #else // OS_MACOSX |
| 260 |
| 261 // Test that our stub is there for now |
| 262 TEST(FilePathComponentWatcherTest, StubTest) { |
| 263 base::FilePathComponentWatcher file_watcher_; |
| 264 ScopedTempDir temp_dir; |
| 265 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 266 ASSERT_FALSE(file_watcher_.Watch(temp_dir.path(), NULL)); |
| 267 } |
| 268 |
| 269 #endif // OS_MACOSX |
OLD | NEW |