langis 0.1.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,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