Chromium Code Reviews| 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() : components_changed_(false) { } | |
| 23 virtual ~TestDelegate() { } | |
| 24 virtual void OnFilePathComponentsChanged(const FilePath& old_path, | |
| 25 const FilePath& new_path) { | |
| 26 components_changed_ = true; | |
| 27 old_path_ = old_path; | |
| 28 new_path_ = new_path; | |
| 29 MessageLoop::current()->Quit(); | |
| 30 } | |
| 31 | |
| 32 bool components_changed_; | |
| 33 FilePath old_path_; | |
| 34 FilePath new_path_; | |
| 35 }; | |
| 36 | |
| 37 class FilePathComponentWatcherTest : public testing::Test { | |
| 38 public: | |
| 39 // Implementation of FilePathWatcher on Mac requires UI loop. | |
| 40 FilePathComponentWatcherTest() | |
| 41 : loop_(MessageLoop::TYPE_UI), delegate_(new TestDelegate) { | |
| 42 } | |
| 43 | |
| 44 protected: | |
| 45 virtual void SetUp() { | |
| 46 temp_dir_.reset(new ScopedTempDir); | |
| 47 ASSERT_TRUE(temp_dir_->CreateUniqueTempDir()); | |
| 48 } | |
| 49 | |
| 50 virtual void TearDown() { | |
| 51 loop_.RunAllPending(); | |
| 52 } | |
| 53 | |
| 54 FilePath test_file() { | |
| 55 return temp_dir_->path().AppendASCII("FilePathWatcherTest"); | |
| 56 } | |
| 57 | |
| 58 // Write |content| to |file|. Returns true on success. | |
| 59 bool WriteFile(const FilePath& file, const std::string& content) { | |
| 60 int write_size = file_util::WriteFile(file, content.c_str(), | |
| 61 content.length()); | |
| 62 return write_size == static_cast<int>(content.length()); | |
| 63 } | |
| 64 | |
| 65 void WaitForEvents() { | |
| 66 loop_.Run(); | |
| 67 } | |
| 68 | |
| 69 MessageLoop loop_; | |
| 70 scoped_ptr<ScopedTempDir> temp_dir_; | |
|
Paweł Hajdan Jr.
2011/03/10 16:02:04
nit: No need for scoped_ptr, really. The entire te
| |
| 71 base::FilePathComponentWatcher file_watcher_; | |
| 72 scoped_refptr<TestDelegate> delegate_; | |
| 73 }; | |
| 74 | |
| 75 class TestTask : public Task { | |
| 76 public: | |
| 77 void set_success() { *success_ = true; } | |
| 78 | |
| 79 protected: | |
| 80 bool* success_; | |
| 81 TestTask(bool *success) : success_(success) { *success_ = false; } | |
| 82 virtual ~TestTask() { } | |
| 83 }; | |
| 84 | |
| 85 class ChangeAttr : public TestTask { | |
|
Paweł Hajdan Jr.
2011/03/10 16:02:04
nit: It's going to be simpler to use NewRunnableFu
| |
| 86 public: | |
| 87 ChangeAttr(bool *success, const FilePath& path) | |
| 88 : TestTask(success), path_(path) { } | |
| 89 virtual ~ChangeAttr() { } | |
| 90 virtual void Run() { | |
| 91 if (chmod(path_.value().c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0) { | |
| 92 set_success(); | |
| 93 } | |
| 94 } | |
| 95 | |
| 96 private: | |
| 97 FilePath path_; | |
| 98 | |
| 99 DISALLOW_COPY_AND_ASSIGN(ChangeAttr); | |
| 100 }; | |
| 101 | |
| 102 class Move : public TestTask { | |
| 103 public: | |
| 104 Move(bool *success, const FilePath& old_path, const FilePath& new_path) | |
| 105 : TestTask(success), old_path_(old_path), new_path_(new_path) { } | |
| 106 virtual ~Move() { } | |
| 107 virtual void Run() { | |
| 108 if (file_util::Move(old_path_, new_path_)) { | |
| 109 set_success(); | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 private: | |
| 114 FilePath old_path_, new_path_; | |
| 115 | |
| 116 DISALLOW_COPY_AND_ASSIGN(Move); | |
| 117 }; | |
| 118 | |
| 119 class Delete : public TestTask { | |
| 120 public: | |
| 121 Delete(bool *success, const FilePath& path) | |
| 122 : TestTask(success), path_(path) { } | |
| 123 virtual ~Delete() { } | |
| 124 virtual void Run() { | |
| 125 if (file_util::Delete(path_, true)) { | |
| 126 set_success(); | |
| 127 } | |
| 128 } | |
| 129 | |
| 130 private: | |
| 131 FilePath path_; | |
| 132 | |
| 133 DISALLOW_COPY_AND_ASSIGN(Delete); | |
| 134 }; | |
| 135 | |
| 136 TEST_F(FilePathComponentWatcherTest, AttrChange) { | |
| 137 FilePath source_dir(temp_dir_->path().AppendASCII("source")); | |
| 138 FilePath source_file(source_dir.AppendASCII("file")); | |
| 139 | |
| 140 // Setup a directory hierarchy. | |
| 141 ASSERT_TRUE(file_util::CreateDirectory(source_dir)); | |
| 142 ASSERT_TRUE(WriteFile(source_file, "content")); | |
| 143 | |
| 144 ASSERT_TRUE(file_watcher_.Watch(source_file, delegate_)); | |
| 145 bool success; | |
| 146 loop_.PostTask(FROM_HERE, new ChangeAttr(&success, source_file)); | |
| 147 loop_.PostDelayedTask(FROM_HERE, | |
| 148 new MessageLoop::QuitTask, | |
| 149 TestTimeouts::action_timeout_ms()); | |
| 150 WaitForEvents(); | |
| 151 | |
| 152 ASSERT_TRUE(success); | |
| 153 ASSERT_TRUE(delegate_->components_changed_); | |
| 154 ASSERT_TRUE(file_util::AreReferringToSameObject(delegate_->old_path_, | |
| 155 source_file)); | |
| 156 ASSERT_TRUE(file_util::AreReferringToSameObject(delegate_->new_path_, | |
| 157 source_file)); | |
| 158 } | |
| 159 | |
| 160 TEST_F(FilePathComponentWatcherTest, InheritedAttrChange) { | |
| 161 FilePath source_dir1(temp_dir_->path().AppendASCII("source1")); | |
| 162 FilePath source_dir2(source_dir1.AppendASCII("source2")); | |
| 163 FilePath source_file(source_dir2.AppendASCII("file")); | |
| 164 | |
| 165 // Setup a directory hierarchy. | |
| 166 ASSERT_TRUE(file_util::CreateDirectory(source_dir2)); | |
| 167 ASSERT_TRUE(WriteFile(source_file, "content")); | |
| 168 | |
| 169 ASSERT_TRUE(file_watcher_.Watch(source_file, delegate_)); | |
| 170 | |
| 171 bool success; | |
| 172 loop_.PostTask(FROM_HERE, new ChangeAttr(&success, source_dir1)); | |
| 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 ASSERT_TRUE(file_util::AreReferringToSameObject(delegate_->old_path_, | |
| 181 source_file)); | |
| 182 ASSERT_TRUE(file_util::AreReferringToSameObject(delegate_->new_path_, | |
| 183 source_file)); | |
| 184 } | |
| 185 | |
| 186 TEST_F(FilePathComponentWatcherTest, InheritedMove) { | |
| 187 FilePath source_dir1(temp_dir_->path().AppendASCII("source1")); | |
| 188 FilePath source_dir2(source_dir1.AppendASCII("source2")); | |
| 189 FilePath source_file(source_dir2.AppendASCII("file")); | |
| 190 FilePath new_sourcedir1(temp_dir_->path().AppendASCII("new_source1")); | |
| 191 FilePath new_sourcedir2(new_sourcedir1.AppendASCII("source2")); | |
| 192 FilePath new_source_file(new_sourcedir2.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, new Move(&success, source_dir1, new_sourcedir1)); | |
| 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 ASSERT_TRUE(file_util::AreReferringToSameObject(delegate_->new_path_, | |
| 211 new_source_file)); | |
| 212 | |
| 213 // File has been moved, so these paths will no longer exist | |
| 214 ASSERT_FALSE(file_util::PathExists(delegate_->old_path_)); | |
| 215 ASSERT_FALSE(file_util::PathExists(source_file)); | |
| 216 } | |
| 217 | |
| 218 TEST_F(FilePathComponentWatcherTest, Delete) { | |
| 219 FilePath source_dir1(temp_dir_->path().AppendASCII("source1")); | |
| 220 FilePath source_dir2(source_dir1.AppendASCII("source2")); | |
| 221 FilePath source_file(source_dir2.AppendASCII("file")); | |
| 222 | |
| 223 // Setup a directory hierarchy. | |
| 224 ASSERT_TRUE(file_util::CreateDirectory(source_dir2)); | |
| 225 ASSERT_TRUE(WriteFile(source_file, "content")); | |
| 226 | |
| 227 ASSERT_TRUE(file_watcher_.Watch(source_file, delegate_)); | |
| 228 | |
| 229 bool success; | |
| 230 loop_.PostTask(FROM_HERE, new Delete(&success, source_file)); | |
| 231 loop_.PostDelayedTask(FROM_HERE, | |
| 232 new MessageLoop::QuitTask, | |
| 233 TestTimeouts::action_timeout_ms()); | |
| 234 WaitForEvents(); | |
| 235 | |
| 236 ASSERT_TRUE(success); | |
| 237 ASSERT_TRUE(delegate_->components_changed_); | |
| 238 | |
| 239 // File has been deleted, so these paths will no longer exist | |
| 240 ASSERT_FALSE(file_util::PathExists(delegate_->old_path_)); | |
| 241 ASSERT_FALSE(file_util::PathExists(source_file)); | |
| 242 } | |
| 243 | |
| 244 } | |
| 245 | |
| 246 #else // OS_MACOSX | |
| 247 | |
| 248 // Test that our stub is there for now | |
| 249 TEST(FilePathComponentWatcherTest, StubTest) { | |
| 250 base::FilePathComponentWatcher file_watcher_; | |
| 251 ScopedTempDir temp_dir; | |
| 252 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | |
| 253 ASSERT_FALSE(file_watcher_.Watch(temp_dir.path(), NULL)); | |
| 254 } | |
| 255 | |
| 256 #endif // OS_MACOSX | |
| OLD | NEW |