1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
|
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
require 'phusion_passenger/utils/file_system_watcher'
module PhusionPassenger
describe Utils::FileSystemWatcher do
before :each do
@tmpdir = "tmp.fs_watcher"
@tmpdir2 = "tmp.fs_watcher2"
@tmpdir3 = "tmp.fs_watcher3"
@term_pipe = IO.pipe
[@tmpdir, @tmpdir2, @tmpdir3].each do |dir|
remove_dir_tree(dir)
Dir.mkdir(dir)
end
end
after :each do
if @thread
@term_pipe[1].write("x")
@thread.join
end
@watcher.close if @watcher
@term_pipe[0].close
@term_pipe[1].close
[@tmpdir, @tmpdir2, @tmpdir3].each do |dir|
remove_dir_tree(dir)
end
end
def create(*args)
@watcher = Utils::FileSystemWatcher.new(*args)
@watcher.poll_interval = 0.1 if @watcher.respond_to?(:poll_interval=)
return @watcher
end
describe "#wait_for_change blocks until" do
def test_block(filenames)
create(filenames, @term_pipe[0])
result = nil
thread = Thread.new do
result = @watcher.wait_for_change
end
yield if block_given?
eventually do
!thread.alive?
end
return result
ensure
if thread
@term_pipe[1].write("x")
thread.join
end
@watcher.close
end
specify "a subdirectory has been created in one of the watched directories" do
result = test_block([@tmpdir, @tmpdir2]) do
Dir.mkdir("#{@tmpdir}/foo")
end
result.should be_true
end
specify "a subdirectory has been removed in one of the watched directories" do
Dir.mkdir("#{@tmpdir2}/foo")
result = test_block([@tmpdir, @tmpdir2]) do
Dir.rmdir("#{@tmpdir2}/foo")
end
result.should be_true
end
specify "a subdirectory has been renamed in one of the watched directories" do
Dir.mkdir("#{@tmpdir}/foo")
result = test_block([@tmpdir, @tmpdir2]) do
File.rename("#{@tmpdir}/foo", "#{@tmpdir3}/bar")
end
result.should be_true
end
specify "a file has been created in one of the watched directories" do
result = test_block([@tmpdir, @tmpdir2]) do
File.touch("#{@tmpdir}/foo")
end
result.should be_true
end
specify "a file has been removed in one of the watched directories" do
File.touch("#{@tmpdir2}/foo")
result = test_block([@tmpdir, @tmpdir2]) do
File.unlink("#{@tmpdir2}/foo")
end
result.should be_true
end
specify "a file has been renamed in one of the watched directories" do
File.touch("#{@tmpdir}/foo")
result = test_block([@tmpdir, @tmpdir2]) do
File.rename("#{@tmpdir}/foo", "#{@tmpdir3}/bar")
end
result.should be_true
end
specify "a watched file has been written to" do
File.touch("#{@tmpdir}/foo")
result = test_block(["#{@tmpdir}/foo"]) do
File.write("#{@tmpdir}/foo", "bar")
end
end
specify "a watched file has been truncated" do
File.write("#{@tmpdir}/foo", "contents")
result = test_block(["#{@tmpdir}/foo"]) do
File.open("#{@tmpdir}/foo", "w").close
end
end
specify "a watched file has been removed" do
File.touch("#{@tmpdir}/foo")
result = test_block(["#{@tmpdir}/foo"]) do
File.unlink("#{@tmpdir}/foo")
end
end
specify "a watched file has been renamed" do
File.touch("#{@tmpdir}/foo")
result = test_block(["#{@tmpdir}/foo"]) do
File.rename("#{@tmpdir}/foo", "#{@tmpdir}/bar")
end
end
specify "the termination pipe became readable" do
result = test_block([@tmpdir]) do
@term_pipe[1].write("x")
end
result.should be_nil
end
specify "one of the watched files or directories could not be statted while constructing the object" do
test_block([@tmpdir, "#{@tmpdir}/foo"]).should be_false
when_not_running_as_root do
Dir.mkdir("#{@tmpdir}/foo")
File.touch("#{@tmpdir}/foo/file")
Dir.mkdir("#{@tmpdir}/foo/dir")
File.chmod(0000, "#{@tmpdir}/foo")
test_block([@tmpdir, "#{@tmpdir}/foo/file"]).should be_false
test_block([@tmpdir, "#{@tmpdir}/foo/dir"]).should be_false
end
end
if Utils::FileSystemWatcher.opens_files?
when_not_running_as_root do
specify "one of the watched files or directories could not be opened while constructing the object" do
File.touch("#{@tmpdir}/file")
File.chmod(0000, "#{@tmpdir}/file")
test_block([@tmpdir, "#{@tmpdir}/file"]).should be_false
Dir.mkdir("#{@tmpdir}/dir")
File.chmod(0000, "#{@tmpdir}/dir")
test_block([@tmpdir, "#{@tmpdir}/dir"]).should be_false
end
end
end # if
end
describe "#wait_for_change does not return if" do
def test_block(filenames)
create(filenames, @term_pipe[0])
@thread = Thread.new do
@watcher.wait_for_change
end
yield
should_never_happen(0.4) do
!@thread.alive?
end
end
specify "nothing happened in one of its watched files or directories" do
test_block([@tmpdir, @tmpdir2]) do
File.touch("#{@tmpdir3}/file")
Dir.mkdir("#{@tmpdir3}/dir")
end
end
specify "something happened in a subdirectory that isn't on the watch list" do
# In other words it does not watch subdirectories recursively.
Dir.mkdir("#{@tmpdir}/subdir")
test_block([@tmpdir, @tmpdir2]) do
File.touch("#{@tmpdir}/subdir/file")
end
end
specify "a file in a watched directory is merely modified" do
File.touch("#{@tmpdir}/hello", 10)
test_block([@tmpdir, @tmpdir2]) do
File.touch("#{@tmpdir}/hello", 4567)
File.write("#{@tmpdir}/hello", "foobar")
end
end
end
specify "#wait_for_change notices events that have occurred after object construction but before #wait_for_change has been called" do
create([@tmpdir, @tmpdir2], @term_pipe[0])
@thread = Thread.new do
@watcher.wait_for_change
end
File.touch("#{@tmpdir}/foo", Time.now - 10)
eventually do
!@thread.alive?
end
end
it "can be closed multiple times" do
create([@tmpdir])
@watcher.close
@watcher.close
end
end
end # module PhusionPassenger
|