diff --git a/spec/lib/listen/adapter/linux_spec.rb b/spec/lib/listen/adapter/linux_spec.rb index 64eac46b..9d9caff6 100644 --- a/spec/lib/listen/adapter/linux_spec.rb +++ b/spec/lib/listen/adapter/linux_spec.rb @@ -12,187 +12,187 @@ end if linux? - describe 'instance methods' do - before(:all) do - require 'rb-inotify' - end - - let(:dir1) { Pathname.new("/foo/dir1") } - - let(:queue) { instance_double(Queue, "queue", close: nil) } - let(:config) { instance_double(Listen::Adapter::Config, "config", queue: queue) } - let(:silencer) { instance_double(Listen::Silencer, "silencer") } - let(:snapshot) { instance_double(Listen::Change, "snapshot") } - let(:record) { instance_double(Listen::Record, "record") } - - # TODO: fix other adapters too! - subject { described_class.new(config) } - - after do - subject.stop - end + describe 'instance methods' do + before(:all) do + require 'rb-inotify' + end - describe 'watch events' do - let(:directories) { [Pathname.pwd] } - let(:adapter_options) { {} } - let(:default_events) { [:recursive, :attrib, :create, :modify, :delete, :move, :close_write] } - let(:fake_worker) { double(:fake_worker_for_watch_events) } - let(:fake_notifier) { double(:fake_notifier, new: fake_worker) } + let(:dir1) { Pathname.new("/foo/dir1") } - before do - stub_const('INotify::Notifier', fake_notifier) + let(:queue) { instance_double(Queue, "queue", close: nil) } + let(:config) { instance_double(Listen::Adapter::Config, "config", queue: queue) } + let(:silencer) { instance_double(Listen::Silencer, "silencer") } + let(:snapshot) { instance_double(Listen::Change, "snapshot") } + let(:record) { instance_double(Listen::Record, "record") } - allow(config).to receive(:directories).and_return(directories) - allow(config).to receive(:adapter_options).and_return(adapter_options) - allow(config).to receive(:silencer).and_return(silencer) - allow(fake_worker).to receive(:close) - end + # TODO: fix other adapters too! + subject { described_class.new(config) } after do subject.stop end - it 'starts by calling watch with default events' do - expect(fake_worker).to receive(:watch).with(*directories.map(&:to_s), *default_events) - subject.start - end - end - - describe 'inotify limit message' do - let(:directories) { [Pathname.pwd] } - let(:adapter_options) { {} } - - before do - fake_worker = double(:fake_worker_for_inotify_limit_message) - allow(fake_worker).to receive(:watch).and_raise(Errno::ENOSPC) - allow(fake_worker).to receive(:close) - - fake_notifier = double(:fake_notifier, new: fake_worker) - stub_const('INotify::Notifier', fake_notifier) + describe 'watch events' do + let(:directories) { [Pathname.pwd] } + let(:adapter_options) { {} } + let(:default_events) { [:recursive, :attrib, :create, :modify, :delete, :move, :close_write] } + let(:fake_worker) { double(:fake_worker_for_watch_events) } + let(:fake_notifier) { double(:fake_notifier, new: fake_worker) } - allow(config).to receive(:directories).and_return(directories) - allow(config).to receive(:adapter_options).and_return(adapter_options) - end - - it 'should be shown before calling abort' do - expected_message = described_class.const_get('INOTIFY_LIMIT_MESSAGE') - expect { subject.start }.to raise_error SystemExit, expected_message - end - end - - # TODO: should probably be adapted to be more like adapter/base_spec.rb - describe '_callback' do - let(:directories) { [dir1] } - let(:adapter_options) { { events: [:recursive, :close_write] } } - - before do - fake_worker = double(:fake_worker_for_callback) - events = [:recursive, :close_write] - allow(fake_worker).to receive(:watch).with('/foo/dir1', *events) - allow(fake_worker).to receive(:close) - - fake_notifier = double(:fake_notifier, new: fake_worker) - stub_const('INotify::Notifier', fake_notifier) - - allow(config).to receive(:directories).and_return(directories) - allow(config).to receive(:adapter_options).and_return(adapter_options) - allow(config).to receive(:silencer).and_return(silencer) - - allow(Listen::Record).to receive(:new).with(dir1).and_return(record) - allow(Listen::Change::Config).to receive(:new).with(queue, silencer). - and_return(config) - allow(Listen::Change).to receive(:new).with(config, record). - and_return(snapshot) + before do + stub_const('INotify::Notifier', fake_notifier) - allow(subject).to receive(:require).with('rb-inotify') - subject.configure - end + allow(config).to receive(:directories).and_return(directories) + allow(config).to receive(:adapter_options).and_return(adapter_options) + allow(config).to receive(:silencer).and_return(silencer) + allow(fake_worker).to receive(:close) + end - let(:expect_change) do - lambda do |change| - expect(snapshot).to receive(:invalidate).with( - :file, - 'path/foo.txt', - cookie: 123, - change: change - ) + after do + subject.stop end - end - let(:event_callback) do - lambda do |flags| - callbacks = subject.instance_variable_get(:'@callbacks') - callbacks.values.flatten.each do |callback| - callback.call double( - :inotify_event, - name: 'foo.txt', - watcher: double(:watcher, path: '/foo/dir1/path'), - flags: flags, - cookie: 123) - end + it 'starts by calling watch with default events' do + expect(fake_worker).to receive(:watch).with(*directories.map(&:to_s), *default_events) + subject.start end end - # TODO: get fsevent adapter working like INotify - unless /1|true/ =~ ENV['LISTEN_GEM_SIMULATE_FSEVENT'] - it 'recognizes close_write as modify' do - expect_change.call(:modified) - event_callback.call([:close_write]) - end + describe 'inotify limit message' do + let(:directories) { [Pathname.pwd] } + let(:adapter_options) { {} } + + before do + fake_worker = double(:fake_worker_for_inotify_limit_message) + allow(fake_worker).to receive(:watch).and_raise(Errno::ENOSPC) + allow(fake_worker).to receive(:close) - it 'recognizes moved_to as moved_to' do - expect_change.call(:moved_to) - event_callback.call([:moved_to]) + fake_notifier = double(:fake_notifier, new: fake_worker) + stub_const('INotify::Notifier', fake_notifier) + + allow(config).to receive(:directories).and_return(directories) + allow(config).to receive(:adapter_options).and_return(adapter_options) end - it 'recognizes moved_from as moved_from' do - expect_change.call(:moved_from) - event_callback.call([:moved_from]) + it 'should be shown before calling abort' do + expected_message = described_class.const_get('INOTIFY_LIMIT_MESSAGE') + expect { subject.start }.to raise_error SystemExit, expected_message end end - end - describe '#stop' do - let(:fake_worker) { double(:fake_worker_for_stop, close: true) } - let(:directories) { [dir1] } - let(:adapter_options) { { events: [:recursive, :close_write] } } + # TODO: should probably be adapted to be more like adapter/base_spec.rb + describe '_callback' do + let(:directories) { [dir1] } + let(:adapter_options) { { events: [:recursive, :close_write] } } - before do - allow(config).to receive(:directories).and_return(directories) - allow(config).to receive(:adapter_options).and_return(adapter_options) - end - - context 'when configured' do before do + fake_worker = double(:fake_worker_for_callback) events = [:recursive, :close_write] allow(fake_worker).to receive(:watch).with('/foo/dir1', *events) + allow(fake_worker).to receive(:close) fake_notifier = double(:fake_notifier, new: fake_worker) stub_const('INotify::Notifier', fake_notifier) + allow(config).to receive(:directories).and_return(directories) + allow(config).to receive(:adapter_options).and_return(adapter_options) allow(config).to receive(:silencer).and_return(silencer) + allow(Listen::Record).to receive(:new).with(dir1).and_return(record) + allow(Listen::Change::Config).to receive(:new).with(queue, silencer). + and_return(config) + allow(Listen::Change).to receive(:new).with(config, record). + and_return(snapshot) + allow(subject).to receive(:require).with('rb-inotify') subject.configure end - it 'stops the worker' do - subject.stop + let(:expect_change) do + lambda do |change| + expect(snapshot).to receive(:invalidate).with( + :file, + 'path/foo.txt', + cookie: 123, + change: change + ) + end + end + + let(:event_callback) do + lambda do |flags| + callbacks = subject.instance_variable_get(:'@callbacks') + callbacks.values.flatten.each do |callback| + callback.call double( + :inotify_event, + name: 'foo.txt', + watcher: double(:watcher, path: '/foo/dir1/path'), + flags: flags, + cookie: 123) + end + end + end + + # TODO: get fsevent adapter working like INotify + unless /1|true/ =~ ENV['LISTEN_GEM_SIMULATE_FSEVENT'] + it 'recognizes close_write as modify' do + expect_change.call(:modified) + event_callback.call([:close_write]) + end + + it 'recognizes moved_to as moved_to' do + expect_change.call(:moved_to) + event_callback.call([:moved_to]) + end + + it 'recognizes moved_from as moved_from' do + expect_change.call(:moved_from) + event_callback.call([:moved_from]) + end end end - context 'when not even initialized' do + describe '#stop' do + let(:fake_worker) { double(:fake_worker_for_stop, close: true) } + let(:directories) { [dir1] } + let(:adapter_options) { { events: [:recursive, :close_write] } } + before do - allow(queue).to receive(:close) + allow(config).to receive(:directories).and_return(directories) + allow(config).to receive(:adapter_options).and_return(adapter_options) end - it 'does not crash' do - expect do + context 'when configured' do + before do + events = [:recursive, :close_write] + allow(fake_worker).to receive(:watch).with('/foo/dir1', *events) + + fake_notifier = double(:fake_notifier, new: fake_worker) + stub_const('INotify::Notifier', fake_notifier) + + allow(config).to receive(:silencer).and_return(silencer) + + allow(subject).to receive(:require).with('rb-inotify') + subject.configure + end + + it 'stops the worker' do subject.stop - end.to_not raise_error + end + end + + context 'when not even initialized' do + before do + allow(queue).to receive(:close) + end + + it 'does not crash' do + expect do + subject.stop + end.to_not raise_error + end end end end end - end end