gilmour 0.3.4 → 0.4.1

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,207 @@
1
+ require 'rspec/given'
2
+
3
+ require_relative '../../lib/gilmour'
4
+ require_relative 'helpers/common'
5
+
6
+ class Server
7
+ include Gilmour::Base
8
+ end
9
+
10
+ describe 'Pipelines' do
11
+ after(:all) do
12
+ EM.stop
13
+ end
14
+ Given(:gilmour) {
15
+ Server.new.enable_backend('redis')
16
+ }
17
+ When {
18
+ gilmour.reply_to 'one' do
19
+ respond request.body.merge({'one' => 'foo'})
20
+ end
21
+ }
22
+ When {
23
+ gilmour.reply_to 'two' do
24
+ respond request.body.merge({'two' => 'foo'})
25
+ end
26
+ }
27
+ When {
28
+ gilmour.reply_to 'badtwo' do
29
+ respond request.body.merge({'badtwo' => 'foo'}), 500
30
+ end
31
+ }
32
+ When {
33
+ gilmour.reply_to 'three' do
34
+ respond request.body.merge({'three' => 'foo'})
35
+ end
36
+ }
37
+ When {
38
+ # Make sure all subscribers are active
39
+ sleep 1
40
+ }
41
+ context 'Compose' do
42
+ Given(:composed) {
43
+ gilmour.compose([{topic: 'one'}, {topic: 'two'},
44
+ {topic: 'three', message: {'anotherthree' => 'anotherthree'}}])
45
+ }
46
+ Then {
47
+ waiter = Waiter.new
48
+ code = data = nil
49
+ composed.execute({zero: 'foo'}) do |d, c|
50
+ data = d
51
+ code = c
52
+ waiter.signal
53
+ end
54
+ waiter.wait
55
+ ['zero', 'one', 'two', 'three', 'anotherthree'].each do |k|
56
+ expect(data.has_key?(k)).to be_truthy
57
+ end
58
+ expect(code).to eq(200)
59
+ }
60
+ end
61
+
62
+ context 'AndAnd' do
63
+ context 'All successful' do
64
+ Given(:andand) {
65
+ gilmour.andand([{topic: 'one'}, {topic: 'two'},
66
+ {topic: 'three', message: {'anotherthree' => 'anotherthree'}}])
67
+ }
68
+ Then {
69
+ waiter = Waiter.new
70
+ code = data = nil
71
+ andand.execute do |d, c|
72
+ data = d
73
+ code = c
74
+ waiter.signal
75
+ end
76
+ waiter.wait
77
+ expect(data.keys.size).to eq(2)
78
+ ['three', 'anotherthree'].each do |k|
79
+ expect(data.has_key?(k)).to be_truthy
80
+ end
81
+ expect(code).to eq(200)
82
+ }
83
+ end
84
+
85
+ context 'Interrupted' do
86
+ Given(:interupted) {
87
+ gilmour.andand([{topic: 'one'}, {topic: 'badtwo'},
88
+ {topic: 'three', message: {'anotherthree' => 'anotherthree'}}])
89
+ }
90
+ Given(:firsttry) {
91
+ waiter = Waiter.new
92
+ cont = code = data = nil
93
+ interupted.execute do |d, c, continuation|
94
+ data = d
95
+ code = c
96
+ cont = continuation
97
+ waiter.signal
98
+ end
99
+ waiter.wait
100
+ {code: code, data: data, continuation: cont}
101
+ }
102
+ Given(:secondtry) {
103
+ waiter = Waiter.new
104
+ code = data = nil
105
+ firsttry[:continuation].execute do |d, c|
106
+ data = d
107
+ code = c
108
+ waiter.signal
109
+ end
110
+ waiter.wait
111
+ {code: code, data: data}
112
+ }
113
+ Then {
114
+ data = firsttry[:data]
115
+ code = firsttry[:code]
116
+ expect(data.keys.size).to eq(1)
117
+ ['badtwo'].each do |k|
118
+ expect(data.has_key?(k)).to be_truthy
119
+ end
120
+ expect(code).to eq(500)
121
+ }
122
+ And {
123
+ data = secondtry[:data]
124
+ code = secondtry[:code]
125
+ expect(data.keys.size).to eq(2)
126
+ ['three', 'anotherthree'].each do |k|
127
+ expect(data.has_key?(k)).to be_truthy
128
+ end
129
+ expect(code).to eq(200)
130
+ }
131
+ end
132
+ end
133
+
134
+ context 'Batch' do
135
+ context 'Without record' do
136
+ Given(:batch) {
137
+ gilmour.batch([{topic: 'one'}, {topic: 'badtwo'},
138
+ {topic: 'three', message: {'anotherthree' => 'anotherthree'}}])
139
+ }
140
+ Then {
141
+ waiter = Waiter.new
142
+ code = data = nil
143
+ batch.execute do |d, c|
144
+ data = d
145
+ code = c
146
+ waiter.signal
147
+ end
148
+ waiter.wait
149
+ expect(data).to be_kind_of(Hash)
150
+ expect(data.keys.size).to eq(2)
151
+ ['three', 'anotherthree'].each do |k|
152
+ expect(data.has_key?(k)).to be_truthy
153
+ end
154
+ expect(code).to eq(200)
155
+ }
156
+ end
157
+
158
+ context 'With record' do
159
+ Given(:batchrecord) {
160
+ gilmour.batch([{topic: 'one'}, {topic: 'badtwo'},
161
+ {topic: 'three', message: {'anotherthree' => 'anotherthree'}}],
162
+ true)
163
+ }
164
+ Then {
165
+ waiter = Waiter.new
166
+ code = data = nil
167
+ batchrecord.execute do |d, c|
168
+ data = d
169
+ code = c
170
+ waiter.signal
171
+ end
172
+ waiter.wait
173
+ expect(data).to be_kind_of(Array)
174
+ expect(data.size).to eq(3)
175
+ %w{one badtwo three anotherthree}.each do |k|
176
+ expect(data.find {|o| o[:data].has_key?(k)}).not_to be_nil
177
+ end
178
+ }
179
+ end
180
+ end
181
+ context 'Combinations' do
182
+ context 'Andand and compose' do
183
+ Given(:andand) {
184
+ gilmour.andand([{topic: 'one'}, {topic: 'two'}])
185
+ }
186
+ Given(:compose) {
187
+ gilmour.compose([andand, {topic: 'three'}])
188
+ }
189
+ Then {
190
+ waiter = Waiter.new
191
+ code = data = nil
192
+ compose.execute do |d, c|
193
+ data = d
194
+ code = c
195
+ waiter.signal
196
+ end
197
+ waiter.wait
198
+ expect(data.keys.size).to eq(2)
199
+ ['two', 'three'].each do |k|
200
+ expect(data.has_key?(k)).to be_truthy
201
+ end
202
+ expect(code).to eq(200)
203
+ }
204
+ end
205
+ end
206
+ end
207
+
@@ -264,7 +264,7 @@ describe 'TestSubscriber' do
264
264
 
265
265
  end
266
266
 
267
- context 'Send and receive a message' do
267
+ context 'Send and receive a message', :debug do
268
268
  Given(:ping_opts) { redis_ping_options }
269
269
  When(:sub) do
270
270
  Gilmour::RedisBackend.new({})
@@ -206,7 +206,7 @@ describe 'TestSubscriberFork' do
206
206
  end
207
207
  end
208
208
 
209
- context 'Send and receive a message' do
209
+ context 'Send and receive a message', :debug do
210
210
  Given(:ping_opts) { redis_ping_options }
211
211
  When(:sub) do
212
212
  Gilmour::RedisBackend.new({})
@@ -375,7 +375,6 @@ describe 'TestSubscriberFork' do
375
375
 
376
376
  Thread.new{
377
377
  loop {
378
- $stderr.puts "Checking values"
379
378
  sub.publisher.lpop(error_key) do |val|
380
379
  if val.is_a? String
381
380
  code = 500
@@ -0,0 +1,303 @@
1
+ # encoding: utf-8
2
+ require 'rspec/given'
3
+ require 'securerandom'
4
+ require './testservice/test_service_base'
5
+
6
+ require_relative 'helpers/common'
7
+ require_relative 'helpers/connection'
8
+
9
+ def install_test_subscriber
10
+ waiter = Waiter.new
11
+ TestReplier.callback do |topic, data|
12
+ @topic = topic
13
+ @data = data
14
+ $stderr.puts "Got callback #{topic}, #{data}"
15
+ waiter.signal
16
+ end
17
+ waiter
18
+ end
19
+
20
+ describe 'TestReplier' do
21
+ opts = redis_connection_options
22
+ opts[:health_check] = true
23
+
24
+ test_subscriber_path = './testservice/subscribers/test_reply'
25
+ after(:all) do
26
+ EM.stop
27
+ end
28
+ Given(:subscriber) { TestServiceBase }
29
+ Given do
30
+ subscriber.load_subscriber(test_subscriber_path)
31
+ end
32
+ Then do
33
+ handlers = subscriber.subscribers(TestReplier::Topic)
34
+ module_present = handlers.find { |h| h[:subscriber] == TestReplier }
35
+ module_present.should be_truthy
36
+ end
37
+
38
+ context 'Running Service' do
39
+ before(:all) do
40
+ @service = TestServiceBase.new(opts, 'redis')
41
+ end
42
+ Given(:connection_opts) { opts }
43
+ before(:all) do
44
+ @service.registered_subscribers.each do |s|
45
+ s.backend = 'redis'
46
+ end
47
+ @service.start
48
+ end
49
+
50
+ context 'Handler Register' do
51
+ When { install_test_subscriber }
52
+ context 'Check registered handlers' do
53
+ When(:handlers) do
54
+ subscriber.subscribers(TestReplier::Simulation)
55
+ .map { |h| h[:handler] }
56
+ end
57
+ Then { handlers.each { |h| h.should be_kind_of Proc } }
58
+ Then do
59
+ arg1 = TestReplier::Simulation
60
+ handlers.each do |h|
61
+ arg2 = SecureRandom.hex
62
+ # simualate a handler call
63
+ h.call(arg1, arg2)
64
+ @topic.should be == arg1
65
+ @data.should be == arg2
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ context 'Receive messages' do
72
+ context 'Receive a message' do
73
+ Given(:ping_opts) { redis_ping_options }
74
+ When do
75
+ @data = @topic = nil
76
+ waiter = install_test_subscriber
77
+ g = Gilmour::RedisBackend.new({})
78
+ g.request!(ping_opts[:message], TestReplier::Topic)
79
+ waiter.wait(5)
80
+ end
81
+ Then do
82
+ @data.should be == ping_opts[:message]
83
+ @topic.should be == "gilmour.request.#{TestReplier::Topic}"
84
+ end
85
+ And { expect(EM.reactor_thread.alive?).to be_truthy }
86
+ end
87
+ end
88
+
89
+ context 'Non Fork can add dynamic listeners', :fork_dynamic do
90
+ Given(:ping_opts) do
91
+ redis_ping_options
92
+ end
93
+
94
+ When(:sub) do
95
+ Gilmour::RedisBackend.new({})
96
+ end
97
+ When(:code) do
98
+ waiter = Waiter.new
99
+ dynamicaly_subscribed = 0
100
+
101
+ sub.request!(1, TestReplier::ReListenTopic) do |d, c|
102
+ sub.confirm_subscriber(sub.request_destination("test.world")) do |present|
103
+ dynamicaly_subscribed = present
104
+ waiter.signal
105
+ end
106
+ end
107
+
108
+ waiter.wait(5)
109
+ dynamicaly_subscribed
110
+ end
111
+ Then do
112
+ code.should be == true
113
+ end
114
+ end
115
+
116
+ context 'Publisher side timeout' do
117
+ Given(:ping_opts) do
118
+ redis_ping_options
119
+ end
120
+
121
+ When(:sub) do
122
+ Gilmour::RedisBackend.new({})
123
+ end
124
+ When(:code) do
125
+ code = nil
126
+ waiter_code = Waiter.new
127
+
128
+ sub.request!(3, TestReplier::TimeoutTopic, {:timeout => 1}) do |d, c|
129
+ code = c
130
+ waiter_code.signal
131
+ end
132
+
133
+ waiter_code.wait(5)
134
+ code
135
+ end
136
+ Then do
137
+ code.should be == 499
138
+ end
139
+ end
140
+
141
+ context 'Handler sleeps longer than the Timeout' do
142
+ Given(:ping_opts) do
143
+ redis_ping_options
144
+ end
145
+
146
+ When(:sub) do
147
+ Gilmour::RedisBackend.new({})
148
+ end
149
+ When(:code) do
150
+ waiter_error = Waiter.new
151
+ waiter_code = Waiter.new
152
+ code = nil
153
+
154
+ backend = @service.get_backend("redis")
155
+ backend.broadcast_errors = true
156
+ sub.slot Gilmour::ErrorChannel do
157
+ waiter_error.signal
158
+ end
159
+
160
+ sub.request!(3, TestReplier::TimeoutTopic) do |d, c|
161
+ code = c
162
+ waiter_code.signal
163
+ end
164
+
165
+ waiter_code.wait(5)
166
+ waiter_error.wait(5)
167
+
168
+ backend.broadcast_errors = false
169
+ code
170
+ end
171
+ Then do
172
+ code.should be == 504
173
+ end
174
+ end
175
+
176
+ context 'Handler sleeps just enough to survive the timeout' do
177
+ Given(:ping_opts) do
178
+ redis_ping_options
179
+ end
180
+
181
+ When(:sub) do
182
+ Gilmour::RedisBackend.new({})
183
+ end
184
+ When(:code) do
185
+ waiter = Waiter.new
186
+ code = nil
187
+
188
+ sub.request!(1, TestReplier::TimeoutTopic) do |d, c|
189
+ code = c
190
+ waiter.signal
191
+ end
192
+
193
+ waiter.wait(5)
194
+ code
195
+ end
196
+ Then do
197
+ code.should be == 200
198
+ end
199
+ end
200
+
201
+
202
+ context 'Request! sans subscriber error' do
203
+ Given(:ping_opts) do
204
+ redis_ping_options
205
+ end
206
+
207
+ When(:sub) do
208
+ Gilmour::RedisBackend.new({})
209
+ end
210
+ When(:response) do
211
+ waiter = Waiter.new
212
+ data = code = nil
213
+ sub.request!(ping_opts[:message], "hello.world") do |d, c|
214
+ data = d
215
+ code = c
216
+ waiter.signal
217
+ end
218
+ waiter.wait(5)
219
+ [data, code]
220
+ end
221
+ Then do
222
+ data, code = response
223
+ data.should be == nil
224
+ code.should be == 404
225
+ end
226
+
227
+ end
228
+
229
+ context 'Send and receive a message' do
230
+ Given(:ping_opts) { redis_ping_options }
231
+ When(:sub) do
232
+ Gilmour::RedisBackend.new({})
233
+ end
234
+ When(:response) do
235
+ waiter = Waiter.new
236
+ data = code = nil
237
+ sub.request!(ping_opts[:message], TestReplier::Topic) do |d, c|
238
+ data = d
239
+ code = c
240
+ waiter.signal
241
+ end
242
+ waiter.wait(5)
243
+ [data, code]
244
+ end
245
+ Then do
246
+ data, code = response
247
+ data.should be == ping_opts[:response]
248
+ code.should be == 200
249
+ end
250
+ end
251
+
252
+ context 'Send once, Receive twice' do
253
+ Given(:ping_opts) { redis_ping_options }
254
+ When(:sub) do
255
+ Gilmour::RedisBackend.new({})
256
+ end
257
+ When (:response) do
258
+ waiter = Waiter.new
259
+
260
+ actual_ret = []
261
+
262
+ group_proc = sub.slot TestReplier::GroupReturn do
263
+ actual_ret.push(request.body)
264
+ waiter.signal if actual_ret.length == 4
265
+ end
266
+
267
+ sub.signal!(ping_opts[:message], TestReplier::GroupTopic)
268
+ waiter.wait(5)
269
+
270
+ sub.remove_slot TestReplier::GroupReturn, group_proc
271
+ actual_ret
272
+ end
273
+ Then do
274
+ response.select { |e| e == ping_opts[:message] }.size.should == 2
275
+ response.select { |e| e == "2" }.size.should == 2
276
+ end
277
+ end
278
+
279
+ context 'Send message from subscriber' do
280
+ Given(:ping_opts) { redis_ping_options }
281
+ When(:sub) do
282
+ Gilmour::RedisBackend.new({})
283
+ end
284
+ When (:response) do
285
+ data = code = nil
286
+ waiter = Waiter.new
287
+ sub.request!(ping_opts[:message], TestReplier::Republish) do |d, c|
288
+ data = d
289
+ code = c
290
+ waiter.signal
291
+ end
292
+ waiter.wait(5)
293
+ [data, code]
294
+ end
295
+ Then do
296
+ data, code = response
297
+ data.should be == ping_opts[:response]
298
+ code.should be == 200
299
+ end
300
+ And { expect(EM.reactor_thread.alive?).to be_truthy }
301
+ end
302
+ end
303
+ end