langis 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,301 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ # Just a plain old middleware class for these specs
4
+ class TestMiddleware
5
+ def initialize(app, service, value)
6
+ @app = app
7
+ @service = service
8
+ @value = value
9
+ end
10
+ def call(env)
11
+ @service.my_expected_method(@value)
12
+ @app.call(env)
13
+ end
14
+ end
15
+
16
+ describe 'Langis Dsl Config' do
17
+ it 'should handle an empty dsl block' do
18
+ config = Langis::Dsl.langis_plumbing do
19
+ end
20
+ pipes = config.build_pipes
21
+ pipes.should be_empty
22
+ end
23
+
24
+ it 'should handle raise error on missing sink' do
25
+ begin
26
+ config = Langis::Dsl.langis_plumbing do
27
+ intake :intake_1 do
28
+ flow_to :non_existent_sink
29
+ end
30
+ end
31
+ pipes = config.build_pipes
32
+ fail 'did not raise PipingConfigError'
33
+ rescue Langis::Dsl::PipingConfigError => e
34
+ end
35
+ end
36
+
37
+ it 'should create a single intake with a single app' do
38
+ config = Langis::Dsl.langis_plumbing do
39
+ intake :intake_1 do
40
+ flow_to :sink_1
41
+ end
42
+ for_sink :sink_1 do
43
+ end
44
+ end
45
+ pipes = config.build_pipes
46
+ pipes.size.should eql 1
47
+ pipes['intake_1'].size.should eql 1
48
+ end
49
+
50
+ it 'should create one intake with a three apps' do
51
+ config = Langis::Dsl.langis_plumbing do
52
+ intake :intake_1 do
53
+ flow_to :sink_1
54
+ flow_to :sink_2, :sink_3
55
+ end
56
+ for_sink :sink_1 do
57
+ end
58
+ for_sink :sink_2 do
59
+ end
60
+ for_sink :sink_3 do
61
+ end
62
+ end
63
+ pipes = config.build_pipes
64
+ pipes.size.should eql 1
65
+ pipes['intake_1'].size.should eql 3
66
+ end
67
+
68
+ it 'should create ignore unreferenced sinks, executing proper sink' do
69
+ env = {
70
+ :envkey => 1
71
+ }
72
+
73
+ # Create 3 mocks where 1 is called and the other 2 are uncalled.
74
+ service1= mock 'service1'
75
+ service2 = mock 'service2'
76
+ service2.should_receive(:call).with(env).once
77
+ service3 = mock 'service3'
78
+
79
+ # Now create the config.
80
+ config = Langis::Dsl.langis_plumbing do
81
+ intake :intake_1 do
82
+ flow_to :sink_2
83
+ end
84
+ for_sink :sink_1 do
85
+ run service1
86
+ end
87
+ for_sink :sink_2 do
88
+ run service2
89
+ end
90
+ for_sink :sink_3 do
91
+ run service3
92
+ end
93
+ end
94
+
95
+ # build the pipes and run the test.
96
+ pipes = config.build_pipes
97
+ pipes.size.should eql 1
98
+ pipes['intake_1'].size.should eql 1
99
+ pipes['intake_1'][0].call(env)
100
+ end
101
+
102
+ it 'should create two intakes with a three apps each' do
103
+ config = Langis::Dsl.langis_plumbing do
104
+ intake :intake_1, :intake_2 do
105
+ flow_to :sink_1
106
+ flow_to :sink_2, :sink_3
107
+ end
108
+ for_sink :sink_1 do
109
+ end
110
+ for_sink :sink_2 do
111
+ end
112
+ for_sink :sink_3 do
113
+ end
114
+ end
115
+ pipes = config.build_pipes
116
+ pipes.size.should eql 2
117
+ pipes['intake_1'].size.should eql 3
118
+ pipes['intake_2'].size.should eql 3
119
+ end
120
+
121
+ it 'should have sinks that run middleware in order' do
122
+ env = {}
123
+ first_value = 1
124
+ second_value = 2
125
+ service = mock 'middleware_service'
126
+ service.should_receive(:my_expected_method).once.with(first_value).ordered
127
+ service.should_receive(:my_expected_method).once.with(second_value).ordered
128
+ config = Langis::Dsl.langis_plumbing do
129
+ intake :intake_1 do
130
+ flow_to :sink_1
131
+ end
132
+ for_sink :sink_1 do
133
+ use TestMiddleware, service, first_value
134
+ use TestMiddleware, service, second_value
135
+ end
136
+ end
137
+ pipes = config.build_pipes
138
+ pipes['intake_1'].size.should eql 1
139
+ pipes['intake_1'][0].call(env)
140
+ end
141
+
142
+ it 'should have sinks that run middleware in order, with a final app' do
143
+ env = {}
144
+ first_value = 1
145
+ second_value = 2
146
+ service = mock 'middleware_service'
147
+ service.should_receive(:my_expected_method).once.with(first_value).ordered
148
+ service.should_receive(:my_expected_method).once.with(second_value).ordered
149
+ service.should_receive(:call).once.with(an_instance_of(Hash))
150
+ config = Langis::Dsl.langis_plumbing do
151
+ intake :intake_1 do
152
+ flow_to :sink_1
153
+ end
154
+ for_sink :sink_1 do
155
+ use TestMiddleware, service, first_value
156
+ use TestMiddleware, service, second_value
157
+ run service
158
+ end
159
+ end
160
+ pipes = config.build_pipes
161
+ pipes['intake_1'].size.should eql 1
162
+ pipes['intake_1'][0].call(env)
163
+ end
164
+
165
+ it 'should have separate sinks that run middleware and app in order' do
166
+ env = {}
167
+ first_value = 1
168
+ second_value = 2
169
+ service1 = mock 'middleware_service1'
170
+ service1.should_receive(:my_expected_method).once.with(first_value).ordered
171
+ service1.should_receive(:my_expected_method).once.with(second_value).ordered
172
+ service1.should_receive(:call).once.with(an_instance_of(Hash))
173
+ service2 = mock 'middleware_service2'
174
+ service2.should_receive(:my_expected_method).once.with(first_value).ordered
175
+ service2.should_receive(:my_expected_method).once.with(second_value).ordered
176
+ service2.should_receive(:call).once.with(an_instance_of(Hash))
177
+ config = Langis::Dsl.langis_plumbing do
178
+ intake :intake_1 do
179
+ flow_to :sink_1, :sink_2
180
+ end
181
+ for_sink :sink_1 do
182
+ use TestMiddleware, service1, first_value
183
+ use TestMiddleware, service1, second_value
184
+ run service1
185
+ end
186
+ for_sink :sink_2 do
187
+ use TestMiddleware, service2, first_value
188
+ use TestMiddleware, service2, second_value
189
+ run service2
190
+ end
191
+ end
192
+ pipes = config.build_pipes
193
+ pipes['intake_1'].size.should eql 2
194
+ pipes['intake_1'][0].call(env)
195
+ pipes['intake_1'][1].call(env)
196
+ end
197
+
198
+ it 'should allow message through with a set type' do
199
+ message_type = 'MyMessageType'
200
+ message_type_2 = 'MyMessageType2'
201
+ env = {
202
+ Langis::MESSAGE_TYPE_KEY => message_type
203
+ }
204
+ service = mock 'middleware_service'
205
+ service.should_receive(:call).once.with(
206
+ hash_including(Langis::MESSAGE_TYPE_KEY => message_type))
207
+ config = Langis::Dsl.langis_plumbing do
208
+ intake :intake_1 do
209
+ flow_to :sink_1, :when => message_type
210
+ end
211
+ for_sink :sink_1 do
212
+ run service
213
+ end
214
+ end
215
+ pipes = config.build_pipes
216
+ pipes['intake_1'].size.should eql 1
217
+ pipes['intake_1'][0].call(env)
218
+ end
219
+
220
+ it 'should allow message through a filter looking for a list of types' do
221
+ message_type = 'MyMessageType'
222
+ message_type_2 = 'MyMessageType2'
223
+ env = {
224
+ Langis::MESSAGE_TYPE_KEY => message_type
225
+ }
226
+ service = mock 'middleware_service'
227
+ service.should_receive(:call).once.with(
228
+ hash_including(Langis::MESSAGE_TYPE_KEY => message_type))
229
+ config = Langis::Dsl.langis_plumbing do
230
+ intake :intake_1 do
231
+ flow_to :sink_1, :when => [message_type.to_sym, message_type_2.to_sym]
232
+ end
233
+ for_sink :sink_1 do
234
+ run service
235
+ end
236
+ end
237
+ pipes = config.build_pipes
238
+ pipes['intake_1'].size.should eql 1
239
+ pipes['intake_1'][0].call(env)
240
+ end
241
+
242
+ it 'should filter by message types given by array' do
243
+ message_type = 'MyMessageType'
244
+ message_type_2 = 'MyMessageType2'
245
+ env = {
246
+ Langis::MESSAGE_TYPE_KEY => 'NotTheRightType'
247
+ }
248
+ # Service should receive zero calls.
249
+ service = mock 'middleware_service'
250
+ config = Langis::Dsl.langis_plumbing do
251
+ intake :intake_1 do
252
+ flow_to :sink_1, :when => [message_type.to_sym, message_type_2.to_sym]
253
+ end
254
+ for_sink :sink_1 do
255
+ run service
256
+ end
257
+ end
258
+ pipes = config.build_pipes
259
+ pipes['intake_1'].size.should eql 1
260
+ pipes['intake_1'][0].call(env)
261
+ end
262
+
263
+ it 'should run the check_valve middleware for all routes' do
264
+ value = 'TestMiddlewareValue'
265
+ env = {
266
+ :envkey => 1
267
+ }
268
+ service1= mock 'service1'
269
+ service1.should_receive(:call).with(env).once
270
+ service2 = mock 'service2'
271
+ service2.should_receive(:call).with(env).once
272
+ service3 = mock 'service3'
273
+ service3.should_receive(:call).with(env).once
274
+ check_valve_service = mock 'check_valve'
275
+ check_valve_service.
276
+ should_receive(:my_expected_method).with(value).exactly(3).times
277
+ config = Langis::Dsl.langis_plumbing do
278
+ intake :intake_1 do
279
+ flow_to :sink_1, :sink_2, :sink_3
280
+ end
281
+ for_sink :sink_1 do
282
+ run service1
283
+ end
284
+ for_sink :sink_2 do
285
+ run service2
286
+ end
287
+ for_sink :sink_3 do
288
+ run service3
289
+ end
290
+ check_valve do
291
+ use TestMiddleware, check_valve_service, value
292
+ end
293
+ end
294
+ pipes = config.build_pipes
295
+ pipes.size.should eql 1
296
+ pipes['intake_1'].size.should eql 3
297
+ pipes['intake_1'].each do |sink|
298
+ sink.call(env)
299
+ end
300
+ end
301
+ end
@@ -0,0 +1,168 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ # We want an ipmlementation of EventMachine::Channel without EventMachine
4
+ # to run inside these tests.
5
+ class NonEvmChannel
6
+ def initialize
7
+ @list = []
8
+ end
9
+
10
+ def subscribe(*args, &block)
11
+ @list << args[0]
12
+ end
13
+
14
+ def push(*args)
15
+ @list.each do |subscriber|
16
+ subscriber.call *args
17
+ end
18
+ end
19
+ end
20
+
21
+ # We need EventMachine defer without EventMachine.
22
+ class EventMachineStub
23
+ def self.defer(op = nil, callback = nil)
24
+ if callback
25
+ callback.call(op.call)
26
+ else
27
+ op.call
28
+ end
29
+ end
30
+ end
31
+
32
+ describe 'EventMachineEngine' do
33
+ it 'should pump a message to one intake' do
34
+ my_message = 'pingy pong'
35
+ env = {
36
+ Langis::MESSAGE_KEY => my_message,
37
+ Langis::INTAKE_KEY => 'intake_1'
38
+ }
39
+ service = mock 'service'
40
+ service.should_receive(:call).with(env).once
41
+ config = Langis::Dsl.langis_plumbing do
42
+ intake :intake_1, :intake_2 do
43
+ flow_to :sink_1
44
+ end
45
+ for_sink :sink_1 do
46
+ run service
47
+ end
48
+ end
49
+ engine = Langis::Engine::EventMachineEngine.new(config.build_pipes,
50
+ :evm => EventMachineStub,
51
+ :evm_channel => NonEvmChannel)
52
+ engine.pump my_message, :intake_1
53
+ end
54
+
55
+ it 'should pump a message to multiple intakes' do
56
+ my_message = 'pingy pong'
57
+ env1 = {
58
+ Langis::MESSAGE_KEY => my_message,
59
+ Langis::INTAKE_KEY => 'intake_1'
60
+ }
61
+ env2 = {
62
+ Langis::MESSAGE_KEY => my_message,
63
+ Langis::INTAKE_KEY => 'intake_2'
64
+ }
65
+ service = mock 'service'
66
+ service.should_receive(:call).with(env1).once
67
+ service.should_receive(:call).with(env2).once
68
+ config = Langis::Dsl.langis_plumbing do
69
+ intake :intake_1, :intake_2 do
70
+ flow_to :sink_1
71
+ end
72
+ for_sink :sink_1 do
73
+ run service
74
+ end
75
+ end
76
+ engine = Langis::Engine::EventMachineEngine.new(config.build_pipes,
77
+ :evm => EventMachineStub,
78
+ :evm_channel => NonEvmChannel)
79
+ engine.pump my_message, :intake_1, :intake_2
80
+ end
81
+
82
+ it 'should handle success callbacks' do
83
+ my_message = 'pingy pong'
84
+ return_message = [200, {}, ['']]
85
+ env = {
86
+ Langis::MESSAGE_KEY => my_message,
87
+ Langis::INTAKE_KEY => 'intake_1'
88
+ }
89
+ service = mock 'service'
90
+ service.should_receive(:call).with(env).once.and_return(return_message)
91
+ success_channel = mock 'success channel'
92
+ success_channel.should_receive(:push).with(return_message).once
93
+ config = Langis::Dsl.langis_plumbing do
94
+ intake :intake_1, :intake_2 do
95
+ flow_to :sink_1
96
+ end
97
+ for_sink :sink_1 do
98
+ run service
99
+ end
100
+ end
101
+ engine = Langis::Engine::EventMachineEngine.new(config.build_pipes,
102
+ :evm => EventMachineStub,
103
+ :evm_channel => NonEvmChannel,
104
+ :success_channel => success_channel)
105
+ engine.pump my_message, :intake_1
106
+ end
107
+
108
+ it 'should handle error callback' do
109
+ my_message = 'pingy pong'
110
+ my_error = RuntimeError.new
111
+ env = {
112
+ Langis::MESSAGE_KEY => my_message,
113
+ Langis::INTAKE_KEY => 'intake_1'
114
+ }
115
+ error_result = [
116
+ Langis::SERVER_ERROR,
117
+ {
118
+ Langis::MESSAGE_KEY => my_message,
119
+ Langis::INTAKE_KEY => 'intake_1',
120
+ Langis::X_EXCEPTION => my_error
121
+ },
122
+ ['']
123
+ ]
124
+ service = mock 'service'
125
+ service.should_receive(:call).with(env).once.and_raise(my_error)
126
+ error_channel = mock 'error channel'
127
+ error_channel.should_receive(:push).with(error_result).once
128
+ config = Langis::Dsl.langis_plumbing do
129
+ intake :intake_1, :intake_2 do
130
+ flow_to :sink_1
131
+ end
132
+ for_sink :sink_1 do
133
+ run service
134
+ end
135
+ end
136
+ engine = Langis::Engine::EventMachineEngine.new(config.build_pipes,
137
+ :evm => EventMachineStub,
138
+ :evm_channel => NonEvmChannel,
139
+ :error_channel => error_channel)
140
+ engine.pump my_message, :intake_1
141
+ end
142
+
143
+ it 'should set the MESSAGE_TYPE field if the message responds to :message_type' do
144
+ my_type = 'MyMessageType'
145
+ my_message = mock 'message'
146
+ my_message.should_receive(:respond_to?).with(:message_type).once.and_return true
147
+ my_message.should_receive(:message_type).once.and_return(my_type)
148
+ env = {
149
+ Langis::MESSAGE_TYPE_KEY => my_type,
150
+ Langis::MESSAGE_KEY => my_message,
151
+ Langis::INTAKE_KEY => 'intake_1'
152
+ }
153
+ service = mock 'service'
154
+ service.should_receive(:call).with(env)
155
+ config = Langis::Dsl.langis_plumbing do
156
+ intake :intake_1, :intake_2 do
157
+ flow_to :sink_1
158
+ end
159
+ for_sink :sink_1 do
160
+ run service
161
+ end
162
+ end
163
+ engine = Langis::Engine::EventMachineEngine.new(config.build_pipes,
164
+ :evm => EventMachineStub,
165
+ :evm_channel => NonEvmChannel)
166
+ engine.pump my_message, :intake_1
167
+ end
168
+ end