Sindbad~EG File Manager
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
PhusionPassenger.require_passenger_lib '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_truthy
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_truthy
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_truthy
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_truthy
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_truthy
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_truthy
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
if RUBY_PLATFORM =~ /darwin/
# OS X kernel bug in kqueue... sigh...
File.open("#{@tmpdir}/foo", "w") do |f|
f.write("a")
f.truncate(0)
end
else
File.open("#{@tmpdir}/foo", "w").close
end
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_falsey
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_falsey
test_block([@tmpdir, "#{@tmpdir}/foo/dir"]).should be_falsey
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_falsey
Dir.mkdir("#{@tmpdir}/dir")
File.chmod(0000, "#{@tmpdir}/dir")
test_block([@tmpdir, "#{@tmpdir}/dir"]).should be_falsey
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
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists