cocaine-framework-ruby 0.11.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ module Cocaine
2
+ VERSION = '0.11.2'
3
+ end
@@ -0,0 +1,160 @@
1
+ require 'rspec'
2
+
3
+ require_relative '../lib/cocaine/asio/channel'
4
+ require_relative '../lib/cocaine/asio/channel/combiner'
5
+
6
+ describe Cocaine::Channel do
7
+ it 'should invoke callback immediately if it has pending data' do
8
+ done = false
9
+ channel = Cocaine::Channel.new
10
+ channel.trigger 'actual'
11
+ channel.callback { |data|
12
+ expect(data).to be == 'actual'
13
+ done = true
14
+ }
15
+ done.should == true
16
+ end
17
+
18
+ it 'should invoke errback immediately if it has pending errors' do
19
+ done = false
20
+ channel = Cocaine::Channel.new
21
+ channel.error 'actual'
22
+ channel.errback { |data|
23
+ expect(data).to be == 'actual'
24
+ done = true
25
+ }
26
+ done.should == true
27
+ end
28
+
29
+ it 'should invoke callback after triggering' do
30
+ done = false
31
+ channel = Cocaine::Channel.new
32
+ channel.callback { |data|
33
+ expect(data).to be == 'actual'
34
+ done = true
35
+ }
36
+ channel.trigger 'actual'
37
+ done.should == true
38
+ end
39
+
40
+ it 'should invoke errback after triggering' do
41
+ done = false
42
+ channel = Cocaine::Channel.new
43
+ channel.errback { |data|
44
+ expect(data).to be == 'actual'
45
+ done = true
46
+ }
47
+ channel.error 'actual'
48
+ done.should == true
49
+ end
50
+
51
+ it 'should invoke all callbacks after closed' do
52
+ counter = 0
53
+
54
+ channel = Cocaine::Channel.new
55
+ channel.trigger 'actual'
56
+ channel.trigger 'actual'
57
+
58
+ channel.callback { |data|
59
+ expect(data).to be == 'actual'
60
+ counter += 1
61
+ }
62
+ channel.close
63
+
64
+ expect counter == 2
65
+ end
66
+
67
+ it 'should raise error when triggered after it was closed' do
68
+ channel = Cocaine::Channel.new
69
+ channel.close
70
+ expect { channel.trigger nil }.to raise_error IllegalStateError
71
+ end
72
+
73
+ it 'should raise error when adding callback after is was closed' do
74
+ channel = Cocaine::Channel.new
75
+ channel.close
76
+ expect { channel.callback {} }.to raise_error IllegalStateError
77
+ end
78
+ end
79
+
80
+ describe Cocaine::Channel, '#collect' do
81
+ it 'should have `collect` method' do
82
+ Cocaine::Channel.new.collect
83
+ end
84
+
85
+ it 'should return all collected chunks after closing' do
86
+ flag = false
87
+ ch = Cocaine::Channel.new
88
+ ch.trigger 'chunk'
89
+ ch.trigger 'chmod'
90
+ ch.trigger 'chang'
91
+ df = ch.collect
92
+ df.callback { |chunks|
93
+ expect(chunks).to eq(%w(chunk chmod chang))
94
+ flag = true
95
+ }
96
+ ch.close
97
+ expect(flag).to be true
98
+ end
99
+
100
+ it 'should return all collected errors after closing' do
101
+ flag = false
102
+ ch = Cocaine::Channel.new
103
+ ch.error Exception.new 123
104
+ ch.error Exception.new 456
105
+ df = ch.collect
106
+ df.callback { |errors|
107
+ expect(errors).to eq([Exception.new(123), Exception.new(456)])
108
+ flag = true
109
+ }
110
+ ch.close
111
+ expect(flag).to be true
112
+ end
113
+
114
+ it 'should fail and return error if only one error comes' do
115
+ flag = false
116
+ ch = Cocaine::Channel.new
117
+ ch.error Exception.new 123
118
+ df = ch.collect
119
+ df.errback { |errors|
120
+ expect(errors).to eq(Exception.new(123))
121
+ flag = true
122
+ }
123
+ ch.close
124
+ expect(flag).to be true
125
+ end
126
+ end
127
+
128
+
129
+ describe Cocaine::ChannelCombiner do
130
+ it 'should be' do
131
+ channel = Cocaine::Channel.new
132
+ Cocaine::ChannelCombiner.new channel
133
+ end
134
+
135
+ it 'should merge callbacks' do
136
+ flag = false
137
+ channel = Cocaine::Channel.new
138
+ zipper = Cocaine::ChannelCombiner.new channel
139
+ zipper.callback { |r|
140
+ expect(r.get).to eq('test')
141
+ flag = true
142
+ }
143
+ channel.trigger('test')
144
+
145
+ expect(flag).to be true
146
+ end
147
+
148
+ it 'should merge errorbacks' do
149
+ flag = false
150
+ channel = Cocaine::Channel.new
151
+ zipper = Cocaine::ChannelCombiner.new channel
152
+ zipper.callback { |r|
153
+ expect { r.get }.to raise_error(Exception)
154
+ flag = true
155
+ }
156
+ channel.error(Exception.new 'test')
157
+
158
+ expect(flag).to be true
159
+ end
160
+ end
@@ -0,0 +1,31 @@
1
+ require 'rspec'
2
+ require 'msgpack'
3
+
4
+ require_relative '../lib/cocaine/asio/connection'
5
+ require_relative '../lib/cocaine/client/dispatcher'
6
+ require_relative '../lib/cocaine/protocol'
7
+
8
+ require_relative 'stub_server'
9
+
10
+ describe Cocaine::Connection do
11
+ it 'should transmit received data to decoder' do
12
+ EventMachine::run {
13
+ msg = [4, 1, [['0.0.0.0', 0], 0, {0 => 'method'}].to_msgpack]
14
+ encoded_msg = msg.to_msgpack
15
+ server = StubServer.new(response: encoded_msg)
16
+
17
+ decoder = double()
18
+ expect(decoder).to receive(:feed).with(encoded_msg) do |&arg|
19
+ arg.call(msg)
20
+ end
21
+ EventMachine.connect '127.0.0.1', 9053, Cocaine::Connection, decoder do |conn|
22
+ dispatcher = Cocaine::ClientDispatcher.new conn
23
+ channel = dispatcher.invoke 0, 'bullshit'
24
+ channel.callback {
25
+ server.stop
26
+ EventMachine::stop
27
+ }
28
+ end
29
+ }
30
+ end
31
+ end
@@ -0,0 +1,19 @@
1
+ require 'rspec'
2
+
3
+ require_relative '../lib/cocaine/server/health'
4
+
5
+ describe Cocaine::HealthManager do
6
+ it 'should be' do
7
+ d = double()
8
+ Cocaine::HealthManager.new d
9
+ end
10
+
11
+ it 'should stop event loop if nobody takes breath to it until timeout' do
12
+ EM.run do
13
+ d = double()
14
+ d.should_receive(:send_heartbeat).with(0).once
15
+ health = Cocaine::HealthManager.new d, disown: 0.0, heartbeat: 0.1
16
+ health.start()
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,322 @@
1
+ require 'rspec'
2
+
3
+ require_relative '../lib/cocaine/client/service'
4
+ require_relative '../lib/cocaine/protocol'
5
+ require_relative '../lib/cocaine/synchrony/service'
6
+ require_relative '../lib/cocaine/testing/mock_server'
7
+
8
+ require_relative 'stub_server'
9
+
10
+
11
+ describe Cocaine::Locator do
12
+ it 'should send correct message to the locator while resolving service' do
13
+ EM.run do
14
+ expected = {endpoint: ['127.0.0.1', 10054], version: 1, api: {0 => 'start_app', 1 => 'pause_app', 2 => 'list'}}
15
+ server = CocaineRuntimeMock.new
16
+ server.register 'node', 1, expected
17
+ server.run
18
+
19
+ locator = Cocaine::Locator.new
20
+ locator.resolve('node').callback { |endpoint, version, api|
21
+ expect(endpoint).to eq(expected[:endpoint])
22
+ expect(version).to eq(expected[:version])
23
+ expect(api).to eq(expected[:api])
24
+ EM.stop()
25
+ }.errback {
26
+ fail('Failed')
27
+ EM.stop()
28
+ }
29
+ end
30
+ end
31
+
32
+ it 'should trigger errorback if locator cannot be reached' do
33
+ EM.run do
34
+ locator = Cocaine::Locator.new
35
+ locator.resolve('node-when-locator-not-reached').callback {
36
+ fail('Failed')
37
+ EM.stop()
38
+ }.errback { |err|
39
+ expect(err).to eq(Cocaine::ConnectionError.new)
40
+ EM.stop()
41
+ }
42
+ end
43
+ end
44
+
45
+ it 'should trigger errorback is service can not be resolved' do
46
+ EM.run do
47
+ server = CocaineRuntimeMock.new
48
+ server.on 'locator', [0, 1, ['node']], [Error.new(1, 'service is not available')]
49
+ server.run
50
+
51
+ locator = Cocaine::Locator.new
52
+ locator.resolve('node').callback {
53
+ fail('Failed')
54
+ EM.stop()
55
+ }.errback { |err|
56
+ expect(err).to be_a(Cocaine::ServiceError)
57
+ EM.stop()
58
+ }
59
+ end
60
+ end
61
+ end
62
+
63
+ describe Cocaine::Service do
64
+ it 'should connect to the provided endpoint' do
65
+ flag = false
66
+ EM.run do
67
+ expected = {endpoint: ['127.0.0.1', 10054], version: 1, api: {0 => 'start_app', 1 => 'pause_app', 2 => 'list'}}
68
+ server = CocaineRuntimeMock.new
69
+ server.register 'node', 1, expected
70
+ server.when('node').connected do
71
+ flag = true
72
+ EM.stop
73
+ end
74
+ server.run
75
+
76
+ node = Cocaine::Service.new 'node'
77
+ node.connect
78
+ end
79
+ expect(flag).to be true
80
+ end
81
+
82
+ it 'should provide methods dynamically' do
83
+ flag = false
84
+ EM.run do
85
+ expected = {endpoint: ['127.0.0.1', 10054], version: 1, api: {0 => 'start_app', 1 => 'pause_app', 2 => 'list'}}
86
+ server = CocaineRuntimeMock.new
87
+ server.register 'node', 1, expected
88
+ server.when('node').message([2, 1, []]) do
89
+ flag = true
90
+ EM.stop
91
+ ['app']
92
+ end
93
+ server.run
94
+
95
+ node = Cocaine::Service.new 'node'
96
+ node.connect.callback {
97
+ node.list
98
+ }.errback { |err|
99
+ fail("Failed: #{err}")
100
+ EM.stop
101
+ }
102
+ end
103
+ expect(flag).to be true
104
+ end
105
+
106
+ it 'should return error if service cannot be reached' do
107
+ EM.synchrony do
108
+ server = CocaineRuntimeMock.new
109
+ server.on 'locator',
110
+ [0, 1, ['node']],
111
+ [[['127.0.0.1', 10054], 1, {0 => 'start_app', 1 => 'pause_app', 2 => 'list'}]]
112
+ server.run
113
+
114
+ node = Cocaine::Service.new 'node'
115
+ node.connect.callback {
116
+ fail('Failed')
117
+ EM.stop
118
+ }.errback { |err|
119
+ expect(err).to be_a(Cocaine::ConnectionError)
120
+ EM.stop
121
+ }
122
+ end
123
+ end
124
+
125
+ it 'should return future with error if service throws error' do
126
+ counter = 0
127
+ EM.synchrony do
128
+ expected = {endpoint: ['127.0.0.1', 10054], version: 1, api: {0 => 'list'}}
129
+ server = CocaineRuntimeMock.new
130
+ server.register 'node', 1, expected
131
+ server.when('node').message([0, 1, []]) do
132
+ [Error.new(1, 'wtf')]
133
+ end
134
+ server.run
135
+
136
+ expected = [Cocaine::ServiceError, ChokeEvent]
137
+ node = Cocaine::Service.new 'node'
138
+ node.connect.callback {
139
+ node.list.callback { |future|
140
+ expect { future.get }.to raise_error expected[counter]
141
+ counter += 1
142
+ EM.stop if counter == 2
143
+ }
144
+ }.errback {
145
+ fail('Failed')
146
+ EM.stop
147
+ }
148
+ end
149
+ expect(counter).to be 2
150
+ end
151
+ end
152
+
153
+ describe Cocaine::Synchrony::Service do
154
+ it 'should synchrony connect to the service' do
155
+ flag = false
156
+ EM.synchrony do
157
+ expected = {endpoint: ['127.0.0.1', 10054], version: 1, api: {}}
158
+ server = CocaineRuntimeMock.new
159
+ server.register 'mock-app', 1, expected
160
+ server.when('mock-app').connected do
161
+ flag = true
162
+ EM.stop
163
+ end
164
+ server.run
165
+
166
+ Cocaine::Synchrony::Service.new 'mock-app'
167
+ end
168
+ expect(flag).to be true
169
+ end
170
+
171
+ it 'should throw error on locator connect failure' do
172
+ EM.synchrony do
173
+ expect { Cocaine::Synchrony::Service.new 'mock-app' }.to raise_error Cocaine::ConnectionError
174
+ EM.stop
175
+ end
176
+ end
177
+
178
+ it 'should throw error on connect failure' do
179
+ EM.synchrony do
180
+ server = CocaineRuntimeMock.new
181
+ server.on 'locator',
182
+ [0, 1, ['mock-app']],
183
+ [[['127.0.0.1', 10054], 1, {0 => 'start_app', 1 => 'pause_app', 2 => 'list'}]]
184
+ server.run
185
+
186
+ expect { Cocaine::Synchrony::Service.new 'mock-app' }.to raise_error Cocaine::ConnectionError
187
+ EM.stop
188
+ end
189
+ end
190
+
191
+ it 'should synchrony read exactly one chunk' do
192
+ EM.synchrony do
193
+ expected = {endpoint: ['127.0.0.1', 10054], version: 1, api: {0 => 'enqueue', 1 => 'info'}}
194
+ server = CocaineRuntimeMock.new
195
+ server.register 'mock-app', 1, expected
196
+ server.when('mock-app').message([0, 1, ['ping', 'message']]) { ['chunk#1'] }
197
+ server.run
198
+
199
+ service = Cocaine::Synchrony::Service.new 'mock-app'
200
+ ch = service.enqueue('ping', 'message')
201
+ msg = ch.read
202
+ expect(msg).to eq('chunk#1')
203
+ EM.stop
204
+ end
205
+ end
206
+
207
+ it 'should synchrony read exactly three chunks' do
208
+ EM.synchrony do
209
+ expected = {endpoint: ['127.0.0.1', 10054], version: 1, api: {0 => 'enqueue', 1 => 'info'}}
210
+ server = CocaineRuntimeMock.new
211
+ server.register 'mock-app', 1, expected
212
+ server.when('mock-app').message([0, 1, ['ping', 'message']]) { ['chunk#1', 'chunk#2', 'chunk#3'] }
213
+ server.run
214
+
215
+ service = Cocaine::Synchrony::Service.new 'mock-app'
216
+ ch = service.enqueue('ping', 'message')
217
+ msg = [nil] * 3
218
+ msg[0] = ch.read
219
+ msg[1] = ch.read
220
+ msg[2] = ch.read
221
+ expect(msg).to eq(['chunk#1', 'chunk#2', 'chunk#3'])
222
+ EM.stop
223
+ end
224
+ end
225
+
226
+ it 'should synchrony partial read chunks via collect' do
227
+ EM.synchrony do
228
+ expected = {endpoint: ['127.0.0.1', 10054], version: 1, api: {0 => 'enqueue', 1 => 'info'}}
229
+ server = CocaineRuntimeMock.new
230
+ server.register 'mock-app', 1, expected
231
+ server.when('mock-app').message([0, 1, ['ping', 'message']]) { ['chunk#1', 'chunk#2', 'chunk#3'] }
232
+ server.run
233
+
234
+ service = Cocaine::Synchrony::Service.new 'mock-app'
235
+ ch = service.enqueue('ping', 'message')
236
+ actual = ch.collect(2)
237
+ expect(actual).to eq(['chunk#1', 'chunk#2'])
238
+ EM.stop
239
+ end
240
+ end
241
+
242
+ it 'should synchrony fully read chunks via collect' do
243
+ EM.synchrony do
244
+ expected = {endpoint: ['127.0.0.1', 10054], version: 1, api: {0 => 'enqueue', 1 => 'info'}}
245
+ server = CocaineRuntimeMock.new
246
+ server.register 'mock-app', 1, expected
247
+ server.when('mock-app').message([0, 1, ['ping', 'message']]) { ['chunk#1', 'chunk#2', 'chunk#3'] }
248
+ server.run
249
+
250
+ service = Cocaine::Synchrony::Service.new 'mock-app'
251
+ ch = service.enqueue('ping', 'message')
252
+ actual = ch.collect(3)
253
+ expect(actual).to eq(['chunk#1', 'chunk#2', 'chunk#3'])
254
+ EM.stop
255
+ end
256
+ end
257
+
258
+ it 'should synchrony read chunks until choke' do
259
+ EM.synchrony do
260
+ expected = {endpoint: ['127.0.0.1', 10054], version: 1, api: {0 => 'enqueue', 1 => 'info'}}
261
+ server = CocaineRuntimeMock.new
262
+ server.register 'mock-app', 1, expected
263
+ server.when('mock-app').message([0, 1, ['ping', 'message']]) { ['chunk#1', 'chunk#2', 'chunk#3'] }
264
+ server.run
265
+
266
+ service = Cocaine::Synchrony::Service.new 'mock-app'
267
+ ch = service.enqueue('ping', 'message')
268
+ actual = ch.collect()
269
+ expect(actual).to eq(['chunk#1', 'chunk#2', 'chunk#3'])
270
+ EM.stop
271
+ end
272
+ end
273
+
274
+ it 'should synchrony iterate chunks with each method' do
275
+ EM.synchrony do
276
+ expected = {endpoint: ['127.0.0.1', 10054], version: 1, api: {0 => 'enqueue', 1 => 'info'}}
277
+ server = CocaineRuntimeMock.new
278
+ server.register 'mock-app', 1, expected
279
+ server.when('mock-app').message([0, 1, ['ping', 'message']]) { ['chunk#1', 'chunk#2', 'chunk#3'] }
280
+ server.run
281
+
282
+ results = []
283
+ service = Cocaine::Synchrony::Service.new 'mock-app'
284
+ ch = service.enqueue('ping', 'message')
285
+ ch.each do |result|
286
+ results.push result
287
+ end
288
+ expect(results).to eq(['chunk#1', 'chunk#2', 'chunk#3'])
289
+ EM.stop
290
+ end
291
+ end
292
+
293
+ it 'should throw error on error received while single fetching' do
294
+ EM.synchrony do
295
+ expected = {endpoint: ['127.0.0.1', 10054], version: 1, api: {0 => 'enqueue', 1 => 'info'}}
296
+ server = CocaineRuntimeMock.new
297
+ server.register 'mock-app', 1, expected
298
+ server.when('mock-app').message([0, 1, ['ping', 'message']]) { [Error.new(1, 'Some error occurred')] }
299
+ server.run
300
+
301
+ service = Cocaine::Synchrony::Service.new 'mock-app'
302
+ ch = service.enqueue('ping', 'message')
303
+ expect { ch.read }.to raise_error Cocaine::ServiceError
304
+ EM.stop
305
+ end
306
+ end
307
+
308
+ it 'should throw error on error received while collect fetching' do
309
+ EM.synchrony do
310
+ expected = {endpoint: ['127.0.0.1', 10054], version: 1, api: {0 => 'enqueue', 1 => 'info'}}
311
+ server = CocaineRuntimeMock.new
312
+ server.register 'mock-app', 1, expected
313
+ server.when('mock-app').message([0, 1, ['ping', 'message']]) { ['chunk#1', Error.new(1, 'Some error occurred')] }
314
+ server.run
315
+
316
+ service = Cocaine::Synchrony::Service.new 'mock-app'
317
+ ch = service.enqueue('ping', 'message')
318
+ expect { ch.collect }.to raise_error Cocaine::ServiceError
319
+ EM.stop
320
+ end
321
+ end
322
+ end