lsqs 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,346 @@
1
+ require 'spec_helper'
2
+ require 'aws-sdk'
3
+
4
+ describe 'Testing actions against the aws-sdk' do
5
+ before do
6
+ base_url = 'www.example.com'
7
+ port = 8080
8
+ @url = "http://#{base_url}:#{port}"
9
+ Aws.config.update(:endpoint => @url)
10
+ @client = Aws::SQS::Client.new
11
+ end
12
+
13
+ after do
14
+ list = @client.list_queues
15
+ list.queue_urls.each do |queue|
16
+ @client.delete_queue(:queue_url => queue)
17
+ end
18
+ end
19
+
20
+ describe '#create_queue'
21
+ it 'creates a queue if it does not exist' do
22
+ response = @client.create_queue(:queue_name => 'foo_queue')
23
+
24
+ response.queue_url.should == "#{@url}/foo_queue"
25
+
26
+ response.data.kind_of?(Aws::SQS::Types::CreateQueueResult).should be_truthy
27
+ end
28
+
29
+ it 'throws an error if queue exists' do
30
+ @client.create_queue(:queue_name => 'bar_queue')
31
+
32
+ expect{
33
+ @client.create_queue(:queue_name => 'bar_queue')
34
+ }.to raise_error(Aws::SQS::Errors::Error400, 'QueueNameExists')
35
+ end
36
+
37
+ describe '#delete_queue' do
38
+ it 'deletes a queue if it exists' do
39
+ queue = @client.create_queue(:queue_name => 'bar')
40
+
41
+ response = @client.delete_queue(:queue_url => queue.queue_url)
42
+
43
+ response.data.kind_of?(Aws::EmptyStructure).should be_truthy
44
+ end
45
+
46
+ it 'throws an error if queue does not exist' do
47
+
48
+ expect{
49
+ @client.delete_queue(:queue_url => "#{@url}/no_queue")
50
+ }.to raise_error(Aws::SQS::Errors::Error400, 'NonExistentQueue')
51
+ end
52
+ end
53
+
54
+ describe '#purge_queue' do
55
+ it 'purges a queue if it exists' do
56
+ queue = @client.create_queue(:queue_name => 'another_queue')
57
+
58
+ response = @client.purge_queue(:queue_url => queue.queue_url)
59
+
60
+ response.data.kind_of?(Aws::EmptyStructure).should be_truthy
61
+ end
62
+
63
+ it 'throws an error if queue does not exist' do
64
+ expect{
65
+ @client.delete_queue(:queue_url => "#{@url}/not_there")
66
+ }.to raise_error(Aws::SQS::Errors::Error400, 'NonExistentQueue')
67
+ end
68
+ end
69
+
70
+ describe '#get_queue_url' do
71
+ it 'purges a queue if it exists' do
72
+ queue = @client.create_queue(:queue_name => 'this_queue')
73
+
74
+ response = @client.get_queue_url(:queue_name => 'this_queue')
75
+ response.data.kind_of?(Aws::SQS::Types::GetQueueUrlResult).should be_truthy
76
+ end
77
+
78
+ it 'throws an error if queue does not exist' do
79
+ expect{
80
+ @client.get_queue_url(:queue_name => 'foo_bar')
81
+ }.to raise_error(Aws::SQS::Errors::Error400, 'NonExistentQueue')
82
+ end
83
+ end
84
+
85
+ describe '#list_queues' do
86
+ it 'returns an empty array if there are no queues' do
87
+ list = @client.list_queues
88
+
89
+ list.queue_urls.empty?.should be_truthy
90
+ end
91
+
92
+ it 'returns an array with the queue urls' do
93
+ queue = @client.create_queue(:queue_name => 'great_queue')
94
+ list = @client.list_queues
95
+
96
+ list.queue_urls.size.should eql(1)
97
+ list.queue_urls.first.should == queue.queue_url
98
+ end
99
+
100
+ it 'searches for a url based on a prefix' do
101
+ @client.create_queue(:queue_name => 'bad_queue')
102
+ nice = @client.create_queue(:queue_name => 'nice_queue')
103
+ list = @client.list_queues(:queue_name_prefix => 'nice')
104
+
105
+ list.queue_urls.size.should eql(1)
106
+ list.queue_urls.first.should == nice.queue_url
107
+ end
108
+ end
109
+
110
+ describe '#send_message' do
111
+ it 'throws an error if queue does not exist' do
112
+ entry = {:foo => 'bar'}
113
+ queue_url = "#{@url}/test"
114
+ expect{
115
+ @client.send_message(
116
+ :queue_url => queue_url,
117
+ :message_body => entry.to_json
118
+ )
119
+ }.to raise_error(Aws::SQS::Errors::Error400, 'NonExistentQueue')
120
+ end
121
+
122
+ it 'returns message on success' do
123
+ entry = {:foo => 'bar'}
124
+ queue = @client.create_queue(:queue_name => 'test')
125
+ queue_url = queue.queue_url
126
+ response = @client.send_message(
127
+ :queue_url => queue_url,
128
+ :message_body => entry.to_json
129
+ )
130
+
131
+ response.message_id.kind_of?(String).should be_truthy
132
+ response.md5_of_message_body.kind_of?(String).should be_truthy
133
+ response.data.kind_of?(Aws::SQS::Types::SendMessageResult).should be_truthy
134
+ end
135
+ end
136
+
137
+ describe '#send_message_batch' do
138
+ before do
139
+ @entries = [
140
+ {
141
+ :message_body => 'foo and bar',
142
+ :id => 'foo_bar'
143
+ },
144
+ {
145
+ :message_body => 'hey hello',
146
+ :id => 'hey_hello'
147
+ }
148
+ ]
149
+ end
150
+
151
+ it 'throws an error if queue does not exist' do
152
+ queue_url = "#{@url}/test"
153
+ expect{
154
+ @client.send_message_batch(
155
+ :queue_url => queue_url,
156
+ :entries => @entries
157
+ )
158
+ }.to raise_error(Aws::SQS::Errors::Error400, 'NonExistentQueue')
159
+ end
160
+
161
+ it 'returns messages on success' do
162
+ queue = @client.create_queue(:queue_name => 'test')
163
+ queue_url = queue.queue_url
164
+ response = @client.send_message_batch(
165
+ :queue_url => queue_url,
166
+ :entries => @entries
167
+ )
168
+
169
+ response.successful.size.should == 2
170
+ response.data.kind_of?(Aws::SQS::Types::SendMessageBatchResult).should be_truthy
171
+ end
172
+ end
173
+
174
+ describe '#receive_message' do
175
+ before do
176
+ @entries = [
177
+ {
178
+ :message_body => 'foo and bar',
179
+ :id => 'foo_bar'
180
+ },
181
+ {
182
+ :message_body => 'hey hello',
183
+ :id => 'hey_hello'
184
+ }
185
+ ]
186
+ end
187
+
188
+ it 'throws an error if queue does not exist' do
189
+ queue_url = "#{@url}/test"
190
+ expect{
191
+ @client.receive_message(:queue_url => queue_url)
192
+ }.to raise_error(Aws::SQS::Errors::Error400, 'NonExistentQueue')
193
+ end
194
+
195
+ it 'receives an empty response if there are no messages' do
196
+ queue = @client.create_queue(:queue_name => 'receive_test')
197
+ queue_url = queue.queue_url
198
+ response = @client.receive_message(:queue_url => queue_url)
199
+
200
+ response.messages.size.should == 0
201
+ end
202
+
203
+ it 'receives a message if there are messages in the queue' do
204
+ queue = @client.create_queue(:queue_name => 'receive_test')
205
+ queue_url = queue.queue_url
206
+ @client.send_message_batch(:queue_url => queue_url, :entries => @entries)
207
+ response = @client.receive_message(:queue_url => queue_url)
208
+
209
+ response.messages.size.should == 1
210
+ response.data.class.kind_of?(Aws::SQS::Types::ReceiveMessageResult)
211
+ end
212
+
213
+ it 'receives more message if maximum number of messages is set' do
214
+ queue = @client.create_queue(:queue_name => 'receive_test')
215
+ queue_url = queue.queue_url
216
+ @client.send_message_batch(:queue_url => queue_url, :entries => @entries)
217
+
218
+ response = @client.receive_message(:queue_url => queue_url, :max_number_of_messages => 5)
219
+
220
+ response.messages.size.should == 2
221
+ response.data.class.kind_of?(Aws::SQS::Types::ReceiveMessageResult)
222
+ end
223
+ end
224
+
225
+ describe '#delete_message' do
226
+ it 'throws an error if queue does not exist' do
227
+ queue_url = "#{@url}/test"
228
+ expect{
229
+ @client.delete_message(:queue_url => queue_url, :receipt_handle => 'test')
230
+ }.to raise_error(Aws::SQS::Errors::Error400, 'NonExistentQueue')
231
+ end
232
+
233
+ it 'throws message not in flight error after deleting successfully' do
234
+ queue = @client.create_queue(:queue_name => 'delete_test')
235
+ entry = {:foo => 'bar'}
236
+ queue_url = queue.queue_url
237
+ @client.send_message(:queue_url => queue_url, :message_body => entry.to_json)
238
+
239
+ response = @client.receive_message(:queue_url => queue_url)
240
+
241
+ @client.delete_message(:queue_url => queue_url, :receipt_handle => response.messages.first.receipt_handle)
242
+
243
+ expect{
244
+ @client.change_message_visibility(
245
+ :queue_url => queue_url,
246
+ :receipt_handle => response.messages.first.receipt_handle,
247
+ :visibility_timeout => 0
248
+ )
249
+ }.to raise_error(Aws::SQS::Errors::Error400, 'MessageNotInflight')
250
+ end
251
+ end
252
+
253
+ describe '#delete_message_batch' do
254
+ it 'throws an error if queue does not exist' do
255
+ entries = [
256
+ {
257
+ :receipt_handle => 'foo',
258
+ :id => 'test1'
259
+ },
260
+ {
261
+ :receipt_handle => 'bar',
262
+ :id => 'test2'
263
+ }
264
+ ]
265
+ queue_url = "#{@url}/test"
266
+ expect{
267
+ @client.delete_message_batch(:queue_url => queue_url, :entries => entries)
268
+ }.to raise_error(Aws::SQS::Errors::Error400, 'NonExistentQueue')
269
+ end
270
+
271
+ it 'throws message not in flight error after deleting successfully' do
272
+ queue = @client.create_queue(:queue_name => 'delete_batch_test')
273
+ entry1 = {:foo => 'bar'}
274
+ entry2 = {:hey => 'hello'}
275
+ queue_url = queue.queue_url
276
+
277
+ @client.send_message(:queue_url => queue_url, :message_body => entry1.to_json)
278
+ @client.send_message(:queue_url => queue_url, :message_body => entry2.to_json)
279
+
280
+ response = @client.receive_message(:queue_url => queue_url, :max_number_of_messages => 2)
281
+
282
+ entries = response.messages.map do |m|
283
+ {:receipt_handle => m.receipt_handle, :id => m.message_id}
284
+ end
285
+
286
+ @client.delete_message_batch(:queue_url => queue_url, :entries => entries)
287
+
288
+ expect{
289
+ @client.change_message_visibility(
290
+ :queue_url => queue_url,
291
+ :receipt_handle => response.messages.first.receipt_handle,
292
+ :visibility_timeout => 0
293
+ )
294
+ }.to raise_error(Aws::SQS::Errors::Error400, 'MessageNotInflight')
295
+
296
+ expect{
297
+ @client.change_message_visibility(
298
+ :queue_url => queue_url,
299
+ :receipt_handle => response.messages.last.receipt_handle,
300
+ :visibility_timeout => 0
301
+ )
302
+ }.to raise_error(Aws::SQS::Errors::Error400, 'MessageNotInflight')
303
+ end
304
+ end
305
+
306
+ describe '#change_message_visibility' do
307
+ it 'throws an error if queue does not exist' do
308
+ queue_url = "#{@url}/test"
309
+ expect{
310
+ @client.change_message_visibility(
311
+ :queue_url => queue_url,
312
+ :receipt_handle => 'test',
313
+ :visibility_timeout => 0
314
+ )
315
+ }.to raise_error(Aws::SQS::Errors::Error400, 'NonExistentQueue')
316
+ end
317
+
318
+ it 'puts a message back in the queue when visibility is 0' do
319
+ queue = @client.create_queue(:queue_name => 'visibility_test')
320
+ entry = {:foo => 'bar'}
321
+ queue_url = queue.queue_url
322
+ @client.send_message(:queue_url => queue_url, :message_body => entry.to_json)
323
+
324
+ response1 = @client.receive_message(:queue_url => queue_url)
325
+
326
+ response1.messages.size.should == 1
327
+
328
+ response2 = @client.receive_message(:queue_url => queue_url)
329
+
330
+ response2.messages.size.should == 0
331
+
332
+ @client.change_message_visibility(
333
+ :queue_url => queue_url,
334
+ :receipt_handle => response1.messages.first.receipt_handle,
335
+ :visibility_timeout => 0
336
+ )
337
+
338
+ response3 = @client.receive_message(:queue_url => queue_url)
339
+
340
+ response1.messages.size.should == 1
341
+
342
+ response1.messages.first.message_id.should == response3.messages.first.message_id
343
+ response1.messages.first.md5_of_body.should == response3.messages.first.md5_of_body
344
+ end
345
+ end
346
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe LSQS::Message do
4
+ before do
5
+ @attributes = {'MessageBody' => 'test'}
6
+ @message = described_class.new(@attributes)
7
+ end
8
+ describe '#attributes' do
9
+ it 'has same message body' do
10
+ @message.attributes['MessageBody'].should == @attributes['MessageBody']
11
+ end
12
+
13
+ it 'has correct MD5 message hash' do
14
+ @message.attributes['MD5'].should == Digest::MD5.hexdigest(@attributes['MessageBody'])
15
+ end
16
+
17
+ it 'has an Id' do
18
+ @message.attributes['Id'].kind_of?(String).should be_truthy
19
+ end
20
+
21
+ it 'can initialize its id' do
22
+ attributes = {'MessageBody' => 'test', 'Id' => 'foo'}
23
+ message = described_class.new(attributes)
24
+ message.attributes['Id'].should == attributes['Id']
25
+ end
26
+
27
+ it 'can initialize its md5' do
28
+ attributes = {'MessageBody' => 'test', 'MD5' => 'bar'}
29
+ message = described_class.new(attributes)
30
+ message.attributes['MD5'].should == attributes['MD5']
31
+ end
32
+ end
33
+
34
+ describe '#expired?' do
35
+ it 'returns true if visibility_timeout is not set' do
36
+ @message.expired?.should be_truthy
37
+ end
38
+
39
+ it 'returns false if visibility_timeout is set' do
40
+ @message.expire_in(30)
41
+ @message.expired?.should be_falsey
42
+ end
43
+ end
44
+
45
+ describe '#expire_in' do
46
+ it 'sets the visibility_timeout' do
47
+ time = Time.now
48
+ @message.expire_in(30)
49
+ @message.visibility_timeout.should > time + 30
50
+ end
51
+ end
52
+
53
+ describe '#expire' do
54
+ it 'resets the visibility_timeout' do
55
+ @message.expire_in(30)
56
+ @message.visibility_timeout.kind_of?(NilClass).should be_falsey
57
+ @message.expire
58
+ @message.visibility_timeout.kind_of?(NilClass).should be_truthy
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,99 @@
1
+ require 'spec_helper'
2
+
3
+ describe LSQS::QueueList do
4
+ before do
5
+ @list = described_class.new
6
+ end
7
+
8
+ describe '#initialize' do
9
+ it 'initializes properly' do
10
+
11
+ list = described_class.new
12
+
13
+ list.queues.kind_of?(Hash).should be_truthy
14
+ list.queues.size.zero?.should be_truthy
15
+ end
16
+ end
17
+
18
+ describe '#create' do
19
+ it 'creates a queue' do
20
+ @list.create('foo')
21
+ @list.create('bar')
22
+
23
+ @list.queues.size.should == 2
24
+ @list.queues['foo'].kind_of?(LSQS::Queue).should be_truthy
25
+ end
26
+
27
+ it 'throws an error if queue already exists' do
28
+ @list.create('test')
29
+ expect{@list.create('test')}.to raise_error(RuntimeError, 'QueueNameExists')
30
+ end
31
+ end
32
+
33
+ describe '#inspect' do
34
+ it 'gives the list of queues' do
35
+ @list.create('foo')
36
+ @list.create('bar')
37
+
38
+ result = @list.inspect
39
+
40
+ result.size.should == 2
41
+ result.include?('bar').should be_truthy
42
+ result.include?('foo').should be_truthy
43
+ result.kind_of?(Array).should be_truthy
44
+ end
45
+
46
+ it 'gives the list of queues by prefix' do
47
+ @list.create('foo')
48
+ @list.create('bar')
49
+
50
+ result = @list.inspect('QueueNamePrefix' => 'foo')
51
+
52
+ result.size.should == 1
53
+ result.include?('foo').should be_truthy
54
+ result.kind_of?(Array).should be_truthy
55
+ end
56
+ end
57
+
58
+ describe '#find' do
59
+ it 'returns a single queue' do
60
+ @list.create('test')
61
+
62
+ result = @list.find('test')
63
+
64
+ result.kind_of?(LSQS::Queue).should be_truthy
65
+ result.name.should == 'test'
66
+ end
67
+
68
+ it 'throws an error if queue does not exist' do
69
+ expect{@list.find('foo')}.to raise_error(RuntimeError, 'NonExistentQueue')
70
+ end
71
+ end
72
+
73
+ describe '#delete' do
74
+ it 'deletes a queue' do
75
+ @list.create('test')
76
+
77
+ @list.queues.size.should == 1
78
+
79
+ @list.delete('test')
80
+ @list.queues.size.zero?.should be_truthy
81
+ end
82
+
83
+ it 'throws an error if queue does not exist' do
84
+ expect{@list.delete('foo')}.to raise_error(RuntimeError, 'NonExistentQueue')
85
+ end
86
+ end
87
+
88
+ describe '#purge' do
89
+ it 'empties the queue list' do
90
+ @list.create('test')
91
+
92
+ @list.queues.size.should == 1
93
+
94
+ @list.purge
95
+
96
+ @list.queues.size.zero?.should be_truthy
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,192 @@
1
+ require 'spec_helper'
2
+
3
+ describe LSQS::Queue do
4
+ before do
5
+ @queue = described_class.new('test')
6
+ end
7
+
8
+ describe '#initialize' do
9
+ it 'has a name' do
10
+ @queue.name.should == 'test'
11
+ end
12
+
13
+ it 'has a messages array' do
14
+ @queue.messages.kind_of?(Array).should be_truthy
15
+ @queue.messages.empty?.should be_truthy
16
+ end
17
+
18
+ it 'has an in_flight hash' do
19
+ @queue.in_flight.kind_of?(Hash).should be_truthy
20
+ @queue.in_flight.empty?.should be_truthy
21
+ end
22
+
23
+ it 'has attributes hash' do
24
+ @queue.attributes.kind_of?(Hash).should be_truthy
25
+ end
26
+ end
27
+
28
+ describe '#default_timeout' do
29
+ it 'has default visibility if not set' do
30
+ queue = described_class.new('test')
31
+
32
+ queue.visibility_timeout.should == described_class::DEFAULT_TIMEOUT
33
+ end
34
+
35
+ it 'has visibility timeout if set' do
36
+ queue = described_class.new('test', {'Attributes' => {'VisibilityTimeout' => 10}})
37
+
38
+ queue.visibility_timeout.should == 10
39
+ end
40
+ end
41
+
42
+ describe '#create_message' do
43
+ it 'creates a message' do
44
+ @queue.create_message
45
+
46
+ @queue.messages.size.should == 1
47
+ @queue.messages.first.kind_of?(Message).should be_truthy
48
+ end
49
+ end
50
+
51
+ describe '#get_messages' do
52
+ it 'gets a single message' do
53
+ @queue.create_message('MessageBody' => 'foo')
54
+
55
+ result = @queue.get_messages
56
+
57
+ result.size.should == 1
58
+ @queue.in_flight.size.should == 1
59
+ result.find{|k,v| v.body == 'foo'}.should be_truthy
60
+ end
61
+
62
+ it 'gets a two messages if MaxNumberOfMessages is 2' do
63
+ @queue.create_message('MessageBody' => 'foo')
64
+ @queue.create_message('MessageBody' => 'bar')
65
+ @queue.create_message('MessageBody' => 'foo bar')
66
+
67
+ result = @queue.get_messages('MaxNumberOfMessages' => 2)
68
+
69
+ result.size.should == 2
70
+ @queue.in_flight.size.should == 2
71
+ end
72
+
73
+ it 'gets a two messages if MaxNumberOfMessages is 5 and available are 2' do
74
+ @queue.create_message('MessageBody' => 'foo')
75
+ @queue.create_message('MessageBody' => 'bar')
76
+
77
+ result = @queue.get_messages('MaxNumberOfMessages' => 5)
78
+
79
+ result.size.should == 2
80
+ @queue.in_flight.size.should == 2
81
+ end
82
+
83
+ it 'throws an error if max number is above 10' do
84
+ @queue.create_message('MessageBody' => 'foo')
85
+ @queue.create_message('MessageBody' => 'bar')
86
+
87
+ expect{@queue.get_messages('MaxNumberOfMessages' => 11)}.to raise_error(RuntimeError, 'ReadCountOutOfRange')
88
+ end
89
+ end
90
+
91
+ describe '#delete_message' do
92
+ end
93
+
94
+ describe '#size' do
95
+ it 'calculates size correctly' do
96
+ @queue.create_message('MessageBody' => 'foo')
97
+ @queue.create_message('MessageBody' => 'bar')
98
+ @queue.create_message('MessageBody' => 'test')
99
+
100
+ @queue.size.should == 3
101
+ end
102
+ end
103
+
104
+ describe '#purge_queue' do
105
+ it 'clears the queue' do
106
+ @queue.create_message('MessageBody' => 'foo')
107
+ @queue.create_message('MessageBody' => 'bar')
108
+
109
+ @queue.size.should == 2
110
+ @queue.in_flight.size.should == 0
111
+
112
+ @queue.get_messages
113
+
114
+ @queue.size.should == 1
115
+ @queue.in_flight.size.should == 1
116
+
117
+ @queue.purge
118
+
119
+ @queue.size.zero?.should be_truthy
120
+ @queue.in_flight.size.zero?.should be_truthy
121
+
122
+ end
123
+ end
124
+
125
+ describe '#generate_receipt' do
126
+ it 'generates a string' do
127
+ receipt = @queue.generate_receipt
128
+ receipt.kind_of?(String).should be_truthy
129
+ receipt.length.should == 32
130
+ end
131
+ end
132
+
133
+ describe '#change_message_visibility' do
134
+ it 'puts the message back in the queue if seconds is 0' do
135
+ @queue.create_message
136
+
137
+ @queue.size.should == 1
138
+
139
+ result = @queue.get_messages
140
+
141
+ @queue.size.zero?.should be_truthy
142
+ @queue.in_flight.size.should == 1
143
+
144
+ @queue.change_message_visibility(result.first.first, 0)
145
+
146
+ @queue.size.should == 1
147
+ @queue.in_flight.size.zero?.should be_truthy
148
+ end
149
+
150
+ it 'throws an error if the message is not in flight' do
151
+ expect{@queue.change_message_visibility('foo', 0)}.to raise_error(RuntimeError, 'MessageNotInflight')
152
+ end
153
+
154
+ it 'keeps the message in flight if seconds is more than 0' do
155
+ @queue.create_message
156
+
157
+ @queue.size.should == 1
158
+
159
+ result = @queue.get_messages
160
+
161
+ @queue.size.zero?.should be_truthy
162
+ @queue.in_flight.size.should == 1
163
+
164
+ @queue.change_message_visibility(result.first.first, 10)
165
+
166
+ @queue.size.zero?.should be_truthy
167
+ @queue.in_flight.size.should == 1
168
+ end
169
+ end
170
+
171
+ describe '#timeout_messages' do
172
+ it 'puts messages back in the queue' do
173
+ queue = described_class.new('test', {'Attributes' => {'VisibilityTimeout' => 1}})
174
+
175
+ queue.create_message
176
+
177
+ queue.size.should == 1
178
+ queue.in_flight.size.zero?.should be_truthy
179
+
180
+ queue.get_messages
181
+ queue.size.zero?.should be_truthy
182
+ queue.in_flight.size.should == 1
183
+
184
+ sleep(2)
185
+
186
+ queue.timeout_messages
187
+
188
+ queue.size.should == 1
189
+ queue.in_flight.size.zero?.should be_truthy
190
+ end
191
+ end
192
+ end