listen 2.7.5 → 2.7.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -0
  3. data/.rspec +0 -0
  4. data/.rubocop.yml +0 -0
  5. data/.travis.yml +0 -1
  6. data/.yardopts +0 -0
  7. data/CHANGELOG.md +0 -0
  8. data/CONTRIBUTING.md +0 -0
  9. data/Gemfile +25 -4
  10. data/Guardfile +0 -0
  11. data/LICENSE.txt +0 -0
  12. data/README.md +18 -10
  13. data/Rakefile +0 -0
  14. data/lib/listen.rb +2 -4
  15. data/lib/listen/adapter.rb +13 -4
  16. data/lib/listen/adapter/base.rb +33 -16
  17. data/lib/listen/adapter/bsd.rb +21 -38
  18. data/lib/listen/adapter/darwin.rb +17 -25
  19. data/lib/listen/adapter/linux.rb +34 -52
  20. data/lib/listen/adapter/polling.rb +9 -25
  21. data/lib/listen/adapter/tcp.rb +27 -14
  22. data/lib/listen/adapter/windows.rb +67 -23
  23. data/lib/listen/change.rb +26 -23
  24. data/lib/listen/cli.rb +0 -0
  25. data/lib/listen/directory.rb +47 -58
  26. data/lib/listen/file.rb +66 -101
  27. data/lib/listen/listener.rb +214 -155
  28. data/lib/listen/queue_optimizer.rb +104 -0
  29. data/lib/listen/record.rb +15 -5
  30. data/lib/listen/silencer.rb +14 -10
  31. data/lib/listen/tcp.rb +0 -1
  32. data/lib/listen/tcp/broadcaster.rb +31 -26
  33. data/lib/listen/tcp/message.rb +2 -2
  34. data/lib/listen/version.rb +1 -1
  35. data/listen.gemspec +1 -1
  36. data/spec/acceptance/listen_spec.rb +151 -239
  37. data/spec/acceptance/tcp_spec.rb +125 -134
  38. data/spec/lib/listen/adapter/base_spec.rb +13 -30
  39. data/spec/lib/listen/adapter/bsd_spec.rb +7 -35
  40. data/spec/lib/listen/adapter/darwin_spec.rb +18 -30
  41. data/spec/lib/listen/adapter/linux_spec.rb +49 -55
  42. data/spec/lib/listen/adapter/polling_spec.rb +20 -35
  43. data/spec/lib/listen/adapter/tcp_spec.rb +25 -27
  44. data/spec/lib/listen/adapter/windows_spec.rb +7 -33
  45. data/spec/lib/listen/adapter_spec.rb +10 -10
  46. data/spec/lib/listen/change_spec.rb +55 -57
  47. data/spec/lib/listen/directory_spec.rb +105 -155
  48. data/spec/lib/listen/file_spec.rb +186 -73
  49. data/spec/lib/listen/listener_spec.rb +233 -216
  50. data/spec/lib/listen/record_spec.rb +60 -22
  51. data/spec/lib/listen/silencer_spec.rb +48 -75
  52. data/spec/lib/listen/tcp/broadcaster_spec.rb +78 -69
  53. data/spec/lib/listen/tcp/listener_spec.rb +28 -71
  54. data/spec/lib/listen/tcp/message_spec.rb +48 -14
  55. data/spec/lib/listen_spec.rb +3 -3
  56. data/spec/spec_helper.rb +6 -3
  57. data/spec/support/acceptance_helper.rb +250 -31
  58. data/spec/support/fixtures_helper.rb +6 -4
  59. data/spec/support/platform_helper.rb +2 -2
  60. metadata +5 -5
  61. data/lib/listen/tcp/listener.rb +0 -108
@@ -1,145 +1,136 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Listen::TCP do
3
+ describe Listen::Listener do
4
4
 
5
5
  let(:port) { 4000 }
6
-
7
- let(:broadcaster) { Listen.to(Dir.pwd, forward_to: port) }
8
- let(:recipient) { Listen.on(port) }
9
- let(:callback) do
10
- lambda do |modified, added, removed|
11
- add_changes(:modified, modified)
12
- add_changes(:added, added)
13
- add_changes(:removed, removed)
14
- end
15
- end
6
+ let(:broadcast_options) { { forward_to: port } }
16
7
  let(:paths) { Pathname.new(Dir.pwd) }
17
8
 
18
9
  around { |example| fixtures { example.run } }
19
10
 
20
- before do
21
- broadcaster.start
22
- end
23
-
24
- context 'when broadcaster' do
25
- before do
26
- broadcaster.block = callback
27
- end
28
-
29
- it 'still handles local changes' do
30
- expect(listen do
31
- touch 'file.rb'
32
- end).to eq(
33
- modified: [],
34
- added: ['file.rb'],
35
- removed: []
36
- )
37
- end
38
-
39
- it 'may be paused and unpaused' do
40
- broadcaster.pause
41
-
42
- expect(listen do
43
- touch 'file.rb'
44
- end).to eq(
45
- modified: [],
46
- added: [],
47
- removed: []
48
- )
49
-
50
- broadcaster.unpause
51
-
52
- expect(listen do
53
- touch 'file.rb'
54
- end).to eq(
55
- modified: ['file.rb'],
56
- added: [],
57
- removed: []
58
- )
59
- end
60
-
61
- it 'may be stopped and restarted' do
62
- broadcaster.stop
63
-
64
- expect(listen do
65
- touch 'file.rb'
66
- end).to eq(
67
- modified: [],
68
- added: [],
69
- removed: []
70
- )
71
-
72
- broadcaster.start
73
-
74
- expect(listen do
75
- touch 'file.rb'
76
- end).to eq(
77
- modified: ['file.rb'],
78
- added: [],
79
- removed: []
80
- )
11
+ modes = if !windows? || Celluloid::VERSION > '0.15.2'
12
+ [:recipient, :broadcaster]
13
+ else
14
+ [:broadcaster]
15
+ end
16
+
17
+ modes.each do |mode|
18
+ context "when #{mode}" do
19
+ if mode == :broadcaster
20
+ subject { setup_listener(broadcast_options, :track_changes) }
21
+ before { subject.listener.start }
22
+ after { subject.listener.stop }
23
+ else
24
+ subject { setup_recipient(port, :track_changes) }
25
+ let(:broadcaster) { setup_listener(broadcast_options) }
26
+
27
+ before do
28
+ broadcaster.listener.start
29
+ # Travis on OSX is too slow
30
+ subject.lag = 1.2
31
+ subject.listener.start
32
+ end
33
+ after do
34
+ broadcaster.listener.stop
35
+ subject.listener.stop
36
+ end
37
+ end
38
+
39
+ it { should process_addition_of('file.rb') }
40
+
41
+ context 'when paused' do
42
+ before { subject.listener.pause }
43
+
44
+ context 'with no queued changes' do
45
+ it { should_not process_addition_of('file.rb') }
46
+
47
+ context 'when unpaused' do
48
+ before { subject.listener.unpause }
49
+ it { should process_addition_of('file.rb') }
50
+ end
51
+ end
52
+
53
+ context 'with queued addition' do
54
+ before { change_fs(:added, 'file.rb') }
55
+ it { should_not process_modification_of('file.rb') }
56
+
57
+ context 'when unpaused' do
58
+ before { subject.listener.unpause }
59
+ it { should process_queued_addition_of('file.rb') }
60
+ it { should process_modification_of('file.rb') }
61
+ end
62
+ end
63
+
64
+ context 'with queued modification' do
65
+ before do
66
+ change_fs(:added, 'file.rb')
67
+ change_fs(:modified, 'file.rb')
68
+ end
69
+
70
+ it { should_not process_queued_addition_of('file.rb') }
71
+ it { should_not process_queued_modification_of('file.rb') }
72
+
73
+ context 'when unpaused' do
74
+ before { subject.listener.unpause }
75
+ it { should process_queued_addition_of('file.rb') }
76
+
77
+ # NOTE: when adapter is 'local_fs?', the change optimizer
78
+ # (_squash_changes) reduces the "add+mod" into a single "add"
79
+ if mode == :broadcaster
80
+ # "optimizing" on local fs (broadcaster) will remove
81
+ # :modified from queue
82
+ it { should_not process_queued_modification_of('file.rb') }
83
+ else
84
+ # optimization skipped, because it's TCP, so we'll have both
85
+ # :modified and :added events for same file
86
+ it { should process_queued_modification_of('file.rb') }
87
+ end
88
+
89
+ it { should process_modification_of('file.rb') }
90
+ end
91
+ end
92
+ end
93
+
94
+ context 'when stopped' do
95
+ before { subject.listener.stop }
96
+
97
+ context 'with no queued changes' do
98
+ it { should_not process_addition_of('file.rb') }
99
+
100
+ context 'when started' do
101
+ before { subject.listener.start }
102
+ it { should process_addition_of('file.rb') }
103
+ end
104
+ end
105
+
106
+ context 'with queued addition' do
107
+ before { change_fs(:added, 'file.rb') }
108
+ it { should_not process_modification_of('file.rb') }
109
+
110
+ context 'when started' do
111
+ before { subject.listener.start }
112
+ it { should_not process_queued_addition_of('file.rb') }
113
+ it { should process_modification_of('file.rb') }
114
+ end
115
+ end
116
+
117
+ context 'with queued modification' do
118
+ before do
119
+ change_fs(:added, 'file.rb')
120
+ change_fs(:modified, 'file.rb')
121
+ end
122
+
123
+ it { should_not process_queued_addition_of('file.rb') }
124
+ it { should_not process_queued_modification_of('file.rb') }
125
+
126
+ context 'when started' do
127
+ before { subject.listener.start }
128
+ it { should_not process_queued_addition_of('file.rb') }
129
+ it { should_not process_queued_modification_of('file.rb') }
130
+ it { should process_modification_of('file.rb') }
131
+ end
132
+ end
133
+ end
81
134
  end
82
135
  end
83
-
84
- context 'when recipient' do
85
- before do
86
- recipient.start
87
- recipient.block = callback
88
- end
89
-
90
- it 'receives changes over TCP' do
91
- expect(listen(1) do
92
- touch 'file.rb'
93
- end).to eq(
94
- modified: [],
95
- added: ['file.rb'],
96
- removed: []
97
- )
98
- end
99
-
100
- it 'may be paused and unpaused' do
101
- recipient.pause
102
-
103
- expect(listen(1) do
104
- touch 'file.rb'
105
- end).to eq(
106
- modified: [],
107
- added: [],
108
- removed: []
109
- )
110
-
111
- recipient.unpause
112
-
113
- expect(listen(1) do
114
- touch 'file.rb'
115
- end).to eq(
116
- modified: ['file.rb'],
117
- added: [],
118
- removed: []
119
- )
120
- end
121
-
122
- it 'may be stopped and restarted' do
123
- recipient.stop
124
-
125
- expect(listen(1) do
126
- touch 'file.rb'
127
- end).to eq(
128
- modified: [],
129
- added: [],
130
- removed: []
131
- )
132
-
133
- recipient.start
134
-
135
- expect(listen(1) do
136
- touch 'file.rb'
137
- end).to eq(
138
- modified: ['file.rb'],
139
- added: [],
140
- removed: []
141
- )
142
- end
143
- end
144
-
145
136
  end
@@ -1,46 +1,29 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Listen::Adapter::Base do
4
- let(:adapter) { described_class.new(listener) }
5
- let(:registry) { double(Celluloid::Registry) }
6
- let(:listener) { double(Listen::Listener, registry: registry, options: {}) }
4
+ subject { described_class.new(listener) }
7
5
 
8
- describe '#_latency' do
9
- it 'returns default_latency with listener actor latency not present' do
10
- latency = Listen::Adapter::Base::DEFAULT_LATENCY
11
- expect(adapter.send(:_latency)).to eq latency
12
- end
6
+ let(:listener) { instance_double(Listen::Listener) }
13
7
 
14
- it 'returns latency from listener actor if present' do
15
- listener.stub(:options) { { latency: 1234 } }
16
- expect(adapter.send(:_latency)).to eq 1234
17
- end
18
- end
8
+ before { allow(listener).to receive(:async).with(:change_pool) { worker } }
19
9
 
20
10
  describe '#_notify_change' do
21
- let(:change_pool) { double(Listen::Change) }
22
- let(:change_pool_async) { double('ChangePoolAsync') }
23
- before do
24
- change_pool.stub(:async) { change_pool_async }
25
- registry.stub(:[]).with(:change_pool) { change_pool }
26
- end
27
-
28
- context 'listener listen' do
29
- before { listener.stub(:listen?) { true } }
11
+ context 'listener is listening or paused' do
12
+ let(:worker) { instance_double(Listen::Change) }
30
13
 
31
14
  it 'calls change on change_pool asynchronously' do
32
- expect(change_pool_async).to receive(:change).
33
- with('path', type: 'Dir', recurcise: true)
34
- adapter.send(:_notify_change, 'path', type: 'Dir', recurcise: true)
15
+ expect(worker).to receive(:change).
16
+ with(:dir, 'path', recursive: true)
17
+ subject.send(:_notify_change, :dir, 'path', recursive: true)
35
18
  end
36
19
  end
37
20
 
38
- context "listener doesn't listen" do
39
- before { listener.stub(:listen?) { false } }
21
+ context 'listener is stopped' do
22
+ let(:worker) { nil }
40
23
 
41
- it 'calls change on change_pool asynchronously' do
42
- expect(change_pool_async).to_not receive(:change)
43
- adapter.send(:_notify_change, 'path', type: 'Dir', recurcise: true)
24
+ it 'does not fail when no worker is available' do
25
+ expect(worker).to_not receive(:change)
26
+ subject.send(:_notify_change, :dir, 'path', recursive: true)
44
27
  end
45
28
  end
46
29
  end
@@ -1,42 +1,14 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Listen::Adapter::BSD do
4
+ describe 'class' do
5
+ subject { described_class }
6
+ it { should be_local_fs }
4
7
 
5
- if bsd?
6
- let(:listener) { double(Listen::Listener) }
7
- let(:adapter) { described_class.new(listener) }
8
-
9
- describe '.usable?' do
10
- it 'returns always true' do
11
- expect(described_class).to be_usable
12
- end
13
-
14
- it 'requires rb-kqueue and find gem' do
15
- described_class.usable?
16
- expect(defined?(KQueue)).to be_true
17
- expect(defined?(Find)).to be_true
18
- end
8
+ if bsd?
9
+ it { should be_usable }
10
+ else
11
+ it { should_not be_usable }
19
12
  end
20
13
  end
21
-
22
- if darwin?
23
- it "isn't usable on Darwin" do
24
- expect(described_class).to_not be_usable
25
- end
26
- end
27
-
28
- if linux?
29
- it "isn't usable on Linux" do
30
- expect(described_class).to_not be_usable
31
- end
32
- end
33
-
34
- if windows?
35
- it "isn't usable on Windows" do
36
- expect(described_class).to_not be_usable
37
- end
38
- end
39
-
40
- specify { expect(described_class).to be_local_fs }
41
-
42
14
  end
@@ -1,42 +1,30 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Listen::Adapter::Darwin do
4
- if darwin?
5
- let(:listener) { double(Listen::Listener) }
6
- let(:adapter) { described_class.new(listener) }
7
-
8
- describe '.usable?' do
9
- it 'returns always true' do
10
- expect(described_class).to be_usable
11
- end
12
- end
13
-
14
- describe '#initialize' do
15
- it 'requires rb-fsevent gem' do
16
- described_class.new(listener)
17
- expect(defined?(FSEvent)).to be_true
18
- end
4
+ describe 'class' do
5
+ subject { described_class }
6
+ it { should be_local_fs }
7
+
8
+ if darwin?
9
+ it { should be_usable }
10
+ else
11
+ it { should_not be_usable }
19
12
  end
20
13
  end
21
14
 
22
- if windows?
23
- it "isn't usable on Windows" do
24
- expect(described_class).to_not be_usable
25
- end
26
- end
15
+ let(:options) { {} }
16
+ let(:listener) { instance_double(Listen::Listener, options: options) }
27
17
 
28
- if linux?
29
- it "isn't usable on Linux" do
30
- expect(described_class).to_not be_usable
18
+ describe '#_latency' do
19
+ subject { described_class.new(listener).send(:_latency) }
20
+
21
+ context 'with no overriding option' do
22
+ it { should eq described_class.const_get('DEFAULT_LATENCY') }
31
23
  end
32
- end
33
24
 
34
- if bsd?
35
- it "isn't usable on BSD" do
36
- expect(described_class).to_not be_usable
25
+ context 'with custom latency overriding' do
26
+ let(:options) { { latency: 1234 } }
27
+ it { should eq 1234 }
37
28
  end
38
29
  end
39
-
40
- specify { expect(described_class).to be_local_fs }
41
-
42
30
  end
@@ -1,19 +1,27 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Listen::Adapter::Linux do
4
+ describe 'class' do
5
+ subject { described_class }
6
+ it { should be_local_fs }
7
+
8
+ if linux?
9
+ it { should be_usable }
10
+ else
11
+ it { should_not be_usable }
12
+ end
13
+ end
14
+
4
15
  if linux?
5
- let(:listener) { double(Listen::Listener) }
16
+ let(:listener) { instance_double(Listen::Listener) }
6
17
  let(:adapter) { described_class.new(listener) }
7
18
 
8
- describe '.usable?' do
9
- it 'returns always true' do
10
- expect(described_class).to be_usable
11
- end
12
- end
13
-
14
19
  describe '#initialize' do
20
+ before do
21
+ allow(listener).to receive(:directories) { [] }
22
+ end
15
23
  it 'requires rb-inotify gem' do
16
- described_class.new(listener)
24
+ adapter.send(:_configure)
17
25
  expect(defined?(INotify)).to be
18
26
  end
19
27
  end
@@ -23,13 +31,16 @@ describe Listen::Adapter::Linux do
23
31
  let!(:adapter) { described_class.new(listener) }
24
32
 
25
33
  before do
26
- allow_any_instance_of(INotify::Notifier).to receive(:watch).
27
- and_raise(Errno::ENOSPC)
28
-
34
+ require 'rb-inotify'
29
35
  allow(listener).to receive(:directories) { ['foo/dir'] }
36
+ fake_worker = double(:fake_worker)
37
+ allow(fake_worker).to receive(:watch).and_raise(Errno::ENOSPC)
38
+
39
+ fake_notifier = double(:fake_notifier, new: fake_worker)
40
+ stub_const('INotify::Notifier', fake_notifier)
30
41
  end
31
42
 
32
- it 'should be show before calling abort' do
43
+ it 'should be shown before calling abort' do
33
44
  expected_message = described_class.const_get('INOTIFY_LIMIT_MESSAGE')
34
45
  expect(STDERR).to receive(:puts).with(expected_message)
35
46
 
@@ -40,15 +51,18 @@ describe Listen::Adapter::Linux do
40
51
  end
41
52
  end
42
53
 
43
- describe '_worker_callback' do
54
+ describe '_callback' do
55
+ before do
56
+ allow(listener).to receive(:directories) { [] }
57
+ end
44
58
 
45
59
  let(:expect_change) do
46
60
  lambda do |change|
47
61
  allow_any_instance_of(Listen::Adapter::Base).
48
62
  to receive(:_notify_change).
49
63
  with(
64
+ :file,
50
65
  Pathname.new('path/foo.txt'),
51
- type: 'File',
52
66
  change: change,
53
67
  cookie: 123)
54
68
  end
@@ -56,53 +70,33 @@ describe Listen::Adapter::Linux do
56
70
 
57
71
  let(:event_callback) do
58
72
  lambda do |flags|
59
- callback = adapter.send(:_worker_callback)
60
- callback.call double(:event,
61
- name: 'foo.txt',
62
- flags: flags,
63
- absolute_name: 'path/foo.txt',
64
- cookie: 123)
73
+ callback = adapter.send(:_callback)
74
+ callback.call double(
75
+ :inotify_event,
76
+ name: 'foo.txt',
77
+ watcher: double(:watcher, path: 'path'),
78
+ flags: flags,
79
+ cookie: 123)
65
80
  end
66
81
  end
67
82
 
68
- # use case: close_write is the only way to detect changes
69
- # on ecryptfs
70
- it 'recognizes close_write as modify' do
71
- expect_change.call(:modified)
72
- event_callback.call([:close_write])
73
- end
83
+ # TODO: get fsevent adapter working like INotify
84
+ unless /1|true/ =~ ENV['LISTEN_GEM_SIMULATE_FSEVENT']
85
+ it 'recognizes close_write as modify' do
86
+ expect_change.call(:modified)
87
+ event_callback.call([:close_write])
88
+ end
74
89
 
75
- it 'recognizes moved_to as moved_to' do
76
- expect_change.call(:moved_to)
77
- event_callback.call([:moved_to])
78
- end
90
+ it 'recognizes moved_to as moved_to' do
91
+ expect_change.call(:moved_to)
92
+ event_callback.call([:moved_to])
93
+ end
79
94
 
80
- it 'recognizes moved_from as moved_from' do
81
- expect_change.call(:moved_from)
82
- event_callback.call([:moved_from])
95
+ it 'recognizes moved_from as moved_from' do
96
+ expect_change.call(:moved_from)
97
+ event_callback.call([:moved_from])
98
+ end
83
99
  end
84
100
  end
85
-
86
- end
87
-
88
- if darwin?
89
- it "isn't usable on Darwin" do
90
- expect(described_class).to_not be_usable
91
- end
92
- end
93
-
94
- if windows?
95
- it "isn't usable on Windows" do
96
- expect(described_class).to_not be_usable
97
- end
98
101
  end
99
-
100
- if bsd?
101
- it "isn't usable on BSD" do
102
- expect(described_class).to_not be_usable
103
- end
104
- end
105
-
106
- specify { expect(described_class).to be_local_fs }
107
-
108
102
  end