listen 2.7.5 → 2.7.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +0 -0
- data/.rspec +0 -0
- data/.rubocop.yml +0 -0
- data/.travis.yml +0 -1
- data/.yardopts +0 -0
- data/CHANGELOG.md +0 -0
- data/CONTRIBUTING.md +0 -0
- data/Gemfile +25 -4
- data/Guardfile +0 -0
- data/LICENSE.txt +0 -0
- data/README.md +18 -10
- data/Rakefile +0 -0
- data/lib/listen.rb +2 -4
- data/lib/listen/adapter.rb +13 -4
- data/lib/listen/adapter/base.rb +33 -16
- data/lib/listen/adapter/bsd.rb +21 -38
- data/lib/listen/adapter/darwin.rb +17 -25
- data/lib/listen/adapter/linux.rb +34 -52
- data/lib/listen/adapter/polling.rb +9 -25
- data/lib/listen/adapter/tcp.rb +27 -14
- data/lib/listen/adapter/windows.rb +67 -23
- data/lib/listen/change.rb +26 -23
- data/lib/listen/cli.rb +0 -0
- data/lib/listen/directory.rb +47 -58
- data/lib/listen/file.rb +66 -101
- data/lib/listen/listener.rb +214 -155
- data/lib/listen/queue_optimizer.rb +104 -0
- data/lib/listen/record.rb +15 -5
- data/lib/listen/silencer.rb +14 -10
- data/lib/listen/tcp.rb +0 -1
- data/lib/listen/tcp/broadcaster.rb +31 -26
- data/lib/listen/tcp/message.rb +2 -2
- data/lib/listen/version.rb +1 -1
- data/listen.gemspec +1 -1
- data/spec/acceptance/listen_spec.rb +151 -239
- data/spec/acceptance/tcp_spec.rb +125 -134
- data/spec/lib/listen/adapter/base_spec.rb +13 -30
- data/spec/lib/listen/adapter/bsd_spec.rb +7 -35
- data/spec/lib/listen/adapter/darwin_spec.rb +18 -30
- data/spec/lib/listen/adapter/linux_spec.rb +49 -55
- data/spec/lib/listen/adapter/polling_spec.rb +20 -35
- data/spec/lib/listen/adapter/tcp_spec.rb +25 -27
- data/spec/lib/listen/adapter/windows_spec.rb +7 -33
- data/spec/lib/listen/adapter_spec.rb +10 -10
- data/spec/lib/listen/change_spec.rb +55 -57
- data/spec/lib/listen/directory_spec.rb +105 -155
- data/spec/lib/listen/file_spec.rb +186 -73
- data/spec/lib/listen/listener_spec.rb +233 -216
- data/spec/lib/listen/record_spec.rb +60 -22
- data/spec/lib/listen/silencer_spec.rb +48 -75
- data/spec/lib/listen/tcp/broadcaster_spec.rb +78 -69
- data/spec/lib/listen/tcp/listener_spec.rb +28 -71
- data/spec/lib/listen/tcp/message_spec.rb +48 -14
- data/spec/lib/listen_spec.rb +3 -3
- data/spec/spec_helper.rb +6 -3
- data/spec/support/acceptance_helper.rb +250 -31
- data/spec/support/fixtures_helper.rb +6 -4
- data/spec/support/platform_helper.rb +2 -2
- metadata +5 -5
- data/lib/listen/tcp/listener.rb +0 -108
@@ -1,29 +1,32 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Listen::Record do
|
4
|
-
let(:registry) {
|
5
|
-
|
4
|
+
let(:registry) { instance_double(Celluloid::Registry) }
|
5
|
+
|
6
|
+
let(:listener) do
|
7
|
+
instance_double(Listen::Listener, registry: registry, options: {})
|
8
|
+
end
|
9
|
+
|
6
10
|
let(:record) { Listen::Record.new(listener) }
|
7
11
|
let(:path) { '/dir/path/file.rb' }
|
8
|
-
let(:data) { { type: 'File' } }
|
9
12
|
|
10
13
|
describe '#set_path' do
|
11
|
-
it 'sets path by spliting
|
12
|
-
record.set_path(
|
13
|
-
expect(record.paths
|
14
|
+
it 'sets path by spliting dirname and basename' do
|
15
|
+
record.set_path(:file, path)
|
16
|
+
expect(record.paths['/dir/path']).to eq('file.rb' => { type: :file })
|
14
17
|
end
|
15
18
|
|
16
19
|
it 'sets path and keeps old data not overwritten' do
|
17
|
-
record.set_path(path,
|
18
|
-
record.set_path(path,
|
19
|
-
|
20
|
-
expect(
|
20
|
+
record.set_path(:file, path, foo: 1, bar: 2)
|
21
|
+
record.set_path(:file, path, foo: 3)
|
22
|
+
file_data = record.paths['/dir/path']['file.rb']
|
23
|
+
expect(file_data).to eq(foo: 3, bar: 2, type: :file)
|
21
24
|
end
|
22
25
|
end
|
23
26
|
|
24
27
|
describe '#unset_path' do
|
25
28
|
context 'path is present' do
|
26
|
-
before { record.set_path(
|
29
|
+
before { record.set_path(:file, path) }
|
27
30
|
|
28
31
|
it 'unsets path' do
|
29
32
|
record.unset_path(path)
|
@@ -41,10 +44,10 @@ describe Listen::Record do
|
|
41
44
|
|
42
45
|
describe '#file_data' do
|
43
46
|
context 'path is present' do
|
44
|
-
before { record.set_path(
|
47
|
+
before { record.set_path(:file, path) }
|
45
48
|
|
46
49
|
it 'returns file data' do
|
47
|
-
expect(record.file_data(path)).to eq
|
50
|
+
expect(record.file_data(path)).to eq(type: :file)
|
48
51
|
end
|
49
52
|
end
|
50
53
|
|
@@ -57,10 +60,11 @@ describe Listen::Record do
|
|
57
60
|
|
58
61
|
describe '#dir_entries' do
|
59
62
|
context 'path is present' do
|
60
|
-
before { record.set_path(
|
63
|
+
before { record.set_path(:file, path) }
|
61
64
|
|
62
65
|
it 'returns file path' do
|
63
|
-
|
66
|
+
entries = record.dir_entries('/dir/path')
|
67
|
+
expect(entries).to eq('file.rb' => { type: :file })
|
64
68
|
end
|
65
69
|
end
|
66
70
|
|
@@ -73,24 +77,58 @@ describe Listen::Record do
|
|
73
77
|
|
74
78
|
describe '#build' do
|
75
79
|
let(:directories) { ['dir_path'] }
|
76
|
-
|
80
|
+
|
81
|
+
let(:actor) do
|
82
|
+
instance_double(Listen::Change, change: nil, terminate: true)
|
83
|
+
end
|
84
|
+
|
77
85
|
before do
|
78
|
-
|
79
|
-
|
80
|
-
listener.stub(:directories) { directories }
|
86
|
+
allow(listener).to receive(:directories) { directories }
|
87
|
+
allow(listener).to receive(:sync).with(:change_pool) { actor }
|
81
88
|
end
|
82
89
|
|
83
90
|
it 're-inits paths' do
|
84
|
-
record.set_path(
|
91
|
+
record.set_path(:file, path)
|
85
92
|
record.build
|
86
93
|
expect(record.file_data(path)).to be_empty
|
87
94
|
end
|
88
95
|
|
89
96
|
it 'calls change asynchronously on all directories to build record' do
|
90
|
-
expect(
|
91
|
-
with('dir_path',
|
97
|
+
expect(actor).to receive(:change).
|
98
|
+
with(:dir, 'dir_path', recursive: true, silence: true, build: true)
|
99
|
+
record.build
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe '#still_building!' do
|
104
|
+
let(:directories) { ['dir_path'] }
|
92
105
|
|
106
|
+
let(:actor) do
|
107
|
+
instance_double(Listen::Change, change: nil, terminate: true)
|
108
|
+
end
|
109
|
+
|
110
|
+
before do
|
111
|
+
allow(listener).to receive(:directories) { directories }
|
112
|
+
allow(listener).to receive(:sync).with(:change_pool) { actor }
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'keeps the build blocking longer' do
|
116
|
+
record # To avoid initializing record in thread
|
117
|
+
|
118
|
+
th = Thread.new do
|
119
|
+
10.times do
|
120
|
+
sleep 0.05
|
121
|
+
record.still_building!
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
started = Time.now
|
93
126
|
record.build
|
127
|
+
ended = Time.now
|
128
|
+
|
129
|
+
th.join
|
130
|
+
|
131
|
+
expect(ended - started).to be > 0.5
|
94
132
|
end
|
95
133
|
end
|
96
134
|
end
|
@@ -4,10 +4,11 @@ describe Listen::Silencer do
|
|
4
4
|
let(:options) { {} }
|
5
5
|
|
6
6
|
let(:listener) do
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
instance_double(
|
8
|
+
Listen::Listener,
|
9
|
+
directories: [Pathname.pwd, Pathname.new('/Users/Shared/')],
|
10
|
+
options: options
|
11
|
+
)
|
11
12
|
end
|
12
13
|
|
13
14
|
let(:silencer) { Listen::Silencer.new(listener) }
|
@@ -19,46 +20,42 @@ describe Listen::Silencer do
|
|
19
20
|
hidden_dirs = %w(.git .svn .hg .rbx .bundle)
|
20
21
|
other_dirs = %w(bundle vendor/bundle log tmp vendor/ruby)
|
21
22
|
(hidden_dirs + other_dirs).each do |dir|
|
22
|
-
|
23
|
-
|
23
|
+
it "silences #{dir}" do
|
24
|
+
expect(silencer.silenced?(pwd + dir, :dir)).to be_truthy
|
25
|
+
end
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
-
|
27
|
+
it "doesn't silence #{dir}foo" do
|
28
|
+
expect(silencer.silenced?(pwd + "#{dir}foo", :dir)).to be_falsey
|
29
|
+
end
|
28
30
|
|
29
|
-
|
30
|
-
|
31
|
+
it "doesn't silence foo#{dir}" do
|
32
|
+
expect(silencer.silenced?(pwd + "foo#{dir}", :dir)).to be_falsey
|
33
|
+
end
|
34
|
+
end
|
31
35
|
|
32
|
-
|
33
|
-
expect(silencer.silenced?(path)).to be_false
|
34
|
-
end
|
35
|
-
end
|
36
|
+
all_files = %w(.DS_Store foo.tmp foo~)
|
36
37
|
|
37
|
-
|
38
|
-
|
38
|
+
# Gedit swap files
|
39
|
+
all_files += %w(.goutputstream-S3FBGX)
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
41
|
+
# Kate editor swap files
|
42
|
+
all_files += %w(foo.rbo54321.new foo.rbB22583.new foo.rb.kate-swp)
|
46
43
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
44
|
+
# Intellij swap files
|
45
|
+
all_files += %w(foo.rb___jb_bak___ foo.rb___jb_old___)
|
46
|
+
|
47
|
+
# Vim swap files
|
48
|
+
all_files += %w(foo.swp foo.swx foo.swpx 4913)
|
49
|
+
|
50
|
+
all_files.each do |path|
|
51
|
+
it "silences #{path}" do
|
52
|
+
expect(silencer.silenced?(pwd + path, :file)).to be_truthy
|
54
53
|
end
|
55
54
|
end
|
56
55
|
|
57
|
-
%w(foo.tmpl file.new file54321.new).each do |path|
|
58
|
-
|
59
|
-
|
60
|
-
expect(silencer.silenced?(pwd + path)).to be_false
|
61
|
-
end
|
56
|
+
%w(foo.tmpl file.new file54321.new a.swf 14913 49131).each do |path|
|
57
|
+
it "does not silence #{path}" do
|
58
|
+
expect(silencer.silenced?(pwd + path, :file)).to be_falsey
|
62
59
|
end
|
63
60
|
end
|
64
61
|
end
|
@@ -67,7 +64,7 @@ describe Listen::Silencer do
|
|
67
64
|
let(:options) { { ignore: /\.pid$/ } }
|
68
65
|
|
69
66
|
it 'silences path matching custom ignore regex' do
|
70
|
-
expect(silencer.silenced?(pwd + 'foo.pid')).to
|
67
|
+
expect(silencer.silenced?(pwd + 'foo.pid', :file)).to be_truthy
|
71
68
|
end
|
72
69
|
end
|
73
70
|
|
@@ -75,8 +72,8 @@ describe Listen::Silencer do
|
|
75
72
|
let(:options) { { ignore: [%r{^foo/bar}, /\.pid$/] } }
|
76
73
|
|
77
74
|
it 'silences paths matching custom ignore regexes' do
|
78
|
-
expect(silencer.silenced?(pwd + 'foo/bar/baz')).to
|
79
|
-
expect(silencer.silenced?(pwd + 'foo.pid')).to
|
75
|
+
expect(silencer.silenced?(pwd + 'foo/bar/baz', :file)).to be_truthy
|
76
|
+
expect(silencer.silenced?(pwd + 'foo.pid', :file)).to be_truthy
|
80
77
|
end
|
81
78
|
end
|
82
79
|
|
@@ -84,90 +81,66 @@ describe Listen::Silencer do
|
|
84
81
|
let(:options) { { ignore!: /\.pid$/ } }
|
85
82
|
|
86
83
|
it 'silences custom ignored directory' do
|
87
|
-
expect(silencer.silenced?(pwd + 'foo.pid')).to
|
84
|
+
expect(silencer.silenced?(pwd + 'foo.pid', :file)).to be_truthy
|
88
85
|
end
|
89
86
|
|
90
87
|
it "doesn't silence default ignored directory" do
|
91
|
-
expect(silencer.silenced?(pwd + '.git')).to
|
88
|
+
expect(silencer.silenced?(pwd + '.git', :file)).to be_falsey
|
92
89
|
end
|
93
90
|
end
|
94
91
|
|
95
92
|
context 'with only options (regexp)' do
|
96
93
|
let(:options) { { only: %r{foo} } }
|
97
94
|
|
98
|
-
it 'do not take only regex in account if type is Unknown' do
|
99
|
-
expect(silencer.silenced?(pwd + 'baz')).to be_false
|
100
|
-
end
|
101
|
-
|
102
95
|
it 'do not silence path matches only regex if type is File' do
|
103
|
-
expect(silencer.silenced?(pwd + 'foo',
|
96
|
+
expect(silencer.silenced?(pwd + 'foo', :file)).to be_falsey
|
104
97
|
end
|
105
98
|
|
106
99
|
it 'silences other directory' do
|
107
|
-
expect(silencer.silenced?(pwd + 'bar',
|
100
|
+
expect(silencer.silenced?(pwd + 'bar', :file)).to be_truthy
|
108
101
|
end
|
109
102
|
end
|
110
103
|
|
111
104
|
context 'with only options (array)' do
|
112
105
|
let(:options) { { only: [%r{^foo/}, %r{\.txt$}] } }
|
113
106
|
|
114
|
-
it 'do not take only regex in account if type is Unknown' do
|
115
|
-
expect(silencer.silenced?(pwd + 'baz')).to be_false
|
116
|
-
end
|
117
|
-
|
118
107
|
it "doesn't silence good directory" do
|
119
|
-
expect(silencer.silenced?(pwd + 'foo/bar.rb',
|
108
|
+
expect(silencer.silenced?(pwd + 'foo/bar.rb', :file)).to be_falsey
|
120
109
|
end
|
121
110
|
|
122
111
|
it "doesn't silence good file" do
|
123
|
-
expect(silencer.silenced?(pwd + 'bar.txt',
|
112
|
+
expect(silencer.silenced?(pwd + 'bar.txt', :file)).to be_falsey
|
124
113
|
end
|
125
114
|
|
126
115
|
it 'silences other directory' do
|
127
|
-
expect(silencer.silenced?(pwd + 'bar/baz.rb',
|
116
|
+
expect(silencer.silenced?(pwd + 'bar/baz.rb', :file)).to be_truthy
|
128
117
|
end
|
129
118
|
|
130
119
|
it 'silences other file' do
|
131
|
-
expect(silencer.silenced?(pwd + 'bar.rb',
|
120
|
+
expect(silencer.silenced?(pwd + 'bar.rb', :file)).to be_truthy
|
132
121
|
end
|
133
122
|
end
|
134
123
|
|
135
124
|
context 'with ignore and only options' do
|
136
125
|
let(:options) { { only: /\.pid$/, ignore: %r{^bar} } }
|
137
126
|
|
138
|
-
context 'with Unknown type' do
|
139
|
-
context 'when not matching :only' do
|
140
|
-
context 'when not matching :ignore' do
|
141
|
-
it 'does not silence' do
|
142
|
-
expect(silencer.silenced?(pwd + 'baz')).to be_false
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
context 'when matching :ignore' do
|
147
|
-
it 'silences' do
|
148
|
-
expect(silencer.silenced?(pwd + 'bar')).to be_true
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
127
|
context 'with File type' do
|
155
128
|
context 'when not matching :only' do
|
156
129
|
it 'silences' do
|
157
|
-
expect(silencer.silenced?(pwd + 'foo.rb',
|
130
|
+
expect(silencer.silenced?(pwd + 'foo.rb', :file)).to be_truthy
|
158
131
|
end
|
159
132
|
end
|
160
133
|
|
161
134
|
context 'when matching :only' do
|
162
135
|
context 'when matching :ignore' do
|
163
136
|
it 'silences' do
|
164
|
-
expect(silencer.silenced?(pwd + 'bar.pid',
|
137
|
+
expect(silencer.silenced?(pwd + 'bar.pid', :file)).to be_truthy
|
165
138
|
end
|
166
139
|
end
|
167
140
|
|
168
141
|
context 'when not matching :ignore' do
|
169
142
|
it 'does not silence' do
|
170
|
-
expect(silencer.silenced?(pwd + 'foo.pid',
|
143
|
+
expect(silencer.silenced?(pwd + 'foo.pid', :file)).to be_falsey
|
171
144
|
end
|
172
145
|
end
|
173
146
|
end
|
@@ -175,8 +148,8 @@ describe Listen::Silencer do
|
|
175
148
|
end
|
176
149
|
|
177
150
|
it "doesn't silence normal path" do
|
178
|
-
path = pwd + 'some_dir' + 'some_file.rb'
|
179
|
-
expect(silencer.silenced?(path)).to
|
151
|
+
path = (pwd + 'some_dir') + 'some_file.rb'
|
152
|
+
expect(silencer.silenced?(path, :file)).to be_falsey
|
180
153
|
end
|
181
154
|
end
|
182
155
|
|
@@ -1,115 +1,124 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
+
require 'listen/tcp/broadcaster'
|
4
|
+
|
3
5
|
describe Listen::TCP::Broadcaster do
|
4
6
|
|
5
7
|
let(:host) { '10.0.0.2' }
|
6
8
|
let(:port) { 4000 }
|
7
9
|
|
8
10
|
subject { described_class.new(host, port) }
|
9
|
-
|
10
|
-
let(:
|
11
|
+
|
12
|
+
let(:server) do
|
13
|
+
instance_double(described_class::TCPServer, close: true, accept: nil)
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:socket) do
|
17
|
+
instance_double(described_class::TCPSocket, close: true, write: true)
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:socket2) do
|
21
|
+
instance_double(described_class::TCPSocket, close: true, write: true)
|
22
|
+
end
|
23
|
+
|
11
24
|
let(:payload) { Listen::TCP::Message.new.payload }
|
12
25
|
|
13
26
|
before do
|
14
27
|
expect(described_class::TCPServer).to receive(:new).
|
15
28
|
with(host, port).and_return server
|
29
|
+
allow(server).to receive(:accept).and_raise('stub called')
|
16
30
|
end
|
17
31
|
|
18
32
|
after do
|
19
33
|
subject.terminate
|
20
34
|
end
|
21
35
|
|
22
|
-
describe '#initialize' do
|
23
|
-
it 'initializes and exposes a server' do
|
24
|
-
expect(subject.server).to be server
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'initializes and exposes a list of sockets' do
|
28
|
-
expect(subject.sockets).to eq []
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
36
|
describe '#start' do
|
33
|
-
let(:async) { double('TCP-listener async') }
|
34
|
-
|
35
37
|
it 'invokes run loop asynchronously' do
|
36
|
-
|
37
|
-
expect(async).to receive(:run)
|
38
|
+
expect_any_instance_of(described_class).to receive(:run)
|
38
39
|
subject.start
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
42
43
|
describe '#finalize' do
|
43
|
-
|
44
|
-
expect(subject.sockets).to receive(:clear)
|
45
|
-
subject.finalize
|
46
|
-
end
|
44
|
+
before { allow(server).to receive(:accept).and_return nil }
|
47
45
|
|
48
46
|
it 'closes server' do
|
49
|
-
expect(
|
47
|
+
expect(server).to receive(:close)
|
50
48
|
subject.finalize
|
51
|
-
expect(subject.server).to be_nil
|
52
49
|
end
|
53
50
|
end
|
54
51
|
|
55
52
|
describe '#broadcast' do
|
56
|
-
|
57
|
-
|
58
|
-
expect(subject.wrapped_object).to receive(:unicast).with socket, payload
|
59
|
-
subject.broadcast payload
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
describe '#unicast' do
|
64
|
-
before do
|
65
|
-
subject.handle_connection socket
|
66
|
-
end
|
53
|
+
context 'with active socket' do
|
54
|
+
before { allow(server).to receive(:accept).and_return socket, nil }
|
67
55
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
56
|
+
it 'should broadcast payload' do
|
57
|
+
expect(socket).to receive(:write).with(payload)
|
58
|
+
subject.run
|
59
|
+
subject.broadcast payload
|
72
60
|
end
|
73
|
-
end
|
74
61
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
expect(subject.sockets).not_to include socket
|
62
|
+
it 'should keep socket' do
|
63
|
+
expect(socket).to receive(:write).twice.with(payload)
|
64
|
+
subject.run
|
65
|
+
2.times { subject.broadcast payload }
|
80
66
|
end
|
81
|
-
end
|
82
67
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
68
|
+
context 'with IOError' do
|
69
|
+
it 'should remove socket from list' do
|
70
|
+
allow(socket).to receive(:write).once.and_raise IOError
|
71
|
+
subject.run
|
72
|
+
2.times { subject.broadcast payload }
|
73
|
+
end
|
88
74
|
end
|
89
|
-
end
|
90
75
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
76
|
+
context 'when reset by peer' do
|
77
|
+
it 'should remove socket from list' do
|
78
|
+
allow(socket).to receive(:write).once.and_raise Errno::ECONNRESET
|
79
|
+
subject.run
|
80
|
+
2.times { subject.broadcast payload }
|
81
|
+
end
|
96
82
|
end
|
97
|
-
end
|
98
|
-
end
|
99
83
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
84
|
+
context 'when broken pipe' do
|
85
|
+
it 'should remove socket from list' do
|
86
|
+
allow(socket).to receive(:write).once.and_raise Errno::EPIPE
|
87
|
+
subject.run
|
88
|
+
2.times { subject.broadcast payload }
|
89
|
+
end
|
90
|
+
end
|
107
91
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
92
|
+
context 'with another active socket' do
|
93
|
+
before do
|
94
|
+
allow(server).to receive(:accept).and_return socket, socket2, nil
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should broadcast payload to both' do
|
98
|
+
expect(socket).to receive(:write).with(payload)
|
99
|
+
expect(socket2).to receive(:write).with(payload)
|
100
|
+
subject.run
|
101
|
+
subject.broadcast payload
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'with a failure in first socket' do
|
105
|
+
before do
|
106
|
+
allow(socket).to receive(:write).once.and_raise Errno::EPIPE
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should still broadcast to remaining socket' do
|
110
|
+
expect(socket2).to receive(:write).with(payload)
|
111
|
+
subject.run
|
112
|
+
subject.broadcast payload
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should broadcast to only remaining socket' do
|
116
|
+
expect(socket2).to receive(:write).twice.with(payload)
|
117
|
+
subject.run
|
118
|
+
2.times { subject.broadcast payload }
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
112
122
|
end
|
113
123
|
end
|
114
|
-
|
115
124
|
end
|