celluloid_pubsub 1.0.2 → 2.0.0

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.
@@ -0,0 +1,78 @@
1
+ # encoding:utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe CelluloidPubsub::BaseActor do
6
+ let(:actor) { TestActor.new }
7
+ subject { actor.own_self }
8
+
9
+ it 'returns the self' do
10
+ expect(actor.own_self.class.name).to eq('TestActor')
11
+ expect(actor.own_self).to_not respond_to(:mailbox)
12
+ end
13
+
14
+ it 'returns the actor' do
15
+ expect(actor.cell_actor).to respond_to(:mailbox)
16
+ end
17
+
18
+ it 'returns true if action subscribe' do
19
+ expect(subject.send(:action_subscribe?, 'subscribe')).to eq(true)
20
+ end
21
+
22
+ describe '#parse_options' do
23
+ it 'returns empty hash for null value' do
24
+ expect(subject.send(:parse_options, nil)).to eq({})
25
+ end
26
+ it 'returns empty hash for null value' do
27
+ expect(subject.send(:parse_options, [{ a: 1 }, { b: 2 }])).to eq('b' => 2)
28
+ end
29
+ end
30
+
31
+ describe 'booting up' do
32
+ it 'does not boot if already running' do
33
+ allow(Celluloid).to receive(:running?).and_return(true)
34
+ expect(Celluloid).to_not receive(:boot)
35
+ CelluloidPubsub::BaseActor.boot_up
36
+ end
37
+
38
+ it 'boos if not running' do
39
+ allow(Celluloid).to receive(:running?).and_return(false)
40
+ expect(Celluloid).to receive(:boot)
41
+ CelluloidPubsub::BaseActor.boot_up
42
+ end
43
+
44
+ it 'boos if running? returns error ' do
45
+ allow(Celluloid).to receive(:running?).and_raise(RuntimeError)
46
+ expect(Celluloid).to receive(:boot)
47
+ begin
48
+ CelluloidPubsub::BaseActor.boot_up
49
+ rescue RuntimeError => e
50
+ end
51
+ end
52
+ end
53
+
54
+ describe 'fetch_gem_version' do
55
+ let(:gem_name) { 'rails' }
56
+ let(:version) { '1.2.3' }
57
+
58
+ it 'returns the loaded gem version' do
59
+ expect(subject).to receive(:find_loaded_gem_property).with(gem_name).and_return(nil)
60
+ result = actor.send(:fetch_gem_version, gem_name)
61
+ expect(result).to eq(nil)
62
+ end
63
+
64
+ it 'returns the loaded gem version' do
65
+ expected = 1.2
66
+ expect(subject).to receive(:find_loaded_gem_property).with(gem_name).and_return(version)
67
+ expect(subject).to receive(:get_parsed_version).with(version).and_return(expected)
68
+ result = actor.send(:fetch_gem_version, gem_name)
69
+ expect(result).to eq(expected)
70
+ end
71
+ end
72
+ describe 'filtered_error?' do
73
+ it 'filters the interrupt exception' do
74
+ error = Interrupt.new
75
+ expect(actor.send(:filtered_error?, error)).to eq(true)
76
+ end
77
+ end
78
+ end
@@ -5,27 +5,29 @@ require 'spec_helper'
5
5
  describe CelluloidPubsub::Client do
6
6
  let(:blk) { proc { |a| puts a } }
7
7
  let(:options) { {} }
8
- let(:actor) { mock }
9
- let(:connection) { mock }
8
+ let(:actor) { double('actor') }
9
+ let(:connection) { double('connection') }
10
10
  let(:channel) { 'some_channel' }
11
+ let(:additional_options) { {} }
11
12
 
12
13
  before(:each) do
13
- CelluloidPubsub::Client.any_instance.stubs(:supervise_actors).returns(true)
14
- CelluloidPubsub::Client.any_instance.stubs(:connection).returns(connection)
15
- @worker = CelluloidPubsub::Client.new(actor: actor, channel: channel, enable_debug: false)
16
- @worker.stubs(:debug).returns(true)
17
- @worker.stubs(:async).returns(@worker)
18
- actor.stubs(:async).returns(actor)
19
- actor.stubs(:respond_to?).returns(false)
20
- actor.stubs(:terminate).returns(true)
21
- connection.stubs(:terminate).returns(true)
22
- connection.stubs(:text).returns(true)
14
+ allow_any_instance_of(CelluloidPubsub::Client).to receive(:supervise_actors).and_return(true)
15
+ allow_any_instance_of(CelluloidPubsub::Client).to receive(:connection).and_return(connection)
16
+ allow(actor).to receive(:async).and_return(actor)
17
+ allow(actor).to receive(:terminate).and_return(true)
18
+ allow(connection).to receive(:terminate).and_return(true)
19
+ allow(connection).to receive(:text).and_return(true)
20
+ allow(connection).to receive(:alive?).and_return(true)
21
+ @worker = CelluloidPubsub::Client.new(additional_options.merge(actor: actor, channel: channel, enable_debug: false))
22
+ @own_self = @worker.own_self
23
+ allow(@own_self).to receive(:debug).and_return(true)
24
+ allow(@own_self).to receive(:async).and_return(@worker)
23
25
  end
24
26
 
25
27
  describe '#initialize' do
26
28
  it 'creates a object' do
27
- expect(@worker.channel).to eq channel
28
- expect(@worker.actor).to eq actor
29
+ expect(@own_self.channel).to eq channel
30
+ expect(@own_self.actor).to eq actor
29
31
  end
30
32
  end
31
33
 
@@ -63,30 +65,29 @@ describe CelluloidPubsub::Client do
63
65
  describe '#subscribe' do
64
66
  let(:channel) { 'some_channel' }
65
67
  it 'chats with the server' do
66
- @worker.expects(:chat).with('client_action' => 'subscribe', 'channel' => channel)
68
+ expect(@own_self).to receive(:chat).with('client_action' => 'subscribe', 'channel' => channel)
67
69
  @worker.subscribe(channel)
68
70
  end
69
71
  end
70
72
 
71
73
  describe '#succesfull_subscription?' do
72
- let(:message) { mock }
73
- let(:action) { mock }
74
+ let(:message) { double(present?: true) }
75
+ let(:action) { double }
74
76
 
75
77
  before(:each) do
76
- message.stubs(:present?).returns(true)
77
- message.stubs(:[]).with('client_action').returns('successful_subscription')
78
+ allow(message).to receive(:[]).with('client_action').and_return('successful_subscription')
78
79
  end
79
80
 
80
81
  it 'checks the message and returns true' do
81
- message.expects(:is_a?).with(Hash).returns(true)
82
- message.stubs(:[]).with('client_action').returns('successful_subscription')
82
+ expect(message).to receive(:is_a?).with(Hash).and_return(true)
83
+ allow(message).to receive(:[]).with('client_action').and_return('successful_subscription')
83
84
  actual = @worker.succesfull_subscription?(message)
84
85
  expect(actual).to eq(true)
85
86
  end
86
87
 
87
88
  it 'checks the message and returns false' do
88
- message.expects(:is_a?).with(Hash).returns(true)
89
- message.stubs(:[]).with('client_action').returns('something_else')
89
+ expect(message).to receive(:is_a?).with(Hash).and_return(true)
90
+ allow(message).to receive(:[]).with('client_action').and_return('something_else')
90
91
  actual = @worker.succesfull_subscription?(message)
91
92
  expect(actual).to eq(false)
92
93
  end
@@ -96,16 +97,59 @@ describe CelluloidPubsub::Client do
96
97
  let(:channel) { 'some_channel' }
97
98
  let(:data) { 'some_message' }
98
99
  it 'chats with the server' do
99
- @worker.expects(:send_action).with('publish', channel, data)
100
+ expect(@own_self).to receive(:send_action).with('publish', channel, data)
100
101
  @worker.publish(channel, data)
101
102
  end
102
103
  end
103
104
 
105
+ describe '#unsubscribe' do
106
+ let(:channel) { 'some_channel' }
107
+ it 'chats with the server' do
108
+ expect(@own_self).to receive(:send_action).with('unsubscribe', channel)
109
+ @worker.unsubscribe(channel)
110
+ end
111
+ end
112
+
113
+ describe '#unsubscribe_clients' do
114
+ let(:channel) { 'some_channel' }
115
+ it 'chats with the server' do
116
+ expect(@own_self).to receive(:send_action).with('unsubscribe_clients', channel)
117
+ @worker.unsubscribe_clients(channel)
118
+ end
119
+ end
120
+
121
+ describe '#unsubscribe_all' do
122
+ it 'chats with the server' do
123
+ expect(@own_self).to receive(:send_action).with('unsubscribe_all')
124
+ @worker.unsubscribe_all
125
+ end
126
+ end
127
+
128
+ describe '#supervise_actors' do
129
+ before do
130
+ allow_any_instance_of(CelluloidPubsub::Client).to receive(:supervise_actors).and_call_original
131
+ end
132
+
133
+ it 'supervises the actor' do
134
+ allow(actor).to receive(:respond_to?).with(:link).and_return(true)
135
+ expect(actor).to receive(:link).with(@worker)
136
+ expect(@worker).to receive(:link).with(connection)
137
+ @worker.supervise_actors
138
+ end
139
+
140
+ it 'does not link the actor if not possible' do
141
+ allow(actor).to receive(:respond_to?).with(:link).and_return(false)
142
+ expect(actor).to_not receive(:link).with(@worker)
143
+ expect(@worker).to receive(:link).with(connection)
144
+ @worker.supervise_actors
145
+ end
146
+ end
147
+
104
148
  describe '#on_open' do
105
149
  let(:channel) { 'some_channel' }
106
150
  let(:data) { 'some_message' }
107
151
  it 'chats with the server' do
108
- @worker.expects(:subscribe).with(channel)
152
+ expect(@own_self).to receive(:subscribe).with(channel)
109
153
  @worker.on_open
110
154
  end
111
155
  end
@@ -114,17 +158,17 @@ describe CelluloidPubsub::Client do
114
158
  let(:channel) { 'some_channel' }
115
159
  let(:data) { 'some_message' }
116
160
  it 'chats with the server' do
117
- JSON.expects(:parse).with(data).returns(data)
118
- @worker.actor.expects(:respond_to?).returns(true)
119
- @worker.actor.expects(:async).returns(actor)
120
- @worker.actor.expects(:on_message).with(data)
161
+ expect(JSON).to receive(:parse).with(data).and_return(data)
162
+ expect(@own_self.actor).to receive(:respond_to?).and_return(true)
163
+ expect(@own_self.actor).to receive(:async).and_return(actor)
164
+ expect(@own_self.actor).to receive(:on_message).with(data)
121
165
  @worker.on_message(data)
122
166
  end
123
167
 
124
168
  it 'chats with the server without async' do
125
- JSON.expects(:parse).with(data).returns(data)
126
- @worker.actor.expects(:respond_to?).returns(false)
127
- @worker.actor.expects(:on_message).with(data)
169
+ expect(JSON).to receive(:parse).with(data).and_return(data)
170
+ expect(@own_self.actor).to receive(:respond_to?).and_return(false)
171
+ expect(@own_self.actor).to receive(:on_message).with(data)
128
172
  @worker.on_message(data)
129
173
  end
130
174
  end
@@ -135,7 +179,13 @@ describe CelluloidPubsub::Client do
135
179
  let(:reason) { 'some_reason' }
136
180
 
137
181
  it 'chats with the server' do
138
- actor.expects(:on_close).with(code, reason).returns(true)
182
+ expect(actor).to receive(:on_close).with(code, reason).and_return(true)
183
+ @worker.on_close(code, reason)
184
+ end
185
+
186
+ it 'chats with the server' do
187
+ expect(actor).to receive(:respond_to?).with(:async).and_return(false)
188
+ expect(actor).to receive(:on_close).with(code, reason).and_return(true)
139
189
  @worker.on_close(code, reason)
140
190
  end
141
191
  end
@@ -145,15 +195,96 @@ describe CelluloidPubsub::Client do
145
195
  let(:data) { 'some_message' }
146
196
  let(:data_hash) { { a: 'some mesage ' } }
147
197
  let(:json) { { action: 'message', message: data } }
148
- it 'chats witout hash' do
149
- JSON.expects(:dump).with(json).returns(json)
150
- connection.expects(:text).with(json)
198
+ it 'chats without hash' do
199
+ expect(JSON).to receive(:dump).with(json).and_return(json)
200
+ expect(connection).to receive(:text).with(json)
151
201
  @worker.send(:chat, data)
152
202
  end
153
203
 
154
204
  it 'chats with a hash' do
155
- connection.expects(:text).with(data_hash.to_json)
205
+ expect(connection).to receive(:text).with(data_hash.to_json)
156
206
  @worker.send(:chat, data_hash)
157
207
  end
158
208
  end
209
+
210
+ describe 'shutting_down?' do
211
+ it 'returns false by default' do
212
+ expect(@worker.shutting_down?).to eq(false)
213
+ end
214
+
215
+ it 'returns true' do
216
+ allow(@own_self).to receive(:terminate).and_return(true)
217
+ expect { @worker.shutdown }.to change(@worker, :shutting_down?).from(false).to(true)
218
+ end
219
+
220
+ it 'returns true when actor dies' do
221
+ allow(@own_self).to receive(:shutdown).and_return(true)
222
+ allow(@worker).to receive(:hostname).and_raise(RuntimeError)
223
+ begin
224
+ expect { @worker.hostname }.to change(@worker, :shutting_down?).from(false).to(true)
225
+ rescue RuntimeError => e
226
+ # do nothing
227
+ end
228
+ end
229
+ end
230
+
231
+ describe 'log_file_path' do
232
+ it 'returns nil by default' do
233
+ expect(@worker.log_file_path).to eq(nil)
234
+ end
235
+
236
+ context 'when log file path is defined' do
237
+ let(:path) { '/some-path-here' }
238
+ let(:additional_options) { { log_file_path: path } }
239
+
240
+ it 'returns the path' do
241
+ expect(@worker.log_file_path).to eq(path)
242
+ end
243
+ end
244
+ end
245
+
246
+ describe 'log_level' do
247
+ it 'returns info by default' do
248
+ expect(@worker.log_level).to eq(::Logger::Severity::INFO)
249
+ end
250
+
251
+ context 'when log level is defined' do
252
+ let(:level) { Logger::Severity::DEBUG }
253
+ let(:additional_options) { { log_level: level } }
254
+
255
+ it 'returns the path' do
256
+ expect(@worker.log_level).to eq(level)
257
+ end
258
+ end
259
+ end
260
+
261
+ describe 'path' do
262
+ it 'returns the path of the server' do
263
+ expect(@worker.path).to eq(CelluloidPubsub::WebServer::PATH)
264
+ end
265
+
266
+ context 'when path is defined' do
267
+ let(:path) { '/demo' }
268
+ let(:additional_options) { { path: path } }
269
+
270
+ it 'returns the path' do
271
+ expect(@worker.path).to eq(path)
272
+ end
273
+ end
274
+ end
275
+
276
+ describe 'connection' do
277
+ it 'returns the path of the server' do
278
+ allow_any_instance_of(CelluloidPubsub::Client).to receive(:connection).and_call_original
279
+ expect(CelluloidPubsub::ClientConnection).to receive(:new).with("ws://#{@worker.hostname}:#{@worker.port}#{@worker.path}", @worker).and_return(connection)
280
+ result = @worker.connection
281
+ expect(result).to eq(connection)
282
+ end
283
+ end
284
+
285
+ describe 'actor_died' do
286
+ it 'sets the shutting down' do
287
+ expect { @worker.send(:actor_died, @worker, nil) }.to change(@worker, :shutting_down?).from(false).to(true)
288
+ end
289
+ end
159
290
  end
@@ -3,39 +3,62 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe CelluloidPubsub::Reactor do
6
- let(:websocket) { mock }
7
- let(:server) { mock }
8
- let(:mutex) { mock }
9
- let(:synchronizer) { mock }
6
+ let(:websocket) do
7
+ double(
8
+ 'websocket',
9
+ url: nil,
10
+ read: nil,
11
+ close: nil,
12
+ closed?: false,
13
+ present?: false
14
+ )
15
+ end
16
+ let(:server_options) { {}.with_indifferent_access }
17
+ let(:server) do
18
+ double(
19
+ 'server',
20
+ debug_enabled?: false,
21
+ adapter: CelluloidPubsub::WebServer::CLASSIC_ADAPTER,
22
+ server_options: server_options,
23
+ dead?: false,
24
+ subscribers: {},
25
+ handle_dispatched_message: nil,
26
+ mutex: mutex,
27
+ timers_mutex: timers_mutex,
28
+ reactors: []
29
+ )
30
+ end
31
+ let(:mutex) { double('mutex') }
32
+ let(:synchronizer) { double('synchronizer') }
33
+ let(:timers_mutex) { double('timers_mutex') }
34
+ let(:timers_synchronizer) { double('timers_synchronizer') }
10
35
 
11
36
  before(:each) do
12
- subject.stubs(:async).returns(subject)
13
- server.stubs(:debug_enabled?).returns(false)
14
- server.stubs(:async).returns(server)
15
- server.stubs(:handle_dispatched_message)
16
- server.stubs(:subscribers).returns({})
17
- server.stubs(:adapter).returns(CelluloidPubsub::WebServer::CLASSIC_ADAPTER)
18
- websocket.stubs(:read)
19
- websocket.stubs(:url)
20
- websocket.stubs(:close)
21
- websocket.stubs(:closed?).returns(false)
22
- server.stubs(:dead?).returns(false)
23
- subject.stubs(:inspect).returns(subject)
24
- subject.stubs(:run)
25
- subject.work(websocket, server)
26
- subject.stubs(:unsubscribe_from_channel).returns(true)
27
- server.stubs(:mutex).returns(mutex)
28
- mutex.stubs(:synchronize).yields(server)
29
- Celluloid::Actor.stubs(:kill).returns(true)
37
+ allow(server).to receive(:async).and_return(server)
38
+ allow(actor).to receive(:async).and_return(actor)
39
+ allow(actor).to receive(:inspect).and_return(actor)
40
+ allow(actor).to receive(:run)
41
+ allow(actor).to receive(:unsubscribe_from_channel).and_return(true)
42
+ allow(mutex).to receive(:synchronize).and_yield
43
+ allow(timers_mutex).to receive(:synchronize).and_yield
44
+ allow(Celluloid::Actor).to receive(:kill).and_return(true)
45
+ allow_any_instance_of(CelluloidPubsub::Reactor).to receive(:shutdown).and_return(true)
46
+ end
47
+
48
+ after(:each) do
49
+ Celluloid.shutdown
30
50
  end
31
51
 
52
+ let(:actor) { CelluloidPubsub::Reactor.new.initialize_data(websocket, server) }
53
+ subject { actor.own_self }
54
+
32
55
  describe '#work' do
33
56
  it 'works ' do
34
- subject.expects(:run)
35
- subject.work(websocket, server)
36
- expect(subject.websocket).to eq websocket
37
- expect(subject.server).to eq server
38
- expect(subject.channels).to eq []
57
+ expect(actor).to receive(:run)
58
+ actor.work(websocket, server)
59
+ expect(actor.websocket).to eq(websocket)
60
+ expect(actor.server).to eq(server)
61
+ expect(actor.channels).to eq([])
39
62
  end
40
63
  end
41
64
 
@@ -43,10 +66,10 @@ describe CelluloidPubsub::Reactor do
43
66
  # let(:data) { 'some message' }
44
67
  #
45
68
  # it 'works ' do
46
- # subject.unstub(:run)
47
- # websocket.stubs(:read).returns(data)
48
- # subject.expects(:handle_websocket_message).with(data)
49
- # subject.run
69
+ # actor.unstub(:run)
70
+ # allow(websocket).to receive(:read).and_return(data)
71
+ # expect(subject).to receive(:handle_websocket_message).with(data)
72
+ # actor.run
50
73
  # end
51
74
  # end
52
75
 
@@ -55,14 +78,14 @@ describe CelluloidPubsub::Reactor do
55
78
  let(:expected) { data.to_json }
56
79
 
57
80
  it 'works with hash ' do
58
- JSON.expects(:parse).with(data).returns(expected)
59
- actual = subject.parse_json_data(data)
81
+ expect(JSON).to receive(:parse).with(data).and_return(expected)
82
+ actual = actor.parse_json_data(data)
60
83
  expect(actual).to eq expected
61
84
  end
62
85
 
63
86
  it 'works with exception parsing ' do
64
- JSON.expects(:parse).with(data).raises(StandardError)
65
- actual = subject.parse_json_data(data)
87
+ expect(JSON).to receive(:parse).with(data).and_raise(StandardError)
88
+ actual = actor.parse_json_data(data)
66
89
  expect(actual).to eq data
67
90
  end
68
91
  end
@@ -72,96 +95,91 @@ describe CelluloidPubsub::Reactor do
72
95
  let(:json_data) { { a: 'b' } }
73
96
 
74
97
  it 'handle_websocket_message' do
75
- subject.expects(:parse_json_data).with(data).returns(json_data)
76
- subject.expects(:handle_parsed_websocket_message).with(json_data)
77
- subject.handle_websocket_message(data)
98
+ expect(subject).to receive(:parse_json_data).with(data).and_return(json_data)
99
+ expect(subject).to receive(:handle_parsed_websocket_message).with(json_data)
100
+ actor.handle_websocket_message(data)
78
101
  end
79
102
  end
80
103
 
81
104
  describe '#handle_parsed_websocket_message' do
82
105
  it 'handle_websocket_message with a hash' do
83
- data = { 'client_action' => 'subscribe' }
84
- data.expects(:stringify_keys).returns(data)
85
- subject.expects(:delegate_action).with(data)
86
- subject.handle_parsed_websocket_message(data)
106
+ data = { 'client_action' => 'subscribe', 'channel' => 'test' }
107
+ expect(data).to receive(:stringify_keys).and_return(data)
108
+ expect(subject).to receive(:delegate_action).with(data).and_return(true)
109
+ actor.handle_parsed_websocket_message(data)
87
110
  end
88
111
 
89
112
  it 'handle_websocket_message with something else than a hash' do
90
- data = { 'message'=> 'some message' }
91
- subject.expects(:handle_unknown_action).with(data['channel'], data)
92
- subject.handle_parsed_websocket_message(data)
113
+ data = { 'message' => 'some message' }
114
+ expect(subject).to receive(:handle_unknown_action).with(data['channel'], data).and_return(true)
115
+ actor.handle_parsed_websocket_message(data)
93
116
  end
94
117
  end
95
118
 
96
119
  describe '#delegate_action' do
97
-
98
120
  before(:each) do
99
- subject.stubs(:unsubscribe_clients).returns(true)
100
- subject.stubs(:shutdown).returns(true)
121
+ allow(subject).to receive(:unsubscribe_clients).and_return(true)
122
+ allow(subject).to receive(:shutdown).and_return(true)
101
123
  end
102
124
 
103
125
  it 'unsubscribes all' do
104
126
  data = { 'client_action' => 'unsubscribe_all', 'channel' => '' }
105
- subject.expects(:send).with(data['client_action'], data['channel'], data).returns('bla')
106
- subject.delegate_action(data)
127
+ expect(subject).to receive(:send).with(data['client_action'], data['channel'], data).and_return('bla')
128
+ actor.delegate_action(data)
107
129
  end
108
130
 
109
131
  it 'unsubscribes all' do
110
132
  data = { 'client_action' => 'unsubscribe', 'channel' => 'some channel' }
111
- subject.expects(:send).with(data['client_action'], data['channel'], data)
112
- subject.delegate_action(data)
133
+ expect(subject).to receive(:send).with(data['client_action'], data['channel'], data)
134
+ actor.delegate_action(data)
113
135
  end
114
- #
115
136
  it 'subscribes to channell' do
116
137
  data = { 'client_action' => 'subscribe', 'channel' => 'some channel' }
117
- subject.expects(:send).with(data['client_action'], data['channel'], data)
118
- subject.delegate_action(data)
138
+ expect(subject).to receive(:send).with(data['client_action'], data['channel'], data)
139
+ actor.delegate_action(data)
119
140
  end
120
141
 
121
142
  it 'publish' do
122
143
  data = { 'client_action' => 'publish', 'channel' => 'some channel', 'data' => 'some data' }
123
- subject.expects(:send).with(data['client_action'], data['channel'], data)
124
- subject.delegate_action(data)
144
+ expect(subject).to receive(:send).with(data['client_action'], data['channel'], data)
145
+ actor.delegate_action(data)
125
146
  end
126
147
  end
127
- #
128
148
  describe '#handle_unknown_action' do
129
149
  it 'handles unknown' do
130
150
  data = 'some data'
131
- channel = "some_channel"
132
- server.expects(:handle_dispatched_message)
133
- subject.handle_unknown_action(channel, data)
151
+ channel = 'some_channel'
152
+ expect(server).to receive(:handle_dispatched_message)
153
+ actor.handle_unknown_action(channel, data)
134
154
  end
135
155
  end
136
156
 
137
157
  describe '#unsubscribe_client' do
138
158
  let(:channel) { 'some channel' }
139
- let(:data) { {'client_action' => 'unsubscribe', 'channel' => channel } }
159
+ let(:data) { { 'client_action' => 'unsubscribe', 'channel' => channel } }
140
160
  it 'returns nil' do
141
- act = subject.unsubscribe('', data)
161
+ act = actor.unsubscribe('', data)
142
162
  expect(act).to eq(nil)
143
163
  end
144
164
 
145
165
  it 'unsubscribes' do
146
- channel.stubs(:present?).returns(true)
147
- subject.expects(:forget_channel).with(channel)
148
- subject.expects(:delete_server_subscribers).with(channel)
149
- act = subject.unsubscribe(channel, data)
166
+ allow(channel).to receive(:present?).and_return(true)
167
+ expect(subject).to receive(:forget_channel).with(channel)
168
+ expect(subject).to receive(:delete_server_subscribers).with(channel)
169
+ act = actor.unsubscribe(channel, data)
150
170
  expect(act).to eq(nil)
151
171
  end
152
-
153
-
154
172
  end
155
173
 
156
174
  describe '#delete_server_subscribers' do
157
175
  let(:channel) { 'some channel' }
158
176
 
159
177
  before(:each) do
160
- server.stubs(:subscribers).returns("#{channel}" => [{ reactor: subject }])
178
+ allow(server).to receive(:subscribers).and_return(channel.to_s => [{ reactor: actor }])
161
179
  end
162
180
 
163
181
  it 'unsubscribes' do
164
- act = subject.delete_server_subscribers(channel)
182
+ act = actor.delete_server_subscribers(channel)
165
183
  expect(server.subscribers[channel]).to eq([])
166
184
  end
167
185
  end
@@ -170,25 +188,29 @@ describe CelluloidPubsub::Reactor do
170
188
  let(:channel) { 'some channel' }
171
189
 
172
190
  it 'unsubscribes' do
173
- subject.channels.stubs(:blank?).returns(true)
174
- subject.websocket.expects(:close)
175
- act = subject.forget_channel(channel)
191
+ allow(actor.channels).to receive(:blank?).and_return(true)
192
+ expect(actor.websocket).to receive(:close)
193
+ act = actor.forget_channel(channel)
176
194
  expect(act).to eq(nil)
177
195
  end
178
196
 
179
197
  it 'unsubscribes' do
180
- subject.channels.stubs(:blank?).returns(false)
181
- subject.channels.expects(:delete).with(channel)
182
- # server.stubs(:subscribers).returns("#{channel}" => [{ reactor: subject }])
183
- subject.forget_channel(channel)
184
- # expect(server.subscribers[channel]).to eq([])
198
+ allow(actor.channels).to receive(:blank?).and_return(false)
199
+ expect(actor.channels).to receive(:delete).with(channel)
200
+ # allow(server).to receive(:subscribers).and_return("#{channel}" => [{ reactor: subject }])
201
+ actor.forget_channel(channel)
202
+ # expect(server.subscribers[channel]).to eq([])
185
203
  end
186
204
  end
187
205
 
188
206
  describe '#shutdown' do
207
+ before(:each) do
208
+ allow_any_instance_of(CelluloidPubsub::Reactor).to receive(:shutdown).and_call_original
209
+ end
210
+
189
211
  it 'shutdowns' do
190
- subject.expects(:terminate)
191
- subject.shutdown
212
+ expect(subject).to receive(:terminate).at_least(:once)
213
+ actor.shutdown
192
214
  end
193
215
  end
194
216
 
@@ -197,22 +219,22 @@ describe CelluloidPubsub::Reactor do
197
219
  let(:message) { { a: 'b' } }
198
220
 
199
221
  it 'subscribes ' do
200
- act = subject.subscribe('', message)
222
+ act = actor.subscribe('', message)
201
223
  expect(act).to eq(nil)
202
224
  end
203
225
 
204
226
  it 'subscribes ' do
205
- subject.stubs(:add_subscriber_to_channel).with(channel, message)
206
- server.stubs(:redis_enabled?).returns(false)
207
- subject.websocket.expects(:<<).with(message.merge('client_action' => 'successful_subscription', 'channel' => channel).to_json)
208
- subject.subscribe(channel, message)
227
+ allow(subject).to receive(:add_subscriber_to_channel).with(channel, message)
228
+ allow(server).to receive(:redis_enabled?).and_return(false)
229
+ expect(actor.websocket).to receive(:<<).with(message.merge('client_action' => 'successful_subscription', 'channel' => channel).to_json)
230
+ actor.subscribe(channel, message)
209
231
  end
210
232
 
211
233
  # it 'raises error' do
212
- # subject.stubs(:add_subscriber_to_channel).raises(StandardError)
234
+ # subject).to receive(:add_subscriber_to_channel).raises(StandardError)
213
235
  #
214
236
  # expect do
215
- # subject.start_subscriber(channel, message)
237
+ # actor.start_subscriber(channel, message)
216
238
  # end.to raise_error(StandardError) { |e|
217
239
  # expect(e.message).to include(channel)
218
240
  # }
@@ -222,15 +244,15 @@ describe CelluloidPubsub::Reactor do
222
244
  describe '#add_subscriber_to_channel' do
223
245
  let(:channel) { 'some channel' }
224
246
  let(:message) { { a: 'b' } }
225
- let(:subscribers) { mock }
247
+ let(:subscribers) { double }
226
248
 
227
249
  it 'adds subscribed' do
228
- CelluloidPubsub::Registry.channels.stubs(:include?).with(channel).returns(false)
229
- CelluloidPubsub::Registry.channels.expects(:<<).with(channel)
230
- subject.expects(:channel_subscribers).with(channel).returns(subscribers)
231
- subscribers.expects(:push).with(reactor: subject, message: message)
232
- subject.add_subscriber_to_channel(channel, message)
233
- expect(subject.channels).to include(channel)
250
+ allow(CelluloidPubsub::Registry.channels).to receive(:include?).with(channel).and_return(false)
251
+ expect(CelluloidPubsub::Registry.channels).to receive(:<<).with(channel)
252
+ expect(subject).to receive(:channel_subscribers).with(channel).and_return(subscribers)
253
+ expect(subscribers).to receive(:push).with(reactor: actor, message: message)
254
+ actor.add_subscriber_to_channel(channel, message)
255
+ expect(actor.channels).to include(channel)
234
256
  end
235
257
  end
236
258
 
@@ -239,9 +261,262 @@ describe CelluloidPubsub::Reactor do
239
261
  let(:message) { { a: 'b' } }
240
262
 
241
263
  it 'adds subscribed' do
242
- CelluloidPubsub::Registry.stubs(:channels).returns([channel])
243
- subject.expects(:unsubscribe_from_channel).with(channel).returns(true)
244
- subject.unsubscribe_all(channel, message)
264
+ allow(CelluloidPubsub::Registry).to receive(:channels).and_return([channel])
265
+ expect(subject).to receive(:unsubscribe_from_channel).with(channel).and_return(true)
266
+ actor.unsubscribe_all(channel, message)
267
+ end
268
+ end
269
+
270
+ describe 'log_file_path' do
271
+ it 'returns nil by default' do
272
+ expect(actor.log_file_path).to eq(nil)
273
+ end
274
+
275
+ context 'when log file path is defined' do
276
+ let(:path) { '/some-path-here' }
277
+ let(:server_options) { { log_file_path: path }.with_indifferent_access }
278
+
279
+ it 'returns the path' do
280
+ expect(actor.log_file_path).to eq(path)
281
+ end
282
+ end
283
+ end
284
+
285
+ describe 'log_level' do
286
+ it 'returns info by default' do
287
+ expect(actor.log_level).to eq(::Logger::Severity::INFO)
288
+ end
289
+
290
+ context 'when log level is defined' do
291
+ let(:level) { Logger::Severity::DEBUG }
292
+ let(:server_options) { { log_level: level }.with_indifferent_access }
293
+
294
+ it 'returns the path' do
295
+ expect(actor.log_level).to eq(level)
296
+ end
297
+ end
298
+ end
299
+
300
+ describe 'adapter options' do
301
+ it 'returns info by default' do
302
+ expect(actor.adapter_options).to eq({})
303
+ end
304
+
305
+ context 'when log level is defined' do
306
+ let(:adapter_options) { { something: :here, another: { key: :value } } }
307
+ let(:server_options) { { adapter_options: adapter_options }.with_indifferent_access }
308
+
309
+ it 'returns the path' do
310
+ expect(actor.adapter_options).to eq(adapter_options.deep_stringify_keys)
311
+ end
312
+ end
313
+ end
314
+
315
+ describe 'shutting_down?' do
316
+ before(:each) do
317
+ allow_any_instance_of(CelluloidPubsub::Reactor).to receive(:shutdown).and_call_original
318
+ end
319
+
320
+ it 'returns false by default' do
321
+ expect(actor.shutting_down?).to eq(false)
322
+ end
323
+
324
+ it 'returns true' do
325
+ allow(subject).to receive(:terminate).and_return(true)
326
+ expect { actor.shutdown }.to change(actor, :shutting_down?).from(false).to(true)
327
+ end
328
+
329
+ it 'returns true when actor dies' do
330
+ allow(subject).to receive(:shutdown).and_return(true)
331
+ allow(actor).to receive(:log_level).and_raise(RuntimeError)
332
+ begin
333
+ expect { actor.log_level }.to change(actor, :shutting_down?).from(false).to(true)
334
+ rescue RuntimeError => e
335
+ # do nothing
336
+ end
337
+ end
338
+ end
339
+
340
+ describe 'try_read_websocket' do
341
+ it 'returns nil if socket closed' do
342
+ allow(websocket).to receive(:closed?).and_return(true)
343
+ expect(websocket).to_not receive(:read)
344
+ result = actor.try_read_websocket
345
+ expect(result).to eq(nil)
346
+ end
347
+
348
+ it 'reads the socket' do
349
+ expected = 'something'
350
+ allow(websocket).to receive(:closed?).and_return(false)
351
+ expect(websocket).to receive(:read).and_return(expected)
352
+ result = actor.try_read_websocket
353
+ expect(result).to eq(expected)
354
+ end
355
+
356
+ it 'returns nil if socket closed' do
357
+ allow(websocket).to receive(:closed?).and_return(false)
358
+ expect(websocket).to receive(:read).and_raise(StandardError)
359
+ result = actor.try_read_websocket
360
+ expect(result).to eq(nil)
361
+ end
362
+ end
363
+
364
+ describe 'send_unpublshed' do
365
+ let(:channel) { 'test' }
366
+ let(:messages) { [1, 2, 3] }
367
+
368
+ it 'does not send if no messages' do
369
+ allow(subject).to receive(:unpublished_messages).with(channel).and_return(nil)
370
+ expect(websocket).to_not receive(:<<)
371
+ subject.send_unpublished(channel)
372
+ end
373
+
374
+ it 'sends the messages' do
375
+ allow(subject).to receive(:unpublished_messages).with(channel).and_return(messages)
376
+ messages.each do |msg|
377
+ expect(websocket).to receive(:<<).ordered.with(msg.to_json)
378
+ end
379
+ subject.send_unpublished(channel)
380
+ end
381
+ end
382
+
383
+ describe 'clears the messages' do
384
+ let(:channel) { 'test' }
385
+ let(:messages) { [1, 2, 3] }
386
+
387
+ before do
388
+ CelluloidPubsub::Registry.messages[channel] = messages
389
+ end
390
+
391
+ after do
392
+ CelluloidPubsub::Registry.messages = {}
393
+ end
394
+
395
+ it 'clears the messages' do
396
+ actor.clear_unpublished_messages(channel)
397
+ expect(CelluloidPubsub::Registry.messages).to eq(channel => [])
398
+ end
399
+ end
400
+
401
+ describe 'unpublished_messages' do
402
+ let(:channel) { 'test' }
403
+ let(:messages) { [1, 2, 3] }
404
+
405
+ before do
406
+ CelluloidPubsub::Registry.messages[channel] = messages
407
+ end
408
+
409
+ after do
410
+ CelluloidPubsub::Registry.messages = {}
411
+ end
412
+
413
+ it 'retrieves the messages' do
414
+ result = actor.unpublished_messages(channel)
415
+ expect(result).to eq(messages)
416
+ end
417
+
418
+ it 'returns empty array for non existing channel' do
419
+ result = actor.unpublished_messages('something-here')
420
+ expect(result).to eq([])
421
+ end
422
+ end
423
+
424
+ describe 'subscribers' do
425
+ let(:channel) { 'test' }
426
+ before do
427
+ server.subscribers[channel] = [{ reactor: actor }]
428
+ end
429
+
430
+ it 'returns empty array' do
431
+ result = actor.channel_subscribers('some-channel')
432
+ expect(result).to eq([])
433
+ end
434
+
435
+ it 'returns the subscribers' do
436
+ result = actor.channel_subscribers(channel)
437
+ expect(result).to eq([{ reactor: actor }])
438
+ end
439
+ end
440
+
441
+ describe 'publish' do
442
+ let(:channel) { 'test' }
443
+ let(:data) { { 'client_action' => 'publish', 'channel' => 'test_channel', 'data' => { 'data' => ' my_message' } } }
444
+
445
+ it 'publishes the message' do
446
+ expect(subject).to receive(:server_publish_event).with(channel, data['data'].to_json)
447
+ actor.publish(channel, data)
448
+ end
449
+
450
+ it 'does not publish if channel is blank' do
451
+ expect(subject).to_not receive(:server_publish_event)
452
+ actor.publish(nil, data)
453
+ end
454
+
455
+ it 'publishes null' do
456
+ expect(subject).to receive(:server_publish_event).with(channel, 'null')
457
+ actor.publish(channel, data.except('data'))
458
+ end
459
+
460
+ it 'catches error' do
461
+ expect(subject).to receive(:server_publish_event).and_raise(StandardError)
462
+ expect(subject).to receive(:log_debug)
463
+ actor.publish(channel, data.except('data'))
464
+ end
465
+ end
466
+
467
+ describe 'server_publish_event' do
468
+ let(:actor2) { CelluloidPubsub::Reactor.new.initialize_data(websocket, server) }
469
+ let(:subject2) { actor2.own_self }
470
+
471
+ let(:channel) { 'test' }
472
+ let(:message) { '1' }
473
+ before do
474
+ server.subscribers[channel] = [{ reactor: actor }, { reactor: actor2 }]
475
+ end
476
+
477
+ it 'published message to channel' do
478
+ server.subscribers[channel].each do |hash|
479
+ expect(hash[:reactor].websocket).to receive(:<<).with(message)
480
+ end
481
+ actor.server_publish_event(channel, message)
482
+ end
483
+
484
+ it 'saves the mesages if no subscribers' do
485
+ channel2 = 'some-channel'
486
+ expect(subject).to receive(:save_unpublished_message).with(channel2, message).and_call_original
487
+ actor.server_publish_event(channel2, message)
488
+ expect(CelluloidPubsub::Registry.messages).to eq(channel2 => [message])
489
+ end
490
+ end
491
+ describe 'unsubscribe_from_channel' do
492
+ let(:channel) { 'test' }
493
+ it 'kills the reactors' do
494
+ expect(subject).to receive(:server_kill_reactors).with(channel)
495
+ subject.unsubscribe_from_channel(channel)
496
+ end
497
+ end
498
+
499
+ describe 'server_kill_reactors' do
500
+ let(:actor2) { CelluloidPubsub::Reactor.new.initialize_data(websocket, server) }
501
+ let(:subject2) { actor2.own_self }
502
+
503
+ let(:channel) { 'test' }
504
+
505
+ before do
506
+ server.subscribers[channel] = [{ reactor: actor }, { reactor: actor2 }]
507
+ end
508
+
509
+ it 'kills the reactors' do
510
+ server.subscribers[channel].each do |hash|
511
+ expect(hash[:reactor].websocket).to receive(:close)
512
+ expect(Celluloid::Actor).to receive(:kill).ordered.with(hash[:reactor])
513
+ end
514
+ actor.server_kill_reactors(channel)
515
+ end
516
+ end
517
+ describe 'actor_died' do
518
+ it 'sets the shutting down' do
519
+ expect { actor.send(:actor_died, actor, nil) }.to change(actor, :shutting_down?).from(false).to(true)
245
520
  end
246
521
  end
247
522
  end